warcraft-3-w3ts-utils 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/dist/tstl_output.lua +11424 -0
  2. package/dist/dist/tstl_output.lua.map +1 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/package.json +40 -39
  6. package/dist/utils/abilities.d.ts +2 -0
  7. package/dist/utils/abilities.d.ts.map +1 -0
  8. package/dist/utils/camera.d.ts +2 -0
  9. package/dist/utils/camera.d.ts.map +1 -0
  10. package/dist/utils/chat-command.d.ts +2 -0
  11. package/dist/utils/chat-command.d.ts.map +1 -0
  12. package/dist/utils/color.d.ts +2 -103
  13. package/dist/utils/color.d.ts.map +1 -0
  14. package/dist/utils/index.d.ts +2 -0
  15. package/dist/utils/index.d.ts.map +1 -0
  16. package/dist/utils/item.d.ts +2 -0
  17. package/dist/utils/item.d.ts.map +1 -0
  18. package/dist/utils/math.d.ts +2 -0
  19. package/dist/utils/math.d.ts.map +1 -0
  20. package/dist/utils/minimapIcons.d.ts +2 -0
  21. package/dist/utils/minimapIcons.d.ts.map +1 -0
  22. package/dist/utils/misc.d.ts +2 -0
  23. package/dist/utils/misc.d.ts.map +1 -0
  24. package/dist/utils/physics.d.ts +2 -0
  25. package/dist/utils/physics.d.ts.map +1 -0
  26. package/dist/utils/players.d.ts +2 -0
  27. package/dist/utils/players.d.ts.map +1 -0
  28. package/dist/utils/point.d.ts +2 -0
  29. package/dist/utils/point.d.ts.map +1 -0
  30. package/dist/utils/quests.d.ts +2 -0
  31. package/dist/utils/quests.d.ts.map +1 -0
  32. package/dist/utils/textTag.d.ts +2 -0
  33. package/dist/utils/textTag.d.ts.map +1 -0
  34. package/dist/utils/timer.d.ts +2 -0
  35. package/dist/utils/timer.d.ts.map +1 -0
  36. package/dist/utils/units.d.ts +2 -0
  37. package/dist/utils/units.d.ts.map +1 -0
  38. package/package.json +40 -39
  39. package/readme.md +1 -7
  40. package/src/index.ts +1 -0
  41. package/src/utils/abilities.ts +158 -0
  42. package/src/utils/camera.ts +63 -0
  43. package/src/utils/chat-command.ts +22 -0
  44. package/src/utils/color.ts +139 -0
  45. package/src/utils/index.ts +15 -0
  46. package/src/utils/item.ts +163 -0
  47. package/src/utils/math.ts +14 -0
  48. package/src/utils/minimapIcons.ts +34 -0
  49. package/src/utils/misc.ts +179 -0
  50. package/src/utils/physics.ts +295 -0
  51. package/src/utils/players.ts +213 -0
  52. package/src/utils/point.ts +81 -0
  53. package/src/utils/quests.ts +38 -0
  54. package/src/utils/textTag.ts +80 -0
  55. package/src/utils/timer.ts +14 -0
  56. package/src/utils/units.ts +84 -0
@@ -0,0 +1,81 @@
1
+ import { Point, Rectangle } from "w3ts";
2
+ const MAP_EDGE_BUFFER_DIST = 300;
3
+
4
+ export function createValidPoint(maxAttempts: number, validatorFn: (p: Point) => {}) {
5
+ const MAX_ATTEMPTS = 65000; // 100 was about 10 seconds; 1000 gets good coverage
6
+ let currentAttempts = 0;
7
+ const worldBounds = Rectangle.fromHandle(GetWorldBounds());
8
+ if (!worldBounds) return;
9
+ const [maxX, maxY] = [GetCameraBoundMaxX(), GetCameraBoundMaxY()];
10
+
11
+ while (currentAttempts <= MAX_ATTEMPTS) {
12
+ const dirX = Math.floor(Math.random() * 100) >= 50 ? 1 : -1;
13
+ const dirY = Math.floor(Math.random() * 100) >= 50 ? 1 : -1;
14
+
15
+ //multiply dir by the buffer distance from max bounds since we can get a negative number
16
+ const randX = dirX * Math.ceil(Math.random() * maxX) - dirX * MAP_EDGE_BUFFER_DIST;
17
+ const randY = dirY * Math.ceil(Math.random() * maxY) - dirY * MAP_EDGE_BUFFER_DIST;
18
+
19
+ const p = Point.create(randX, randY);
20
+
21
+ const isValidPoint = validatorFn(p);
22
+
23
+ if (isValidPoint) {
24
+ // pointsChosen.push(p);
25
+ return p;
26
+ } else {
27
+ //well add it here later, just testing for now
28
+ currentAttempts++;
29
+ }
30
+ }
31
+ }
32
+
33
+ export function getRandomCoordinatesInCircularArea(relativeX: number, relativeY: number, radius: number) {
34
+ const randomTheta = Math.random() * 360;
35
+ const randomRadius = Math.random() * radius;
36
+
37
+ const randomX = relativeX + randomRadius * Cos(randomTheta);
38
+ const randomY = relativeY + randomRadius * Sin(randomTheta);
39
+
40
+ return {
41
+ x: randomX,
42
+ y: randomY,
43
+ };
44
+ }
45
+
46
+ export function getRandomCoordinatesOnCircle(relativeX: number, relativeY: number, radius: number) {
47
+ const randomTheta = Math.random() * 360;
48
+
49
+ const randomX = relativeX + radius * Cos(randomTheta);
50
+ const randomY = relativeY + radius * Sin(randomTheta);
51
+
52
+ return {
53
+ x: randomX,
54
+ y: randomY,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Returns degrees or radians?
60
+ */
61
+ export function getAngleBetweenPoints(x1: number, y1: number, x2: number, y2: number) {
62
+ const locA = Location(x1, y1);
63
+ const locB = Location(x2, y2);
64
+
65
+ const angle = AngleBetweenPoints(locA, locB);
66
+ //arc tan
67
+ RemoveLocation(locA);
68
+ RemoveLocation(locB);
69
+
70
+ return angle;
71
+ }
72
+
73
+ export function distanceBetweenPoints(x1: number, y1: number, x2: number, y2: number) {
74
+ const deltaX = x1 - x2;
75
+ const deltaY = y1 - y2;
76
+ const squaredDist = deltaX * deltaX + deltaY * deltaY;
77
+ // const squaredDist = Math.pow(deltaX, 2) + Math.pow(deltaY, 2);
78
+ const dist = Math.sqrt(squaredDist);
79
+
80
+ return dist;
81
+ }
@@ -0,0 +1,38 @@
1
+ import { Quest, Timer } from "w3ts";
2
+ import { tColor } from "./misc";
3
+
4
+ export function setup_quests() {
5
+ Timer.create().start(1, false, () => {
6
+ addQuest(
7
+ "Basic Game Info",
8
+ `\nA roguelite base assault game. \nChoose from a wide variety of units that are trained in various schools of magic and skills.\n Outsmart and counter your opponent..
9
+ `,
10
+ "ReplaceableTextures\\CommandButtons\\BTNPeasant.blp"
11
+ );
12
+
13
+ // \n${tColor("-fixSpawns", "goldenrod")}: Player 1 can only use this. This will fix add all player's spawn units to their corresponding spawn pool.
14
+ addQuest(
15
+ "Commands",
16
+ `
17
+ \n${tColor("-cam ####", "goldenrod")}: Sets the camera distance.
18
+ \n-playername xxxx This will change your name.
19
+ `,
20
+ "ReplaceableTextures\\WorldEditUI\\Doodad-Cinematic.blp",
21
+ false
22
+ );
23
+
24
+ addQuest("|cffffcc00Evolution Castle Assault v0.01|r", "Created by JediMindTrix/NihilismIsDeath", "ReplaceableTextures\\CommandButtons\\BTNClayFigurine.blp", false);
25
+ });
26
+ }
27
+
28
+ export function addQuest(title: string, description: string, iconPath?: string, required: boolean = true) {
29
+ const q = Quest.create();
30
+ if (q) {
31
+ q.setTitle(title);
32
+ q.required = required;
33
+ q.setDescription(description);
34
+ if (iconPath) {
35
+ q.setIcon(iconPath);
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,80 @@
1
+ import { TextTag, Trigger, Unit } from "w3ts";
2
+ import { ptColor } from "./misc";
3
+ import { delayedTimer } from "./timer";
4
+
5
+ /**
6
+ * https://www.hiveworkshop.com/threads/floating-text.149719/
7
+ *
8
+ * function CreateFloatingText takes string text, real x, real y, real heightOffset, real duration, real size returns nothing
9
+ local texttag tt = CreateTextTag()
10
+ call SetTextTagText(tt, text, size)
11
+ call SetTextTagPos(tt, x, y, heightOffset)
12
+ call SetTextTagColor(tt, 255, 255, 255, 255) // RGBA format
13
+ call SetTextTagVisibility(tt, true)
14
+ call SetTextTagLifespan(tt, duration)
15
+ call SetTextTagPermanent(tt, false)
16
+ endfunction
17
+
18
+ function ExampleUsage takes nothing returns nothing
19
+ call CreateFloatingText("Hello World", 0.0, 0.0, 25.0, 5.0, 10.0)
20
+ endfunction
21
+ * @param unit
22
+ * @param text
23
+ * @param duration
24
+ */
25
+ export function createFloatingTextTagOnUnit(unit: Unit, text: string, config?: { duration?: number; yVelocity?: number; xVelocity?: number; useFade?: boolean }) {
26
+ const tag = TextTag.create();
27
+ tag?.setVisible(true);
28
+
29
+ tag?.setText(text, 10, true);
30
+
31
+ tag?.setLifespan(config?.duration === undefined ? 2 : config.duration);
32
+
33
+ if (config?.useFade !== false) {
34
+ tag?.setFadepoint(0.01);
35
+ }
36
+
37
+ tag?.setVelocity(config?.xVelocity === undefined ? 0 : config.xVelocity, config?.yVelocity === undefined ? 0.025 : config.yVelocity);
38
+ tag?.setPermanent(false);
39
+
40
+ tag?.setPosUnit(unit, 10);
41
+
42
+ if (config && config.duration && config.duration === 0) {
43
+ return;
44
+ }
45
+
46
+ delayedTimer(config?.duration ?? 2, () => {
47
+ tag?.destroy();
48
+ });
49
+ }
50
+
51
+ export function createPermanentTextTagOnPoint(text: string, x: number, y: number) {
52
+ const tag = TextTag.create();
53
+ tag?.setVisible(true);
54
+
55
+ tag?.setText(text, 20, true);
56
+ tag?.setLifespan(2);
57
+
58
+ tag?.setVelocity(0, 0);
59
+ tag?.setPermanent(true);
60
+ tag?.setPos(x, y, 20);
61
+ }
62
+
63
+ export function setup_createTextForSpellCast() {
64
+ const t = Trigger.create();
65
+
66
+ t.registerAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT);
67
+
68
+ t.addAction(() => {
69
+ const u = Unit.fromEvent();
70
+
71
+ if (u) {
72
+ const spellNumber = GetSpellAbilityId();
73
+ const spellName = GetAbilityName(spellNumber);
74
+ if (!spellName || spellName === "Default String") return;
75
+ //alt + 0164 ¤
76
+ //alt + 0149 •
77
+ createFloatingTextTagOnUnit(u, ptColor(u.owner, "¤ ") + spellName);
78
+ }
79
+ });
80
+ }
@@ -0,0 +1,14 @@
1
+ import { Timer } from "w3ts";
2
+
3
+ /**
4
+ * @param duration milliseconds
5
+ */
6
+ export function delayedTimer(duration: number, cb: (...args: any[]) => any) {
7
+ const timer = Timer.create();
8
+ timer.start(duration, false, () => {
9
+ cb();
10
+ timer.destroy();
11
+ });
12
+
13
+ return timer;
14
+ }
@@ -0,0 +1,84 @@
1
+ import { Group, MapPlayer, Timer, Unit } from "w3ts";
2
+ import { adjustGold, adjustLumber } from "./players";
3
+
4
+ export function createUnits(quantity: number, useFood: boolean, ...args: Parameters<typeof Unit.create>) {
5
+ const units: Unit[] = [];
6
+ for (let x = 0; x < quantity; x++) {
7
+ const u = Unit.create(...args);
8
+
9
+ if (u) {
10
+ u.setUseFood(useFood);
11
+ units.push(u);
12
+ }
13
+ }
14
+
15
+ return units;
16
+ }
17
+
18
+ /**
19
+ * Refund unit's gold and wood cost.
20
+ * @param u
21
+ */
22
+ export function refundUnitCost(u: Unit) {
23
+ const gold = GetUnitGoldCost(u.typeId);
24
+ const wood = GetUnitWoodCost(u.typeId);
25
+ adjustGold(u.owner, gold);
26
+ adjustLumber(u.owner, wood);
27
+ }
28
+
29
+ /**
30
+ * Returns true if the ALIVE unit has the ability within their first 12 abilities
31
+ * @param unit
32
+ * @param abilityId
33
+ * @returns
34
+ */
35
+ export function unitHasAbility(unit: Unit, abilityId: number): boolean {
36
+ for (let x = 0; x < 12; x++) {
37
+ const currentAbility = unit.getAbilityByIndex(x);
38
+
39
+ if (currentAbility && currentAbility === unit.getAbility(abilityId) && unit.isAlive()) {
40
+ return true;
41
+ }
42
+ }
43
+
44
+ return false;
45
+ }
46
+
47
+ export function unitsInRange(x: number, y: number, radius: number, cb: (unit: Unit) => void) {
48
+ const g = Group.create();
49
+ if (g) {
50
+ g.enumUnitsInRange(x, y, radius, () => {
51
+ const unit = Unit.fromFilter();
52
+ if (unit) {
53
+ cb(unit);
54
+ }
55
+ return true;
56
+ });
57
+
58
+ g.destroy();
59
+ }
60
+ }
61
+
62
+ /**
63
+ *
64
+ * @param cb
65
+ * @param abilityId
66
+ * @param owner
67
+ */
68
+ export function useTempDummyUnit(dummyUnitCode: number, cb: (dummy: Unit) => void, abilityId: number, owner: MapPlayer, x: number, y: number, config?: { facing?: number; abilityLevel?: number; dummyLifeSpan?: number }) {
69
+ let dummy: Unit | undefined = undefined;
70
+ dummy = Unit.create(owner, dummyUnitCode, x, y, config?.facing ?? 0);
71
+
72
+ const t = Timer.create();
73
+
74
+ if (dummy) {
75
+ dummy.addAbility(abilityId);
76
+ dummy.setAbilityManaCost(abilityId, config?.abilityLevel ? config.abilityLevel - 1 : 0, 0);
77
+ cb(dummy);
78
+
79
+ t.start(config?.dummyLifeSpan ?? 2, false, () => {
80
+ dummy?.destroy();
81
+ t.destroy();
82
+ });
83
+ }
84
+ }