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