blizzard.j

1
//===========================================================================
2
// Blizzard.j ( define Jass2 functions that need to be in every map script )
3
//===========================================================================
4
5
6
globals
7
    //-----------------------------------------------------------------------
8
    // Constants
9
    //
10
11
    // Misc constants
12
    constant real      bj_PI                            = 3.14159
13
    constant real      bj_E                             = 2.71828
14
    constant real      bj_CELLWIDTH                     = 128.0
15
    constant real      bj_CLIFFHEIGHT                   = 128.0
16
    constant real      bj_UNIT_FACING                   = 270.0
17
    constant real      bj_RADTODEG                      = 180.0/bj_PI
18
    constant real      bj_DEGTORAD                      = bj_PI/180.0
19
    constant real      bj_TEXT_DELAY_QUEST              = 20.00
20
    constant real      bj_TEXT_DELAY_QUESTUPDATE        = 20.00
21
    constant real      bj_TEXT_DELAY_QUESTDONE          = 20.00
22
    constant real      bj_TEXT_DELAY_QUESTFAILED        = 20.00
23
    constant real      bj_TEXT_DELAY_QUESTREQUIREMENT   = 20.00
24
    constant real      bj_TEXT_DELAY_MISSIONFAILED      = 20.00
25
    constant real      bj_TEXT_DELAY_ALWAYSHINT         = 12.00
26
    constant real      bj_TEXT_DELAY_HINT               = 12.00
27
    constant real      bj_TEXT_DELAY_SECRET             = 10.00
28
    constant real      bj_TEXT_DELAY_UNITACQUIRED       = 15.00
29
    constant real      bj_TEXT_DELAY_UNITAVAILABLE      = 10.00
30
    constant real      bj_TEXT_DELAY_ITEMACQUIRED       = 10.00
31
    constant real      bj_TEXT_DELAY_WARNING            = 12.00
32
    constant real      bj_QUEUE_DELAY_QUEST             =  5.00
33
    constant real      bj_QUEUE_DELAY_HINT              =  5.00
34
    constant real      bj_QUEUE_DELAY_SECRET            =  3.00
35
    constant real      bj_HANDICAP_EASY                 = 60.00
36
    constant real      bj_HANDICAP_NORMAL               = 90.00
37
    constant real      bj_HANDICAPDAMAGE_EASY           = 50.00
38
    constant real      bj_HANDICAPDAMAGE_NORMAL         = 90.00
39
    constant real      bj_HANDICAPREVIVE_NOTHARD        = 50.00
40
    constant real      bj_GAME_STARTED_THRESHOLD        =  0.01
41
    constant real      bj_WAIT_FOR_COND_MIN_INTERVAL    =  0.10
42
    constant real      bj_POLLED_WAIT_INTERVAL          =  0.10
43
    constant real      bj_POLLED_WAIT_SKIP_THRESHOLD    =  2.00
44
45
    // Game constants
46
    constant integer   bj_MAX_INVENTORY                 =  6
47
    constant integer   bj_MAX_PLAYERS                   =  GetBJMaxPlayers()
48
    constant integer   bj_PLAYER_NEUTRAL_VICTIM         =  GetBJPlayerNeutralVictim()
49
    constant integer   bj_PLAYER_NEUTRAL_EXTRA          =  GetBJPlayerNeutralExtra()
50
    constant integer   bj_MAX_PLAYER_SLOTS              =  GetBJMaxPlayerSlots()
51
    constant integer   bj_MAX_SKELETONS                 =  25
52
    constant integer   bj_MAX_STOCK_ITEM_SLOTS          =  11
53
    constant integer   bj_MAX_STOCK_UNIT_SLOTS          =  11
54
    constant integer   bj_MAX_ITEM_LEVEL                =  10
55
    
56
    // Auto Save constants
57
    constant integer   bj_MAX_CHECKPOINTS               =  5
58
59
    // Ideally these would be looked up from Units/MiscData.txt,
60
    // but there is currently no script functionality exposed to do that
61
    constant real      bj_TOD_DAWN                      = 6.00
62
    constant real      bj_TOD_DUSK                      = 18.00
63
64
    // Melee game settings:
65
    //   - Starting Time of Day (TOD)
66
    //   - Starting Gold
67
    //   - Starting Lumber
68
    //   - Starting Hero Tokens (free heroes)
69
    //   - Max heroes allowed per player
70
    //   - Max heroes allowed per hero type
71
    //   - Distance from start loc to search for nearby mines
72
    //
73
    constant real      bj_MELEE_STARTING_TOD            = 8.00
74
    constant integer   bj_MELEE_STARTING_GOLD_V0        = 750
75
    constant integer   bj_MELEE_STARTING_GOLD_V1        = 500
76
    constant integer   bj_MELEE_STARTING_LUMBER_V0      = 200
77
    constant integer   bj_MELEE_STARTING_LUMBER_V1      = 150
78
    constant integer   bj_MELEE_STARTING_HERO_TOKENS    = 1
79
    constant integer   bj_MELEE_HERO_LIMIT              = 3
80
    constant integer   bj_MELEE_HERO_TYPE_LIMIT         = 1
81
    constant real      bj_MELEE_MINE_SEARCH_RADIUS      = 2000
82
    constant real      bj_MELEE_CLEAR_UNITS_RADIUS      = 1500
83
    constant real      bj_MELEE_CRIPPLE_TIMEOUT         = 120.00
84
    constant real      bj_MELEE_CRIPPLE_MSG_DURATION    = 20.00
85
    constant integer   bj_MELEE_MAX_TWINKED_HEROES_V0   = 3
86
    constant integer   bj_MELEE_MAX_TWINKED_HEROES_V1   = 1
87
88
    // Delay between a creep's death and the time it may drop an item.
89
    constant real      bj_CREEP_ITEM_DELAY              = 0.50
90
91
    // Timing settings for Marketplace inventories.
92
    constant real      bj_STOCK_RESTOCK_INITIAL_DELAY   = 120
93
    constant real      bj_STOCK_RESTOCK_INTERVAL        = 30
94
    constant integer   bj_STOCK_MAX_ITERATIONS          = 20
95
96
    // Max events registered by a single "dest dies in region" event.
97
    constant integer   bj_MAX_DEST_IN_REGION_EVENTS     = 64
98
99
    // Camera settings
100
    constant integer   bj_CAMERA_MIN_FARZ               = 100
101
    constant integer   bj_CAMERA_DEFAULT_DISTANCE       = 1650
102
    constant integer   bj_CAMERA_DEFAULT_FARZ           = 5000
103
    constant integer   bj_CAMERA_DEFAULT_AOA            = 304
104
    constant integer   bj_CAMERA_DEFAULT_FOV            = 70
105
    constant integer   bj_CAMERA_DEFAULT_ROLL           = 0
106
    constant integer   bj_CAMERA_DEFAULT_ROTATION       = 90
107
108
    // Rescue
109
    constant real      bj_RESCUE_PING_TIME              = 2.00
110
111
    // Transmission behavior settings
112
    constant real      bj_NOTHING_SOUND_DURATION        = 5.00
113
    constant real      bj_TRANSMISSION_PING_TIME        = 1.00
114
    constant integer   bj_TRANSMISSION_IND_RED          = 255
115
    constant integer   bj_TRANSMISSION_IND_BLUE         = 255
116
    constant integer   bj_TRANSMISSION_IND_GREEN        = 255
117
    constant integer   bj_TRANSMISSION_IND_ALPHA        = 255
118
    constant real      bj_TRANSMISSION_PORT_HANGTIME    = 1.50
119
120
    // Cinematic mode settings
121
    constant real      bj_CINEMODE_INTERFACEFADE        = 0.50
122
    constant gamespeed bj_CINEMODE_GAMESPEED            = MAP_SPEED_NORMAL
123
124
    // Cinematic mode volume levels
125
    constant real      bj_CINEMODE_VOLUME_UNITMOVEMENT  = 0.40
126
    constant real      bj_CINEMODE_VOLUME_UNITSOUNDS    = 0.00
127
    constant real      bj_CINEMODE_VOLUME_COMBAT        = 0.40
128
    constant real      bj_CINEMODE_VOLUME_SPELLS        = 0.40
129
    constant real      bj_CINEMODE_VOLUME_UI            = 0.00
130
    constant real      bj_CINEMODE_VOLUME_MUSIC         = 0.55
131
    constant real      bj_CINEMODE_VOLUME_AMBIENTSOUNDS = 1.00
132
    constant real      bj_CINEMODE_VOLUME_FIRE          = 0.60
133
134
    // Speech mode volume levels
135
    constant real      bj_SPEECH_VOLUME_UNITMOVEMENT    = 0.25
136
    constant real      bj_SPEECH_VOLUME_UNITSOUNDS      = 0.00
137
    constant real      bj_SPEECH_VOLUME_COMBAT          = 0.25
138
    constant real      bj_SPEECH_VOLUME_SPELLS          = 0.25
139
    constant real      bj_SPEECH_VOLUME_UI              = 0.00
140
    constant real      bj_SPEECH_VOLUME_MUSIC           = 0.55
141
    constant real      bj_SPEECH_VOLUME_AMBIENTSOUNDS   = 1.00
142
    constant real      bj_SPEECH_VOLUME_FIRE            = 0.60
143
144
    // Smart pan settings
145
    constant real      bj_SMARTPAN_TRESHOLD_PAN         = 500
146
    constant real      bj_SMARTPAN_TRESHOLD_SNAP        = 3500
147
148
    // QueuedTriggerExecute settings
149
    constant integer   bj_MAX_QUEUED_TRIGGERS           = 100
150
    constant real      bj_QUEUED_TRIGGER_TIMEOUT        = 180.00
151
152
    // Campaign indexing constants
153
    constant integer   bj_CAMPAIGN_INDEX_T        = 0
154
    constant integer   bj_CAMPAIGN_INDEX_H        = 1
155
    constant integer   bj_CAMPAIGN_INDEX_U        = 2
156
    constant integer   bj_CAMPAIGN_INDEX_O        = 3
157
    constant integer   bj_CAMPAIGN_INDEX_N        = 4
158
    constant integer   bj_CAMPAIGN_INDEX_XN       = 5
159
    constant integer   bj_CAMPAIGN_INDEX_XH       = 6
160
    constant integer   bj_CAMPAIGN_INDEX_XU       = 7
161
    constant integer   bj_CAMPAIGN_INDEX_XO       = 8
162
163
    // Campaign offset constants (for mission indexing)
164
    constant integer   bj_CAMPAIGN_OFFSET_T       = 0
165
    constant integer   bj_CAMPAIGN_OFFSET_H       = 1
166
    constant integer   bj_CAMPAIGN_OFFSET_U       = 2
167
    constant integer   bj_CAMPAIGN_OFFSET_O       = 3
168
    constant integer   bj_CAMPAIGN_OFFSET_N       = 4
169
    constant integer   bj_CAMPAIGN_OFFSET_XN      = 5
170
    constant integer   bj_CAMPAIGN_OFFSET_XH      = 6
171
    constant integer   bj_CAMPAIGN_OFFSET_XU      = 7
172
    constant integer   bj_CAMPAIGN_OFFSET_XO      = 8
173
174
    // Mission indexing constants
175
    // Tutorial
176
    constant integer   bj_MISSION_INDEX_T00       = bj_CAMPAIGN_OFFSET_T * 1000 + 0
177
    constant integer   bj_MISSION_INDEX_T01       = bj_CAMPAIGN_OFFSET_T * 1000 + 1
178
    constant integer   bj_MISSION_INDEX_T02       = bj_CAMPAIGN_OFFSET_T * 1000 + 2
179
    constant integer   bj_MISSION_INDEX_T03       = bj_CAMPAIGN_OFFSET_T * 1000 + 3
180
    constant integer   bj_MISSION_INDEX_T04       = bj_CAMPAIGN_OFFSET_T * 1000 + 4
181
    // Human
182
    constant integer   bj_MISSION_INDEX_H00       = bj_CAMPAIGN_OFFSET_H * 1000 + 0
183
    constant integer   bj_MISSION_INDEX_H01       = bj_CAMPAIGN_OFFSET_H * 1000 + 1
184
    constant integer   bj_MISSION_INDEX_H02       = bj_CAMPAIGN_OFFSET_H * 1000 + 2
185
    constant integer   bj_MISSION_INDEX_H03       = bj_CAMPAIGN_OFFSET_H * 1000 + 3
186
    constant integer   bj_MISSION_INDEX_H04       = bj_CAMPAIGN_OFFSET_H * 1000 + 4
187
    constant integer   bj_MISSION_INDEX_H05       = bj_CAMPAIGN_OFFSET_H * 1000 + 5
188
    constant integer   bj_MISSION_INDEX_H06       = bj_CAMPAIGN_OFFSET_H * 1000 + 6
189
    constant integer   bj_MISSION_INDEX_H07       = bj_CAMPAIGN_OFFSET_H * 1000 + 7
190
    constant integer   bj_MISSION_INDEX_H08       = bj_CAMPAIGN_OFFSET_H * 1000 + 8
191
    constant integer   bj_MISSION_INDEX_H09       = bj_CAMPAIGN_OFFSET_H * 1000 + 9
192
    constant integer   bj_MISSION_INDEX_H10       = bj_CAMPAIGN_OFFSET_H * 1000 + 10
193
    constant integer   bj_MISSION_INDEX_H11       = bj_CAMPAIGN_OFFSET_H * 1000 + 11
194
    // Undead
195
    constant integer   bj_MISSION_INDEX_U00       = bj_CAMPAIGN_OFFSET_U * 1000 + 0
196
    constant integer   bj_MISSION_INDEX_U01       = bj_CAMPAIGN_OFFSET_U * 1000 + 1
197
    constant integer   bj_MISSION_INDEX_U02       = bj_CAMPAIGN_OFFSET_U * 1000 + 2
198
    constant integer   bj_MISSION_INDEX_U03       = bj_CAMPAIGN_OFFSET_U * 1000 + 3
199
    constant integer   bj_MISSION_INDEX_U05       = bj_CAMPAIGN_OFFSET_U * 1000 + 4
200
    constant integer   bj_MISSION_INDEX_U07       = bj_CAMPAIGN_OFFSET_U * 1000 + 5
201
    constant integer   bj_MISSION_INDEX_U08       = bj_CAMPAIGN_OFFSET_U * 1000 + 6
202
    constant integer   bj_MISSION_INDEX_U09       = bj_CAMPAIGN_OFFSET_U * 1000 + 7
203
    constant integer   bj_MISSION_INDEX_U10       = bj_CAMPAIGN_OFFSET_U * 1000 + 8
204
    constant integer   bj_MISSION_INDEX_U11       = bj_CAMPAIGN_OFFSET_U * 1000 + 9
205
    // Orc
206
    constant integer   bj_MISSION_INDEX_O00       = bj_CAMPAIGN_OFFSET_O * 1000 + 0
207
    constant integer   bj_MISSION_INDEX_O01       = bj_CAMPAIGN_OFFSET_O * 1000 + 1
208
    constant integer   bj_MISSION_INDEX_O02       = bj_CAMPAIGN_OFFSET_O * 1000 + 2
209
    constant integer   bj_MISSION_INDEX_O03       = bj_CAMPAIGN_OFFSET_O * 1000 + 3
210
    constant integer   bj_MISSION_INDEX_O04       = bj_CAMPAIGN_OFFSET_O * 1000 + 4
211
    constant integer   bj_MISSION_INDEX_O05       = bj_CAMPAIGN_OFFSET_O * 1000 + 5
212
    constant integer   bj_MISSION_INDEX_O06       = bj_CAMPAIGN_OFFSET_O * 1000 + 6
213
    constant integer   bj_MISSION_INDEX_O07       = bj_CAMPAIGN_OFFSET_O * 1000 + 7
214
    constant integer   bj_MISSION_INDEX_O08       = bj_CAMPAIGN_OFFSET_O * 1000 + 8
215
    constant integer   bj_MISSION_INDEX_O09       = bj_CAMPAIGN_OFFSET_O * 1000 + 9
216
    constant integer   bj_MISSION_INDEX_O10       = bj_CAMPAIGN_OFFSET_O * 1000 + 10
217
    // Night Elf
218
    constant integer   bj_MISSION_INDEX_N00       = bj_CAMPAIGN_OFFSET_N * 1000 + 0
219
    constant integer   bj_MISSION_INDEX_N01       = bj_CAMPAIGN_OFFSET_N * 1000 + 1
220
    constant integer   bj_MISSION_INDEX_N02       = bj_CAMPAIGN_OFFSET_N * 1000 + 2
221
    constant integer   bj_MISSION_INDEX_N03       = bj_CAMPAIGN_OFFSET_N * 1000 + 3
222
    constant integer   bj_MISSION_INDEX_N04       = bj_CAMPAIGN_OFFSET_N * 1000 + 4
223
    constant integer   bj_MISSION_INDEX_N05       = bj_CAMPAIGN_OFFSET_N * 1000 + 5
224
    constant integer   bj_MISSION_INDEX_N06       = bj_CAMPAIGN_OFFSET_N * 1000 + 6
225
    constant integer   bj_MISSION_INDEX_N07       = bj_CAMPAIGN_OFFSET_N * 1000 + 7
226
    constant integer   bj_MISSION_INDEX_N08       = bj_CAMPAIGN_OFFSET_N * 1000 + 8
227
    constant integer   bj_MISSION_INDEX_N09       = bj_CAMPAIGN_OFFSET_N * 1000 + 9
228
    // Expansion Night Elf
229
    constant integer   bj_MISSION_INDEX_XN00       = bj_CAMPAIGN_OFFSET_XN * 1000 + 0
230
    constant integer   bj_MISSION_INDEX_XN01       = bj_CAMPAIGN_OFFSET_XN * 1000 + 1
231
    constant integer   bj_MISSION_INDEX_XN02       = bj_CAMPAIGN_OFFSET_XN * 1000 + 2
232
    constant integer   bj_MISSION_INDEX_XN03       = bj_CAMPAIGN_OFFSET_XN * 1000 + 3
233
    constant integer   bj_MISSION_INDEX_XN04       = bj_CAMPAIGN_OFFSET_XN * 1000 + 4
234
    constant integer   bj_MISSION_INDEX_XN05       = bj_CAMPAIGN_OFFSET_XN * 1000 + 5
235
    constant integer   bj_MISSION_INDEX_XN06       = bj_CAMPAIGN_OFFSET_XN * 1000 + 6
236
    constant integer   bj_MISSION_INDEX_XN07       = bj_CAMPAIGN_OFFSET_XN * 1000 + 7
237
    constant integer   bj_MISSION_INDEX_XN08       = bj_CAMPAIGN_OFFSET_XN * 1000 + 8
238
    constant integer   bj_MISSION_INDEX_XN09       = bj_CAMPAIGN_OFFSET_XN * 1000 + 9
239
    constant integer   bj_MISSION_INDEX_XN10       = bj_CAMPAIGN_OFFSET_XN * 1000 + 10
240
    // Expansion Human
241
    constant integer   bj_MISSION_INDEX_XH00       = bj_CAMPAIGN_OFFSET_XH * 1000 + 0
242
    constant integer   bj_MISSION_INDEX_XH01       = bj_CAMPAIGN_OFFSET_XH * 1000 + 1
243
    constant integer   bj_MISSION_INDEX_XH02       = bj_CAMPAIGN_OFFSET_XH * 1000 + 2
244
    constant integer   bj_MISSION_INDEX_XH03       = bj_CAMPAIGN_OFFSET_XH * 1000 + 3
245
    constant integer   bj_MISSION_INDEX_XH04       = bj_CAMPAIGN_OFFSET_XH * 1000 + 4
246
    constant integer   bj_MISSION_INDEX_XH05       = bj_CAMPAIGN_OFFSET_XH * 1000 + 5
247
    constant integer   bj_MISSION_INDEX_XH06       = bj_CAMPAIGN_OFFSET_XH * 1000 + 6
248
    constant integer   bj_MISSION_INDEX_XH07       = bj_CAMPAIGN_OFFSET_XH * 1000 + 7
249
    constant integer   bj_MISSION_INDEX_XH08       = bj_CAMPAIGN_OFFSET_XH * 1000 + 8
250
    constant integer   bj_MISSION_INDEX_XH09       = bj_CAMPAIGN_OFFSET_XH * 1000 + 9
251
    // Expansion Undead
252
    constant integer   bj_MISSION_INDEX_XU00       = bj_CAMPAIGN_OFFSET_XU * 1000 + 0
253
    constant integer   bj_MISSION_INDEX_XU01       = bj_CAMPAIGN_OFFSET_XU * 1000 + 1
254
    constant integer   bj_MISSION_INDEX_XU02       = bj_CAMPAIGN_OFFSET_XU * 1000 + 2
255
    constant integer   bj_MISSION_INDEX_XU03       = bj_CAMPAIGN_OFFSET_XU * 1000 + 3
256
    constant integer   bj_MISSION_INDEX_XU04       = bj_CAMPAIGN_OFFSET_XU * 1000 + 4
257
    constant integer   bj_MISSION_INDEX_XU05       = bj_CAMPAIGN_OFFSET_XU * 1000 + 5
258
    constant integer   bj_MISSION_INDEX_XU06       = bj_CAMPAIGN_OFFSET_XU * 1000 + 6
259
    constant integer   bj_MISSION_INDEX_XU07       = bj_CAMPAIGN_OFFSET_XU * 1000 + 7
260
    constant integer   bj_MISSION_INDEX_XU08       = bj_CAMPAIGN_OFFSET_XU * 1000 + 8
261
    constant integer   bj_MISSION_INDEX_XU09       = bj_CAMPAIGN_OFFSET_XU * 1000 + 9
262
    constant integer   bj_MISSION_INDEX_XU10       = bj_CAMPAIGN_OFFSET_XU * 1000 + 10
263
    constant integer   bj_MISSION_INDEX_XU11       = bj_CAMPAIGN_OFFSET_XU * 1000 + 11
264
    constant integer   bj_MISSION_INDEX_XU12       = bj_CAMPAIGN_OFFSET_XU * 1000 + 12
265
    constant integer   bj_MISSION_INDEX_XU13       = bj_CAMPAIGN_OFFSET_XU * 1000 + 13
266
267
    // Expansion Orc
268
    constant integer   bj_MISSION_INDEX_XO00       = bj_CAMPAIGN_OFFSET_XO * 1000 + 0
269
    constant integer   bj_MISSION_INDEX_XO01       = bj_CAMPAIGN_OFFSET_XO * 1000 + 1
270
    constant integer   bj_MISSION_INDEX_XO02       = bj_CAMPAIGN_OFFSET_XO * 1000 + 2
271
    constant integer   bj_MISSION_INDEX_XO03       = bj_CAMPAIGN_OFFSET_XO * 1000 + 3
272
273
    // Cinematic indexing constants
274
    constant integer   bj_CINEMATICINDEX_TOP      = 0
275
    constant integer   bj_CINEMATICINDEX_HOP      = 1
276
    constant integer   bj_CINEMATICINDEX_HED      = 2
277
    constant integer   bj_CINEMATICINDEX_OOP      = 3
278
    constant integer   bj_CINEMATICINDEX_OED      = 4
279
    constant integer   bj_CINEMATICINDEX_UOP      = 5
280
    constant integer   bj_CINEMATICINDEX_UED      = 6
281
    constant integer   bj_CINEMATICINDEX_NOP      = 7
282
    constant integer   bj_CINEMATICINDEX_NED      = 8
283
    constant integer   bj_CINEMATICINDEX_XOP      = 9
284
    constant integer   bj_CINEMATICINDEX_XED      = 10
285
286
    // Alliance settings
287
    constant integer   bj_ALLIANCE_UNALLIED        = 0
288
    constant integer   bj_ALLIANCE_UNALLIED_VISION = 1
289
    constant integer   bj_ALLIANCE_ALLIED          = 2
290
    constant integer   bj_ALLIANCE_ALLIED_VISION   = 3
291
    constant integer   bj_ALLIANCE_ALLIED_UNITS    = 4
292
    constant integer   bj_ALLIANCE_ALLIED_ADVUNITS = 5
293
    constant integer   bj_ALLIANCE_NEUTRAL         = 6
294
    constant integer   bj_ALLIANCE_NEUTRAL_VISION  = 7
295
296
    // Keyboard Event Types
297
    constant integer   bj_KEYEVENTTYPE_DEPRESS     = 0
298
    constant integer   bj_KEYEVENTTYPE_RELEASE     = 1
299
300
    // Keyboard Event Keys
301
    constant integer   bj_KEYEVENTKEY_LEFT         = 0
302
    constant integer   bj_KEYEVENTKEY_RIGHT        = 1
303
    constant integer   bj_KEYEVENTKEY_DOWN         = 2
304
    constant integer   bj_KEYEVENTKEY_UP           = 3
305
306
    // Mouse Event Types
307
    constant integer   bj_MOUSEEVENTTYPE_DOWN     = 0
308
    constant integer   bj_MOUSEEVENTTYPE_UP       = 1
309
    constant integer   bj_MOUSEEVENTTYPE_MOVE     = 2
310
311
    // Transmission timing methods
312
    constant integer   bj_TIMETYPE_ADD             = 0
313
    constant integer   bj_TIMETYPE_SET             = 1
314
    constant integer   bj_TIMETYPE_SUB             = 2
315
316
    // Camera bounds adjustment methods
317
    constant integer   bj_CAMERABOUNDS_ADJUST_ADD  = 0
318
    constant integer   bj_CAMERABOUNDS_ADJUST_SUB  = 1
319
320
    // Quest creation states
321
    constant integer   bj_QUESTTYPE_REQ_DISCOVERED   = 0
322
    constant integer   bj_QUESTTYPE_REQ_UNDISCOVERED = 1
323
    constant integer   bj_QUESTTYPE_OPT_DISCOVERED   = 2
324
    constant integer   bj_QUESTTYPE_OPT_UNDISCOVERED = 3
325
326
    // Quest message types
327
    constant integer   bj_QUESTMESSAGE_DISCOVERED    = 0
328
    constant integer   bj_QUESTMESSAGE_UPDATED       = 1
329
    constant integer   bj_QUESTMESSAGE_COMPLETED     = 2
330
    constant integer   bj_QUESTMESSAGE_FAILED        = 3
331
    constant integer   bj_QUESTMESSAGE_REQUIREMENT   = 4
332
    constant integer   bj_QUESTMESSAGE_MISSIONFAILED = 5
333
    constant integer   bj_QUESTMESSAGE_ALWAYSHINT    = 6
334
    constant integer   bj_QUESTMESSAGE_HINT          = 7
335
    constant integer   bj_QUESTMESSAGE_SECRET        = 8
336
    constant integer   bj_QUESTMESSAGE_UNITACQUIRED  = 9
337
    constant integer   bj_QUESTMESSAGE_UNITAVAILABLE = 10
338
    constant integer   bj_QUESTMESSAGE_ITEMACQUIRED  = 11
339
    constant integer   bj_QUESTMESSAGE_WARNING       = 12
340
341
    // Leaderboard sorting methods
342
    constant integer   bj_SORTTYPE_SORTBYVALUE     = 0
343
    constant integer   bj_SORTTYPE_SORTBYPLAYER    = 1
344
    constant integer   bj_SORTTYPE_SORTBYLABEL     = 2
345
346
    // Cinematic fade filter methods
347
    constant integer   bj_CINEFADETYPE_FADEIN      = 0
348
    constant integer   bj_CINEFADETYPE_FADEOUT     = 1
349
    constant integer   bj_CINEFADETYPE_FADEOUTIN   = 2
350
351
    // Buff removal methods
352
    constant integer   bj_REMOVEBUFFS_POSITIVE     = 0
353
    constant integer   bj_REMOVEBUFFS_NEGATIVE     = 1
354
    constant integer   bj_REMOVEBUFFS_ALL          = 2
355
    constant integer   bj_REMOVEBUFFS_NONTLIFE     = 3
356
357
    // Buff properties - polarity
358
    constant integer   bj_BUFF_POLARITY_POSITIVE   = 0
359
    constant integer   bj_BUFF_POLARITY_NEGATIVE   = 1
360
    constant integer   bj_BUFF_POLARITY_EITHER     = 2
361
362
    // Buff properties - resist type
363
    constant integer   bj_BUFF_RESIST_MAGIC        = 0
364
    constant integer   bj_BUFF_RESIST_PHYSICAL     = 1
365
    constant integer   bj_BUFF_RESIST_EITHER       = 2
366
    constant integer   bj_BUFF_RESIST_BOTH         = 3
367
368
    // Hero stats
369
    constant integer   bj_HEROSTAT_STR             = 0
370
    constant integer   bj_HEROSTAT_AGI             = 1
371
    constant integer   bj_HEROSTAT_INT             = 2
372
373
    // Hero skill point modification methods
374
    constant integer   bj_MODIFYMETHOD_ADD    = 0
375
    constant integer   bj_MODIFYMETHOD_SUB    = 1
376
    constant integer   bj_MODIFYMETHOD_SET    = 2
377
378
    // Unit state adjustment methods (for replaced units)
379
    constant integer   bj_UNIT_STATE_METHOD_ABSOLUTE = 0
380
    constant integer   bj_UNIT_STATE_METHOD_RELATIVE = 1
381
    constant integer   bj_UNIT_STATE_METHOD_DEFAULTS = 2
382
    constant integer   bj_UNIT_STATE_METHOD_MAXIMUM  = 3
383
384
    // Gate operations
385
    constant integer   bj_GATEOPERATION_CLOSE      = 0
386
    constant integer   bj_GATEOPERATION_OPEN       = 1
387
    constant integer   bj_GATEOPERATION_DESTROY    = 2
388
389
    // Game cache value types
390
    constant integer   bj_GAMECACHE_BOOLEAN                 = 0
391
    constant integer   bj_GAMECACHE_INTEGER                 = 1
392
    constant integer   bj_GAMECACHE_REAL                    = 2
393
    constant integer   bj_GAMECACHE_UNIT                    = 3
394
    constant integer   bj_GAMECACHE_STRING                  = 4
395
    
396
    // Hashtable value types
397
    constant integer   bj_HASHTABLE_BOOLEAN                 = 0
398
    constant integer   bj_HASHTABLE_INTEGER                 = 1
399
    constant integer   bj_HASHTABLE_REAL                    = 2
400
    constant integer   bj_HASHTABLE_STRING                  = 3
401
    constant integer   bj_HASHTABLE_HANDLE                  = 4
402
403
    // Item status types
404
    constant integer   bj_ITEM_STATUS_HIDDEN       = 0
405
    constant integer   bj_ITEM_STATUS_OWNED        = 1
406
    constant integer   bj_ITEM_STATUS_INVULNERABLE = 2
407
    constant integer   bj_ITEM_STATUS_POWERUP      = 3
408
    constant integer   bj_ITEM_STATUS_SELLABLE     = 4
409
    constant integer   bj_ITEM_STATUS_PAWNABLE     = 5
410
411
    // Itemcode status types
412
    constant integer   bj_ITEMCODE_STATUS_POWERUP  = 0
413
    constant integer   bj_ITEMCODE_STATUS_SELLABLE = 1
414
    constant integer   bj_ITEMCODE_STATUS_PAWNABLE = 2
415
416
    // Minimap ping styles
417
    constant integer   bj_MINIMAPPINGSTYLE_SIMPLE  = 0
418
    constant integer   bj_MINIMAPPINGSTYLE_FLASHY  = 1
419
    constant integer   bj_MINIMAPPINGSTYLE_ATTACK  = 2
420
    
421
    // Campaign Minimap icon styles
422
    constant integer   bj_CAMPPINGSTYLE_PRIMARY            = 0
423
    constant integer   bj_CAMPPINGSTYLE_PRIMARY_GREEN   = 1
424
    constant integer   bj_CAMPPINGSTYLE_PRIMARY_RED     = 2
425
    constant integer   bj_CAMPPINGSTYLE_BONUS            = 3
426
    constant integer   bj_CAMPPINGSTYLE_TURNIN            = 4
427
    constant integer   bj_CAMPPINGSTYLE_BOSS            = 5
428
    constant integer   bj_CAMPPINGSTYLE_CONTROL_ALLY    = 6
429
    constant integer   bj_CAMPPINGSTYLE_CONTROL_NEUTRAL    = 7
430
    constant integer   bj_CAMPPINGSTYLE_CONTROL_ENEMY    = 8
431
432
    // Corpse creation settings
433
    constant real      bj_CORPSE_MAX_DEATH_TIME    = 8.00
434
435
    // Corpse creation styles
436
    constant integer   bj_CORPSETYPE_FLESH         = 0
437
    constant integer   bj_CORPSETYPE_BONE          = 1
438
439
    // Elevator pathing-blocker destructable code
440
    constant integer   bj_ELEVATOR_BLOCKER_CODE    = 'DTep'
441
    constant integer   bj_ELEVATOR_CODE01          = 'DTrf'
442
    constant integer   bj_ELEVATOR_CODE02          = 'DTrx'
443
444
    // Elevator wall codes
445
    constant integer   bj_ELEVATOR_WALL_TYPE_ALL        = 0
446
    constant integer   bj_ELEVATOR_WALL_TYPE_EAST       = 1
447
    constant integer   bj_ELEVATOR_WALL_TYPE_NORTH      = 2
448
    constant integer   bj_ELEVATOR_WALL_TYPE_SOUTH      = 3
449
    constant integer   bj_ELEVATOR_WALL_TYPE_WEST       = 4
450
451
    //-----------------------------------------------------------------------
452
    // Variables
453
    //
454
455
    // Force predefs
456
    force              bj_FORCE_ALL_PLAYERS        = null
457
    force array        bj_FORCE_PLAYER
458
459
    integer            bj_MELEE_MAX_TWINKED_HEROES = 0
460
461
    // Map area rects
462
    rect               bj_mapInitialPlayableArea   = null
463
    rect               bj_mapInitialCameraBounds   = null
464
465
    // Utility function vars
466
    integer            bj_forLoopAIndex            = 0
467
    integer            bj_forLoopBIndex            = 0
468
    integer            bj_forLoopAIndexEnd         = 0
469
    integer            bj_forLoopBIndexEnd         = 0
470
471
    boolean            bj_slotControlReady         = false
472
    boolean array      bj_slotControlUsed
473
    mapcontrol array   bj_slotControl
474
475
    // Game started detection vars
476
    timer              bj_gameStartedTimer         = null
477
    boolean            bj_gameStarted              = false
478
    timer              bj_volumeGroupsTimer        = CreateTimer()
479
480
    // Singleplayer check
481
    boolean            bj_isSinglePlayer           = false
482
483
    // Day/Night Cycle vars
484
    trigger            bj_dncSoundsDay             = null
485
    trigger            bj_dncSoundsNight           = null
486
    sound              bj_dayAmbientSound          = null
487
    sound              bj_nightAmbientSound        = null
488
    trigger            bj_dncSoundsDawn            = null
489
    trigger            bj_dncSoundsDusk            = null
490
    sound              bj_dawnSound                = null
491
    sound              bj_duskSound                = null
492
    boolean            bj_useDawnDuskSounds        = true
493
    boolean            bj_dncIsDaytime             = false
494
495
    // Triggered sounds
496
    //sound              bj_pingMinimapSound         = null
497
    sound              bj_rescueSound              = null
498
    sound              bj_questDiscoveredSound     = null
499
    sound              bj_questUpdatedSound        = null
500
    sound              bj_questCompletedSound      = null
501
    sound              bj_questFailedSound         = null
502
    sound              bj_questHintSound           = null
503
    sound              bj_questSecretSound         = null
504
    sound              bj_questItemAcquiredSound   = null
505
    sound              bj_questWarningSound        = null
506
    sound              bj_victoryDialogSound       = null
507
    sound              bj_defeatDialogSound        = null
508
509
    // Marketplace vars
510
    trigger            bj_stockItemPurchased       = null
511
    timer              bj_stockUpdateTimer         = null
512
    boolean array      bj_stockAllowedPermanent
513
    boolean array      bj_stockAllowedCharged
514
    boolean array      bj_stockAllowedArtifact
515
    integer            bj_stockPickedItemLevel     = 0
516
    itemtype           bj_stockPickedItemType
517
518
    // Melee vars
519
    trigger            bj_meleeVisibilityTrained   = null
520
    boolean            bj_meleeVisibilityIsDay     = true
521
    boolean            bj_meleeGrantHeroItems      = false
522
    location           bj_meleeNearestMineToLoc    = null
523
    unit               bj_meleeNearestMine         = null
524
    real               bj_meleeNearestMineDist     = 0.00
525
    boolean            bj_meleeGameOver            = false
526
    boolean array      bj_meleeDefeated
527
    boolean array      bj_meleeVictoried
528
    unit array         bj_ghoul
529
    timer array        bj_crippledTimer
530
    timerdialog array  bj_crippledTimerWindows
531
    boolean array      bj_playerIsCrippled
532
    boolean array      bj_playerIsExposed
533
    boolean            bj_finishSoonAllExposed     = false
534
    timerdialog        bj_finishSoonTimerDialog    = null
535
    integer array      bj_meleeTwinkedHeroes
536
537
    // Rescue behavior vars
538
    trigger            bj_rescueUnitBehavior       = null
539
    boolean            bj_rescueChangeColorUnit    = true
540
    boolean            bj_rescueChangeColorBldg    = true
541
542
    // Transmission vars
543
    timer              bj_cineSceneEndingTimer     = null
544
    sound              bj_cineSceneLastSound       = null
545
    trigger            bj_cineSceneBeingSkipped    = null
546
547
    // Cinematic mode vars
548
    gamespeed          bj_cineModePriorSpeed       = MAP_SPEED_NORMAL
549
    boolean            bj_cineModePriorFogSetting  = false
550
    boolean            bj_cineModePriorMaskSetting = false
551
    boolean            bj_cineModeAlreadyIn        = false
552
    boolean            bj_cineModePriorDawnDusk    = false
553
    integer            bj_cineModeSavedSeed        = 0
554
555
    // Cinematic fade vars
556
    timer              bj_cineFadeFinishTimer      = null
557
    timer              bj_cineFadeContinueTimer    = null
558
    real               bj_cineFadeContinueRed      = 0
559
    real               bj_cineFadeContinueGreen    = 0
560
    real               bj_cineFadeContinueBlue     = 0
561
    real               bj_cineFadeContinueTrans    = 0
562
    real               bj_cineFadeContinueDuration = 0
563
    string             bj_cineFadeContinueTex      = ""
564
565
    // QueuedTriggerExecute vars
566
    integer            bj_queuedExecTotal          = 0
567
    trigger array      bj_queuedExecTriggers
568
    boolean array      bj_queuedExecUseConds
569
    timer              bj_queuedExecTimeoutTimer   = CreateTimer()
570
    trigger            bj_queuedExecTimeout        = null
571
572
    // Helper vars (for Filter and Enum funcs)
573
    integer            bj_destInRegionDiesCount    = 0
574
    trigger            bj_destInRegionDiesTrig     = null
575
    integer            bj_groupCountUnits          = 0
576
    integer            bj_forceCountPlayers        = 0
577
    integer            bj_groupEnumTypeId          = 0
578
    player             bj_groupEnumOwningPlayer    = null
579
    group              bj_groupAddGroupDest        = null
580
    group              bj_groupRemoveGroupDest     = null
581
    integer            bj_groupRandomConsidered    = 0
582
    unit               bj_groupRandomCurrentPick   = null
583
    group              bj_groupLastCreatedDest     = null
584
    group              bj_randomSubGroupGroup      = null
585
    integer            bj_randomSubGroupWant       = 0
586
    integer            bj_randomSubGroupTotal      = 0
587
    real               bj_randomSubGroupChance     = 0
588
    integer            bj_destRandomConsidered     = 0
589
    destructable       bj_destRandomCurrentPick    = null
590
    destructable       bj_elevatorWallBlocker      = null
591
    destructable       bj_elevatorNeighbor         = null
592
    integer            bj_itemRandomConsidered     = 0
593
    item               bj_itemRandomCurrentPick    = null
594
    integer            bj_forceRandomConsidered    = 0
595
    player             bj_forceRandomCurrentPick   = null
596
    unit               bj_makeUnitRescuableUnit    = null
597
    boolean            bj_makeUnitRescuableFlag    = true
598
    boolean            bj_pauseAllUnitsFlag        = true
599
    location           bj_enumDestructableCenter   = null
600
    real               bj_enumDestructableRadius   = 0
601
    playercolor        bj_setPlayerTargetColor     = null
602
    boolean            bj_isUnitGroupDeadResult    = true
603
    boolean            bj_isUnitGroupEmptyResult   = true
604
    boolean            bj_isUnitGroupInRectResult  = true
605
    rect               bj_isUnitGroupInRectRect    = null
606
    boolean            bj_changeLevelShowScores    = false
607
    string             bj_changeLevelMapName       = null
608
    group              bj_suspendDecayFleshGroup   = CreateGroup()
609
    group              bj_suspendDecayBoneGroup    = CreateGroup()
610
    timer              bj_delayedSuspendDecayTimer = CreateTimer()
611
    trigger            bj_delayedSuspendDecayTrig  = null
612
    integer            bj_livingPlayerUnitsTypeId  = 0
613
    widget             bj_lastDyingWidget          = null
614
615
    // Random distribution vars
616
    integer            bj_randDistCount            = 0
617
    integer array      bj_randDistID
618
    integer array      bj_randDistChance
619
620
    // Last X'd vars
621
    unit               bj_lastCreatedUnit          = null
622
    item               bj_lastCreatedItem          = null
623
    item               bj_lastRemovedItem          = null
624
    unit               bj_lastHauntedGoldMine      = null
625
    destructable       bj_lastCreatedDestructable  = null
626
    group              bj_lastCreatedGroup         = CreateGroup()
627
    fogmodifier        bj_lastCreatedFogModifier   = null
628
    effect             bj_lastCreatedEffect        = null
629
    weathereffect      bj_lastCreatedWeatherEffect = null
630
    terraindeformation bj_lastCreatedTerrainDeformation = null
631
    quest              bj_lastCreatedQuest         = null
632
    questitem          bj_lastCreatedQuestItem     = null
633
    defeatcondition    bj_lastCreatedDefeatCondition = null
634
    timer              bj_lastStartedTimer         = CreateTimer()
635
    timerdialog        bj_lastCreatedTimerDialog   = null
636
    leaderboard        bj_lastCreatedLeaderboard   = null
637
    multiboard         bj_lastCreatedMultiboard    = null
638
    sound              bj_lastPlayedSound          = null
639
    string             bj_lastPlayedMusic          = ""
640
    real               bj_lastTransmissionDuration = 0
641
    gamecache          bj_lastCreatedGameCache     = null
642
    hashtable          bj_lastCreatedHashtable     = null
643
    unit               bj_lastLoadedUnit           = null
644
    button             bj_lastCreatedButton        = null
645
    unit               bj_lastReplacedUnit         = null
646
    texttag            bj_lastCreatedTextTag       = null
647
    lightning          bj_lastCreatedLightning     = null
648
    image              bj_lastCreatedImage         = null
649
    ubersplat          bj_lastCreatedUbersplat     = null
650
    minimapicon        bj_lastCreatedMinimapIcon   = null
651
    commandbuttoneffect bj_lastCreatedCommandButtonEffect = null
652
653
    // Filter function vars
654
    boolexpr           filterIssueHauntOrderAtLocBJ      = null
655
    boolexpr           filterEnumDestructablesInCircleBJ = null
656
    boolexpr           filterGetUnitsInRectOfPlayer      = null
657
    boolexpr           filterGetUnitsOfTypeIdAll         = null
658
    boolexpr           filterGetUnitsOfPlayerAndTypeId   = null
659
    boolexpr           filterMeleeTrainedUnitIsHeroBJ    = null
660
    boolexpr           filterLivingPlayerUnitsOfTypeId   = null
661
662
    // Memory cleanup vars
663
    boolean            bj_wantDestroyGroup         = false
664
665
    // Instanced Operation Results
666
    boolean            bj_lastInstObjFuncSuccessful = true
667
endglobals
668
669
670
671
//***************************************************************************
672
//*
673
//*  Debugging Functions
674
//*
675
//***************************************************************************
676
677
//===========================================================================
678
function BJDebugMsg takes string msg returns nothing
679
    local integer i = 0
680
    loop
681
        call DisplayTimedTextToPlayer(Player(i),0,0,60,msg)
682
        set i = i + 1
683
        exitwhen i == bj_MAX_PLAYERS
684
    endloop
685
endfunction
686
687
688
689
//***************************************************************************
690
//*
691
//*  Math Utility Functions
692
//*
693
//***************************************************************************
694
695
//===========================================================================
696
function RMinBJ takes real a, real b returns real
697
    if (a < b) then
698
        return a
699
    else
700
        return b
701
    endif
702
endfunction
703
704
//===========================================================================
705
function RMaxBJ takes real a, real b returns real
706
    if (a < b) then
707
        return b
708
    else
709
        return a
710
    endif
711
endfunction
712
713
//===========================================================================
714
function RAbsBJ takes real a returns real
715
    if (a >= 0) then
716
        return a
717
    else
718
        return -a
719
    endif
720
endfunction
721
722
//===========================================================================
723
function RSignBJ takes real a returns real
724
    if (a >= 0.0) then
725
        return 1.0
726
    else
727
        return -1.0
728
    endif
729
endfunction
730
731
//===========================================================================
732
function IMinBJ takes integer a, integer b returns integer
733
    if (a < b) then
734
        return a
735
    else
736
        return b
737
    endif
738
endfunction
739
740
//===========================================================================
741
function IMaxBJ takes integer a, integer b returns integer
742
    if (a < b) then
743
        return b
744
    else
745
        return a
746
    endif
747
endfunction
748
749
//===========================================================================
750
function IAbsBJ takes integer a returns integer
751
    if (a >= 0) then
752
        return a
753
    else
754
        return -a
755
    endif
756
endfunction
757
758
//===========================================================================
759
function ISignBJ takes integer a returns integer
760
    if (a >= 0) then
761
        return 1
762
    else
763
        return -1
764
    endif
765
endfunction
766
767
//===========================================================================
768
function SinBJ takes real degrees returns real
769
    return Sin(degrees * bj_DEGTORAD)
770
endfunction
771
772
//===========================================================================
773
function CosBJ takes real degrees returns real
774
    return Cos(degrees * bj_DEGTORAD)
775
endfunction
776
777
//===========================================================================
778
function TanBJ takes real degrees returns real
779
    return Tan(degrees * bj_DEGTORAD)
780
endfunction
781
782
//===========================================================================
783
function AsinBJ takes real degrees returns real
784
    return Asin(degrees) * bj_RADTODEG
785
endfunction
786
787
//===========================================================================
788
function AcosBJ takes real degrees returns real
789
    return Acos(degrees) * bj_RADTODEG
790
endfunction
791
792
//===========================================================================
793
function AtanBJ takes real degrees returns real
794
    return Atan(degrees) * bj_RADTODEG
795
endfunction
796
797
//===========================================================================
798
function Atan2BJ takes real y, real x returns real
799
    return Atan2(y, x) * bj_RADTODEG
800
endfunction
801
802
//===========================================================================
803
function AngleBetweenPoints takes location locA, location locB returns real
804
    return bj_RADTODEG * Atan2(GetLocationY(locB) - GetLocationY(locA), GetLocationX(locB) - GetLocationX(locA))
805
endfunction
806
807
//===========================================================================
808
function DistanceBetweenPoints takes location locA, location locB returns real
809
    local real dx = GetLocationX(locB) - GetLocationX(locA)
810
    local real dy = GetLocationY(locB) - GetLocationY(locA)
811
    return SquareRoot(dx * dx + dy * dy)
812
endfunction
813
814
//===========================================================================
815
function PolarProjectionBJ takes location source, real dist, real angle returns location
816
    local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
817
    local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
818
    return Location(x, y)
819
endfunction
820
821
//===========================================================================
822
function GetRandomDirectionDeg takes nothing returns real
823
    return GetRandomReal(0, 360)
824
endfunction
825
826
//===========================================================================
827
function GetRandomPercentageBJ takes nothing returns real
828
    return GetRandomReal(0, 100)
829
endfunction
830
831
//===========================================================================
832
function GetRandomLocInRect takes rect whichRect returns location
833
    return Location(GetRandomReal(GetRectMinX(whichRect), GetRectMaxX(whichRect)), GetRandomReal(GetRectMinY(whichRect), GetRectMaxY(whichRect)))
834
endfunction
835
836
//===========================================================================
837
// Calculate the modulus/remainder of (dividend) divided by (divisor).
838
// Examples:  18 mod 5 = 3.  15 mod 5 = 0.  -8 mod 5 = 2.
839
//
840
function ModuloInteger takes integer dividend, integer divisor returns integer
841
    local integer modulus = dividend - (dividend / divisor) * divisor
842
843
    // If the dividend was negative, the above modulus calculation will
844
    // be negative, but within (-divisor..0).  We can add (divisor) to
845
    // shift this result into the desired range of (0..divisor).
846
    if (modulus < 0) then
847
        set modulus = modulus + divisor
848
    endif
849
850
    return modulus
851
endfunction
852
853
//===========================================================================
854
// Calculate the modulus/remainder of (dividend) divided by (divisor).
855
// Examples:  13.000 mod 2.500 = 0.500.  -6.000 mod 2.500 = 1.500.
856
//
857
function ModuloReal takes real dividend, real divisor returns real
858
    local real modulus = dividend - I2R(R2I(dividend / divisor)) * divisor
859
860
    // If the dividend was negative, the above modulus calculation will
861
    // be negative, but within (-divisor..0).  We can add (divisor) to
862
    // shift this result into the desired range of (0..divisor).
863
    if (modulus < 0) then
864
        set modulus = modulus + divisor
865
    endif
866
867
    return modulus
868
endfunction
869
870
//===========================================================================
871
function OffsetLocation takes location loc, real dx, real dy returns location
872
    return Location(GetLocationX(loc) + dx, GetLocationY(loc) + dy)
873
endfunction
874
875
//===========================================================================
876
function OffsetRectBJ takes rect r, real dx, real dy returns rect
877
    return Rect( GetRectMinX(r) + dx, GetRectMinY(r) + dy, GetRectMaxX(r) + dx, GetRectMaxY(r) + dy )
878
endfunction
879
880
//===========================================================================
881
function RectFromCenterSizeBJ takes location center, real width, real height returns rect
882
    local real x = GetLocationX( center )
883
    local real y = GetLocationY( center )
884
    return Rect( x - width*0.5, y - height*0.5, x + width*0.5, y + height*0.5 )
885
endfunction
886
887
//===========================================================================
888
function RectContainsCoords takes rect r, real x, real y returns boolean
889
    return (GetRectMinX(r) <= x) and (x <= GetRectMaxX(r)) and (GetRectMinY(r) <= y) and (y <= GetRectMaxY(r))
890
endfunction
891
892
//===========================================================================
893
function RectContainsLoc takes rect r, location loc returns boolean
894
    return RectContainsCoords(r, GetLocationX(loc), GetLocationY(loc))
895
endfunction
896
897
//===========================================================================
898
function RectContainsUnit takes rect r, unit whichUnit returns boolean
899
    return RectContainsCoords(r, GetUnitX(whichUnit), GetUnitY(whichUnit))
900
endfunction
901
902
//===========================================================================
903
function RectContainsItem takes item whichItem, rect r returns boolean
904
    if (whichItem == null) then
905
        return false
906
    endif
907
908
    if (IsItemOwned(whichItem)) then
909
        return false
910
    endif
911
912
    return RectContainsCoords(r, GetItemX(whichItem), GetItemY(whichItem))
913
endfunction
914
915
916
917
//***************************************************************************
918
//*
919
//*  Utility Constructs
920
//*
921
//***************************************************************************
922
923
//===========================================================================
924
// Runs the trigger's actions if the trigger's conditions evaluate to true.
925
//
926
function ConditionalTriggerExecute takes trigger trig returns nothing
927
    if TriggerEvaluate(trig) then
928
        call TriggerExecute(trig)
929
    endif
930
endfunction
931
932
//===========================================================================
933
// Runs the trigger's actions if the trigger's conditions evaluate to true.
934
//
935
function TriggerExecuteBJ takes trigger trig, boolean checkConditions returns boolean
936
    if checkConditions then
937
        if not (TriggerEvaluate(trig)) then
938
            return false
939
        endif
940
    endif
941
    call TriggerExecute(trig)
942
    return true
943
endfunction
944
945
//===========================================================================
946
// Arranges for a trigger to fire almost immediately, except that the calling
947
// trigger is not interrupted as is the case with a TriggerExecute call.
948
// Since the trigger executes normally, its conditions are still evaluated.
949
//
950
function PostTriggerExecuteBJ takes trigger trig, boolean checkConditions returns boolean
951
    if checkConditions then
952
        if not (TriggerEvaluate(trig)) then
953
            return false
954
        endif
955
    endif
956
    call TriggerRegisterTimerEvent(trig, 0, false)
957
    return true
958
endfunction
959
960
//===========================================================================
961
// Debug - Display the contents of the trigger queue (as either null or "x"
962
// for each entry).
963
function QueuedTriggerCheck takes nothing returns nothing
964
    local string s = "TrigQueue Check "
965
    local integer i
966
967
    set i = 0
968
    loop
969
        exitwhen i >= bj_queuedExecTotal
970
        set s = s + "q[" + I2S(i) + "]="
971
        if (bj_queuedExecTriggers[i] == null) then
972
            set s = s + "null "
973
        else
974
            set s = s + "x "
975
        endif
976
        set i = i + 1
977
    endloop
978
    set s = s + "(" + I2S(bj_queuedExecTotal) + " total)"
979
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,600,s)
980
endfunction
981
982
//===========================================================================
983
// Searches the queue for a given trigger, returning the index of the
984
// trigger within the queue if it is found, or -1 if it is not found.
985
//
986
function QueuedTriggerGetIndex takes trigger trig returns integer
987
    // Determine which, if any, of the queued triggers is being removed.
988
    local integer index     = 0
989
    loop
990
        exitwhen index >= bj_queuedExecTotal
991
        if (bj_queuedExecTriggers[index] == trig) then
992
            return index
993
        endif
994
        set index = index + 1
995
    endloop
996
    return -1
997
endfunction
998
999
//===========================================================================
1000
// Removes a trigger from the trigger queue, shifting other triggers down
1001
// to fill the unused space.  If the currently running trigger is removed
1002
// in this manner, this function does NOT attempt to run the next trigger.
1003
//
1004
function QueuedTriggerRemoveByIndex takes integer trigIndex returns boolean
1005
    local integer index
1006
1007
    // If the to-be-removed index is out of range, fail.
1008
    if (trigIndex >= bj_queuedExecTotal) then
1009
        return false
1010
    endif
1011
1012
    // Shift all queue entries down to fill in the gap.
1013
    set bj_queuedExecTotal = bj_queuedExecTotal - 1
1014
    set index = trigIndex
1015
    loop
1016
        exitwhen index >= bj_queuedExecTotal
1017
        set bj_queuedExecTriggers[index] = bj_queuedExecTriggers[index + 1]
1018
        set bj_queuedExecUseConds[index] = bj_queuedExecUseConds[index + 1]
1019
        set index = index + 1
1020
    endloop
1021
    return true
1022
endfunction
1023
1024
//===========================================================================
1025
// Attempt to execute the first trigger in the queue.  If it fails, remove
1026
// it and execute the next one.  Continue this cycle until a trigger runs,
1027
// or until the queue is empty.
1028
//
1029
function QueuedTriggerAttemptExec takes nothing returns boolean
1030
    loop
1031
        exitwhen bj_queuedExecTotal == 0
1032
1033
        if TriggerExecuteBJ(bj_queuedExecTriggers[0], bj_queuedExecUseConds[0]) then
1034
            // Timeout the queue if it sits at the front of the queue for too long.
1035
            call TimerStart(bj_queuedExecTimeoutTimer, bj_QUEUED_TRIGGER_TIMEOUT, false, null)
1036
            return true
1037
        endif
1038
1039
        call QueuedTriggerRemoveByIndex(0)
1040
    endloop
1041
    return false
1042
endfunction
1043
1044
//===========================================================================
1045
// Queues a trigger to be executed, assuring that such triggers are not
1046
// executed at the same time.
1047
//
1048
function QueuedTriggerAddBJ takes trigger trig, boolean checkConditions returns boolean
1049
    // Make sure our queue isn't full.  If it is, return failure.
1050
    if (bj_queuedExecTotal >= bj_MAX_QUEUED_TRIGGERS) then
1051
        return false
1052
    endif
1053
1054
    // Add the trigger to an array of to-be-executed triggers.
1055
    set bj_queuedExecTriggers[bj_queuedExecTotal] = trig
1056
    set bj_queuedExecUseConds[bj_queuedExecTotal] = checkConditions
1057
    set bj_queuedExecTotal = bj_queuedExecTotal + 1
1058
1059
    // If this is the only trigger in the queue, run it.
1060
    if (bj_queuedExecTotal == 1) then
1061
        call QueuedTriggerAttemptExec()
1062
    endif
1063
    return true
1064
endfunction
1065
1066
//===========================================================================
1067
// Denotes the end of a queued trigger. Be sure to call this only once per
1068
// queued trigger, or risk stepping on the toes of other queued triggers.
1069
//
1070
function QueuedTriggerRemoveBJ takes trigger trig returns nothing
1071
    local integer index
1072
    local integer trigIndex
1073
    local boolean trigExecuted
1074
1075
    // Find the trigger's index.
1076
    set trigIndex = QueuedTriggerGetIndex(trig)
1077
    if (trigIndex == -1) then
1078
        return
1079
    endif
1080
1081
    // Shuffle the other trigger entries down to fill in the gap.
1082
    call QueuedTriggerRemoveByIndex(trigIndex)
1083
1084
    // If we just axed the currently running trigger, run the next one.
1085
    if (trigIndex == 0) then
1086
        call PauseTimer(bj_queuedExecTimeoutTimer)
1087
        call QueuedTriggerAttemptExec()
1088
    endif
1089
endfunction
1090
1091
//===========================================================================
1092
// Denotes the end of a queued trigger. Be sure to call this only once per
1093
// queued trigger, lest you step on the toes of other queued triggers.
1094
//
1095
function QueuedTriggerDoneBJ takes nothing returns nothing
1096
    local integer index
1097
1098
    // Make sure there's something on the queue to remove.
1099
    if (bj_queuedExecTotal <= 0) then
1100
        return
1101
    endif
1102
1103
    // Remove the currently running trigger from the array.
1104
    call QueuedTriggerRemoveByIndex(0)
1105
1106
    // If other triggers are waiting to run, run one of them.
1107
    call PauseTimer(bj_queuedExecTimeoutTimer)
1108
    call QueuedTriggerAttemptExec()
1109
endfunction
1110
1111
//===========================================================================
1112
// Empty the trigger queue.
1113
//
1114
function QueuedTriggerClearBJ takes nothing returns nothing
1115
    call PauseTimer(bj_queuedExecTimeoutTimer)
1116
    set bj_queuedExecTotal = 0
1117
endfunction
1118
1119
//===========================================================================
1120
// Remove all but the currently executing trigger from the trigger queue.
1121
//
1122
function QueuedTriggerClearInactiveBJ takes nothing returns nothing
1123
    set bj_queuedExecTotal = IMinBJ(bj_queuedExecTotal, 1)
1124
endfunction
1125
1126
//===========================================================================
1127
function QueuedTriggerCountBJ takes nothing returns integer
1128
    return bj_queuedExecTotal
1129
endfunction
1130
1131
//===========================================================================
1132
function IsTriggerQueueEmptyBJ takes nothing returns boolean
1133
    return bj_queuedExecTotal <= 0
1134
endfunction
1135
1136
//===========================================================================
1137
function IsTriggerQueuedBJ takes trigger trig returns boolean
1138
    return QueuedTriggerGetIndex(trig) != -1
1139
endfunction
1140
1141
//===========================================================================
1142
function GetForLoopIndexA takes nothing returns integer
1143
    return bj_forLoopAIndex
1144
endfunction
1145
1146
//===========================================================================
1147
function SetForLoopIndexA takes integer newIndex returns nothing
1148
    set bj_forLoopAIndex = newIndex
1149
endfunction
1150
1151
//===========================================================================
1152
function GetForLoopIndexB takes nothing returns integer
1153
    return bj_forLoopBIndex
1154
endfunction
1155
1156
//===========================================================================
1157
function SetForLoopIndexB takes integer newIndex returns nothing
1158
    set bj_forLoopBIndex = newIndex
1159
endfunction
1160
1161
//===========================================================================
1162
// We can't do game-time waits, so this simulates one by starting a timer
1163
// and polling until the timer expires.
1164
function PolledWait takes real duration returns nothing
1165
    local timer t
1166
    local real  timeRemaining
1167
1168
    if (duration > 0) then
1169
        set t = CreateTimer()
1170
        call TimerStart(t, duration, false, null)
1171
        loop
1172
            set timeRemaining = TimerGetRemaining(t)
1173
            exitwhen timeRemaining <= 0
1174
1175
            // If we have a bit of time left, skip past 10% of the remaining
1176
            // duration instead of checking every interval, to minimize the
1177
            // polling on long waits.
1178
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
1179
                call TriggerSleepAction(0.1 * timeRemaining)
1180
            else
1181
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
1182
            endif
1183
        endloop
1184
        call DestroyTimer(t)
1185
    endif
1186
endfunction
1187
1188
//===========================================================================
1189
function IntegerTertiaryOp takes boolean flag, integer valueA, integer valueB returns integer
1190
    if flag then
1191
        return valueA
1192
    else
1193
        return valueB
1194
    endif
1195
endfunction
1196
1197
1198
//***************************************************************************
1199
//*
1200
//*  General Utility Functions
1201
//*  These functions exist purely to make the trigger dialogs cleaner and
1202
//*  more comprehensible.
1203
//*
1204
//***************************************************************************
1205
1206
//===========================================================================
1207
function DoNothing takes nothing returns nothing
1208
endfunction
1209
1210
//===========================================================================
1211
// This function does nothing.  WorldEdit should should eventually ignore
1212
// CommentString triggers during script generation, but until such a time,
1213
// this function will serve as a stub.
1214
//
1215
function CommentString takes string commentString returns nothing
1216
endfunction
1217
1218
//===========================================================================
1219
// This function returns the input string, converting it from the localized text, if necessary
1220
//
1221
function StringIdentity takes string theString returns string
1222
    return GetLocalizedString(theString)
1223
endfunction
1224
1225
//===========================================================================
1226
function GetBooleanAnd takes boolean valueA, boolean valueB returns boolean
1227
    return valueA and valueB
1228
endfunction
1229
1230
//===========================================================================
1231
function GetBooleanOr takes boolean valueA, boolean valueB returns boolean
1232
    return valueA or valueB
1233
endfunction
1234
1235
//===========================================================================
1236
// Converts a percentage (real, 0..100) into a scaled integer (0..max),
1237
// clipping the result to 0..max in case the input is invalid.
1238
//
1239
function PercentToInt takes real percentage, integer max returns integer
1240
    local real realpercent = percentage * I2R(max) * 0.01
1241
    local integer result = MathRound(realpercent)
1242
1243
    if (result < 0) then
1244
        set result = 0
1245
    elseif (result > max) then
1246
        set result = max
1247
    endif
1248
1249
    return result
1250
endfunction
1251
1252
//===========================================================================
1253
function PercentTo255 takes real percentage returns integer
1254
    return PercentToInt(percentage, 255)
1255
endfunction
1256
1257
//===========================================================================
1258
function GetTimeOfDay takes nothing returns real
1259
    return GetFloatGameState(GAME_STATE_TIME_OF_DAY)
1260
endfunction
1261
1262
//===========================================================================
1263
function SetTimeOfDay takes real whatTime returns nothing
1264
    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, whatTime)
1265
endfunction
1266
1267
//===========================================================================
1268
function SetTimeOfDayScalePercentBJ takes real scalePercent returns nothing
1269
    call SetTimeOfDayScale(scalePercent * 0.01)
1270
endfunction
1271
1272
//===========================================================================
1273
function GetTimeOfDayScalePercentBJ takes nothing returns real
1274
    return GetTimeOfDayScale() * 100
1275
endfunction
1276
1277
//===========================================================================
1278
function PlaySound takes string soundName returns nothing
1279
    local sound soundHandle = CreateSound(soundName, false, false, true, 12700, 12700, "")
1280
    call StartSound(soundHandle)
1281
    call KillSoundWhenDone(soundHandle)
1282
endfunction
1283
1284
//===========================================================================
1285
function CompareLocationsBJ takes location A, location B returns boolean
1286
    return GetLocationX(A) == GetLocationX(B) and GetLocationY(A) == GetLocationY(B)
1287
endfunction
1288
1289
//===========================================================================
1290
function CompareRectsBJ takes rect A, rect B returns boolean
1291
    return GetRectMinX(A) == GetRectMinX(B) and GetRectMinY(A) == GetRectMinY(B) and GetRectMaxX(A) == GetRectMaxX(B) and GetRectMaxY(A) == GetRectMaxY(B)
1292
endfunction
1293
1294
//===========================================================================
1295
// Returns a square rect that exactly encompasses the specified circle.
1296
//
1297
function GetRectFromCircleBJ takes location center, real radius returns rect
1298
    local real centerX = GetLocationX(center)
1299
    local real centerY = GetLocationY(center)
1300
    return Rect(centerX - radius, centerY - radius, centerX + radius, centerY + radius)
1301
endfunction
1302
1303
1304
1305
//***************************************************************************
1306
//*
1307
//*  Camera Utility Functions
1308
//*
1309
//***************************************************************************
1310
1311
//===========================================================================
1312
function GetCurrentCameraSetup takes nothing returns camerasetup
1313
    local camerasetup theCam = CreateCameraSetup()
1314
    local real duration = 0
1315
    call CameraSetupSetField(theCam, CAMERA_FIELD_TARGET_DISTANCE, GetCameraField(CAMERA_FIELD_TARGET_DISTANCE), duration)
1316
    call CameraSetupSetField(theCam, CAMERA_FIELD_FARZ,            GetCameraField(CAMERA_FIELD_FARZ),            duration)
1317
    call CameraSetupSetField(theCam, CAMERA_FIELD_ZOFFSET,         GetCameraField(CAMERA_FIELD_ZOFFSET),         duration)
1318
    call CameraSetupSetField(theCam, CAMERA_FIELD_ANGLE_OF_ATTACK, bj_RADTODEG * GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK), duration)
1319
    call CameraSetupSetField(theCam, CAMERA_FIELD_FIELD_OF_VIEW,   bj_RADTODEG * GetCameraField(CAMERA_FIELD_FIELD_OF_VIEW),   duration)
1320
    call CameraSetupSetField(theCam, CAMERA_FIELD_ROLL,            bj_RADTODEG * GetCameraField(CAMERA_FIELD_ROLL),            duration)
1321
    call CameraSetupSetField(theCam, CAMERA_FIELD_ROTATION,        bj_RADTODEG * GetCameraField(CAMERA_FIELD_ROTATION),        duration)
1322
    call CameraSetupSetField(theCam, CAMERA_FIELD_LOCAL_PITCH,     bj_RADTODEG * GetCameraField(CAMERA_FIELD_LOCAL_PITCH),     duration)
1323
    call CameraSetupSetField(theCam, CAMERA_FIELD_LOCAL_YAW,       bj_RADTODEG * GetCameraField(CAMERA_FIELD_LOCAL_YAW),       duration)
1324
    call CameraSetupSetField(theCam, CAMERA_FIELD_LOCAL_ROLL,      bj_RADTODEG * GetCameraField(CAMERA_FIELD_LOCAL_ROLL),      duration)
1325
    call CameraSetupSetDestPosition(theCam, GetCameraTargetPositionX(), GetCameraTargetPositionY(), duration)
1326
    return theCam
1327
endfunction
1328
1329
//===========================================================================
1330
function CameraSetupApplyForPlayer takes boolean doPan, camerasetup whichSetup, player whichPlayer, real duration returns nothing
1331
    if (GetLocalPlayer() == whichPlayer) then
1332
        // Use only local code (no net traffic) within this block to avoid desyncs.
1333
        call CameraSetupApplyForceDuration(whichSetup, doPan, duration)
1334
    endif
1335
endfunction
1336
1337
//===========================================================================
1338
function CameraSetupApplyForPlayerSmooth takes boolean doPan, camerasetup whichSetup, player whichPlayer, real forcedDuration, real easeInDuration, real easeOutDuration, real smoothFactor returns nothing
1339
    if (GetLocalPlayer() == whichPlayer) then
1340
        // Use only local code (no net traffic) within this block to avoid desyncs.
1341
        call BlzCameraSetupApplyForceDurationSmooth(whichSetup, doPan, forcedDuration, easeInDuration, easeOutDuration, smoothFactor)
1342
    endif
1343
endfunction
1344
1345
//===========================================================================
1346
function CameraSetupGetFieldSwap takes camerafield whichField, camerasetup whichSetup returns real
1347
    return CameraSetupGetField(whichSetup, whichField)
1348
endfunction
1349
1350
//===========================================================================
1351
function SetCameraFieldForPlayer takes player whichPlayer, camerafield whichField, real value, real duration returns nothing
1352
    if (GetLocalPlayer() == whichPlayer) then
1353
        // Use only local code (no net traffic) within this block to avoid desyncs.
1354
        call SetCameraField(whichField, value, duration)
1355
    endif
1356
endfunction
1357
1358
//===========================================================================
1359
function SetCameraTargetControllerNoZForPlayer takes player whichPlayer, unit whichUnit, real xoffset, real yoffset, boolean inheritOrientation returns nothing
1360
    if (GetLocalPlayer() == whichPlayer) then
1361
        // Use only local code (no net traffic) within this block to avoid desyncs.
1362
        call SetCameraTargetController(whichUnit, xoffset, yoffset, inheritOrientation)
1363
    endif
1364
endfunction
1365
1366
//===========================================================================
1367
function SetCameraPositionForPlayer takes player whichPlayer, real x, real y returns nothing
1368
    if (GetLocalPlayer() == whichPlayer) then
1369
        // Use only local code (no net traffic) within this block to avoid desyncs.
1370
        call SetCameraPosition(x, y)
1371
    endif
1372
endfunction
1373
1374
//===========================================================================
1375
function SetCameraPositionLocForPlayer takes player whichPlayer, location loc returns nothing
1376
    if (GetLocalPlayer() == whichPlayer) then
1377
        // Use only local code (no net traffic) within this block to avoid desyncs.
1378
        call SetCameraPosition(GetLocationX(loc), GetLocationY(loc))
1379
    endif
1380
endfunction
1381
1382
//===========================================================================
1383
function RotateCameraAroundLocBJ takes real degrees, location loc, player whichPlayer, real duration returns nothing
1384
    if (GetLocalPlayer() == whichPlayer) then
1385
        // Use only local code (no net traffic) within this block to avoid desyncs.
1386
        call SetCameraRotateMode(GetLocationX(loc), GetLocationY(loc), bj_DEGTORAD * degrees, duration)
1387
    endif
1388
endfunction
1389
1390
//===========================================================================
1391
function PanCameraToForPlayer takes player whichPlayer, real x, real y returns nothing
1392
    if (GetLocalPlayer() == whichPlayer) then
1393
        // Use only local code (no net traffic) within this block to avoid desyncs.
1394
        call PanCameraTo(x, y)
1395
    endif
1396
endfunction
1397
1398
//===========================================================================
1399
function PanCameraToLocForPlayer takes player whichPlayer, location loc returns nothing
1400
    if (GetLocalPlayer() == whichPlayer) then
1401
        // Use only local code (no net traffic) within this block to avoid desyncs.
1402
        call PanCameraTo(GetLocationX(loc), GetLocationY(loc))
1403
    endif
1404
endfunction
1405
1406
//===========================================================================
1407
function PanCameraToTimedForPlayer takes player whichPlayer, real x, real y, real duration returns nothing
1408
    if (GetLocalPlayer() == whichPlayer) then
1409
        // Use only local code (no net traffic) within this block to avoid desyncs.
1410
        call PanCameraToTimed(x, y, duration)
1411
    endif
1412
endfunction
1413
1414
//===========================================================================
1415
function PanCameraToTimedLocForPlayer takes player whichPlayer, location loc, real duration returns nothing
1416
    if (GetLocalPlayer() == whichPlayer) then
1417
        // Use only local code (no net traffic) within this block to avoid desyncs.
1418
        call PanCameraToTimed(GetLocationX(loc), GetLocationY(loc), duration)
1419
    endif
1420
endfunction
1421
1422
//===========================================================================
1423
function PanCameraToTimedLocWithZForPlayer takes player whichPlayer, location loc, real zOffset, real duration returns nothing
1424
    if (GetLocalPlayer() == whichPlayer) then
1425
        // Use only local code (no net traffic) within this block to avoid desyncs.
1426
        call PanCameraToTimedWithZ(GetLocationX(loc), GetLocationY(loc), zOffset, duration)
1427
    endif
1428
endfunction
1429
1430
//===========================================================================
1431
function SmartCameraPanBJ takes player whichPlayer, location loc, real duration returns nothing
1432
    local real dist
1433
    local location cameraLoc = GetCameraTargetPositionLoc()
1434
    if (GetLocalPlayer() == whichPlayer) then
1435
        // Use only local code (no net traffic) within this block to avoid desyncs.
1436
1437
        set dist = DistanceBetweenPoints(loc, cameraLoc)
1438
        if (dist >= bj_SMARTPAN_TRESHOLD_SNAP) then
1439
            // If the user is too far away, snap the camera.
1440
            call PanCameraToTimed(GetLocationX(loc), GetLocationY(loc), 0)
1441
        elseif (dist >= bj_SMARTPAN_TRESHOLD_PAN) then
1442
            // If the user is moderately close, pan the camera.
1443
            call PanCameraToTimed(GetLocationX(loc), GetLocationY(loc), duration)
1444
        else
1445
            // User is close enough, so don't touch the camera.
1446
        endif
1447
    endif
1448
    call RemoveLocation(cameraLoc)
1449
endfunction
1450
1451
//===========================================================================
1452
function SetCinematicCameraForPlayer takes player whichPlayer, string cameraModelFile returns nothing
1453
    if (GetLocalPlayer() == whichPlayer) then
1454
        // Use only local code (no net traffic) within this block to avoid desyncs.
1455
        call SetCinematicCamera(cameraModelFile)
1456
    endif
1457
endfunction
1458
1459
//===========================================================================
1460
function ResetToGameCameraForPlayer takes player whichPlayer, real duration returns nothing
1461
    if (GetLocalPlayer() == whichPlayer) then
1462
        // Use only local code (no net traffic) within this block to avoid desyncs.
1463
        call ResetToGameCamera(duration)
1464
    endif
1465
endfunction
1466
1467
//===========================================================================
1468
function CameraSetSourceNoiseForPlayer takes player whichPlayer, real magnitude, real velocity returns nothing
1469
    if (GetLocalPlayer() == whichPlayer) then
1470
        // Use only local code (no net traffic) within this block to avoid desyncs.
1471
        call CameraSetSourceNoise(magnitude, velocity)
1472
    endif
1473
endfunction
1474
1475
//===========================================================================
1476
function CameraSetTargetNoiseForPlayer takes player whichPlayer, real magnitude, real velocity returns nothing
1477
    if (GetLocalPlayer() == whichPlayer) then
1478
        // Use only local code (no net traffic) within this block to avoid desyncs.
1479
        call CameraSetTargetNoise(magnitude, velocity)
1480
    endif
1481
endfunction
1482
1483
//===========================================================================
1484
function CameraSetEQNoiseForPlayer takes player whichPlayer, real magnitude returns nothing
1485
    local real richter = magnitude
1486
    if (richter > 5.0) then
1487
        set richter = 5.0
1488
    endif
1489
    if (richter < 2.0) then
1490
        set richter = 2.0
1491
    endif
1492
    if (GetLocalPlayer() == whichPlayer) then
1493
        // Use only local code (no net traffic) within this block to avoid desyncs.
1494
        call CameraSetTargetNoiseEx(magnitude*2.0, magnitude*Pow(10,richter),true)
1495
        call CameraSetSourceNoiseEx(magnitude*2.0, magnitude*Pow(10,richter),true)
1496
    endif
1497
endfunction
1498
1499
//===========================================================================
1500
function CameraClearNoiseForPlayer takes player whichPlayer returns nothing
1501
    if (GetLocalPlayer() == whichPlayer) then
1502
        // Use only local code (no net traffic) within this block to avoid desyncs.
1503
        call CameraSetSourceNoise(0, 0)
1504
        call CameraSetTargetNoise(0, 0)
1505
    endif
1506
endfunction
1507
1508
//===========================================================================
1509
// Query the current camera bounds.
1510
//
1511
function GetCurrentCameraBoundsMapRectBJ takes nothing returns rect
1512
    return Rect(GetCameraBoundMinX(), GetCameraBoundMinY(), GetCameraBoundMaxX(), GetCameraBoundMaxY())
1513
endfunction
1514
1515
//===========================================================================
1516
// Query the initial camera bounds, as defined at map init.
1517
//
1518
function GetCameraBoundsMapRect takes nothing returns rect
1519
    return bj_mapInitialCameraBounds
1520
endfunction
1521
1522
//===========================================================================
1523
// Query the playable map area, as defined at map init.
1524
//
1525
function GetPlayableMapRect takes nothing returns rect
1526
    return bj_mapInitialPlayableArea
1527
endfunction
1528
1529
//===========================================================================
1530
// Query the entire map area, as defined at map init.
1531
//
1532
function GetEntireMapRect takes nothing returns rect
1533
    return GetWorldBounds()
1534
endfunction
1535
1536
//===========================================================================
1537
function SetCameraBoundsToRect takes rect r returns nothing
1538
    local real minX = GetRectMinX(r)
1539
    local real minY = GetRectMinY(r)
1540
    local real maxX = GetRectMaxX(r)
1541
    local real maxY = GetRectMaxY(r)
1542
    call SetCameraBounds(minX, minY, minX, maxY, maxX, maxY, maxX, minY)
1543
endfunction
1544
1545
//===========================================================================
1546
function SetCameraBoundsToRectForPlayerBJ takes player whichPlayer, rect r returns nothing
1547
    if (GetLocalPlayer() == whichPlayer) then
1548
        // Use only local code (no net traffic) within this block to avoid desyncs.
1549
        call SetCameraBoundsToRect(r)
1550
    endif
1551
endfunction
1552
1553
//===========================================================================
1554
function AdjustCameraBoundsBJ takes integer adjustMethod, real dxWest, real dxEast, real dyNorth, real dySouth returns nothing
1555
    local real minX = 0
1556
    local real minY = 0
1557
    local real maxX = 0
1558
    local real maxY = 0
1559
    local real scale = 0
1560
1561
    if (adjustMethod == bj_CAMERABOUNDS_ADJUST_ADD) then
1562
        set scale = 1
1563
    elseif (adjustMethod == bj_CAMERABOUNDS_ADJUST_SUB) then
1564
        set scale = -1
1565
    else
1566
        // Unrecognized adjustment method - ignore the request.
1567
        return
1568
    endif
1569
1570
    // Adjust the actual camera values
1571
    set minX = GetCameraBoundMinX() - scale * dxWest
1572
    set maxX = GetCameraBoundMaxX() + scale * dxEast
1573
    set minY = GetCameraBoundMinY() - scale * dySouth
1574
    set maxY = GetCameraBoundMaxY() + scale * dyNorth
1575
1576
    // Make sure the camera bounds are still valid.
1577
    if (maxX < minX) then
1578
        set minX = (minX + maxX) * 0.5
1579
        set maxX = minX
1580
    endif
1581
    if (maxY < minY) then
1582
        set minY = (minY + maxY) * 0.5
1583
        set maxY = minY
1584
    endif
1585
1586
    // Apply the new camera values.
1587
    call SetCameraBounds(minX, minY, minX, maxY, maxX, maxY, maxX, minY)
1588
endfunction
1589
1590
//===========================================================================
1591
function AdjustCameraBoundsForPlayerBJ takes integer adjustMethod, player whichPlayer, real dxWest, real dxEast, real dyNorth, real dySouth returns nothing
1592
    if (GetLocalPlayer() == whichPlayer) then
1593
        // Use only local code (no net traffic) within this block to avoid desyncs.
1594
        call AdjustCameraBoundsBJ(adjustMethod, dxWest, dxEast, dyNorth, dySouth)
1595
    endif
1596
endfunction
1597
1598
//===========================================================================
1599
function SetCameraQuickPositionForPlayer takes player whichPlayer, real x, real y returns nothing
1600
    if (GetLocalPlayer() == whichPlayer) then
1601
        // Use only local code (no net traffic) within this block to avoid desyncs.
1602
        call SetCameraQuickPosition(x, y)
1603
    endif
1604
endfunction
1605
1606
//===========================================================================
1607
function SetCameraQuickPositionLocForPlayer takes player whichPlayer, location loc returns nothing
1608
    if (GetLocalPlayer() == whichPlayer) then
1609
        // Use only local code (no net traffic) within this block to avoid desyncs.
1610
        call SetCameraQuickPosition(GetLocationX(loc), GetLocationY(loc))
1611
    endif
1612
endfunction
1613
1614
//===========================================================================
1615
function SetCameraQuickPositionLoc takes location loc returns nothing
1616
    call SetCameraQuickPosition(GetLocationX(loc), GetLocationY(loc))
1617
endfunction
1618
1619
//===========================================================================
1620
function StopCameraForPlayerBJ takes player whichPlayer returns nothing
1621
    if (GetLocalPlayer() == whichPlayer) then
1622
        // Use only local code (no net traffic) within this block to avoid desyncs.
1623
        call StopCamera()
1624
    endif
1625
endfunction
1626
1627
//===========================================================================
1628
function SetCameraOrientControllerForPlayerBJ takes player whichPlayer, unit whichUnit, real xoffset, real yoffset returns nothing
1629
    if (GetLocalPlayer() == whichPlayer) then
1630
        // Use only local code (no net traffic) within this block to avoid desyncs.
1631
        call SetCameraOrientController(whichUnit, xoffset, yoffset)
1632
    endif
1633
endfunction
1634
1635
//===========================================================================
1636
function CameraSetSmoothingFactorBJ takes real factor returns nothing
1637
    call CameraSetSmoothingFactor(factor)
1638
endfunction
1639
1640
//===========================================================================
1641
function CameraResetSmoothingFactorBJ takes nothing returns nothing
1642
    call CameraSetSmoothingFactor(0)
1643
endfunction
1644
1645
1646
1647
//***************************************************************************
1648
//*
1649
//*  Text Utility Functions
1650
//*
1651
//***************************************************************************
1652
1653
//===========================================================================
1654
function DisplayTextToForce takes force toForce, string message returns nothing
1655
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
1656
        // Use only local code (no net traffic) within this block to avoid desyncs.
1657
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, message)
1658
    endif
1659
endfunction
1660
1661
//===========================================================================
1662
function DisplayTimedTextToForce takes force toForce, real duration, string message returns nothing
1663
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
1664
        // Use only local code (no net traffic) within this block to avoid desyncs.
1665
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, duration, message)
1666
    endif
1667
endfunction
1668
1669
//===========================================================================
1670
function ClearTextMessagesBJ takes force toForce returns nothing
1671
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
1672
        // Use only local code (no net traffic) within this block to avoid desyncs.
1673
        call ClearTextMessages()
1674
    endif
1675
endfunction
1676
1677
//===========================================================================
1678
// The parameters for the API Substring function are unintuitive, so this
1679
// merely performs a translation for the starting index.
1680
//
1681
function SubStringBJ takes string source, integer start, integer end returns string
1682
    return SubString(source, start-1, end)
1683
endfunction  
1684
  
1685
function GetHandleIdBJ takes handle h returns integer
1686
    return GetHandleId(h)
1687
endfunction
1688
1689
function StringHashBJ takes string s returns integer
1690
    return StringHash(s)
1691
endfunction
1692
1693
1694
1695
//***************************************************************************
1696
//*
1697
//*  Event Registration Utility Functions
1698
//*
1699
//***************************************************************************
1700
1701
//===========================================================================
1702
function TriggerRegisterTimerEventPeriodic takes trigger trig, real timeout returns event
1703
    return TriggerRegisterTimerEvent(trig, timeout, true)
1704
endfunction
1705
1706
//===========================================================================
1707
function TriggerRegisterTimerEventSingle takes trigger trig, real timeout returns event
1708
    return TriggerRegisterTimerEvent(trig, timeout, false)
1709
endfunction
1710
1711
//===========================================================================
1712
function TriggerRegisterTimerExpireEventBJ takes trigger trig, timer t returns event
1713
    return TriggerRegisterTimerExpireEvent(trig, t)
1714
endfunction
1715
1716
//===========================================================================
1717
function TriggerRegisterPlayerUnitEventSimple takes trigger trig, player whichPlayer, playerunitevent whichEvent returns event
1718
    return TriggerRegisterPlayerUnitEvent(trig, whichPlayer, whichEvent, null)
1719
endfunction
1720
1721
//===========================================================================
1722
function TriggerRegisterAnyUnitEventBJ takes trigger trig, playerunitevent whichEvent returns nothing
1723
    local integer index
1724
1725
    set index = 0
1726
    loop
1727
        call TriggerRegisterPlayerUnitEvent(trig, Player(index), whichEvent, null)
1728
1729
        set index = index + 1
1730
        exitwhen index == bj_MAX_PLAYER_SLOTS
1731
    endloop
1732
endfunction
1733
1734
//===========================================================================
1735
function TriggerRegisterPlayerSelectionEventBJ takes trigger trig, player whichPlayer, boolean selected returns event
1736
    if selected then
1737
        return TriggerRegisterPlayerUnitEvent(trig, whichPlayer, EVENT_PLAYER_UNIT_SELECTED, null)
1738
    else
1739
        return TriggerRegisterPlayerUnitEvent(trig, whichPlayer, EVENT_PLAYER_UNIT_DESELECTED, null)
1740
    endif
1741
endfunction
1742
1743
//===========================================================================
1744
function TriggerRegisterPlayerKeyEventBJ takes trigger trig, player whichPlayer, integer keType, integer keKey returns event
1745
    if (keType == bj_KEYEVENTTYPE_DEPRESS) then
1746
        // Depress event - find out what key
1747
        if (keKey == bj_KEYEVENTKEY_LEFT) then
1748
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_LEFT_DOWN)
1749
        elseif (keKey == bj_KEYEVENTKEY_RIGHT) then
1750
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_RIGHT_DOWN)
1751
        elseif (keKey == bj_KEYEVENTKEY_DOWN) then
1752
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_DOWN_DOWN)
1753
        elseif (keKey == bj_KEYEVENTKEY_UP) then
1754
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_UP_DOWN)
1755
        else
1756
            // Unrecognized key - ignore the request and return failure.
1757
            return null
1758
        endif
1759
    elseif (keType == bj_KEYEVENTTYPE_RELEASE) then
1760
        // Release event - find out what key
1761
        if (keKey == bj_KEYEVENTKEY_LEFT) then
1762
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_LEFT_UP)
1763
        elseif (keKey == bj_KEYEVENTKEY_RIGHT) then
1764
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_RIGHT_UP)
1765
        elseif (keKey == bj_KEYEVENTKEY_DOWN) then
1766
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_DOWN_UP)
1767
        elseif (keKey == bj_KEYEVENTKEY_UP) then
1768
            return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ARROW_UP_UP)
1769
        else
1770
            // Unrecognized key - ignore the request and return failure.
1771
            return null
1772
        endif
1773
    else
1774
        // Unrecognized type - ignore the request and return failure.
1775
        return null
1776
    endif
1777
endfunction
1778
1779
//===========================================================================
1780
function TriggerRegisterPlayerMouseEventBJ takes trigger trig, player whichPlayer, integer meType returns event
1781
     if (meType == bj_MOUSEEVENTTYPE_DOWN) then
1782
        // Mouse down event
1783
        return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_MOUSE_DOWN)
1784
    elseif (meType == bj_MOUSEEVENTTYPE_UP) then
1785
        // Mouse up event
1786
        return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_MOUSE_UP)
1787
    elseif (meType == bj_MOUSEEVENTTYPE_MOVE) then
1788
        // Mouse move event
1789
        return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_MOUSE_MOVE)
1790
    else
1791
        // Unrecognized type - ignore the request and return failure.
1792
         return null
1793
    endif
1794
endfunction
1795
1796
//===========================================================================
1797
function TriggerRegisterPlayerEventVictory takes trigger trig, player whichPlayer returns event
1798
    return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_VICTORY)
1799
endfunction
1800
1801
//===========================================================================
1802
function TriggerRegisterPlayerEventDefeat takes trigger trig, player whichPlayer returns event
1803
    return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_DEFEAT)
1804
endfunction
1805
1806
//===========================================================================
1807
function TriggerRegisterPlayerEventLeave takes trigger trig, player whichPlayer returns event
1808
    return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_LEAVE)
1809
endfunction
1810
1811
//===========================================================================
1812
function TriggerRegisterPlayerEventAllianceChanged takes trigger trig, player whichPlayer returns event
1813
    return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_ALLIANCE_CHANGED)
1814
endfunction
1815
1816
//===========================================================================
1817
function TriggerRegisterPlayerEventEndCinematic takes trigger trig, player whichPlayer returns event
1818
    return TriggerRegisterPlayerEvent(trig, whichPlayer, EVENT_PLAYER_END_CINEMATIC)
1819
endfunction
1820
1821
//===========================================================================
1822
function TriggerRegisterGameStateEventTimeOfDay takes trigger trig, limitop opcode, real limitval returns event
1823
    return TriggerRegisterGameStateEvent(trig, GAME_STATE_TIME_OF_DAY, opcode, limitval)
1824
endfunction
1825
1826
//===========================================================================
1827
function TriggerRegisterEnterRegionSimple takes trigger trig, region whichRegion returns event
1828
    return TriggerRegisterEnterRegion(trig, whichRegion, null)
1829
endfunction
1830
1831
//===========================================================================
1832
function TriggerRegisterLeaveRegionSimple takes trigger trig, region whichRegion returns event
1833
    return TriggerRegisterLeaveRegion(trig, whichRegion, null)
1834
endfunction
1835
1836
//===========================================================================
1837
function TriggerRegisterEnterRectSimple takes trigger trig, rect r returns event
1838
    local region rectRegion = CreateRegion()
1839
    call RegionAddRect(rectRegion, r)
1840
    return TriggerRegisterEnterRegion(trig, rectRegion, null)
1841
endfunction
1842
1843
//===========================================================================
1844
function TriggerRegisterLeaveRectSimple takes trigger trig, rect r returns event
1845
    local region rectRegion = CreateRegion()
1846
    call RegionAddRect(rectRegion, r)
1847
    return TriggerRegisterLeaveRegion(trig, rectRegion, null)
1848
endfunction
1849
1850
//===========================================================================
1851
function TriggerRegisterDistanceBetweenUnits takes trigger trig, unit whichUnit, boolexpr condition, real range returns event
1852
    return TriggerRegisterUnitInRange(trig, whichUnit, range, condition)
1853
endfunction
1854
1855
//===========================================================================
1856
function TriggerRegisterUnitInRangeSimple takes trigger trig, real range, unit whichUnit returns event
1857
    return TriggerRegisterUnitInRange(trig, whichUnit, range, null)
1858
endfunction
1859
1860
//===========================================================================
1861
function TriggerRegisterUnitLifeEvent takes trigger trig, unit whichUnit, limitop opcode, real limitval returns event
1862
    return TriggerRegisterUnitStateEvent(trig, whichUnit, UNIT_STATE_LIFE, opcode, limitval)
1863
endfunction
1864
1865
//===========================================================================
1866
function TriggerRegisterUnitManaEvent takes trigger trig, unit whichUnit, limitop opcode, real limitval returns event
1867
    return TriggerRegisterUnitStateEvent(trig, whichUnit, UNIT_STATE_MANA, opcode, limitval)
1868
endfunction
1869
1870
//===========================================================================
1871
function TriggerRegisterDialogEventBJ takes trigger trig, dialog whichDialog returns event
1872
    return TriggerRegisterDialogEvent(trig, whichDialog)
1873
endfunction
1874
1875
//===========================================================================
1876
function TriggerRegisterShowSkillEventBJ takes trigger trig returns event
1877
    return TriggerRegisterGameEvent(trig, EVENT_GAME_SHOW_SKILL)
1878
endfunction
1879
1880
//===========================================================================
1881
function TriggerRegisterBuildSubmenuEventBJ takes trigger trig returns event
1882
    return TriggerRegisterGameEvent(trig, EVENT_GAME_BUILD_SUBMENU)
1883
endfunction
1884
1885
//===========================================================================
1886
function TriggerRegisterBuildCommandEventBJ takes trigger trig, integer unitId returns event
1887
    call TriggerRegisterCommandEvent(trig, 'ANbu', UnitId2String(unitId))
1888
    call TriggerRegisterCommandEvent(trig, 'AHbu', UnitId2String(unitId))
1889
    call TriggerRegisterCommandEvent(trig, 'AEbu', UnitId2String(unitId))
1890
    call TriggerRegisterCommandEvent(trig, 'AObu', UnitId2String(unitId))
1891
    call TriggerRegisterCommandEvent(trig, 'AUbu', UnitId2String(unitId))
1892
    return TriggerRegisterCommandEvent(trig, 'AGbu', UnitId2String(unitId))
1893
endfunction
1894
1895
//===========================================================================
1896
function TriggerRegisterTrainCommandEventBJ takes trigger trig, integer unitId returns event
1897
    return TriggerRegisterCommandEvent(trig, 'Aque', UnitId2String(unitId))
1898
endfunction
1899
1900
//===========================================================================
1901
function TriggerRegisterUpgradeCommandEventBJ takes trigger trig, integer techId returns event
1902
    return TriggerRegisterUpgradeCommandEvent(trig, techId)
1903
endfunction
1904
1905
//===========================================================================
1906
function TriggerRegisterCommonCommandEventBJ takes trigger trig, string order returns event
1907
    return TriggerRegisterCommandEvent(trig, 0, order)
1908
endfunction
1909
1910
//===========================================================================
1911
function TriggerRegisterGameLoadedEventBJ takes trigger trig returns event
1912
    return TriggerRegisterGameEvent(trig, EVENT_GAME_LOADED)
1913
endfunction
1914
1915
//===========================================================================
1916
function TriggerRegisterGameSavedEventBJ takes trigger trig returns event
1917
    return TriggerRegisterGameEvent(trig, EVENT_GAME_SAVE)
1918
endfunction
1919
1920
//===========================================================================
1921
function RegisterDestDeathInRegionEnum takes nothing returns nothing
1922
    set bj_destInRegionDiesCount = bj_destInRegionDiesCount + 1
1923
    if (bj_destInRegionDiesCount <= bj_MAX_DEST_IN_REGION_EVENTS) then
1924
        call TriggerRegisterDeathEvent(bj_destInRegionDiesTrig, GetEnumDestructable())
1925
    endif
1926
endfunction
1927
1928
//===========================================================================
1929
function TriggerRegisterDestDeathInRegionEvent takes trigger trig, rect r returns nothing
1930
    set bj_destInRegionDiesTrig = trig
1931
    set bj_destInRegionDiesCount = 0
1932
    call EnumDestructablesInRect(r, null, function RegisterDestDeathInRegionEnum)
1933
endfunction
1934
1935
1936
1937
//***************************************************************************
1938
//*
1939
//*  Environment Utility Functions
1940
//*
1941
//***************************************************************************
1942
1943
//===========================================================================
1944
function AddWeatherEffectSaveLast takes rect where, integer effectID returns weathereffect
1945
    set bj_lastCreatedWeatherEffect = AddWeatherEffect(where, effectID)
1946
    return bj_lastCreatedWeatherEffect
1947
endfunction
1948
1949
//===========================================================================
1950
function GetLastCreatedWeatherEffect takes nothing returns weathereffect
1951
    return bj_lastCreatedWeatherEffect
1952
endfunction
1953
1954
//===========================================================================
1955
function RemoveWeatherEffectBJ takes weathereffect whichWeatherEffect returns nothing
1956
    call RemoveWeatherEffect(whichWeatherEffect)
1957
endfunction
1958
1959
//===========================================================================
1960
function TerrainDeformationCraterBJ takes real duration, boolean permanent, location where, real radius, real depth returns terraindeformation
1961
    set bj_lastCreatedTerrainDeformation = TerrainDeformCrater(GetLocationX(where), GetLocationY(where), radius, depth, R2I(duration * 1000), permanent)
1962
    return bj_lastCreatedTerrainDeformation
1963
endfunction
1964
1965
//===========================================================================
1966
function TerrainDeformationRippleBJ takes real duration, boolean limitNeg, location where, real startRadius, real endRadius, real depth, real wavePeriod, real waveWidth returns terraindeformation
1967
    local real spaceWave
1968
    local real timeWave
1969
    local real radiusRatio
1970
1971
    if (endRadius <= 0 or waveWidth <= 0 or wavePeriod <= 0) then
1972
        return null
1973
    endif
1974
1975
    set timeWave = 2.0 * duration / wavePeriod
1976
    set spaceWave = 2.0 * endRadius / waveWidth
1977
    set radiusRatio = startRadius / endRadius
1978
1979
    set bj_lastCreatedTerrainDeformation = TerrainDeformRipple(GetLocationX(where), GetLocationY(where), endRadius, depth, R2I(duration * 1000), 1, spaceWave, timeWave, radiusRatio, limitNeg)
1980
    return bj_lastCreatedTerrainDeformation
1981
endfunction
1982
1983
//===========================================================================
1984
function TerrainDeformationWaveBJ takes real duration, location source, location target, real radius, real depth, real trailDelay returns terraindeformation
1985
    local real distance
1986
    local real dirX
1987
    local real dirY
1988
    local real speed
1989
1990
    set distance = DistanceBetweenPoints(source, target)
1991
    if (distance == 0 or duration <= 0) then
1992
        return null
1993
    endif
1994
1995
    set dirX = (GetLocationX(target) - GetLocationX(source)) / distance
1996
    set dirY = (GetLocationY(target) - GetLocationY(source)) / distance
1997
    set speed = distance / duration
1998
1999
    set bj_lastCreatedTerrainDeformation = TerrainDeformWave(GetLocationX(source), GetLocationY(source), dirX, dirY, distance, speed, radius, depth, R2I(trailDelay * 1000), 1)
2000
    return bj_lastCreatedTerrainDeformation
2001
endfunction
2002
2003
//===========================================================================
2004
function TerrainDeformationRandomBJ takes real duration, location where, real radius, real minDelta, real maxDelta, real updateInterval returns terraindeformation
2005
    set bj_lastCreatedTerrainDeformation = TerrainDeformRandom(GetLocationX(where), GetLocationY(where), radius, minDelta, maxDelta, R2I(duration * 1000), R2I(updateInterval * 1000))
2006
    return bj_lastCreatedTerrainDeformation
2007
endfunction
2008
2009
//===========================================================================
2010
function TerrainDeformationStopBJ takes terraindeformation deformation, real duration returns nothing
2011
    call TerrainDeformStop(deformation, R2I(duration * 1000))
2012
endfunction
2013
2014
//===========================================================================
2015
function GetLastCreatedTerrainDeformation takes nothing returns terraindeformation
2016
    return bj_lastCreatedTerrainDeformation
2017
endfunction
2018
2019
//===========================================================================
2020
function AddLightningLoc takes string codeName, location where1, location where2 returns lightning
2021
    set bj_lastCreatedLightning = AddLightningEx(codeName, true, GetLocationX(where1), GetLocationY(where1), GetLocationZ(where1), GetLocationX(where2), GetLocationY(where2), GetLocationZ(where2))
2022
    return bj_lastCreatedLightning
2023
endfunction
2024
2025
//===========================================================================
2026
function DestroyLightningBJ takes lightning whichBolt returns boolean
2027
    return DestroyLightning(whichBolt)
2028
endfunction
2029
2030
//===========================================================================
2031
function MoveLightningLoc takes lightning whichBolt, location where1, location where2 returns boolean
2032
    return MoveLightningEx(whichBolt, true, GetLocationX(where1), GetLocationY(where1), GetLocationZ(where1), GetLocationX(where2), GetLocationY(where2), GetLocationZ(where2))
2033
endfunction
2034
2035
//===========================================================================
2036
function GetLightningColorABJ takes lightning whichBolt returns real
2037
    return GetLightningColorA(whichBolt)
2038
endfunction
2039
2040
//===========================================================================
2041
function GetLightningColorRBJ takes lightning whichBolt returns real
2042
    return GetLightningColorR(whichBolt)
2043
endfunction
2044
2045
//===========================================================================
2046
function GetLightningColorGBJ takes lightning whichBolt returns real
2047
    return GetLightningColorG(whichBolt)
2048
endfunction
2049
2050
//===========================================================================
2051
function GetLightningColorBBJ takes lightning whichBolt returns real
2052
    return GetLightningColorB(whichBolt)
2053
endfunction
2054
2055
//===========================================================================
2056
function SetLightningColorBJ takes lightning whichBolt, real r, real g, real b, real a returns boolean
2057
    return SetLightningColor(whichBolt, r, g, b, a)
2058
endfunction
2059
2060
//===========================================================================
2061
function GetLastCreatedLightningBJ takes nothing returns lightning
2062
    return bj_lastCreatedLightning
2063
endfunction
2064
2065
//===========================================================================
2066
function GetAbilityEffectBJ takes integer abilcode, effecttype t, integer index returns string
2067
    return GetAbilityEffectById(abilcode, t, index)
2068
endfunction
2069
2070
//===========================================================================
2071
function GetAbilitySoundBJ takes integer abilcode, soundtype t returns string
2072
    return GetAbilitySoundById(abilcode, t)
2073
endfunction
2074
2075
2076
//===========================================================================
2077
function GetTerrainCliffLevelBJ takes location where returns integer
2078
    return GetTerrainCliffLevel(GetLocationX(where), GetLocationY(where))
2079
endfunction
2080
2081
//===========================================================================
2082
function GetTerrainTypeBJ takes location where returns integer
2083
    return GetTerrainType(GetLocationX(where), GetLocationY(where))
2084
endfunction
2085
2086
//===========================================================================
2087
function GetTerrainVarianceBJ takes location where returns integer
2088
    return GetTerrainVariance(GetLocationX(where), GetLocationY(where))
2089
endfunction
2090
2091
//===========================================================================
2092
function SetTerrainTypeBJ takes location where, integer terrainType, integer variation, integer area, integer shape returns nothing
2093
    call SetTerrainType(GetLocationX(where), GetLocationY(where), terrainType, variation, area, shape)
2094
endfunction
2095
2096
//===========================================================================
2097
function IsTerrainPathableBJ takes location where, pathingtype t returns boolean
2098
    return IsTerrainPathable(GetLocationX(where), GetLocationY(where), t)
2099
endfunction
2100
2101
//===========================================================================
2102
function SetTerrainPathableBJ takes location where, pathingtype t, boolean flag returns nothing
2103
    call SetTerrainPathable(GetLocationX(where), GetLocationY(where), t, flag)
2104
endfunction
2105
2106
//===========================================================================
2107
function SetWaterBaseColorBJ takes real red, real green, real blue, real transparency returns nothing
2108
    call SetWaterBaseColor(PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
2109
endfunction
2110
2111
//===========================================================================
2112
function CreateFogModifierRectSimple takes player whichPlayer, fogstate whichFogState, rect r, boolean afterUnits returns fogmodifier
2113
    set bj_lastCreatedFogModifier = CreateFogModifierRect(whichPlayer, whichFogState, r, true, afterUnits)
2114
    return bj_lastCreatedFogModifier
2115
endfunction
2116
2117
//===========================================================================
2118
function CreateFogModifierRadiusLocSimple takes player whichPlayer, fogstate whichFogState, location center, real radius, boolean afterUnits returns fogmodifier
2119
    set bj_lastCreatedFogModifier = CreateFogModifierRadiusLoc(whichPlayer, whichFogState, center, radius, true, afterUnits)
2120
    return bj_lastCreatedFogModifier
2121
endfunction
2122
2123
//===========================================================================
2124
// Version of CreateFogModifierRect that assumes use of sharedVision and
2125
// gives the option of immediately enabling the modifier, so that triggers
2126
// can default to modifiers that are immediately enabled.
2127
//
2128
function CreateFogModifierRectBJ takes boolean enabled, player whichPlayer, fogstate whichFogState, rect r returns fogmodifier
2129
    set bj_lastCreatedFogModifier = CreateFogModifierRect(whichPlayer, whichFogState, r, true, false)
2130
    if enabled then
2131
        call FogModifierStart(bj_lastCreatedFogModifier)
2132
    endif
2133
    return bj_lastCreatedFogModifier
2134
endfunction
2135
2136
//===========================================================================
2137
// Version of CreateFogModifierRadius that assumes use of sharedVision and
2138
// gives the option of immediately enabling the modifier, so that triggers
2139
// can default to modifiers that are immediately enabled.
2140
//
2141
function CreateFogModifierRadiusLocBJ takes boolean enabled, player whichPlayer, fogstate whichFogState, location center, real radius returns fogmodifier
2142
    set bj_lastCreatedFogModifier = CreateFogModifierRadiusLoc(whichPlayer, whichFogState, center, radius, true, false)
2143
    if enabled then
2144
        call FogModifierStart(bj_lastCreatedFogModifier)
2145
    endif
2146
    return bj_lastCreatedFogModifier
2147
endfunction
2148
2149
//===========================================================================
2150
function GetLastCreatedFogModifier takes nothing returns fogmodifier
2151
    return bj_lastCreatedFogModifier
2152
endfunction
2153
2154
//===========================================================================
2155
function FogEnableOn takes nothing returns nothing
2156
    call FogEnable(true)
2157
endfunction
2158
2159
//===========================================================================
2160
function FogEnableOff takes nothing returns nothing
2161
    call FogEnable(false)
2162
endfunction
2163
2164
//===========================================================================
2165
function FogMaskEnableOn takes nothing returns nothing
2166
    call FogMaskEnable(true)
2167
endfunction
2168
2169
//===========================================================================
2170
function FogMaskEnableOff takes nothing returns nothing
2171
    call FogMaskEnable(false)
2172
endfunction
2173
2174
//===========================================================================
2175
function UseTimeOfDayBJ takes boolean flag returns nothing
2176
    call SuspendTimeOfDay(not flag)
2177
endfunction
2178
2179
//===========================================================================
2180
function SetTerrainFogExBJ takes integer style, real zstart, real zend, real density, real red, real green, real blue returns nothing
2181
    call SetTerrainFogEx(style, zstart, zend, density, red * 0.01, green * 0.01, blue * 0.01)
2182
endfunction
2183
2184
//===========================================================================
2185
function ResetTerrainFogBJ takes nothing returns nothing
2186
    call ResetTerrainFog()
2187
endfunction
2188
2189
//===========================================================================
2190
function SetDoodadAnimationBJ takes string animName, integer doodadID, real radius, location center returns nothing
2191
    call SetDoodadAnimation(GetLocationX(center), GetLocationY(center), radius, doodadID, false, animName, false)
2192
endfunction
2193
2194
//===========================================================================
2195
function SetDoodadAnimationRectBJ takes string animName, integer doodadID, rect r returns nothing
2196
    call SetDoodadAnimationRect(r, doodadID, animName, false)
2197
endfunction
2198
2199
//===========================================================================
2200
function AddUnitAnimationPropertiesBJ takes boolean add, string animProperties, unit whichUnit returns nothing
2201
    call AddUnitAnimationProperties(whichUnit, animProperties, add)
2202
endfunction
2203
2204
2205
//============================================================================
2206
function CreateImageBJ takes string file, real size, location where, real zOffset, integer imageType returns image
2207
    set bj_lastCreatedImage = CreateImage(file, size, size, size, GetLocationX(where), GetLocationY(where), zOffset, 0, 0, 0, imageType)
2208
    return bj_lastCreatedImage
2209
endfunction
2210
2211
//============================================================================
2212
function ShowImageBJ takes boolean flag, image whichImage returns nothing
2213
    call ShowImage(whichImage, flag)
2214
endfunction
2215
2216
//============================================================================
2217
function SetImagePositionBJ takes image whichImage, location where, real zOffset returns nothing
2218
    call SetImagePosition(whichImage, GetLocationX(where), GetLocationY(where), zOffset)
2219
endfunction
2220
2221
//============================================================================
2222
function SetImageColorBJ takes image whichImage, real red, real green, real blue, real alpha returns nothing
2223
    call SetImageColor(whichImage, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-alpha))
2224
endfunction
2225
2226
//============================================================================
2227
function GetLastCreatedImage takes nothing returns image
2228
    return bj_lastCreatedImage
2229
endfunction
2230
2231
//============================================================================
2232
function CreateUbersplatBJ takes location where, string name, real red, real green, real blue, real alpha, boolean forcePaused, boolean noBirthTime returns ubersplat
2233
    set bj_lastCreatedUbersplat = CreateUbersplat(GetLocationX(where), GetLocationY(where), name, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-alpha), forcePaused, noBirthTime)
2234
    return bj_lastCreatedUbersplat
2235
endfunction
2236
2237
//============================================================================
2238
function ShowUbersplatBJ takes boolean flag, ubersplat whichSplat returns nothing
2239
    call ShowUbersplat(whichSplat, flag)
2240
endfunction
2241
2242
//============================================================================
2243
function GetLastCreatedUbersplat takes nothing returns ubersplat
2244
    return bj_lastCreatedUbersplat
2245
endfunction
2246
2247
//============================================================================
2248
function GetLastCreatedMinimapIcon takes nothing returns minimapicon
2249
    return bj_lastCreatedMinimapIcon
2250
endfunction
2251
2252
//============================================================================
2253
function CreateMinimapIconOnUnitBJ takes unit whichUnit, integer red, integer green, integer blue, string pingPath, fogstate fogVisibility returns minimapicon
2254
    set bj_lastCreatedMinimapIcon = CreateMinimapIconOnUnit(whichUnit, red, green, blue, pingPath, fogVisibility)
2255
    return bj_lastCreatedMinimapIcon
2256
endfunction
2257
2258
//============================================================================
2259
function CreateMinimapIconAtLocBJ takes location where, integer red, integer green, integer blue, string pingPath, fogstate fogVisibility returns minimapicon
2260
    set bj_lastCreatedMinimapIcon = CreateMinimapIconAtLoc(where, red, green, blue, pingPath, fogVisibility)
2261
    return bj_lastCreatedMinimapIcon
2262
endfunction
2263
2264
//============================================================================
2265
function CreateMinimapIconBJ takes real x, real y, integer red, integer green, integer blue, string pingPath, fogstate fogVisibility returns minimapicon
2266
    set bj_lastCreatedMinimapIcon = CreateMinimapIcon(x, y, red, green, blue, pingPath, fogVisibility)
2267
    return bj_lastCreatedMinimapIcon
2268
endfunction
2269
2270
//============================================================================
2271
function CampaignMinimapIconUnitBJ takes unit whichUnit, integer style returns nothing
2272
    local integer    red
2273
    local integer     green
2274
    local integer     blue
2275
    local string     path
2276
    if ( style == bj_CAMPPINGSTYLE_PRIMARY ) then
2277
        // green
2278
        set red     = 255
2279
        set green     = 0
2280
        set blue    = 0
2281
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectivePrimary" )
2282
    elseif ( style == bj_CAMPPINGSTYLE_PRIMARY_GREEN ) then
2283
        // green
2284
        set red     = 0
2285
        set green     = 255
2286
        set blue    = 0
2287
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectivePrimary" )
2288
    elseif ( style == bj_CAMPPINGSTYLE_PRIMARY_RED ) then
2289
        // green
2290
        set red     = 255
2291
        set green     = 0
2292
        set blue    = 0
2293
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectivePrimary" )
2294
    elseif ( style == bj_CAMPPINGSTYLE_BONUS ) then
2295
        // yellow
2296
        set red     = 255
2297
        set green     = 255
2298
        set blue    = 0
2299
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectiveBonus" )
2300
    elseif ( style == bj_CAMPPINGSTYLE_TURNIN ) then
2301
        // yellow
2302
        set red     = 255
2303
        set green     = 255
2304
        set blue    = 0
2305
        set path    = SkinManagerGetLocalPath( "MinimapQuestTurnIn" )
2306
    elseif ( style == bj_CAMPPINGSTYLE_BOSS ) then
2307
        // red
2308
        set red     = 255
2309
        set green     = 0
2310
        set blue    = 0
2311
        set path    = SkinManagerGetLocalPath( "MinimapQuestBoss" )
2312
    elseif ( style == bj_CAMPPINGSTYLE_CONTROL_ALLY ) then
2313
        // green
2314
        set red     = 0
2315
        set green     = 255
2316
        set blue    = 0
2317
        set path    = SkinManagerGetLocalPath( "MinimapQuestControlPoint" )
2318
    elseif ( style == bj_CAMPPINGSTYLE_CONTROL_NEUTRAL ) then
2319
        // white
2320
        set red     = 255
2321
        set green     = 255
2322
        set blue    = 255
2323
        set path    = SkinManagerGetLocalPath( "MinimapQuestControlPoint" )
2324
    elseif ( style == bj_CAMPPINGSTYLE_CONTROL_ENEMY ) then
2325
        // red
2326
        set red     = 255
2327
        set green     = 0
2328
        set blue    = 0
2329
        set path    = SkinManagerGetLocalPath( "MinimapQuestControlPoint" )
2330
    endif
2331
    call CreateMinimapIconOnUnitBJ( whichUnit, red, green, blue, path, FOG_OF_WAR_MASKED )
2332
    call SetMinimapIconOrphanDestroy( bj_lastCreatedMinimapIcon, true )
2333
endfunction
2334
2335
2336
//============================================================================
2337
function CampaignMinimapIconLocBJ takes location where, integer style returns nothing
2338
    local integer    red
2339
    local integer     green
2340
    local integer     blue
2341
    local string     path
2342
    if ( style == bj_CAMPPINGSTYLE_PRIMARY ) then
2343
        // green (different from the unit version)
2344
        set red     = 0
2345
        set green     = 255
2346
        set blue    = 0
2347
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectivePrimary" )
2348
    elseif ( style == bj_CAMPPINGSTYLE_PRIMARY_GREEN ) then
2349
        // green (different from the unit version)
2350
        set red     = 0
2351
        set green     = 255
2352
        set blue    = 0
2353
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectivePrimary" )
2354
    elseif ( style == bj_CAMPPINGSTYLE_PRIMARY_RED ) then
2355
        // green (different from the unit version)
2356
        set red     = 255
2357
        set green     = 0
2358
        set blue    = 0
2359
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectivePrimary" )
2360
    elseif ( style == bj_CAMPPINGSTYLE_BONUS ) then
2361
        // yellow
2362
        set red     = 255
2363
        set green     = 255
2364
        set blue    = 0
2365
        set path    = SkinManagerGetLocalPath( "MinimapQuestObjectiveBonus" )
2366
    elseif ( style == bj_CAMPPINGSTYLE_TURNIN ) then
2367
        // yellow
2368
        set red     = 255
2369
        set green     = 255
2370
        set blue    = 0
2371
        set path    = SkinManagerGetLocalPath( "MinimapQuestTurnIn" )
2372
    elseif ( style == bj_CAMPPINGSTYLE_BOSS ) then
2373
        // red
2374
        set red     = 255
2375
        set green     = 0
2376
        set blue    = 0
2377
        set path    = SkinManagerGetLocalPath( "MinimapQuestBoss" )
2378
    elseif ( style == bj_CAMPPINGSTYLE_CONTROL_ALLY ) then
2379
        // green
2380
        set red     = 0
2381
        set green     = 255
2382
        set blue    = 0
2383
        set path    = SkinManagerGetLocalPath( "MinimapQuestControlPoint" )
2384
    elseif ( style == bj_CAMPPINGSTYLE_CONTROL_NEUTRAL ) then
2385
        // white
2386
        set red     = 255
2387
        set green     = 255
2388
        set blue    = 255
2389
        set path    = SkinManagerGetLocalPath( "MinimapQuestControlPoint" )
2390
    elseif ( style == bj_CAMPPINGSTYLE_CONTROL_ENEMY ) then
2391
        // red
2392
        set red     = 255
2393
        set green     = 0
2394
        set blue    = 0
2395
        set path    = SkinManagerGetLocalPath( "MinimapQuestControlPoint" )
2396
    endif
2397
    call CreateMinimapIconAtLocBJ( where, red, green, blue, path, FOG_OF_WAR_MASKED )
2398
endfunction
2399
2400
2401
//***************************************************************************
2402
//*
2403
//*  Sound Utility Functions
2404
//*
2405
//***************************************************************************
2406
2407
//===========================================================================
2408
function PlaySoundBJ takes sound soundHandle returns nothing
2409
    set bj_lastPlayedSound = soundHandle
2410
    if (soundHandle != null) then
2411
        call StartSound(soundHandle)
2412
    endif
2413
endfunction
2414
2415
//===========================================================================
2416
function StopSoundBJ takes sound soundHandle, boolean fadeOut returns nothing
2417
    call StopSound(soundHandle, false, fadeOut)
2418
endfunction
2419
2420
//===========================================================================
2421
function SetSoundVolumeBJ takes sound soundHandle, real volumePercent returns nothing
2422
    call SetSoundVolume(soundHandle, PercentToInt(volumePercent, 127))
2423
endfunction
2424
2425
//===========================================================================
2426
function SetSoundOffsetBJ takes real newOffset, sound soundHandle returns nothing
2427
    call SetSoundPlayPosition(soundHandle, R2I(newOffset * 1000))
2428
endfunction
2429
2430
//===========================================================================
2431
function SetSoundDistanceCutoffBJ takes sound soundHandle, real cutoff returns nothing
2432
    call SetSoundDistanceCutoff(soundHandle, cutoff)
2433
endfunction
2434
2435
//===========================================================================
2436
function SetSoundPitchBJ takes sound soundHandle, real pitch returns nothing
2437
    call SetSoundPitch(soundHandle, pitch)
2438
endfunction
2439
2440
//===========================================================================
2441
function SetSoundPositionLocBJ takes sound soundHandle, location loc, real z returns nothing
2442
    call SetSoundPosition(soundHandle, GetLocationX(loc), GetLocationY(loc), z)
2443
endfunction
2444
2445
//===========================================================================
2446
function AttachSoundToUnitBJ takes sound soundHandle, unit whichUnit returns nothing
2447
    call AttachSoundToUnit(soundHandle, whichUnit)
2448
endfunction
2449
2450
//===========================================================================
2451
function SetSoundConeAnglesBJ takes sound soundHandle, real inside, real outside, real outsideVolumePercent returns nothing
2452
    call SetSoundConeAngles(soundHandle, inside, outside, PercentToInt(outsideVolumePercent, 127))
2453
endfunction
2454
2455
//===========================================================================
2456
function KillSoundWhenDoneBJ takes sound soundHandle returns nothing
2457
    call KillSoundWhenDone(soundHandle)
2458
endfunction
2459
2460
//===========================================================================
2461
function PlaySoundAtPointBJ takes sound soundHandle, real volumePercent, location loc, real z returns nothing
2462
    call SetSoundPositionLocBJ(soundHandle, loc, z)
2463
    call SetSoundVolumeBJ(soundHandle, volumePercent)
2464
    call PlaySoundBJ(soundHandle)
2465
endfunction
2466
2467
//===========================================================================
2468
function PlaySoundOnUnitBJ takes sound soundHandle, real volumePercent, unit whichUnit returns nothing
2469
    call AttachSoundToUnitBJ(soundHandle, whichUnit)
2470
    call SetSoundVolumeBJ(soundHandle, volumePercent)
2471
    call PlaySoundBJ(soundHandle)
2472
endfunction
2473
2474
//===========================================================================
2475
function PlaySoundFromOffsetBJ takes sound soundHandle, real volumePercent, real startingOffset returns nothing
2476
    call SetSoundVolumeBJ(soundHandle, volumePercent)
2477
    call PlaySoundBJ(soundHandle)
2478
    call SetSoundOffsetBJ(startingOffset, soundHandle)
2479
endfunction
2480
2481
//===========================================================================
2482
function PlayMusicBJ takes string musicFileName returns nothing
2483
    set bj_lastPlayedMusic = musicFileName
2484
    call PlayMusic(musicFileName)
2485
endfunction
2486
2487
//===========================================================================
2488
function PlayMusicExBJ takes string musicFileName, real startingOffset, real fadeInTime returns nothing
2489
    set bj_lastPlayedMusic = musicFileName
2490
    call PlayMusicEx(musicFileName, R2I(startingOffset * 1000), R2I(fadeInTime * 1000))
2491
endfunction
2492
2493
//===========================================================================
2494
function SetMusicOffsetBJ takes real newOffset returns nothing
2495
    call SetMusicPlayPosition(R2I(newOffset * 1000))
2496
endfunction
2497
2498
//===========================================================================
2499
function PlayThematicMusicBJ takes string musicName returns nothing
2500
    call PlayThematicMusic(musicName)
2501
endfunction
2502
2503
//===========================================================================
2504
function PlayThematicMusicExBJ takes string musicName, real startingOffset returns nothing
2505
    call PlayThematicMusicEx(musicName, R2I(startingOffset * 1000))
2506
endfunction
2507
2508
//===========================================================================
2509
function SetThematicMusicOffsetBJ takes real newOffset returns nothing
2510
    call SetThematicMusicPlayPosition(R2I(newOffset * 1000))
2511
endfunction
2512
2513
//===========================================================================
2514
function EndThematicMusicBJ takes nothing returns nothing
2515
    call EndThematicMusic()
2516
endfunction
2517
2518
//===========================================================================
2519
function StopMusicBJ takes boolean fadeOut returns nothing
2520
    call StopMusic(fadeOut)
2521
endfunction
2522
2523
//===========================================================================
2524
function ResumeMusicBJ takes nothing returns nothing
2525
    call ResumeMusic()
2526
endfunction
2527
2528
//===========================================================================
2529
function SetMusicVolumeBJ takes real volumePercent returns nothing
2530
    call SetMusicVolume(PercentToInt(volumePercent, 127))
2531
endfunction
2532
2533
//===========================================================================
2534
function SetThematicMusicVolumeBJ takes real volumePercent returns nothing
2535
    call SetThematicMusicVolume(PercentToInt(volumePercent, 127))
2536
endfunction
2537
2538
//===========================================================================
2539
function GetSoundDurationBJ takes sound soundHandle returns real
2540
    if (soundHandle == null) then
2541
        return bj_NOTHING_SOUND_DURATION
2542
    else
2543
        return I2R(GetSoundDuration(soundHandle)) * 0.001
2544
    endif
2545
endfunction
2546
2547
//===========================================================================
2548
function GetSoundFileDurationBJ takes string musicFileName returns real
2549
    return I2R(GetSoundFileDuration(musicFileName)) * 0.001
2550
endfunction
2551
2552
//===========================================================================
2553
function GetLastPlayedSound takes nothing returns sound
2554
    return bj_lastPlayedSound
2555
endfunction
2556
2557
//===========================================================================
2558
function GetLastPlayedMusic takes nothing returns string
2559
    return bj_lastPlayedMusic
2560
endfunction
2561
2562
//===========================================================================
2563
function VolumeGroupSetVolumeBJ takes volumegroup vgroup, real percent returns nothing
2564
    call VolumeGroupSetVolume(vgroup, percent * 0.01)
2565
endfunction
2566
2567
//===========================================================================
2568
function SetCineModeVolumeGroupsImmediateBJ takes nothing returns nothing
2569
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_UNITMOVEMENT,  bj_CINEMODE_VOLUME_UNITMOVEMENT)
2570
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_UNITSOUNDS,    bj_CINEMODE_VOLUME_UNITSOUNDS)
2571
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_COMBAT,        bj_CINEMODE_VOLUME_COMBAT)
2572
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_SPELLS,        bj_CINEMODE_VOLUME_SPELLS)
2573
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_UI,            bj_CINEMODE_VOLUME_UI)
2574
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_MUSIC,         bj_CINEMODE_VOLUME_MUSIC)
2575
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_AMBIENTSOUNDS, bj_CINEMODE_VOLUME_AMBIENTSOUNDS)
2576
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_FIRE,          bj_CINEMODE_VOLUME_FIRE)
2577
endfunction
2578
2579
//===========================================================================
2580
function SetCineModeVolumeGroupsBJ takes nothing returns nothing
2581
    // Delay the request if it occurs at map init.
2582
    if bj_gameStarted then
2583
        call SetCineModeVolumeGroupsImmediateBJ()
2584
    else
2585
        call TimerStart(bj_volumeGroupsTimer, bj_GAME_STARTED_THRESHOLD, false, function SetCineModeVolumeGroupsImmediateBJ)
2586
    endif
2587
endfunction
2588
2589
//===========================================================================
2590
function SetSpeechVolumeGroupsImmediateBJ takes nothing returns nothing
2591
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_UNITMOVEMENT,  bj_SPEECH_VOLUME_UNITMOVEMENT)
2592
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_UNITSOUNDS,    bj_SPEECH_VOLUME_UNITSOUNDS)
2593
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_COMBAT,        bj_SPEECH_VOLUME_COMBAT)
2594
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_SPELLS,        bj_SPEECH_VOLUME_SPELLS)
2595
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_UI,            bj_SPEECH_VOLUME_UI)
2596
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_MUSIC,         bj_SPEECH_VOLUME_MUSIC)
2597
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_AMBIENTSOUNDS, bj_SPEECH_VOLUME_AMBIENTSOUNDS)
2598
    call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_FIRE,          bj_SPEECH_VOLUME_FIRE)
2599
endfunction
2600
2601
//===========================================================================
2602
function SetSpeechVolumeGroupsBJ takes nothing returns nothing
2603
    // Delay the request if it occurs at map init.
2604
    if bj_gameStarted then
2605
        call SetSpeechVolumeGroupsImmediateBJ()
2606
    else
2607
        call TimerStart(bj_volumeGroupsTimer, bj_GAME_STARTED_THRESHOLD, false, function SetSpeechVolumeGroupsImmediateBJ)
2608
    endif
2609
endfunction
2610
2611
//===========================================================================
2612
function VolumeGroupResetImmediateBJ takes nothing returns nothing
2613
    call VolumeGroupReset()
2614
endfunction
2615
2616
//===========================================================================
2617
function VolumeGroupResetBJ takes nothing returns nothing
2618
    // Delay the request if it occurs at map init.
2619
    if bj_gameStarted then
2620
        call VolumeGroupResetImmediateBJ()
2621
    else
2622
        call TimerStart(bj_volumeGroupsTimer, bj_GAME_STARTED_THRESHOLD, false, function VolumeGroupResetImmediateBJ)
2623
    endif
2624
endfunction
2625
2626
//===========================================================================
2627
function GetSoundIsPlayingBJ takes sound soundHandle returns boolean
2628
    return GetSoundIsLoading(soundHandle) or GetSoundIsPlaying(soundHandle)
2629
endfunction
2630
2631
//===========================================================================
2632
function WaitForSoundBJ takes sound soundHandle, real offset returns nothing
2633
    call TriggerWaitForSound( soundHandle, offset )
2634
endfunction
2635
2636
//===========================================================================
2637
function SetMapMusicIndexedBJ takes string musicName, integer index returns nothing
2638
    call SetMapMusic(musicName, false, index)
2639
endfunction
2640
2641
//===========================================================================
2642
function SetMapMusicRandomBJ takes string musicName returns nothing
2643
    call SetMapMusic(musicName, true, 0)
2644
endfunction
2645
2646
//===========================================================================
2647
function ClearMapMusicBJ takes nothing returns nothing
2648
    call ClearMapMusic()
2649
endfunction
2650
2651
//===========================================================================
2652
function SetStackedSoundBJ takes boolean add, sound soundHandle, rect r returns nothing
2653
    local real width = GetRectMaxX(r) - GetRectMinX(r)
2654
    local real height = GetRectMaxY(r) - GetRectMinY(r)
2655
2656
    call SetSoundPosition(soundHandle, GetRectCenterX(r), GetRectCenterY(r), 0)
2657
    if add then
2658
        call RegisterStackedSound(soundHandle, true, width, height)
2659
    else
2660
        call UnregisterStackedSound(soundHandle, true, width, height)
2661
    endif
2662
endfunction
2663
2664
//===========================================================================
2665
function StartSoundForPlayerBJ takes player whichPlayer, sound soundHandle returns nothing
2666
    if (whichPlayer == GetLocalPlayer()) then
2667
        call StartSound(soundHandle)
2668
    endif
2669
endfunction
2670
2671
//===========================================================================
2672
function VolumeGroupSetVolumeForPlayerBJ takes player whichPlayer, volumegroup vgroup, real scale returns nothing
2673
    if (GetLocalPlayer() == whichPlayer) then
2674
        call VolumeGroupSetVolume(vgroup, scale)
2675
    endif
2676
endfunction
2677
2678
//===========================================================================
2679
function EnableDawnDusk takes boolean flag returns nothing
2680
    set bj_useDawnDuskSounds = flag
2681
endfunction
2682
2683
//===========================================================================
2684
function IsDawnDuskEnabled takes nothing returns boolean
2685
    return bj_useDawnDuskSounds
2686
endfunction
2687
2688
2689
2690
//***************************************************************************
2691
//*
2692
//*  Day/Night ambient sounds
2693
//*
2694
//***************************************************************************
2695
2696
//===========================================================================
2697
function SetAmbientDaySound takes string inLabel returns nothing
2698
    local real ToD
2699
2700
    // Stop old sound, if necessary
2701
    if (bj_dayAmbientSound != null) then
2702
        call StopSound(bj_dayAmbientSound, true, true)
2703
    endif
2704
2705
    // Create new sound
2706
    set bj_dayAmbientSound = CreateMIDISound(inLabel, 20, 20)
2707
2708
    // Start the sound if necessary, based on current time
2709
    set ToD = GetTimeOfDay()
2710
    if (ToD >= bj_TOD_DAWN and ToD < bj_TOD_DUSK) then
2711
        call StartSound(bj_dayAmbientSound)
2712
    endif
2713
endfunction
2714
2715
//===========================================================================
2716
function SetAmbientNightSound takes string inLabel returns nothing
2717
    local real ToD
2718
2719
    // Stop old sound, if necessary
2720
    if (bj_nightAmbientSound != null) then
2721
        call StopSound(bj_nightAmbientSound, true, true)
2722
    endif
2723
2724
    // Create new sound
2725
    set bj_nightAmbientSound = CreateMIDISound(inLabel, 20, 20)
2726
2727
    // Start the sound if necessary, based on current time
2728
    set ToD = GetTimeOfDay()
2729
    if (ToD < bj_TOD_DAWN or ToD >= bj_TOD_DUSK) then
2730
        call StartSound(bj_nightAmbientSound)
2731
    endif
2732
endfunction
2733
2734
2735
2736
//***************************************************************************
2737
//*
2738
//*  Special Effect Utility Functions
2739
//*
2740
//***************************************************************************
2741
2742
//===========================================================================
2743
function AddSpecialEffectLocBJ takes location where, string modelName returns effect
2744
    set bj_lastCreatedEffect = AddSpecialEffectLoc(modelName, where)
2745
    return bj_lastCreatedEffect
2746
endfunction
2747
2748
//===========================================================================
2749
function AddSpecialEffectTargetUnitBJ takes string attachPointName, widget targetWidget, string modelName returns effect
2750
    set bj_lastCreatedEffect = AddSpecialEffectTarget(modelName, targetWidget, attachPointName)
2751
    return bj_lastCreatedEffect
2752
endfunction
2753
2754
//===========================================================================
2755
// Two distinct trigger actions can't share the same function name, so this
2756
// dummy function simply mimics the behavior of an existing call.
2757
//
2758
// Commented out - Destructibles have no attachment points.
2759
//
2760
//function AddSpecialEffectTargetDestructableBJ takes string attachPointName, widget targetWidget, string modelName returns effect
2761
//    return AddSpecialEffectTargetUnitBJ(attachPointName, targetWidget, modelName)
2762
//endfunction
2763
2764
//===========================================================================
2765
// Two distinct trigger actions can't share the same function name, so this
2766
// dummy function simply mimics the behavior of an existing call.
2767
//
2768
// Commented out - Items have no attachment points.
2769
//
2770
//function AddSpecialEffectTargetItemBJ takes string attachPointName, widget targetWidget, string modelName returns effect
2771
//    return AddSpecialEffectTargetUnitBJ(attachPointName, targetWidget, modelName)
2772
//endfunction
2773
2774
//===========================================================================
2775
function DestroyEffectBJ takes effect whichEffect returns nothing
2776
    call DestroyEffect(whichEffect)
2777
endfunction
2778
2779
//===========================================================================
2780
function GetLastCreatedEffectBJ takes nothing returns effect
2781
    return bj_lastCreatedEffect
2782
endfunction
2783
2784
2785
2786
//***************************************************************************
2787
//*
2788
//*  Command Button Effect Utility Functions
2789
//*
2790
//***************************************************************************
2791
2792
//===========================================================================
2793
function CreateCommandButtonEffectBJ takes integer abilityId, string order returns commandbuttoneffect
2794
    set bj_lastCreatedCommandButtonEffect = CreateCommandButtonEffect(abilityId, order)
2795
    return bj_lastCreatedCommandButtonEffect
2796
endfunction
2797
2798
//===========================================================================
2799
function CreateTrainCommandButtonEffectBJ takes integer unitId returns commandbuttoneffect
2800
    set bj_lastCreatedCommandButtonEffect = CreateCommandButtonEffect('Aque', UnitId2String(unitId))
2801
    return bj_lastCreatedCommandButtonEffect
2802
endfunction
2803
2804
//===========================================================================
2805
function CreateUpgradeCommandButtonEffectBJ takes integer techId returns commandbuttoneffect
2806
    set bj_lastCreatedCommandButtonEffect = CreateUpgradeCommandButtonEffect(techId)
2807
    return bj_lastCreatedCommandButtonEffect
2808
endfunction
2809
2810
//===========================================================================
2811
function CreateCommonCommandButtonEffectBJ takes string order returns commandbuttoneffect
2812
    set bj_lastCreatedCommandButtonEffect = CreateCommandButtonEffect(0, order)
2813
    return bj_lastCreatedCommandButtonEffect
2814
endfunction
2815
2816
//===========================================================================
2817
function CreateLearnCommandButtonEffectBJ takes integer abilityId returns commandbuttoneffect
2818
    set bj_lastCreatedCommandButtonEffect = CreateLearnCommandButtonEffect(abilityId)
2819
    return bj_lastCreatedCommandButtonEffect
2820
endfunction
2821
2822
//===========================================================================
2823
function CreateBuildCommandButtonEffectBJ takes integer unitId returns commandbuttoneffect
2824
    local race r = GetPlayerRace(GetLocalPlayer())
2825
    local integer abilityId
2826
    if (r == RACE_HUMAN) then
2827
        set abilityId = 'AHbu'
2828
    elseif (r == RACE_ORC) then
2829
        set abilityId = 'AObu'
2830
    elseif (r == RACE_UNDEAD) then
2831
        set abilityId = 'AUbu'
2832
    elseif (r == RACE_NIGHTELF) then
2833
        set abilityId = 'AEbu'
2834
    else
2835
        set abilityId = 'ANbu'
2836
    endif
2837
    set bj_lastCreatedCommandButtonEffect = CreateCommandButtonEffect(abilityId, UnitId2String(unitId))
2838
    return bj_lastCreatedCommandButtonEffect
2839
endfunction
2840
2841
//===========================================================================
2842
function GetLastCreatedCommandButtonEffectBJ takes nothing returns commandbuttoneffect
2843
    return bj_lastCreatedCommandButtonEffect
2844
endfunction
2845
2846
2847
//***************************************************************************
2848
//*
2849
//*  Hero and Item Utility Functions
2850
//*
2851
//***************************************************************************
2852
2853
//===========================================================================
2854
function GetItemLoc takes item whichItem returns location
2855
    return Location(GetItemX(whichItem), GetItemY(whichItem))
2856
endfunction
2857
2858
//===========================================================================
2859
function GetItemLifeBJ takes widget whichWidget returns real
2860
    return GetWidgetLife(whichWidget)
2861
endfunction
2862
2863
//===========================================================================
2864
function SetItemLifeBJ takes widget whichWidget, real life returns nothing
2865
    call SetWidgetLife(whichWidget, life)
2866
endfunction
2867
2868
//===========================================================================
2869
function AddHeroXPSwapped takes integer xpToAdd, unit whichHero, boolean showEyeCandy returns nothing
2870
    call AddHeroXP(whichHero, xpToAdd, showEyeCandy)
2871
endfunction
2872
2873
//===========================================================================
2874
function SetHeroLevelBJ takes unit whichHero, integer newLevel, boolean showEyeCandy returns nothing
2875
    local integer oldLevel = GetHeroLevel(whichHero)
2876
2877
    if (newLevel > oldLevel) then
2878
        call SetHeroLevel(whichHero, newLevel, showEyeCandy)
2879
    elseif (newLevel < oldLevel) then
2880
        call UnitStripHeroLevel(whichHero, oldLevel - newLevel)
2881
    else
2882
        // No change in level - ignore the request.
2883
    endif
2884
endfunction
2885
2886
//===========================================================================
2887
function DecUnitAbilityLevelSwapped takes integer abilcode, unit whichUnit returns integer
2888
    return DecUnitAbilityLevel(whichUnit, abilcode)
2889
endfunction
2890
2891
//===========================================================================
2892
function IncUnitAbilityLevelSwapped takes integer abilcode, unit whichUnit returns integer
2893
    return IncUnitAbilityLevel(whichUnit, abilcode)
2894
endfunction
2895
2896
//===========================================================================
2897
function SetUnitAbilityLevelSwapped takes integer abilcode, unit whichUnit, integer level returns integer
2898
    return SetUnitAbilityLevel(whichUnit, abilcode, level)
2899
endfunction
2900
2901
//===========================================================================
2902
function GetUnitAbilityLevelSwapped takes integer abilcode, unit whichUnit returns integer
2903
    return GetUnitAbilityLevel(whichUnit, abilcode)
2904
endfunction
2905
2906
//===========================================================================
2907
function UnitHasBuffBJ takes unit whichUnit, integer buffcode returns boolean
2908
    return (GetUnitAbilityLevel(whichUnit, buffcode) > 0)
2909
endfunction
2910
2911
//===========================================================================
2912
function UnitRemoveBuffBJ takes integer buffcode, unit whichUnit returns boolean
2913
    return UnitRemoveAbility(whichUnit, buffcode)
2914
endfunction
2915
2916
//===========================================================================
2917
function UnitAddItemSwapped takes item whichItem, unit whichHero returns boolean
2918
    return UnitAddItem(whichHero, whichItem)
2919
endfunction
2920
2921
//===========================================================================
2922
function UnitAddItemByIdSwapped takes integer itemId, unit whichHero returns item
2923
    // Create the item at the hero's feet first, and then give it to him.
2924
    // This is to ensure that the item will be left at the hero's feet if
2925
    // his inventory is full. 
2926
    set bj_lastCreatedItem = CreateItem(itemId, GetUnitX(whichHero), GetUnitY(whichHero))
2927
    call UnitAddItem(whichHero, bj_lastCreatedItem)
2928
    return bj_lastCreatedItem
2929
endfunction
2930
2931
//===========================================================================
2932
function UnitRemoveItemSwapped takes item whichItem, unit whichHero returns nothing
2933
    set bj_lastRemovedItem = whichItem
2934
    call UnitRemoveItem(whichHero, whichItem)
2935
endfunction
2936
2937
//===========================================================================
2938
// Translates 0-based slot indices to 1-based slot indices.
2939
//
2940
function UnitRemoveItemFromSlotSwapped takes integer itemSlot, unit whichHero returns item
2941
    set bj_lastRemovedItem = UnitRemoveItemFromSlot(whichHero, itemSlot-1)
2942
    return bj_lastRemovedItem
2943
endfunction
2944
2945
//===========================================================================
2946
function CreateItemLoc takes integer itemId, location loc returns item
2947
    set bj_lastCreatedItem = CreateItem(itemId, GetLocationX(loc), GetLocationY(loc))
2948
    return bj_lastCreatedItem
2949
endfunction
2950
2951
//===========================================================================
2952
function GetLastCreatedItem takes nothing returns item
2953
    return bj_lastCreatedItem
2954
endfunction
2955
2956
//===========================================================================
2957
function GetLastRemovedItem takes nothing returns item
2958
    return bj_lastRemovedItem
2959
endfunction
2960
2961
//===========================================================================
2962
function SetItemPositionLoc takes item whichItem, location loc returns nothing
2963
    call SetItemPosition(whichItem, GetLocationX(loc), GetLocationY(loc))
2964
endfunction
2965
2966
//===========================================================================
2967
function GetLearnedSkillBJ takes nothing returns integer
2968
    return GetLearnedSkill()
2969
endfunction
2970
2971
//===========================================================================
2972
function SuspendHeroXPBJ takes boolean flag, unit whichHero returns nothing
2973
    call SuspendHeroXP(whichHero, not flag)
2974
endfunction
2975
2976
//===========================================================================
2977
function SetPlayerHandicapDamageBJ takes player whichPlayer, real handicapPercent returns nothing
2978
    call SetPlayerHandicapDamage(whichPlayer, handicapPercent * 0.01)
2979
endfunction
2980
2981
//===========================================================================
2982
function GetPlayerHandicapDamageBJ takes player whichPlayer returns real
2983
    return GetPlayerHandicapDamage(whichPlayer) * 100
2984
endfunction
2985
2986
//===========================================================================
2987
function SetPlayerHandicapReviveTimeBJ takes player whichPlayer, real handicapPercent returns nothing
2988
    call SetPlayerHandicapReviveTime(whichPlayer, handicapPercent * 0.01)
2989
endfunction
2990
2991
//===========================================================================
2992
function GetPlayerHandicapReviveTimeBJ takes player whichPlayer returns real
2993
    return GetPlayerHandicapReviveTime(whichPlayer) * 100
2994
endfunction
2995
2996
//===========================================================================
2997
function SetPlayerHandicapXPBJ takes player whichPlayer, real handicapPercent returns nothing
2998
    call SetPlayerHandicapXP(whichPlayer, handicapPercent * 0.01)
2999
endfunction
3000
3001
//===========================================================================
3002
function GetPlayerHandicapXPBJ takes player whichPlayer returns real
3003
    return GetPlayerHandicapXP(whichPlayer) * 100
3004
endfunction
3005
3006
//===========================================================================
3007
function SetPlayerHandicapBJ takes player whichPlayer, real handicapPercent returns nothing
3008
    call SetPlayerHandicap(whichPlayer, handicapPercent * 0.01)
3009
endfunction
3010
3011
//===========================================================================
3012
function GetPlayerHandicapBJ takes player whichPlayer returns real
3013
    return GetPlayerHandicap(whichPlayer) * 100
3014
endfunction
3015
3016
//===========================================================================
3017
function GetHeroStatBJ takes integer whichStat, unit whichHero, boolean includeBonuses returns integer
3018
    if (whichStat == bj_HEROSTAT_STR) then
3019
        return GetHeroStr(whichHero, includeBonuses)
3020
    elseif (whichStat == bj_HEROSTAT_AGI) then
3021
        return GetHeroAgi(whichHero, includeBonuses)
3022
    elseif (whichStat == bj_HEROSTAT_INT) then
3023
        return GetHeroInt(whichHero, includeBonuses)
3024
    else
3025
        // Unrecognized hero stat - return 0
3026
        return 0
3027
    endif
3028
endfunction
3029
3030
//===========================================================================
3031
function SetHeroStat takes unit whichHero, integer whichStat, integer value returns nothing
3032
    // Ignore requests for negative hero stats.
3033
    if (value <= 0) then
3034
        return
3035
    endif
3036
3037
    if (whichStat == bj_HEROSTAT_STR) then
3038
        call SetHeroStr(whichHero, value, true)
3039
    elseif (whichStat == bj_HEROSTAT_AGI) then
3040
        call SetHeroAgi(whichHero, value, true)
3041
    elseif (whichStat == bj_HEROSTAT_INT) then
3042
        call SetHeroInt(whichHero, value, true)
3043
    else
3044
        // Unrecognized hero stat - ignore the request.
3045
    endif
3046
endfunction
3047
3048
//===========================================================================
3049
function ModifyHeroStat takes integer whichStat, unit whichHero, integer modifyMethod, integer value returns nothing
3050
    if (modifyMethod == bj_MODIFYMETHOD_ADD) then
3051
        call SetHeroStat(whichHero, whichStat, GetHeroStatBJ(whichStat, whichHero, false) + value)
3052
    elseif (modifyMethod == bj_MODIFYMETHOD_SUB) then
3053
        call SetHeroStat(whichHero, whichStat, GetHeroStatBJ(whichStat, whichHero, false) - value)
3054
    elseif (modifyMethod == bj_MODIFYMETHOD_SET) then
3055
        call SetHeroStat(whichHero, whichStat, value)
3056
    else
3057
        // Unrecognized modification method - ignore the request.
3058
    endif
3059
endfunction
3060
3061
//===========================================================================
3062
function ModifyHeroSkillPoints takes unit whichHero, integer modifyMethod, integer value returns boolean
3063
    if (modifyMethod == bj_MODIFYMETHOD_ADD) then
3064
        return UnitModifySkillPoints(whichHero, value)
3065
    elseif (modifyMethod == bj_MODIFYMETHOD_SUB) then
3066
        return UnitModifySkillPoints(whichHero, -value)
3067
    elseif (modifyMethod == bj_MODIFYMETHOD_SET) then
3068
        return UnitModifySkillPoints(whichHero, value - GetHeroSkillPoints(whichHero))
3069
    else
3070
        // Unrecognized modification method - ignore the request and return failure.
3071
        return false
3072
    endif
3073
endfunction
3074
3075
//===========================================================================
3076
function UnitDropItemPointBJ takes unit whichUnit, item whichItem, real x, real y returns boolean
3077
    return UnitDropItemPoint(whichUnit, whichItem, x, y)
3078
endfunction
3079
3080
//===========================================================================
3081
function UnitDropItemPointLoc takes unit whichUnit, item whichItem, location loc returns boolean
3082
    return UnitDropItemPoint(whichUnit, whichItem, GetLocationX(loc), GetLocationY(loc))
3083
endfunction
3084
3085
//===========================================================================
3086
function UnitDropItemSlotBJ takes unit whichUnit, item whichItem, integer slot returns boolean
3087
    return UnitDropItemSlot(whichUnit, whichItem, slot-1)
3088
endfunction
3089
3090
//===========================================================================
3091
function UnitDropItemTargetBJ takes unit whichUnit, item whichItem, widget target returns boolean
3092
    return UnitDropItemTarget(whichUnit, whichItem, target)
3093
endfunction
3094
3095
//===========================================================================
3096
// Two distinct trigger actions can't share the same function name, so this
3097
// dummy function simply mimics the behavior of an existing call.
3098
//
3099
function UnitUseItemDestructable takes unit whichUnit, item whichItem, widget target returns boolean
3100
    return UnitUseItemTarget(whichUnit, whichItem, target)
3101
endfunction
3102
3103
//===========================================================================
3104
function UnitUseItemPointLoc takes unit whichUnit, item whichItem, location loc returns boolean
3105
    return UnitUseItemPoint(whichUnit, whichItem, GetLocationX(loc), GetLocationY(loc))
3106
endfunction
3107
3108
//===========================================================================
3109
// Translates 0-based slot indices to 1-based slot indices.
3110
//
3111
function UnitItemInSlotBJ takes unit whichUnit, integer itemSlot returns item
3112
    return UnitItemInSlot(whichUnit, itemSlot-1)
3113
endfunction
3114
3115
//===========================================================================
3116
// Translates 0-based slot indices to 1-based slot indices.
3117
//
3118
function GetInventoryIndexOfItemTypeBJ takes unit whichUnit, integer itemId returns integer
3119
    local integer index
3120
    local item    indexItem
3121
3122
    set index = 0
3123
    loop
3124
        set indexItem = UnitItemInSlot(whichUnit, index)
3125
        if (indexItem != null) and (GetItemTypeId(indexItem) == itemId) then
3126
            return index + 1
3127
        endif
3128
3129
        set index = index + 1
3130
        exitwhen index >= bj_MAX_INVENTORY
3131
    endloop
3132
    return 0
3133
endfunction
3134
3135
//===========================================================================
3136
function GetItemOfTypeFromUnitBJ takes unit whichUnit, integer itemId returns item
3137
    local integer index = GetInventoryIndexOfItemTypeBJ(whichUnit, itemId)
3138
3139
    if (index == 0) then
3140
        return null
3141
    else
3142
        return UnitItemInSlot(whichUnit, index - 1)
3143
    endif
3144
endfunction
3145
3146
//===========================================================================
3147
function UnitHasItemOfTypeBJ takes unit whichUnit, integer itemId returns boolean
3148
    return GetInventoryIndexOfItemTypeBJ(whichUnit, itemId) > 0
3149
endfunction
3150
3151
//===========================================================================
3152
function UnitInventoryCount takes unit whichUnit returns integer
3153
    local integer index = 0
3154
    local integer count = 0
3155
3156
    loop
3157
        if (UnitItemInSlot(whichUnit, index) != null) then
3158
            set count = count + 1
3159
        endif
3160
3161
        set index = index + 1
3162
        exitwhen index >= bj_MAX_INVENTORY
3163
    endloop
3164
3165
    return count
3166
endfunction
3167
3168
//===========================================================================
3169
function UnitInventorySizeBJ takes unit whichUnit returns integer
3170
    return UnitInventorySize(whichUnit)
3171
endfunction
3172
3173
//===========================================================================
3174
function SetItemInvulnerableBJ takes item whichItem, boolean flag returns nothing
3175
    call SetItemInvulnerable(whichItem, flag)
3176
endfunction
3177
3178
//===========================================================================
3179
function SetItemDropOnDeathBJ takes item whichItem, boolean flag returns nothing
3180
    call SetItemDropOnDeath(whichItem, flag)
3181
endfunction
3182
3183
//===========================================================================
3184
function SetItemDroppableBJ takes item whichItem, boolean flag returns nothing
3185
    call SetItemDroppable(whichItem, flag)
3186
endfunction
3187
3188
//===========================================================================
3189
function SetItemPlayerBJ takes item whichItem, player whichPlayer, boolean changeColor returns nothing
3190
    call SetItemPlayer(whichItem, whichPlayer, changeColor)
3191
endfunction
3192
3193
//===========================================================================
3194
function SetItemVisibleBJ takes boolean show, item whichItem returns nothing
3195
    call SetItemVisible(whichItem, show)
3196
endfunction
3197
3198
//===========================================================================
3199
function IsItemHiddenBJ takes item whichItem returns boolean
3200
    return not IsItemVisible(whichItem)
3201
endfunction
3202
3203
//===========================================================================
3204
function ChooseRandomItemBJ takes integer level returns integer
3205
    return ChooseRandomItem(level)
3206
endfunction
3207
3208
//===========================================================================
3209
function ChooseRandomItemExBJ takes integer level, itemtype whichType returns integer
3210
    return ChooseRandomItemEx(whichType, level)
3211
endfunction
3212
3213
//===========================================================================
3214
function ChooseRandomNPBuildingBJ takes nothing returns integer
3215
    return ChooseRandomNPBuilding()
3216
endfunction
3217
3218
//===========================================================================
3219
function ChooseRandomCreepBJ takes integer level returns integer
3220
    return ChooseRandomCreep(level)
3221
endfunction
3222
3223
//===========================================================================
3224
function EnumItemsInRectBJ takes rect r, code actionFunc returns nothing
3225
    call EnumItemsInRect(r, null, actionFunc)
3226
endfunction
3227
3228
//===========================================================================
3229
// See GroupPickRandomUnitEnum for the details of this algorithm.
3230
//
3231
function RandomItemInRectBJEnum takes nothing returns nothing
3232
    set bj_itemRandomConsidered = bj_itemRandomConsidered + 1
3233
    if (GetRandomInt(1, bj_itemRandomConsidered) == 1) then
3234
        set bj_itemRandomCurrentPick = GetEnumItem()
3235
    endif
3236
endfunction
3237
3238
//===========================================================================
3239
// Picks a random item from within a rect, matching a condition
3240
//
3241
function RandomItemInRectBJ takes rect r, boolexpr filter returns item
3242
    set bj_itemRandomConsidered = 0
3243
    set bj_itemRandomCurrentPick = null
3244
    call EnumItemsInRect(r, filter, function RandomItemInRectBJEnum)
3245
    call DestroyBoolExpr(filter)
3246
    return bj_itemRandomCurrentPick
3247
endfunction
3248
3249
//===========================================================================
3250
// Picks a random item from within a rect
3251
//
3252
function RandomItemInRectSimpleBJ takes rect r returns item
3253
    return RandomItemInRectBJ(r, null)
3254
endfunction
3255
3256
//===========================================================================
3257
function CheckItemStatus takes item whichItem, integer status returns boolean
3258
    if (status == bj_ITEM_STATUS_HIDDEN) then
3259
        return not IsItemVisible(whichItem)
3260
    elseif (status == bj_ITEM_STATUS_OWNED) then
3261
        return IsItemOwned(whichItem)
3262
    elseif (status == bj_ITEM_STATUS_INVULNERABLE) then
3263
        return IsItemInvulnerable(whichItem)
3264
    elseif (status == bj_ITEM_STATUS_POWERUP) then
3265
        return IsItemPowerup(whichItem)
3266
    elseif (status == bj_ITEM_STATUS_SELLABLE) then
3267
        return IsItemSellable(whichItem)
3268
    elseif (status == bj_ITEM_STATUS_PAWNABLE) then
3269
        return IsItemPawnable(whichItem)
3270
    else
3271
        // Unrecognized status - return false
3272
        return false
3273
    endif
3274
endfunction
3275
3276
//===========================================================================
3277
function CheckItemcodeStatus takes integer itemId, integer status returns boolean
3278
    if (status == bj_ITEMCODE_STATUS_POWERUP) then
3279
        return IsItemIdPowerup(itemId)
3280
    elseif (status == bj_ITEMCODE_STATUS_SELLABLE) then
3281
        return IsItemIdSellable(itemId)
3282
    elseif (status == bj_ITEMCODE_STATUS_PAWNABLE) then
3283
        return IsItemIdPawnable(itemId)
3284
    else
3285
        // Unrecognized status - return false
3286
        return false
3287
    endif
3288
endfunction
3289
3290
3291
3292
//***************************************************************************
3293
//*
3294
//*  Unit Utility Functions
3295
//*
3296
//***************************************************************************
3297
3298
//===========================================================================
3299
function UnitId2OrderIdBJ takes integer unitId returns integer
3300
    return unitId
3301
endfunction
3302
3303
//===========================================================================
3304
function String2UnitIdBJ takes string unitIdString returns integer
3305
    return UnitId(unitIdString)
3306
endfunction
3307
3308
//===========================================================================
3309
function UnitId2StringBJ takes integer unitId returns string
3310
    local string unitString = UnitId2String(unitId)
3311
3312
    if (unitString != null) then
3313
        return unitString
3314
    endif
3315
3316
    // The unitId was not recognized - return an empty string.
3317
    return ""
3318
endfunction
3319
3320
//===========================================================================
3321
function String2OrderIdBJ takes string orderIdString returns integer
3322
    local integer orderId
3323
    
3324
    // Check to see if it's a generic order.
3325
    set orderId = OrderId(orderIdString)
3326
    if (orderId != 0) then
3327
        return orderId
3328
    endif
3329
3330
    // Check to see if it's a (train) unit order.
3331
    set orderId = UnitId(orderIdString)
3332
    if (orderId != 0) then
3333
        return orderId
3334
    endif
3335
3336
    // Unrecognized - return 0
3337
    return 0
3338
endfunction
3339
3340
//===========================================================================
3341
function OrderId2StringBJ takes integer orderId returns string
3342
    local string orderString
3343
3344
    // Check to see if it's a generic order.
3345
    set orderString = OrderId2String(orderId)
3346
    if (orderString != null) then
3347
        return orderString
3348
    endif
3349
3350
    // Check to see if it's a (train) unit order.
3351
    set orderString = UnitId2String(orderId)
3352
    if (orderString != null) then
3353
        return orderString
3354
    endif
3355
3356
    // Unrecognized - return an empty string.
3357
    return ""
3358
endfunction
3359
3360
//===========================================================================
3361
function GetIssuedOrderIdBJ takes nothing returns integer
3362
    return GetIssuedOrderId()
3363
endfunction
3364
3365
//===========================================================================
3366
function GetKillingUnitBJ takes nothing returns unit
3367
    return GetKillingUnit()
3368
endfunction
3369
3370
//===========================================================================
3371
function CreateUnitAtLocSaveLast takes player id, integer unitid, location loc, real face returns unit
3372
    if (unitid == 'ugol') then
3373
        set bj_lastCreatedUnit = CreateBlightedGoldmine(id, GetLocationX(loc), GetLocationY(loc), face)
3374
    else
3375
        set bj_lastCreatedUnit = CreateUnitAtLoc(id, unitid, loc, face)
3376
    endif
3377
3378
    return bj_lastCreatedUnit
3379
endfunction
3380
3381
//===========================================================================
3382
function GetLastCreatedUnit takes nothing returns unit
3383
    return bj_lastCreatedUnit
3384
endfunction
3385
3386
//===========================================================================
3387
function CreateNUnitsAtLoc takes integer count, integer unitId, player whichPlayer, location loc, real face returns group
3388
    call GroupClear(bj_lastCreatedGroup)
3389
    loop
3390
        set count = count - 1
3391
        exitwhen count < 0
3392
        call CreateUnitAtLocSaveLast(whichPlayer, unitId, loc, face)
3393
        call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
3394
    endloop
3395
    return bj_lastCreatedGroup
3396
endfunction
3397
3398
//===========================================================================
3399
function CreateNUnitsAtLocFacingLocBJ takes integer count, integer unitId, player whichPlayer, location loc, location lookAt returns group
3400
    return CreateNUnitsAtLoc(count, unitId, whichPlayer, loc, AngleBetweenPoints(loc, lookAt))
3401
endfunction
3402
3403
//===========================================================================
3404
function GetLastCreatedGroupEnum takes nothing returns nothing
3405
    call GroupAddUnit(bj_groupLastCreatedDest, GetEnumUnit())
3406
endfunction
3407
3408
//===========================================================================
3409
function GetLastCreatedGroup takes nothing returns group
3410
    set bj_groupLastCreatedDest = CreateGroup()
3411
    call ForGroup(bj_lastCreatedGroup, function GetLastCreatedGroupEnum)
3412
    return bj_groupLastCreatedDest
3413
endfunction
3414
3415
//===========================================================================
3416
function CreateCorpseLocBJ takes integer unitid, player whichPlayer, location loc returns unit
3417
    set bj_lastCreatedUnit = CreateCorpse(whichPlayer, unitid, GetLocationX(loc), GetLocationY(loc), GetRandomReal(0, 360))
3418
    return bj_lastCreatedUnit
3419
endfunction
3420
3421
//===========================================================================
3422
function UnitSuspendDecayBJ takes boolean suspend, unit whichUnit returns nothing
3423
    call UnitSuspendDecay(whichUnit, suspend)
3424
endfunction
3425
3426
//===========================================================================
3427
function DelayedSuspendDecayStopAnimEnum takes nothing returns nothing
3428
    local unit enumUnit = GetEnumUnit()
3429
3430
    if (GetUnitState(enumUnit, UNIT_STATE_LIFE) <= 0) then
3431
        call SetUnitTimeScale(enumUnit, 0.0001)
3432
    endif
3433
endfunction
3434
3435
//===========================================================================
3436
function DelayedSuspendDecayBoneEnum takes nothing returns nothing
3437
    local unit enumUnit = GetEnumUnit()
3438
3439
    if (GetUnitState(enumUnit, UNIT_STATE_LIFE) <= 0) then
3440
        call UnitSuspendDecay(enumUnit, true)
3441
        call SetUnitTimeScale(enumUnit, 0.0001)
3442
    endif
3443
endfunction
3444
3445
//===========================================================================
3446
// Game code explicitly sets the animation back to "decay bone" after the
3447
// initial corpse fades away, so we reset it now.  It's best not to show
3448
// off corpses thus created until after this grace period has passed.
3449
//
3450
function DelayedSuspendDecayFleshEnum takes nothing returns nothing
3451
    local unit enumUnit = GetEnumUnit()
3452
3453
    if (GetUnitState(enumUnit, UNIT_STATE_LIFE) <= 0) then
3454
        call UnitSuspendDecay(enumUnit, true)
3455
        call SetUnitTimeScale(enumUnit, 10.0)
3456
        call SetUnitAnimation(enumUnit, "decay flesh")
3457
    endif
3458
endfunction
3459
3460
//===========================================================================
3461
// Waits a short period of time to ensure that the corpse is decaying, and
3462
// then suspend the animation and corpse decay.
3463
//
3464
function DelayedSuspendDecay takes nothing returns nothing
3465
    local group boneGroup
3466
    local group fleshGroup
3467
3468
    // Switch the global unit groups over to local variables and recreate
3469
    // the global versions, so that this function can handle overlapping
3470
    // calls.
3471
    set boneGroup = bj_suspendDecayBoneGroup
3472
    set fleshGroup = bj_suspendDecayFleshGroup
3473
    set bj_suspendDecayBoneGroup = CreateGroup()
3474
    set bj_suspendDecayFleshGroup = CreateGroup()
3475
3476
    call ForGroup(fleshGroup, function DelayedSuspendDecayStopAnimEnum)
3477
    call ForGroup(boneGroup, function DelayedSuspendDecayStopAnimEnum)
3478
3479
    call TriggerSleepAction(bj_CORPSE_MAX_DEATH_TIME)
3480
    call ForGroup(fleshGroup, function DelayedSuspendDecayFleshEnum)
3481
    call ForGroup(boneGroup, function DelayedSuspendDecayBoneEnum)
3482
3483
    call TriggerSleepAction(0.05)
3484
    call ForGroup(fleshGroup, function DelayedSuspendDecayStopAnimEnum)
3485
3486
    call DestroyGroup(boneGroup)
3487
    call DestroyGroup(fleshGroup)
3488
endfunction
3489
3490
//===========================================================================
3491
function DelayedSuspendDecayCreate takes nothing returns nothing
3492
    set bj_delayedSuspendDecayTrig = CreateTrigger()
3493
    call TriggerRegisterTimerExpireEvent(bj_delayedSuspendDecayTrig, bj_delayedSuspendDecayTimer)
3494
    call TriggerAddAction(bj_delayedSuspendDecayTrig, function DelayedSuspendDecay)
3495
endfunction
3496
3497
//===========================================================================
3498
function CreatePermanentCorpseLocBJ takes integer style, integer unitid, player whichPlayer, location loc, real facing returns unit
3499
    set bj_lastCreatedUnit = CreateCorpse(whichPlayer, unitid, GetLocationX(loc), GetLocationY(loc), facing)
3500
    call SetUnitBlendTime(bj_lastCreatedUnit, 0)
3501
3502
    if (style == bj_CORPSETYPE_FLESH) then
3503
        call SetUnitAnimation(bj_lastCreatedUnit, "decay flesh")
3504
        call GroupAddUnit(bj_suspendDecayFleshGroup, bj_lastCreatedUnit)
3505
    elseif (style == bj_CORPSETYPE_BONE) then
3506
        call SetUnitAnimation(bj_lastCreatedUnit, "decay bone")
3507
        call GroupAddUnit(bj_suspendDecayBoneGroup, bj_lastCreatedUnit)
3508
    else
3509
        // Unknown decay style - treat as skeletal.
3510
        call SetUnitAnimation(bj_lastCreatedUnit, "decay bone")
3511
        call GroupAddUnit(bj_suspendDecayBoneGroup, bj_lastCreatedUnit)
3512
    endif
3513
3514
    call TimerStart(bj_delayedSuspendDecayTimer, 0.05, false, null)
3515
    return bj_lastCreatedUnit
3516
endfunction
3517
3518
//===========================================================================
3519
function GetUnitStateSwap takes unitstate whichState, unit whichUnit returns real
3520
    return GetUnitState(whichUnit, whichState)
3521
endfunction
3522
3523
//===========================================================================
3524
function GetUnitStatePercent takes unit whichUnit, unitstate whichState, unitstate whichMaxState returns real
3525
    local real value    = GetUnitState(whichUnit, whichState)
3526
    local real maxValue = GetUnitState(whichUnit, whichMaxState)
3527
3528
    // Return 0 for null units.
3529
    if (whichUnit == null) or (maxValue == 0) then
3530
        return 0.0
3531
    endif
3532
3533
    return value / maxValue * 100.0
3534
endfunction
3535
3536
//===========================================================================
3537
function GetUnitLifePercent takes unit whichUnit returns real
3538
    return GetUnitStatePercent(whichUnit, UNIT_STATE_LIFE, UNIT_STATE_MAX_LIFE)
3539
endfunction
3540
3541
//===========================================================================
3542
function GetUnitManaPercent takes unit whichUnit returns real
3543
    return GetUnitStatePercent(whichUnit, UNIT_STATE_MANA, UNIT_STATE_MAX_MANA)
3544
endfunction
3545
3546
//===========================================================================
3547
function SelectUnitSingle takes unit whichUnit returns nothing
3548
    call ClearSelection()
3549
    call SelectUnit(whichUnit, true)
3550
endfunction
3551
3552
//===========================================================================
3553
function SelectGroupBJEnum takes nothing returns nothing
3554
    call SelectUnit( GetEnumUnit(), true )
3555
endfunction
3556
3557
//===========================================================================
3558
function SelectGroupBJ takes group g returns nothing
3559
    call ClearSelection()
3560
    call ForGroup( g, function SelectGroupBJEnum )
3561
endfunction
3562
3563
//===========================================================================
3564
function SelectUnitAdd takes unit whichUnit returns nothing
3565
    call SelectUnit(whichUnit, true)
3566
endfunction
3567
3568
//===========================================================================
3569
function SelectUnitRemove takes unit whichUnit returns nothing
3570
    call SelectUnit(whichUnit, false)
3571
endfunction
3572
3573
//===========================================================================
3574
function ClearSelectionForPlayer takes player whichPlayer returns nothing
3575
    if (GetLocalPlayer() == whichPlayer) then
3576
        // Use only local code (no net traffic) within this block to avoid desyncs.
3577
        call ClearSelection()
3578
    endif
3579
endfunction
3580
3581
//===========================================================================
3582
function SelectUnitForPlayerSingle takes unit whichUnit, player whichPlayer returns nothing
3583
    if (GetLocalPlayer() == whichPlayer) then
3584
        // Use only local code (no net traffic) within this block to avoid desyncs.
3585
        call ClearSelection()
3586
        call SelectUnit(whichUnit, true)
3587
    endif
3588
endfunction
3589
3590
//===========================================================================
3591
function SelectGroupForPlayerBJ takes group g, player whichPlayer returns nothing
3592
    if (GetLocalPlayer() == whichPlayer) then
3593
        // Use only local code (no net traffic) within this block to avoid desyncs.
3594
        call ClearSelection()
3595
        call ForGroup( g, function SelectGroupBJEnum )
3596
    endif
3597
endfunction
3598
3599
//===========================================================================
3600
function SelectUnitAddForPlayer takes unit whichUnit, player whichPlayer returns nothing
3601
    if (GetLocalPlayer() == whichPlayer) then
3602
        // Use only local code (no net traffic) within this block to avoid desyncs.
3603
        call SelectUnit(whichUnit, true)
3604
    endif
3605
endfunction
3606
3607
//===========================================================================
3608
function SelectUnitRemoveForPlayer takes unit whichUnit, player whichPlayer returns nothing
3609
    if (GetLocalPlayer() == whichPlayer) then
3610
        // Use only local code (no net traffic) within this block to avoid desyncs.
3611
        call SelectUnit(whichUnit, false)
3612
    endif
3613
endfunction
3614
3615
//===========================================================================
3616
function SetUnitLifeBJ takes unit whichUnit, real newValue returns nothing
3617
    call SetUnitState(whichUnit, UNIT_STATE_LIFE, RMaxBJ(0,newValue))
3618
endfunction
3619
3620
//===========================================================================
3621
function SetUnitManaBJ takes unit whichUnit, real newValue returns nothing
3622
    call SetUnitState(whichUnit, UNIT_STATE_MANA, RMaxBJ(0,newValue))
3623
endfunction
3624
3625
//===========================================================================
3626
function SetUnitLifePercentBJ takes unit whichUnit, real percent returns nothing
3627
    call SetUnitState(whichUnit, UNIT_STATE_LIFE, GetUnitState(whichUnit, UNIT_STATE_MAX_LIFE) * RMaxBJ(0,percent) * 0.01)
3628
endfunction
3629
3630
//===========================================================================
3631
function SetUnitManaPercentBJ takes unit whichUnit, real percent returns nothing
3632
    call SetUnitState(whichUnit, UNIT_STATE_MANA, GetUnitState(whichUnit, UNIT_STATE_MAX_MANA) * RMaxBJ(0,percent) * 0.01)
3633
endfunction
3634
3635
//===========================================================================
3636
function IsUnitDeadBJ takes unit whichUnit returns boolean
3637
    return GetUnitState(whichUnit, UNIT_STATE_LIFE) <= 0
3638
endfunction
3639
3640
//===========================================================================
3641
function IsUnitAliveBJ takes unit whichUnit returns boolean
3642
    return not IsUnitDeadBJ(whichUnit)
3643
endfunction
3644
3645
//===========================================================================
3646
function IsUnitGroupDeadBJEnum takes nothing returns nothing
3647
    if not IsUnitDeadBJ(GetEnumUnit()) then
3648
        set bj_isUnitGroupDeadResult = false
3649
    endif
3650
endfunction
3651
3652
//===========================================================================
3653
// Returns true if every unit of the group is dead.
3654
//
3655
function IsUnitGroupDeadBJ takes group g returns boolean
3656
    // If the user wants the group destroyed, remember that fact and clear
3657
    // the flag, in case it is used again in the callback.
3658
    local boolean wantDestroy = bj_wantDestroyGroup
3659
    set bj_wantDestroyGroup = false
3660
3661
    set bj_isUnitGroupDeadResult = true
3662
    call ForGroup(g, function IsUnitGroupDeadBJEnum)
3663
3664
    // If the user wants the group destroyed, do so now.
3665
    if (wantDestroy) then
3666
        call DestroyGroup(g)
3667
    endif
3668
    return bj_isUnitGroupDeadResult
3669
endfunction
3670
3671
//===========================================================================
3672
function IsUnitGroupEmptyBJEnum takes nothing returns nothing
3673
    set bj_isUnitGroupEmptyResult = false
3674
endfunction
3675
3676
//===========================================================================
3677
// Returns true if the group contains no units.
3678
//
3679
function IsUnitGroupEmptyBJ takes group g returns boolean
3680
    // If the user wants the group destroyed, remember that fact and clear
3681
    // the flag, in case it is used again in the callback.
3682
    local boolean wantDestroy = bj_wantDestroyGroup
3683
    set bj_wantDestroyGroup = false
3684
3685
    set bj_isUnitGroupEmptyResult = true
3686
    call ForGroup(g, function IsUnitGroupEmptyBJEnum)
3687
3688
    // If the user wants the group destroyed, do so now.
3689
    if (wantDestroy) then
3690
        call DestroyGroup(g)
3691
    endif
3692
    return bj_isUnitGroupEmptyResult
3693
endfunction
3694
3695
//===========================================================================
3696
function IsUnitGroupInRectBJEnum takes nothing returns nothing
3697
    if not RectContainsUnit(bj_isUnitGroupInRectRect, GetEnumUnit()) then
3698
        set bj_isUnitGroupInRectResult = false
3699
    endif
3700
endfunction
3701
3702
//===========================================================================
3703
// Returns true if every unit of the group is within the given rect.
3704
//
3705
function IsUnitGroupInRectBJ takes group g, rect r returns boolean
3706
    set bj_isUnitGroupInRectResult = true
3707
    set bj_isUnitGroupInRectRect = r
3708
    call ForGroup(g, function IsUnitGroupInRectBJEnum)
3709
    return bj_isUnitGroupInRectResult
3710
endfunction
3711
3712
//===========================================================================
3713
function IsUnitHiddenBJ takes unit whichUnit returns boolean
3714
    return IsUnitHidden(whichUnit)
3715
endfunction
3716
3717
//===========================================================================
3718
function ShowUnitHide takes unit whichUnit returns nothing
3719
    call ShowUnit(whichUnit, false)
3720
endfunction
3721
3722
//===========================================================================
3723
function ShowUnitShow takes unit whichUnit returns nothing
3724
    // Prevent dead heroes from being unhidden.
3725
    if (IsUnitType(whichUnit, UNIT_TYPE_HERO) and IsUnitDeadBJ(whichUnit)) then
3726
        return
3727
    endif
3728
3729
    call ShowUnit(whichUnit, true)
3730
endfunction
3731
3732
//===========================================================================
3733
function IssueHauntOrderAtLocBJFilter takes nothing returns boolean
3734
    return GetUnitTypeId(GetFilterUnit()) == 'ngol'
3735
endfunction
3736
3737
//===========================================================================
3738
function IssueHauntOrderAtLocBJ takes unit whichPeon, location loc returns boolean
3739
    local group g = null
3740
    local unit goldMine = null
3741
3742
    // Search for a gold mine within a 1-cell radius of the specified location.
3743
    set g = CreateGroup()
3744
    call GroupEnumUnitsInRangeOfLoc(g, loc, 2*bj_CELLWIDTH, filterIssueHauntOrderAtLocBJ)
3745
    set goldMine = FirstOfGroup(g)
3746
    call DestroyGroup(g)
3747
3748
    // If no mine was found, abort the request.
3749
    if (goldMine == null) then
3750
        return false
3751
    endif
3752
3753
    // Issue the Haunt Gold Mine order.
3754
    return IssueTargetOrderById(whichPeon, 'ugol', goldMine)
3755
endfunction
3756
3757
//===========================================================================
3758
function IssueBuildOrderByIdLocBJ takes unit whichPeon, integer unitId, location loc returns boolean
3759
    if (unitId == 'ugol') then
3760
        return IssueHauntOrderAtLocBJ(whichPeon, loc)
3761
    else
3762
        return IssueBuildOrderById(whichPeon, unitId, GetLocationX(loc), GetLocationY(loc))
3763
    endif
3764
endfunction
3765
3766
//===========================================================================
3767
function IssueTrainOrderByIdBJ takes unit whichUnit, integer unitId returns boolean
3768
    return IssueImmediateOrderById(whichUnit, unitId)
3769
endfunction
3770
3771
//===========================================================================
3772
function GroupTrainOrderByIdBJ takes group g, integer unitId returns boolean
3773
    return GroupImmediateOrderById(g, unitId)
3774
endfunction
3775
3776
//===========================================================================
3777
function IssueUpgradeOrderByIdBJ takes unit whichUnit, integer techId returns boolean
3778
    return IssueImmediateOrderById(whichUnit, techId)
3779
endfunction
3780
3781
//===========================================================================
3782
function GetAttackedUnitBJ takes nothing returns unit
3783
    return GetTriggerUnit()
3784
endfunction
3785
3786
//===========================================================================
3787
function SetUnitFlyHeightBJ takes unit whichUnit, real newHeight, real rate returns nothing
3788
    call SetUnitFlyHeight(whichUnit, newHeight, rate)
3789
endfunction
3790
3791
//===========================================================================
3792
function SetUnitTurnSpeedBJ takes unit whichUnit, real turnSpeed returns nothing
3793
    call SetUnitTurnSpeed(whichUnit, turnSpeed)
3794
endfunction
3795
3796
//===========================================================================
3797
function SetUnitPropWindowBJ takes unit whichUnit, real propWindow returns nothing
3798
    local real angle = propWindow
3799
    if (angle <= 0) then
3800
        set angle = 1
3801
    elseif (angle >= 360) then
3802
        set angle = 359
3803
    endif
3804
    set angle = angle * bj_DEGTORAD
3805
3806
    call SetUnitPropWindow(whichUnit, angle)
3807
endfunction
3808
3809
//===========================================================================
3810
function GetUnitPropWindowBJ takes unit whichUnit returns real
3811
    return GetUnitPropWindow(whichUnit) * bj_RADTODEG
3812
endfunction
3813
3814
//===========================================================================
3815
function GetUnitDefaultPropWindowBJ takes unit whichUnit returns real
3816
    return GetUnitDefaultPropWindow(whichUnit)
3817
endfunction
3818
3819
//===========================================================================
3820
function SetUnitBlendTimeBJ takes unit whichUnit, real blendTime returns nothing
3821
    call SetUnitBlendTime(whichUnit, blendTime)
3822
endfunction
3823
3824
//===========================================================================
3825
function SetUnitAcquireRangeBJ takes unit whichUnit, real acquireRange returns nothing
3826
    call SetUnitAcquireRange(whichUnit, acquireRange)
3827
endfunction
3828
3829
//===========================================================================
3830
function UnitSetCanSleepBJ takes unit whichUnit, boolean canSleep returns nothing
3831
    call UnitAddSleep(whichUnit, canSleep)
3832
endfunction
3833
3834
//===========================================================================
3835
function UnitCanSleepBJ takes unit whichUnit returns boolean
3836
    return UnitCanSleep(whichUnit)
3837
endfunction
3838
3839
//===========================================================================
3840
function UnitWakeUpBJ takes unit whichUnit returns nothing
3841
    call UnitWakeUp(whichUnit)
3842
endfunction
3843
3844
//===========================================================================
3845
function UnitIsSleepingBJ takes unit whichUnit returns boolean
3846
    return UnitIsSleeping(whichUnit)
3847
endfunction
3848
3849
//===========================================================================
3850
function WakePlayerUnitsEnum takes nothing returns nothing
3851
    call UnitWakeUp(GetEnumUnit())
3852
endfunction
3853
3854
//===========================================================================
3855
function WakePlayerUnits takes player whichPlayer returns nothing
3856
    local group g = CreateGroup()
3857
    call GroupEnumUnitsOfPlayer(g, whichPlayer, null)
3858
    call ForGroup(g, function WakePlayerUnitsEnum)
3859
    call DestroyGroup(g)
3860
endfunction
3861
3862
//===========================================================================
3863
function EnableCreepSleepBJ takes boolean enable returns nothing
3864
    call SetPlayerState(Player(PLAYER_NEUTRAL_AGGRESSIVE), PLAYER_STATE_NO_CREEP_SLEEP, IntegerTertiaryOp(enable, 0, 1))
3865
3866
    // If we're disabling, attempt to wake any already-sleeping creeps.
3867
    if (not enable) then
3868
        call WakePlayerUnits(Player(PLAYER_NEUTRAL_AGGRESSIVE))
3869
    endif
3870
endfunction
3871
3872
//===========================================================================
3873
function UnitGenerateAlarms takes unit whichUnit, boolean generate returns boolean
3874
    return UnitIgnoreAlarm(whichUnit, not generate)
3875
endfunction
3876
3877
//===========================================================================
3878
function DoesUnitGenerateAlarms takes unit whichUnit returns boolean
3879
    return not UnitIgnoreAlarmToggled(whichUnit)
3880
endfunction
3881
3882
//===========================================================================
3883
function PauseAllUnitsBJEnum takes nothing returns nothing
3884
    call PauseUnit( GetEnumUnit(), bj_pauseAllUnitsFlag )
3885
endfunction
3886
3887
//===========================================================================
3888
// Pause all units 
3889
function PauseAllUnitsBJ takes boolean pause returns nothing
3890
    local integer index
3891
    local player  indexPlayer
3892
    local group   g
3893
3894
    set bj_pauseAllUnitsFlag = pause
3895
    set g = CreateGroup()
3896
    set index = 0
3897
    loop
3898
        set indexPlayer = Player( index )
3899
3900
        // If this is a computer slot, pause/resume the AI.
3901
        if (GetPlayerController( indexPlayer ) == MAP_CONTROL_COMPUTER) then
3902
            call PauseCompAI( indexPlayer, pause )
3903
        endif
3904
3905
        // Enumerate and unpause every unit owned by the player.
3906
        call GroupEnumUnitsOfPlayer( g, indexPlayer, null )
3907
        call ForGroup( g, function PauseAllUnitsBJEnum )
3908
        call GroupClear( g )
3909
3910
        set index = index + 1
3911
        exitwhen index == bj_MAX_PLAYER_SLOTS
3912
    endloop
3913
    call DestroyGroup(g)
3914
endfunction
3915
3916
//===========================================================================
3917
function PauseUnitBJ takes boolean pause, unit whichUnit returns nothing
3918
    call PauseUnit(whichUnit, pause)
3919
endfunction
3920
3921
//===========================================================================
3922
function IsUnitPausedBJ takes unit whichUnit returns boolean
3923
    return IsUnitPaused(whichUnit)
3924
endfunction
3925
3926
//===========================================================================
3927
function UnitPauseTimedLifeBJ takes boolean flag, unit whichUnit returns nothing
3928
    call UnitPauseTimedLife(whichUnit, flag)
3929
endfunction
3930
3931
//===========================================================================
3932
function UnitApplyTimedLifeBJ takes real duration, integer buffId, unit whichUnit returns nothing
3933
    call UnitApplyTimedLife(whichUnit, buffId, duration)
3934
endfunction
3935
3936
//===========================================================================
3937
function UnitShareVisionBJ takes boolean share, unit whichUnit, player whichPlayer returns nothing
3938
    call UnitShareVision(whichUnit, whichPlayer, share)
3939
endfunction
3940
3941
//===========================================================================
3942
function UnitRemoveBuffsBJ takes integer buffType, unit whichUnit returns nothing
3943
    if (buffType == bj_REMOVEBUFFS_POSITIVE) then
3944
        call UnitRemoveBuffs(whichUnit, true, false)
3945
    elseif (buffType == bj_REMOVEBUFFS_NEGATIVE) then
3946
        call UnitRemoveBuffs(whichUnit, false, true)
3947
    elseif (buffType == bj_REMOVEBUFFS_ALL) then
3948
        call UnitRemoveBuffs(whichUnit, true, true)
3949
    elseif (buffType == bj_REMOVEBUFFS_NONTLIFE) then
3950
        call UnitRemoveBuffsEx(whichUnit, true, true, false, false, false, true, false)
3951
    else
3952
        // Unrecognized dispel type - ignore the request.
3953
    endif
3954
endfunction
3955
3956
//===========================================================================
3957
function UnitRemoveBuffsExBJ takes integer polarity, integer resist, unit whichUnit, boolean bTLife, boolean bAura returns nothing
3958
    local boolean bPos   = (polarity == bj_BUFF_POLARITY_EITHER) or (polarity == bj_BUFF_POLARITY_POSITIVE)
3959
    local boolean bNeg   = (polarity == bj_BUFF_POLARITY_EITHER) or (polarity == bj_BUFF_POLARITY_NEGATIVE)
3960
    local boolean bMagic = (resist == bj_BUFF_RESIST_BOTH) or (resist == bj_BUFF_RESIST_MAGIC)
3961
    local boolean bPhys  = (resist == bj_BUFF_RESIST_BOTH) or (resist == bj_BUFF_RESIST_PHYSICAL)
3962
3963
    call UnitRemoveBuffsEx(whichUnit, bPos, bNeg, bMagic, bPhys, bTLife, bAura, false)
3964
endfunction
3965
3966
//===========================================================================
3967
function UnitCountBuffsExBJ takes integer polarity, integer resist, unit whichUnit, boolean bTLife, boolean bAura returns integer
3968
    local boolean bPos   = (polarity == bj_BUFF_POLARITY_EITHER) or (polarity == bj_BUFF_POLARITY_POSITIVE)
3969
    local boolean bNeg   = (polarity == bj_BUFF_POLARITY_EITHER) or (polarity == bj_BUFF_POLARITY_NEGATIVE)
3970
    local boolean bMagic = (resist == bj_BUFF_RESIST_BOTH) or (resist == bj_BUFF_RESIST_MAGIC)
3971
    local boolean bPhys  = (resist == bj_BUFF_RESIST_BOTH) or (resist == bj_BUFF_RESIST_PHYSICAL)
3972
3973
    return UnitCountBuffsEx(whichUnit, bPos, bNeg, bMagic, bPhys, bTLife, bAura, false)
3974
endfunction
3975
3976
//===========================================================================
3977
function UnitRemoveAbilityBJ takes integer abilityId, unit whichUnit returns boolean
3978
    return UnitRemoveAbility(whichUnit, abilityId)
3979
endfunction
3980
3981
//===========================================================================
3982
function UnitAddAbilityBJ takes integer abilityId, unit whichUnit returns boolean
3983
    return UnitAddAbility(whichUnit, abilityId)
3984
endfunction
3985
3986
//===========================================================================
3987
function UnitRemoveTypeBJ takes unittype whichType, unit whichUnit returns boolean
3988
    return UnitRemoveType(whichUnit, whichType)
3989
endfunction
3990
3991
//===========================================================================
3992
function UnitAddTypeBJ takes unittype whichType, unit whichUnit returns boolean
3993
    return UnitAddType(whichUnit, whichType)
3994
endfunction
3995
3996
//===========================================================================
3997
function UnitMakeAbilityPermanentBJ takes boolean permanent, integer abilityId, unit whichUnit returns boolean
3998
    return UnitMakeAbilityPermanent(whichUnit, permanent, abilityId)
3999
endfunction
4000
4001
//===========================================================================
4002
function SetUnitExplodedBJ takes unit whichUnit, boolean exploded returns nothing
4003
    call SetUnitExploded(whichUnit, exploded)
4004
endfunction
4005
4006
//===========================================================================
4007
function ExplodeUnitBJ takes unit whichUnit returns nothing
4008
    call SetUnitExploded(whichUnit, true)
4009
    call KillUnit(whichUnit)
4010
endfunction
4011
4012
//===========================================================================
4013
function GetTransportUnitBJ takes nothing returns unit
4014
    return GetTransportUnit()
4015
endfunction
4016
4017
//===========================================================================
4018
function GetLoadedUnitBJ takes nothing returns unit
4019
    return GetLoadedUnit()
4020
endfunction
4021
4022
//===========================================================================
4023
function IsUnitInTransportBJ takes unit whichUnit, unit whichTransport returns boolean
4024
    return IsUnitInTransport(whichUnit, whichTransport)
4025
endfunction
4026
4027
//===========================================================================
4028
function IsUnitLoadedBJ takes unit whichUnit returns boolean
4029
    return IsUnitLoaded(whichUnit)
4030
endfunction
4031
4032
//===========================================================================
4033
function IsUnitIllusionBJ takes unit whichUnit returns boolean
4034
    return IsUnitIllusion(whichUnit)
4035
endfunction
4036
4037
//===========================================================================
4038
// This attempts to replace a unit with a new unit type by creating a new
4039
// unit of the desired type using the old unit's location, facing, etc.
4040
//
4041
function ReplaceUnitBJ takes unit whichUnit, integer newUnitId, integer unitStateMethod returns unit
4042
    local unit    oldUnit = whichUnit
4043
    local unit    newUnit
4044
    local boolean wasHidden
4045
    local integer index
4046
    local item    indexItem
4047
    local real    oldRatio
4048
4049
    // If we have bogus data, don't attempt the replace.
4050
    if (oldUnit == null) then
4051
        set bj_lastReplacedUnit = oldUnit
4052
        return oldUnit
4053
    endif
4054
4055
    // Hide the original unit.
4056
    set wasHidden = IsUnitHidden(oldUnit)
4057
    call ShowUnit(oldUnit, false)
4058
4059
    // Create the replacement unit.
4060
    if (newUnitId == 'ugol') then
4061
        set newUnit = CreateBlightedGoldmine(GetOwningPlayer(oldUnit), GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
4062
    else
4063
        set newUnit = CreateUnit(GetOwningPlayer(oldUnit), newUnitId, GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
4064
    endif
4065
4066
    // Set the unit's life and mana according to the requested method.
4067
    if (unitStateMethod == bj_UNIT_STATE_METHOD_RELATIVE) then
4068
        // Set the replacement's current/max life ratio to that of the old unit.
4069
        // If both units have mana, do the same for mana.
4070
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE) > 0) then
4071
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_LIFE) / GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE)
4072
            call SetUnitState(newUnit, UNIT_STATE_LIFE, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
4073
        endif
4074
4075
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_MANA) > 0) and (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
4076
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_MANA) / GetUnitState(oldUnit, UNIT_STATE_MAX_MANA)
4077
            call SetUnitState(newUnit, UNIT_STATE_MANA, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
4078
        endif
4079
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_ABSOLUTE) then
4080
        // Set the replacement's current life to that of the old unit.
4081
        // If the new unit has mana, do the same for mana.
4082
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(oldUnit, UNIT_STATE_LIFE))
4083
        if (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
4084
            call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(oldUnit, UNIT_STATE_MANA))
4085
        endif
4086
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_DEFAULTS) then
4087
        // The newly created unit should already have default life and mana.
4088
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_MAXIMUM) then
4089
        // Use max life and mana.
4090
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
4091
        call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
4092
    else
4093
        // Unrecognized unit state method - ignore the request.
4094
    endif
4095
4096
    // Mirror properties of the old unit onto the new unit.
4097
    //call PauseUnit(newUnit, IsUnitPaused(oldUnit))
4098
    call SetResourceAmount(newUnit, GetResourceAmount(oldUnit))
4099
4100
    // If both the old and new units are heroes, handle their hero info.
4101
    if (IsUnitType(oldUnit, UNIT_TYPE_HERO) and IsUnitType(newUnit, UNIT_TYPE_HERO)) then
4102
        call SetHeroXP(newUnit, GetHeroXP(oldUnit), false)
4103
4104
        set index = 0
4105
        loop
4106
            set indexItem = UnitItemInSlot(oldUnit, index)
4107
            if (indexItem != null) then
4108
                call UnitRemoveItem(oldUnit, indexItem)
4109
                call UnitAddItem(newUnit, indexItem)
4110
            endif
4111
4112
            set index = index + 1
4113
            exitwhen index >= bj_MAX_INVENTORY
4114
        endloop
4115
    endif
4116
4117
    // Remove or kill the original unit.  It is sometimes unsafe to remove
4118
    // hidden units, so kill the original unit if it was previously hidden.
4119
    if wasHidden then
4120
        call KillUnit(oldUnit)
4121
        call RemoveUnit(oldUnit)
4122
    else
4123
        call RemoveUnit(oldUnit)
4124
    endif
4125
4126
    set bj_lastReplacedUnit = newUnit
4127
    return newUnit
4128
endfunction
4129
4130
//===========================================================================
4131
function GetLastReplacedUnitBJ takes nothing returns unit
4132
    return bj_lastReplacedUnit
4133
endfunction
4134
4135
//===========================================================================
4136
function SetUnitPositionLocFacingBJ takes unit whichUnit, location loc, real facing returns nothing
4137
    call SetUnitPositionLoc(whichUnit, loc)
4138
    call SetUnitFacing(whichUnit, facing)
4139
endfunction
4140
4141
//===========================================================================
4142
function SetUnitPositionLocFacingLocBJ takes unit whichUnit, location loc, location lookAt returns nothing
4143
    call SetUnitPositionLoc(whichUnit, loc)
4144
    call SetUnitFacing(whichUnit, AngleBetweenPoints(loc, lookAt))
4145
endfunction
4146
4147
//===========================================================================
4148
function AddItemToStockBJ takes integer itemId, unit whichUnit, integer currentStock, integer stockMax returns nothing
4149
    call AddItemToStock(whichUnit, itemId, currentStock, stockMax)
4150
endfunction
4151
4152
//===========================================================================
4153
function AddUnitToStockBJ takes integer unitId, unit whichUnit, integer currentStock, integer stockMax returns nothing
4154
    call AddUnitToStock(whichUnit, unitId, currentStock, stockMax)
4155
endfunction
4156
4157
//===========================================================================
4158
function RemoveItemFromStockBJ takes integer itemId, unit whichUnit returns nothing
4159
    call RemoveItemFromStock(whichUnit, itemId)
4160
endfunction
4161
4162
//===========================================================================
4163
function RemoveUnitFromStockBJ takes integer unitId, unit whichUnit returns nothing
4164
    call RemoveUnitFromStock(whichUnit, unitId)
4165
endfunction
4166
4167
//===========================================================================
4168
function SetUnitUseFoodBJ takes boolean enable, unit whichUnit returns nothing
4169
    call SetUnitUseFood(whichUnit, enable)
4170
endfunction
4171
4172
//===========================================================================
4173
function UnitDamagePointLoc takes unit whichUnit, real delay, real radius, location loc, real amount, attacktype whichAttack, damagetype whichDamage returns boolean
4174
    return UnitDamagePoint(whichUnit, delay, radius, GetLocationX(loc), GetLocationY(loc), amount, true, false, whichAttack, whichDamage, WEAPON_TYPE_WHOKNOWS)
4175
endfunction
4176
4177
//===========================================================================
4178
function UnitDamageTargetBJ takes unit whichUnit, unit target, real amount, attacktype whichAttack, damagetype whichDamage returns boolean
4179
    return UnitDamageTarget(whichUnit, target, amount, true, false, whichAttack, whichDamage, WEAPON_TYPE_WHOKNOWS)
4180
endfunction
4181
4182
4183
4184
//***************************************************************************
4185
//*
4186
//*  Destructable Utility Functions
4187
//*
4188
//***************************************************************************
4189
4190
//===========================================================================
4191
function CreateDestructableLoc takes integer objectid, location loc, real facing, real scale, integer variation returns destructable
4192
    set bj_lastCreatedDestructable = CreateDestructable(objectid, GetLocationX(loc), GetLocationY(loc), facing, scale, variation)
4193
    return bj_lastCreatedDestructable
4194
endfunction
4195
4196
//===========================================================================
4197
function CreateDeadDestructableLocBJ takes integer objectid, location loc, real facing, real scale, integer variation returns destructable
4198
    set bj_lastCreatedDestructable = CreateDeadDestructable(objectid, GetLocationX(loc), GetLocationY(loc), facing, scale, variation)
4199
    return bj_lastCreatedDestructable
4200
endfunction
4201
4202
//===========================================================================
4203
function GetLastCreatedDestructable takes nothing returns destructable
4204
    return bj_lastCreatedDestructable
4205
endfunction
4206
4207
//===========================================================================
4208
function ShowDestructableBJ takes boolean flag, destructable d returns nothing
4209
    call ShowDestructable(d, flag)
4210
endfunction
4211
4212
//===========================================================================
4213
function SetDestructableInvulnerableBJ takes destructable d, boolean flag returns nothing
4214
    call SetDestructableInvulnerable(d, flag)
4215
endfunction
4216
4217
//===========================================================================
4218
function IsDestructableInvulnerableBJ takes destructable d returns boolean
4219
    return IsDestructableInvulnerable(d)
4220
endfunction
4221
4222
//===========================================================================
4223
function GetDestructableLoc takes destructable whichDestructable returns location
4224
    return Location(GetDestructableX(whichDestructable), GetDestructableY(whichDestructable))
4225
endfunction
4226
4227
//===========================================================================
4228
function EnumDestructablesInRectAll takes rect r, code actionFunc returns nothing
4229
    call EnumDestructablesInRect(r, null, actionFunc)
4230
endfunction
4231
4232
//===========================================================================
4233
function EnumDestructablesInCircleBJFilter takes nothing returns boolean
4234
    local location destLoc = GetDestructableLoc(GetFilterDestructable())
4235
    local boolean result
4236
4237
    set result = DistanceBetweenPoints(destLoc, bj_enumDestructableCenter) <= bj_enumDestructableRadius
4238
    call RemoveLocation(destLoc)
4239
    return result
4240
endfunction
4241
4242
//===========================================================================
4243
function IsDestructableDeadBJ takes destructable d returns boolean
4244
    return GetDestructableLife(d) <= 0
4245
endfunction
4246
4247
//===========================================================================
4248
function IsDestructableAliveBJ takes destructable d returns boolean
4249
    return not IsDestructableDeadBJ(d)
4250
endfunction
4251
4252
//===========================================================================
4253
// See GroupPickRandomUnitEnum for the details of this algorithm.
4254
//
4255
function RandomDestructableInRectBJEnum takes nothing returns nothing
4256
    set bj_destRandomConsidered = bj_destRandomConsidered + 1
4257
    if (GetRandomInt(1,bj_destRandomConsidered) == 1) then
4258
        set bj_destRandomCurrentPick = GetEnumDestructable()
4259
    endif
4260
endfunction
4261
4262
//===========================================================================
4263
// Picks a random destructable from within a rect, matching a condition
4264
//
4265
function RandomDestructableInRectBJ takes rect r, boolexpr filter returns destructable
4266
    set bj_destRandomConsidered = 0
4267
    set bj_destRandomCurrentPick = null
4268
    call EnumDestructablesInRect(r, filter, function RandomDestructableInRectBJEnum)
4269
    call DestroyBoolExpr(filter)
4270
    return bj_destRandomCurrentPick
4271
endfunction
4272
4273
//===========================================================================
4274
// Picks a random destructable from within a rect
4275
//
4276
function RandomDestructableInRectSimpleBJ takes rect r returns destructable
4277
    return RandomDestructableInRectBJ(r, null)
4278
endfunction
4279
4280
//===========================================================================
4281
// Enumerates within a rect, with a filter to narrow the enumeration down
4282
// objects within a circular area.
4283
//
4284
function EnumDestructablesInCircleBJ takes real radius, location loc, code actionFunc returns nothing
4285
    local rect r
4286
4287
    if (radius >= 0) then
4288
        set bj_enumDestructableCenter = loc
4289
        set bj_enumDestructableRadius = radius
4290
        set r = GetRectFromCircleBJ(loc, radius)
4291
        call EnumDestructablesInRect(r, filterEnumDestructablesInCircleBJ, actionFunc)
4292
        call RemoveRect(r)
4293
    endif
4294
endfunction
4295
4296
//===========================================================================
4297
function SetDestructableLifePercentBJ takes destructable d, real percent returns nothing
4298
    call SetDestructableLife(d, GetDestructableMaxLife(d) * percent * 0.01)
4299
endfunction
4300
4301
//===========================================================================
4302
function SetDestructableMaxLifeBJ takes destructable d, real max returns nothing
4303
    call SetDestructableMaxLife(d, max)
4304
endfunction
4305
4306
//===========================================================================
4307
function ModifyGateBJ takes integer gateOperation, destructable d returns nothing
4308
    if (gateOperation == bj_GATEOPERATION_CLOSE) then
4309
        if (GetDestructableLife(d) <= 0) then
4310
            call DestructableRestoreLife(d, GetDestructableMaxLife(d), true)
4311
        endif
4312
        call SetDestructableAnimation(d, "stand")
4313
    elseif (gateOperation == bj_GATEOPERATION_OPEN) then
4314
        if (GetDestructableLife(d) > 0) then
4315
            call KillDestructable(d)
4316
        endif
4317
        call SetDestructableAnimation(d, "death alternate")
4318
    elseif (gateOperation == bj_GATEOPERATION_DESTROY) then
4319
        if (GetDestructableLife(d) > 0) then
4320
            call KillDestructable(d)
4321
        endif
4322
        call SetDestructableAnimation(d, "death")
4323
    else
4324
        // Unrecognized gate state - ignore the request.
4325
    endif
4326
endfunction
4327
4328
//===========================================================================
4329
// Determine the elevator's height from its occlusion height.
4330
//
4331
function GetElevatorHeight takes destructable d returns integer
4332
    local integer height
4333
4334
    set height = 1 + R2I(GetDestructableOccluderHeight(d) / bj_CLIFFHEIGHT)
4335
    if (height < 1) or (height > 3) then
4336
        set height = 1
4337
    endif
4338
    return height
4339
endfunction
4340
4341
//===========================================================================
4342
// To properly animate an elevator, we must know not only what height we
4343
// want to change to, but also what height we are currently at.  This code
4344
// determines the elevator's current height from its occlusion height.
4345
// Arbitrarily changing an elevator's occlusion height is thus inadvisable.
4346
//
4347
function ChangeElevatorHeight takes destructable d, integer newHeight returns nothing
4348
    local integer oldHeight
4349
4350
    // Cap the new height within the supported range.
4351
    set newHeight = IMaxBJ(1, newHeight)
4352
    set newHeight = IMinBJ(3, newHeight)
4353
4354
    // Find out what height the elevator is already at.
4355
    set oldHeight = GetElevatorHeight(d)
4356
4357
    // Set the elevator's occlusion height.
4358
    call SetDestructableOccluderHeight(d, bj_CLIFFHEIGHT*(newHeight-1))
4359
4360
    if (newHeight == 1) then
4361
        if (oldHeight == 2) then
4362
            call SetDestructableAnimation(d, "birth")
4363
            call QueueDestructableAnimation(d, "stand")
4364
        elseif (oldHeight == 3) then
4365
            call SetDestructableAnimation(d, "birth third")
4366
            call QueueDestructableAnimation(d, "stand")
4367
        else
4368
            // Unrecognized old height - snap to new height.
4369
            call SetDestructableAnimation(d, "stand")
4370
        endif
4371
    elseif (newHeight == 2) then
4372
        if (oldHeight == 1) then
4373
            call SetDestructableAnimation(d, "death")
4374
            call QueueDestructableAnimation(d, "stand second")
4375
        elseif (oldHeight == 3) then
4376
            call SetDestructableAnimation(d, "birth second")
4377
            call QueueDestructableAnimation(d, "stand second")
4378
        else
4379
            // Unrecognized old height - snap to new height.
4380
            call SetDestructableAnimation(d, "stand second")
4381
        endif
4382
    elseif (newHeight == 3) then
4383
        if (oldHeight == 1) then
4384
            call SetDestructableAnimation(d, "death third")
4385
            call QueueDestructableAnimation(d, "stand third")
4386
        elseif (oldHeight == 2) then
4387
            call SetDestructableAnimation(d, "death second")
4388
            call QueueDestructableAnimation(d, "stand third")
4389
        else
4390
            // Unrecognized old height - snap to new height.
4391
            call SetDestructableAnimation(d, "stand third")
4392
        endif
4393
    else
4394
        // Unrecognized new height - ignore the request.
4395
    endif
4396
endfunction
4397
4398
//===========================================================================
4399
// Grab the unit and throw his own coords in his face, forcing him to push
4400
// and shove until he finds a spot where noone will bother him.
4401
//
4402
function NudgeUnitsInRectEnum takes nothing returns nothing
4403
    local unit nudgee = GetEnumUnit()
4404
4405
    call SetUnitPosition(nudgee, GetUnitX(nudgee), GetUnitY(nudgee))
4406
endfunction
4407
4408
//===========================================================================
4409
function NudgeItemsInRectEnum takes nothing returns nothing
4410
    local item nudgee = GetEnumItem()
4411
4412
    call SetItemPosition(nudgee, GetItemX(nudgee), GetItemY(nudgee))
4413
endfunction
4414
4415
//===========================================================================
4416
// Nudge the items and units within a given rect ever so gently, so as to
4417
// encourage them to find locations where they can peacefully coexist with
4418
// pathing restrictions and live happy, fruitful lives.
4419
//
4420
function NudgeObjectsInRect takes rect nudgeArea returns nothing
4421
    local group        g
4422
4423
    set g = CreateGroup()
4424
    call GroupEnumUnitsInRect(g, nudgeArea, null)
4425
    call ForGroup(g, function NudgeUnitsInRectEnum)
4426
    call DestroyGroup(g)
4427
4428
    call EnumItemsInRect(nudgeArea, null, function NudgeItemsInRectEnum)
4429
endfunction
4430
4431
//===========================================================================
4432
function NearbyElevatorExistsEnum takes nothing returns nothing
4433
    local destructable d     = GetEnumDestructable()
4434
    local integer      dType = GetDestructableTypeId(d)
4435
4436
    if (dType == bj_ELEVATOR_CODE01) or (dType == bj_ELEVATOR_CODE02) then
4437
        set bj_elevatorNeighbor = d
4438
    endif
4439
endfunction
4440
4441
//===========================================================================
4442
function NearbyElevatorExists takes real x, real y returns boolean
4443
    local real findThreshold = 32
4444
    local rect r
4445
4446
    // If another elevator is overlapping this one, ignore the wall.
4447
    set r = Rect(x - findThreshold, y - findThreshold, x + findThreshold, y + findThreshold)
4448
    set bj_elevatorNeighbor = null
4449
    call EnumDestructablesInRect(r, null, function NearbyElevatorExistsEnum)
4450
    call RemoveRect(r)
4451
4452
    return bj_elevatorNeighbor != null
4453
endfunction
4454
4455
//===========================================================================
4456
function FindElevatorWallBlockerEnum takes nothing returns nothing
4457
    set bj_elevatorWallBlocker = GetEnumDestructable()
4458
endfunction
4459
4460
//===========================================================================
4461
// This toggles pathing on or off for one wall of an elevator by killing
4462
// or reviving a pathing blocker at the appropriate location (and creating
4463
// the pathing blocker in the first place, if it does not yet exist).
4464
//
4465
function ChangeElevatorWallBlocker takes real x, real y, real facing, boolean open returns nothing
4466
    local destructable blocker = null
4467
    local real         findThreshold = 32
4468
    local real         nudgeLength   = 4.25 * bj_CELLWIDTH
4469
    local real         nudgeWidth    = 1.25 * bj_CELLWIDTH
4470
    local rect         r
4471
4472
    // Search for the pathing blocker within the general area.
4473
    set r = Rect(x - findThreshold, y - findThreshold, x + findThreshold, y + findThreshold)
4474
    set bj_elevatorWallBlocker = null
4475
    call EnumDestructablesInRect(r, null, function FindElevatorWallBlockerEnum)
4476
    call RemoveRect(r)
4477
    set blocker = bj_elevatorWallBlocker
4478
4479
    // Ensure that the blocker exists.
4480
    if (blocker == null) then
4481
        set blocker = CreateDeadDestructable(bj_ELEVATOR_BLOCKER_CODE, x, y, facing, 1, 0)
4482
    elseif (GetDestructableTypeId(blocker) != bj_ELEVATOR_BLOCKER_CODE) then
4483
        // If a different destructible exists in the blocker's spot, ignore
4484
        // the request.  (Two destructibles cannot occupy the same location
4485
        // on the map, so we cannot create an elevator blocker here.)
4486
        return
4487
    endif
4488
4489
    if (open) then
4490
        // Ensure that the blocker is dead.
4491
        if (GetDestructableLife(blocker) > 0) then
4492
            call KillDestructable(blocker)
4493
        endif
4494
    else
4495
        // Ensure that the blocker is alive.
4496
        if (GetDestructableLife(blocker) <= 0) then
4497
            call DestructableRestoreLife(blocker, GetDestructableMaxLife(blocker), false)
4498
        endif
4499
4500
        // Nudge any objects standing in the blocker's way.
4501
        if (facing == 0) then
4502
            set r = Rect(x - nudgeWidth/2, y - nudgeLength/2, x + nudgeWidth/2, y + nudgeLength/2)
4503
            call NudgeObjectsInRect(r)
4504
            call RemoveRect(r)
4505
        elseif (facing == 90) then
4506
            set r = Rect(x - nudgeLength/2, y - nudgeWidth/2, x + nudgeLength/2, y + nudgeWidth/2)
4507
            call NudgeObjectsInRect(r)
4508
            call RemoveRect(r)
4509
        else
4510
            // Unrecognized blocker angle - don't nudge anything.
4511
        endif
4512
    endif
4513
endfunction
4514
4515
//===========================================================================
4516
function ChangeElevatorWalls takes boolean open, integer walls, destructable d returns nothing
4517
    local real x = GetDestructableX(d)
4518
    local real y = GetDestructableY(d)
4519
    local real distToBlocker = 192
4520
    local real distToNeighbor = 256
4521
4522
    if (walls == bj_ELEVATOR_WALL_TYPE_ALL) or (walls == bj_ELEVATOR_WALL_TYPE_EAST) then
4523
        if (not NearbyElevatorExists(x + distToNeighbor, y)) then
4524
            call ChangeElevatorWallBlocker(x + distToBlocker, y, 0, open)
4525
        endif
4526
    endif
4527
4528
    if (walls == bj_ELEVATOR_WALL_TYPE_ALL) or (walls == bj_ELEVATOR_WALL_TYPE_NORTH) then
4529
        if (not NearbyElevatorExists(x, y + distToNeighbor)) then
4530
            call ChangeElevatorWallBlocker(x, y + distToBlocker, 90, open)
4531
        endif
4532
    endif
4533
4534
    if (walls == bj_ELEVATOR_WALL_TYPE_ALL) or (walls == bj_ELEVATOR_WALL_TYPE_SOUTH) then
4535
        if (not NearbyElevatorExists(x, y - distToNeighbor)) then
4536
            call ChangeElevatorWallBlocker(x, y - distToBlocker, 90, open)
4537
        endif
4538
    endif
4539
4540
    if (walls == bj_ELEVATOR_WALL_TYPE_ALL) or (walls == bj_ELEVATOR_WALL_TYPE_WEST) then
4541
        if (not NearbyElevatorExists(x - distToNeighbor, y)) then
4542
            call ChangeElevatorWallBlocker(x - distToBlocker, y, 0, open)
4543
        endif
4544
    endif
4545
endfunction
4546
4547
4548
4549
//***************************************************************************
4550
//*
4551
//*  Neutral Building Utility Functions
4552
//*
4553
//***************************************************************************
4554
4555
//===========================================================================
4556
function WaygateActivateBJ takes boolean activate, unit waygate returns nothing
4557
    call WaygateActivate(waygate, activate)
4558
endfunction
4559
4560
//===========================================================================
4561
function WaygateIsActiveBJ takes unit waygate returns boolean
4562
    return WaygateIsActive(waygate)
4563
endfunction
4564
4565
//===========================================================================
4566
function WaygateSetDestinationLocBJ takes unit waygate, location loc returns nothing
4567
    call WaygateSetDestination(waygate, GetLocationX(loc), GetLocationY(loc))
4568
endfunction
4569
4570
//===========================================================================
4571
function WaygateGetDestinationLocBJ takes unit waygate returns location
4572
    return Location(WaygateGetDestinationX(waygate), WaygateGetDestinationY(waygate))
4573
endfunction
4574
4575
//===========================================================================
4576
function UnitSetUsesAltIconBJ takes boolean flag, unit whichUnit returns nothing
4577
    call UnitSetUsesAltIcon(whichUnit, flag)
4578
endfunction
4579
4580
4581
4582
//***************************************************************************
4583
//*
4584
//*  UI Utility Functions
4585
//*
4586
//***************************************************************************
4587
4588
//===========================================================================
4589
function ForceUIKeyBJ takes player whichPlayer, string key returns nothing
4590
    if (GetLocalPlayer() == whichPlayer) then
4591
        // Use only local code (no net traffic) within this block to avoid desyncs.
4592
        call ForceUIKey(key)
4593
    endif
4594
endfunction
4595
4596
//===========================================================================
4597
function ForceUICancelBJ takes player whichPlayer returns nothing
4598
    if (GetLocalPlayer() == whichPlayer) then
4599
        // Use only local code (no net traffic) within this block to avoid desyncs.
4600
        call ForceUICancel()
4601
    endif
4602
endfunction
4603
4604
4605
4606
//***************************************************************************
4607
//*
4608
//*  Group and Force Utility Functions
4609
//*
4610
//***************************************************************************
4611
4612
//===========================================================================
4613
function ForGroupBJ takes group whichGroup, code callback returns nothing
4614
    // If the user wants the group destroyed, remember that fact and clear
4615
    // the flag, in case it is used again in the callback.
4616
    local boolean wantDestroy = bj_wantDestroyGroup
4617
    set bj_wantDestroyGroup = false
4618
4619
    call ForGroup(whichGroup, callback)
4620
4621
    // If the user wants the group destroyed, do so now.
4622
    if (wantDestroy) then
4623
        call DestroyGroup(whichGroup)
4624
    endif
4625
endfunction
4626
4627
//===========================================================================
4628
function GroupAddUnitSimple takes unit whichUnit, group whichGroup returns nothing
4629
    call GroupAddUnit(whichGroup, whichUnit)
4630
endfunction
4631
4632
//===========================================================================
4633
function GroupRemoveUnitSimple takes unit whichUnit, group whichGroup returns nothing
4634
    call GroupRemoveUnit(whichGroup, whichUnit)
4635
endfunction
4636
4637
//===========================================================================
4638
function GroupAddGroupEnum takes nothing returns nothing
4639
    call GroupAddUnit(bj_groupAddGroupDest, GetEnumUnit())
4640
endfunction
4641
4642
//===========================================================================
4643
function GroupAddGroup takes group sourceGroup, group destGroup returns nothing
4644
    // If the user wants the group destroyed, remember that fact and clear
4645
    // the flag, in case it is used again in the callback.
4646
    local boolean wantDestroy = bj_wantDestroyGroup
4647
    set bj_wantDestroyGroup = false
4648
4649
    set bj_groupAddGroupDest = destGroup
4650
    call ForGroup(sourceGroup, function GroupAddGroupEnum)
4651
4652
    // If the user wants the group destroyed, do so now.
4653
    if (wantDestroy) then
4654
        call DestroyGroup(sourceGroup)
4655
    endif
4656
endfunction
4657
4658
//===========================================================================
4659
function GroupRemoveGroupEnum takes nothing returns nothing
4660
    call GroupRemoveUnit(bj_groupRemoveGroupDest, GetEnumUnit())
4661
endfunction
4662
4663
//===========================================================================
4664
function GroupRemoveGroup takes group sourceGroup, group destGroup returns nothing
4665
    // If the user wants the group destroyed, remember that fact and clear
4666
    // the flag, in case it is used again in the callback.
4667
    local boolean wantDestroy = bj_wantDestroyGroup
4668
    set bj_wantDestroyGroup = false
4669
4670
    set bj_groupRemoveGroupDest = destGroup
4671
    call ForGroup(sourceGroup, function GroupRemoveGroupEnum)
4672
4673
    // If the user wants the group destroyed, do so now.
4674
    if (wantDestroy) then
4675
        call DestroyGroup(sourceGroup)
4676
    endif
4677
endfunction
4678
4679
//===========================================================================
4680
function ForceAddPlayerSimple takes player whichPlayer, force whichForce returns nothing
4681
    call ForceAddPlayer(whichForce, whichPlayer)
4682
endfunction
4683
4684
//===========================================================================
4685
function ForceRemovePlayerSimple takes player whichPlayer, force whichForce returns nothing
4686
    call ForceRemovePlayer(whichForce, whichPlayer)
4687
endfunction
4688
4689
//===========================================================================
4690
// Consider each unit, one at a time, keeping a "current pick".   Once all units
4691
// are considered, this "current pick" will be the resulting random unit.
4692
//
4693
// The chance of picking a given unit over the "current pick" is 1/N, where N is
4694
// the number of units considered thusfar (including the current consideration).
4695
//
4696
function GroupPickRandomUnitEnum takes nothing returns nothing
4697
    set bj_groupRandomConsidered = bj_groupRandomConsidered + 1
4698
    if (GetRandomInt(1,bj_groupRandomConsidered) == 1) then
4699
        set bj_groupRandomCurrentPick = GetEnumUnit()
4700
    endif
4701
endfunction
4702
4703
//===========================================================================
4704
// Picks a random unit from a group.
4705
//
4706
function GroupPickRandomUnit takes group whichGroup returns unit
4707
    // If the user wants the group destroyed, remember that fact and clear
4708
    // the flag, in case it is used again in the callback.
4709
    local boolean wantDestroy = bj_wantDestroyGroup
4710
    set bj_wantDestroyGroup = false
4711
4712
    set bj_groupRandomConsidered = 0
4713
    set bj_groupRandomCurrentPick = null
4714
    call ForGroup(whichGroup, function GroupPickRandomUnitEnum)
4715
4716
    // If the user wants the group destroyed, do so now.
4717
    if (wantDestroy) then
4718
        call DestroyGroup(whichGroup)
4719
    endif
4720
    return bj_groupRandomCurrentPick
4721
endfunction
4722
4723
//===========================================================================
4724
// See GroupPickRandomUnitEnum for the details of this algorithm.
4725
//
4726
function ForcePickRandomPlayerEnum takes nothing returns nothing
4727
    set bj_forceRandomConsidered = bj_forceRandomConsidered + 1
4728
    if (GetRandomInt(1,bj_forceRandomConsidered) == 1) then
4729
        set bj_forceRandomCurrentPick = GetEnumPlayer()
4730
    endif
4731
endfunction
4732
4733
//===========================================================================
4734
// Picks a random player from a force.
4735
//
4736
function ForcePickRandomPlayer takes force whichForce returns player
4737
    set bj_forceRandomConsidered = 0
4738
    set bj_forceRandomCurrentPick = null
4739
    call ForForce(whichForce, function ForcePickRandomPlayerEnum)
4740
    return bj_forceRandomCurrentPick
4741
endfunction
4742
4743
//===========================================================================
4744
function EnumUnitsSelected takes player whichPlayer, boolexpr enumFilter, code enumAction returns nothing
4745
    local group g = CreateGroup()
4746
    call SyncSelections()
4747
    call GroupEnumUnitsSelected(g, whichPlayer, enumFilter)
4748
    call DestroyBoolExpr(enumFilter)
4749
    call ForGroup(g, enumAction)
4750
    call DestroyGroup(g)
4751
endfunction
4752
4753
//===========================================================================
4754
function GetUnitsInRectMatching takes rect r, boolexpr filter returns group
4755
    local group g = CreateGroup()
4756
    call GroupEnumUnitsInRect(g, r, filter)
4757
    call DestroyBoolExpr(filter)
4758
    return g
4759
endfunction
4760
4761
//===========================================================================
4762
function GetUnitsInRectAll takes rect r returns group
4763
    return GetUnitsInRectMatching(r, null)
4764
endfunction
4765
4766
//===========================================================================
4767
function GetUnitsInRectOfPlayerFilter takes nothing returns boolean
4768
    return GetOwningPlayer(GetFilterUnit()) == bj_groupEnumOwningPlayer
4769
endfunction
4770
4771
//===========================================================================
4772
function GetUnitsInRectOfPlayer takes rect r, player whichPlayer returns group
4773
    local group g = CreateGroup()
4774
    set bj_groupEnumOwningPlayer = whichPlayer
4775
    call GroupEnumUnitsInRect(g, r, filterGetUnitsInRectOfPlayer)
4776
    return g
4777
endfunction
4778
4779
//===========================================================================
4780
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
4781
    local group g = CreateGroup()
4782
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
4783
    call DestroyBoolExpr(filter)
4784
    return g
4785
endfunction
4786
4787
//===========================================================================
4788
function GetUnitsInRangeOfLocAll takes real radius, location whichLocation returns group
4789
    return GetUnitsInRangeOfLocMatching(radius, whichLocation, null)
4790
endfunction
4791
4792
//===========================================================================
4793
function GetUnitsOfTypeIdAllFilter takes nothing returns boolean
4794
    return GetUnitTypeId(GetFilterUnit()) == bj_groupEnumTypeId
4795
endfunction
4796
4797
//===========================================================================
4798
function GetUnitsOfTypeIdAll takes integer unitid returns group
4799
    local group   result = CreateGroup()
4800
    local group   g      = CreateGroup()
4801
    local integer index
4802
4803
    set index = 0
4804
    loop
4805
        set bj_groupEnumTypeId = unitid
4806
        call GroupClear(g)
4807
        call GroupEnumUnitsOfPlayer(g, Player(index), filterGetUnitsOfTypeIdAll)
4808
        call GroupAddGroup(g, result)
4809
4810
        set index = index + 1
4811
        exitwhen index == bj_MAX_PLAYER_SLOTS
4812
    endloop
4813
    call DestroyGroup(g)
4814
4815
    return result
4816
endfunction
4817
4818
//===========================================================================
4819
function GetUnitsOfPlayerMatching takes player whichPlayer, boolexpr filter returns group
4820
    local group g = CreateGroup()
4821
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filter)
4822
    call DestroyBoolExpr(filter)
4823
    return g
4824
endfunction
4825
4826
//===========================================================================
4827
function GetUnitsOfPlayerAll takes player whichPlayer returns group
4828
    return GetUnitsOfPlayerMatching(whichPlayer, null)
4829
endfunction
4830
4831
//===========================================================================
4832
function GetUnitsOfPlayerAndTypeIdFilter takes nothing returns boolean
4833
    return GetUnitTypeId(GetFilterUnit()) == bj_groupEnumTypeId
4834
endfunction
4835
4836
//===========================================================================
4837
function GetUnitsOfPlayerAndTypeId takes player whichPlayer, integer unitid returns group
4838
    local group g = CreateGroup()
4839
    set bj_groupEnumTypeId = unitid
4840
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filterGetUnitsOfPlayerAndTypeId)
4841
    return g
4842
endfunction
4843
4844
//===========================================================================
4845
function GetUnitsSelectedAll takes player whichPlayer returns group
4846
    local group g = CreateGroup()
4847
    call SyncSelections()
4848
    call GroupEnumUnitsSelected(g, whichPlayer, null)
4849
    return g
4850
endfunction
4851
4852
//===========================================================================
4853
function GetForceOfPlayer takes player whichPlayer returns force
4854
    local force f = CreateForce()
4855
    call ForceAddPlayer(f, whichPlayer)
4856
    return f
4857
endfunction
4858
4859
//===========================================================================
4860
function GetPlayersAll takes nothing returns force
4861
    return bj_FORCE_ALL_PLAYERS
4862
endfunction
4863
4864
//===========================================================================
4865
function GetPlayersByMapControl takes mapcontrol whichControl returns force
4866
    local force f = CreateForce()
4867
    local integer playerIndex
4868
    local player  indexPlayer
4869
4870
    set playerIndex = 0
4871
    loop
4872
        set indexPlayer = Player(playerIndex)
4873
        if GetPlayerController(indexPlayer) == whichControl then
4874
            call ForceAddPlayer(f, indexPlayer)
4875
        endif
4876
4877
        set playerIndex = playerIndex + 1
4878
        exitwhen playerIndex == bj_MAX_PLAYER_SLOTS
4879
    endloop
4880
4881
    return f
4882
endfunction
4883
4884
//===========================================================================
4885
function GetPlayersAllies takes player whichPlayer returns force
4886
    local force f = CreateForce()
4887
    call ForceEnumAllies(f, whichPlayer, null)
4888
    return f
4889
endfunction
4890
4891
//===========================================================================
4892
function GetPlayersEnemies takes player whichPlayer returns force
4893
    local force f = CreateForce()
4894
    call ForceEnumEnemies(f, whichPlayer, null)
4895
    return f
4896
endfunction
4897
4898
//===========================================================================
4899
function GetPlayersMatching takes boolexpr filter returns force
4900
    local force f = CreateForce()
4901
    call ForceEnumPlayers(f, filter)
4902
    call DestroyBoolExpr(filter)
4903
    return f
4904
endfunction
4905
4906
//===========================================================================
4907
function CountUnitsInGroupEnum takes nothing returns nothing
4908
    set bj_groupCountUnits = bj_groupCountUnits + 1
4909
endfunction
4910
4911
//===========================================================================
4912
function CountUnitsInGroup takes group g returns integer
4913
    // If the user wants the group destroyed, remember that fact and clear
4914
    // the flag, in case it is used again in the callback.
4915
    local boolean wantDestroy = bj_wantDestroyGroup
4916
    set bj_wantDestroyGroup = false
4917
4918
    set bj_groupCountUnits = 0
4919
    call ForGroup(g, function CountUnitsInGroupEnum)
4920
4921
    // If the user wants the group destroyed, do so now.
4922
    if (wantDestroy) then
4923
        call DestroyGroup(g)
4924
    endif
4925
    return bj_groupCountUnits
4926
endfunction
4927
4928
//===========================================================================
4929
function CountPlayersInForceEnum takes nothing returns nothing
4930
    set bj_forceCountPlayers = bj_forceCountPlayers + 1
4931
endfunction
4932
4933
//===========================================================================
4934
function CountPlayersInForceBJ takes force f returns integer
4935
    set bj_forceCountPlayers = 0
4936
    call ForForce(f, function CountPlayersInForceEnum)
4937
    return bj_forceCountPlayers
4938
endfunction
4939
4940
//===========================================================================
4941
function GetRandomSubGroupEnum takes nothing returns nothing
4942
    if (bj_randomSubGroupWant > 0) then
4943
        if (bj_randomSubGroupWant >= bj_randomSubGroupTotal) or (GetRandomReal(0,1) < bj_randomSubGroupChance) then
4944
            // We either need every remaining unit, or the unit passed its chance check.
4945
            call GroupAddUnit(bj_randomSubGroupGroup, GetEnumUnit())
4946
            set bj_randomSubGroupWant = bj_randomSubGroupWant - 1
4947
        endif
4948
    endif
4949
    set bj_randomSubGroupTotal = bj_randomSubGroupTotal - 1
4950
endfunction
4951
4952
//===========================================================================
4953
function GetRandomSubGroup takes integer count, group sourceGroup returns group
4954
    local group g = CreateGroup()
4955
4956
    set bj_randomSubGroupGroup = g
4957
    set bj_randomSubGroupWant  = count
4958
    set bj_randomSubGroupTotal = CountUnitsInGroup(sourceGroup)
4959
4960
    if (bj_randomSubGroupWant <= 0 or bj_randomSubGroupTotal <= 0) then
4961
        return g
4962
    endif
4963
4964
    set bj_randomSubGroupChance = I2R(bj_randomSubGroupWant) / I2R(bj_randomSubGroupTotal)
4965
    call ForGroup(sourceGroup, function GetRandomSubGroupEnum)
4966
    return g
4967
endfunction
4968
4969
//===========================================================================
4970
function LivingPlayerUnitsOfTypeIdFilter takes nothing returns boolean
4971
    local unit filterUnit = GetFilterUnit()
4972
    return IsUnitAliveBJ(filterUnit) and GetUnitTypeId(filterUnit) == bj_livingPlayerUnitsTypeId
4973
endfunction
4974
4975
//===========================================================================
4976
function CountLivingPlayerUnitsOfTypeId takes integer unitId, player whichPlayer returns integer
4977
    local group g
4978
    local integer matchedCount
4979
4980
    set g = CreateGroup()
4981
    set bj_livingPlayerUnitsTypeId = unitId
4982
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filterLivingPlayerUnitsOfTypeId)
4983
    set matchedCount = CountUnitsInGroup(g)
4984
    call DestroyGroup(g)
4985
4986
    return matchedCount
4987
endfunction
4988
4989
4990
4991
//***************************************************************************
4992
//*
4993
//*  Animation Utility Functions
4994
//*
4995
//***************************************************************************
4996
4997
//===========================================================================
4998
function ResetUnitAnimation takes unit whichUnit returns nothing
4999
    call SetUnitAnimation(whichUnit, "stand")
5000
endfunction
5001
5002
//===========================================================================
5003
function SetUnitTimeScalePercent takes unit whichUnit, real percentScale returns nothing
5004
    call SetUnitTimeScale(whichUnit, percentScale * 0.01)
5005
endfunction
5006
5007
//===========================================================================
5008
function SetUnitScalePercent takes unit whichUnit, real percentScaleX, real percentScaleY, real percentScaleZ returns nothing
5009
    call SetUnitScale(whichUnit, percentScaleX * 0.01, percentScaleY * 0.01, percentScaleZ * 0.01)
5010
endfunction
5011
5012
//===========================================================================
5013
// This version differs from the common.j interface in that the alpha value
5014
// is reversed so as to be displayed as transparency, and all four parameters
5015
// are treated as percentages rather than bytes.
5016
//
5017
function SetUnitVertexColorBJ takes unit whichUnit, real red, real green, real blue, real transparency returns nothing
5018
    call SetUnitVertexColor(whichUnit, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
5019
endfunction
5020
5021
//===========================================================================
5022
function UnitAddIndicatorBJ takes unit whichUnit, real red, real green, real blue, real transparency returns nothing
5023
    call AddIndicator(whichUnit, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
5024
endfunction
5025
5026
//===========================================================================
5027
function DestructableAddIndicatorBJ takes destructable whichDestructable, real red, real green, real blue, real transparency returns nothing
5028
    call AddIndicator(whichDestructable, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
5029
endfunction
5030
5031
//===========================================================================
5032
function ItemAddIndicatorBJ takes item whichItem, real red, real green, real blue, real transparency returns nothing
5033
    call AddIndicator(whichItem, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
5034
endfunction
5035
5036
//===========================================================================
5037
// Sets a unit's facing to point directly at a location.
5038
//
5039
function SetUnitFacingToFaceLocTimed takes unit whichUnit, location target, real duration returns nothing
5040
    local location unitLoc = GetUnitLoc(whichUnit)
5041
5042
    call SetUnitFacingTimed(whichUnit, AngleBetweenPoints(unitLoc, target), duration)
5043
    call RemoveLocation(unitLoc)
5044
endfunction
5045
5046
//===========================================================================
5047
// Sets a unit's facing to point directly at another unit.
5048
//
5049
function SetUnitFacingToFaceUnitTimed takes unit whichUnit, unit target, real duration returns nothing
5050
    local location unitLoc = GetUnitLoc(target)
5051
5052
    call SetUnitFacingToFaceLocTimed(whichUnit, unitLoc, duration)
5053
    call RemoveLocation(unitLoc)
5054
endfunction
5055
5056
//===========================================================================
5057
function QueueUnitAnimationBJ takes unit whichUnit, string whichAnimation returns nothing
5058
    call QueueUnitAnimation(whichUnit, whichAnimation)
5059
endfunction
5060
5061
//===========================================================================
5062
function SetDestructableAnimationBJ takes destructable d, string whichAnimation returns nothing
5063
    call SetDestructableAnimation(d, whichAnimation)
5064
endfunction
5065
5066
//===========================================================================
5067
function QueueDestructableAnimationBJ takes destructable d, string whichAnimation returns nothing
5068
    call QueueDestructableAnimation(d, whichAnimation)
5069
endfunction
5070
5071
//===========================================================================
5072
function SetDestAnimationSpeedPercent takes destructable d, real percentScale returns nothing
5073
    call SetDestructableAnimationSpeed(d, percentScale * 0.01)
5074
endfunction
5075
5076
5077
5078
//***************************************************************************
5079
//*
5080
//*  Dialog Utility Functions
5081
//*
5082
//***************************************************************************
5083
5084
//===========================================================================
5085
function DialogDisplayBJ takes boolean flag, dialog whichDialog, player whichPlayer returns nothing
5086
    call DialogDisplay(whichPlayer, whichDialog, flag)
5087
endfunction
5088
5089
//===========================================================================
5090
function DialogSetMessageBJ takes dialog whichDialog, string message returns nothing
5091
    call DialogSetMessage(whichDialog, message)
5092
endfunction
5093
5094
//===========================================================================
5095
function DialogAddButtonBJ takes dialog whichDialog, string buttonText returns button
5096
    set bj_lastCreatedButton = DialogAddButton(whichDialog, buttonText,0)
5097
    return bj_lastCreatedButton
5098
endfunction
5099
5100
//===========================================================================
5101
function DialogAddButtonWithHotkeyBJ takes dialog whichDialog, string buttonText, integer hotkey returns button
5102
    set bj_lastCreatedButton = DialogAddButton(whichDialog, buttonText,hotkey)
5103
    return bj_lastCreatedButton
5104
endfunction
5105
5106
//===========================================================================
5107
function DialogClearBJ takes dialog whichDialog returns nothing
5108
    call DialogClear(whichDialog)
5109
endfunction
5110
5111
//===========================================================================
5112
function GetLastCreatedButtonBJ takes nothing returns button
5113
    return bj_lastCreatedButton
5114
endfunction
5115
5116
//===========================================================================
5117
function GetClickedButtonBJ takes nothing returns button
5118
    return GetClickedButton()
5119
endfunction
5120
5121
//===========================================================================
5122
function GetClickedDialogBJ takes nothing returns dialog
5123
    return GetClickedDialog()
5124
endfunction
5125
5126
5127
5128
//***************************************************************************
5129
//*
5130
//*  Alliance Utility Functions
5131
//*
5132
//***************************************************************************
5133
5134
//===========================================================================
5135
function SetPlayerAllianceBJ takes player sourcePlayer, alliancetype whichAllianceSetting, boolean value, player otherPlayer returns nothing
5136
    // Prevent players from attempting to ally with themselves.
5137
    if (sourcePlayer == otherPlayer) then
5138
        return
5139
    endif
5140
5141
    call SetPlayerAlliance(sourcePlayer, otherPlayer, whichAllianceSetting, value)
5142
endfunction
5143
5144
//===========================================================================
5145
// Set all flags used by the in-game "Ally" checkbox.
5146
//
5147
function SetPlayerAllianceStateAllyBJ takes player sourcePlayer, player otherPlayer, boolean flag returns nothing
5148
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_PASSIVE,       flag)
5149
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_HELP_REQUEST,  flag)
5150
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_HELP_RESPONSE, flag)
5151
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_XP,     flag)
5152
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_SPELLS, flag)
5153
endfunction
5154
5155
//===========================================================================
5156
// Set all flags used by the in-game "Shared Vision" checkbox.
5157
//
5158
function SetPlayerAllianceStateVisionBJ takes player sourcePlayer, player otherPlayer, boolean flag returns nothing
5159
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_VISION, flag)
5160
endfunction
5161
5162
//===========================================================================
5163
// Set all flags used by the in-game "Shared Units" checkbox.
5164
//
5165
function SetPlayerAllianceStateControlBJ takes player sourcePlayer, player otherPlayer, boolean flag returns nothing
5166
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_CONTROL, flag)
5167
endfunction
5168
5169
//===========================================================================
5170
// Set all flags used by the in-game "Shared Units" checkbox with the Full
5171
// Shared Unit Control feature enabled.
5172
//
5173
function SetPlayerAllianceStateFullControlBJ takes player sourcePlayer, player otherPlayer, boolean flag returns nothing
5174
    call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_ADVANCED_CONTROL, flag)
5175
endfunction
5176
5177
//===========================================================================
5178
function SetPlayerAllianceStateBJ takes player sourcePlayer, player otherPlayer, integer allianceState returns nothing
5179
    // Prevent players from attempting to ally with themselves.
5180
    if (sourcePlayer == otherPlayer) then
5181
        return
5182
    endif
5183
5184
    if allianceState == bj_ALLIANCE_UNALLIED then
5185
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, false )
5186
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, false )
5187
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, false )
5188
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5189
    elseif allianceState == bj_ALLIANCE_UNALLIED_VISION then
5190
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, false )
5191
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, true  )
5192
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, false )
5193
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5194
    elseif allianceState == bj_ALLIANCE_ALLIED then
5195
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, true  )
5196
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, false )
5197
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, false )
5198
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5199
    elseif allianceState == bj_ALLIANCE_ALLIED_VISION then
5200
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, true  )
5201
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, true  )
5202
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, false )
5203
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5204
    elseif allianceState == bj_ALLIANCE_ALLIED_UNITS then
5205
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, true  )
5206
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, true  )
5207
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, true  )
5208
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5209
    elseif allianceState == bj_ALLIANCE_ALLIED_ADVUNITS then
5210
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, true  )
5211
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, true  )
5212
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, true  )
5213
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, true  )
5214
    elseif allianceState == bj_ALLIANCE_NEUTRAL then
5215
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, false )
5216
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, false )
5217
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, false )
5218
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5219
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_PASSIVE, true )
5220
    elseif allianceState == bj_ALLIANCE_NEUTRAL_VISION then
5221
        call SetPlayerAllianceStateAllyBJ(        sourcePlayer, otherPlayer, false )
5222
        call SetPlayerAllianceStateVisionBJ(      sourcePlayer, otherPlayer, true  )
5223
        call SetPlayerAllianceStateControlBJ(     sourcePlayer, otherPlayer, false )
5224
        call SetPlayerAllianceStateFullControlBJ( sourcePlayer, otherPlayer, false )
5225
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_PASSIVE, true )
5226
    else
5227
        // Unrecognized alliance state - ignore the request.
5228
    endif
5229
endfunction
5230
5231
//===========================================================================
5232
// Set the alliance states for an entire force towards another force.
5233
//
5234
function SetForceAllianceStateBJ takes force sourceForce, force targetForce, integer allianceState returns nothing
5235
    local integer sourceIndex
5236
    local integer targetIndex
5237
5238
    set sourceIndex = 0
5239
    loop
5240
5241
        if (sourceForce==bj_FORCE_ALL_PLAYERS or IsPlayerInForce(Player(sourceIndex), sourceForce)) then
5242
            set targetIndex = 0
5243
            loop
5244
                if (targetForce==bj_FORCE_ALL_PLAYERS or IsPlayerInForce(Player(targetIndex), targetForce)) then
5245
                    call SetPlayerAllianceStateBJ(Player(sourceIndex), Player(targetIndex), allianceState)
5246
                endif
5247
5248
                set targetIndex = targetIndex + 1
5249
                exitwhen targetIndex == bj_MAX_PLAYER_SLOTS
5250
            endloop
5251
        endif
5252
5253
        set sourceIndex = sourceIndex + 1
5254
        exitwhen sourceIndex == bj_MAX_PLAYER_SLOTS
5255
    endloop
5256
endfunction
5257
5258
//===========================================================================
5259
// Test to see if two players are co-allied (allied with each other).
5260
//
5261
function PlayersAreCoAllied takes player playerA, player playerB returns boolean
5262
    // Players are considered to be allied with themselves.
5263
    if (playerA == playerB) then
5264
        return true
5265
    endif
5266
5267
    // Co-allies are both allied with each other.
5268
    if GetPlayerAlliance(playerA, playerB, ALLIANCE_PASSIVE) then
5269
        if GetPlayerAlliance(playerB, playerA, ALLIANCE_PASSIVE) then
5270
            return true
5271
        endif
5272
    endif
5273
    return false
5274
endfunction
5275
5276
//===========================================================================
5277
// Force (whichPlayer) AI player to share vision and advanced unit control 
5278
// with all AI players of its allies.
5279
//
5280
function ShareEverythingWithTeamAI takes player whichPlayer returns nothing
5281
    local integer playerIndex
5282
    local player  indexPlayer
5283
5284
    set playerIndex = 0
5285
    loop
5286
        set indexPlayer = Player(playerIndex)
5287
        if (PlayersAreCoAllied(whichPlayer, indexPlayer) and whichPlayer != indexPlayer) then
5288
            if (GetPlayerController(indexPlayer) == MAP_CONTROL_COMPUTER) then
5289
                call SetPlayerAlliance(whichPlayer, indexPlayer, ALLIANCE_SHARED_VISION, true)
5290
                call SetPlayerAlliance(whichPlayer, indexPlayer, ALLIANCE_SHARED_CONTROL, true)
5291
                call SetPlayerAlliance(whichPlayer, indexPlayer, ALLIANCE_SHARED_ADVANCED_CONTROL, true)
5292
            endif
5293
        endif
5294
5295
        set playerIndex = playerIndex + 1
5296
        exitwhen playerIndex == bj_MAX_PLAYERS
5297
    endloop
5298
endfunction
5299
5300
//===========================================================================
5301
// Force (whichPlayer) to share vision and advanced unit control with all of his/her allies.
5302
//
5303
function ShareEverythingWithTeam takes player whichPlayer returns nothing
5304
    local integer playerIndex
5305
    local player  indexPlayer
5306
5307
    set playerIndex = 0
5308
    loop
5309
        set indexPlayer = Player(playerIndex)
5310
        if (PlayersAreCoAllied(whichPlayer, indexPlayer) and whichPlayer != indexPlayer) then
5311
            call SetPlayerAlliance(whichPlayer, indexPlayer, ALLIANCE_SHARED_VISION, true)
5312
            call SetPlayerAlliance(whichPlayer, indexPlayer, ALLIANCE_SHARED_CONTROL, true)
5313
            call SetPlayerAlliance(indexPlayer, whichPlayer, ALLIANCE_SHARED_CONTROL, true)
5314
            call SetPlayerAlliance(whichPlayer, indexPlayer, ALLIANCE_SHARED_ADVANCED_CONTROL, true)
5315
        endif
5316
5317
        set playerIndex = playerIndex + 1
5318
        exitwhen playerIndex == bj_MAX_PLAYERS
5319
    endloop
5320
endfunction
5321
5322
//===========================================================================
5323
// Creates a 'Neutral Victim' player slot.  This slot is passive towards all
5324
// other players, but all other players are aggressive towards him/her.
5325
// 
5326
function ConfigureNeutralVictim takes nothing returns nothing
5327
    local integer index
5328
    local player indexPlayer
5329
    local player neutralVictim = Player(bj_PLAYER_NEUTRAL_VICTIM)
5330
5331
    set index = 0
5332
    loop
5333
        set indexPlayer = Player(index)
5334
5335
        call SetPlayerAlliance(neutralVictim, indexPlayer, ALLIANCE_PASSIVE, true)
5336
        call SetPlayerAlliance(indexPlayer, neutralVictim, ALLIANCE_PASSIVE, false)
5337
5338
        set index = index + 1
5339
        exitwhen index == bj_MAX_PLAYERS
5340
    endloop
5341
5342
    // Neutral Victim and Neutral Aggressive should not fight each other.
5343
    set indexPlayer = Player(PLAYER_NEUTRAL_AGGRESSIVE)
5344
    call SetPlayerAlliance(neutralVictim, indexPlayer, ALLIANCE_PASSIVE, true)
5345
    call SetPlayerAlliance(indexPlayer, neutralVictim, ALLIANCE_PASSIVE, true)
5346
5347
    // Neutral Victim does not give bounties.
5348
    call SetPlayerState(neutralVictim, PLAYER_STATE_GIVES_BOUNTY, 0)
5349
endfunction
5350
5351
//===========================================================================
5352
function MakeUnitsPassiveForPlayerEnum takes nothing returns nothing
5353
    call SetUnitOwner(GetEnumUnit(), Player(bj_PLAYER_NEUTRAL_VICTIM), false)
5354
endfunction
5355
5356
//===========================================================================
5357
// Change ownership for every unit of (whichPlayer)'s team to neutral passive.
5358
//
5359
function MakeUnitsPassiveForPlayer takes player whichPlayer returns nothing
5360
    local group   playerUnits = CreateGroup()
5361
    call CachePlayerHeroData(whichPlayer)
5362
    call GroupEnumUnitsOfPlayer(playerUnits, whichPlayer, null)
5363
    call ForGroup(playerUnits, function MakeUnitsPassiveForPlayerEnum)
5364
    call DestroyGroup(playerUnits)
5365
endfunction
5366
5367
//===========================================================================
5368
// Change ownership for every unit of (whichPlayer)'s team to neutral passive.
5369
//
5370
function MakeUnitsPassiveForTeam takes player whichPlayer returns nothing
5371
    local integer playerIndex
5372
    local player  indexPlayer
5373
5374
    set playerIndex = 0
5375
    loop
5376
        set indexPlayer = Player(playerIndex)
5377
        if PlayersAreCoAllied(whichPlayer, indexPlayer) then
5378
            call MakeUnitsPassiveForPlayer(indexPlayer)
5379
        endif
5380
5381
        set playerIndex = playerIndex + 1
5382
        exitwhen playerIndex == bj_MAX_PLAYERS
5383
    endloop
5384
endfunction
5385
5386
//===========================================================================
5387
// Determine whether or not victory/defeat is disabled via cheat codes.
5388
//
5389
function AllowVictoryDefeat takes playergameresult gameResult returns boolean
5390
    if (gameResult == PLAYER_GAME_RESULT_VICTORY) then
5391
        return not IsNoVictoryCheat()
5392
    endif
5393
    if (gameResult == PLAYER_GAME_RESULT_DEFEAT) then
5394
        return not IsNoDefeatCheat()
5395
    endif
5396
    if (gameResult == PLAYER_GAME_RESULT_NEUTRAL) then
5397
        return (not IsNoVictoryCheat()) and (not IsNoDefeatCheat())
5398
    endif
5399
    return true
5400
endfunction
5401
5402
//===========================================================================
5403
function EndGameBJ takes nothing returns nothing
5404
    call EndGame( true )
5405
endfunction
5406
5407
//===========================================================================
5408
function MeleeVictoryDialogBJ takes player whichPlayer, boolean leftGame returns nothing
5409
    local trigger t = CreateTrigger()
5410
    local dialog  d = DialogCreate()
5411
    local string formatString
5412
5413
    // Display "player was victorious" or "player has left the game" message
5414
    if (leftGame) then
5415
        set formatString = GetLocalizedString( "PLAYER_LEFT_GAME" )
5416
    else
5417
        set formatString = GetLocalizedString( "PLAYER_VICTORIOUS" )
5418
    endif
5419
5420
    call DisplayTimedTextFromPlayer(whichPlayer, 0, 0, 60, formatString)
5421
5422
    call DialogSetMessage( d, GetLocalizedString( "GAMEOVER_VICTORY_MSG" ) )
5423
    call DialogAddButton( d, GetLocalizedString( "GAMEOVER_CONTINUE_GAME" ), GetLocalizedHotkey("GAMEOVER_CONTINUE_GAME") )
5424
5425
    set t = CreateTrigger()
5426
    call TriggerRegisterDialogButtonEvent( t, DialogAddQuitButton( d, true, GetLocalizedString( "GAMEOVER_QUIT_GAME" ), GetLocalizedHotkey("GAMEOVER_QUIT_GAME") ) )
5427
5428
    call DialogDisplay( whichPlayer, d, true )
5429
    call StartSoundForPlayerBJ( whichPlayer, bj_victoryDialogSound )
5430
endfunction
5431
5432
//===========================================================================
5433
function MeleeDefeatDialogBJ takes player whichPlayer, boolean leftGame returns nothing
5434
    local trigger t = CreateTrigger()
5435
    local dialog  d = DialogCreate()
5436
    local string formatString
5437
5438
    // Display "player was defeated" or "player has left the game" message
5439
    if (leftGame) then
5440
        set formatString = GetLocalizedString( "PLAYER_LEFT_GAME" )
5441
    else
5442
        set formatString = GetLocalizedString( "PLAYER_DEFEATED" )
5443
    endif
5444
5445
    call DisplayTimedTextFromPlayer(whichPlayer, 0, 0, 60, formatString)
5446
5447
    call DialogSetMessage( d, GetLocalizedString( "GAMEOVER_DEFEAT_MSG" ) )
5448
5449
    // Only show the continue button if the game is not over and observers on death are allowed
5450
    if (not bj_meleeGameOver and IsMapFlagSet(MAP_OBSERVERS_ON_DEATH)) then
5451
        call DialogAddButton( d, GetLocalizedString( "GAMEOVER_CONTINUE_OBSERVING" ), GetLocalizedHotkey("GAMEOVER_CONTINUE_OBSERVING") )
5452
    endif
5453
5454
    set t = CreateTrigger()
5455
    call TriggerRegisterDialogButtonEvent( t, DialogAddQuitButton( d, true, GetLocalizedString( "GAMEOVER_QUIT_GAME" ), GetLocalizedHotkey("GAMEOVER_QUIT_GAME") ) )
5456
5457
    call DialogDisplay( whichPlayer, d, true )
5458
    call StartSoundForPlayerBJ( whichPlayer, bj_defeatDialogSound )
5459
endfunction
5460
5461
//===========================================================================
5462
function GameOverDialogBJ takes player whichPlayer, boolean leftGame returns nothing
5463
    local trigger t = CreateTrigger()
5464
    local dialog  d = DialogCreate()
5465
    local string  s
5466
5467
    // Display "player left the game" message
5468
    call DisplayTimedTextFromPlayer(whichPlayer, 0, 0, 60, GetLocalizedString( "PLAYER_LEFT_GAME" ))
5469
5470
    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then
5471
        set s = GetLocalizedString( "GAMEOVER_DISCONNECTED" )
5472
    else
5473
        set s = GetLocalizedString( "GAMEOVER_GAME_OVER" )
5474
    endif
5475
5476
    call DialogSetMessage( d, s )
5477
5478
    set t = CreateTrigger()
5479
    call TriggerRegisterDialogButtonEvent( t, DialogAddQuitButton( d, true, GetLocalizedString( "GAMEOVER_OK" ), GetLocalizedHotkey("GAMEOVER_OK") ) )
5480
5481
    call DialogDisplay( whichPlayer, d, true )
5482
    call StartSoundForPlayerBJ( whichPlayer, bj_defeatDialogSound )
5483
endfunction
5484
5485
//===========================================================================
5486
function RemovePlayerPreserveUnitsBJ takes player whichPlayer, playergameresult gameResult, boolean leftGame returns nothing
5487
    if AllowVictoryDefeat(gameResult) then
5488
5489
        call RemovePlayer(whichPlayer, gameResult)
5490
5491
        if( gameResult == PLAYER_GAME_RESULT_VICTORY ) then
5492
            call MeleeVictoryDialogBJ( whichPlayer, leftGame )
5493
            return
5494
        elseif( gameResult == PLAYER_GAME_RESULT_DEFEAT ) then
5495
            call MeleeDefeatDialogBJ( whichPlayer, leftGame )
5496
        else
5497
            call GameOverDialogBJ( whichPlayer, leftGame )
5498
        endif
5499
5500
    endif
5501
endfunction
5502
5503
//===========================================================================
5504
function CustomVictoryOkBJ takes nothing returns nothing
5505
    if bj_isSinglePlayer then
5506
        call PauseGame( false )
5507
        // Bump the difficulty back up to the default.
5508
        call SetGameDifficulty(GetDefaultDifficulty())
5509
    endif
5510
5511
    if (bj_changeLevelMapName == null) then
5512
        call EndGame( bj_changeLevelShowScores )
5513
    else
5514
        call ChangeLevel( bj_changeLevelMapName, bj_changeLevelShowScores )
5515
    endif
5516
endfunction
5517
5518
//===========================================================================
5519
function CustomVictoryQuitBJ takes nothing returns nothing
5520
    if bj_isSinglePlayer then
5521
        call PauseGame( false )
5522
        // Bump the difficulty back up to the default.
5523
        call SetGameDifficulty(GetDefaultDifficulty())
5524
    endif
5525
5526
    call EndGame( bj_changeLevelShowScores )
5527
endfunction
5528
5529
//===========================================================================
5530
function CustomVictoryDialogBJ takes player whichPlayer returns nothing
5531
    local trigger t = CreateTrigger()
5532
    local dialog  d = DialogCreate()
5533
5534
    call DialogSetMessage( d, GetLocalizedString( "GAMEOVER_VICTORY_MSG" ) )
5535
5536
    set t = CreateTrigger()
5537
    call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, GetLocalizedString( "GAMEOVER_CONTINUE" ), GetLocalizedHotkey("GAMEOVER_CONTINUE") ) )
5538
    call TriggerAddAction( t, function CustomVictoryOkBJ )
5539
5540
    set t = CreateTrigger()
5541
    call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, GetLocalizedString( "GAMEOVER_QUIT_MISSION" ), GetLocalizedHotkey("GAMEOVER_QUIT_MISSION") ) )
5542
    call TriggerAddAction( t, function CustomVictoryQuitBJ )
5543
5544
    if (GetLocalPlayer() == whichPlayer) then
5545
        call EnableUserControl( true )
5546
        if bj_isSinglePlayer then
5547
            call PauseGame( true )
5548
        endif
5549
        call EnableUserUI(false)
5550
    endif
5551
5552
    call DialogDisplay( whichPlayer, d, true )
5553
    call VolumeGroupSetVolumeForPlayerBJ( whichPlayer, SOUND_VOLUMEGROUP_UI, 1.0 )
5554
    call StartSoundForPlayerBJ( whichPlayer, bj_victoryDialogSound )
5555
endfunction
5556
5557
//===========================================================================
5558
function CustomVictorySkipBJ takes player whichPlayer returns nothing
5559
    if (GetLocalPlayer() == whichPlayer) then
5560
        if bj_isSinglePlayer then
5561
            // Bump the difficulty back up to the default.
5562
            call SetGameDifficulty(GetDefaultDifficulty())
5563
        endif
5564
5565
        if (bj_changeLevelMapName == null) then
5566
            call EndGame( bj_changeLevelShowScores )
5567
        else
5568
            call ChangeLevel( bj_changeLevelMapName, bj_changeLevelShowScores )
5569
        endif
5570
    endif
5571
endfunction
5572
5573
//===========================================================================
5574
function CustomVictoryBJ takes player whichPlayer, boolean showDialog, boolean showScores returns nothing
5575
    if AllowVictoryDefeat( PLAYER_GAME_RESULT_VICTORY ) then
5576
        call RemovePlayer( whichPlayer, PLAYER_GAME_RESULT_VICTORY )
5577
5578
        if not bj_isSinglePlayer then
5579
            call DisplayTimedTextFromPlayer(whichPlayer, 0, 0, 60, GetLocalizedString( "PLAYER_VICTORIOUS" ) )
5580
        endif
5581
5582
        // UI only needs to be displayed to users.
5583
        if (GetPlayerController(whichPlayer) == MAP_CONTROL_USER) then
5584
            set bj_changeLevelShowScores = showScores
5585
            if showDialog then
5586
                call CustomVictoryDialogBJ( whichPlayer )
5587
            else
5588
                call CustomVictorySkipBJ( whichPlayer )
5589
            endif
5590
        endif
5591
    endif
5592
endfunction
5593
5594
//===========================================================================
5595
function CustomDefeatRestartBJ takes nothing returns nothing
5596
    call PauseGame( false )
5597
    call RestartGame( true )
5598
endfunction
5599
5600
//===========================================================================
5601
function CustomDefeatReduceDifficultyBJ takes nothing returns nothing
5602
    local gamedifficulty diff = GetGameDifficulty()
5603
5604
    call PauseGame( false )
5605
5606
    // Knock the difficulty down, if possible.
5607
    if (diff == MAP_DIFFICULTY_EASY) then
5608
        // Sorry, but it doesn't get any easier than this.
5609
    elseif (diff == MAP_DIFFICULTY_NORMAL) then
5610
        call SetGameDifficulty(MAP_DIFFICULTY_EASY)
5611
    elseif (diff == MAP_DIFFICULTY_HARD) then
5612
        call SetGameDifficulty(MAP_DIFFICULTY_NORMAL)
5613
    else
5614
        // Unrecognized difficulty
5615
    endif
5616
5617
    call RestartGame( true )
5618
endfunction
5619
5620
//===========================================================================
5621
function CustomDefeatLoadBJ takes nothing returns nothing
5622
    call PauseGame( false )
5623
    call DisplayLoadDialog()
5624
endfunction
5625
5626
//===========================================================================
5627
function CustomDefeatQuitBJ takes nothing returns nothing
5628
    if bj_isSinglePlayer then
5629
        call PauseGame( false )
5630
    endif
5631
5632
    // Bump the difficulty back up to the default.
5633
    call SetGameDifficulty(GetDefaultDifficulty())
5634
    call EndGame( true )
5635
endfunction
5636
5637
//===========================================================================
5638
function CustomDefeatDialogBJ takes player whichPlayer, string message returns nothing
5639
    local trigger t = CreateTrigger()
5640
    local dialog  d = DialogCreate()
5641
5642
    call DialogSetMessage( d, message )
5643
5644
    if bj_isSinglePlayer then
5645
        set t = CreateTrigger()
5646
        call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, GetLocalizedString( "GAMEOVER_RESTART" ), GetLocalizedHotkey("GAMEOVER_RESTART") ) )
5647
        call TriggerAddAction( t, function CustomDefeatRestartBJ )
5648
5649
        if (GetGameDifficulty() != MAP_DIFFICULTY_EASY) then
5650
            set t = CreateTrigger()
5651
            call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, GetLocalizedString( "GAMEOVER_REDUCE_DIFFICULTY" ), GetLocalizedHotkey("GAMEOVER_REDUCE_DIFFICULTY") ) )
5652
            call TriggerAddAction( t, function CustomDefeatReduceDifficultyBJ )
5653
        endif
5654
5655
        set t = CreateTrigger()
5656
        call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, GetLocalizedString( "GAMEOVER_LOAD" ), GetLocalizedHotkey("GAMEOVER_LOAD") ) )
5657
        call TriggerAddAction( t, function CustomDefeatLoadBJ )
5658
    endif
5659
5660
    set t = CreateTrigger()
5661
    call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, GetLocalizedString( "GAMEOVER_QUIT_MISSION" ), GetLocalizedHotkey("GAMEOVER_QUIT_MISSION") ) )
5662
    call TriggerAddAction( t, function CustomDefeatQuitBJ )
5663
5664
    if (GetLocalPlayer() == whichPlayer) then
5665
        call EnableUserControl( true )
5666
        if bj_isSinglePlayer then
5667
            call PauseGame( true )
5668
        endif
5669
        call EnableUserUI(false)
5670
    endif
5671
5672
    call DialogDisplay( whichPlayer, d, true )
5673
    call VolumeGroupSetVolumeForPlayerBJ( whichPlayer, SOUND_VOLUMEGROUP_UI, 1.0 )
5674
    call StartSoundForPlayerBJ( whichPlayer, bj_defeatDialogSound )
5675
endfunction
5676
5677
//===========================================================================
5678
function CustomDefeatBJ takes player whichPlayer, string message returns nothing
5679
    if AllowVictoryDefeat( PLAYER_GAME_RESULT_DEFEAT ) then
5680
        call RemovePlayer( whichPlayer, PLAYER_GAME_RESULT_DEFEAT )
5681
5682
        if not bj_isSinglePlayer then
5683
            call DisplayTimedTextFromPlayer(whichPlayer, 0, 0, 60, GetLocalizedString( "PLAYER_DEFEATED" ) )
5684
        endif
5685
5686
        // UI only needs to be displayed to users.
5687
        if (GetPlayerController(whichPlayer) == MAP_CONTROL_USER) then
5688
            call CustomDefeatDialogBJ( whichPlayer, message )
5689
        endif
5690
    endif
5691
endfunction
5692
5693
//===========================================================================
5694
function SetNextLevelBJ takes string nextLevel returns nothing
5695
    if (nextLevel == "") then
5696
        set bj_changeLevelMapName = null
5697
    else
5698
        set bj_changeLevelMapName = nextLevel
5699
    endif
5700
endfunction
5701
5702
//===========================================================================
5703
function SetPlayerOnScoreScreenBJ takes boolean flag, player whichPlayer returns nothing
5704
    call SetPlayerOnScoreScreen(whichPlayer, flag)
5705
endfunction
5706
5707
5708
5709
//***************************************************************************
5710
//*
5711
//*  Quest Utility Functions
5712
//*
5713
//***************************************************************************
5714
5715
//===========================================================================
5716
function CreateQuestBJ takes integer questType, string title, string description, string iconPath returns quest
5717
    local boolean required   = (questType == bj_QUESTTYPE_REQ_DISCOVERED) or (questType == bj_QUESTTYPE_REQ_UNDISCOVERED)
5718
    local boolean discovered = (questType == bj_QUESTTYPE_REQ_DISCOVERED) or (questType == bj_QUESTTYPE_OPT_DISCOVERED)
5719
5720
    set bj_lastCreatedQuest = CreateQuest()
5721
    call QuestSetTitle(bj_lastCreatedQuest, title)
5722
    call QuestSetDescription(bj_lastCreatedQuest, description)
5723
    call QuestSetIconPath(bj_lastCreatedQuest, iconPath)
5724
    call QuestSetRequired(bj_lastCreatedQuest, required)
5725
    call QuestSetDiscovered(bj_lastCreatedQuest, discovered)
5726
    call QuestSetCompleted(bj_lastCreatedQuest, false)
5727
    return bj_lastCreatedQuest
5728
endfunction
5729
5730
//===========================================================================
5731
function DestroyQuestBJ takes quest whichQuest returns nothing
5732
    call DestroyQuest(whichQuest)
5733
endfunction
5734
5735
//===========================================================================
5736
function QuestSetEnabledBJ takes boolean enabled, quest whichQuest returns nothing
5737
    call QuestSetEnabled(whichQuest, enabled)
5738
endfunction
5739
5740
//===========================================================================
5741
function QuestSetTitleBJ takes quest whichQuest, string title returns nothing
5742
    call QuestSetTitle(whichQuest, title)
5743
endfunction
5744
5745
//===========================================================================
5746
function QuestSetDescriptionBJ takes quest whichQuest, string description returns nothing
5747
    call QuestSetDescription(whichQuest, description)
5748
endfunction
5749
5750
//===========================================================================
5751
function QuestSetCompletedBJ takes quest whichQuest, boolean completed returns nothing
5752
    call QuestSetCompleted(whichQuest, completed)
5753
endfunction
5754
5755
//===========================================================================
5756
function QuestSetFailedBJ takes quest whichQuest, boolean failed returns nothing
5757
    call QuestSetFailed(whichQuest, failed)
5758
endfunction
5759
5760
//===========================================================================
5761
function QuestSetDiscoveredBJ takes quest whichQuest, boolean discovered returns nothing
5762
    call QuestSetDiscovered(whichQuest, discovered)
5763
endfunction
5764
5765
//===========================================================================
5766
function GetLastCreatedQuestBJ takes nothing returns quest
5767
    return bj_lastCreatedQuest
5768
endfunction
5769
5770
//===========================================================================
5771
function CreateQuestItemBJ takes quest whichQuest, string description returns questitem
5772
    set bj_lastCreatedQuestItem = QuestCreateItem(whichQuest)
5773
    call QuestItemSetDescription(bj_lastCreatedQuestItem, description)
5774
    call QuestItemSetCompleted(bj_lastCreatedQuestItem, false)
5775
    return bj_lastCreatedQuestItem
5776
endfunction
5777
5778
//===========================================================================
5779
function QuestItemSetDescriptionBJ takes questitem whichQuestItem, string description returns nothing
5780
    call QuestItemSetDescription(whichQuestItem, description)
5781
endfunction
5782
5783
//===========================================================================
5784
function QuestItemSetCompletedBJ takes questitem whichQuestItem, boolean completed returns nothing
5785
    call QuestItemSetCompleted(whichQuestItem, completed)
5786
endfunction
5787
5788
//===========================================================================
5789
function GetLastCreatedQuestItemBJ takes nothing returns questitem
5790
    return bj_lastCreatedQuestItem
5791
endfunction
5792
5793
//===========================================================================
5794
function CreateDefeatConditionBJ takes string description returns defeatcondition
5795
    set bj_lastCreatedDefeatCondition = CreateDefeatCondition()
5796
    call DefeatConditionSetDescription(bj_lastCreatedDefeatCondition, description)
5797
    return bj_lastCreatedDefeatCondition
5798
endfunction
5799
5800
//===========================================================================
5801
function DestroyDefeatConditionBJ takes defeatcondition whichCondition returns nothing
5802
    call DestroyDefeatCondition(whichCondition)
5803
endfunction
5804
5805
//===========================================================================
5806
function DefeatConditionSetDescriptionBJ takes defeatcondition whichCondition, string description returns nothing
5807
    call DefeatConditionSetDescription(whichCondition, description)
5808
endfunction
5809
5810
//===========================================================================
5811
function GetLastCreatedDefeatConditionBJ takes nothing returns defeatcondition
5812
    return bj_lastCreatedDefeatCondition
5813
endfunction
5814
5815
//===========================================================================
5816
function FlashQuestDialogButtonBJ takes nothing returns nothing
5817
    call FlashQuestDialogButton()
5818
endfunction
5819
5820
//===========================================================================
5821
function QuestMessageBJ takes force f, integer messageType, string message returns nothing
5822
    if (IsPlayerInForce(GetLocalPlayer(), f)) then
5823
        // Use only local code (no net traffic) within this block to avoid desyncs.
5824
5825
        if (messageType == bj_QUESTMESSAGE_DISCOVERED) then
5826
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUEST, " ")
5827
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUEST, message)
5828
            call StartSound(bj_questDiscoveredSound)
5829
            call FlashQuestDialogButton()
5830
5831
        elseif (messageType == bj_QUESTMESSAGE_UPDATED) then
5832
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTUPDATE, " ")
5833
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTUPDATE, message)
5834
            call StartSound(bj_questUpdatedSound)
5835
            call FlashQuestDialogButton()
5836
5837
        elseif (messageType == bj_QUESTMESSAGE_COMPLETED) then
5838
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTDONE, " ")
5839
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTDONE, message)
5840
            call StartSound(bj_questCompletedSound)
5841
            call FlashQuestDialogButton()
5842
5843
        elseif (messageType == bj_QUESTMESSAGE_FAILED) then
5844
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTFAILED, " ")
5845
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTFAILED, message)
5846
            call StartSound(bj_questFailedSound)
5847
            call FlashQuestDialogButton()
5848
5849
        elseif (messageType == bj_QUESTMESSAGE_REQUIREMENT) then
5850
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_QUESTREQUIREMENT, message)
5851
5852
        elseif (messageType == bj_QUESTMESSAGE_MISSIONFAILED) then
5853
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_MISSIONFAILED, " ")
5854
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_MISSIONFAILED, message)
5855
            call StartSound(bj_questFailedSound)
5856
5857
        elseif (messageType == bj_QUESTMESSAGE_HINT) then
5858
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_HINT, " ")
5859
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_HINT, message)
5860
            call StartSound(bj_questHintSound)
5861
5862
        elseif (messageType == bj_QUESTMESSAGE_ALWAYSHINT) then
5863
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_ALWAYSHINT, " ")
5864
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_ALWAYSHINT, message)
5865
            call StartSound(bj_questHintSound)
5866
5867
        elseif (messageType == bj_QUESTMESSAGE_SECRET) then
5868
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_SECRET, " ")
5869
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_SECRET, message)
5870
            call StartSound(bj_questSecretSound)
5871
5872
        elseif (messageType == bj_QUESTMESSAGE_UNITACQUIRED) then
5873
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_UNITACQUIRED, " ")
5874
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_UNITACQUIRED, message)
5875
            call StartSound(bj_questHintSound)
5876
5877
        elseif (messageType == bj_QUESTMESSAGE_UNITAVAILABLE) then
5878
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_UNITAVAILABLE, " ")
5879
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_UNITAVAILABLE, message)
5880
            call StartSound(bj_questHintSound)
5881
5882
        elseif (messageType == bj_QUESTMESSAGE_ITEMACQUIRED) then
5883
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_ITEMACQUIRED, " ")
5884
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_ITEMACQUIRED, message)
5885
            call StartSound(bj_questItemAcquiredSound)
5886
5887
        elseif (messageType == bj_QUESTMESSAGE_WARNING) then
5888
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_WARNING, " ")
5889
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_TEXT_DELAY_WARNING, message)
5890
            call StartSound(bj_questWarningSound)
5891
5892
        else
5893
            // Unrecognized message type - ignore the request.
5894
        endif
5895
    endif
5896
endfunction
5897
5898
5899
5900
//***************************************************************************
5901
//*
5902
//*  Timer Utility Functions
5903
//*
5904
//***************************************************************************
5905
5906
//===========================================================================
5907
function StartTimerBJ takes timer t, boolean periodic, real timeout returns timer
5908
    set bj_lastStartedTimer = t
5909
    call TimerStart(t, timeout, periodic, null)
5910
    return bj_lastStartedTimer
5911
endfunction
5912
5913
//===========================================================================
5914
function CreateTimerBJ takes boolean periodic, real timeout returns timer
5915
    set bj_lastStartedTimer = CreateTimer()
5916
    call TimerStart(bj_lastStartedTimer, timeout, periodic, null)
5917
    return bj_lastStartedTimer
5918
endfunction
5919
5920
//===========================================================================
5921
function DestroyTimerBJ takes timer whichTimer returns nothing
5922
    call DestroyTimer(whichTimer)
5923
endfunction
5924
5925
//===========================================================================
5926
function PauseTimerBJ takes boolean pause, timer whichTimer returns nothing
5927
    if pause then
5928
        call PauseTimer(whichTimer)
5929
    else
5930
        call ResumeTimer(whichTimer)
5931
    endif
5932
endfunction
5933
5934
//===========================================================================
5935
function GetLastCreatedTimerBJ takes nothing returns timer
5936
    return bj_lastStartedTimer
5937
endfunction
5938
5939
//===========================================================================
5940
function CreateTimerDialogBJ takes timer t, string title returns timerdialog
5941
    set bj_lastCreatedTimerDialog = CreateTimerDialog(t)
5942
    call TimerDialogSetTitle(bj_lastCreatedTimerDialog, title)
5943
    call TimerDialogDisplay(bj_lastCreatedTimerDialog, true)
5944
    return bj_lastCreatedTimerDialog
5945
endfunction
5946
5947
//===========================================================================
5948
function DestroyTimerDialogBJ takes timerdialog td returns nothing
5949
    call DestroyTimerDialog(td)
5950
endfunction
5951
5952
//===========================================================================
5953
function TimerDialogSetTitleBJ takes timerdialog td, string title returns nothing
5954
    call TimerDialogSetTitle(td, title)
5955
endfunction
5956
5957
//===========================================================================
5958
function TimerDialogSetTitleColorBJ takes timerdialog td, real red, real green, real blue, real transparency returns nothing
5959
    call TimerDialogSetTitleColor(td, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
5960
endfunction
5961
5962
//===========================================================================
5963
function TimerDialogSetTimeColorBJ takes timerdialog td, real red, real green, real blue, real transparency returns nothing
5964
    call TimerDialogSetTimeColor(td, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
5965
endfunction
5966
5967
//===========================================================================
5968
function TimerDialogSetSpeedBJ takes timerdialog td, real speedMultFactor returns nothing
5969
    call TimerDialogSetSpeed(td, speedMultFactor)
5970
endfunction
5971
5972
//===========================================================================
5973
function TimerDialogDisplayForPlayerBJ takes boolean show, timerdialog td, player whichPlayer returns nothing
5974
    if (GetLocalPlayer() == whichPlayer) then
5975
        // Use only local code (no net traffic) within this block to avoid desyncs.
5976
        call TimerDialogDisplay(td, show)
5977
    endif
5978
endfunction
5979
5980
//===========================================================================
5981
function TimerDialogDisplayBJ takes boolean show, timerdialog td returns nothing
5982
    call TimerDialogDisplay(td, show)
5983
endfunction
5984
5985
//===========================================================================
5986
function GetLastCreatedTimerDialogBJ takes nothing returns timerdialog
5987
    return bj_lastCreatedTimerDialog
5988
endfunction
5989
5990
5991
5992
//***************************************************************************
5993
//*
5994
//*  Leaderboard Utility Functions
5995
//*
5996
//***************************************************************************
5997
5998
//===========================================================================
5999
function LeaderboardResizeBJ takes leaderboard lb returns nothing
6000
    local integer size = LeaderboardGetItemCount(lb)
6001
6002
    if (LeaderboardGetLabelText(lb) == "") then
6003
        set size = size - 1
6004
    endif
6005
    call LeaderboardSetSizeByItemCount(lb, size)
6006
endfunction
6007
6008
//===========================================================================
6009
function LeaderboardSetPlayerItemValueBJ takes player whichPlayer, leaderboard lb, integer val returns nothing
6010
    call LeaderboardSetItemValue(lb, LeaderboardGetPlayerIndex(lb, whichPlayer), val)
6011
endfunction
6012
6013
//===========================================================================
6014
function LeaderboardSetPlayerItemLabelBJ takes player whichPlayer, leaderboard lb, string val returns nothing
6015
    call LeaderboardSetItemLabel(lb, LeaderboardGetPlayerIndex(lb, whichPlayer), val)
6016
endfunction
6017
6018
//===========================================================================
6019
function LeaderboardSetPlayerItemStyleBJ takes player whichPlayer, leaderboard lb, boolean showLabel, boolean showValue, boolean showIcon returns nothing
6020
    call LeaderboardSetItemStyle(lb, LeaderboardGetPlayerIndex(lb, whichPlayer), showLabel, showValue, showIcon)
6021
endfunction
6022
6023
//===========================================================================
6024
function LeaderboardSetPlayerItemLabelColorBJ takes player whichPlayer, leaderboard lb, real red, real green, real blue, real transparency returns nothing
6025
    call LeaderboardSetItemLabelColor(lb, LeaderboardGetPlayerIndex(lb, whichPlayer), PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6026
endfunction
6027
6028
//===========================================================================
6029
function LeaderboardSetPlayerItemValueColorBJ takes player whichPlayer, leaderboard lb, real red, real green, real blue, real transparency returns nothing
6030
    call LeaderboardSetItemValueColor(lb, LeaderboardGetPlayerIndex(lb, whichPlayer), PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6031
endfunction
6032
6033
//===========================================================================
6034
function LeaderboardSetLabelColorBJ takes leaderboard lb, real red, real green, real blue, real transparency returns nothing
6035
    call LeaderboardSetLabelColor(lb, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6036
endfunction
6037
6038
//===========================================================================
6039
function LeaderboardSetValueColorBJ takes leaderboard lb, real red, real green, real blue, real transparency returns nothing
6040
    call LeaderboardSetValueColor(lb, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6041
endfunction
6042
6043
//===========================================================================
6044
function LeaderboardSetLabelBJ takes leaderboard lb, string label returns nothing
6045
    call LeaderboardSetLabel(lb, label)
6046
    call LeaderboardResizeBJ(lb)
6047
endfunction
6048
6049
//===========================================================================
6050
function LeaderboardSetStyleBJ takes leaderboard lb, boolean showLabel, boolean showNames, boolean showValues, boolean showIcons returns nothing
6051
    call LeaderboardSetStyle(lb, showLabel, showNames, showValues, showIcons)
6052
endfunction
6053
6054
//===========================================================================
6055
function LeaderboardGetItemCountBJ takes leaderboard lb returns integer
6056
    return LeaderboardGetItemCount(lb)
6057
endfunction
6058
6059
//===========================================================================
6060
function LeaderboardHasPlayerItemBJ takes leaderboard lb, player whichPlayer returns boolean
6061
    return LeaderboardHasPlayerItem(lb, whichPlayer)
6062
endfunction
6063
6064
//===========================================================================
6065
function ForceSetLeaderboardBJ takes leaderboard lb, force toForce returns nothing
6066
    local integer index
6067
    local player  indexPlayer
6068
6069
    set index = 0
6070
    loop
6071
        set indexPlayer = Player(index)
6072
        if IsPlayerInForce(indexPlayer, toForce) then
6073
            call PlayerSetLeaderboard(indexPlayer, lb)
6074
        endif
6075
        set index = index + 1
6076
        exitwhen index == bj_MAX_PLAYERS
6077
    endloop
6078
endfunction
6079
6080
//===========================================================================
6081
function CreateLeaderboardBJ takes force toForce, string label returns leaderboard
6082
    set bj_lastCreatedLeaderboard = CreateLeaderboard()
6083
    call LeaderboardSetLabel(bj_lastCreatedLeaderboard, label)
6084
    call ForceSetLeaderboardBJ(bj_lastCreatedLeaderboard, toForce)
6085
    call LeaderboardDisplay(bj_lastCreatedLeaderboard, true)
6086
    return bj_lastCreatedLeaderboard
6087
endfunction
6088
6089
//===========================================================================
6090
function DestroyLeaderboardBJ takes leaderboard lb returns nothing
6091
    call DestroyLeaderboard(lb)
6092
endfunction
6093
6094
//===========================================================================
6095
function LeaderboardDisplayBJ takes boolean show, leaderboard lb returns nothing
6096
    call LeaderboardDisplay(lb, show)
6097
endfunction
6098
6099
//===========================================================================
6100
function LeaderboardAddItemBJ takes player whichPlayer, leaderboard lb, string label, integer value returns nothing
6101
    if (LeaderboardHasPlayerItem(lb, whichPlayer)) then
6102
        call LeaderboardRemovePlayerItem(lb, whichPlayer)
6103
    endif
6104
    call LeaderboardAddItem(lb, label, value, whichPlayer)
6105
    call LeaderboardResizeBJ(lb)
6106
    //call LeaderboardSetSizeByItemCount(lb, LeaderboardGetItemCount(lb))
6107
endfunction
6108
6109
//===========================================================================
6110
function LeaderboardRemovePlayerItemBJ takes player whichPlayer, leaderboard lb returns nothing
6111
    call LeaderboardRemovePlayerItem(lb, whichPlayer)
6112
    call LeaderboardResizeBJ(lb)
6113
endfunction
6114
6115
//===========================================================================
6116
function LeaderboardSortItemsBJ takes leaderboard lb, integer sortType, boolean ascending returns nothing
6117
    if (sortType == bj_SORTTYPE_SORTBYVALUE) then
6118
        call LeaderboardSortItemsByValue(lb, ascending)
6119
    elseif (sortType == bj_SORTTYPE_SORTBYPLAYER) then
6120
        call LeaderboardSortItemsByPlayer(lb, ascending)
6121
    elseif (sortType == bj_SORTTYPE_SORTBYLABEL) then
6122
        call LeaderboardSortItemsByLabel(lb, ascending)
6123
    else
6124
        // Unrecognized sort type - ignore the request.
6125
    endif
6126
endfunction
6127
6128
//===========================================================================
6129
function LeaderboardSortItemsByPlayerBJ takes leaderboard lb, boolean ascending returns nothing
6130
    call LeaderboardSortItemsByPlayer(lb, ascending)
6131
endfunction
6132
6133
//===========================================================================
6134
function LeaderboardSortItemsByLabelBJ takes leaderboard lb, boolean ascending returns nothing
6135
    call LeaderboardSortItemsByLabel(lb, ascending)
6136
endfunction
6137
6138
//===========================================================================
6139
function LeaderboardGetPlayerIndexBJ takes player whichPlayer, leaderboard lb returns integer
6140
    return LeaderboardGetPlayerIndex(lb, whichPlayer) + 1
6141
endfunction
6142
6143
//===========================================================================
6144
// Returns the player who is occupying a specified position in a leaderboard.
6145
// The position parameter is expected in the range of 1..16.
6146
//
6147
function LeaderboardGetIndexedPlayerBJ takes integer position, leaderboard lb returns player
6148
    local integer index
6149
    local player  indexPlayer
6150
6151
    set index = 0
6152
    loop
6153
        set indexPlayer = Player(index)
6154
        if (LeaderboardGetPlayerIndex(lb, indexPlayer) == position - 1) then
6155
            return indexPlayer
6156
        endif
6157
6158
        set index = index + 1
6159
        exitwhen index == bj_MAX_PLAYERS
6160
    endloop
6161
6162
    return Player(PLAYER_NEUTRAL_PASSIVE)
6163
endfunction
6164
6165
//===========================================================================
6166
function PlayerGetLeaderboardBJ takes player whichPlayer returns leaderboard
6167
    return PlayerGetLeaderboard(whichPlayer)
6168
endfunction
6169
6170
//===========================================================================
6171
function GetLastCreatedLeaderboard takes nothing returns leaderboard
6172
    return bj_lastCreatedLeaderboard
6173
endfunction
6174
6175
//***************************************************************************
6176
//*
6177
//*  Multiboard Utility Functions
6178
//*
6179
//***************************************************************************
6180
6181
//===========================================================================
6182
function CreateMultiboardBJ takes integer cols, integer rows, string title returns multiboard
6183
    set bj_lastCreatedMultiboard = CreateMultiboard()
6184
    call MultiboardSetRowCount(bj_lastCreatedMultiboard, rows)
6185
    call MultiboardSetColumnCount(bj_lastCreatedMultiboard, cols)
6186
    call MultiboardSetTitleText(bj_lastCreatedMultiboard, title)
6187
    call MultiboardDisplay(bj_lastCreatedMultiboard, true)
6188
    return bj_lastCreatedMultiboard
6189
endfunction
6190
6191
//===========================================================================
6192
function DestroyMultiboardBJ takes multiboard mb returns nothing
6193
    call DestroyMultiboard(mb)
6194
endfunction
6195
6196
//===========================================================================
6197
function GetLastCreatedMultiboard takes nothing returns multiboard
6198
    return bj_lastCreatedMultiboard
6199
endfunction
6200
6201
//===========================================================================
6202
function MultiboardDisplayBJ takes boolean show, multiboard mb returns nothing
6203
    call MultiboardDisplay(mb, show)
6204
endfunction
6205
6206
//===========================================================================
6207
function MultiboardMinimizeBJ takes boolean minimize, multiboard mb returns nothing
6208
    call MultiboardMinimize(mb, minimize)
6209
endfunction
6210
6211
//===========================================================================
6212
function MultiboardSetTitleTextColorBJ takes multiboard mb, real red, real green, real blue, real transparency returns nothing
6213
    call MultiboardSetTitleTextColor(mb, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6214
endfunction
6215
6216
//===========================================================================
6217
function MultiboardAllowDisplayBJ takes boolean flag returns nothing
6218
    call MultiboardSuppressDisplay(not flag)
6219
endfunction
6220
6221
//===========================================================================
6222
function MultiboardSetItemStyleBJ takes multiboard mb, integer col, integer row, boolean showValue, boolean showIcon returns nothing
6223
    local integer curRow = 0
6224
    local integer curCol = 0
6225
    local integer numRows = MultiboardGetRowCount(mb)
6226
    local integer numCols = MultiboardGetColumnCount(mb)
6227
    local multiboarditem mbitem = null
6228
6229
    // Loop over rows, using 1-based index
6230
    loop
6231
        set curRow = curRow + 1
6232
        exitwhen curRow > numRows
6233
6234
        // Apply setting to the requested row, or all rows (if row is 0)
6235
        if (row == 0 or row == curRow) then
6236
            // Loop over columns, using 1-based index
6237
            set curCol = 0
6238
            loop
6239
                set curCol = curCol + 1
6240
                exitwhen curCol > numCols
6241
6242
                // Apply setting to the requested column, or all columns (if col is 0)
6243
                if (col == 0 or col == curCol) then
6244
                    set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
6245
                    call MultiboardSetItemStyle(mbitem, showValue, showIcon)
6246
                    call MultiboardReleaseItem(mbitem)
6247
                endif
6248
            endloop
6249
        endif
6250
    endloop
6251
endfunction
6252
6253
//===========================================================================
6254
function MultiboardSetItemValueBJ takes multiboard mb, integer col, integer row, string val returns nothing
6255
    local integer curRow = 0
6256
    local integer curCol = 0
6257
    local integer numRows = MultiboardGetRowCount(mb)
6258
    local integer numCols = MultiboardGetColumnCount(mb)
6259
    local multiboarditem mbitem = null
6260
6261
    // Loop over rows, using 1-based index
6262
    loop
6263
        set curRow = curRow + 1
6264
        exitwhen curRow > numRows
6265
6266
        // Apply setting to the requested row, or all rows (if row is 0)
6267
        if (row == 0 or row == curRow) then
6268
            // Loop over columns, using 1-based index
6269
            set curCol = 0
6270
            loop
6271
                set curCol = curCol + 1
6272
                exitwhen curCol > numCols
6273
6274
                // Apply setting to the requested column, or all columns (if col is 0)
6275
                if (col == 0 or col == curCol) then
6276
                    set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
6277
                    call MultiboardSetItemValue(mbitem, val)
6278
                    call MultiboardReleaseItem(mbitem)
6279
                endif
6280
            endloop
6281
        endif
6282
    endloop
6283
endfunction
6284
6285
//===========================================================================
6286
function MultiboardSetItemColorBJ takes multiboard mb, integer col, integer row, real red, real green, real blue, real transparency returns nothing
6287
    local integer curRow = 0
6288
    local integer curCol = 0
6289
    local integer numRows = MultiboardGetRowCount(mb)
6290
    local integer numCols = MultiboardGetColumnCount(mb)
6291
    local multiboarditem mbitem = null
6292
6293
    // Loop over rows, using 1-based index
6294
    loop
6295
        set curRow = curRow + 1
6296
        exitwhen curRow > numRows
6297
6298
        // Apply setting to the requested row, or all rows (if row is 0)
6299
        if (row == 0 or row == curRow) then
6300
            // Loop over columns, using 1-based index
6301
            set curCol = 0
6302
            loop
6303
                set curCol = curCol + 1
6304
                exitwhen curCol > numCols
6305
6306
                // Apply setting to the requested column, or all columns (if col is 0)
6307
                if (col == 0 or col == curCol) then
6308
                    set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
6309
                    call MultiboardSetItemValueColor(mbitem, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6310
                    call MultiboardReleaseItem(mbitem)
6311
                endif
6312
            endloop
6313
        endif
6314
    endloop
6315
endfunction
6316
6317
//===========================================================================
6318
function MultiboardSetItemWidthBJ takes multiboard mb, integer col, integer row, real width returns nothing
6319
    local integer curRow = 0
6320
    local integer curCol = 0
6321
    local integer numRows = MultiboardGetRowCount(mb)
6322
    local integer numCols = MultiboardGetColumnCount(mb)
6323
    local multiboarditem mbitem = null
6324
6325
    // Loop over rows, using 1-based index
6326
    loop
6327
        set curRow = curRow + 1
6328
        exitwhen curRow > numRows
6329
6330
        // Apply setting to the requested row, or all rows (if row is 0)
6331
        if (row == 0 or row == curRow) then
6332
            // Loop over columns, using 1-based index
6333
            set curCol = 0
6334
            loop
6335
                set curCol = curCol + 1
6336
                exitwhen curCol > numCols
6337
6338
                // Apply setting to the requested column, or all columns (if col is 0)
6339
                if (col == 0 or col == curCol) then
6340
                    set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
6341
                    call MultiboardSetItemWidth(mbitem, width/100.0)
6342
                    call MultiboardReleaseItem(mbitem)
6343
                endif
6344
            endloop
6345
        endif
6346
    endloop
6347
endfunction
6348
6349
//===========================================================================
6350
function MultiboardSetItemIconBJ takes multiboard mb, integer col, integer row, string iconFileName returns nothing
6351
    local integer curRow = 0
6352
    local integer curCol = 0
6353
    local integer numRows = MultiboardGetRowCount(mb)
6354
    local integer numCols = MultiboardGetColumnCount(mb)
6355
    local multiboarditem mbitem = null
6356
6357
    // Loop over rows, using 1-based index
6358
    loop
6359
        set curRow = curRow + 1
6360
        exitwhen curRow > numRows
6361
6362
        // Apply setting to the requested row, or all rows (if row is 0)
6363
        if (row == 0 or row == curRow) then
6364
            // Loop over columns, using 1-based index
6365
            set curCol = 0
6366
            loop
6367
                set curCol = curCol + 1
6368
                exitwhen curCol > numCols
6369
6370
                // Apply setting to the requested column, or all columns (if col is 0)
6371
                if (col == 0 or col == curCol) then
6372
                    set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
6373
                    call MultiboardSetItemIcon(mbitem, iconFileName)
6374
                    call MultiboardReleaseItem(mbitem)
6375
                endif
6376
            endloop
6377
        endif
6378
    endloop
6379
endfunction
6380
6381
6382
6383
//***************************************************************************
6384
//*
6385
//*  Text Tag Utility Functions
6386
//*
6387
//***************************************************************************
6388
6389
//===========================================================================
6390
// Scale the font size linearly such that size 10 equates to height 0.023.
6391
// Screen-relative font heights are harder to grasp and than font sizes.
6392
//
6393
function TextTagSize2Height takes real size returns real
6394
    return size * 0.023 / 10
6395
endfunction
6396
6397
//===========================================================================
6398
// Scale the speed linearly such that speed 128 equates to 0.071.
6399
// Screen-relative speeds are hard to grasp.
6400
//
6401
function TextTagSpeed2Velocity takes real speed returns real
6402
    return speed * 0.071 / 128
6403
endfunction
6404
6405
//===========================================================================
6406
function SetTextTagColorBJ takes texttag tt, real red, real green, real blue, real transparency returns nothing
6407
    call SetTextTagColor(tt, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
6408
endfunction
6409
6410
//===========================================================================
6411
function SetTextTagVelocityBJ takes texttag tt, real speed, real angle returns nothing
6412
    local real vel = TextTagSpeed2Velocity(speed)
6413
    local real xvel = vel * Cos(angle * bj_DEGTORAD)
6414
    local real yvel = vel * Sin(angle * bj_DEGTORAD)
6415
6416
    call SetTextTagVelocity(tt, xvel, yvel)
6417
endfunction
6418
6419
//===========================================================================
6420
function SetTextTagTextBJ takes texttag tt, string s, real size returns nothing
6421
    local real textHeight = TextTagSize2Height(size)
6422
6423
    call SetTextTagText(tt, s, textHeight)
6424
endfunction
6425
6426
//===========================================================================
6427
function SetTextTagPosBJ takes texttag tt, location loc, real zOffset returns nothing
6428
    call SetTextTagPos(tt, GetLocationX(loc), GetLocationY(loc), zOffset)
6429
endfunction
6430
6431
//===========================================================================
6432
function SetTextTagPosUnitBJ takes texttag tt, unit whichUnit, real zOffset returns nothing
6433
    call SetTextTagPosUnit(tt, whichUnit, zOffset)
6434
endfunction
6435
6436
//===========================================================================
6437
function SetTextTagSuspendedBJ takes texttag tt, boolean flag returns nothing
6438
    call SetTextTagSuspended(tt, flag)
6439
endfunction
6440
6441
//===========================================================================
6442
function SetTextTagPermanentBJ takes texttag tt, boolean flag returns nothing
6443
    call SetTextTagPermanent(tt, flag)
6444
endfunction
6445
6446
//===========================================================================
6447
function SetTextTagAgeBJ takes texttag tt, real age returns nothing
6448
    call SetTextTagAge(tt, age)
6449
endfunction
6450
6451
//===========================================================================
6452
function SetTextTagLifespanBJ takes texttag tt, real lifespan returns nothing
6453
    call SetTextTagLifespan(tt, lifespan)
6454
endfunction
6455
6456
//===========================================================================
6457
function SetTextTagFadepointBJ takes texttag tt, real fadepoint returns nothing
6458
    call SetTextTagFadepoint(tt, fadepoint)
6459
endfunction
6460
6461
//===========================================================================
6462
function CreateTextTagLocBJ takes string s, location loc, real zOffset, real size, real red, real green, real blue, real transparency returns texttag
6463
    set bj_lastCreatedTextTag = CreateTextTag()
6464
    call SetTextTagTextBJ(bj_lastCreatedTextTag, s, size)
6465
    call SetTextTagPosBJ(bj_lastCreatedTextTag, loc, zOffset)
6466
    call SetTextTagColorBJ(bj_lastCreatedTextTag, red, green, blue, transparency)
6467
6468
    return bj_lastCreatedTextTag
6469
endfunction
6470
6471
//===========================================================================
6472
function CreateTextTagUnitBJ takes string s, unit whichUnit, real zOffset, real size, real red, real green, real blue, real transparency returns texttag
6473
    set bj_lastCreatedTextTag = CreateTextTag()
6474
    call SetTextTagTextBJ(bj_lastCreatedTextTag, s, size)
6475
    call SetTextTagPosUnitBJ(bj_lastCreatedTextTag, whichUnit, zOffset)
6476
    call SetTextTagColorBJ(bj_lastCreatedTextTag, red, green, blue, transparency)
6477
6478
    return bj_lastCreatedTextTag
6479
endfunction
6480
6481
//===========================================================================
6482
function DestroyTextTagBJ takes texttag tt returns nothing
6483
    call DestroyTextTag(tt)
6484
endfunction
6485
6486
//===========================================================================
6487
function ShowTextTagForceBJ takes boolean show, texttag tt, force whichForce returns nothing
6488
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6489
        // Use only local code (no net traffic) within this block to avoid desyncs.
6490
        call SetTextTagVisibility(tt, show)
6491
    endif
6492
endfunction
6493
6494
//===========================================================================
6495
function GetLastCreatedTextTag takes nothing returns texttag
6496
    return bj_lastCreatedTextTag
6497
endfunction
6498
6499
6500
6501
//***************************************************************************
6502
//*
6503
//*  Cinematic Utility Functions
6504
//*
6505
//***************************************************************************
6506
6507
//===========================================================================
6508
function PauseGameOn takes nothing returns nothing
6509
    call PauseGame(true)
6510
endfunction
6511
6512
//===========================================================================
6513
function PauseGameOff takes nothing returns nothing
6514
    call PauseGame(false)
6515
endfunction
6516
6517
//===========================================================================
6518
function SetUserControlForceOn takes force whichForce returns nothing
6519
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6520
        // Use only local code (no net traffic) within this block to avoid desyncs.
6521
        call EnableUserControl(true)
6522
    endif
6523
endfunction
6524
6525
//===========================================================================
6526
function SetUserControlForceOff takes force whichForce returns nothing
6527
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6528
        // Use only local code (no net traffic) within this block to avoid desyncs.
6529
        call EnableUserControl(false)
6530
    endif
6531
endfunction
6532
6533
//===========================================================================
6534
function ShowInterfaceForceOn takes force whichForce, real fadeDuration returns nothing
6535
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6536
        // Use only local code (no net traffic) within this block to avoid desyncs.
6537
        call ShowInterface(true, fadeDuration)
6538
    endif
6539
endfunction
6540
6541
//===========================================================================
6542
function ShowInterfaceForceOff takes force whichForce, real fadeDuration returns nothing
6543
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6544
        // Use only local code (no net traffic) within this block to avoid desyncs.
6545
        call ShowInterface(false, fadeDuration)
6546
    endif
6547
endfunction
6548
6549
//===========================================================================
6550
function PingMinimapForForce takes force whichForce, real x, real y, real duration returns nothing
6551
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6552
        // Use only local code (no net traffic) within this block to avoid desyncs.
6553
        call PingMinimap(x, y, duration)
6554
        //call StartSound(bj_pingMinimapSound)
6555
    endif
6556
endfunction
6557
6558
//===========================================================================
6559
function PingMinimapLocForForce takes force whichForce, location loc, real duration returns nothing
6560
    call PingMinimapForForce(whichForce, GetLocationX(loc), GetLocationY(loc), duration)
6561
endfunction
6562
6563
//===========================================================================
6564
function PingMinimapForPlayer takes player whichPlayer, real x, real y, real duration returns nothing
6565
    if (GetLocalPlayer() == whichPlayer) then
6566
        // Use only local code (no net traffic) within this block to avoid desyncs.
6567
        call PingMinimap(x, y, duration)
6568
        //call StartSound(bj_pingMinimapSound)
6569
    endif
6570
endfunction
6571
6572
//===========================================================================
6573
function PingMinimapLocForPlayer takes player whichPlayer, location loc, real duration returns nothing
6574
    call PingMinimapForPlayer(whichPlayer, GetLocationX(loc), GetLocationY(loc), duration)
6575
endfunction
6576
6577
//===========================================================================
6578
function PingMinimapForForceEx takes force whichForce, real x, real y, real duration, integer style, real red, real green, real blue returns nothing
6579
    local integer red255   = PercentTo255(red)
6580
    local integer green255 = PercentTo255(green)
6581
    local integer blue255  = PercentTo255(blue)
6582
6583
    if (IsPlayerInForce(GetLocalPlayer(), whichForce)) then
6584
        // Use only local code (no net traffic) within this block to avoid desyncs.
6585
6586
        // Prevent 100% red simple and flashy pings, as they become "attack" pings.
6587
        if (red255 == 255) and (green255 == 0) and (blue255 == 0) then
6588
            set red255 = 254
6589
        endif
6590
6591
        if (style == bj_MINIMAPPINGSTYLE_SIMPLE) then
6592
            call PingMinimapEx(x, y, duration, red255, green255, blue255, false)
6593
        elseif (style == bj_MINIMAPPINGSTYLE_FLASHY) then
6594
            call PingMinimapEx(x, y, duration, red255, green255, blue255, true)
6595
        elseif (style == bj_MINIMAPPINGSTYLE_ATTACK) then
6596
            call PingMinimapEx(x, y, duration, 255, 0, 0, false)
6597
        else
6598
            // Unrecognized ping style - ignore the request.
6599
        endif
6600
        
6601
        //call StartSound(bj_pingMinimapSound)
6602
    endif
6603
endfunction
6604
6605
//===========================================================================
6606
function PingMinimapLocForForceEx takes force whichForce, location loc, real duration, integer style, real red, real green, real blue returns nothing
6607
    call PingMinimapForForceEx(whichForce, GetLocationX(loc), GetLocationY(loc), duration, style, red, green, blue)
6608
endfunction
6609
6610
//===========================================================================
6611
function EnableWorldFogBoundaryBJ takes boolean enable, force f returns nothing
6612
    if (IsPlayerInForce(GetLocalPlayer(), f)) then
6613
        // Use only local code (no net traffic) within this block to avoid desyncs.
6614
        call EnableWorldFogBoundary(enable)
6615
    endif
6616
endfunction
6617
6618
//===========================================================================
6619
function EnableOcclusionBJ takes boolean enable, force f returns nothing
6620
    if (IsPlayerInForce(GetLocalPlayer(), f)) then
6621
        // Use only local code (no net traffic) within this block to avoid desyncs.
6622
        call EnableOcclusion(enable)
6623
    endif
6624
endfunction
6625
6626
6627
6628
//***************************************************************************
6629
//*
6630
//*  Cinematic Transmission Utility Functions
6631
//*
6632
//***************************************************************************
6633
6634
//===========================================================================
6635
// If cancelled, stop the sound and end the cinematic scene.
6636
//
6637
function CancelCineSceneBJ takes nothing returns nothing
6638
    call StopSoundBJ(bj_cineSceneLastSound, true)
6639
    call EndCinematicScene()
6640
endfunction
6641
6642
//===========================================================================
6643
// Init a trigger to listen for END_CINEMATIC events and respond to them if
6644
// a cinematic scene is in progress.  For performance reasons, this should
6645
// only be called once a cinematic scene has been started, so that maps
6646
// lacking such scenes do not bother to register for these events.
6647
//
6648
function TryInitCinematicBehaviorBJ takes nothing returns nothing
6649
    local integer index
6650
6651
    if (bj_cineSceneBeingSkipped == null) then
6652
        set bj_cineSceneBeingSkipped = CreateTrigger()
6653
        set index = 0
6654
        loop
6655
            call TriggerRegisterPlayerEvent(bj_cineSceneBeingSkipped, Player(index), EVENT_PLAYER_END_CINEMATIC)
6656
            set index = index + 1
6657
            exitwhen index == bj_MAX_PLAYERS
6658
        endloop
6659
        call TriggerAddAction(bj_cineSceneBeingSkipped, function CancelCineSceneBJ)
6660
    endif
6661
endfunction
6662
6663
//===========================================================================
6664
function SetCinematicSceneBJ takes sound soundHandle, integer portraitUnitId, playercolor color, string speakerTitle, string text, real sceneDuration, real voiceoverDuration returns nothing
6665
    set bj_cineSceneLastSound = soundHandle
6666
    call SetCinematicScene(portraitUnitId, color, speakerTitle, text, sceneDuration, voiceoverDuration)
6667
    call PlaySoundBJ(soundHandle)
6668
endfunction
6669
6670
//===========================================================================
6671
function GetTransmissionDuration takes sound soundHandle, integer timeType, real timeVal returns real
6672
    local real duration
6673
6674
    if (timeType == bj_TIMETYPE_ADD) then
6675
        set duration = GetSoundDurationBJ(soundHandle) + timeVal
6676
    elseif (timeType == bj_TIMETYPE_SET) then
6677
        set duration = timeVal
6678
    elseif (timeType == bj_TIMETYPE_SUB) then
6679
        set duration = GetSoundDurationBJ(soundHandle) - timeVal
6680
    else
6681
        // Unrecognized timeType - ignore timeVal.
6682
        set duration = GetSoundDurationBJ(soundHandle)
6683
    endif
6684
6685
    // Make sure we have a non-negative duration.
6686
    if (duration < 0) then
6687
        set duration = 0
6688
    endif
6689
    return duration
6690
endfunction
6691
6692
//===========================================================================
6693
function WaitTransmissionDuration takes sound soundHandle, integer timeType, real timeVal returns nothing
6694
    if (timeType == bj_TIMETYPE_SET) then
6695
        // If we have a static duration wait, just perform the wait.
6696
        call TriggerSleepAction(timeVal)
6697
6698
    elseif (soundHandle == null) then
6699
        // If the sound does not exist, perform a default length wait.
6700
        call TriggerSleepAction(bj_NOTHING_SOUND_DURATION)
6701
6702
    elseif (timeType == bj_TIMETYPE_SUB) then
6703
        // If the transmission is cutting off the sound, wait for the sound
6704
        // to be mostly finished.
6705
        call WaitForSoundBJ(soundHandle, timeVal)
6706
6707
    elseif (timeType == bj_TIMETYPE_ADD) then
6708
        // If the transmission is extending beyond the sound's length, wait
6709
        // for it to finish, and then wait the additional time.
6710
        call WaitForSoundBJ(soundHandle, 0)
6711
        call TriggerSleepAction(timeVal)
6712
6713
    else
6714
        // Unrecognized timeType - ignore.
6715
    endif
6716
endfunction
6717
6718
//===========================================================================
6719
function DoTransmissionBasicsXYBJ takes integer unitId, playercolor color, real x, real y, sound soundHandle, string unitName, string message, real duration returns nothing
6720
    call SetCinematicSceneBJ(soundHandle, unitId, color, unitName, message, duration + bj_TRANSMISSION_PORT_HANGTIME, duration)
6721
6722
    if (unitId != 0) then
6723
        call PingMinimap(x, y, bj_TRANSMISSION_PING_TIME)
6724
        //call SetCameraQuickPosition(x, y)
6725
    endif
6726
endfunction
6727
6728
//===========================================================================
6729
// Display a text message to a Player Group with an accompanying sound,
6730
// portrait, speech indicator, and all that good stuff.
6731
//   - Query duration of sound
6732
//   - Play sound
6733
//   - Display text message for duration
6734
//   - Display animating portrait for duration
6735
//   - Display a speech indicator for the unit
6736
//   - Ping the minimap
6737
//
6738
function TransmissionFromUnitWithNameBJ takes force toForce, unit whichUnit, string unitName, sound soundHandle, string message, integer timeType, real timeVal, boolean wait returns nothing
6739
    call TryInitCinematicBehaviorBJ()
6740
6741
    call AttachSoundToUnit(soundHandle, whichUnit)
6742
6743
    // Ensure that the time value is non-negative.
6744
    set timeVal = RMaxBJ(timeVal, 0)
6745
6746
    set bj_lastTransmissionDuration = GetTransmissionDuration(soundHandle, timeType, timeVal)
6747
    set bj_lastPlayedSound = soundHandle
6748
6749
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
6750
        // Use only local code (no net traffic) within this block to avoid desyncs.
6751
6752
        if (whichUnit == null) then
6753
            // If the unit reference is invalid, send the transmission from the center of the map with no portrait.
6754
            call DoTransmissionBasicsXYBJ(0, PLAYER_COLOR_RED, 0, 0, soundHandle, unitName, message, bj_lastTransmissionDuration)
6755
        else
6756
            call DoTransmissionBasicsXYBJ(GetUnitTypeId(whichUnit), GetPlayerColor(GetOwningPlayer(whichUnit)), GetUnitX(whichUnit), GetUnitY(whichUnit), soundHandle, unitName, message, bj_lastTransmissionDuration)
6757
            if (not IsUnitHidden(whichUnit)) then
6758
                call UnitAddIndicator(whichUnit, bj_TRANSMISSION_IND_RED, bj_TRANSMISSION_IND_BLUE, bj_TRANSMISSION_IND_GREEN, bj_TRANSMISSION_IND_ALPHA)
6759
            endif
6760
        endif
6761
    endif
6762
6763
    if wait and (bj_lastTransmissionDuration > 0) then
6764
        // call TriggerSleepAction(bj_lastTransmissionDuration)
6765
        call WaitTransmissionDuration(soundHandle, timeType, timeVal)
6766
    endif
6767
6768
endfunction
6769
6770
//===========================================================================
6771
function PlayDialogueFromSpeakerEx takes force toForce, unit speaker, integer speakerType, sound soundHandle, integer timeType, real timeVal, boolean wait returns boolean
6772
    //Make sure that the runtime unit type and the parameter are the same,
6773
    //otherwise the offline animations will not match and will fail
6774
    if GetUnitTypeId(speaker) != speakerType then
6775
        debug call BJDebugMsg(("Attempted to play FacialAnimation with the wrong speaker UnitType - Param: " + I2S(speakerType) + " Runtime: " +  I2S(GetUnitTypeId(speaker))))
6776
        //return false
6777
    endif
6778
6779
    call TryInitCinematicBehaviorBJ()
6780
6781
    call AttachSoundToUnit(soundHandle, speaker)
6782
6783
    // Ensure that the time value is non-negative.
6784
    set timeVal = RMaxBJ(timeVal, 0)
6785
6786
    set bj_lastTransmissionDuration = GetTransmissionDuration(soundHandle, timeType, timeVal)
6787
    set bj_lastPlayedSound = soundHandle
6788
6789
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
6790
        call SetCinematicSceneBJ(soundHandle, speakerType, GetPlayerColor(GetOwningPlayer(speaker)), GetLocalizedString(GetDialogueSpeakerNameKey(soundHandle)), GetLocalizedString(GetDialogueTextKey(soundHandle)), bj_lastTransmissionDuration + bj_TRANSMISSION_PORT_HANGTIME, bj_lastTransmissionDuration)
6791
    endif
6792
6793
    if wait and (bj_lastTransmissionDuration > 0) then
6794
        // call TriggerSleepAction(bj_lastTransmissionDuration)
6795
        call WaitTransmissionDuration(soundHandle, timeType, timeVal)
6796
    endif
6797
6798
    return true
6799
endfunction
6800
6801
//===========================================================================
6802
function PlayDialogueFromSpeakerTypeEx takes force toForce, player fromPlayer, integer speakerType, location loc, sound soundHandle, integer timeType, real timeVal, boolean wait returns boolean
6803
    call TryInitCinematicBehaviorBJ()
6804
6805
    // Ensure that the time value is non-negative.
6806
    set timeVal = RMaxBJ(timeVal, 0)
6807
6808
    set bj_lastTransmissionDuration = GetTransmissionDuration(soundHandle, timeType, timeVal)
6809
    set bj_lastPlayedSound = soundHandle
6810
6811
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
6812
        call SetCinematicSceneBJ(soundHandle, speakerType, GetPlayerColor(fromPlayer), GetLocalizedString(GetDialogueSpeakerNameKey(soundHandle)), GetLocalizedString(GetDialogueTextKey(soundHandle)), bj_lastTransmissionDuration + bj_TRANSMISSION_PORT_HANGTIME, bj_lastTransmissionDuration)
6813
        if(speakerType != 0) then
6814
            call PingMinimap(GetLocationX(loc), GetLocationY(loc), bj_TRANSMISSION_PING_TIME)
6815
        endif
6816
    endif
6817
6818
    if wait and (bj_lastTransmissionDuration > 0) then
6819
        // call TriggerSleepAction(bj_lastTransmissionDuration)
6820
        call WaitTransmissionDuration(soundHandle, timeType, timeVal)
6821
    endif
6822
6823
    return true
6824
endfunction
6825
6826
//===========================================================================
6827
// This operates like TransmissionFromUnitWithNameBJ, but for a unit type
6828
// rather than a unit instance.  As such, no speech indicator is employed.
6829
//
6830
function TransmissionFromUnitTypeWithNameBJ takes force toForce, player fromPlayer, integer unitId, string unitName, location loc, sound soundHandle, string message, integer timeType, real timeVal, boolean wait returns nothing
6831
    call TryInitCinematicBehaviorBJ()
6832
6833
    // Ensure that the time value is non-negative.
6834
    set timeVal = RMaxBJ(timeVal, 0)
6835
6836
    set bj_lastTransmissionDuration = GetTransmissionDuration(soundHandle, timeType, timeVal)
6837
    set bj_lastPlayedSound = soundHandle
6838
6839
    if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
6840
        // Use only local code (no net traffic) within this block to avoid desyncs.
6841
6842
        call DoTransmissionBasicsXYBJ(unitId, GetPlayerColor(fromPlayer), GetLocationX(loc), GetLocationY(loc), soundHandle, unitName, message, bj_lastTransmissionDuration)
6843
    endif
6844
6845
    if wait and (bj_lastTransmissionDuration > 0) then
6846
        // call TriggerSleepAction(bj_lastTransmissionDuration)
6847
        call WaitTransmissionDuration(soundHandle, timeType, timeVal)
6848
    endif
6849
6850
endfunction
6851
6852
//===========================================================================
6853
function GetLastTransmissionDurationBJ takes nothing returns real
6854
    return bj_lastTransmissionDuration
6855
endfunction
6856
6857
//===========================================================================
6858
function ForceCinematicSubtitlesBJ takes boolean flag returns nothing
6859
    call ForceCinematicSubtitles(flag)
6860
endfunction
6861
6862
6863
//***************************************************************************
6864
//*
6865
//*  Cinematic Mode Utility Functions
6866
//*
6867
//***************************************************************************
6868
6869
//===========================================================================
6870
// Makes many common UI settings changes at once, for use when beginning and
6871
// ending cinematic sequences.  Note that some affects apply to all players,
6872
// such as game speed.  This is unavoidable.
6873
//   - Clear the screen of text messages
6874
//   - Hide interface UI (letterbox mode)
6875
//   - Hide game messages (ally under attack, etc.)
6876
//   - Disable user control
6877
//   - Disable occlusion
6878
//   - Set game speed (for all players)
6879
//   - Lock game speed (for all players)
6880
//   - Disable black mask (for all players)
6881
//   - Disable fog of war (for all players)
6882
//   - Disable world boundary fog (for all players)
6883
//   - Dim non-speech sound channels
6884
//   - End any outstanding music themes
6885
//   - Fix the random seed to a set value
6886
//   - Reset the camera smoothing factor
6887
//
6888
function CinematicModeExBJ takes boolean cineMode, force forForce, real interfaceFadeTime returns nothing
6889
    // If the game hasn't started yet, perform interface fades immediately
6890
    if (not bj_gameStarted) then
6891
        set interfaceFadeTime = 0
6892
    endif
6893
6894
    if (cineMode) then
6895
        // Save the UI state so that we can restore it later.
6896
        if (not bj_cineModeAlreadyIn) then
6897
            call SetCinematicAudio(true)
6898
            set bj_cineModeAlreadyIn = true
6899
            set bj_cineModePriorSpeed = GetGameSpeed()
6900
            set bj_cineModePriorFogSetting = IsFogEnabled()
6901
            set bj_cineModePriorMaskSetting = IsFogMaskEnabled()
6902
            set bj_cineModePriorDawnDusk = IsDawnDuskEnabled()
6903
            set bj_cineModeSavedSeed = GetRandomInt(0, 1000000)
6904
        endif
6905
6906
        // Perform local changes
6907
        if (IsPlayerInForce(GetLocalPlayer(), forForce)) then
6908
            // Use only local code (no net traffic) within this block to avoid desyncs.
6909
            call ClearTextMessages()
6910
            call ShowInterface(false, interfaceFadeTime)
6911
            call EnableUserControl(false)
6912
            call EnableOcclusion(false)
6913
            call SetCineModeVolumeGroupsBJ()
6914
        endif
6915
6916
        // Perform global changes
6917
        call SetGameSpeed(bj_CINEMODE_GAMESPEED)
6918
        call SetMapFlag(MAP_LOCK_SPEED, true)
6919
        call FogMaskEnable(false)
6920
        call FogEnable(false)
6921
        call EnableWorldFogBoundary(false)
6922
        call EnableDawnDusk(false)
6923
6924
        // Use a fixed random seed, so that cinematics play consistently.
6925
        call SetRandomSeed(0)
6926
    else
6927
        set bj_cineModeAlreadyIn = false
6928
        call SetCinematicAudio(false)
6929
6930
        // Perform local changes
6931
        if (IsPlayerInForce(GetLocalPlayer(), forForce)) then
6932
            // Use only local code (no net traffic) within this block to avoid desyncs.
6933
            call ShowInterface(true, interfaceFadeTime)
6934
            call EnableUserControl(true)
6935
            call EnableOcclusion(true)
6936
            call VolumeGroupReset()
6937
            call EndThematicMusic()
6938
            call CameraResetSmoothingFactorBJ()
6939
        endif
6940
6941
        // Perform global changes
6942
        call SetMapFlag(MAP_LOCK_SPEED, false)
6943
        call SetGameSpeed(bj_cineModePriorSpeed)
6944
        call FogMaskEnable(bj_cineModePriorMaskSetting)
6945
        call FogEnable(bj_cineModePriorFogSetting)
6946
        call EnableWorldFogBoundary(true)
6947
        call EnableDawnDusk(bj_cineModePriorDawnDusk)
6948
        call SetRandomSeed(bj_cineModeSavedSeed)
6949
    endif
6950
endfunction
6951
6952
//===========================================================================
6953
function CinematicModeBJ takes boolean cineMode, force forForce returns nothing
6954
    call CinematicModeExBJ(cineMode, forForce, bj_CINEMODE_INTERFACEFADE)
6955
endfunction
6956
6957
6958
6959
//***************************************************************************
6960
//*
6961
//*  Cinematic Filter Utility Functions
6962
//*
6963
//***************************************************************************
6964
6965
//===========================================================================
6966
function DisplayCineFilterBJ takes boolean flag returns nothing
6967
    call DisplayCineFilter(flag)
6968
endfunction
6969
6970
//===========================================================================
6971
function CinematicFadeCommonBJ takes real red, real green, real blue, real duration, string tex, real startTrans, real endTrans returns nothing
6972
    if (duration == 0) then
6973
        // If the fade is instant, use the same starting and ending values,
6974
        // so that we effectively do a set rather than a fade.
6975
        set startTrans = endTrans
6976
    endif
6977
    call EnableUserUI(false)
6978
    call SetCineFilterTexture(tex)
6979
    call SetCineFilterBlendMode(BLEND_MODE_BLEND)
6980
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
6981
    call SetCineFilterStartUV(0, 0, 1, 1)
6982
    call SetCineFilterEndUV(0, 0, 1, 1)
6983
    call SetCineFilterStartColor(PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-startTrans))
6984
    call SetCineFilterEndColor(PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-endTrans))
6985
    call SetCineFilterDuration(duration)
6986
    call DisplayCineFilter(true)
6987
endfunction
6988
6989
//===========================================================================
6990
function FinishCinematicFadeBJ takes nothing returns nothing
6991
    call DestroyTimer(bj_cineFadeFinishTimer)
6992
    set bj_cineFadeFinishTimer = null
6993
    call DisplayCineFilter(false)
6994
    call EnableUserUI(true)
6995
endfunction
6996
6997
//===========================================================================
6998
function FinishCinematicFadeAfterBJ takes real duration returns nothing
6999
    // Create a timer to end the cinematic fade.
7000
    set bj_cineFadeFinishTimer = CreateTimer()
7001
    call TimerStart(bj_cineFadeFinishTimer, duration, false, function FinishCinematicFadeBJ)
7002
endfunction
7003
7004
//===========================================================================
7005
function ContinueCinematicFadeBJ takes nothing returns nothing
7006
    call DestroyTimer(bj_cineFadeContinueTimer)
7007
    set bj_cineFadeContinueTimer = null
7008
    call CinematicFadeCommonBJ(bj_cineFadeContinueRed, bj_cineFadeContinueGreen, bj_cineFadeContinueBlue, bj_cineFadeContinueDuration, bj_cineFadeContinueTex, bj_cineFadeContinueTrans, 100)
7009
endfunction
7010
7011
//===========================================================================
7012
function ContinueCinematicFadeAfterBJ takes real duration, real red, real green, real blue, real trans, string tex returns nothing
7013
    set bj_cineFadeContinueRed = red
7014
    set bj_cineFadeContinueGreen = green
7015
    set bj_cineFadeContinueBlue = blue
7016
    set bj_cineFadeContinueTrans = trans
7017
    set bj_cineFadeContinueDuration = duration
7018
    set bj_cineFadeContinueTex = tex
7019
7020
    // Create a timer to continue the cinematic fade.
7021
    set bj_cineFadeContinueTimer = CreateTimer()
7022
    call TimerStart(bj_cineFadeContinueTimer, duration, false, function ContinueCinematicFadeBJ)
7023
endfunction
7024
7025
//===========================================================================
7026
function AbortCinematicFadeBJ takes nothing returns nothing
7027
    if (bj_cineFadeContinueTimer != null) then
7028
        call DestroyTimer(bj_cineFadeContinueTimer)
7029
    endif
7030
7031
    if (bj_cineFadeFinishTimer != null) then
7032
        call DestroyTimer(bj_cineFadeFinishTimer)
7033
    endif
7034
endfunction
7035
7036
//===========================================================================
7037
function CinematicFadeBJ takes integer fadetype, real duration, string tex, real red, real green, real blue, real trans returns nothing
7038
    if (fadetype == bj_CINEFADETYPE_FADEOUT) then
7039
        // Fade out to the requested color.
7040
        call AbortCinematicFadeBJ()
7041
        call CinematicFadeCommonBJ(red, green, blue, duration, tex, 100, trans)
7042
    elseif (fadetype == bj_CINEFADETYPE_FADEIN) then
7043
        // Fade in from the requested color.
7044
        call AbortCinematicFadeBJ()
7045
        call CinematicFadeCommonBJ(red, green, blue, duration, tex, trans, 100)
7046
        call FinishCinematicFadeAfterBJ(duration)
7047
    elseif (fadetype == bj_CINEFADETYPE_FADEOUTIN) then
7048
        // Fade out to the requested color, and then fade back in from it.
7049
        if (duration > 0) then
7050
            call AbortCinematicFadeBJ()
7051
            call CinematicFadeCommonBJ(red, green, blue, duration * 0.5, tex, 100, trans)
7052
            call ContinueCinematicFadeAfterBJ(duration * 0.5, red, green, blue, trans, tex)
7053
            call FinishCinematicFadeAfterBJ(duration)
7054
        endif
7055
    else
7056
        // Unrecognized fadetype - ignore the request.
7057
    endif
7058
endfunction
7059
7060
//===========================================================================
7061
function CinematicFilterGenericBJ takes real duration, blendmode bmode, string tex, real red0, real green0, real blue0, real trans0, real red1, real green1, real blue1, real trans1 returns nothing
7062
    call AbortCinematicFadeBJ()
7063
    call SetCineFilterTexture(tex)
7064
    call SetCineFilterBlendMode(bmode)
7065
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
7066
    call SetCineFilterStartUV(0, 0, 1, 1)
7067
    call SetCineFilterEndUV(0, 0, 1, 1)
7068
    call SetCineFilterStartColor(PercentTo255(red0), PercentTo255(green0), PercentTo255(blue0), PercentTo255(100.0-trans0))
7069
    call SetCineFilterEndColor(PercentTo255(red1), PercentTo255(green1), PercentTo255(blue1), PercentTo255(100.0-trans1))
7070
    call SetCineFilterDuration(duration)
7071
    call DisplayCineFilter(true)
7072
endfunction
7073
7074
7075
7076
//***************************************************************************
7077
//*
7078
//*  Rescuable Unit Utility Functions
7079
//*
7080
//***************************************************************************
7081
7082
//===========================================================================
7083
// Rescues a unit for a player.  This performs the default rescue behavior,
7084
// including a rescue sound, flashing selection circle, ownership change,
7085
// and optionally a unit color change.
7086
//
7087
function RescueUnitBJ takes unit whichUnit, player rescuer, boolean changeColor returns nothing
7088
    if IsUnitDeadBJ(whichUnit) or (GetOwningPlayer(whichUnit) == rescuer) then
7089
        return
7090
    endif
7091
7092
    call StartSound(bj_rescueSound)
7093
    call SetUnitOwner(whichUnit, rescuer, changeColor)
7094
    call UnitAddIndicator(whichUnit, 0, 255, 0, 255)
7095
    call PingMinimapForPlayer(rescuer, GetUnitX(whichUnit), GetUnitY(whichUnit), bj_RESCUE_PING_TIME)
7096
endfunction
7097
7098
//===========================================================================
7099
function TriggerActionUnitRescuedBJ takes nothing returns nothing
7100
    local unit theUnit = GetTriggerUnit()
7101
7102
    if IsUnitType(theUnit, UNIT_TYPE_STRUCTURE) then
7103
        call RescueUnitBJ(theUnit, GetOwningPlayer(GetRescuer()), bj_rescueChangeColorBldg)
7104
    else
7105
        call RescueUnitBJ(theUnit, GetOwningPlayer(GetRescuer()), bj_rescueChangeColorUnit)
7106
    endif
7107
endfunction
7108
7109
//===========================================================================
7110
// Attempt to init triggers for default rescue behavior.  For performance
7111
// reasons, this should only be attempted if a player is set to Rescuable,
7112
// or if a specific unit is thus flagged.
7113
//
7114
function TryInitRescuableTriggersBJ takes nothing returns nothing
7115
    local integer index
7116
7117
    if (bj_rescueUnitBehavior == null) then
7118
        set bj_rescueUnitBehavior = CreateTrigger()
7119
        set index = 0
7120
        loop
7121
            call TriggerRegisterPlayerUnitEvent(bj_rescueUnitBehavior, Player(index), EVENT_PLAYER_UNIT_RESCUED, null)
7122
            set index = index + 1
7123
            exitwhen index == bj_MAX_PLAYER_SLOTS
7124
        endloop
7125
        call TriggerAddAction(bj_rescueUnitBehavior, function TriggerActionUnitRescuedBJ)
7126
    endif
7127
endfunction
7128
7129
//===========================================================================
7130
// Determines whether or not rescued units automatically change color upon
7131
// being rescued.
7132
//
7133
function SetRescueUnitColorChangeBJ takes boolean changeColor returns nothing
7134
    set bj_rescueChangeColorUnit = changeColor
7135
endfunction
7136
7137
//===========================================================================
7138
// Determines whether or not rescued buildings automatically change color
7139
// upon being rescued.
7140
//
7141
function SetRescueBuildingColorChangeBJ takes boolean changeColor returns nothing
7142
    set bj_rescueChangeColorBldg = changeColor
7143
endfunction
7144
7145
//===========================================================================
7146
function MakeUnitRescuableToForceBJEnum takes nothing returns nothing
7147
    call TryInitRescuableTriggersBJ()
7148
    call SetUnitRescuable(bj_makeUnitRescuableUnit, GetEnumPlayer(), bj_makeUnitRescuableFlag)
7149
endfunction
7150
7151
//===========================================================================
7152
function MakeUnitRescuableToForceBJ takes unit whichUnit, boolean isRescuable, force whichForce returns nothing
7153
    // Flag the unit as rescuable/unrescuable for the appropriate players.
7154
    set bj_makeUnitRescuableUnit = whichUnit
7155
    set bj_makeUnitRescuableFlag = isRescuable
7156
    call ForForce(whichForce, function MakeUnitRescuableToForceBJEnum)
7157
endfunction
7158
7159
//===========================================================================
7160
function InitRescuableBehaviorBJ takes nothing returns nothing
7161
    local integer index
7162
7163
    set index = 0
7164
    loop
7165
        // If at least one player slot is "Rescuable"-controlled, init the
7166
        // rescue behavior triggers.
7167
        if (GetPlayerController(Player(index)) == MAP_CONTROL_RESCUABLE) then
7168
            call TryInitRescuableTriggersBJ()
7169
            return
7170
        endif
7171
        set index = index + 1
7172
        exitwhen index == bj_MAX_PLAYERS
7173
    endloop
7174
endfunction
7175
7176
7177
7178
//***************************************************************************
7179
//*
7180
//*  Research and Upgrade Utility Functions
7181
//*
7182
//***************************************************************************
7183
7184
//===========================================================================
7185
function SetPlayerTechResearchedSwap takes integer techid, integer levels, player whichPlayer returns nothing
7186
    call SetPlayerTechResearched(whichPlayer, techid, levels)
7187
endfunction
7188
7189
//===========================================================================
7190
function SetPlayerTechMaxAllowedSwap takes integer techid, integer maximum, player whichPlayer returns nothing
7191
    call SetPlayerTechMaxAllowed(whichPlayer, techid, maximum)
7192
endfunction
7193
7194
//===========================================================================
7195
function SetPlayerMaxHeroesAllowed takes integer maximum, player whichPlayer returns nothing
7196
    call SetPlayerTechMaxAllowed(whichPlayer, 'HERO', maximum)
7197
endfunction
7198
7199
//===========================================================================
7200
function GetPlayerTechCountSimple takes integer techid, player whichPlayer returns integer
7201
    return GetPlayerTechCount(whichPlayer, techid, true)
7202
endfunction
7203
7204
//===========================================================================
7205
function GetPlayerTechMaxAllowedSwap takes integer techid, player whichPlayer returns integer
7206
    return GetPlayerTechMaxAllowed(whichPlayer, techid)
7207
endfunction
7208
7209
//===========================================================================
7210
function SetPlayerAbilityAvailableBJ takes boolean avail, integer abilid, player whichPlayer returns nothing
7211
    call SetPlayerAbilityAvailable(whichPlayer, abilid, avail)
7212
endfunction
7213
7214
7215
7216
//***************************************************************************
7217
//*
7218
//*  Campaign Utility Functions
7219
//*
7220
//***************************************************************************
7221
7222
function SetCampaignMenuRaceBJ takes integer campaignNumber returns nothing
7223
    if (campaignNumber == bj_CAMPAIGN_INDEX_T) then
7224
        call SetCampaignMenuRace(RACE_OTHER)
7225
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_H) then
7226
        call SetCampaignMenuRace(RACE_HUMAN)
7227
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_U) then
7228
        call SetCampaignMenuRace(RACE_UNDEAD)
7229
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_O) then
7230
        call SetCampaignMenuRace(RACE_ORC)
7231
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_N) then
7232
        call SetCampaignMenuRace(RACE_NIGHTELF)
7233
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XN) then
7234
        call SetCampaignMenuRaceEx(bj_CAMPAIGN_OFFSET_XN)
7235
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XH) then
7236
        call SetCampaignMenuRaceEx(bj_CAMPAIGN_OFFSET_XH)
7237
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XU) then
7238
        call SetCampaignMenuRaceEx(bj_CAMPAIGN_OFFSET_XU)
7239
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XO) then
7240
        call SetCampaignMenuRaceEx(bj_CAMPAIGN_OFFSET_XO)
7241
    else
7242
        // Unrecognized campaign - ignore the request
7243
    endif
7244
endfunction
7245
7246
//===========================================================================
7247
// Converts a single campaign mission designation into campaign and mission
7248
// numbers.  The 1000's digit is considered the campaign index, and the 1's
7249
// digit is considered the mission index within that campaign.  This is done
7250
// so that the trigger for this can use a single drop-down to list all of
7251
// the campaign missions.
7252
//
7253
function SetMissionAvailableBJ takes boolean available, integer missionIndex returns nothing
7254
    local integer campaignNumber = missionIndex / 1000
7255
    local integer missionNumber = missionIndex - campaignNumber * 1000
7256
7257
    call SetMissionAvailable(campaignNumber, missionNumber, available)
7258
endfunction
7259
7260
//===========================================================================
7261
function SetCampaignAvailableBJ takes boolean available, integer campaignNumber returns nothing
7262
    local integer campaignOffset
7263
7264
    if (campaignNumber == bj_CAMPAIGN_INDEX_H) then
7265
        call SetTutorialCleared(true)
7266
    endif
7267
7268
    if (campaignNumber == bj_CAMPAIGN_INDEX_XN) then
7269
        set campaignOffset = bj_CAMPAIGN_OFFSET_XN
7270
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XH) then
7271
        set campaignOffset = bj_CAMPAIGN_OFFSET_XH
7272
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XU) then
7273
        set campaignOffset = bj_CAMPAIGN_OFFSET_XU
7274
    elseif (campaignNumber == bj_CAMPAIGN_INDEX_XO) then
7275
        set campaignOffset = bj_CAMPAIGN_OFFSET_XO
7276
    else
7277
        set campaignOffset = campaignNumber
7278
    endif
7279
7280
    call SetCampaignAvailable(campaignOffset, available)
7281
    call SetCampaignMenuRaceBJ(campaignNumber)
7282
    call ForceCampaignSelectScreen()
7283
endfunction
7284
7285
//===========================================================================
7286
function SetCinematicAvailableBJ takes boolean available, integer cinematicIndex returns nothing
7287
    if ( cinematicIndex == bj_CINEMATICINDEX_TOP ) then
7288
        call SetOpCinematicAvailable( bj_CAMPAIGN_INDEX_T, available )
7289
        call PlayCinematic( "TutorialOp" )
7290
    elseif (cinematicIndex == bj_CINEMATICINDEX_HOP) then
7291
        call SetOpCinematicAvailable( bj_CAMPAIGN_INDEX_H, available )
7292
        call PlayCinematic( "HumanOp" )
7293
    elseif (cinematicIndex == bj_CINEMATICINDEX_HED) then
7294
        call SetEdCinematicAvailable( bj_CAMPAIGN_INDEX_H, available )
7295
        call PlayCinematic( "HumanEd" )
7296
    elseif (cinematicIndex == bj_CINEMATICINDEX_OOP) then
7297
        call SetOpCinematicAvailable( bj_CAMPAIGN_INDEX_O, available )
7298
        call PlayCinematic( "OrcOp" )
7299
    elseif (cinematicIndex == bj_CINEMATICINDEX_OED) then
7300
        call SetEdCinematicAvailable( bj_CAMPAIGN_INDEX_O, available )
7301
        call PlayCinematic( "OrcEd" )
7302
    elseif (cinematicIndex == bj_CINEMATICINDEX_UOP) then
7303
        call SetEdCinematicAvailable( bj_CAMPAIGN_INDEX_U, available )
7304
        call PlayCinematic( "UndeadOp" )
7305
    elseif (cinematicIndex == bj_CINEMATICINDEX_UED) then
7306
        call SetEdCinematicAvailable( bj_CAMPAIGN_INDEX_U, available )
7307
        call PlayCinematic( "UndeadEd" )
7308
    elseif (cinematicIndex == bj_CINEMATICINDEX_NOP) then
7309
        call SetEdCinematicAvailable( bj_CAMPAIGN_INDEX_N, available )
7310
        call PlayCinematic( "NightElfOp" )
7311
    elseif (cinematicIndex == bj_CINEMATICINDEX_NED) then
7312
        call SetEdCinematicAvailable( bj_CAMPAIGN_INDEX_N, available )
7313
        call PlayCinematic( "NightElfEd" )
7314
    elseif (cinematicIndex == bj_CINEMATICINDEX_XOP) then
7315
        call SetOpCinematicAvailable( bj_CAMPAIGN_OFFSET_XN, available )
7316
        // call PlayCinematic( "IntroX" )
7317
    elseif (cinematicIndex == bj_CINEMATICINDEX_XED) then
7318
        call SetEdCinematicAvailable( bj_CAMPAIGN_OFFSET_XU, available )
7319
        call PlayCinematic( "OutroX" )
7320
    else
7321
        // Unrecognized cinematic - ignore the request.
7322
    endif
7323
endfunction
7324
7325
//===========================================================================
7326
function InitGameCacheBJ takes string campaignFile returns gamecache
7327
    set bj_lastCreatedGameCache = InitGameCache(campaignFile)
7328
    return bj_lastCreatedGameCache
7329
endfunction
7330
7331
//===========================================================================
7332
function SaveGameCacheBJ takes gamecache cache returns boolean
7333
    return SaveGameCache(cache)
7334
endfunction
7335
7336
//===========================================================================
7337
function GetLastCreatedGameCacheBJ takes nothing returns gamecache
7338
    return bj_lastCreatedGameCache
7339
endfunction
7340
7341
//===========================================================================
7342
function InitHashtableBJ takes nothing returns hashtable
7343
    set bj_lastCreatedHashtable = InitHashtable()
7344
    return bj_lastCreatedHashtable
7345
endfunction
7346
7347
//===========================================================================
7348
function GetLastCreatedHashtableBJ takes nothing returns hashtable
7349
    return bj_lastCreatedHashtable
7350
endfunction
7351
7352
//===========================================================================
7353
function StoreRealBJ takes real value, string key, string missionKey, gamecache cache returns nothing
7354
    call StoreReal(cache, missionKey, key, value)
7355
endfunction
7356
7357
//===========================================================================
7358
function StoreIntegerBJ takes integer value, string key, string missionKey, gamecache cache returns nothing
7359
    call StoreInteger(cache, missionKey, key, value)
7360
endfunction
7361
7362
//===========================================================================
7363
function StoreBooleanBJ takes boolean value, string key, string missionKey, gamecache cache returns nothing
7364
    call StoreBoolean(cache, missionKey, key, value)
7365
endfunction
7366
7367
//===========================================================================
7368
function StoreStringBJ takes string value, string key, string missionKey, gamecache cache returns boolean
7369
    return StoreString(cache, missionKey, key, value)
7370
endfunction
7371
7372
//===========================================================================
7373
function StoreUnitBJ takes unit whichUnit, string key, string missionKey, gamecache cache returns boolean
7374
    return StoreUnit(cache, missionKey, key, whichUnit)
7375
endfunction
7376
7377
//===========================================================================
7378
function SaveRealBJ takes real value, integer key, integer missionKey, hashtable table returns nothing
7379
    call SaveReal(table, missionKey, key, value)
7380
endfunction
7381
7382
//===========================================================================
7383
function SaveIntegerBJ takes integer value, integer key, integer missionKey, hashtable table returns nothing
7384
    call SaveInteger(table, missionKey, key, value)
7385
endfunction
7386
7387
//===========================================================================
7388
function SaveBooleanBJ takes boolean value, integer key, integer missionKey, hashtable table returns nothing
7389
    call SaveBoolean(table, missionKey, key, value)
7390
endfunction
7391
7392
//===========================================================================
7393
function SaveStringBJ takes string value, integer key, integer missionKey, hashtable table returns boolean
7394
    return SaveStr(table, missionKey, key, value)
7395
endfunction
7396
7397
//===========================================================================
7398
function SavePlayerHandleBJ takes player whichPlayer, integer key, integer missionKey, hashtable table returns boolean
7399
    return SavePlayerHandle(table, missionKey, key, whichPlayer)
7400
endfunction
7401
7402
//===========================================================================
7403
function SaveWidgetHandleBJ takes widget whichWidget, integer key, integer missionKey, hashtable table returns boolean
7404
    return SaveWidgetHandle(table, missionKey, key, whichWidget)
7405
endfunction
7406
7407
//===========================================================================
7408
function SaveDestructableHandleBJ takes destructable whichDestructable, integer key, integer missionKey, hashtable table returns boolean
7409
    return SaveDestructableHandle(table, missionKey, key, whichDestructable)
7410
endfunction
7411
7412
//===========================================================================
7413
function SaveItemHandleBJ takes item whichItem, integer key, integer missionKey, hashtable table returns boolean
7414
    return SaveItemHandle(table, missionKey, key, whichItem)
7415
endfunction
7416
7417
//===========================================================================
7418
function SaveUnitHandleBJ takes unit whichUnit, integer key, integer missionKey, hashtable table returns boolean
7419
    return SaveUnitHandle(table, missionKey, key, whichUnit)
7420
endfunction
7421
7422
//===========================================================================
7423
function SaveAbilityHandleBJ takes ability whichAbility, integer key, integer missionKey, hashtable table returns boolean
7424
    return SaveAbilityHandle(table, missionKey, key, whichAbility)
7425
endfunction
7426
7427
//===========================================================================
7428
function SaveTimerHandleBJ takes timer whichTimer, integer key, integer missionKey, hashtable table returns boolean
7429
    return SaveTimerHandle(table, missionKey, key, whichTimer)
7430
endfunction
7431
7432
//===========================================================================
7433
function SaveTriggerHandleBJ takes trigger whichTrigger, integer key, integer missionKey, hashtable table returns boolean
7434
    return SaveTriggerHandle(table, missionKey, key, whichTrigger)
7435
endfunction
7436
7437
//===========================================================================
7438
function SaveTriggerConditionHandleBJ takes triggercondition whichTriggercondition, integer key, integer missionKey, hashtable table returns boolean
7439
    return SaveTriggerConditionHandle(table, missionKey, key, whichTriggercondition)
7440
endfunction
7441
7442
//===========================================================================
7443
function SaveTriggerActionHandleBJ takes triggeraction whichTriggeraction, integer key, integer missionKey, hashtable table returns boolean
7444
    return SaveTriggerActionHandle(table, missionKey, key, whichTriggeraction)
7445
endfunction
7446
7447
//===========================================================================
7448
function SaveTriggerEventHandleBJ takes event whichEvent, integer key, integer missionKey, hashtable table returns boolean
7449
    return SaveTriggerEventHandle(table, missionKey, key, whichEvent)
7450
endfunction
7451
7452
//===========================================================================
7453
function SaveForceHandleBJ takes force whichForce, integer key, integer missionKey, hashtable table returns boolean
7454
    return SaveForceHandle(table, missionKey, key, whichForce)
7455
endfunction
7456
7457
//===========================================================================
7458
function SaveGroupHandleBJ takes group whichGroup, integer key, integer missionKey, hashtable table returns boolean
7459
    return SaveGroupHandle(table, missionKey, key, whichGroup)
7460
endfunction
7461
7462
//===========================================================================
7463
function SaveLocationHandleBJ takes location whichLocation, integer key, integer missionKey, hashtable table returns boolean
7464
    return SaveLocationHandle(table, missionKey, key, whichLocation)
7465
endfunction
7466
7467
//===========================================================================
7468
function SaveRectHandleBJ takes rect whichRect, integer key, integer missionKey, hashtable table returns boolean
7469
    return SaveRectHandle(table, missionKey, key, whichRect)
7470
endfunction
7471
7472
//===========================================================================
7473
function SaveBooleanExprHandleBJ takes boolexpr whichBoolexpr, integer key, integer missionKey, hashtable table returns boolean
7474
    return SaveBooleanExprHandle(table, missionKey, key, whichBoolexpr)
7475
endfunction
7476
7477
//===========================================================================
7478
function SaveSoundHandleBJ takes sound whichSound, integer key, integer missionKey, hashtable table returns boolean
7479
    return SaveSoundHandle(table, missionKey, key, whichSound)
7480
endfunction
7481
7482
//===========================================================================
7483
function SaveEffectHandleBJ takes effect whichEffect, integer key, integer missionKey, hashtable table returns boolean
7484
    return SaveEffectHandle(table, missionKey, key, whichEffect)
7485
endfunction
7486
7487
//===========================================================================
7488
function SaveUnitPoolHandleBJ takes unitpool whichUnitpool, integer key, integer missionKey, hashtable table returns boolean
7489
    return SaveUnitPoolHandle(table, missionKey, key, whichUnitpool)
7490
endfunction
7491
7492
//===========================================================================
7493
function SaveItemPoolHandleBJ takes itempool whichItempool, integer key, integer missionKey, hashtable table returns boolean
7494
    return SaveItemPoolHandle(table, missionKey, key, whichItempool)
7495
endfunction
7496
7497
//===========================================================================
7498
function SaveQuestHandleBJ takes quest whichQuest, integer key, integer missionKey, hashtable table returns boolean
7499
    return SaveQuestHandle(table, missionKey, key, whichQuest)
7500
endfunction
7501
7502
//===========================================================================
7503
function SaveQuestItemHandleBJ takes questitem whichQuestitem, integer key, integer missionKey, hashtable table returns boolean
7504
    return SaveQuestItemHandle(table, missionKey, key, whichQuestitem)
7505
endfunction
7506
7507
//===========================================================================
7508
function SaveDefeatConditionHandleBJ takes defeatcondition whichDefeatcondition, integer key, integer missionKey, hashtable table returns boolean
7509
    return SaveDefeatConditionHandle(table, missionKey, key, whichDefeatcondition)
7510
endfunction
7511
7512
//===========================================================================
7513
function SaveTimerDialogHandleBJ takes timerdialog whichTimerdialog, integer key, integer missionKey, hashtable table returns boolean
7514
    return SaveTimerDialogHandle(table, missionKey, key, whichTimerdialog)
7515
endfunction
7516
7517
//===========================================================================
7518
function SaveLeaderboardHandleBJ takes leaderboard whichLeaderboard, integer key, integer missionKey, hashtable table returns boolean
7519
    return SaveLeaderboardHandle(table, missionKey, key, whichLeaderboard)
7520
endfunction
7521
7522
//===========================================================================
7523
function SaveMultiboardHandleBJ takes multiboard whichMultiboard, integer key, integer missionKey, hashtable table returns boolean
7524
    return SaveMultiboardHandle(table, missionKey, key, whichMultiboard)
7525
endfunction
7526
7527
//===========================================================================
7528
function SaveMultiboardItemHandleBJ takes multiboarditem whichMultiboarditem, integer key, integer missionKey, hashtable table returns boolean
7529
    return SaveMultiboardItemHandle(table, missionKey, key, whichMultiboarditem)
7530
endfunction
7531
7532
//===========================================================================
7533
function SaveTrackableHandleBJ takes trackable whichTrackable, integer key, integer missionKey, hashtable table returns boolean
7534
    return SaveTrackableHandle(table, missionKey, key, whichTrackable)
7535
endfunction
7536
7537
//===========================================================================
7538
function SaveDialogHandleBJ takes dialog whichDialog, integer key, integer missionKey, hashtable table returns boolean
7539
    return SaveDialogHandle(table, missionKey, key, whichDialog)
7540
endfunction
7541
7542
//===========================================================================
7543
function SaveButtonHandleBJ takes button whichButton, integer key, integer missionKey, hashtable table returns boolean
7544
    return SaveButtonHandle(table, missionKey, key, whichButton)
7545
endfunction
7546
7547
//===========================================================================
7548
function SaveTextTagHandleBJ takes texttag whichTexttag, integer key, integer missionKey, hashtable table returns boolean
7549
    return SaveTextTagHandle(table, missionKey, key, whichTexttag)
7550
endfunction
7551
7552
//===========================================================================
7553
function SaveLightningHandleBJ takes lightning whichLightning, integer key, integer missionKey, hashtable table returns boolean
7554
    return SaveLightningHandle(table, missionKey, key, whichLightning)
7555
endfunction
7556
7557
//===========================================================================
7558
function SaveImageHandleBJ takes image whichImage, integer key, integer missionKey, hashtable table returns boolean
7559
    return SaveImageHandle(table, missionKey, key, whichImage)
7560
endfunction
7561
7562
//===========================================================================
7563
function SaveUbersplatHandleBJ takes ubersplat whichUbersplat, integer key, integer missionKey, hashtable table returns boolean
7564
    return SaveUbersplatHandle(table, missionKey, key, whichUbersplat)
7565
endfunction
7566
7567
//===========================================================================
7568
function SaveRegionHandleBJ takes region whichRegion, integer key, integer missionKey, hashtable table returns boolean
7569
    return SaveRegionHandle(table, missionKey, key, whichRegion)
7570
endfunction
7571
7572
//===========================================================================
7573
function SaveFogStateHandleBJ takes fogstate whichFogState, integer key, integer missionKey, hashtable table returns boolean
7574
    return SaveFogStateHandle(table, missionKey, key, whichFogState)
7575
endfunction
7576
7577
//===========================================================================
7578
function SaveFogModifierHandleBJ takes fogmodifier whichFogModifier, integer key, integer missionKey, hashtable table returns boolean
7579
    return SaveFogModifierHandle(table, missionKey, key, whichFogModifier)
7580
endfunction
7581
7582
//===========================================================================
7583
function SaveAgentHandleBJ takes agent whichAgent, integer key, integer missionKey, hashtable table returns boolean
7584
    return SaveAgentHandle(table, missionKey, key, whichAgent)
7585
endfunction
7586
7587
//===========================================================================
7588
function SaveHashtableHandleBJ takes hashtable whichHashtable, integer key, integer missionKey, hashtable table returns boolean
7589
    return SaveHashtableHandle(table, missionKey, key, whichHashtable)
7590
endfunction
7591
7592
//===========================================================================
7593
function GetStoredRealBJ takes string key, string missionKey, gamecache cache returns real
7594
    //call SyncStoredReal(cache, missionKey, key)
7595
    return GetStoredReal(cache, missionKey, key)
7596
endfunction
7597
7598
//===========================================================================
7599
function GetStoredIntegerBJ takes string key, string missionKey, gamecache cache returns integer
7600
    //call SyncStoredInteger(cache, missionKey, key)
7601
    return GetStoredInteger(cache, missionKey, key)
7602
endfunction
7603
7604
//===========================================================================
7605
function GetStoredBooleanBJ takes string key, string missionKey, gamecache cache returns boolean
7606
    //call SyncStoredBoolean(cache, missionKey, key)
7607
    return GetStoredBoolean(cache, missionKey, key)
7608
endfunction
7609
7610
//===========================================================================
7611
function GetStoredStringBJ takes string key, string missionKey, gamecache cache returns string
7612
    local string s
7613
7614
    //call SyncStoredString(cache, missionKey, key)
7615
    set s = GetStoredString(cache, missionKey, key)
7616
    if (s == null) then
7617
        return ""
7618
    else
7619
        return s
7620
    endif
7621
endfunction
7622
7623
//===========================================================================
7624
function LoadRealBJ takes integer key, integer missionKey, hashtable table returns real
7625
    //call SyncStoredReal(table, missionKey, key)
7626
    return LoadReal(table, missionKey, key)
7627
endfunction
7628
7629
//===========================================================================
7630
function LoadIntegerBJ takes integer key, integer missionKey, hashtable table returns integer
7631
    //call SyncStoredInteger(table, missionKey, key)
7632
    return LoadInteger(table, missionKey, key)
7633
endfunction
7634
7635
//===========================================================================
7636
function LoadBooleanBJ takes integer key, integer missionKey, hashtable table returns boolean
7637
    //call SyncStoredBoolean(table, missionKey, key)
7638
    return LoadBoolean(table, missionKey, key)
7639
endfunction
7640
7641
//===========================================================================
7642
function LoadStringBJ takes integer key, integer missionKey, hashtable table returns string
7643
    local string s
7644
7645
    //call SyncStoredString(table, missionKey, key)
7646
    set s = LoadStr(table, missionKey, key)
7647
    if (s == null) then
7648
        return ""
7649
    else
7650
        return s
7651
    endif
7652
endfunction
7653
7654
//===========================================================================
7655
function LoadPlayerHandleBJ takes integer key, integer missionKey, hashtable table returns player
7656
    return LoadPlayerHandle(table, missionKey, key)
7657
endfunction
7658
7659
//===========================================================================
7660
function LoadWidgetHandleBJ takes integer key, integer missionKey, hashtable table returns widget
7661
    return LoadWidgetHandle(table, missionKey, key)
7662
endfunction
7663
7664
//===========================================================================
7665
function LoadDestructableHandleBJ takes integer key, integer missionKey, hashtable table returns destructable
7666
    return LoadDestructableHandle(table, missionKey, key)
7667
endfunction
7668
7669
//===========================================================================
7670
function LoadItemHandleBJ takes integer key, integer missionKey, hashtable table returns item
7671
    return LoadItemHandle(table, missionKey, key)
7672
endfunction
7673
7674
//===========================================================================
7675
function LoadUnitHandleBJ takes integer key, integer missionKey, hashtable table returns unit
7676
    return LoadUnitHandle(table, missionKey, key)
7677
endfunction
7678
7679
//===========================================================================
7680
function LoadAbilityHandleBJ takes integer key, integer missionKey, hashtable table returns ability
7681
    return LoadAbilityHandle(table, missionKey, key)
7682
endfunction
7683
7684
//===========================================================================
7685
function LoadTimerHandleBJ takes integer key, integer missionKey, hashtable table returns timer
7686
    return LoadTimerHandle(table, missionKey, key)
7687
endfunction
7688
7689
//===========================================================================
7690
function LoadTriggerHandleBJ takes integer key, integer missionKey, hashtable table returns trigger
7691
    return LoadTriggerHandle(table, missionKey, key)
7692
endfunction
7693
7694
//===========================================================================
7695
function LoadTriggerConditionHandleBJ takes integer key, integer missionKey, hashtable table returns triggercondition
7696
    return LoadTriggerConditionHandle(table, missionKey, key)
7697
endfunction
7698
7699
//===========================================================================
7700
function LoadTriggerActionHandleBJ takes integer key, integer missionKey, hashtable table returns triggeraction
7701
    return LoadTriggerActionHandle(table, missionKey, key)
7702
endfunction
7703
7704
//===========================================================================
7705
function LoadTriggerEventHandleBJ takes integer key, integer missionKey, hashtable table returns event
7706
    return LoadTriggerEventHandle(table, missionKey, key)
7707
endfunction
7708
7709
//===========================================================================
7710
function LoadForceHandleBJ takes integer key, integer missionKey, hashtable table returns force
7711
    return LoadForceHandle(table, missionKey, key)
7712
endfunction
7713
7714
//===========================================================================
7715
function LoadGroupHandleBJ takes integer key, integer missionKey, hashtable table returns group
7716
    return LoadGroupHandle(table, missionKey, key)
7717
endfunction
7718
7719
//===========================================================================
7720
function LoadLocationHandleBJ takes integer key, integer missionKey, hashtable table returns location
7721
    return LoadLocationHandle(table, missionKey, key)
7722
endfunction
7723
7724
//===========================================================================
7725
function LoadRectHandleBJ takes integer key, integer missionKey, hashtable table returns rect
7726
    return LoadRectHandle(table, missionKey, key)
7727
endfunction
7728
7729
//===========================================================================
7730
function LoadBooleanExprHandleBJ takes integer key, integer missionKey, hashtable table returns boolexpr
7731
    return LoadBooleanExprHandle(table, missionKey, key)
7732
endfunction
7733
7734
//===========================================================================
7735
function LoadSoundHandleBJ takes integer key, integer missionKey, hashtable table returns sound
7736
    return LoadSoundHandle(table, missionKey, key)
7737
endfunction
7738
7739
//===========================================================================
7740
function LoadEffectHandleBJ takes integer key, integer missionKey, hashtable table returns effect
7741
    return LoadEffectHandle(table, missionKey, key)
7742
endfunction
7743
7744
//===========================================================================
7745
function LoadUnitPoolHandleBJ takes integer key, integer missionKey, hashtable table returns unitpool
7746
    return LoadUnitPoolHandle(table, missionKey, key)
7747
endfunction
7748
7749
//===========================================================================
7750
function LoadItemPoolHandleBJ takes integer key, integer missionKey, hashtable table returns itempool
7751
    return LoadItemPoolHandle(table, missionKey, key)
7752
endfunction
7753
7754
//===========================================================================
7755
function LoadQuestHandleBJ takes integer key, integer missionKey, hashtable table returns quest
7756
    return LoadQuestHandle(table, missionKey, key)
7757
endfunction
7758
7759
//===========================================================================
7760
function LoadQuestItemHandleBJ takes integer key, integer missionKey, hashtable table returns questitem
7761
    return LoadQuestItemHandle(table, missionKey, key)
7762
endfunction
7763
7764
//===========================================================================
7765
function LoadDefeatConditionHandleBJ takes integer key, integer missionKey, hashtable table returns defeatcondition
7766
    return LoadDefeatConditionHandle(table, missionKey, key)
7767
endfunction
7768
7769
//===========================================================================
7770
function LoadTimerDialogHandleBJ takes integer key, integer missionKey, hashtable table returns timerdialog
7771
    return LoadTimerDialogHandle(table, missionKey, key)
7772
endfunction
7773
7774
//===========================================================================
7775
function LoadLeaderboardHandleBJ takes integer key, integer missionKey, hashtable table returns leaderboard
7776
    return LoadLeaderboardHandle(table, missionKey, key)
7777
endfunction
7778
7779
//===========================================================================
7780
function LoadMultiboardHandleBJ takes integer key, integer missionKey, hashtable table returns multiboard
7781
    return LoadMultiboardHandle(table, missionKey, key)
7782
endfunction
7783
7784
//===========================================================================
7785
function LoadMultiboardItemHandleBJ takes integer key, integer missionKey, hashtable table returns multiboarditem
7786
    return LoadMultiboardItemHandle(table, missionKey, key)
7787
endfunction
7788
7789
//===========================================================================
7790
function LoadTrackableHandleBJ takes integer key, integer missionKey, hashtable table returns trackable
7791
    return LoadTrackableHandle(table, missionKey, key)
7792
endfunction
7793
7794
//===========================================================================
7795
function LoadDialogHandleBJ takes integer key, integer missionKey, hashtable table returns dialog
7796
    return LoadDialogHandle(table, missionKey, key)
7797
endfunction
7798
7799
//===========================================================================
7800
function LoadButtonHandleBJ takes integer key, integer missionKey, hashtable table returns button
7801
    return LoadButtonHandle(table, missionKey, key)
7802
endfunction
7803
7804
//===========================================================================
7805
function LoadTextTagHandleBJ takes integer key, integer missionKey, hashtable table returns texttag
7806
    return LoadTextTagHandle(table, missionKey, key)
7807
endfunction
7808
7809
//===========================================================================
7810
function LoadLightningHandleBJ takes integer key, integer missionKey, hashtable table returns lightning
7811
    return LoadLightningHandle(table, missionKey, key)
7812
endfunction
7813
7814
//===========================================================================
7815
function LoadImageHandleBJ takes integer key, integer missionKey, hashtable table returns image
7816
    return LoadImageHandle(table, missionKey, key)
7817
endfunction
7818
7819
//===========================================================================
7820
function LoadUbersplatHandleBJ takes integer key, integer missionKey, hashtable table returns ubersplat
7821
    return LoadUbersplatHandle(table, missionKey, key)
7822
endfunction
7823
7824
//===========================================================================
7825
function LoadRegionHandleBJ takes integer key, integer missionKey, hashtable table returns region
7826
    return LoadRegionHandle(table, missionKey, key)
7827
endfunction
7828
7829
//===========================================================================
7830
function LoadFogStateHandleBJ takes integer key, integer missionKey, hashtable table returns fogstate
7831
    return LoadFogStateHandle(table, missionKey, key)
7832
endfunction
7833
7834
//===========================================================================
7835
function LoadFogModifierHandleBJ takes integer key, integer missionKey, hashtable table returns fogmodifier
7836
    return LoadFogModifierHandle(table, missionKey, key)
7837
endfunction
7838
7839
//===========================================================================
7840
function LoadHashtableHandleBJ takes integer key, integer missionKey, hashtable table returns hashtable
7841
    return LoadHashtableHandle(table, missionKey, key)
7842
endfunction
7843
7844
//===========================================================================
7845
function RestoreUnitLocFacingAngleBJ takes string key, string missionKey, gamecache cache, player forWhichPlayer, location loc, real facing returns unit
7846
    //call SyncStoredUnit(cache, missionKey, key)
7847
    set bj_lastLoadedUnit = RestoreUnit(cache, missionKey, key, forWhichPlayer, GetLocationX(loc), GetLocationY(loc), facing)
7848
    return bj_lastLoadedUnit
7849
endfunction
7850
7851
//===========================================================================
7852
function RestoreUnitLocFacingPointBJ takes string key, string missionKey, gamecache cache, player forWhichPlayer, location loc, location lookAt returns unit
7853
    //call SyncStoredUnit(cache, missionKey, key)
7854
    return RestoreUnitLocFacingAngleBJ(key, missionKey, cache, forWhichPlayer, loc, AngleBetweenPoints(loc, lookAt))
7855
endfunction
7856
7857
//===========================================================================
7858
function GetLastRestoredUnitBJ takes nothing returns unit
7859
    return bj_lastLoadedUnit
7860
endfunction
7861
7862
//===========================================================================
7863
function FlushGameCacheBJ takes gamecache cache returns nothing
7864
    call FlushGameCache(cache)
7865
endfunction
7866
7867
//===========================================================================
7868
function FlushStoredMissionBJ takes string missionKey, gamecache cache returns nothing
7869
    call FlushStoredMission(cache, missionKey)
7870
endfunction
7871
7872
//===========================================================================
7873
function FlushParentHashtableBJ takes hashtable table returns nothing
7874
    call FlushParentHashtable(table)
7875
endfunction
7876
7877
//===========================================================================
7878
function FlushChildHashtableBJ takes integer missionKey, hashtable table returns nothing
7879
    call FlushChildHashtable(table, missionKey)
7880
endfunction
7881
7882
//===========================================================================
7883
function HaveStoredValue takes string key, integer valueType, string missionKey, gamecache cache returns boolean
7884
    if (valueType == bj_GAMECACHE_BOOLEAN) then
7885
        return HaveStoredBoolean(cache, missionKey, key)
7886
    elseif (valueType == bj_GAMECACHE_INTEGER) then
7887
        return HaveStoredInteger(cache, missionKey, key)
7888
    elseif (valueType == bj_GAMECACHE_REAL) then
7889
        return HaveStoredReal(cache, missionKey, key)
7890
    elseif (valueType == bj_GAMECACHE_UNIT) then
7891
        return HaveStoredUnit(cache, missionKey, key)
7892
    elseif (valueType == bj_GAMECACHE_STRING) then
7893
        return HaveStoredString(cache, missionKey, key)
7894
    else
7895
        // Unrecognized value type - ignore the request.
7896
        return false
7897
    endif
7898
endfunction
7899
7900
//===========================================================================
7901
function HaveSavedValue takes integer key, integer valueType, integer missionKey, hashtable table returns boolean
7902
    if (valueType == bj_HASHTABLE_BOOLEAN) then
7903
        return HaveSavedBoolean(table, missionKey, key)
7904
    elseif (valueType == bj_HASHTABLE_INTEGER) then
7905
        return HaveSavedInteger(table, missionKey, key)
7906
    elseif (valueType == bj_HASHTABLE_REAL) then
7907
        return HaveSavedReal(table, missionKey, key)
7908
    elseif (valueType == bj_HASHTABLE_STRING) then
7909
        return HaveSavedString(table, missionKey, key)
7910
    elseif (valueType == bj_HASHTABLE_HANDLE) then
7911
        return HaveSavedHandle(table, missionKey, key)
7912
    else
7913
        // Unrecognized value type - ignore the request.
7914
        return false
7915
    endif
7916
endfunction
7917
7918
//===========================================================================
7919
function ShowCustomCampaignButton takes boolean show, integer whichButton returns nothing
7920
    call SetCustomCampaignButtonVisible(whichButton - 1, show)
7921
endfunction
7922
7923
//===========================================================================
7924
function IsCustomCampaignButtonVisibile takes integer whichButton returns boolean
7925
    return GetCustomCampaignButtonVisible(whichButton - 1)
7926
endfunction
7927
7928
//===========================================================================
7929
// Placeholder function for auto save feature
7930
//===========================================================================
7931
function SaveGameCheckPointBJ takes string mapSaveName, boolean doCheckpointHint returns nothing
7932
    call SaveGameCheckpoint(mapSaveName, doCheckpointHint)
7933
endfunction
7934
7935
//===========================================================================
7936
function LoadGameBJ takes string loadFileName, boolean doScoreScreen returns nothing
7937
    call LoadGame(loadFileName, doScoreScreen)
7938
endfunction
7939
7940
//===========================================================================
7941
function SaveAndChangeLevelBJ takes string saveFileName, string newLevel, boolean doScoreScreen returns nothing
7942
    call SaveGame(saveFileName)
7943
    call ChangeLevel(newLevel, doScoreScreen)
7944
endfunction
7945
7946
//===========================================================================
7947
function SaveAndLoadGameBJ takes string saveFileName, string loadFileName, boolean doScoreScreen returns nothing
7948
    call SaveGame(saveFileName)
7949
    call LoadGame(loadFileName, doScoreScreen)
7950
endfunction
7951
7952
//===========================================================================
7953
function RenameSaveDirectoryBJ takes string sourceDirName, string destDirName returns boolean
7954
    return RenameSaveDirectory(sourceDirName, destDirName)
7955
endfunction
7956
7957
//===========================================================================
7958
function RemoveSaveDirectoryBJ takes string sourceDirName returns boolean
7959
    return RemoveSaveDirectory(sourceDirName)
7960
endfunction
7961
7962
//===========================================================================
7963
function CopySaveGameBJ takes string sourceSaveName, string destSaveName returns boolean
7964
    return CopySaveGame(sourceSaveName, destSaveName)
7965
endfunction
7966
7967
7968
7969
//***************************************************************************
7970
//*
7971
//*  Miscellaneous Utility Functions
7972
//*
7973
//***************************************************************************
7974
7975
//===========================================================================
7976
function GetPlayerStartLocationX takes player whichPlayer returns real
7977
    return GetStartLocationX(GetPlayerStartLocation(whichPlayer))
7978
endfunction
7979
7980
//===========================================================================
7981
function GetPlayerStartLocationY takes player whichPlayer returns real
7982
    return GetStartLocationY(GetPlayerStartLocation(whichPlayer))
7983
endfunction
7984
7985
//===========================================================================
7986
function GetPlayerStartLocationLoc takes player whichPlayer returns location
7987
    return GetStartLocationLoc(GetPlayerStartLocation(whichPlayer))
7988
endfunction
7989
7990
//===========================================================================
7991
function GetRectCenter takes rect whichRect returns location
7992
    return Location(GetRectCenterX(whichRect), GetRectCenterY(whichRect))
7993
endfunction
7994
7995
//===========================================================================
7996
function IsPlayerSlotState takes player whichPlayer, playerslotstate whichState returns boolean
7997
    return GetPlayerSlotState(whichPlayer) == whichState
7998
endfunction
7999
8000
//===========================================================================
8001
function GetFadeFromSeconds takes real seconds returns integer
8002
    if (seconds != 0) then
8003
        return 128 / R2I(seconds)
8004
    endif
8005
    return 10000
8006
endfunction
8007
8008
//===========================================================================
8009
function GetFadeFromSecondsAsReal takes real seconds returns real
8010
    if (seconds != 0) then
8011
        return 128.00 / seconds
8012
    endif
8013
    return 10000.00
8014
endfunction
8015
8016
//===========================================================================
8017
function AdjustPlayerStateSimpleBJ takes player whichPlayer, playerstate whichPlayerState, integer delta returns nothing
8018
    call SetPlayerState(whichPlayer, whichPlayerState, GetPlayerState(whichPlayer, whichPlayerState) + delta)
8019
endfunction
8020
8021
//===========================================================================
8022
function AdjustPlayerStateBJ takes integer delta, player whichPlayer, playerstate whichPlayerState returns nothing
8023
    // If the change was positive, apply the difference to the player's
8024
    // gathered resources property as well.
8025
    if (delta > 0) then
8026
        if (whichPlayerState == PLAYER_STATE_RESOURCE_GOLD) then
8027
            call AdjustPlayerStateSimpleBJ(whichPlayer, PLAYER_STATE_GOLD_GATHERED, delta)
8028
        elseif (whichPlayerState == PLAYER_STATE_RESOURCE_LUMBER) then
8029
            call AdjustPlayerStateSimpleBJ(whichPlayer, PLAYER_STATE_LUMBER_GATHERED, delta)
8030
        endif
8031
    endif
8032
8033
    call AdjustPlayerStateSimpleBJ(whichPlayer, whichPlayerState, delta)
8034
endfunction
8035
8036
//===========================================================================
8037
function SetPlayerStateBJ takes player whichPlayer, playerstate whichPlayerState, integer value returns nothing
8038
    local integer oldValue = GetPlayerState(whichPlayer, whichPlayerState)
8039
    call AdjustPlayerStateBJ(value - oldValue, whichPlayer, whichPlayerState)
8040
endfunction
8041
8042
//===========================================================================
8043
function SetPlayerFlagBJ takes playerstate whichPlayerFlag, boolean flag, player whichPlayer returns nothing
8044
    call SetPlayerState(whichPlayer, whichPlayerFlag, IntegerTertiaryOp(flag, 1, 0))
8045
endfunction
8046
8047
//===========================================================================
8048
function SetPlayerTaxRateBJ takes integer rate, playerstate whichResource, player sourcePlayer, player otherPlayer returns nothing
8049
    call SetPlayerTaxRate(sourcePlayer, otherPlayer, whichResource, rate)
8050
endfunction
8051
8052
//===========================================================================
8053
function GetPlayerTaxRateBJ takes playerstate whichResource, player sourcePlayer, player otherPlayer returns integer
8054
    return GetPlayerTaxRate(sourcePlayer, otherPlayer, whichResource)
8055
endfunction
8056
8057
//===========================================================================
8058
function IsPlayerFlagSetBJ takes playerstate whichPlayerFlag, player whichPlayer returns boolean
8059
    return GetPlayerState(whichPlayer, whichPlayerFlag) == 1
8060
endfunction
8061
8062
//===========================================================================
8063
function AddResourceAmountBJ takes integer delta, unit whichUnit returns nothing
8064
    call AddResourceAmount(whichUnit, delta)
8065
endfunction
8066
8067
//===========================================================================
8068
function GetConvertedPlayerId takes player whichPlayer returns integer
8069
    return GetPlayerId(whichPlayer) + 1
8070
endfunction
8071
8072
//===========================================================================
8073
function ConvertedPlayer takes integer convertedPlayerId returns player
8074
    return Player(convertedPlayerId - 1)
8075
endfunction
8076
8077
//===========================================================================
8078
function GetRectWidthBJ takes rect r returns real
8079
    return GetRectMaxX(r) - GetRectMinX(r)
8080
endfunction
8081
8082
//===========================================================================
8083
function GetRectHeightBJ takes rect r returns real
8084
    return GetRectMaxY(r) - GetRectMinY(r)
8085
endfunction
8086
8087
//===========================================================================
8088
// Replaces a gold mine with a blighted gold mine for the given player.
8089
//
8090
function BlightGoldMineForPlayerBJ takes unit goldMine, player whichPlayer returns unit
8091
    local real    mineX
8092
    local real    mineY
8093
    local integer mineGold
8094
    local unit    newMine
8095
8096
    // Make sure we're replacing a Gold Mine and not some other type of unit.
8097
    if GetUnitTypeId(goldMine) != 'ngol' then
8098
        return null
8099
    endif
8100
8101
    // Save the Gold Mine's properties and remove it.
8102
    set mineX    = GetUnitX(goldMine)
8103
    set mineY    = GetUnitY(goldMine)
8104
    set mineGold = GetResourceAmount(goldMine)
8105
    call RemoveUnit(goldMine)
8106
8107
    // Create a Haunted Gold Mine to replace the Gold Mine.
8108
    set newMine = CreateBlightedGoldmine(whichPlayer, mineX, mineY, bj_UNIT_FACING)
8109
    call SetResourceAmount(newMine, mineGold)
8110
    return newMine
8111
endfunction
8112
8113
//===========================================================================
8114
function BlightGoldMineForPlayer takes unit goldMine, player whichPlayer returns unit
8115
    set bj_lastHauntedGoldMine = BlightGoldMineForPlayerBJ(goldMine, whichPlayer)
8116
    return bj_lastHauntedGoldMine
8117
endfunction
8118
8119
//===========================================================================
8120
function GetLastHauntedGoldMine takes nothing returns unit
8121
    return bj_lastHauntedGoldMine
8122
endfunction
8123
8124
//===========================================================================
8125
function IsPointBlightedBJ takes location where returns boolean
8126
    return IsPointBlighted(GetLocationX(where), GetLocationY(where))
8127
endfunction
8128
8129
//===========================================================================
8130
function SetPlayerColorBJEnum takes nothing returns nothing
8131
    call SetUnitColor(GetEnumUnit(), bj_setPlayerTargetColor)
8132
endfunction
8133
8134
//===========================================================================
8135
function SetPlayerColorBJ takes player whichPlayer, playercolor color, boolean changeExisting returns nothing
8136
    local group g
8137
8138
    call SetPlayerColor(whichPlayer, color)
8139
    if changeExisting then
8140
        set bj_setPlayerTargetColor = color
8141
        set g = CreateGroup()
8142
        call GroupEnumUnitsOfPlayer(g, whichPlayer, null)
8143
        call ForGroup(g, function SetPlayerColorBJEnum)
8144
        call DestroyGroup(g)
8145
    endif
8146
endfunction
8147
8148
//===========================================================================
8149
function SetPlayerUnitAvailableBJ takes integer unitId, boolean allowed, player whichPlayer returns nothing
8150
    if allowed then
8151
        call SetPlayerTechMaxAllowed(whichPlayer, unitId, -1)
8152
    else
8153
        call SetPlayerTechMaxAllowed(whichPlayer, unitId, 0)
8154
    endif
8155
endfunction
8156
8157
//===========================================================================
8158
function LockGameSpeedBJ takes nothing returns nothing
8159
    call SetMapFlag(MAP_LOCK_SPEED, true)
8160
endfunction
8161
8162
//===========================================================================
8163
function UnlockGameSpeedBJ takes nothing returns nothing
8164
    call SetMapFlag(MAP_LOCK_SPEED, false)
8165
endfunction
8166
8167
//===========================================================================
8168
function IssueTargetOrderBJ takes unit whichUnit, string order, widget targetWidget returns boolean
8169
    return IssueTargetOrder( whichUnit, order, targetWidget )
8170
endfunction
8171
8172
//===========================================================================
8173
function IssuePointOrderLocBJ takes unit whichUnit, string order, location whichLocation returns boolean
8174
    return IssuePointOrderLoc( whichUnit, order, whichLocation )
8175
endfunction
8176
8177
//===========================================================================
8178
// Two distinct trigger actions can't share the same function name, so this
8179
// dummy function simply mimics the behavior of an existing call.
8180
//
8181
function IssueTargetDestructableOrder takes unit whichUnit, string order, widget targetWidget returns boolean
8182
    return IssueTargetOrder( whichUnit, order, targetWidget )
8183
endfunction
8184
8185
function IssueTargetItemOrder takes unit whichUnit, string order, widget targetWidget returns boolean
8186
    return IssueTargetOrder( whichUnit, order, targetWidget )
8187
endfunction
8188
8189
//===========================================================================
8190
function IssueImmediateOrderBJ takes unit whichUnit, string order returns boolean
8191
    return IssueImmediateOrder( whichUnit, order )
8192
endfunction
8193
8194
//===========================================================================
8195
function GroupTargetOrderBJ takes group whichGroup, string order, widget targetWidget returns boolean
8196
    return GroupTargetOrder( whichGroup, order, targetWidget )
8197
endfunction
8198
8199
//===========================================================================
8200
function GroupPointOrderLocBJ takes group whichGroup, string order, location whichLocation returns boolean
8201
    return GroupPointOrderLoc( whichGroup, order, whichLocation )
8202
endfunction
8203
8204
//===========================================================================
8205
function GroupImmediateOrderBJ takes group whichGroup, string order returns boolean
8206
    return GroupImmediateOrder( whichGroup, order )
8207
endfunction
8208
8209
//===========================================================================
8210
// Two distinct trigger actions can't share the same function name, so this
8211
// dummy function simply mimics the behavior of an existing call.
8212
//
8213
function GroupTargetDestructableOrder takes group whichGroup, string order, widget targetWidget returns boolean
8214
    return GroupTargetOrder( whichGroup, order, targetWidget )
8215
endfunction
8216
8217
function GroupTargetItemOrder takes group whichGroup, string order, widget targetWidget returns boolean
8218
    return GroupTargetOrder( whichGroup, order, targetWidget )
8219
endfunction
8220
8221
//===========================================================================
8222
function GetDyingDestructable takes nothing returns destructable
8223
    return GetTriggerDestructable()
8224
endfunction
8225
8226
//===========================================================================
8227
// Rally point setting
8228
//
8229
function SetUnitRallyPoint takes unit whichUnit, location targPos returns nothing
8230
    call IssuePointOrderLocBJ(whichUnit, "setrally", targPos)
8231
endfunction
8232
8233
//===========================================================================
8234
function SetUnitRallyUnit takes unit whichUnit, unit targUnit returns nothing
8235
    call IssueTargetOrder(whichUnit, "setrally", targUnit)
8236
endfunction
8237
8238
//===========================================================================
8239
function SetUnitRallyDestructable takes unit whichUnit, destructable targDest returns nothing
8240
    call IssueTargetOrder(whichUnit, "setrally", targDest)
8241
endfunction
8242
8243
//===========================================================================
8244
// Utility function for use by editor-generated item drop table triggers.
8245
// This function is added as an action to all destructable drop triggers,
8246
// so that a widget drop may be differentiated from a unit drop.
8247
//
8248
function SaveDyingWidget takes nothing returns nothing
8249
    set bj_lastDyingWidget = GetTriggerWidget()
8250
endfunction
8251
8252
//===========================================================================
8253
function SetBlightRectBJ takes boolean addBlight, player whichPlayer, rect r returns nothing
8254
    call SetBlightRect(whichPlayer, r, addBlight)
8255
endfunction
8256
8257
//===========================================================================
8258
function SetBlightRadiusLocBJ takes boolean addBlight, player whichPlayer, location loc, real radius returns nothing
8259
    call SetBlightLoc(whichPlayer, loc, radius, addBlight)
8260
endfunction
8261
8262
//===========================================================================
8263
function GetAbilityName takes integer abilcode returns string
8264
    return GetObjectName(abilcode)
8265
endfunction
8266
8267
8268
//***************************************************************************
8269
//*
8270
//*  Melee Template Visibility Settings
8271
//*
8272
//***************************************************************************
8273
8274
//===========================================================================
8275
function MeleeStartingVisibility takes nothing returns nothing
8276
    // Start by setting the ToD.
8277
    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, bj_MELEE_STARTING_TOD)
8278
8279
    // call FogMaskEnable(true)
8280
    // call FogEnable(true)
8281
endfunction
8282
8283
8284
8285
//***************************************************************************
8286
//*
8287
//*  Melee Template Starting Resources
8288
//*
8289
//***************************************************************************
8290
8291
//===========================================================================
8292
function MeleeStartingResources takes nothing returns nothing
8293
    local integer index
8294
    local player  indexPlayer
8295
    local version v
8296
    local integer startingGold
8297
    local integer startingLumber
8298
8299
    set v = VersionGet()
8300
    if (v == VERSION_REIGN_OF_CHAOS) then
8301
        set startingGold = bj_MELEE_STARTING_GOLD_V0
8302
        set startingLumber = bj_MELEE_STARTING_LUMBER_V0
8303
    else
8304
        set startingGold = bj_MELEE_STARTING_GOLD_V1
8305
        set startingLumber = bj_MELEE_STARTING_LUMBER_V1
8306
    endif
8307
8308
    // Set each player's starting resources.
8309
    set index = 0
8310
    loop
8311
        set indexPlayer = Player(index)
8312
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
8313
            call SetPlayerState(indexPlayer, PLAYER_STATE_RESOURCE_GOLD, startingGold)
8314
            call SetPlayerState(indexPlayer, PLAYER_STATE_RESOURCE_LUMBER, startingLumber)
8315
        endif
8316
8317
        set index = index + 1
8318
        exitwhen index == bj_MAX_PLAYERS
8319
    endloop
8320
endfunction
8321
8322
8323
8324
//***************************************************************************
8325
//*
8326
//*  Melee Template Hero Limit
8327
//*
8328
//***************************************************************************
8329
8330
//===========================================================================
8331
function ReducePlayerTechMaxAllowed takes player whichPlayer, integer techId, integer limit returns nothing
8332
    local integer oldMax = GetPlayerTechMaxAllowed(whichPlayer, techId)
8333
8334
    // A value of -1 is used to indicate no limit, so check for that as well.
8335
    if (oldMax < 0 or oldMax > limit) then
8336
        call SetPlayerTechMaxAllowed(whichPlayer, techId, limit)
8337
    endif
8338
endfunction
8339
8340
//===========================================================================
8341
function MeleeStartingHeroLimit takes nothing returns nothing
8342
    local integer index
8343
8344
    set index = 0
8345
    loop
8346
        // max heroes per player
8347
        call SetPlayerMaxHeroesAllowed(bj_MELEE_HERO_LIMIT, Player(index))
8348
8349
        // each player is restricted to a limit per hero type as well
8350
        call ReducePlayerTechMaxAllowed(Player(index), 'Hamg', bj_MELEE_HERO_TYPE_LIMIT)
8351
        call ReducePlayerTechMaxAllowed(Player(index), 'Hmkg', bj_MELEE_HERO_TYPE_LIMIT)
8352
        call ReducePlayerTechMaxAllowed(Player(index), 'Hpal', bj_MELEE_HERO_TYPE_LIMIT)
8353
        call ReducePlayerTechMaxAllowed(Player(index), 'Hblm', bj_MELEE_HERO_TYPE_LIMIT)
8354
8355
        call ReducePlayerTechMaxAllowed(Player(index), 'Obla', bj_MELEE_HERO_TYPE_LIMIT)
8356
        call ReducePlayerTechMaxAllowed(Player(index), 'Ofar', bj_MELEE_HERO_TYPE_LIMIT)
8357
        call ReducePlayerTechMaxAllowed(Player(index), 'Otch', bj_MELEE_HERO_TYPE_LIMIT)
8358
        call ReducePlayerTechMaxAllowed(Player(index), 'Oshd', bj_MELEE_HERO_TYPE_LIMIT)
8359
8360
        call ReducePlayerTechMaxAllowed(Player(index), 'Edem', bj_MELEE_HERO_TYPE_LIMIT)
8361
        call ReducePlayerTechMaxAllowed(Player(index), 'Ekee', bj_MELEE_HERO_TYPE_LIMIT)
8362
        call ReducePlayerTechMaxAllowed(Player(index), 'Emoo', bj_MELEE_HERO_TYPE_LIMIT)
8363
        call ReducePlayerTechMaxAllowed(Player(index), 'Ewar', bj_MELEE_HERO_TYPE_LIMIT)
8364
8365
        call ReducePlayerTechMaxAllowed(Player(index), 'Udea', bj_MELEE_HERO_TYPE_LIMIT)
8366
        call ReducePlayerTechMaxAllowed(Player(index), 'Udre', bj_MELEE_HERO_TYPE_LIMIT)
8367
        call ReducePlayerTechMaxAllowed(Player(index), 'Ulic', bj_MELEE_HERO_TYPE_LIMIT)
8368
        call ReducePlayerTechMaxAllowed(Player(index), 'Ucrl', bj_MELEE_HERO_TYPE_LIMIT)
8369
8370
        call ReducePlayerTechMaxAllowed(Player(index), 'Npbm', bj_MELEE_HERO_TYPE_LIMIT)
8371
        call ReducePlayerTechMaxAllowed(Player(index), 'Nbrn', bj_MELEE_HERO_TYPE_LIMIT)
8372
        call ReducePlayerTechMaxAllowed(Player(index), 'Nngs', bj_MELEE_HERO_TYPE_LIMIT)
8373
        call ReducePlayerTechMaxAllowed(Player(index), 'Nplh', bj_MELEE_HERO_TYPE_LIMIT)
8374
        call ReducePlayerTechMaxAllowed(Player(index), 'Nbst', bj_MELEE_HERO_TYPE_LIMIT)
8375
        call ReducePlayerTechMaxAllowed(Player(index), 'Nalc', bj_MELEE_HERO_TYPE_LIMIT)
8376
        call ReducePlayerTechMaxAllowed(Player(index), 'Ntin', bj_MELEE_HERO_TYPE_LIMIT)
8377
        call ReducePlayerTechMaxAllowed(Player(index), 'Nfir', bj_MELEE_HERO_TYPE_LIMIT)
8378
8379
        set index = index + 1
8380
        exitwhen index == bj_MAX_PLAYERS
8381
    endloop
8382
endfunction
8383
8384
8385
8386
//***************************************************************************
8387
//*
8388
//*  Melee Template Granted Hero Items
8389
//*
8390
//***************************************************************************
8391
8392
//===========================================================================
8393
function MeleeTrainedUnitIsHeroBJFilter takes nothing returns boolean
8394
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO)
8395
endfunction
8396
8397
//===========================================================================
8398
// The first N heroes trained or hired for each player start off with a
8399
// standard set of items.  This is currently:
8400
//   - 1x Scroll of Town Portal
8401
//
8402
function MeleeGrantItemsToHero takes unit whichUnit returns nothing
8403
    local integer owner   = GetPlayerId(GetOwningPlayer(whichUnit))
8404
8405
    // If we haven't twinked N heroes for this player yet, twink away.
8406
    if (bj_meleeTwinkedHeroes[owner] < bj_MELEE_MAX_TWINKED_HEROES) then
8407
        call UnitAddItemById(whichUnit, 'stwp')
8408
        set bj_meleeTwinkedHeroes[owner] = bj_meleeTwinkedHeroes[owner] + 1
8409
    endif
8410
endfunction
8411
8412
//===========================================================================
8413
function MeleeGrantItemsToTrainedHero takes nothing returns nothing
8414
    call MeleeGrantItemsToHero(GetTrainedUnit())
8415
endfunction
8416
8417
//===========================================================================
8418
function MeleeGrantItemsToHiredHero takes nothing returns nothing
8419
    call MeleeGrantItemsToHero(GetSoldUnit())
8420
endfunction
8421
8422
//===========================================================================
8423
function MeleeGrantHeroItems takes nothing returns nothing
8424
    local integer index
8425
    local trigger trig
8426
8427
    // Initialize the twinked hero counts.
8428
    set index = 0
8429
    loop
8430
        set bj_meleeTwinkedHeroes[index] = 0
8431
8432
        set index = index + 1
8433
        exitwhen index == bj_MAX_PLAYER_SLOTS
8434
    endloop
8435
8436
    // Register for an event whenever a hero is trained, so that we can give
8437
    // him/her their starting items.
8438
    set index = 0
8439
    loop
8440
        set trig = CreateTrigger()
8441
        call TriggerRegisterPlayerUnitEvent(trig, Player(index), EVENT_PLAYER_UNIT_TRAIN_FINISH, filterMeleeTrainedUnitIsHeroBJ)
8442
        call TriggerAddAction(trig, function MeleeGrantItemsToTrainedHero)
8443
8444
        set index = index + 1
8445
        exitwhen index == bj_MAX_PLAYERS
8446
    endloop
8447
8448
    // Register for an event whenever a neutral hero is hired, so that we
8449
    // can give him/her their starting items.
8450
    set trig = CreateTrigger()
8451
    call TriggerRegisterPlayerUnitEvent(trig, Player(PLAYER_NEUTRAL_PASSIVE), EVENT_PLAYER_UNIT_SELL, filterMeleeTrainedUnitIsHeroBJ)
8452
    call TriggerAddAction(trig, function MeleeGrantItemsToHiredHero)
8453
8454
    // Flag that we are giving starting items to heroes, so that the melee
8455
    // starting units code can create them as necessary.
8456
    set bj_meleeGrantHeroItems = true
8457
endfunction
8458
8459
8460
8461
//***************************************************************************
8462
//*
8463
//*  Melee Template Clear Start Locations
8464
//*
8465
//***************************************************************************
8466
8467
//===========================================================================
8468
function MeleeClearExcessUnit takes nothing returns nothing
8469
    local unit    theUnit = GetEnumUnit()
8470
    local integer owner   = GetPlayerId(GetOwningPlayer(theUnit))
8471
8472
    if (owner == PLAYER_NEUTRAL_AGGRESSIVE) then
8473
        // Remove any Neutral Hostile units from the area.
8474
        call RemoveUnit(GetEnumUnit())
8475
    elseif (owner == PLAYER_NEUTRAL_PASSIVE) then
8476
        // Remove non-structure Neutral Passive units from the area.
8477
        if not IsUnitType(theUnit, UNIT_TYPE_STRUCTURE) then
8478
            call RemoveUnit(GetEnumUnit())
8479
        endif
8480
    endif
8481
endfunction
8482
8483
//===========================================================================
8484
function MeleeClearNearbyUnits takes real x, real y, real range returns nothing
8485
    local group nearbyUnits
8486
    
8487
    set nearbyUnits = CreateGroup()
8488
    call GroupEnumUnitsInRange(nearbyUnits, x, y, range, null)
8489
    call ForGroup(nearbyUnits, function MeleeClearExcessUnit)
8490
    call DestroyGroup(nearbyUnits)
8491
endfunction
8492
8493
//===========================================================================
8494
function MeleeClearExcessUnits takes nothing returns nothing
8495
    local integer index
8496
    local real    locX
8497
    local real    locY
8498
    local player  indexPlayer
8499
8500
    set index = 0
8501
    loop
8502
        set indexPlayer = Player(index)
8503
8504
        // If the player slot is being used, clear any nearby creeps.
8505
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
8506
            set locX = GetStartLocationX(GetPlayerStartLocation(indexPlayer))
8507
            set locY = GetStartLocationY(GetPlayerStartLocation(indexPlayer))
8508
8509
            call MeleeClearNearbyUnits(locX, locY, bj_MELEE_CLEAR_UNITS_RADIUS)
8510
        endif
8511
8512
        set index = index + 1
8513
        exitwhen index == bj_MAX_PLAYERS
8514
    endloop
8515
endfunction
8516
8517
8518
8519
//***************************************************************************
8520
//*
8521
//*  Melee Template Starting Units
8522
//*
8523
//***************************************************************************
8524
8525
//===========================================================================
8526
function MeleeEnumFindNearestMine takes nothing returns nothing
8527
    local unit enumUnit = GetEnumUnit()
8528
    local real dist
8529
    local location unitLoc
8530
8531
    if (GetUnitTypeId(enumUnit) == 'ngol') then
8532
        set unitLoc = GetUnitLoc(enumUnit)
8533
        set dist = DistanceBetweenPoints(unitLoc, bj_meleeNearestMineToLoc)
8534
        call RemoveLocation(unitLoc)
8535
8536
        // If this is our first mine, or the closest thusfar, use it instead.
8537
        if (bj_meleeNearestMineDist < 0) or (dist < bj_meleeNearestMineDist) then
8538
            set bj_meleeNearestMine = enumUnit
8539
            set bj_meleeNearestMineDist = dist
8540
        endif
8541
    endif
8542
endfunction
8543
8544
//===========================================================================
8545
function MeleeFindNearestMine takes location src, real range returns unit
8546
    local group nearbyMines
8547
8548
    set bj_meleeNearestMine = null
8549
    set bj_meleeNearestMineDist = -1
8550
    set bj_meleeNearestMineToLoc = src
8551
8552
    set nearbyMines = CreateGroup()
8553
    call GroupEnumUnitsInRangeOfLoc(nearbyMines, src, range, null)
8554
    call ForGroup(nearbyMines, function MeleeEnumFindNearestMine)
8555
    call DestroyGroup(nearbyMines)
8556
8557
    return bj_meleeNearestMine
8558
endfunction
8559
8560
//===========================================================================
8561
function MeleeRandomHeroLoc takes player p, integer id1, integer id2, integer id3, integer id4, location loc returns unit
8562
    local unit    hero = null
8563
    local integer roll
8564
    local integer pick
8565
    local version v
8566
8567
    // The selection of heroes is dependant on the game version.
8568
    set v = VersionGet()
8569
    if (v == VERSION_REIGN_OF_CHAOS) then
8570
        set roll = GetRandomInt(1,3)
8571
    else
8572
        set roll = GetRandomInt(1,4)
8573
    endif
8574
8575
    // Translate the roll into a unitid.
8576
    if roll == 1 then
8577
        set pick = id1
8578
    elseif roll == 2 then
8579
        set pick = id2
8580
    elseif roll == 3 then
8581
        set pick = id3
8582
    elseif roll == 4 then
8583
        set pick = id4
8584
    else
8585
        // Unrecognized id index - pick the first hero in the list.
8586
        set pick = id1
8587
    endif
8588
8589
    // Create the hero.
8590
    set hero = CreateUnitAtLoc(p, pick, loc, bj_UNIT_FACING)
8591
    if bj_meleeGrantHeroItems then
8592
        call MeleeGrantItemsToHero(hero)
8593
    endif
8594
    return hero
8595
endfunction
8596
8597
//===========================================================================
8598
// Returns a location which is (distance) away from (src) in the direction of (targ).
8599
//
8600
function MeleeGetProjectedLoc takes location src, location targ, real distance, real deltaAngle returns location
8601
    local real srcX = GetLocationX(src)
8602
    local real srcY = GetLocationY(src)
8603
    local real direction = Atan2(GetLocationY(targ) - srcY, GetLocationX(targ) - srcX) + deltaAngle
8604
    return Location(srcX + distance * Cos(direction), srcY + distance * Sin(direction))
8605
endfunction
8606
8607
//===========================================================================
8608
function MeleeGetNearestValueWithin takes real val, real minVal, real maxVal returns real
8609
    if (val < minVal) then
8610
        return minVal
8611
    elseif (val > maxVal) then
8612
        return maxVal
8613
    else
8614
        return val
8615
    endif
8616
endfunction
8617
8618
//===========================================================================
8619
function MeleeGetLocWithinRect takes location src, rect r returns location
8620
    local real withinX = MeleeGetNearestValueWithin(GetLocationX(src), GetRectMinX(r), GetRectMaxX(r))
8621
    local real withinY = MeleeGetNearestValueWithin(GetLocationY(src), GetRectMinY(r), GetRectMaxY(r))
8622
    return Location(withinX, withinY)
8623
endfunction
8624
8625
//===========================================================================
8626
// Starting Units for Human Players
8627
//   - 1 Town Hall, placed at start location
8628
//   - 5 Peasants, placed between start location and nearest gold mine
8629
//
8630
function MeleeStartingUnitsHuman takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload returns nothing
8631
    local boolean  useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
8632
    local real     unitSpacing   = 64.00
8633
    local unit     nearestMine
8634
    local location nearMineLoc
8635
    local location heroLoc
8636
    local real     peonX
8637
    local real     peonY
8638
    local unit     townHall = null
8639
8640
    if (doPreload) then
8641
        call Preloader( "scripts\\HumanMelee.pld" )
8642
    endif
8643
8644
    set nearestMine = MeleeFindNearestMine(startLoc, bj_MELEE_MINE_SEARCH_RADIUS)
8645
    if (nearestMine != null) then
8646
        // Spawn Town Hall at the start location.
8647
        set townHall = CreateUnitAtLoc(whichPlayer, 'htow', startLoc, bj_UNIT_FACING)
8648
        
8649
        // Spawn Peasants near the mine.
8650
        set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 320, 0)
8651
        set peonX = GetLocationX(nearMineLoc)
8652
        set peonY = GetLocationY(nearMineLoc)
8653
        call CreateUnit(whichPlayer, 'hpea', peonX + 0.00 * unitSpacing, peonY + 1.00 * unitSpacing, bj_UNIT_FACING)
8654
        call CreateUnit(whichPlayer, 'hpea', peonX + 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
8655
        call CreateUnit(whichPlayer, 'hpea', peonX - 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
8656
        call CreateUnit(whichPlayer, 'hpea', peonX + 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
8657
        call CreateUnit(whichPlayer, 'hpea', peonX - 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
8658
8659
        // Set random hero spawn point to be off to the side of the start location.
8660
        set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 384, 45)
8661
    else
8662
        // Spawn Town Hall at the start location.
8663
        set townHall = CreateUnitAtLoc(whichPlayer, 'htow', startLoc, bj_UNIT_FACING)
8664
        
8665
        // Spawn Peasants directly south of the town hall.
8666
        set peonX = GetLocationX(startLoc)
8667
        set peonY = GetLocationY(startLoc) - 224.00
8668
        call CreateUnit(whichPlayer, 'hpea', peonX + 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8669
        call CreateUnit(whichPlayer, 'hpea', peonX + 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8670
        call CreateUnit(whichPlayer, 'hpea', peonX + 0.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8671
        call CreateUnit(whichPlayer, 'hpea', peonX - 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8672
        call CreateUnit(whichPlayer, 'hpea', peonX - 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8673
8674
        // Set random hero spawn point to be just south of the start location.
8675
        set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)
8676
    endif
8677
8678
    if (townHall != null) then
8679
        call UnitAddAbilityBJ('Amic', townHall)
8680
        call UnitMakeAbilityPermanentBJ(true, 'Amic', townHall)
8681
    endif
8682
8683
    if (doHeroes) then
8684
        // If the "Random Hero" option is set, start the player with a random hero.
8685
        // Otherwise, give them a "free hero" token.
8686
        if useRandomHero then
8687
            call MeleeRandomHeroLoc(whichPlayer, 'Hamg', 'Hmkg', 'Hpal', 'Hblm', heroLoc)
8688
        else
8689
            call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
8690
        endif
8691
    endif
8692
8693
    if (doCamera) then
8694
        // Center the camera on the initial Peasants.
8695
        call SetCameraPositionForPlayer(whichPlayer, peonX, peonY)
8696
        call SetCameraQuickPositionForPlayer(whichPlayer, peonX, peonY)
8697
    endif
8698
endfunction
8699
8700
//===========================================================================
8701
// Starting Units for Orc Players
8702
//   - 1 Great Hall, placed at start location
8703
//   - 5 Peons, placed between start location and nearest gold mine
8704
//
8705
function MeleeStartingUnitsOrc takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload returns nothing
8706
    local boolean  useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
8707
    local real     unitSpacing   = 64.00
8708
    local unit     nearestMine
8709
    local location nearMineLoc
8710
    local location heroLoc
8711
    local real     peonX
8712
    local real     peonY
8713
8714
    if (doPreload) then
8715
        call Preloader( "scripts\\OrcMelee.pld" )
8716
    endif
8717
8718
    set nearestMine = MeleeFindNearestMine(startLoc, bj_MELEE_MINE_SEARCH_RADIUS)
8719
    if (nearestMine != null) then
8720
        // Spawn Great Hall at the start location.
8721
        call CreateUnitAtLoc(whichPlayer, 'ogre', startLoc, bj_UNIT_FACING)
8722
        
8723
        // Spawn Peons near the mine.
8724
        set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 320, 0)
8725
        set peonX = GetLocationX(nearMineLoc)
8726
        set peonY = GetLocationY(nearMineLoc)
8727
        call CreateUnit(whichPlayer, 'opeo', peonX + 0.00 * unitSpacing, peonY + 1.00 * unitSpacing, bj_UNIT_FACING)
8728
        call CreateUnit(whichPlayer, 'opeo', peonX + 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
8729
        call CreateUnit(whichPlayer, 'opeo', peonX - 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
8730
        call CreateUnit(whichPlayer, 'opeo', peonX + 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
8731
        call CreateUnit(whichPlayer, 'opeo', peonX - 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
8732
8733
        // Set random hero spawn point to be off to the side of the start location.
8734
        set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 384, 45)
8735
    else
8736
        // Spawn Great Hall at the start location.
8737
        call CreateUnitAtLoc(whichPlayer, 'ogre', startLoc, bj_UNIT_FACING)
8738
        
8739
        // Spawn Peons directly south of the town hall.
8740
        set peonX = GetLocationX(startLoc)
8741
        set peonY = GetLocationY(startLoc) - 224.00
8742
        call CreateUnit(whichPlayer, 'opeo', peonX + 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8743
        call CreateUnit(whichPlayer, 'opeo', peonX + 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8744
        call CreateUnit(whichPlayer, 'opeo', peonX + 0.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8745
        call CreateUnit(whichPlayer, 'opeo', peonX - 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8746
        call CreateUnit(whichPlayer, 'opeo', peonX - 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8747
8748
        // Set random hero spawn point to be just south of the start location.
8749
        set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)
8750
    endif
8751
8752
    if (doHeroes) then
8753
        // If the "Random Hero" option is set, start the player with a random hero.
8754
        // Otherwise, give them a "free hero" token.
8755
        if useRandomHero then
8756
            call MeleeRandomHeroLoc(whichPlayer, 'Obla', 'Ofar', 'Otch', 'Oshd', heroLoc)
8757
        else
8758
            call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
8759
        endif
8760
    endif
8761
8762
    if (doCamera) then
8763
        // Center the camera on the initial Peons.
8764
        call SetCameraPositionForPlayer(whichPlayer, peonX, peonY)
8765
        call SetCameraQuickPositionForPlayer(whichPlayer, peonX, peonY)
8766
    endif
8767
endfunction
8768
8769
//===========================================================================
8770
// Starting Units for Undead Players
8771
//   - 1 Necropolis, placed at start location
8772
//   - 1 Haunted Gold Mine, placed on nearest gold mine
8773
//   - 3 Acolytes, placed between start location and nearest gold mine
8774
//   - 1 Ghoul, placed between start location and nearest gold mine
8775
//   - Blight, centered on nearest gold mine, spread across a "large area"
8776
//
8777
function MeleeStartingUnitsUndead takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload returns nothing
8778
    local boolean  useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
8779
    local real     unitSpacing   = 64.00
8780
    local unit     nearestMine
8781
    local location nearMineLoc
8782
    local location nearTownLoc
8783
    local location heroLoc
8784
    local real     peonX
8785
    local real     peonY
8786
    local real     ghoulX
8787
    local real     ghoulY
8788
8789
    if (doPreload) then
8790
        call Preloader( "scripts\\UndeadMelee.pld" )
8791
    endif
8792
8793
    set nearestMine = MeleeFindNearestMine(startLoc, bj_MELEE_MINE_SEARCH_RADIUS)
8794
    if (nearestMine != null) then
8795
        // Spawn Necropolis at the start location.
8796
        call CreateUnitAtLoc(whichPlayer, 'unpl', startLoc, bj_UNIT_FACING)
8797
        
8798
        // Replace the nearest gold mine with a blighted version.
8799
        set nearestMine = BlightGoldMineForPlayerBJ(nearestMine, whichPlayer)
8800
8801
        // Spawn Ghoul near the Necropolis.
8802
        set nearTownLoc = MeleeGetProjectedLoc(startLoc, GetUnitLoc(nearestMine), 288, 0)
8803
        set ghoulX = GetLocationX(nearTownLoc)
8804
        set ghoulY = GetLocationY(nearTownLoc)
8805
        set bj_ghoul[GetPlayerId(whichPlayer)] = CreateUnit(whichPlayer, 'ugho', ghoulX + 0.00 * unitSpacing, ghoulY + 0.00 * unitSpacing, bj_UNIT_FACING)
8806
8807
        // Spawn Acolytes near the mine.
8808
        set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 320, 0)
8809
        set peonX = GetLocationX(nearMineLoc)
8810
        set peonY = GetLocationY(nearMineLoc)
8811
        call CreateUnit(whichPlayer, 'uaco', peonX + 0.00 * unitSpacing, peonY + 0.50 * unitSpacing, bj_UNIT_FACING)
8812
        call CreateUnit(whichPlayer, 'uaco', peonX + 0.65 * unitSpacing, peonY - 0.50 * unitSpacing, bj_UNIT_FACING)
8813
        call CreateUnit(whichPlayer, 'uaco', peonX - 0.65 * unitSpacing, peonY - 0.50 * unitSpacing, bj_UNIT_FACING)
8814
8815
        // Create a patch of blight around the gold mine.
8816
        call SetBlightLoc(whichPlayer,nearMineLoc, 768, true)
8817
8818
        // Set random hero spawn point to be off to the side of the start location.
8819
        set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 384, 45)
8820
    else
8821
        // Spawn Necropolis at the start location.
8822
        call CreateUnitAtLoc(whichPlayer, 'unpl', startLoc, bj_UNIT_FACING)
8823
        
8824
        // Spawn Acolytes and Ghoul directly south of the Necropolis.
8825
        set peonX = GetLocationX(startLoc)
8826
        set peonY = GetLocationY(startLoc) - 224.00
8827
        call CreateUnit(whichPlayer, 'uaco', peonX - 1.50 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8828
        call CreateUnit(whichPlayer, 'uaco', peonX - 0.50 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8829
        call CreateUnit(whichPlayer, 'uaco', peonX + 0.50 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8830
        call CreateUnit(whichPlayer, 'ugho', peonX + 1.50 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8831
8832
        // Create a patch of blight around the start location.
8833
        call SetBlightLoc(whichPlayer,startLoc, 768, true)
8834
8835
        // Set random hero spawn point to be just south of the start location.
8836
        set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)
8837
    endif
8838
8839
    if (doHeroes) then
8840
        // If the "Random Hero" option is set, start the player with a random hero.
8841
        // Otherwise, give them a "free hero" token.
8842
        if useRandomHero then
8843
            call MeleeRandomHeroLoc(whichPlayer, 'Udea', 'Udre', 'Ulic', 'Ucrl', heroLoc)
8844
        else
8845
            call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
8846
        endif
8847
    endif
8848
8849
    if (doCamera) then
8850
        // Center the camera on the initial Acolytes.
8851
        call SetCameraPositionForPlayer(whichPlayer, peonX, peonY)
8852
        call SetCameraQuickPositionForPlayer(whichPlayer, peonX, peonY)
8853
    endif
8854
endfunction
8855
8856
//===========================================================================
8857
// Starting Units for Night Elf Players
8858
//   - 1 Tree of Life, placed by nearest gold mine, already entangled
8859
//   - 5 Wisps, placed between Tree of Life and nearest gold mine
8860
//
8861
function MeleeStartingUnitsNightElf takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload returns nothing
8862
    local boolean  useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
8863
    local real     unitSpacing   = 64.00
8864
    local real     minTreeDist   = 3.50 * bj_CELLWIDTH
8865
    local real     minWispDist   = 1.75 * bj_CELLWIDTH
8866
    local unit     nearestMine
8867
    local location nearMineLoc
8868
    local location wispLoc
8869
    local location heroLoc
8870
    local real     peonX
8871
    local real     peonY
8872
    local unit     tree
8873
8874
    if (doPreload) then
8875
        call Preloader( "scripts\\NightElfMelee.pld" )
8876
    endif
8877
8878
    set nearestMine = MeleeFindNearestMine(startLoc, bj_MELEE_MINE_SEARCH_RADIUS)
8879
    if (nearestMine != null) then
8880
        // Spawn Tree of Life near the mine and have it entangle the mine.
8881
        // Project the Tree's coordinates from the gold mine, and then snap
8882
        // the X and Y values to within minTreeDist of the Gold Mine.
8883
        set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 650, 0)
8884
        set nearMineLoc = MeleeGetLocWithinRect(nearMineLoc, GetRectFromCircleBJ(GetUnitLoc(nearestMine), minTreeDist))
8885
        set tree = CreateUnitAtLoc(whichPlayer, 'etol', nearMineLoc, bj_UNIT_FACING)
8886
        call IssueTargetOrder(tree, "entangleinstant", nearestMine)
8887
8888
        // Spawn Wisps at the start location.
8889
        set wispLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 320, 0)
8890
        set wispLoc = MeleeGetLocWithinRect(wispLoc, GetRectFromCircleBJ(GetUnitLoc(nearestMine), minWispDist))
8891
        set peonX = GetLocationX(wispLoc)
8892
        set peonY = GetLocationY(wispLoc)
8893
        call CreateUnit(whichPlayer, 'ewsp', peonX + 0.00 * unitSpacing, peonY + 1.00 * unitSpacing, bj_UNIT_FACING)
8894
        call CreateUnit(whichPlayer, 'ewsp', peonX + 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
8895
        call CreateUnit(whichPlayer, 'ewsp', peonX - 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
8896
        call CreateUnit(whichPlayer, 'ewsp', peonX + 0.58 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
8897
        call CreateUnit(whichPlayer, 'ewsp', peonX - 0.58 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
8898
8899
        // Set random hero spawn point to be off to the side of the start location.
8900
        set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 384, 45)
8901
    else
8902
        // Spawn Tree of Life at the start location.
8903
        call CreateUnitAtLoc(whichPlayer, 'etol', startLoc, bj_UNIT_FACING)
8904
8905
        // Spawn Wisps directly south of the town hall.
8906
        set peonX = GetLocationX(startLoc)
8907
        set peonY = GetLocationY(startLoc) - 224.00
8908
        call CreateUnit(whichPlayer, 'ewsp', peonX - 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8909
        call CreateUnit(whichPlayer, 'ewsp', peonX - 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8910
        call CreateUnit(whichPlayer, 'ewsp', peonX + 0.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8911
        call CreateUnit(whichPlayer, 'ewsp', peonX + 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8912
        call CreateUnit(whichPlayer, 'ewsp', peonX + 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
8913
8914
        // Set random hero spawn point to be just south of the start location.
8915
        set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)
8916
    endif
8917
8918
    if (doHeroes) then
8919
        // If the "Random Hero" option is set, start the player with a random hero.
8920
        // Otherwise, give them a "free hero" token.
8921
        if useRandomHero then
8922
            call MeleeRandomHeroLoc(whichPlayer, 'Edem', 'Ekee', 'Emoo', 'Ewar', heroLoc)
8923
        else
8924
            call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
8925
        endif
8926
    endif
8927
8928
    if (doCamera) then
8929
        // Center the camera on the initial Wisps.
8930
        call SetCameraPositionForPlayer(whichPlayer, peonX, peonY)
8931
        call SetCameraQuickPositionForPlayer(whichPlayer, peonX, peonY)
8932
    endif
8933
endfunction
8934
8935
//===========================================================================
8936
// Starting Units for Players Whose Race is Unknown
8937
//   - 12 Sheep, placed randomly around the start location
8938
//
8939
function MeleeStartingUnitsUnknownRace takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload returns nothing
8940
    local integer index
8941
8942
    if (doPreload) then
8943
    endif
8944
8945
    set index = 0
8946
    loop
8947
        call CreateUnit(whichPlayer, 'nshe', GetLocationX(startLoc) + GetRandomReal(-256, 256), GetLocationY(startLoc) + GetRandomReal(-256, 256), GetRandomReal(0, 360))
8948
        set index = index + 1
8949
        exitwhen index == 12
8950
    endloop
8951
8952
    if (doHeroes) then
8953
        // Give them a "free hero" token, out of pity.
8954
        call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
8955
    endif
8956
8957
    if (doCamera) then
8958
        // Center the camera on the initial sheep.
8959
        call SetCameraPositionLocForPlayer(whichPlayer, startLoc)
8960
        call SetCameraQuickPositionLocForPlayer(whichPlayer, startLoc)
8961
    endif
8962
endfunction
8963
8964
//===========================================================================
8965
function MeleeStartingUnits takes nothing returns nothing
8966
    local integer  index
8967
    local player   indexPlayer
8968
    local location indexStartLoc
8969
    local race     indexRace
8970
8971
    call Preloader( "scripts\\SharedMelee.pld" )
8972
8973
    set index = 0
8974
    loop
8975
        set indexPlayer = Player(index)
8976
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
8977
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))
8978
            set indexRace = GetPlayerRace(indexPlayer)
8979
8980
            // Create initial race-specific starting units
8981
            if (indexRace == RACE_HUMAN) then
8982
                call MeleeStartingUnitsHuman(indexPlayer, indexStartLoc, true, true, true)
8983
            elseif (indexRace == RACE_ORC) then
8984
                call MeleeStartingUnitsOrc(indexPlayer, indexStartLoc, true, true, true)
8985
            elseif (indexRace == RACE_UNDEAD) then
8986
                call MeleeStartingUnitsUndead(indexPlayer, indexStartLoc, true, true, true)
8987
            elseif (indexRace == RACE_NIGHTELF) then
8988
                call MeleeStartingUnitsNightElf(indexPlayer, indexStartLoc, true, true, true)
8989
            else
8990
                call MeleeStartingUnitsUnknownRace(indexPlayer, indexStartLoc, true, true, true)
8991
            endif
8992
        endif
8993
8994
        set index = index + 1
8995
        exitwhen index == bj_MAX_PLAYERS
8996
    endloop
8997
    
8998
endfunction
8999
9000
//===========================================================================
9001
function MeleeStartingUnitsForPlayer takes race whichRace, player whichPlayer, location loc, boolean doHeroes returns nothing
9002
    // Create initial race-specific starting units
9003
    if (whichRace == RACE_HUMAN) then
9004
        call MeleeStartingUnitsHuman(whichPlayer, loc, doHeroes, false, false)
9005
    elseif (whichRace == RACE_ORC) then
9006
        call MeleeStartingUnitsOrc(whichPlayer, loc, doHeroes, false, false)
9007
    elseif (whichRace == RACE_UNDEAD) then
9008
        call MeleeStartingUnitsUndead(whichPlayer, loc, doHeroes, false, false)
9009
    elseif (whichRace == RACE_NIGHTELF) then
9010
        call MeleeStartingUnitsNightElf(whichPlayer, loc, doHeroes, false, false)
9011
    else
9012
        // Unrecognized race - ignore the request.
9013
    endif
9014
endfunction
9015
9016
9017
9018
//***************************************************************************
9019
//*
9020
//*  Melee Template Starting AI Scripts
9021
//*
9022
//***************************************************************************
9023
9024
//===========================================================================
9025
function PickMeleeAI takes player num, string s1, string s2, string s3 returns nothing
9026
    local integer pick
9027
9028
    // easy difficulty never uses any custom AI scripts
9029
    // that are designed to be a bit more challenging
9030
    //
9031
    if GetAIDifficulty(num) == AI_DIFFICULTY_NEWBIE then
9032
        call StartMeleeAI(num,s1)
9033
        return
9034
    endif
9035
9036
    if s2 == null then
9037
        set pick = 1
9038
    elseif s3 == null then
9039
        set pick = GetRandomInt(1,2)
9040
    else
9041
        set pick = GetRandomInt(1,3)
9042
    endif
9043
9044
    if pick == 1 then
9045
        call StartMeleeAI(num,s1)
9046
    elseif pick == 2 then
9047
        call StartMeleeAI(num,s2)
9048
    else
9049
        call StartMeleeAI(num,s3)
9050
    endif
9051
endfunction
9052
9053
//===========================================================================
9054
function MeleeStartingAI takes nothing returns nothing
9055
    local integer index
9056
    local player  indexPlayer
9057
    local race    indexRace
9058
9059
    set index = 0
9060
    loop
9061
        set indexPlayer = Player(index)
9062
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
9063
            set indexRace = GetPlayerRace(indexPlayer)
9064
            if (GetPlayerController(indexPlayer) == MAP_CONTROL_COMPUTER) then
9065
                // Run a race-specific melee AI script.
9066
                if (indexRace == RACE_HUMAN) then
9067
                    call PickMeleeAI(indexPlayer, "human.ai", null, null)
9068
                elseif (indexRace == RACE_ORC) then
9069
                    call PickMeleeAI(indexPlayer, "orc.ai", null, null)
9070
                elseif (indexRace == RACE_UNDEAD) then
9071
                    call PickMeleeAI(indexPlayer, "undead.ai", null, null)
9072
                    call RecycleGuardPosition(bj_ghoul[index])
9073
                elseif (indexRace == RACE_NIGHTELF) then
9074
                    call PickMeleeAI(indexPlayer, "elf.ai", null, null)
9075
                else
9076
                    // Unrecognized race.
9077
                endif
9078
                call ShareEverythingWithTeamAI(indexPlayer)
9079
            endif
9080
        endif
9081
9082
        set index = index + 1
9083
        exitwhen index == bj_MAX_PLAYERS
9084
    endloop
9085
endfunction
9086
9087
function LockGuardPosition takes unit targ returns nothing
9088
    call SetUnitCreepGuard(targ,true)
9089
endfunction
9090
9091
9092
//***************************************************************************
9093
//*
9094
//*  Melee Template Victory / Defeat Conditions
9095
//*
9096
//***************************************************************************
9097
9098
//===========================================================================
9099
function MeleePlayerIsOpponent takes integer playerIndex, integer opponentIndex returns boolean
9100
    local player thePlayer = Player(playerIndex)
9101
    local player theOpponent = Player(opponentIndex)
9102
9103
    // The player himself is not an opponent.
9104
    if (playerIndex == opponentIndex) then
9105
        return false
9106
    endif
9107
9108
    // Unused player slots are not opponents.
9109
    if (GetPlayerSlotState(theOpponent) != PLAYER_SLOT_STATE_PLAYING) then
9110
        return false
9111
    endif
9112
9113
    // Players who are already defeated are not opponents.
9114
    if (bj_meleeDefeated[opponentIndex]) then
9115
        return false
9116
    endif
9117
9118
    // Allied players with allied victory set are not opponents.
9119
    if GetPlayerAlliance(thePlayer, theOpponent, ALLIANCE_PASSIVE) then
9120
        if GetPlayerAlliance(theOpponent, thePlayer, ALLIANCE_PASSIVE) then
9121
            if (GetPlayerState(thePlayer, PLAYER_STATE_ALLIED_VICTORY) == 1) then
9122
                if (GetPlayerState(theOpponent, PLAYER_STATE_ALLIED_VICTORY) == 1) then
9123
                    return false
9124
                endif
9125
            endif
9126
        endif
9127
    endif
9128
9129
    return true
9130
endfunction
9131
9132
//===========================================================================
9133
// Count buildings currently owned by all allies, including the player themself.
9134
//
9135
function MeleeGetAllyStructureCount takes player whichPlayer returns integer
9136
    local integer    playerIndex
9137
    local integer    buildingCount
9138
    local player     indexPlayer
9139
9140
    // Count the number of buildings controlled by all not-yet-defeated co-allies.
9141
    set buildingCount = 0
9142
    set playerIndex = 0
9143
    loop
9144
        set indexPlayer = Player(playerIndex)
9145
9146
        // uncomment to cause defeat even if you have control of ally structures, but yours have been nixed
9147
        //if (PlayersAreCoAllied(whichPlayer, indexPlayer) and not bj_meleeDefeated[playerIndex]) then
9148
        if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then
9149
            set buildingCount = buildingCount + GetPlayerStructureCount(indexPlayer, true)
9150
        endif
9151
            
9152
        set playerIndex = playerIndex + 1
9153
        exitwhen playerIndex == bj_MAX_PLAYERS
9154
    endloop
9155
9156
    return buildingCount
9157
endfunction
9158
9159
//===========================================================================
9160
// Count allies, excluding dead players and the player themself.
9161
//
9162
function MeleeGetAllyCount takes player whichPlayer returns integer
9163
    local integer playerIndex
9164
    local integer playerCount
9165
    local player  indexPlayer
9166
9167
    // Count the number of not-yet-defeated co-allies.
9168
    set playerCount = 0
9169
    set playerIndex = 0
9170
    loop
9171
        set indexPlayer = Player(playerIndex)
9172
        if PlayersAreCoAllied(whichPlayer, indexPlayer) and not bj_meleeDefeated[playerIndex] and (whichPlayer != indexPlayer) then
9173
            set playerCount = playerCount + 1
9174
        endif
9175
9176
        set playerIndex = playerIndex + 1
9177
        exitwhen playerIndex == bj_MAX_PLAYERS
9178
    endloop
9179
9180
    return playerCount
9181
endfunction
9182
9183
//===========================================================================
9184
// Counts key structures owned by a player and his or her allies, including
9185
// structures currently upgrading or under construction.
9186
//
9187
// Key structures: Town Hall, Great Hall, Tree of Life, Necropolis
9188
//
9189
function MeleeGetAllyKeyStructureCount takes player whichPlayer returns integer
9190
    local integer    playerIndex
9191
    local player     indexPlayer
9192
    local integer    keyStructs
9193
9194
    // Count the number of buildings controlled by all not-yet-defeated co-allies.
9195
    set keyStructs = 0
9196
    set playerIndex = 0
9197
    loop
9198
        set indexPlayer = Player(playerIndex)
9199
        if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then
9200
            set keyStructs = keyStructs + BlzGetPlayerTownHallCount(indexPlayer)
9201
        endif
9202
            
9203
        set playerIndex = playerIndex + 1
9204
        exitwhen playerIndex == bj_MAX_PLAYERS
9205
    endloop
9206
9207
    return keyStructs
9208
endfunction
9209
9210
//===========================================================================
9211
// Enum: Draw out a specific player.
9212
//
9213
function MeleeDoDrawEnum takes nothing returns nothing
9214
    local player thePlayer = GetEnumPlayer()
9215
9216
    call CachePlayerHeroData(thePlayer)
9217
    call RemovePlayerPreserveUnitsBJ(thePlayer, PLAYER_GAME_RESULT_TIE, false)
9218
endfunction
9219
9220
//===========================================================================
9221
// Enum: Victory out a specific player.
9222
//
9223
function MeleeDoVictoryEnum takes nothing returns nothing
9224
    local player thePlayer = GetEnumPlayer()
9225
    local integer playerIndex = GetPlayerId(thePlayer)
9226
9227
    if (not bj_meleeVictoried[playerIndex]) then
9228
        set bj_meleeVictoried[playerIndex] = true
9229
        call CachePlayerHeroData(thePlayer)
9230
        call RemovePlayerPreserveUnitsBJ(thePlayer, PLAYER_GAME_RESULT_VICTORY, false)
9231
    endif
9232
endfunction
9233
9234
//===========================================================================
9235
// Defeat out a specific player.
9236
//
9237
function MeleeDoDefeat takes player whichPlayer returns nothing
9238
    set bj_meleeDefeated[GetPlayerId(whichPlayer)] = true
9239
    call RemovePlayerPreserveUnitsBJ(whichPlayer, PLAYER_GAME_RESULT_DEFEAT, false)
9240
endfunction
9241
9242
//===========================================================================
9243
// Enum: Defeat out a specific player.
9244
//
9245
function MeleeDoDefeatEnum takes nothing returns nothing
9246
    local player thePlayer = GetEnumPlayer()
9247
9248
    // needs to happen before ownership change
9249
    call CachePlayerHeroData(thePlayer)
9250
    call MakeUnitsPassiveForTeam(thePlayer)
9251
    call MeleeDoDefeat(thePlayer)
9252
endfunction
9253
9254
//===========================================================================
9255
// A specific player left the game.
9256
//
9257
function MeleeDoLeave takes player whichPlayer returns nothing
9258
    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then
9259
        call GameOverDialogBJ( whichPlayer, true )
9260
    else
9261
        set bj_meleeDefeated[GetPlayerId(whichPlayer)] = true
9262
        call RemovePlayerPreserveUnitsBJ(whichPlayer, PLAYER_GAME_RESULT_DEFEAT, true)
9263
    endif
9264
endfunction
9265
9266
//===========================================================================
9267
// Remove all observers
9268
// 
9269
function MeleeRemoveObservers takes nothing returns nothing
9270
    local integer    playerIndex
9271
    local player     indexPlayer
9272
9273
    // Give all observers the game over dialog
9274
    set playerIndex = 0
9275
    loop
9276
        set indexPlayer = Player(playerIndex)
9277
9278
        if (IsPlayerObserver(indexPlayer)) then
9279
            call RemovePlayerPreserveUnitsBJ(indexPlayer, PLAYER_GAME_RESULT_NEUTRAL, false)
9280
        endif
9281
9282
        set playerIndex = playerIndex + 1
9283
        exitwhen playerIndex == bj_MAX_PLAYERS
9284
    endloop
9285
endfunction
9286
9287
//===========================================================================
9288
// Test all players to determine if a team has won.  For a team to win, all
9289
// remaining (read: undefeated) players need to be co-allied with all other
9290
// remaining players.  If even one player is not allied towards another,
9291
// everyone must be denied victory.
9292
//
9293
function MeleeCheckForVictors takes nothing returns force
9294
    local integer    playerIndex
9295
    local integer    opponentIndex
9296
    local force      opponentlessPlayers = CreateForce()
9297
    local boolean    gameOver = false
9298
9299
    // Check to see if any players have opponents remaining.
9300
    set playerIndex = 0
9301
    loop
9302
        if (not bj_meleeDefeated[playerIndex]) then
9303
            // Determine whether or not this player has any remaining opponents.
9304
            set opponentIndex = 0
9305
            loop
9306
                // If anyone has an opponent, noone can be victorious yet.
9307
                if MeleePlayerIsOpponent(playerIndex, opponentIndex) then
9308
                    return CreateForce()
9309
                endif
9310
9311
                set opponentIndex = opponentIndex + 1
9312
                exitwhen opponentIndex == bj_MAX_PLAYERS
9313
            endloop
9314
9315
            // Keep track of each opponentless player so that we can give
9316
            // them a victory later.
9317
            call ForceAddPlayer(opponentlessPlayers, Player(playerIndex))
9318
            set gameOver = true
9319
        endif
9320
9321
        set playerIndex = playerIndex + 1
9322
        exitwhen playerIndex == bj_MAX_PLAYERS
9323
    endloop
9324
9325
    // Set the game over global flag
9326
    set bj_meleeGameOver = gameOver
9327
9328
    return opponentlessPlayers
9329
endfunction
9330
9331
//===========================================================================
9332
// Test each player to determine if anyone has been defeated.
9333
//
9334
function MeleeCheckForLosersAndVictors takes nothing returns nothing
9335
    local integer    playerIndex
9336
    local player     indexPlayer
9337
    local force      defeatedPlayers = CreateForce()
9338
    local force      victoriousPlayers
9339
    local boolean    gameOver = false
9340
9341
    // If the game is already over, do nothing
9342
    if (bj_meleeGameOver) then
9343
        return
9344
    endif
9345
9346
    // If the game was disconnected then it is over, in this case we
9347
    // don't want to report results for anyone as they will most likely
9348
    // conflict with the actual game results
9349
    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then
9350
        set bj_meleeGameOver = true
9351
        return
9352
    endif
9353
9354
    // Check each player to see if he or she has been defeated yet.
9355
    set playerIndex = 0
9356
    loop
9357
        set indexPlayer = Player(playerIndex)
9358
9359
        if (not bj_meleeDefeated[playerIndex] and not bj_meleeVictoried[playerIndex]) then
9360
            //call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Player"+I2S(playerIndex)+" has "+I2S(MeleeGetAllyStructureCount(indexPlayer))+" ally buildings.")
9361
            if (MeleeGetAllyStructureCount(indexPlayer) <= 0) then
9362
9363
                // Keep track of each defeated player so that we can give
9364
                // them a defeat later.
9365
                call ForceAddPlayer(defeatedPlayers, Player(playerIndex))
9366
9367
                // Set their defeated flag now so MeleeCheckForVictors
9368
                // can detect victors.
9369
                set bj_meleeDefeated[playerIndex] = true
9370
            endif
9371
        endif
9372
            
9373
        set playerIndex = playerIndex + 1
9374
        exitwhen playerIndex == bj_MAX_PLAYERS
9375
    endloop
9376
9377
    // Now that the defeated flags are set, check if there are any victors
9378
    set victoriousPlayers = MeleeCheckForVictors()
9379
9380
    // Defeat all defeated players
9381
    call ForForce(defeatedPlayers, function MeleeDoDefeatEnum)
9382
9383
    // Give victory to all victorious players
9384
    call ForForce(victoriousPlayers, function MeleeDoVictoryEnum)
9385
9386
    // If the game is over we should remove all observers
9387
    if (bj_meleeGameOver) then
9388
        call MeleeRemoveObservers()
9389
    endif
9390
endfunction
9391
9392
//===========================================================================
9393
// Returns a race-specific "build X or be revealed" message.
9394
//
9395
function MeleeGetCrippledWarningMessage takes player whichPlayer returns string
9396
    local race r = GetPlayerRace(whichPlayer)
9397
9398
    if (r == RACE_HUMAN) then
9399
        return GetLocalizedString("CRIPPLE_WARNING_HUMAN")
9400
    elseif (r == RACE_ORC) then
9401
        return GetLocalizedString("CRIPPLE_WARNING_ORC")
9402
    elseif (r == RACE_NIGHTELF) then
9403
        return GetLocalizedString("CRIPPLE_WARNING_NIGHTELF")
9404
    elseif (r == RACE_UNDEAD) then
9405
        return GetLocalizedString("CRIPPLE_WARNING_UNDEAD")
9406
    else
9407
        // Unrecognized Race
9408
        return ""
9409
    endif
9410
endfunction
9411
9412
//===========================================================================
9413
// Returns a race-specific "build X" label for cripple timers.
9414
//
9415
function MeleeGetCrippledTimerMessage takes player whichPlayer returns string
9416
    local race r = GetPlayerRace(whichPlayer)
9417
9418
    if (r == RACE_HUMAN) then
9419
        return GetLocalizedString("CRIPPLE_TIMER_HUMAN")
9420
    elseif (r == RACE_ORC) then
9421
        return GetLocalizedString("CRIPPLE_TIMER_ORC")
9422
    elseif (r == RACE_NIGHTELF) then
9423
        return GetLocalizedString("CRIPPLE_TIMER_NIGHTELF")
9424
    elseif (r == RACE_UNDEAD) then
9425
        return GetLocalizedString("CRIPPLE_TIMER_UNDEAD")
9426
    else
9427
        // Unrecognized Race
9428
        return ""
9429
    endif
9430
endfunction
9431
9432
//===========================================================================
9433
// Returns a race-specific "build X" label for cripple timers.
9434
//
9435
function MeleeGetCrippledRevealedMessage takes player whichPlayer returns string
9436
    return GetLocalizedString("CRIPPLE_REVEALING_PREFIX") + GetPlayerName(whichPlayer) + GetLocalizedString("CRIPPLE_REVEALING_POSTFIX")
9437
endfunction
9438
9439
//===========================================================================
9440
function MeleeExposePlayer takes player whichPlayer, boolean expose returns nothing
9441
    local integer playerIndex
9442
    local player  indexPlayer
9443
    local force   toExposeTo = CreateForce()
9444
9445
    call CripplePlayer( whichPlayer, toExposeTo, false )
9446
9447
    set bj_playerIsExposed[GetPlayerId(whichPlayer)] = expose
9448
    set playerIndex = 0
9449
    loop
9450
        set indexPlayer = Player(playerIndex)
9451
        if (not PlayersAreCoAllied(whichPlayer, indexPlayer)) then
9452
            call ForceAddPlayer( toExposeTo, indexPlayer )
9453
        endif
9454
9455
        set playerIndex = playerIndex + 1
9456
        exitwhen playerIndex == bj_MAX_PLAYERS
9457
    endloop
9458
9459
    call CripplePlayer( whichPlayer, toExposeTo, expose )
9460
    call DestroyForce(toExposeTo)
9461
endfunction
9462
9463
//===========================================================================
9464
function MeleeExposeAllPlayers takes nothing returns nothing
9465
    local integer playerIndex
9466
    local player  indexPlayer
9467
    local integer playerIndex2
9468
    local player  indexPlayer2
9469
    local force   toExposeTo = CreateForce()
9470
9471
    set playerIndex = 0
9472
    loop
9473
        set indexPlayer = Player(playerIndex)
9474
9475
        call ForceClear( toExposeTo )
9476
        call CripplePlayer( indexPlayer, toExposeTo, false )
9477
9478
        set playerIndex2 = 0
9479
        loop
9480
            set indexPlayer2 = Player(playerIndex2)
9481
9482
            if playerIndex != playerIndex2 then
9483
                if (not PlayersAreCoAllied(indexPlayer, indexPlayer2)) then
9484
                    call ForceAddPlayer( toExposeTo, indexPlayer2 )
9485
                endif
9486
            endif
9487
9488
            set playerIndex2 = playerIndex2 + 1
9489
            exitwhen playerIndex2 == bj_MAX_PLAYERS
9490
        endloop
9491
9492
        call CripplePlayer( indexPlayer, toExposeTo, true )
9493
9494
        set playerIndex = playerIndex + 1
9495
        exitwhen playerIndex == bj_MAX_PLAYERS
9496
    endloop
9497
9498
    call DestroyForce( toExposeTo )
9499
endfunction
9500
9501
//===========================================================================
9502
function MeleeCrippledPlayerTimeout takes nothing returns nothing
9503
    local timer expiredTimer = GetExpiredTimer()
9504
    local integer playerIndex
9505
    local player  exposedPlayer
9506
9507
    // Determine which player's timer expired.
9508
    set playerIndex = 0
9509
    loop
9510
        if (bj_crippledTimer[playerIndex] == expiredTimer) then
9511
            exitwhen true
9512
        endif
9513
9514
        set playerIndex = playerIndex + 1
9515
        exitwhen playerIndex == bj_MAX_PLAYERS
9516
    endloop
9517
    if (playerIndex == bj_MAX_PLAYERS) then
9518
        return
9519
    endif
9520
    set exposedPlayer = Player(playerIndex)
9521
9522
    if (GetLocalPlayer() == exposedPlayer) then
9523
        // Use only local code (no net traffic) within this block to avoid desyncs.
9524
9525
        // Hide the timer window for this player.
9526
        call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)
9527
    endif
9528
9529
    // Display a text message to all players, explaining the exposure.
9530
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, MeleeGetCrippledRevealedMessage(exposedPlayer))
9531
9532
    // Expose the player.
9533
    call MeleeExposePlayer(exposedPlayer, true)
9534
endfunction
9535
9536
//===========================================================================
9537
function MeleePlayerIsCrippled takes player whichPlayer returns boolean
9538
    local integer playerStructures  = GetPlayerStructureCount(whichPlayer, true)
9539
    local integer playerKeyStructures = BlzGetPlayerTownHallCount(whichPlayer)
9540
9541
    // Dead players are not considered to be crippled.
9542
    return (playerStructures > 0) and (playerKeyStructures <= 0)
9543
endfunction
9544
9545
//===========================================================================
9546
// Test each player to determine if anyone has become crippled.
9547
//
9548
function MeleeCheckForCrippledPlayers takes nothing returns nothing
9549
    local integer    playerIndex
9550
    local player     indexPlayer
9551
    local force      crippledPlayers = CreateForce()
9552
    local boolean    isNowCrippled
9553
    local race       indexRace
9554
9555
    // The "finish soon" exposure of all players overrides any "crippled" exposure
9556
    if bj_finishSoonAllExposed then
9557
        return
9558
    endif
9559
9560
    // Check each player to see if he or she has been crippled or uncrippled.
9561
    set playerIndex = 0
9562
    loop
9563
        set indexPlayer = Player(playerIndex)
9564
        set isNowCrippled = MeleePlayerIsCrippled(indexPlayer)
9565
9566
        if (not bj_playerIsCrippled[playerIndex] and isNowCrippled) then
9567
9568
            // Player became crippled; start their cripple timer.
9569
            set bj_playerIsCrippled[playerIndex] = true
9570
            call TimerStart(bj_crippledTimer[playerIndex], bj_MELEE_CRIPPLE_TIMEOUT, false, function MeleeCrippledPlayerTimeout)
9571
9572
            if (GetLocalPlayer() == indexPlayer) then
9573
                // Use only local code (no net traffic) within this block to avoid desyncs.
9574
9575
                // Show the timer window.
9576
                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], true)
9577
9578
                // Display a warning message.
9579
                call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, MeleeGetCrippledWarningMessage(indexPlayer))
9580
            endif
9581
9582
        elseif (bj_playerIsCrippled[playerIndex] and not isNowCrippled) then
9583
9584
            // Player became uncrippled; stop their cripple timer.
9585
            set bj_playerIsCrippled[playerIndex] = false
9586
            call PauseTimer(bj_crippledTimer[playerIndex])
9587
9588
            if (GetLocalPlayer() == indexPlayer) then
9589
                // Use only local code (no net traffic) within this block to avoid desyncs.
9590
9591
                // Hide the timer window for this player.
9592
                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)
9593
9594
                // Display a confirmation message if the player's team is still alive.
9595
                if (MeleeGetAllyStructureCount(indexPlayer) > 0) then
9596
                    if (bj_playerIsExposed[playerIndex]) then
9597
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNREVEALED"))
9598
                    else
9599
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNCRIPPLED"))
9600
                    endif
9601
                endif
9602
            endif
9603
9604
            // If the player granted shared vision, deny that vision now.
9605
            call MeleeExposePlayer(indexPlayer, false)
9606
9607
        endif
9608
            
9609
        set playerIndex = playerIndex + 1
9610
        exitwhen playerIndex == bj_MAX_PLAYERS
9611
    endloop
9612
endfunction
9613
9614
//===========================================================================
9615
// Determine if the lost unit should result in any defeats or victories.
9616
//
9617
function MeleeCheckLostUnit takes unit lostUnit returns nothing
9618
    local player lostUnitOwner = GetOwningPlayer(lostUnit)
9619
9620
    // We only need to check for mortality if this was the last building.
9621
    if (GetPlayerStructureCount(lostUnitOwner, true) <= 0) then
9622
        call MeleeCheckForLosersAndVictors()
9623
    endif
9624
9625
    // Check if the lost unit has crippled or uncrippled the player.
9626
    // (A team with 0 units is dead, and thus considered uncrippled.)
9627
    call MeleeCheckForCrippledPlayers()
9628
endfunction
9629
9630
//===========================================================================
9631
// Determine if the gained unit should result in any defeats, victories,
9632
// or cripple-status changes.
9633
//
9634
function MeleeCheckAddedUnit takes unit addedUnit returns nothing
9635
    local player addedUnitOwner = GetOwningPlayer(addedUnit)
9636
9637
    // If the player was crippled, this unit may have uncrippled him/her.
9638
    if (bj_playerIsCrippled[GetPlayerId(addedUnitOwner)]) then
9639
        call MeleeCheckForCrippledPlayers()
9640
    endif
9641
endfunction
9642
9643
//===========================================================================
9644
function MeleeTriggerActionConstructCancel takes nothing returns nothing
9645
    call MeleeCheckLostUnit(GetCancelledStructure())
9646
endfunction
9647
9648
//===========================================================================
9649
function MeleeTriggerActionUnitDeath takes nothing returns nothing
9650
    if (IsUnitType(GetDyingUnit(), UNIT_TYPE_STRUCTURE)) then
9651
        call MeleeCheckLostUnit(GetDyingUnit())
9652
    endif
9653
endfunction
9654
9655
//===========================================================================
9656
function MeleeTriggerActionUnitConstructionStart takes nothing returns nothing
9657
    call MeleeCheckAddedUnit(GetConstructingStructure())
9658
endfunction
9659
9660
//===========================================================================
9661
function MeleeTriggerActionPlayerDefeated takes nothing returns nothing
9662
    local player thePlayer = GetTriggerPlayer()
9663
    call CachePlayerHeroData(thePlayer)
9664
9665
    if (MeleeGetAllyCount(thePlayer) > 0) then
9666
        // If at least one ally is still alive and kicking, share units with
9667
        // them and proceed with death.
9668
        call ShareEverythingWithTeam(thePlayer)
9669
        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
9670
            call MeleeDoDefeat(thePlayer)
9671
        endif
9672
    else
9673
        // If no living allies remain, swap all units and buildings over to
9674
        // neutral_passive and proceed with death.
9675
        call MakeUnitsPassiveForTeam(thePlayer)
9676
        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
9677
            call MeleeDoDefeat(thePlayer)
9678
        endif
9679
    endif
9680
    call MeleeCheckForLosersAndVictors()
9681
endfunction
9682
9683
//===========================================================================
9684
function MeleeTriggerActionPlayerLeft takes nothing returns nothing
9685
    local player thePlayer = GetTriggerPlayer()
9686
9687
    // Just show game over for observers when they leave
9688
    if (IsPlayerObserver(thePlayer)) then
9689
        call RemovePlayerPreserveUnitsBJ(thePlayer, PLAYER_GAME_RESULT_NEUTRAL, false)
9690
        return
9691
    endif
9692
9693
    call CachePlayerHeroData(thePlayer)
9694
9695
    // This is the same as defeat except the player generates the message 
9696
    // "player left the game" as opposed to "player was defeated".
9697
9698
    if (MeleeGetAllyCount(thePlayer) > 0) then
9699
        // If at least one ally is still alive and kicking, share units with
9700
        // them and proceed with death.
9701
        call ShareEverythingWithTeam(thePlayer)
9702
        call MeleeDoLeave(thePlayer)
9703
    else
9704
        // If no living allies remain, swap all units and buildings over to
9705
        // neutral_passive and proceed with death.
9706
        call MakeUnitsPassiveForTeam(thePlayer)
9707
        call MeleeDoLeave(thePlayer)
9708
    endif
9709
    call MeleeCheckForLosersAndVictors()
9710
endfunction
9711
9712
//===========================================================================
9713
function MeleeTriggerActionAllianceChange takes nothing returns nothing
9714
    call MeleeCheckForLosersAndVictors()
9715
    call MeleeCheckForCrippledPlayers()
9716
endfunction
9717
9718
//===========================================================================
9719
function MeleeTriggerTournamentFinishSoon takes nothing returns nothing
9720
    // Note: We may get this trigger multiple times
9721
    local integer    playerIndex
9722
    local player     indexPlayer
9723
    local real       timeRemaining = GetTournamentFinishSoonTimeRemaining()
9724
9725
    if not bj_finishSoonAllExposed then
9726
        set bj_finishSoonAllExposed = true
9727
9728
        // Reset all crippled players and their timers, and hide the local crippled timer dialog
9729
        set playerIndex = 0
9730
        loop
9731
            set indexPlayer = Player(playerIndex)
9732
            if bj_playerIsCrippled[playerIndex] then
9733
                // Uncripple the player
9734
                set bj_playerIsCrippled[playerIndex] = false
9735
                call PauseTimer(bj_crippledTimer[playerIndex])
9736
9737
                if (GetLocalPlayer() == indexPlayer) then
9738
                    // Use only local code (no net traffic) within this block to avoid desyncs.
9739
9740
                    // Hide the timer window.
9741
                    call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)
9742
                endif
9743
9744
            endif
9745
            set playerIndex = playerIndex + 1
9746
            exitwhen playerIndex == bj_MAX_PLAYERS
9747
        endloop
9748
9749
        // Expose all players
9750
        call MeleeExposeAllPlayers()
9751
    endif
9752
9753
    // Show the "finish soon" timer dialog and set the real time remaining
9754
    call TimerDialogDisplay(bj_finishSoonTimerDialog, true)
9755
    call TimerDialogSetRealTimeRemaining(bj_finishSoonTimerDialog, timeRemaining)
9756
endfunction
9757
9758
9759
//===========================================================================
9760
function MeleeWasUserPlayer takes player whichPlayer returns boolean
9761
    local playerslotstate slotState
9762
9763
    if (GetPlayerController(whichPlayer) != MAP_CONTROL_USER) then
9764
        return false
9765
    endif
9766
9767
    set slotState = GetPlayerSlotState(whichPlayer)
9768
9769
    return (slotState == PLAYER_SLOT_STATE_PLAYING or slotState == PLAYER_SLOT_STATE_LEFT)
9770
endfunction
9771
9772
//===========================================================================
9773
function MeleeTournamentFinishNowRuleA takes integer multiplier returns nothing
9774
    local integer array playerScore
9775
    local integer array teamScore
9776
    local force array   teamForce
9777
    local integer       teamCount
9778
    local integer       index
9779
    local player        indexPlayer
9780
    local integer       index2
9781
    local player        indexPlayer2
9782
    local integer       bestTeam
9783
    local integer       bestScore
9784
    local boolean       draw
9785
9786
    // Compute individual player scores
9787
    set index = 0
9788
    loop
9789
        set indexPlayer = Player(index)
9790
        if MeleeWasUserPlayer(indexPlayer) then
9791
            set playerScore[index] = GetTournamentScore(indexPlayer)
9792
            if playerScore[index] <= 0 then
9793
                set playerScore[index] = 1
9794
            endif
9795
        else
9796
            set playerScore[index] = 0
9797
        endif
9798
        set index = index + 1
9799
        exitwhen index == bj_MAX_PLAYERS
9800
    endloop
9801
9802
    // Compute team scores and team forces
9803
    set teamCount = 0
9804
    set index = 0
9805
    loop
9806
        if playerScore[index] != 0 then
9807
            set indexPlayer = Player(index)
9808
9809
            set teamScore[teamCount] = 0
9810
            set teamForce[teamCount] = CreateForce()
9811
9812
            set index2 = index
9813
            loop
9814
                if playerScore[index2] != 0 then
9815
                    set indexPlayer2 = Player(index2)
9816
9817
                    if PlayersAreCoAllied(indexPlayer, indexPlayer2) then
9818
                        set teamScore[teamCount] = teamScore[teamCount] + playerScore[index2]
9819
                        call ForceAddPlayer(teamForce[teamCount], indexPlayer2)
9820
                        set playerScore[index2] = 0
9821
                    endif
9822
                endif
9823
9824
                set index2 = index2 + 1
9825
                exitwhen index2 == bj_MAX_PLAYERS
9826
            endloop
9827
9828
            set teamCount = teamCount + 1
9829
        endif
9830
9831
        set index = index + 1
9832
        exitwhen index == bj_MAX_PLAYERS
9833
    endloop
9834
9835
    // The game is now over
9836
    set bj_meleeGameOver = true
9837
9838
    // There should always be at least one team, but continue to work if not
9839
    if teamCount != 0 then
9840
9841
        // Find best team score
9842
        set bestTeam = -1
9843
        set bestScore = -1
9844
        set index = 0
9845
        loop
9846
            if teamScore[index] > bestScore then
9847
                set bestTeam = index
9848
                set bestScore = teamScore[index]
9849
            endif
9850
9851
            set index = index + 1
9852
            exitwhen index == teamCount
9853
        endloop
9854
9855
        // Check whether the best team's score is 'multiplier' times better than
9856
        // every other team. In the case of multiplier == 1 and exactly equal team
9857
        // scores, the first team (which was randomly chosen by the server) will win.
9858
        set draw = false
9859
        set index = 0
9860
        loop
9861
            if index != bestTeam then
9862
                if bestScore < (multiplier * teamScore[index]) then
9863
                    set draw = true
9864
                endif
9865
            endif
9866
9867
            set index = index + 1
9868
            exitwhen index == teamCount
9869
        endloop
9870
9871
        if draw then
9872
            // Give draw to all players on all teams
9873
            set index = 0
9874
            loop
9875
                call ForForce(teamForce[index], function MeleeDoDrawEnum)
9876
9877
                set index = index + 1
9878
                exitwhen index == teamCount
9879
            endloop
9880
        else
9881
            // Give defeat to all players on teams other than the best team
9882
            set index = 0
9883
            loop
9884
                if index != bestTeam then
9885
                    call ForForce(teamForce[index], function MeleeDoDefeatEnum)
9886
                endif
9887
9888
                set index = index + 1
9889
                exitwhen index == teamCount
9890
            endloop
9891
9892
            // Give victory to all players on the best team
9893
            call ForForce(teamForce[bestTeam], function MeleeDoVictoryEnum)
9894
        endif
9895
    endif
9896
9897
endfunction
9898
9899
//===========================================================================
9900
function MeleeTriggerTournamentFinishNow takes nothing returns nothing
9901
    local integer rule = GetTournamentFinishNowRule()
9902
9903
    // If the game is already over, do nothing
9904
    if bj_meleeGameOver then
9905
        return
9906
    endif
9907
9908
    if (rule == 1) then
9909
        // Finals games
9910
        call MeleeTournamentFinishNowRuleA(1)
9911
    else
9912
        // Preliminary games
9913
        call MeleeTournamentFinishNowRuleA(3)
9914
    endif
9915
9916
    // Since the game is over we should remove all observers
9917
    call MeleeRemoveObservers()
9918
9919
endfunction
9920
9921
//===========================================================================
9922
function MeleeInitVictoryDefeat takes nothing returns nothing
9923
    local trigger    trig
9924
    local integer    index
9925
    local player     indexPlayer
9926
9927
    // Create a timer window for the "finish soon" timeout period, it has no timer
9928
    // because it is driven by real time (outside of the game state to avoid desyncs)
9929
    set bj_finishSoonTimerDialog = CreateTimerDialog(null)
9930
9931
    // Set a trigger to fire when we receive a "finish soon" game event
9932
    set trig = CreateTrigger()
9933
    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_SOON)
9934
    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishSoon)
9935
9936
    // Set a trigger to fire when we receive a "finish now" game event
9937
    set trig = CreateTrigger()
9938
    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_NOW)
9939
    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishNow)
9940
9941
    // Set up each player's mortality code.
9942
    set index = 0
9943
    loop
9944
        set indexPlayer = Player(index)
9945
9946
        // Make sure this player slot is playing.
9947
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
9948
            set bj_meleeDefeated[index] = false
9949
            set bj_meleeVictoried[index] = false
9950
9951
            // Create a timer and timer window in case the player is crippled.
9952
            set bj_playerIsCrippled[index] = false
9953
            set bj_playerIsExposed[index] = false
9954
            set bj_crippledTimer[index] = CreateTimer()
9955
            set bj_crippledTimerWindows[index] = CreateTimerDialog(bj_crippledTimer[index])
9956
            call TimerDialogSetTitle(bj_crippledTimerWindows[index], MeleeGetCrippledTimerMessage(indexPlayer))
9957
9958
            // Set a trigger to fire whenever a building is cancelled for this player.
9959
            set trig = CreateTrigger()
9960
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)
9961
            call TriggerAddAction(trig, function MeleeTriggerActionConstructCancel)
9962
9963
            // Set a trigger to fire whenever a unit dies for this player.
9964
            set trig = CreateTrigger()
9965
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_DEATH, null)
9966
            call TriggerAddAction(trig, function MeleeTriggerActionUnitDeath)
9967
9968
            // Set a trigger to fire whenever a unit begins construction for this player
9969
            set trig = CreateTrigger()
9970
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)
9971
            call TriggerAddAction(trig, function MeleeTriggerActionUnitConstructionStart)
9972
9973
            // Set a trigger to fire whenever this player defeats-out
9974
            set trig = CreateTrigger()
9975
            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_DEFEAT)
9976
            call TriggerAddAction(trig, function MeleeTriggerActionPlayerDefeated)
9977
9978
            // Set a trigger to fire whenever this player leaves
9979
            set trig = CreateTrigger()
9980
            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
9981
            call TriggerAddAction(trig, function MeleeTriggerActionPlayerLeft)
9982
9983
            // Set a trigger to fire whenever this player changes his/her alliances.
9984
            set trig = CreateTrigger()
9985
            call TriggerRegisterPlayerAllianceChange(trig, indexPlayer, ALLIANCE_PASSIVE)
9986
            call TriggerRegisterPlayerStateEvent(trig, indexPlayer, PLAYER_STATE_ALLIED_VICTORY, EQUAL, 1)
9987
            call TriggerAddAction(trig, function MeleeTriggerActionAllianceChange)
9988
        else
9989
            set bj_meleeDefeated[index] = true
9990
            set bj_meleeVictoried[index] = false
9991
9992
            // Handle leave events for observers
9993
            if (IsPlayerObserver(indexPlayer)) then
9994
                // Set a trigger to fire whenever this player leaves
9995
                set trig = CreateTrigger()
9996
                call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
9997
                call TriggerAddAction(trig, function MeleeTriggerActionPlayerLeft)
9998
            endif
9999
        endif
10000
10001
        set index = index + 1
10002
        exitwhen index == bj_MAX_PLAYERS
10003
    endloop
10004
10005
    // Test for victory / defeat at startup, in case the user has already won / lost.
10006
    // Allow for a short time to pass first, so that the map can finish loading.
10007
    call TimerStart(CreateTimer(), 2.0, false, function MeleeTriggerActionAllianceChange)
10008
endfunction
10009
10010
10011
10012
//***************************************************************************
10013
//*
10014
//*  Player Slot Availability
10015
//*
10016
//***************************************************************************
10017
10018
//===========================================================================
10019
function CheckInitPlayerSlotAvailability takes nothing returns nothing
10020
    local integer index
10021
10022
    if (not bj_slotControlReady) then
10023
        set index = 0
10024
        loop
10025
            set bj_slotControlUsed[index] = false
10026
            set bj_slotControl[index] = MAP_CONTROL_USER
10027
            set index = index + 1
10028
            exitwhen index == bj_MAX_PLAYERS
10029
        endloop
10030
        set bj_slotControlReady = true
10031
    endif
10032
endfunction
10033
10034
//===========================================================================
10035
function SetPlayerSlotAvailable takes player whichPlayer, mapcontrol control returns nothing
10036
    local integer playerIndex = GetPlayerId(whichPlayer)
10037
10038
    call CheckInitPlayerSlotAvailability()
10039
    set bj_slotControlUsed[playerIndex] = true
10040
    set bj_slotControl[playerIndex] = control
10041
endfunction
10042
10043
10044
10045
//***************************************************************************
10046
//*
10047
//*  Generic Template Player-slot Initialization
10048
//*
10049
//***************************************************************************
10050
10051
//===========================================================================
10052
function TeamInitPlayerSlots takes integer teamCount returns nothing
10053
    local integer index
10054
    local player  indexPlayer
10055
    local integer team
10056
10057
    call SetTeams(teamCount)
10058
10059
    call CheckInitPlayerSlotAvailability()
10060
    set index = 0
10061
    set team = 0
10062
    loop
10063
        if (bj_slotControlUsed[index]) then
10064
            set indexPlayer = Player(index)
10065
            call SetPlayerTeam( indexPlayer, team )
10066
            set team = team + 1
10067
            if (team >= teamCount) then
10068
                set team = 0
10069
            endif
10070
        endif
10071
10072
        set index = index + 1
10073
        exitwhen index == bj_MAX_PLAYERS
10074
    endloop
10075
endfunction
10076
10077
//===========================================================================
10078
function MeleeInitPlayerSlots takes nothing returns nothing
10079
    call TeamInitPlayerSlots(bj_MAX_PLAYERS)
10080
endfunction
10081
10082
//===========================================================================
10083
function FFAInitPlayerSlots takes nothing returns nothing
10084
    call TeamInitPlayerSlots(bj_MAX_PLAYERS)
10085
endfunction
10086
10087
//===========================================================================
10088
function OneOnOneInitPlayerSlots takes nothing returns nothing
10089
    // Limit the game to 2 players.
10090
    call SetTeams(2)
10091
    call SetPlayers(2)
10092
    call TeamInitPlayerSlots(2)
10093
endfunction
10094
10095
//===========================================================================
10096
function InitGenericPlayerSlots takes nothing returns nothing
10097
    local gametype gType = GetGameTypeSelected()
10098
10099
    if (gType == GAME_TYPE_MELEE) then
10100
        call MeleeInitPlayerSlots()
10101
    elseif (gType == GAME_TYPE_FFA) then
10102
        call FFAInitPlayerSlots()
10103
    elseif (gType == GAME_TYPE_USE_MAP_SETTINGS) then
10104
        // Do nothing; the map-specific script handles this.
10105
    elseif (gType == GAME_TYPE_ONE_ON_ONE) then
10106
        call OneOnOneInitPlayerSlots()
10107
    elseif (gType == GAME_TYPE_TWO_TEAM_PLAY) then
10108
        call TeamInitPlayerSlots(2)
10109
    elseif (gType == GAME_TYPE_THREE_TEAM_PLAY) then
10110
        call TeamInitPlayerSlots(3)
10111
    elseif (gType == GAME_TYPE_FOUR_TEAM_PLAY) then
10112
        call TeamInitPlayerSlots(4)
10113
    else
10114
        // Unrecognized Game Type
10115
    endif
10116
endfunction
10117
10118
10119
10120
//***************************************************************************
10121
//*
10122
//*  Blizzard.j Initialization
10123
//*
10124
//***************************************************************************
10125
10126
//===========================================================================
10127
function SetDNCSoundsDawn takes nothing returns nothing
10128
    if bj_useDawnDuskSounds then
10129
        call StartSound(bj_dawnSound)
10130
    endif
10131
endfunction
10132
10133
//===========================================================================
10134
function SetDNCSoundsDusk takes nothing returns nothing
10135
    if bj_useDawnDuskSounds then
10136
        call StartSound(bj_duskSound)
10137
    endif
10138
endfunction
10139
10140
//===========================================================================
10141
function SetDNCSoundsDay takes nothing returns nothing
10142
    local real ToD = GetTimeOfDay()
10143
10144
    if (ToD >= bj_TOD_DAWN and ToD < bj_TOD_DUSK) and not bj_dncIsDaytime then
10145
        set bj_dncIsDaytime = true
10146
10147
        // change ambient sounds
10148
        call StopSound(bj_nightAmbientSound, false, true)
10149
        call StartSound(bj_dayAmbientSound)
10150
    endif
10151
endfunction
10152
10153
//===========================================================================
10154
function SetDNCSoundsNight takes nothing returns nothing
10155
    local real ToD = GetTimeOfDay()
10156
10157
    if (ToD < bj_TOD_DAWN or ToD >= bj_TOD_DUSK) and bj_dncIsDaytime then
10158
        set bj_dncIsDaytime = false
10159
10160
        // change ambient sounds
10161
        call StopSound(bj_dayAmbientSound, false, true)
10162
        call StartSound(bj_nightAmbientSound)
10163
    endif
10164
endfunction
10165
10166
//===========================================================================
10167
function InitDNCSounds takes nothing returns nothing
10168
    // Create sounds to be played at dawn and dusk.
10169
    set bj_dawnSound = CreateSoundFromLabel("RoosterSound", false, false, false, 10000, 10000)
10170
    set bj_duskSound = CreateSoundFromLabel("WolfSound", false, false, false, 10000, 10000)
10171
10172
    // Set up triggers to respond to dawn and dusk.
10173
    set bj_dncSoundsDawn = CreateTrigger()
10174
    call TriggerRegisterGameStateEvent(bj_dncSoundsDawn, GAME_STATE_TIME_OF_DAY, EQUAL, bj_TOD_DAWN)
10175
    call TriggerAddAction(bj_dncSoundsDawn, function SetDNCSoundsDawn)
10176
10177
    set bj_dncSoundsDusk = CreateTrigger()
10178
    call TriggerRegisterGameStateEvent(bj_dncSoundsDusk, GAME_STATE_TIME_OF_DAY, EQUAL, bj_TOD_DUSK)
10179
    call TriggerAddAction(bj_dncSoundsDusk, function SetDNCSoundsDusk)
10180
10181
    // Set up triggers to respond to changes from day to night or vice-versa.
10182
    set bj_dncSoundsDay = CreateTrigger()
10183
    call TriggerRegisterGameStateEvent(bj_dncSoundsDay,   GAME_STATE_TIME_OF_DAY, GREATER_THAN_OR_EQUAL, bj_TOD_DAWN)
10184
    call TriggerRegisterGameStateEvent(bj_dncSoundsDay,   GAME_STATE_TIME_OF_DAY, LESS_THAN,             bj_TOD_DUSK)
10185
    call TriggerAddAction(bj_dncSoundsDay, function SetDNCSoundsDay)
10186
10187
    set bj_dncSoundsNight = CreateTrigger()
10188
    call TriggerRegisterGameStateEvent(bj_dncSoundsNight, GAME_STATE_TIME_OF_DAY, LESS_THAN,             bj_TOD_DAWN)
10189
    call TriggerRegisterGameStateEvent(bj_dncSoundsNight, GAME_STATE_TIME_OF_DAY, GREATER_THAN_OR_EQUAL, bj_TOD_DUSK)
10190
    call TriggerAddAction(bj_dncSoundsNight, function SetDNCSoundsNight)
10191
endfunction
10192
10193
//===========================================================================
10194
function InitBlizzardGlobals takes nothing returns nothing
10195
    local integer index
10196
    local integer userControlledPlayers
10197
    local version v
10198
10199
    // Init filter function vars
10200
    set filterIssueHauntOrderAtLocBJ = Filter(function IssueHauntOrderAtLocBJFilter)
10201
    set filterEnumDestructablesInCircleBJ = Filter(function EnumDestructablesInCircleBJFilter)
10202
    set filterGetUnitsInRectOfPlayer = Filter(function GetUnitsInRectOfPlayerFilter)
10203
    set filterGetUnitsOfTypeIdAll = Filter(function GetUnitsOfTypeIdAllFilter)
10204
    set filterGetUnitsOfPlayerAndTypeId = Filter(function GetUnitsOfPlayerAndTypeIdFilter)
10205
    set filterMeleeTrainedUnitIsHeroBJ = Filter(function MeleeTrainedUnitIsHeroBJFilter)
10206
    set filterLivingPlayerUnitsOfTypeId = Filter(function LivingPlayerUnitsOfTypeIdFilter)
10207
10208
    // Init force presets
10209
    set index = 0
10210
    loop
10211
        exitwhen index == bj_MAX_PLAYER_SLOTS
10212
        set bj_FORCE_PLAYER[index] = CreateForce()
10213
        call ForceAddPlayer(bj_FORCE_PLAYER[index], Player(index))
10214
        set index = index + 1
10215
    endloop
10216
10217
    set bj_FORCE_ALL_PLAYERS = CreateForce()
10218
    call ForceEnumPlayers(bj_FORCE_ALL_PLAYERS, null)
10219
10220
    // Init Cinematic Mode history
10221
    set bj_cineModePriorSpeed = GetGameSpeed()
10222
    set bj_cineModePriorFogSetting = IsFogEnabled()
10223
    set bj_cineModePriorMaskSetting = IsFogMaskEnabled()
10224
10225
    // Init Trigger Queue
10226
    set index = 0
10227
    loop
10228
        exitwhen index >= bj_MAX_QUEUED_TRIGGERS
10229
        set bj_queuedExecTriggers[index] = null
10230
        set bj_queuedExecUseConds[index] = false
10231
        set index = index + 1
10232
    endloop
10233
10234
    // Init singleplayer check
10235
    set bj_isSinglePlayer = false
10236
    set userControlledPlayers = 0
10237
    set index = 0
10238
    loop
10239
        exitwhen index >= bj_MAX_PLAYERS
10240
        if (GetPlayerController(Player(index)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING) then
10241
            set userControlledPlayers = userControlledPlayers + 1
10242
        endif
10243
        set index = index + 1
10244
    endloop
10245
    set bj_isSinglePlayer = (userControlledPlayers == 1)
10246
10247
    // Init sounds
10248
    //set bj_pingMinimapSound = CreateSoundFromLabel("AutoCastButtonClick", false, false, false, 10000, 10000)
10249
    set bj_rescueSound = CreateSoundFromLabel("Rescue", false, false, false, 10000, 10000)
10250
    set bj_questDiscoveredSound = CreateSoundFromLabel("QuestNew", false, false, false, 10000, 10000)
10251
    set bj_questUpdatedSound = CreateSoundFromLabel("QuestUpdate", false, false, false, 10000, 10000)
10252
    set bj_questCompletedSound = CreateSoundFromLabel("QuestCompleted", false, false, false, 10000, 10000)
10253
    set bj_questFailedSound = CreateSoundFromLabel("QuestFailed", false, false, false, 10000, 10000)
10254
    set bj_questHintSound = CreateSoundFromLabel("Hint", false, false, false, 10000, 10000)
10255
    set bj_questSecretSound = CreateSoundFromLabel("SecretFound", false, false, false, 10000, 10000)
10256
    set bj_questItemAcquiredSound = CreateSoundFromLabel("ItemReward", false, false, false, 10000, 10000)
10257
    set bj_questWarningSound = CreateSoundFromLabel("Warning", false, false, false, 10000, 10000)
10258
    set bj_victoryDialogSound = CreateSoundFromLabel("QuestCompleted", false, false, false, 10000, 10000)
10259
    set bj_defeatDialogSound = CreateSoundFromLabel("QuestFailed", false, false, false, 10000, 10000)
10260
10261
    // Init corpse creation triggers.
10262
    call DelayedSuspendDecayCreate()
10263
10264
    // Init version-specific data
10265
    set v = VersionGet()
10266
    if (v == VERSION_REIGN_OF_CHAOS) then
10267
        set bj_MELEE_MAX_TWINKED_HEROES = bj_MELEE_MAX_TWINKED_HEROES_V0
10268
    else
10269
        set bj_MELEE_MAX_TWINKED_HEROES = bj_MELEE_MAX_TWINKED_HEROES_V1
10270
    endif
10271
endfunction
10272
10273
//===========================================================================
10274
function InitQueuedTriggers takes nothing returns nothing
10275
    set bj_queuedExecTimeout = CreateTrigger()
10276
    call TriggerRegisterTimerExpireEvent(bj_queuedExecTimeout, bj_queuedExecTimeoutTimer)
10277
    call TriggerAddAction(bj_queuedExecTimeout, function QueuedTriggerDoneBJ)
10278
endfunction
10279
10280
//===========================================================================
10281
function InitMapRects takes nothing returns nothing
10282
    set bj_mapInitialPlayableArea = Rect(GetCameraBoundMinX()-GetCameraMargin(CAMERA_MARGIN_LEFT), GetCameraBoundMinY()-GetCameraMargin(CAMERA_MARGIN_BOTTOM), GetCameraBoundMaxX()+GetCameraMargin(CAMERA_MARGIN_RIGHT), GetCameraBoundMaxY()+GetCameraMargin(CAMERA_MARGIN_TOP))
10283
    set bj_mapInitialCameraBounds = GetCurrentCameraBoundsMapRectBJ()
10284
endfunction
10285
10286
//===========================================================================
10287
function InitSummonableCaps takes nothing returns nothing
10288
    local integer index
10289
10290
    set index = 0
10291
    loop
10292
        // upgraded units
10293
        // Note: Only do this if the corresponding upgrade is not yet researched
10294
        // Barrage - Siege Engines
10295
        if (not GetPlayerTechResearched(Player(index), 'Rhrt', true)) then
10296
            call SetPlayerTechMaxAllowed(Player(index), 'hrtt', 0)
10297
        endif
10298
10299
        // Berserker Upgrade - Troll Berserkers
10300
        if (not GetPlayerTechResearched(Player(index), 'Robk', true)) then
10301
            call SetPlayerTechMaxAllowed(Player(index), 'otbk', 0)
10302
        endif
10303
10304
        // max skeletons per player
10305
        call SetPlayerTechMaxAllowed(Player(index), 'uske', bj_MAX_SKELETONS)
10306
10307
        set index = index + 1
10308
        exitwhen index == bj_MAX_PLAYERS
10309
    endloop
10310
endfunction
10311
10312
//===========================================================================
10313
// Update the per-class stock limits.
10314
//
10315
function UpdateStockAvailability takes item whichItem returns nothing
10316
    local itemtype iType  = GetItemType(whichItem)
10317
    local integer  iLevel = GetItemLevel(whichItem)
10318
10319
    // Update allowed type/level combinations.
10320
    if (iType == ITEM_TYPE_PERMANENT) then
10321
        set bj_stockAllowedPermanent[iLevel] = true
10322
    elseif (iType == ITEM_TYPE_CHARGED) then
10323
        set bj_stockAllowedCharged[iLevel] = true
10324
    elseif (iType == ITEM_TYPE_ARTIFACT) then
10325
        set bj_stockAllowedArtifact[iLevel] = true
10326
    else
10327
        // Not interested in this item type - ignore the item.
10328
    endif
10329
endfunction
10330
10331
//===========================================================================
10332
// Find a sellable item of the given type and level, and then add it.
10333
//
10334
function UpdateEachStockBuildingEnum takes nothing returns nothing
10335
    local integer iteration = 0
10336
    local integer pickedItemId
10337
10338
    loop
10339
        set pickedItemId = ChooseRandomItemEx(bj_stockPickedItemType, bj_stockPickedItemLevel)
10340
        exitwhen IsItemIdSellable(pickedItemId)
10341
10342
        // If we get hung up on an entire class/level combo of unsellable
10343
        // items, or a very unlucky series of random numbers, give up.
10344
        set iteration = iteration + 1
10345
        if (iteration > bj_STOCK_MAX_ITERATIONS) then
10346
            return
10347
        endif
10348
    endloop
10349
    call AddItemToStock(GetEnumUnit(), pickedItemId, 1, 1)
10350
endfunction
10351
10352
//===========================================================================
10353
function UpdateEachStockBuilding takes itemtype iType, integer iLevel returns nothing
10354
    local group g
10355
10356
    set bj_stockPickedItemType = iType
10357
    set bj_stockPickedItemLevel = iLevel
10358
10359
    set g = CreateGroup()
10360
    call GroupEnumUnitsOfType(g, "marketplace", null)
10361
    call ForGroup(g, function UpdateEachStockBuildingEnum)
10362
    call DestroyGroup(g)
10363
endfunction
10364
10365
//===========================================================================
10366
// Update stock inventory.
10367
//
10368
function PerformStockUpdates takes nothing returns nothing
10369
    local integer  pickedItemId
10370
    local itemtype pickedItemType
10371
    local integer  pickedItemLevel = 0
10372
    local integer  allowedCombinations = 0
10373
    local integer  iLevel
10374
10375
    // Give each type/level combination a chance of being picked.
10376
    set iLevel = 1
10377
    loop
10378
        if (bj_stockAllowedPermanent[iLevel]) then
10379
            set allowedCombinations = allowedCombinations + 1
10380
            if (GetRandomInt(1, allowedCombinations) == 1) then
10381
                set pickedItemType = ITEM_TYPE_PERMANENT
10382
                set pickedItemLevel = iLevel
10383
            endif
10384
        endif
10385
        if (bj_stockAllowedCharged[iLevel]) then
10386
            set allowedCombinations = allowedCombinations + 1
10387
            if (GetRandomInt(1, allowedCombinations) == 1) then
10388
                set pickedItemType = ITEM_TYPE_CHARGED
10389
                set pickedItemLevel = iLevel
10390
            endif
10391
        endif
10392
        if (bj_stockAllowedArtifact[iLevel]) then
10393
            set allowedCombinations = allowedCombinations + 1
10394
            if (GetRandomInt(1, allowedCombinations) == 1) then
10395
                set pickedItemType = ITEM_TYPE_ARTIFACT
10396
                set pickedItemLevel = iLevel
10397
            endif
10398
        endif
10399
10400
        set iLevel = iLevel + 1
10401
        exitwhen iLevel > bj_MAX_ITEM_LEVEL
10402
    endloop
10403
10404
    // Make sure we found a valid item type to add.
10405
    if (allowedCombinations == 0) then
10406
        return
10407
    endif
10408
10409
    call UpdateEachStockBuilding(pickedItemType, pickedItemLevel)
10410
endfunction
10411
10412
//===========================================================================
10413
// Perform the first update, and then arrange future updates.
10414
//
10415
function StartStockUpdates takes nothing returns nothing
10416
    call PerformStockUpdates()
10417
    call TimerStart(bj_stockUpdateTimer, bj_STOCK_RESTOCK_INTERVAL, true, function PerformStockUpdates)
10418
endfunction
10419
10420
//===========================================================================
10421
function RemovePurchasedItem takes nothing returns nothing
10422
    call RemoveItemFromStock(GetSellingUnit(), GetItemTypeId(GetSoldItem()))
10423
endfunction
10424
10425
//===========================================================================
10426
function InitNeutralBuildings takes nothing returns nothing
10427
    local integer iLevel
10428
10429
    // Chart of allowed stock items.
10430
    set iLevel = 0
10431
    loop
10432
        set bj_stockAllowedPermanent[iLevel] = false
10433
        set bj_stockAllowedCharged[iLevel] = false
10434
        set bj_stockAllowedArtifact[iLevel] = false
10435
        set iLevel = iLevel + 1
10436
        exitwhen iLevel > bj_MAX_ITEM_LEVEL
10437
    endloop
10438
10439
    // Limit stock inventory slots.
10440
    call SetAllItemTypeSlots(bj_MAX_STOCK_ITEM_SLOTS)
10441
    call SetAllUnitTypeSlots(bj_MAX_STOCK_UNIT_SLOTS)
10442
10443
    // Arrange the first update.
10444
    set bj_stockUpdateTimer = CreateTimer()
10445
    call TimerStart(bj_stockUpdateTimer, bj_STOCK_RESTOCK_INITIAL_DELAY, false, function StartStockUpdates)
10446
10447
    // Set up a trigger to fire whenever an item is sold.
10448
    set bj_stockItemPurchased = CreateTrigger()
10449
    call TriggerRegisterPlayerUnitEvent(bj_stockItemPurchased, Player(PLAYER_NEUTRAL_PASSIVE), EVENT_PLAYER_UNIT_SELL_ITEM, null)
10450
    call TriggerAddAction(bj_stockItemPurchased, function RemovePurchasedItem)
10451
endfunction
10452
10453
//===========================================================================
10454
function MarkGameStarted takes nothing returns nothing
10455
    set bj_gameStarted = true
10456
    call DestroyTimer(bj_gameStartedTimer)
10457
endfunction
10458
10459
//===========================================================================
10460
function DetectGameStarted takes nothing returns nothing
10461
    set bj_gameStartedTimer = CreateTimer()
10462
    call TimerStart(bj_gameStartedTimer, bj_GAME_STARTED_THRESHOLD, false, function MarkGameStarted)
10463
endfunction
10464
10465
//===========================================================================
10466
function InitBlizzard takes nothing returns nothing
10467
    // Set up the Neutral Victim player slot, to torture the abandoned units
10468
    // of defeated players.  Since some triggers expect this player slot to
10469
    // exist, this is performed for all maps.
10470
    call ConfigureNeutralVictim()
10471
10472
    call InitBlizzardGlobals()
10473
    call InitQueuedTriggers()
10474
    call InitRescuableBehaviorBJ()
10475
    call InitDNCSounds()
10476
    call InitMapRects()
10477
    call InitSummonableCaps()
10478
    call InitNeutralBuildings()
10479
    call DetectGameStarted()
10480
endfunction
10481
10482
10483
10484
//***************************************************************************
10485
//*
10486
//*  Random distribution
10487
//*
10488
//*  Used to select a random object from a given distribution of chances
10489
//*
10490
//*  - RandomDistReset clears the distribution list
10491
//*
10492
//*  - RandomDistAddItem adds a new object to the distribution list
10493
//*    with a given identifier and an integer chance to be chosen
10494
//*
10495
//*  - RandomDistChoose will use the current distribution list to choose
10496
//*    one of the objects randomly based on the chance distribution
10497
//*  
10498
//*  Note that the chances are effectively normalized by their sum,
10499
//*  so only the relative values of each chance are important
10500
//*
10501
//***************************************************************************
10502
10503
//===========================================================================
10504
function RandomDistReset takes nothing returns nothing
10505
    set bj_randDistCount = 0
10506
endfunction
10507
10508
//===========================================================================
10509
function RandomDistAddItem takes integer inID, integer inChance returns nothing
10510
    set bj_randDistID[bj_randDistCount] = inID
10511
    set bj_randDistChance[bj_randDistCount] = inChance
10512
    set bj_randDistCount = bj_randDistCount + 1
10513
endfunction
10514
10515
//===========================================================================
10516
function RandomDistChoose takes nothing returns integer
10517
    local integer sum = 0
10518
    local integer chance = 0
10519
    local integer index
10520
    local integer foundID = -1
10521
    local boolean done
10522
10523
    // No items?
10524
    if (bj_randDistCount == 0) then
10525
        return -1
10526
    endif
10527
10528
    // Find sum of all chances
10529
    set index = 0
10530
    loop
10531
        set sum = sum + bj_randDistChance[index]
10532
10533
        set index = index + 1
10534
        exitwhen index == bj_randDistCount
10535
    endloop
10536
10537
    // Choose random number within the total range
10538
    set chance = GetRandomInt(1, sum)
10539
10540
    // Find ID which corresponds to this chance
10541
    set index = 0
10542
    set sum = 0
10543
    set done = false
10544
    loop
10545
        set sum = sum + bj_randDistChance[index]
10546
10547
        if (chance <= sum) then
10548
            set foundID = bj_randDistID[index]
10549
            set done = true
10550
        endif
10551
10552
        set index = index + 1
10553
        if (index == bj_randDistCount) then
10554
            set done = true
10555
        endif
10556
10557
        exitwhen done == true
10558
    endloop
10559
10560
    return foundID
10561
endfunction
10562
10563
10564
10565
//***************************************************************************
10566
//*
10567
//*  Drop item
10568
//*
10569
//*  Makes the given unit drop the given item
10570
//*
10571
//*  Note: This could potentially cause problems if the unit is standing
10572
//*        right on the edge of an unpathable area and happens to drop the
10573
//*        item into the unpathable area where nobody can get it...
10574
//*
10575
//***************************************************************************
10576
10577
function UnitDropItem takes unit inUnit, integer inItemID returns item
10578
    local real x
10579
    local real y
10580
    local real radius = 32
10581
    local real unitX
10582
    local real unitY
10583
    local item droppedItem
10584
10585
    if (inItemID == -1) then
10586
        return null
10587
    endif
10588
10589
    set unitX = GetUnitX(inUnit)
10590
    set unitY = GetUnitY(inUnit)
10591
10592
    set x = GetRandomReal(unitX - radius, unitX + radius)
10593
    set y = GetRandomReal(unitY - radius, unitY + radius)
10594
10595
    set droppedItem = CreateItem(inItemID, x, y)
10596
10597
    call SetItemDropID(droppedItem, GetUnitTypeId(inUnit))
10598
    call UpdateStockAvailability(droppedItem)
10599
10600
    return droppedItem
10601
endfunction
10602
10603
//===========================================================================
10604
function WidgetDropItem takes widget inWidget, integer inItemID returns item
10605
    local real x
10606
    local real y
10607
    local real radius = 32
10608
    local real widgetX
10609
    local real widgetY
10610
10611
    if (inItemID == -1) then
10612
        return null
10613
    endif
10614
10615
    set widgetX = GetWidgetX(inWidget)
10616
    set widgetY = GetWidgetY(inWidget)
10617
10618
    set x = GetRandomReal(widgetX - radius, widgetX + radius)
10619
    set y = GetRandomReal(widgetY - radius, widgetY + radius)
10620
10621
    return CreateItem(inItemID, x, y)
10622
endfunction
10623
10624
10625
//***************************************************************************
10626
//*
10627
//*  Instanced Object Operation Functions
10628
//*
10629
//*  Get/Set specific fields for single unit/item/ability instance
10630
//*
10631
//***************************************************************************
10632
10633
//===========================================================================
10634
function BlzIsLastInstanceObjectFunctionSuccessful takes nothing returns boolean
10635
    return bj_lastInstObjFuncSuccessful
10636
endfunction
10637
10638
// Ability
10639
//===========================================================================
10640
function BlzSetAbilityBooleanFieldBJ takes ability whichAbility, abilitybooleanfield whichField, boolean value returns nothing
10641
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityBooleanField(whichAbility, whichField, value)
10642
endfunction
10643
10644
//===========================================================================
10645
function BlzSetAbilityIntegerFieldBJ takes ability whichAbility, abilityintegerfield whichField, integer value returns nothing
10646
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityIntegerField(whichAbility, whichField, value)
10647
endfunction
10648
10649
//===========================================================================
10650
function BlzSetAbilityRealFieldBJ takes ability whichAbility, abilityrealfield whichField, real value returns nothing
10651
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityRealField(whichAbility, whichField, value)
10652
endfunction
10653
10654
//===========================================================================
10655
function BlzSetAbilityStringFieldBJ takes ability whichAbility, abilitystringfield whichField, string value returns nothing
10656
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityStringField(whichAbility, whichField, value)
10657
endfunction
10658
10659
//===========================================================================
10660
function BlzSetAbilityBooleanLevelFieldBJ takes ability whichAbility, abilitybooleanlevelfield whichField, integer level, boolean value returns nothing
10661
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityBooleanLevelField(whichAbility, whichField, level, value)
10662
endfunction
10663
10664
//===========================================================================
10665
function BlzSetAbilityIntegerLevelFieldBJ takes ability whichAbility, abilityintegerlevelfield whichField, integer level, integer value returns nothing
10666
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityIntegerLevelField(whichAbility, whichField, level, value)
10667
endfunction
10668
10669
//===========================================================================
10670
function BlzSetAbilityRealLevelFieldBJ takes ability whichAbility, abilityreallevelfield whichField, integer level, real value returns nothing
10671
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityRealLevelField(whichAbility, whichField, level, value)
10672
endfunction
10673
10674
//===========================================================================
10675
function BlzSetAbilityStringLevelFieldBJ takes ability whichAbility, abilitystringlevelfield whichField, integer level, string value returns nothing
10676
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityStringLevelField(whichAbility, whichField, level, value)
10677
endfunction
10678
10679
//===========================================================================
10680
function BlzSetAbilityBooleanLevelArrayFieldBJ takes ability whichAbility, abilitybooleanlevelarrayfield whichField, integer level, integer index, boolean value returns nothing
10681
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityBooleanLevelArrayField(whichAbility, whichField, level, index, value)
10682
endfunction
10683
10684
//===========================================================================
10685
function BlzSetAbilityIntegerLevelArrayFieldBJ takes ability whichAbility, abilityintegerlevelarrayfield whichField, integer level, integer index, integer value returns nothing
10686
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityIntegerLevelArrayField(whichAbility, whichField, level, index, value)
10687
endfunction
10688
10689
//===========================================================================
10690
function BlzSetAbilityRealLevelArrayFieldBJ takes ability whichAbility, abilityreallevelarrayfield whichField, integer level, integer index, real value returns nothing
10691
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityRealLevelArrayField(whichAbility, whichField, level, index, value)
10692
endfunction
10693
10694
//===========================================================================
10695
function BlzSetAbilityStringLevelArrayFieldBJ takes ability whichAbility, abilitystringlevelarrayfield whichField, integer level, integer index, string value returns nothing
10696
    set bj_lastInstObjFuncSuccessful = BlzSetAbilityStringLevelArrayField(whichAbility, whichField, level, index, value)
10697
endfunction
10698
10699
//===========================================================================
10700
function BlzAddAbilityBooleanLevelArrayFieldBJ takes ability whichAbility, abilitybooleanlevelarrayfield whichField, integer level, boolean value returns nothing
10701
    set bj_lastInstObjFuncSuccessful = BlzAddAbilityBooleanLevelArrayField(whichAbility, whichField, level, value)
10702
endfunction
10703
10704
//===========================================================================
10705
function BlzAddAbilityIntegerLevelArrayFieldBJ takes ability whichAbility, abilityintegerlevelarrayfield whichField, integer level, integer value returns nothing
10706
    set bj_lastInstObjFuncSuccessful = BlzAddAbilityIntegerLevelArrayField(whichAbility, whichField, level, value)
10707
endfunction
10708
10709
//===========================================================================
10710
function BlzAddAbilityRealLevelArrayFieldBJ takes ability whichAbility, abilityreallevelarrayfield whichField, integer level, real value returns nothing
10711
    set bj_lastInstObjFuncSuccessful = BlzAddAbilityRealLevelArrayField(whichAbility, whichField, level, value)
10712
endfunction
10713
10714
//===========================================================================
10715
function BlzAddAbilityStringLevelArrayFieldBJ takes ability whichAbility, abilitystringlevelarrayfield whichField, integer level, string value returns nothing
10716
    set bj_lastInstObjFuncSuccessful = BlzAddAbilityStringLevelArrayField(whichAbility, whichField, level, value)
10717
endfunction
10718
10719
//===========================================================================
10720
function BlzRemoveAbilityBooleanLevelArrayFieldBJ takes ability whichAbility, abilitybooleanlevelarrayfield whichField, integer level, boolean value returns nothing
10721
    set bj_lastInstObjFuncSuccessful = BlzRemoveAbilityBooleanLevelArrayField(whichAbility, whichField, level, value)
10722
endfunction
10723
10724
//===========================================================================
10725
function BlzRemoveAbilityIntegerLevelArrayFieldBJ takes ability whichAbility, abilityintegerlevelarrayfield whichField, integer level, integer value returns nothing
10726
    set bj_lastInstObjFuncSuccessful = BlzRemoveAbilityIntegerLevelArrayField(whichAbility, whichField, level, value)
10727
endfunction
10728
10729
//===========================================================================
10730
function BlzRemoveAbilityRealLevelArrayFieldBJ takes ability whichAbility, abilityreallevelarrayfield whichField, integer level, real value returns nothing
10731
    set bj_lastInstObjFuncSuccessful = BlzRemoveAbilityRealLevelArrayField(whichAbility, whichField, level, value)
10732
endfunction
10733
10734
//===========================================================================
10735
function BlzRemoveAbilityStringLevelArrayFieldBJ takes ability whichAbility, abilitystringlevelarrayfield whichField, integer level, string value returns nothing
10736
    set bj_lastInstObjFuncSuccessful = BlzRemoveAbilityStringLevelArrayField(whichAbility, whichField, level, value)
10737
endfunction
10738
10739
// Item 
10740
//=============================================================
10741
function BlzItemAddAbilityBJ takes item whichItem, integer abilCode returns nothing
10742
    set bj_lastInstObjFuncSuccessful = BlzItemAddAbility(whichItem, abilCode)
10743
endfunction
10744
10745
//===========================================================================
10746
function BlzItemRemoveAbilityBJ takes item whichItem, integer abilCode returns nothing
10747
    set bj_lastInstObjFuncSuccessful = BlzItemRemoveAbility(whichItem, abilCode)
10748
endfunction
10749
10750
//===========================================================================
10751
function BlzSetItemBooleanFieldBJ takes item whichItem, itembooleanfield whichField, boolean value returns nothing
10752
    set bj_lastInstObjFuncSuccessful = BlzSetItemBooleanField(whichItem, whichField, value)
10753
endfunction
10754
10755
//===========================================================================
10756
function BlzSetItemIntegerFieldBJ takes item whichItem, itemintegerfield whichField, integer value returns nothing
10757
    set bj_lastInstObjFuncSuccessful = BlzSetItemIntegerField(whichItem, whichField, value)
10758
endfunction
10759
10760
//===========================================================================
10761
function BlzSetItemRealFieldBJ takes item whichItem, itemrealfield whichField, real value returns nothing
10762
    set bj_lastInstObjFuncSuccessful = BlzSetItemRealField(whichItem, whichField, value)
10763
endfunction
10764
10765
//===========================================================================
10766
function BlzSetItemStringFieldBJ takes item whichItem, itemstringfield whichField, string value returns nothing
10767
    set bj_lastInstObjFuncSuccessful = BlzSetItemStringField(whichItem, whichField, value)
10768
endfunction
10769
10770
10771
// Unit 
10772
//===========================================================================
10773
function BlzSetUnitBooleanFieldBJ takes unit whichUnit, unitbooleanfield whichField, boolean value returns nothing
10774
    set bj_lastInstObjFuncSuccessful = BlzSetUnitBooleanField(whichUnit, whichField, value)
10775
endfunction
10776
10777
//===========================================================================
10778
function BlzSetUnitIntegerFieldBJ takes unit whichUnit, unitintegerfield whichField, integer value returns nothing
10779
    set bj_lastInstObjFuncSuccessful = BlzSetUnitIntegerField(whichUnit, whichField, value)
10780
endfunction
10781
10782
//===========================================================================
10783
function BlzSetUnitRealFieldBJ takes unit whichUnit, unitrealfield whichField, real value returns nothing
10784
    set bj_lastInstObjFuncSuccessful = BlzSetUnitRealField(whichUnit, whichField, value)
10785
endfunction
10786
10787
//===========================================================================
10788
function BlzSetUnitStringFieldBJ takes unit whichUnit, unitstringfield whichField, string value returns nothing
10789
    set bj_lastInstObjFuncSuccessful = BlzSetUnitStringField(whichUnit, whichField, value)
10790
endfunction
10791
10792
// Unit Weapon
10793
//===========================================================================
10794
function BlzSetUnitWeaponBooleanFieldBJ takes unit whichUnit, unitweaponbooleanfield whichField, integer index, boolean value returns nothing
10795
    set bj_lastInstObjFuncSuccessful = BlzSetUnitWeaponBooleanField(whichUnit, whichField, index, value)
10796
endfunction
10797
10798
//===========================================================================
10799
function BlzSetUnitWeaponIntegerFieldBJ takes unit whichUnit, unitweaponintegerfield whichField, integer index, integer value returns nothing
10800
    set bj_lastInstObjFuncSuccessful = BlzSetUnitWeaponIntegerField(whichUnit, whichField, index, value)
10801
endfunction
10802
10803
//===========================================================================
10804
function BlzSetUnitWeaponRealFieldBJ takes unit whichUnit, unitweaponrealfield whichField, integer index, real value returns nothing
10805
    set bj_lastInstObjFuncSuccessful = BlzSetUnitWeaponRealField(whichUnit, whichField, index, value)
10806
endfunction
10807
10808
//===========================================================================
10809
function BlzSetUnitWeaponStringFieldBJ takes unit whichUnit, unitweaponstringfield whichField, integer index, string value returns nothing
10810
    set bj_lastInstObjFuncSuccessful = BlzSetUnitWeaponStringField(whichUnit, whichField, index, value)
10811
endfunction
10812