1 /*
2 ** thingdef_data.cpp
3 **
4 ** DECORATE data tables
5 **
6 **---------------------------------------------------------------------------
7 ** Copyright 2002-2008 Christoph Oelckers
8 ** Copyright 2004-2008 Randy Heit
9 ** All rights reserved.
10 **
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
13 ** are met:
14 **
15 ** 1. Redistributions of source code must retain the above copyright
16 ** notice, this list of conditions and the following disclaimer.
17 ** 2. Redistributions in binary form must reproduce the above copyright
18 ** notice, this list of conditions and the following disclaimer in the
19 ** documentation and/or other materials provided with the distribution.
20 ** 3. The name of the author may not be used to endorse or promote products
21 ** derived from this software without specific prior written permission.
22 ** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be
23 ** covered by the terms of the GNU General Public License as published by
24 ** the Free Software Foundation; either version 2 of the License, or (at
25 ** your option) any later version.
26 **
27 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 **---------------------------------------------------------------------------
38 **
39 */
40
41 #include "thingdef.h"
42 #include "actor.h"
43 #include "d_player.h"
44 #include "p_effect.h"
45 #include "autosegs.h"
46
47 static TArray<FPropertyInfo*> properties;
48 static TArray<AFuncDesc> AFTable;
49 static TArray<FVariableInfo*> variables;
50
51 //==========================================================================
52 //
53 // List of all flags
54 //
55 //==========================================================================
56
57 // [RH] Keep GCC quiet by not using offsetof on Actor types.
58 #define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable) }
59 #define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable) }
60 #define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0 }
61 #define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1, 0 }
62
63 static FFlagDef ActorFlagDefs[]=
64 {
65 DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags),
66 DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
67 DEFINE_FLAG(MF, SOLID, AActor, flags),
68 DEFINE_FLAG(MF, SHOOTABLE, AActor, flags),
69 DEFINE_FLAG(MF, NOSECTOR, AActor, flags),
70 DEFINE_FLAG(MF, NOBLOCKMAP, AActor, flags),
71 DEFINE_FLAG(MF, AMBUSH, AActor, flags),
72 DEFINE_FLAG(MF, JUSTHIT, AActor, flags),
73 DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags),
74 DEFINE_FLAG(MF, SPAWNCEILING, AActor, flags),
75 DEFINE_FLAG(MF, NOGRAVITY, AActor, flags),
76 DEFINE_FLAG(MF, DROPOFF, AActor, flags),
77 DEFINE_FLAG(MF, NOCLIP, AActor, flags),
78 DEFINE_FLAG(MF, FLOAT, AActor, flags),
79 DEFINE_FLAG(MF, TELEPORT, AActor, flags),
80 DEFINE_FLAG(MF, MISSILE, AActor, flags),
81 DEFINE_FLAG(MF, DROPPED, AActor, flags),
82 DEFINE_FLAG(MF, SHADOW, AActor, flags),
83 DEFINE_FLAG(MF, NOBLOOD, AActor, flags),
84 DEFINE_FLAG(MF, CORPSE, AActor, flags),
85 DEFINE_FLAG(MF, INFLOAT, AActor, flags),
86 DEFINE_FLAG(MF, COUNTKILL, AActor, flags),
87 DEFINE_FLAG(MF, COUNTITEM, AActor, flags),
88 DEFINE_FLAG(MF, SKULLFLY, AActor, flags),
89 DEFINE_FLAG(MF, NOTDMATCH, AActor, flags),
90 DEFINE_FLAG(MF, SPAWNSOUNDSOURCE, AActor, flags),
91 DEFINE_FLAG(MF, FRIENDLY, AActor, flags),
92 DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags),
93 DEFINE_FLAG(MF, STEALTH, AActor, flags),
94 DEFINE_FLAG(MF, ICECORPSE, AActor, flags),
95
96 DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2),
97 DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
98 DEFINE_FLAG(MF2, DONTSEEKINVISIBLE, AActor, flags2),
99 DEFINE_FLAG(MF2, BLASTED, AActor, flags2),
100 DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
101 DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
102 DEFINE_FLAG(MF2, NOTELEPORT, AActor, flags2),
103 DEFINE_FLAG2(MF2_RIP, RIPPER, AActor, flags2),
104 DEFINE_FLAG(MF2, PUSHABLE, AActor, flags2),
105 DEFINE_FLAG2(MF2_SLIDE, SLIDESONWALLS, AActor, flags2),
106 DEFINE_FLAG2(MF2_PASSMOBJ, CANPASS, AActor, flags2),
107 DEFINE_FLAG(MF2, CANNOTPUSH, AActor, flags2),
108 DEFINE_FLAG(MF2, THRUGHOST, AActor, flags2),
109 DEFINE_FLAG(MF2, BOSS, AActor, flags2),
110 DEFINE_FLAG2(MF2_NODMGTHRUST, NODAMAGETHRUST, AActor, flags2),
111 DEFINE_FLAG(MF2, DONTTRANSLATE, AActor, flags2),
112 DEFINE_FLAG(MF2, TELESTOMP, AActor, flags2),
113 DEFINE_FLAG(MF2, FLOATBOB, AActor, flags2),
114 DEFINE_FLAG(MF2, THRUACTORS, AActor, flags2),
115 DEFINE_FLAG2(MF2_IMPACT, ACTIVATEIMPACT, AActor, flags2),
116 DEFINE_FLAG2(MF2_PUSHWALL, CANPUSHWALLS, AActor, flags2),
117 DEFINE_FLAG2(MF2_MCROSS, ACTIVATEMCROSS, AActor, flags2),
118 DEFINE_FLAG2(MF2_PCROSS, ACTIVATEPCROSS, AActor, flags2),
119 DEFINE_FLAG(MF2, CANTLEAVEFLOORPIC, AActor, flags2),
120 DEFINE_FLAG(MF2, NONSHOOTABLE, AActor, flags2),
121 DEFINE_FLAG(MF2, INVULNERABLE, AActor, flags2),
122 DEFINE_FLAG(MF2, DORMANT, AActor, flags2),
123 DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2),
124 DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2),
125
126 DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3),
127 DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3),
128 DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3),
129 DEFINE_FLAG(MF3, GHOST, AActor, flags3),
130 DEFINE_FLAG(MF3, SPECIALFLOORCLIP, AActor, flags3),
131 DEFINE_FLAG(MF3, ALWAYSPUFF, AActor, flags3),
132 DEFINE_FLAG(MF3, DONTSPLASH, AActor, flags3),
133 DEFINE_FLAG(MF3, DONTOVERLAP, AActor, flags3),
134 DEFINE_FLAG(MF3, DONTMORPH, AActor, flags3),
135 DEFINE_FLAG(MF3, DONTSQUASH, AActor, flags3),
136 DEFINE_FLAG(MF3, EXPLOCOUNT, AActor, flags3),
137 DEFINE_FLAG(MF3, FULLVOLACTIVE, AActor, flags3),
138 DEFINE_FLAG(MF3, ISMONSTER, AActor, flags3),
139 DEFINE_FLAG(MF3, SKYEXPLODE, AActor, flags3),
140 DEFINE_FLAG(MF3, STAYMORPHED, AActor, flags3),
141 DEFINE_FLAG(MF3, DONTBLAST, AActor, flags3),
142 DEFINE_FLAG(MF3, CANBLAST, AActor, flags3),
143 DEFINE_FLAG(MF3, NOTARGET, AActor, flags3),
144 DEFINE_FLAG(MF3, DONTGIB, AActor, flags3),
145 DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3),
146 DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3),
147 DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3),
148 DEFINE_FLAG(MF3, SCREENSEEKER, AActor, flags3),
149 DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3),
150 DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3),
151 DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3),
152 DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3),
153 DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3),
154
155 DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4),
156 DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4),
157 DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4),
158 DEFINE_FLAG(MF4, FIXMAPTHINGPOS , AActor, flags4),
159 DEFINE_FLAG(MF4, ACTLIKEBRIDGE, AActor, flags4),
160 DEFINE_FLAG(MF4, STRIFEDAMAGE, AActor, flags4),
161 DEFINE_FLAG(MF4, CANUSEWALLS, AActor, flags4),
162 DEFINE_FLAG(MF4, MISSILEMORE, AActor, flags4),
163 DEFINE_FLAG(MF4, MISSILEEVENMORE, AActor, flags4),
164 DEFINE_FLAG(MF4, FORCERADIUSDMG, AActor, flags4),
165 DEFINE_FLAG(MF4, DONTFALL, AActor, flags4),
166 DEFINE_FLAG(MF4, SEESDAGGERS, AActor, flags4),
167 DEFINE_FLAG(MF4, INCOMBAT, AActor, flags4),
168 DEFINE_FLAG(MF4, LOOKALLAROUND, AActor, flags4),
169 DEFINE_FLAG(MF4, STANDSTILL, AActor, flags4),
170 DEFINE_FLAG(MF4, SPECTRAL, AActor, flags4),
171 DEFINE_FLAG(MF4, NOSPLASHALERT, AActor, flags4),
172 DEFINE_FLAG(MF4, SYNCHRONIZED, AActor, flags4),
173 DEFINE_FLAG(MF4, NOTARGETSWITCH, AActor, flags4),
174 DEFINE_FLAG(MF4, DONTHARMCLASS, AActor, flags4),
175 DEFINE_FLAG2(MF4_DONTHARMCLASS, DONTHURTSPECIES, AActor, flags4), // Deprecated name as an alias
176 DEFINE_FLAG(MF4, SHIELDREFLECT, AActor, flags4),
177 DEFINE_FLAG(MF4, DEFLECT, AActor, flags4),
178 DEFINE_FLAG(MF4, ALLOWPARTICLES, AActor, flags4),
179 DEFINE_FLAG(MF4, EXTREMEDEATH, AActor, flags4),
180 DEFINE_FLAG(MF4, NOEXTREMEDEATH, AActor, flags4),
181 DEFINE_FLAG(MF4, FRIGHTENED, AActor, flags4),
182 DEFINE_FLAG(MF4, NOSKIN, AActor, flags4),
183 DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4),
184
185 DEFINE_FLAG(MF5, DONTDRAIN, AActor, flags5),
186 DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5),
187 DEFINE_FLAG(MF5, NOFORWARDFALL, AActor, flags5),
188 DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5),
189 DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5),
190 DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5),
191 DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5),
192 DEFINE_FLAG(MF5, DEHEXPLOSION, AActor, flags5),
193 DEFINE_FLAG(MF5, PIERCEARMOR, AActor, flags5),
194 DEFINE_FLAG(MF5, NOBLOODDECALS, AActor, flags5),
195 DEFINE_FLAG(MF5, USESPECIAL, AActor, flags5),
196 DEFINE_FLAG(MF5, NOPAIN, AActor, flags5),
197 DEFINE_FLAG(MF5, ALWAYSFAST, AActor, flags5),
198 DEFINE_FLAG(MF5, NEVERFAST, AActor, flags5),
199 DEFINE_FLAG(MF5, ALWAYSRESPAWN, AActor, flags5),
200 DEFINE_FLAG(MF5, NEVERRESPAWN, AActor, flags5),
201 DEFINE_FLAG(MF5, DONTRIP, AActor, flags5),
202 DEFINE_FLAG(MF5, NOINFIGHTING, AActor, flags5),
203 DEFINE_FLAG(MF5, NOINTERACTION, AActor, flags5),
204 DEFINE_FLAG(MF5, NOTIMEFREEZE, AActor, flags5),
205 DEFINE_FLAG(MF5, PUFFGETSOWNER, AActor, flags5), // [BB] added PUFFGETSOWNER
206 DEFINE_FLAG(MF5, SPECIALFIREDAMAGE, AActor, flags5),
207 DEFINE_FLAG(MF5, SUMMONEDMONSTER, AActor, flags5),
208 DEFINE_FLAG(MF5, NOVERTICALMELEERANGE, AActor, flags5),
209 DEFINE_FLAG(MF5, BRIGHT, AActor, flags5),
210 DEFINE_FLAG(MF5, CANTSEEK, AActor, flags5),
211 DEFINE_FLAG(MF5, PAINLESS, AActor, flags5),
212 DEFINE_FLAG(MF5, MOVEWITHSECTOR, AActor, flags5),
213
214 DEFINE_FLAG(MF6, NOBOSSRIP, AActor, flags6),
215 DEFINE_FLAG(MF6, THRUSPECIES, AActor, flags6),
216 DEFINE_FLAG(MF6, MTHRUSPECIES, AActor, flags6),
217 DEFINE_FLAG(MF6, FORCEPAIN, AActor, flags6),
218 DEFINE_FLAG(MF6, NOFEAR, AActor, flags6),
219 DEFINE_FLAG(MF6, BUMPSPECIAL, AActor, flags6),
220 DEFINE_FLAG(MF6, DONTHARMSPECIES, AActor, flags6),
221 DEFINE_FLAG(MF6, STEPMISSILE, AActor, flags6),
222 DEFINE_FLAG(MF6, NOTELEFRAG, AActor, flags6),
223 DEFINE_FLAG(MF6, TOUCHY, AActor, flags6),
224 DEFINE_FLAG(MF6, CANJUMP, AActor, flags6),
225 DEFINE_FLAG(MF6, JUMPDOWN, AActor, flags6),
226 DEFINE_FLAG(MF6, VULNERABLE, AActor, flags6),
227 DEFINE_FLAG(MF6, NOTRIGGER, AActor, flags6),
228 DEFINE_FLAG(MF6, ADDITIVEPOISONDAMAGE, AActor, flags6),
229 DEFINE_FLAG(MF6, ADDITIVEPOISONDURATION, AActor, flags6),
230 DEFINE_FLAG(MF6, BLOCKEDBYSOLIDACTORS, AActor, flags6),
231 DEFINE_FLAG(MF6, NOMENU, AActor, flags6),
232 DEFINE_FLAG(MF6, SEEINVISIBLE, AActor, flags6),
233 DEFINE_FLAG(MF6, DONTCORPSE, AActor, flags6),
234 DEFINE_FLAG(MF6, DOHARMSPECIES, AActor, flags6),
235 DEFINE_FLAG(MF6, POISONALWAYS, AActor, flags6),
236 DEFINE_FLAG(MF6, NOTAUTOAIMED, AActor, flags6),
237 DEFINE_FLAG(MF6, NOTONAUTOMAP, AActor, flags6),
238 DEFINE_FLAG(MF6, RELATIVETOFLOOR, AActor, flags6),
239
240 DEFINE_FLAG(MF7, NEVERTARGET, AActor, flags7),
241 DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7),
242 DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7),
243 DEFINE_FLAG(MF7, WEAPONSPAWN, AActor, flags7),
244 DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7),
245 DEFINE_FLAG(MF7, BUDDHA, AActor, flags7),
246 DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7),
247 DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7),
248 DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7),
249 DEFINE_FLAG(MF7, CAUSEPAIN, AActor, flags7),
250 DEFINE_FLAG(MF7, THRUREFLECT, AActor, flags7),
251 DEFINE_FLAG(MF7, MIRRORREFLECT, AActor, flags7),
252 DEFINE_FLAG(MF7, AIMREFLECT, AActor, flags7),
253 DEFINE_FLAG(MF7, HITTARGET, AActor, flags7),
254 DEFINE_FLAG(MF7, HITMASTER, AActor, flags7),
255 DEFINE_FLAG(MF7, HITTRACER, AActor, flags7),
256 DEFINE_FLAG(MF7, NODECAL, AActor, flags7), // [ZK] Decal flags
257 DEFINE_FLAG(MF7, FORCEDECAL, AActor, flags7),
258 DEFINE_FLAG(MF7, LAXTELEFRAGDMG, AActor, flags7),
259 DEFINE_FLAG(MF7, ICESHATTER, AActor, flags7),
260
261 // Effect flags
262 DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
263 DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects),
264 DEFINE_FLAG2(FX_GRENADE, GRENADETRAIL, AActor, effects),
265 DEFINE_FLAG(RF, INVISIBLE, AActor, renderflags),
266 DEFINE_FLAG(RF, FORCEYBILLBOARD, AActor, renderflags),
267 DEFINE_FLAG(RF, FORCEXYBILLBOARD, AActor, renderflags),
268
269 // Bounce flags
270 DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags),
271 DEFINE_FLAG2(BOUNCE_Floors, BOUNCEONFLOORS, AActor, BounceFlags),
272 DEFINE_FLAG2(BOUNCE_Ceilings, BOUNCEONCEILINGS, AActor, BounceFlags),
273 DEFINE_FLAG2(BOUNCE_Actors, ALLOWBOUNCEONACTORS, AActor, BounceFlags),
274 DEFINE_FLAG2(BOUNCE_AutoOff, BOUNCEAUTOOFF, AActor, BounceFlags),
275 DEFINE_FLAG2(BOUNCE_HereticType, BOUNCELIKEHERETIC, AActor, BounceFlags),
276 DEFINE_FLAG2(BOUNCE_CanBounceWater, CANBOUNCEWATER, AActor, BounceFlags),
277 DEFINE_FLAG2(BOUNCE_NoWallSound, NOWALLBOUNCESND, AActor, BounceFlags),
278 DEFINE_FLAG2(BOUNCE_Quiet, NOBOUNCESOUND, AActor, BounceFlags),
279 DEFINE_FLAG2(BOUNCE_AllActors, BOUNCEONACTORS, AActor, BounceFlags),
280 DEFINE_FLAG2(BOUNCE_ExplodeOnWater, EXPLODEONWATER, AActor, BounceFlags),
281 DEFINE_FLAG2(BOUNCE_MBF, MBFBOUNCER, AActor, BounceFlags),
282 DEFINE_FLAG2(BOUNCE_AutoOffFloorOnly, BOUNCEAUTOOFFFLOORONLY, AActor, BounceFlags),
283 DEFINE_FLAG2(BOUNCE_UseBounceState, USEBOUNCESTATE, AActor, BounceFlags),
284
285 // Deprecated flags. Handling must be performed in HandleDeprecatedFlags
286 DEFINE_DEPRECATED_FLAG(FIREDAMAGE),
287 DEFINE_DEPRECATED_FLAG(ICEDAMAGE),
288 DEFINE_DEPRECATED_FLAG(LOWGRAVITY),
289 DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE),
290 DEFINE_DEPRECATED_FLAG(LONGMELEERANGE),
291 DEFINE_DEPRECATED_FLAG(QUARTERGRAVITY),
292 DEFINE_DEPRECATED_FLAG(FIRERESIST),
293 DEFINE_DEPRECATED_FLAG(HERETICBOUNCE),
294 DEFINE_DEPRECATED_FLAG(HEXENBOUNCE),
295 DEFINE_DEPRECATED_FLAG(DOOMBOUNCE),
296
297 // Deprecated flags with no more existing functionality.
298 DEFINE_DUMMY_FLAG(FASTER), // obsolete, replaced by 'Fast' state flag
299 DEFINE_DUMMY_FLAG(FASTMELEE), // obsolete, replaced by 'Fast' state flag
300
301 // Various Skulltag flags that are quite irrelevant to ZDoom
302 DEFINE_DUMMY_FLAG(NONETID), // netcode-based
303 DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), // netcode-based
304 DEFINE_DUMMY_FLAG(CLIENTSIDEONLY), // netcode-based
305 DEFINE_DUMMY_FLAG(SERVERSIDEONLY), // netcode-based
306 DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless
307 };
308
309 static FFlagDef InventoryFlagDefs[] =
310 {
311 // Inventory flags
312 DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags),
313 DEFINE_FLAG(IF, AUTOACTIVATE, AInventory, ItemFlags),
314 DEFINE_FLAG(IF, UNDROPPABLE, AInventory, ItemFlags),
315 DEFINE_FLAG(IF, INVBAR, AInventory, ItemFlags),
316 DEFINE_FLAG(IF, HUBPOWER, AInventory, ItemFlags),
317 DEFINE_FLAG(IF, UNTOSSABLE, AInventory, ItemFlags),
318 DEFINE_FLAG(IF, ADDITIVETIME, AInventory, ItemFlags),
319 DEFINE_FLAG(IF, ALWAYSPICKUP, AInventory, ItemFlags),
320 DEFINE_FLAG(IF, FANCYPICKUPSOUND, AInventory, ItemFlags),
321 DEFINE_FLAG(IF, BIGPOWERUP, AInventory, ItemFlags),
322 DEFINE_FLAG(IF, KEEPDEPLETED, AInventory, ItemFlags),
323 DEFINE_FLAG(IF, IGNORESKILL, AInventory, ItemFlags),
324 DEFINE_FLAG(IF, NOATTENPICKUPSOUND, AInventory, ItemFlags),
325 DEFINE_FLAG(IF, PERSISTENTPOWER, AInventory, ItemFlags),
326 DEFINE_FLAG(IF, RESTRICTABSOLUTELY, AInventory, ItemFlags),
327 DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags),
328 DEFINE_FLAG(IF, NOSCREENFLASH, AInventory, ItemFlags),
329 DEFINE_FLAG(IF, TOSSED, AInventory, ItemFlags),
330 DEFINE_FLAG(IF, ALWAYSRESPAWN, AInventory, ItemFlags),
331 DEFINE_FLAG(IF, TRANSFER, AInventory, ItemFlags),
332 DEFINE_FLAG(IF, NOTELEPORTFREEZE, AInventory, ItemFlags),
333
334 DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
335 DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),
336 };
337
338 static FFlagDef WeaponFlagDefs[] =
339 {
340 // Weapon flags
341 DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
342 DEFINE_FLAG(WIF, READYSNDHALF, AWeapon, WeaponFlags),
343 DEFINE_FLAG(WIF, DONTBOB, AWeapon, WeaponFlags),
344 DEFINE_FLAG(WIF, AXEBLOOD, AWeapon, WeaponFlags),
345 DEFINE_FLAG(WIF, NOALERT, AWeapon, WeaponFlags),
346 DEFINE_FLAG(WIF, AMMO_OPTIONAL, AWeapon, WeaponFlags),
347 DEFINE_FLAG(WIF, ALT_AMMO_OPTIONAL, AWeapon, WeaponFlags),
348 DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags),
349 DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
350 DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
351 DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
352 DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
353 DEFINE_FLAG(WIF, MELEEWEAPON, AWeapon, WeaponFlags),
354 DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags),
355 DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
356 DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
357 DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags),
358 DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
359
360 DEFINE_DUMMY_FLAG(NOLMS),
361 DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags),
362 DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL),
363 };
364
365 static FFlagDef PlayerPawnFlagDefs[] =
366 {
367 // PlayerPawn flags
368 DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags),
369 DEFINE_FLAG(PPF, CANSUPERMORPH, APlayerPawn, PlayerFlags),
370 DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags),
371 };
372
373 static FFlagDef PowerSpeedFlagDefs[] =
374 {
375 // PowerSpeed flags
376 DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags),
377 };
378
379 static const struct FFlagList { const PClass *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] =
380 {
381 { RUNTIME_CLASS(AActor), ActorFlagDefs, countof(ActorFlagDefs) },
382 { RUNTIME_CLASS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs) },
383 { RUNTIME_CLASS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs) },
384 { RUNTIME_CLASS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs) },
385 { RUNTIME_CLASS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs) },
386 };
387 #define NUM_FLAG_LISTS (countof(FlagLists))
388
389 //==========================================================================
390 //
391 // Find a flag by name using a binary search
392 //
393 //==========================================================================
FindFlag(FFlagDef * flags,int numflags,const char * flag)394 static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag)
395 {
396 int min = 0, max = numflags - 1;
397
398 while (min <= max)
399 {
400 int mid = (min + max) / 2;
401 int lexval = stricmp (flag, flags[mid].name);
402 if (lexval == 0)
403 {
404 return &flags[mid];
405 }
406 else if (lexval > 0)
407 {
408 min = mid + 1;
409 }
410 else
411 {
412 max = mid - 1;
413 }
414 }
415 return NULL;
416 }
417
418 //==========================================================================
419 //
420 // Finds a flag that may have a qualified name
421 //
422 //==========================================================================
423
FindFlag(const PClass * type,const char * part1,const char * part2)424 FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
425 {
426 FFlagDef *def;
427 size_t i;
428
429 if (part2 == NULL)
430 { // Search all lists
431 for (i = 0; i < NUM_FLAG_LISTS; ++i)
432 {
433 if (type->IsDescendantOf (FlagLists[i].Type))
434 {
435 def = FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part1);
436 if (def != NULL)
437 {
438 return def;
439 }
440 }
441 }
442 }
443 else
444 { // Search just the named list
445 for (i = 0; i < NUM_FLAG_LISTS; ++i)
446 {
447 if (stricmp (FlagLists[i].Type->TypeName.GetChars(), part1) == 0)
448 {
449 if (type->IsDescendantOf (FlagLists[i].Type))
450 {
451 return FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part2);
452 }
453 else
454 {
455 return NULL;
456 }
457 }
458 }
459 }
460 return NULL;
461 }
462
463
464 //==========================================================================
465 //
466 // Gets the name of an actor flag
467 //
468 //==========================================================================
469
GetFlagName(unsigned int flagnum,int flagoffset)470 const char *GetFlagName(unsigned int flagnum, int flagoffset)
471 {
472 for(unsigned i = 0; i < countof(ActorFlagDefs); i++)
473 {
474 if (ActorFlagDefs[i].flagbit == flagnum && ActorFlagDefs[i].structoffset == flagoffset)
475 {
476 return ActorFlagDefs[i].name;
477 }
478 }
479 return "(unknown)"; // return something printable
480 }
481
482 //==========================================================================
483 //
484 // Find a property by name using a binary search
485 //
486 //==========================================================================
487
FindProperty(const char * string)488 FPropertyInfo *FindProperty(const char * string)
489 {
490 int min = 0, max = properties.Size()-1;
491
492 while (min <= max)
493 {
494 int mid = (min + max) / 2;
495 int lexval = stricmp (string, properties[mid]->name);
496 if (lexval == 0)
497 {
498 return properties[mid];
499 }
500 else if (lexval > 0)
501 {
502 min = mid + 1;
503 }
504 else
505 {
506 max = mid - 1;
507 }
508 }
509 return NULL;
510 }
511
512 //==========================================================================
513 //
514 // Find a function by name using a binary search
515 //
516 //==========================================================================
517
FindFunction(const char * string)518 AFuncDesc *FindFunction(const char * string)
519 {
520 int min = 0, max = AFTable.Size()-1;
521
522 while (min <= max)
523 {
524 int mid = (min + max) / 2;
525 int lexval = stricmp (string, AFTable[mid].Name);
526 if (lexval == 0)
527 {
528 return &AFTable[mid];
529 }
530 else if (lexval > 0)
531 {
532 min = mid + 1;
533 }
534 else
535 {
536 max = mid - 1;
537 }
538 }
539 return NULL;
540 }
541
542
543 //==========================================================================
544 //
545 // Find a variable by name using a binary search
546 //
547 //==========================================================================
548
FindVariable(const char * string,const PClass * cls)549 FVariableInfo *FindVariable(const char * string, const PClass *cls)
550 {
551 int min = 0, max = variables.Size()-1;
552
553 while (min <= max)
554 {
555 int mid = (min + max) / 2;
556 int lexval;
557
558 if (cls < variables[mid]->owner) lexval = -1;
559 else if (cls > variables[mid]->owner) lexval = 1;
560 else lexval = stricmp (string, variables[mid]->name);
561
562 if (lexval == 0)
563 {
564 return variables[mid];
565 }
566 else if (lexval > 0)
567 {
568 min = mid + 1;
569 }
570 else
571 {
572 max = mid - 1;
573 }
574 }
575 return NULL;
576 }
577
578
579 //==========================================================================
580 //
581 // Find an action function in AActor's table
582 //
583 //==========================================================================
584
FindGlobalActionFunction(const char * name)585 PSymbolActionFunction *FindGlobalActionFunction(const char *name)
586 {
587 PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false);
588 if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
589 return static_cast<PSymbolActionFunction*>(sym);
590 else
591 return NULL;
592 }
593
594
595 //==========================================================================
596 //
597 // Sorting helpers
598 //
599 //==========================================================================
600
flagcmp(const void * a,const void * b)601 static int STACK_ARGS flagcmp (const void * a, const void * b)
602 {
603 return stricmp( ((FFlagDef*)a)->name, ((FFlagDef*)b)->name);
604 }
605
propcmp(const void * a,const void * b)606 static int STACK_ARGS propcmp(const void * a, const void * b)
607 {
608 return stricmp( (*(FPropertyInfo**)a)->name, (*(FPropertyInfo**)b)->name);
609 }
610
funccmp(const void * a,const void * b)611 static int STACK_ARGS funccmp(const void * a, const void * b)
612 {
613 return stricmp( ((AFuncDesc*)a)->Name, ((AFuncDesc*)b)->Name);
614 }
615
varcmp(const void * a,const void * b)616 static int STACK_ARGS varcmp(const void * a, const void * b)
617 {
618 FVariableInfo *A = *(FVariableInfo**)a;
619 FVariableInfo *B = *(FVariableInfo**)b;
620 if (A->owner < B->owner) return -1;
621 if (A->owner > B->owner) return 1;
622 return stricmp(A->name, B->name);
623 }
624
625 //==========================================================================
626 //
627 // Initialization
628 //
629 //==========================================================================
630
InitThingdef()631 void InitThingdef()
632 {
633 // Sort the flag lists
634 for (size_t i = 0; i < NUM_FLAG_LISTS; ++i)
635 {
636 qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp);
637 }
638
639 // Create a sorted list of properties
640 if (properties.Size() == 0)
641 {
642 FAutoSegIterator probe(GRegHead, GRegTail);
643
644 while (*++probe != NULL)
645 {
646 properties.Push((FPropertyInfo *)*probe);
647 }
648 properties.ShrinkToFit();
649 qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp);
650 }
651
652 // Create a sorted list of native action functions
653 if (AFTable.Size() == 0)
654 {
655 FAutoSegIterator probe(ARegHead, ARegTail);
656
657 while (*++probe != NULL)
658 {
659 AFTable.Push(*(AFuncDesc *)*probe);
660 }
661 AFTable.ShrinkToFit();
662 qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
663 }
664
665 // Create a sorted list of native variables
666 if (variables.Size() == 0)
667 {
668 FAutoSegIterator probe(MRegHead, MRegTail);
669
670 while (*++probe != NULL)
671 {
672 variables.Push((FVariableInfo *)*probe);
673 }
674 variables.ShrinkToFit();
675 qsort(&variables[0], variables.Size(), sizeof(variables[0]), varcmp);
676 }
677 }
678
679