warcraft-3-w3ts-utils 0.1.12 → 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 (54) hide show
  1. package/dist/dist/tstl_output.lua.map +1 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/package.json +40 -39
  5. package/dist/utils/abilities.d.ts +1 -0
  6. package/dist/utils/abilities.d.ts.map +1 -0
  7. package/dist/utils/camera.d.ts +1 -0
  8. package/dist/utils/camera.d.ts.map +1 -0
  9. package/dist/utils/chat-command.d.ts +1 -0
  10. package/dist/utils/chat-command.d.ts.map +1 -0
  11. package/dist/utils/color.d.ts +1 -0
  12. package/dist/utils/color.d.ts.map +1 -0
  13. package/dist/utils/index.d.ts +1 -0
  14. package/dist/utils/index.d.ts.map +1 -0
  15. package/dist/utils/item.d.ts +1 -0
  16. package/dist/utils/item.d.ts.map +1 -0
  17. package/dist/utils/math.d.ts +1 -0
  18. package/dist/utils/math.d.ts.map +1 -0
  19. package/dist/utils/minimapIcons.d.ts +1 -0
  20. package/dist/utils/minimapIcons.d.ts.map +1 -0
  21. package/dist/utils/misc.d.ts +1 -0
  22. package/dist/utils/misc.d.ts.map +1 -0
  23. package/dist/utils/physics.d.ts +1 -0
  24. package/dist/utils/physics.d.ts.map +1 -0
  25. package/dist/utils/players.d.ts +1 -0
  26. package/dist/utils/players.d.ts.map +1 -0
  27. package/dist/utils/point.d.ts +1 -0
  28. package/dist/utils/point.d.ts.map +1 -0
  29. package/dist/utils/quests.d.ts +1 -0
  30. package/dist/utils/quests.d.ts.map +1 -0
  31. package/dist/utils/textTag.d.ts +1 -0
  32. package/dist/utils/textTag.d.ts.map +1 -0
  33. package/dist/utils/timer.d.ts +1 -0
  34. package/dist/utils/timer.d.ts.map +1 -0
  35. package/dist/utils/units.d.ts +1 -0
  36. package/dist/utils/units.d.ts.map +1 -0
  37. package/package.json +40 -39
  38. package/src/index.ts +1 -0
  39. package/src/utils/abilities.ts +158 -0
  40. package/src/utils/camera.ts +63 -0
  41. package/src/utils/chat-command.ts +22 -0
  42. package/src/utils/color.ts +139 -0
  43. package/src/utils/index.ts +15 -0
  44. package/src/utils/item.ts +163 -0
  45. package/src/utils/math.ts +14 -0
  46. package/src/utils/minimapIcons.ts +34 -0
  47. package/src/utils/misc.ts +179 -0
  48. package/src/utils/physics.ts +295 -0
  49. package/src/utils/players.ts +213 -0
  50. package/src/utils/point.ts +81 -0
  51. package/src/utils/quests.ts +38 -0
  52. package/src/utils/textTag.ts +80 -0
  53. package/src/utils/timer.ts +14 -0
  54. package/src/utils/units.ts +84 -0
@@ -0,0 +1,63 @@
1
+ import { Trigger } from "w3ts";
2
+ import { forEachPlayer } from "./players";
3
+
4
+ type CameraDistances = "mid" | "far" | "max";
5
+
6
+ export function enableCameraZoom() {
7
+ const t = Trigger.create();
8
+ forEachPlayer((p) => {
9
+ SetCameraFieldForPlayer(p.handle, CAMERA_FIELD_FARZ, 10000, 0.25);
10
+
11
+ t.registerPlayerChatEvent(p, "-cam", false);
12
+
13
+ t.addAction(() => {
14
+ const str = GetEventPlayerChatString();
15
+ const triggeringPlayer = GetTriggerPlayer();
16
+ if (str && triggeringPlayer) {
17
+ const [command, distance] = str?.split(" ");
18
+ SetCameraFieldForPlayer(
19
+ triggeringPlayer,
20
+ CAMERA_FIELD_FARZ,
21
+ 10000,
22
+ 0.25
23
+ );
24
+
25
+ if ((distance as CameraDistances) === "mid") {
26
+ SetCameraFieldForPlayer(
27
+ triggeringPlayer,
28
+ CAMERA_FIELD_TARGET_DISTANCE,
29
+ 4500,
30
+ 0.25
31
+ );
32
+ return;
33
+ } else if ((distance as CameraDistances) === "far") {
34
+ SetCameraFieldForPlayer(
35
+ triggeringPlayer,
36
+ CAMERA_FIELD_TARGET_DISTANCE,
37
+ 6000,
38
+ 0.25
39
+ );
40
+ return;
41
+ } else if ((distance as CameraDistances) === "max") {
42
+ SetCameraFieldForPlayer(
43
+ triggeringPlayer,
44
+ CAMERA_FIELD_TARGET_DISTANCE,
45
+ 7800,
46
+ 0.25
47
+ );
48
+ return;
49
+ }
50
+
51
+ const distanceAsNumber = Number(distance);
52
+ if (typeof distanceAsNumber !== "number") return;
53
+
54
+ SetCameraFieldForPlayer(
55
+ triggeringPlayer,
56
+ CAMERA_FIELD_TARGET_DISTANCE,
57
+ distanceAsNumber,
58
+ 0.25
59
+ );
60
+ }
61
+ });
62
+ });
63
+ }
@@ -0,0 +1,22 @@
1
+ import { MapPlayer, Trigger } from "w3ts";
2
+
3
+ /**
4
+ * Setup trigger to listen for a chat command for the players specified in the array. Execute function when triggered
5
+ * @param command -cam , -name, -start, etc
6
+ * @param players
7
+ * @param fn
8
+ */
9
+ export function createChatCommand(players: MapPlayer[], command: string, exact: boolean, fn: (player: MapPlayer, data: { trigger: Trigger; command: string; data?: string }) => void) {
10
+ const trigger = Trigger.create();
11
+
12
+ players.forEach((p) => {
13
+ trigger.registerPlayerChatEvent(p, command, exact);
14
+
15
+ trigger.addAction(() => {
16
+ const str = GetEventPlayerChatString();
17
+ const [_, data] = str?.split(" ") ?? [];
18
+
19
+ fn(p, { trigger, command, data });
20
+ });
21
+ });
22
+ }
@@ -0,0 +1,139 @@
1
+ export const playerRGBMap = new Map<number, { r: number; g: number; b: number }>([
2
+ [0, { r: 255, g: 0, b: 0 }],
3
+ [1, { r: 0, g: 0, b: 255 }],
4
+ [2, { r: 0, g: 255, b: 255 }],
5
+ [3, { r: 128, g: 0, b: 128 }],
6
+ [4, { r: 255, g: 255, b: 0 }],
7
+ [5, { r: 254, g: 137, b: 13 }],
8
+ [6, { r: 32, g: 192, b: 0 }],
9
+ [7, { r: 229, g: 91, b: 176 }],
10
+ [8, { r: 149, g: 150, b: 151 }],
11
+ [9, { r: 126, g: 191, b: 241 }],
12
+ [10, { r: 16, g: 98, b: 70 }],
13
+ [11, { r: 78, g: 42, b: 4 }],
14
+ [12, { r: 155, g: 0, b: 0 }],
15
+ [13, { r: 0, g: 0, b: 195 }],
16
+ [14, { r: 155, g: 234, b: 255 }],
17
+ [15, { r: 190, g: 0, b: 254 }],
18
+ [16, { r: 235, g: 205, b: 135 }],
19
+ [17, { r: 248, g: 164, b: 139 }],
20
+ [18, { r: 191, g: 255, b: 128 }],
21
+ [19, { r: 220, g: 185, b: 235 }],
22
+ [20, { r: 40, g: 40, b: 40 }],
23
+ [21, { r: 235, g: 240, b: 255 }],
24
+ [22, { r: 0, g: 120, b: 30 }],
25
+ [23, { r: 164, g: 111, b: 51 }],
26
+ ]);
27
+
28
+ export const playerHexColorMap = new Map<number, string>([
29
+ [0, "ff0303"],
30
+ [1, "0042ff"],
31
+ [2, "1ce6b9"],
32
+ [3, "540081"],
33
+ [4, "fffc00"],
34
+ [5, "fe8a0e"],
35
+ ]);
36
+
37
+ /**
38
+ *
39
+ *
40
+ PlayerStrings[0].colour = "|c00ff0303"
41
+ PlayerStrings[1].colour = "|c000042ff"
42
+ PlayerStrings[2].colour = "|c001ce6b9"
43
+ PlayerStrings[3].colour = "|c00540081"
44
+ PlayerStrings[4].colour = "|c00fffc00"
45
+ PlayerStrings[5].colour = "|c00fe8a0e"
46
+ PlayerStrings[6].colour = "|c0020c000"
47
+ PlayerStrings[7].colour = "|c00e55bb0"
48
+ PlayerStrings[8].colour = "|c00959697"
49
+ PlayerStrings[9].colour = "|c007ebff1"
50
+ PlayerStrings[10].colour = "|c00106246"
51
+ PlayerStrings[11].colour = "|c004e2a04"
52
+ PlayerStrings[12].colour = "|c009b0000"
53
+ PlayerStrings[13].colour = "|c000000c3"
54
+ PlayerStrings[14].colour = "|c0000eaff"
55
+ PlayerStrings[15].colour = "|c00be00fe"
56
+ PlayerStrings[16].colour = "|c00ebcd87"
57
+ PlayerStrings[17].colour = "|c00f8a48b"
58
+ PlayerStrings[18].colour = "|c00bfff80"
59
+ PlayerStrings[19].colour = "|c00dcb9eb"
60
+ PlayerStrings[20].colour = "|c00282828"
61
+ PlayerStrings[21].colour = "|c00ebf0ff"
62
+ PlayerStrings[22].colour = "|c0000781e"
63
+ PlayerStrings[23].colour = "|c00a46f33"
64
+ -- RGB
65
+ PlayerStrings[0].red = 255
66
+ PlayerStrings[0].green = 3
67
+ PlayerStrings[0].blue = 3
68
+ PlayerStrings[1].red = 0
69
+ PlayerStrings[1].green = 66
70
+ PlayerStrings[1].blue = 255
71
+ PlayerStrings[2].red = 28
72
+ PlayerStrings[2].green = 230
73
+ PlayerStrings[2].blue = 185
74
+ PlayerStrings[3].red = 84
75
+ PlayerStrings[3].green = 0
76
+ PlayerStrings[3].blue = 129
77
+ PlayerStrings[4].red = 255
78
+ PlayerStrings[4].green = 254
79
+ PlayerStrings[4].blue = 0
80
+ PlayerStrings[5].red = 254
81
+ PlayerStrings[5].green = 138
82
+ PlayerStrings[5].blue = 14
83
+ PlayerStrings[6].red = 32
84
+ PlayerStrings[6].green = 192
85
+ PlayerStrings[6].blue = 0
86
+ PlayerStrings[7].red = 229
87
+ PlayerStrings[7].green = 91
88
+ PlayerStrings[7].blue = 176
89
+ PlayerStrings[8].red = 149
90
+ PlayerStrings[8].green = 150
91
+ PlayerStrings[8].blue = 151
92
+ PlayerStrings[9].red = 126
93
+ PlayerStrings[9].green = 191
94
+ PlayerStrings[9].blue = 241
95
+ PlayerStrings[10].red = 16
96
+ PlayerStrings[10].green = 98
97
+ PlayerStrings[10].blue = 70
98
+ PlayerStrings[11].red = 78
99
+ PlayerStrings[11].green = 42
100
+ PlayerStrings[11].blue = 4
101
+ PlayerStrings[12].red = 155
102
+ PlayerStrings[12].green = 0
103
+ PlayerStrings[12].blue = 0
104
+ PlayerStrings[13].red = 0
105
+ PlayerStrings[13].green = 0
106
+ PlayerStrings[13].blue = 195
107
+ PlayerStrings[14].red = 155
108
+ PlayerStrings[14].green = 234
109
+ PlayerStrings[14].blue = 255
110
+ PlayerStrings[15].red = 190
111
+ PlayerStrings[15].green = 0
112
+ PlayerStrings[15].blue = 254
113
+ PlayerStrings[16].red = 235
114
+ PlayerStrings[16].green = 205
115
+ PlayerStrings[16].blue = 135
116
+ PlayerStrings[17].red = 248
117
+ PlayerStrings[17].green = 164
118
+ PlayerStrings[17].blue = 139
119
+ PlayerStrings[18].red = 191
120
+ PlayerStrings[18].green = 255
121
+ PlayerStrings[18].blue = 128
122
+ PlayerStrings[19].red = 220
123
+ PlayerStrings[19].green = 185
124
+ PlayerStrings[19].blue = 235
125
+ PlayerStrings[20].red = 40
126
+ PlayerStrings[20].green = 40
127
+ PlayerStrings[20].blue = 40
128
+ PlayerStrings[21].red = 235
129
+ PlayerStrings[21].green = 240
130
+ PlayerStrings[21].blue = 255
131
+ PlayerStrings[22].red = 0
132
+ PlayerStrings[22].green = 120
133
+ PlayerStrings[22].blue = 30
134
+ PlayerStrings[23].red = 164
135
+ PlayerStrings[23].green = 111
136
+ PlayerStrings[23].blue = 51
137
+ *
138
+ *
139
+ */
@@ -0,0 +1,15 @@
1
+ export * from "./abilities";
2
+ export * from "./camera";
3
+ export * from "./chat-command";
4
+ export * from "./color";
5
+ export * from "./item";
6
+ export * from "./math";
7
+ export * from "./minimapIcons";
8
+ export * from "./misc";
9
+ export * from "./physics";
10
+ export * from "./players";
11
+ export * from "./point";
12
+ export * from "./quests";
13
+ export * from "./textTag";
14
+ export * from "./timer";
15
+ export * from "./units";
@@ -0,0 +1,163 @@
1
+ import { Effect, Item, Trigger, Unit } from "w3ts";
2
+ import { notifyPlayer, useTempEffect } from "./misc";
3
+
4
+ /**
5
+ * Checks if the unit has an item in their item slots
6
+ * @param u
7
+ * @param itemTypeId
8
+ * @returns
9
+ */
10
+ export function unitHasItem(u: Unit, itemTypeId: number): boolean {
11
+ for (let x = 0; x < 6; x++) {
12
+ if (u.getItemInSlot(x)?.typeId === itemTypeId) {
13
+ return true;
14
+ }
15
+ }
16
+
17
+ return false;
18
+ }
19
+
20
+ // Player should pick up recipes when needed. if they are missing items then the recipe cost is refunded
21
+ function trig_itemRecipeSystem() {
22
+ //takes a set of items
23
+ //unit or unit clicks
24
+ const t = Trigger.create();
25
+
26
+ t.registerAnyUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM);
27
+ t.addAction(() => {
28
+ const recipeItem = Item.fromEvent();
29
+ const unit = Unit.fromHandle(GetTriggerUnit());
30
+
31
+ if (!unit || !recipeItem) {
32
+ return;
33
+ }
34
+
35
+ //for every item they have, if any has the word recipe, then we check to see if they have the items needed to satisfy the recipe
36
+ for (let x = 0; x < 6; x++) {
37
+ const currItem = unit?.getItemInSlot(x);
38
+ if (currItem?.name.toLowerCase().includes("recipe")) {
39
+ checkItemRecipeRequirements(unit, currItem);
40
+ }
41
+ }
42
+ });
43
+ }
44
+
45
+ function checkItemRecipeRequirements(unit: Unit, recipeItem: Item) {
46
+ if (recipeItem.name.toLowerCase().includes("recipe")) {
47
+ let requiredItems: RecipeItemRequirement[] | null = null;
48
+ let itemToCreateId: number | null = null;
49
+
50
+ for (const [key, value] of itemRecipesMap.entries()) {
51
+ if (key.recipeId === recipeItem.typeId) {
52
+ requiredItems = value;
53
+ itemToCreateId = key.itemId;
54
+ }
55
+ }
56
+
57
+ if (!requiredItems) {
58
+ print("Missing required items data for the recipe ", recipeItem.name);
59
+ return;
60
+ }
61
+
62
+ /**
63
+ * unique list of item types and their quantity and charges that we found on the unit
64
+ */
65
+ const matchingItems: RecipeItemRequirement[] = [];
66
+
67
+ //Loop through the units item slots
68
+ for (let x = 0; x < 6; x++) {
69
+ const currItem = unit?.getItemInSlot(x);
70
+
71
+ //Check that the current item matches at least one of the item types in the requirement list
72
+ if (currItem && requiredItems.some((req) => req.itemTypeId === currItem.typeId)) {
73
+ const alreadyStoredItemIndex = matchingItems.findIndex((itemReq) => itemReq.itemTypeId === currItem.typeId);
74
+
75
+ //If we already came across this item in the unit inventory then increment the quantity
76
+ if (alreadyStoredItemIndex && matchingItems[alreadyStoredItemIndex]) {
77
+ matchingItems[alreadyStoredItemIndex].quantity++;
78
+ }
79
+ //otherwise it is our first match with this item type, so add it to our array of matching items
80
+ else {
81
+ matchingItems.push({ itemTypeId: currItem.typeId, quantity: 1, charges: 0 });
82
+ }
83
+ }
84
+ }
85
+
86
+ //Check that every item required is found in the units inventory satisfies the quantity requirement for the recipe
87
+ const satisfiesRecipe =
88
+ requiredItems.every((reqItemData) => {
89
+ const matching = matchingItems?.find((matchingItemData) => matchingItemData.itemTypeId === reqItemData.itemTypeId);
90
+
91
+ if (matching) {
92
+ return matching.quantity >= reqItemData.quantity;
93
+ }
94
+
95
+ return false;
96
+ }) && matchingItems.length > 0;
97
+
98
+ if (!itemToCreateId) {
99
+ print("Missing the item type id of the item to create for this recipe: ", recipeItem.name);
100
+ }
101
+
102
+ //destroys more items than it needds to
103
+ if (satisfiesRecipe && itemToCreateId) {
104
+ //add the item
105
+ requiredItems.forEach((req: RecipeItemRequirement) => {
106
+ for (let x = 0; x < req.quantity; x++) {
107
+ for (let x = 0; x < 6; x++) {
108
+ const currItem = unit?.getItemInSlot(x);
109
+ if (currItem?.typeId === req.itemTypeId) {
110
+ currItem?.destroy();
111
+ break;
112
+ }
113
+ }
114
+ }
115
+ });
116
+
117
+ recipeItem.destroy();
118
+
119
+ unit.addItemById(itemToCreateId);
120
+
121
+ useTempEffect(Effect.create("Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl", unit.x, unit.y));
122
+ const clap = Effect.create("Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl", unit.x, unit.y);
123
+ clap?.setScaleMatrix(0.5, 0.5, 0.5);
124
+ useTempEffect(clap);
125
+ }
126
+
127
+ if (!satisfiesRecipe) {
128
+ //refund the gold
129
+ notifyPlayer(`Missing recipe requirements for: ${recipeItem.name}.`);
130
+ }
131
+
132
+ //use if or rf to store item gold cost in the world editor
133
+ }
134
+ }
135
+
136
+ /***
137
+ * Determines items that are created by recipes.
138
+ */
139
+ export function registerItemsRecipes(recipesConfiguration: Map<RecipeItem, RecipeItemRequirement[]>) {
140
+ itemRecipesMap = recipesConfiguration;
141
+ trig_itemRecipeSystem();
142
+ }
143
+
144
+ export interface RecipeItemRequirement {
145
+ itemTypeId: number; //ITEMS;
146
+ quantity: number;
147
+ charges: number;
148
+ }
149
+
150
+ export interface RecipeItem {
151
+ recipeId: number;
152
+ itemId: number;
153
+ }
154
+
155
+ let itemRecipesMap = new Map<RecipeItem, RecipeItemRequirement[]>([
156
+ // [
157
+ // { recipeId: ITEMS.recipe_blinkTreads, itemId: ITEMS.blinkTreads },
158
+ // [
159
+ // { itemTypeId: ITEMS.bootsOfSpeed, quantity: 1, charges: 0 }, //
160
+ // { itemTypeId: ITEMS.blinkDagger, quantity: 1, charges: 0 }, //
161
+ // ],
162
+ // ],
163
+ ]);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @deprecated
3
+ * @param a
4
+ * @param b
5
+ * @returns
6
+ */
7
+ export function distanceBetweenCoords(a: { x: number; y: number }, b: { x: number; y: number }) {
8
+ const deltaX = a.x - b.x;
9
+ const deltaY = a.y - b.y;
10
+ const squaredDist = Math.pow(deltaX, 2) + Math.pow(deltaY, 2);
11
+ const dist = Math.sqrt(squaredDist);
12
+
13
+ return dist;
14
+ }
@@ -0,0 +1,34 @@
1
+ export type MINIMAP_ICONS =
2
+ | "UI\\Minimap\\MiniMap-ControlPoint.mdl"
3
+ | "UI\\Minimap\\MiniMap-QuestGiver.mdl"
4
+ | "UI\\Minimap\\Minimap-QuestObjectiveBonus.mdl"
5
+ | "UI\\Minimap\\Minimap-QuestObjectivePrimary.mdl"
6
+ | "UI\\Minimap\\Minimap-QuestTurnIn.mdl"
7
+ | "UI\\Minimap\\MiniMap-Hero.mdl"
8
+ | "UI\\Minimap\\Minimap-Ping.mdl"
9
+ | "UI\\Minimap\\MiniMap-Item.mdl"
10
+ | "UI\\Minimap\\MiniMap-NeutralBuilding.mdl";
11
+
12
+ export enum MinimapIconPath {
13
+ controlPoint = "UI\\Minimap\\MiniMap-ControlPoint.mdl",
14
+ questGiver = "UI\\Minimap\\MiniMap-QuestGiver.mdl",
15
+ questObjectiveBonus = "UI\\Minimap\\Minimap-QuestObjectiveBonus.mdl",
16
+ questObjectivePrimary = "UI\\Minimap\\Minimap-QuestObjectivePrimary.mdl",
17
+ questTurnIn = "UI\\Minimap\\Minimap-QuestTurnIn.mdl",
18
+ hero = "UI\\Minimap\\MiniMap-Hero.mdl",
19
+ item = "UI\\Minimap\\MiniMap-Item.mdl",
20
+ neutralBuilding = "UI\\Minimap\\MiniMap-NeutralBuilding.mdl",
21
+ ping = "UI\\Minimap\\Minimap-Ping.mdl",
22
+ }
23
+
24
+ export const minimapIconPathsSet = new Set<MINIMAP_ICONS>([
25
+ "UI\\Minimap\\MiniMap-ControlPoint.mdl",
26
+ "UI\\Minimap\\MiniMap-Hero.mdl",
27
+ "UI\\Minimap\\MiniMap-Item.mdl",
28
+ "UI\\Minimap\\MiniMap-NeutralBuilding.mdl",
29
+ "UI\\Minimap\\MiniMap-QuestGiver.mdl",
30
+ "UI\\Minimap\\Minimap-Ping.mdl",
31
+ "UI\\Minimap\\Minimap-QuestObjectiveBonus.mdl",
32
+ "UI\\Minimap\\Minimap-QuestObjectivePrimary.mdl",
33
+ "UI\\Minimap\\Minimap-QuestTurnIn.mdl",
34
+ ]);
@@ -0,0 +1,179 @@
1
+ import { Effect, MapPlayer, Timer, Unit } from "w3ts";
2
+
3
+ type ProperColors = "goldenrod" | "magenta" | "green" | "yellow" | "red" | "player1-red" | "player2-blue" | "player3-teal" | "player4-purple" | "player5-yellow" | "player6-orange";
4
+
5
+ export function tColor(text: string | number, color?: ProperColors | null, hex?: PlayerColorHex | string | null, alpha?: string) {
6
+ if (color) {
7
+ return `|cff${properColorHexes.get(color) || "FFFFFF"}${alpha || ""}${text}|r`;
8
+ } else if (hex) {
9
+ return `|cff${hex}${alpha || ""}${text}|r`;
10
+ }
11
+
12
+ return String(text);
13
+ }
14
+
15
+ /**
16
+ * Colorizes the string according to the map player
17
+ */
18
+ export function ptColor(player: MapPlayer, text: string) {
19
+ return `${tColor(text, undefined, playerColors[player.id])}`;
20
+ }
21
+
22
+ const properColorHexes = new Map<ProperColors, string>([
23
+ ["goldenrod", "ffcc00"],
24
+ ["green", "00FF00"],
25
+ ["yellow", "FFFF00"],
26
+ ["red", "FF0000"],
27
+ ["magenta", "FF00FF"],
28
+ ["player1-red", "ff0303"],
29
+ ["player2-blue", "0042ff"],
30
+ ["player3-teal", "1ce6b9"],
31
+ ["player4-purple", "540081"],
32
+ ["player5-yellow", "fffc00"],
33
+ ["player6-orange", "fe8a0e"],
34
+ ]);
35
+ // enum PlayerColors {
36
+ // Player1 = "ff0303", // Red
37
+ // Player2 = "0042ff", // Blue
38
+ // Player3 = "1be7ba", // Teal
39
+ // Player4 = "550081", // Purple
40
+ // Player5 = "fefc00", // Yellow
41
+ // Player6 = "fe890d", // Orange
42
+ // Player7 = "21bf00", // Green
43
+ // Player8 = "e45caf", // Pink
44
+ // Player9 = "939596", // Gray
45
+ // Player10 = "7ebff1", // Light Blue
46
+ // Player11 = "106247", // Dark Green
47
+ // Player12 = "4f2b05", // Brown
48
+ // Player13 = "9c0000", // Maroon
49
+ // Player14 = "0000c3", // Navy
50
+ // Player15 = "00ebff", // Turquoise
51
+ // Player16 = "bd00ff", // Violet
52
+ // Player17 = "ecce87", // Wheat
53
+ // Player18 = "f7a58b", // Peach
54
+ // Player19 = "bfff81", // Mint
55
+ // Player20 = "dbb8eb", // Lavender
56
+ // Player21 = "4f5055", // Coal
57
+ // Player22 = "ecf0ff", // Snow
58
+ // Player23 = "00781e", // Emerald
59
+ // Player24 = "a56f34", // Peanut
60
+ // PlayerNeutral = "2e2d2e", // Black
61
+ // }
62
+
63
+ export enum PlayerColorHex {
64
+ Red = "ff0303",
65
+ Blue = "0042ff",
66
+ Teal = "1be7ba",
67
+ Purple = "550081",
68
+ Yellow = "fefc00",
69
+ Orange = "fe890d",
70
+ Green = "21bf00",
71
+ Pink = "e45caf",
72
+ Gray = "939596",
73
+ LightBlue = "7ebff1",
74
+ DarkGreen = "106247",
75
+ Brown = "4f2b05",
76
+ Maroon = "9c0000",
77
+ Navy = "0000c3",
78
+ Turquoise = "00ebff",
79
+ Violet = "bd00ff",
80
+ Wheat = "ecce87",
81
+ Peach = "f7a58b",
82
+ Mint = "bfff81",
83
+ Lavender = "dbb8eb",
84
+ Coal = "4f5055",
85
+ Snow = "ecf0ff",
86
+ Emerald = "00781e",
87
+ Peanut = "a56f34",
88
+ Black = "2e2d2e",
89
+ }
90
+
91
+ const playerColors = [
92
+ "ff0303", // Player 1: Red
93
+ "0042ff", // Player 2: Blue
94
+ "1be7ba", // Player 3: Teal
95
+ "550081", // Player 4: Purple
96
+ "fefc00", // Player 5: Yellow
97
+ "fe890d", // Player 6: Orange
98
+ "21bf00", // Player 7: Green
99
+ "e45caf", // Player 8: Pink
100
+ "939596", // Player 9: Gray
101
+ "7ebff1", // Player 10: Light Blue
102
+ "106247", // Player 11: Dark Green
103
+ "4f2b05", // Player 12: Brown
104
+ "9c0000", // Player 13: Maroon
105
+ "0000c3", // Player 14: Navy
106
+ "00ebff", // Player 15: Turquoise
107
+ "bd00ff", // Player 16: Violet
108
+ "ecce87", // Player 17: Wheat
109
+ "f7a58b", // Player 18: Peach
110
+ "bfff81", // Player 19: Mint
111
+ "dbb8eb", // Player 20: Lavender
112
+ "4f5055", // Player 21: Coal
113
+ "ecf0ff", // Player 22: Snow
114
+ "00781e", // Player 23: Emerald
115
+ "a56f34", // Player 24: Peanut
116
+ "2e2d2e", // Player Neutral: Black
117
+ ];
118
+
119
+ /**
120
+ * Standardized format for notifying player of events.
121
+ */
122
+ export function notifyPlayer(msg: string) {
123
+ print(`${tColor("!", "goldenrod")} - ${msg}`);
124
+ }
125
+
126
+ export function displayError(msg: string) {
127
+ print(`[ ${tColor("WARNING", "red")} ]: ${msg}`);
128
+ }
129
+
130
+ /**
131
+ * Returns degrees or radians?
132
+ */
133
+ export function getRelativeAngleToUnit(unit: Unit, relativeUnit: Unit) {
134
+ const locA = GetUnitLoc(unit.handle);
135
+ const locB = GetUnitLoc(relativeUnit.handle);
136
+ const angle = AngleBetweenPoints(locA, locB);
137
+
138
+ RemoveLocation(locA);
139
+ RemoveLocation(locB);
140
+
141
+ return angle;
142
+ }
143
+
144
+ /**
145
+ * Manages state of effects in this context so you don't have to!
146
+ */
147
+ export function useEffects() {
148
+ const effects: Effect[] = [];
149
+
150
+ return {
151
+ addEffect: (effect: Effect | undefined) => {
152
+ if (effect) {
153
+ effects.push(effect);
154
+ }
155
+ },
156
+ /**
157
+ * @returns reference to effects array
158
+ */
159
+ getEffects: () => {
160
+ return effects;
161
+ },
162
+ destroyAllEffects: () => {
163
+ effects.forEach((e) => {
164
+ e.destroy();
165
+ });
166
+ },
167
+ };
168
+ }
169
+
170
+ export function useTempEffect(effect: Effect | undefined, duration: number = 1.5) {
171
+ if (effect) {
172
+ const timer = Timer.create();
173
+
174
+ timer.start(duration, false, () => {
175
+ effect.destroy();
176
+ timer.destroy();
177
+ });
178
+ }
179
+ }