2016-03-01 15:47:10 +00:00
/*
* * thingdef_data . cpp
* *
* * DECORATE data tables
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 2002 - 2008 Christoph Oelckers
* * Copyright 2004 - 2008 Randy Heit
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* * 4. When not used as part of ZDoom or a ZDoom derivative , this code will be
* * covered by the terms of the GNU General Public License as published by
* * the Free Software Foundation ; either version 2 of the License , or ( at
* * your option ) any later version .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
*/
# include "thingdef.h"
# include "actor.h"
# include "d_player.h"
# include "p_effect.h"
2016-11-26 00:14:47 +00:00
# include "gi.h"
2016-11-27 23:49:10 +00:00
# include "p_terrain.h"
2016-11-28 17:15:18 +00:00
# include "gstrings.h"
2017-01-08 17:45:30 +00:00
# include "g_levellocals.h"
2017-01-11 22:46:03 +00:00
# include "p_checkposition.h"
2017-02-03 23:46:22 +00:00
# include "v_font.h"
2017-02-10 10:44:46 +00:00
# include "menu/menu.h"
2017-02-18 00:20:07 +00:00
# include "teaminfo.h"
2017-02-17 20:51:23 +00:00
# include "r_data/sprites.h"
2017-03-03 19:11:13 +00:00
# include "serializer.h"
2017-03-18 18:34:03 +00:00
# include "wi_stuff.h"
2017-03-19 23:34:19 +00:00
# include "a_dynlight.h"
2017-04-12 23:12:04 +00:00
# include "types.h"
2016-03-01 15:47:10 +00:00
static TArray < FPropertyInfo * > properties ;
static TArray < AFuncDesc > AFTable ;
2016-11-22 18:20:31 +00:00
static TArray < FieldDesc > FieldTable ;
2017-02-19 14:23:33 +00:00
extern int BackbuttonTime ;
extern float BackbuttonAlpha ;
2017-04-12 20:46:49 +00:00
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// List of all flags
//
//==========================================================================
// [RH] Keep GCC quiet by not using offsetof on Actor types.
2016-10-25 07:55:13 +00:00
# define DEFINE_FLAG(prefix, name, type, variable) { (unsigned int)prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native }
2016-11-08 10:12:56 +00:00
# define DEFINE_PROTECTED_FLAG(prefix, name, type, variable) { (unsigned int)prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native|VARF_ReadOnly|VARF_InternalAccess }
2016-10-25 07:55:13 +00:00
# define DEFINE_FLAG2(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native }
# define DEFINE_FLAG2_DEPRECATED(symbol, name, type, variable) { (unsigned int)symbol, #name, (int)(size_t)&((type*)1)->variable - 1, sizeof(((type *)0)->variable), VARF_Native|VARF_Deprecated }
2016-10-24 15:18:20 +00:00
# define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0, true }
2016-10-25 07:55:13 +00:00
# define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec? VARF_Deprecated:0 }
2016-03-01 15:47:10 +00:00
2016-10-31 16:02:47 +00:00
// internal flags. These do not get exposed to actor definitions but scripts need to be able to access them as variables.
2016-11-22 22:42:32 +00:00
static FFlagDef InternalActorFlagDefs [ ] =
2016-10-31 16:02:47 +00:00
{
DEFINE_FLAG ( MF , INCHASE , AActor , flags ) ,
DEFINE_FLAG ( MF , UNMORPHED , AActor , flags ) ,
DEFINE_FLAG ( MF2 , FLY , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , ONMOBJ , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , ARGSDEFINED , AActor , flags2 ) ,
DEFINE_FLAG ( MF3 , NOSIGHTCHECK , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , CRASHED , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , WARNBOT , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , HUNTPLAYERS , AActor , flags3 ) ,
DEFINE_FLAG ( MF4 , NOHATEPLAYERS , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , SCROLLMOVE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , VFRICTION , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , BOSSSPAWNED , AActor , flags4 ) ,
DEFINE_FLAG ( MF5 , AVOIDINGDROPOFF , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , CHASEGOAL , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , INCONVERSATION , AActor , flags5 ) ,
DEFINE_FLAG ( MF6 , ARMED , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , FALLING , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , LINEDONE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , SHATTERING , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , KILLED , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , BOSSCUBE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , INTRYMOVE , AActor , flags6 ) ,
DEFINE_FLAG ( MF7 , HANDLENODELAY , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , FLYCHEAT , AActor , flags7 ) ,
2017-01-16 22:45:25 +00:00
DEFINE_FLAG ( FX , RESPAWNINVUL , AActor , effects ) ,
2016-10-31 16:02:47 +00:00
} ;
2016-11-22 22:42:32 +00:00
static FFlagDef ActorFlagDefs [ ] =
2016-03-01 15:47:10 +00:00
{
DEFINE_FLAG ( MF , PICKUP , APlayerPawn , flags ) ,
DEFINE_FLAG ( MF , SPECIAL , APlayerPawn , flags ) ,
DEFINE_FLAG ( MF , SOLID , AActor , flags ) ,
DEFINE_FLAG ( MF , SHOOTABLE , AActor , flags ) ,
2016-11-08 10:12:56 +00:00
DEFINE_PROTECTED_FLAG ( MF , NOSECTOR , AActor , flags ) ,
DEFINE_PROTECTED_FLAG ( MF , NOBLOCKMAP , AActor , flags ) ,
2016-03-01 15:47:10 +00:00
DEFINE_FLAG ( MF , AMBUSH , AActor , flags ) ,
DEFINE_FLAG ( MF , JUSTHIT , AActor , flags ) ,
DEFINE_FLAG ( MF , JUSTATTACKED , AActor , flags ) ,
DEFINE_FLAG ( MF , SPAWNCEILING , AActor , flags ) ,
DEFINE_FLAG ( MF , NOGRAVITY , AActor , flags ) ,
DEFINE_FLAG ( MF , DROPOFF , AActor , flags ) ,
DEFINE_FLAG ( MF , NOCLIP , AActor , flags ) ,
DEFINE_FLAG ( MF , FLOAT , AActor , flags ) ,
DEFINE_FLAG ( MF , TELEPORT , AActor , flags ) ,
DEFINE_FLAG ( MF , MISSILE , AActor , flags ) ,
DEFINE_FLAG ( MF , DROPPED , AActor , flags ) ,
DEFINE_FLAG ( MF , SHADOW , AActor , flags ) ,
DEFINE_FLAG ( MF , NOBLOOD , AActor , flags ) ,
DEFINE_FLAG ( MF , CORPSE , AActor , flags ) ,
DEFINE_FLAG ( MF , INFLOAT , AActor , flags ) ,
2016-10-27 13:53:53 +00:00
DEFINE_FLAG ( MF , COUNTKILL , AActor , flags ) ,
DEFINE_FLAG ( MF , COUNTITEM , AActor , flags ) ,
2016-03-01 15:47:10 +00:00
DEFINE_FLAG ( MF , SKULLFLY , AActor , flags ) ,
DEFINE_FLAG ( MF , NOTDMATCH , AActor , flags ) ,
DEFINE_FLAG ( MF , SPAWNSOUNDSOURCE , AActor , flags ) ,
DEFINE_FLAG ( MF , FRIENDLY , AActor , flags ) ,
DEFINE_FLAG ( MF , NOLIFTDROP , AActor , flags ) ,
DEFINE_FLAG ( MF , STEALTH , AActor , flags ) ,
DEFINE_FLAG ( MF , ICECORPSE , AActor , flags ) ,
DEFINE_FLAG ( MF2 , DONTREFLECT , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , WINDTHRUST , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , DONTSEEKINVISIBLE , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , BLASTED , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , FLOORCLIP , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , SPAWNFLOAT , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , NOTELEPORT , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_RIP , RIPPER , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , PUSHABLE , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_SLIDE , SLIDESONWALLS , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_PASSMOBJ , CANPASS , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , CANNOTPUSH , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , THRUGHOST , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , BOSS , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_NODMGTHRUST , NODAMAGETHRUST , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , DONTTRANSLATE , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , TELESTOMP , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , FLOATBOB , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , THRUACTORS , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_IMPACT , ACTIVATEIMPACT , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_PUSHWALL , CANPUSHWALLS , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_MCROSS , ACTIVATEMCROSS , AActor , flags2 ) ,
DEFINE_FLAG2 ( MF2_PCROSS , ACTIVATEPCROSS , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , CANTLEAVEFLOORPIC , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , NONSHOOTABLE , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , INVULNERABLE , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , DORMANT , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , SEEKERMISSILE , AActor , flags2 ) ,
DEFINE_FLAG ( MF2 , REFLECTIVE , AActor , flags2 ) ,
DEFINE_FLAG ( MF3 , FLOORHUGGER , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , CEILINGHUGGER , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , NORADIUSDMG , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , GHOST , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , SPECIALFLOORCLIP , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , ALWAYSPUFF , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , DONTSPLASH , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , DONTOVERLAP , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , DONTMORPH , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , DONTSQUASH , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , EXPLOCOUNT , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , FULLVOLACTIVE , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , ISMONSTER , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , SKYEXPLODE , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , STAYMORPHED , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , DONTBLAST , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , CANBLAST , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , NOTARGET , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , DONTGIB , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , NOBLOCKMONST , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , FULLVOLDEATH , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , AVOIDMELEE , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , SCREENSEEKER , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , FOILINVUL , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , NOTELEOTHER , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , BLOODLESSIMPACT , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , NOEXPLODEFLOOR , AActor , flags3 ) ,
DEFINE_FLAG ( MF3 , PUFFONACTORS , AActor , flags3 ) ,
DEFINE_FLAG ( MF4 , QUICKTORETALIATE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , NOICEDEATH , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , RANDOMIZE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , FIXMAPTHINGPOS , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , ACTLIKEBRIDGE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , STRIFEDAMAGE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , CANUSEWALLS , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , MISSILEMORE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , MISSILEEVENMORE , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , FORCERADIUSDMG , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , DONTFALL , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , SEESDAGGERS , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , INCOMBAT , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , LOOKALLAROUND , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , STANDSTILL , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , SPECTRAL , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , NOSPLASHALERT , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , SYNCHRONIZED , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , NOTARGETSWITCH , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , DONTHARMCLASS , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , SHIELDREFLECT , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , DEFLECT , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , ALLOWPARTICLES , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , EXTREMEDEATH , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , NOEXTREMEDEATH , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , FRIGHTENED , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , NOSKIN , AActor , flags4 ) ,
DEFINE_FLAG ( MF4 , BOSSDEATH , AActor , flags4 ) ,
DEFINE_FLAG ( MF5 , DONTDRAIN , AActor , flags5 ) ,
2016-09-04 13:53:20 +00:00
DEFINE_FLAG ( MF5 , GETOWNER , AActor , flags5 ) ,
2016-03-01 15:47:10 +00:00
DEFINE_FLAG ( MF5 , NODROPOFF , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOFORWARDFALL , AActor , flags5 ) ,
2016-10-27 13:53:53 +00:00
DEFINE_FLAG ( MF5 , COUNTSECRET , AActor , flags5 ) ,
2016-03-01 15:47:10 +00:00
DEFINE_FLAG ( MF5 , NODAMAGE , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , BLOODSPLATTER , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , OLDRADIUSDMG , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , DEHEXPLOSION , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , PIERCEARMOR , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOBLOODDECALS , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , USESPECIAL , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOPAIN , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , ALWAYSFAST , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NEVERFAST , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , ALWAYSRESPAWN , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NEVERRESPAWN , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , DONTRIP , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOINFIGHTING , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOINTERACTION , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOTIMEFREEZE , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , PUFFGETSOWNER , AActor , flags5 ) , // [BB] added PUFFGETSOWNER
DEFINE_FLAG ( MF5 , SPECIALFIREDAMAGE , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , SUMMONEDMONSTER , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , NOVERTICALMELEERANGE , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , BRIGHT , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , CANTSEEK , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , PAINLESS , AActor , flags5 ) ,
DEFINE_FLAG ( MF5 , MOVEWITHSECTOR , AActor , flags5 ) ,
DEFINE_FLAG ( MF6 , NOBOSSRIP , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , THRUSPECIES , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , MTHRUSPECIES , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , FORCEPAIN , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , NOFEAR , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , BUMPSPECIAL , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , DONTHARMSPECIES , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , STEPMISSILE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , NOTELEFRAG , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , TOUCHY , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , CANJUMP , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , JUMPDOWN , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , VULNERABLE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , NOTRIGGER , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , ADDITIVEPOISONDAMAGE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , ADDITIVEPOISONDURATION , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , BLOCKEDBYSOLIDACTORS , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , NOMENU , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , SEEINVISIBLE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , DONTCORPSE , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , DOHARMSPECIES , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , POISONALWAYS , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , NOTAUTOAIMED , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , NOTONAUTOMAP , AActor , flags6 ) ,
DEFINE_FLAG ( MF6 , RELATIVETOFLOOR , AActor , flags6 ) ,
DEFINE_FLAG ( MF7 , NEVERTARGET , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , NOTELESTOMP , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , ALWAYSTELEFRAG , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , WEAPONSPAWN , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , HARMFRIENDS , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , BUDDHA , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , FOILBUDDHA , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , DONTTHRUST , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , ALLOWPAIN , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , CAUSEPAIN , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , THRUREFLECT , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , MIRRORREFLECT , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , AIMREFLECT , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , HITTARGET , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , HITMASTER , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , HITTRACER , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , NODECAL , AActor , flags7 ) , // [ZK] Decal flags
DEFINE_FLAG ( MF7 , FORCEDECAL , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , LAXTELEFRAGDMG , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , ICESHATTER , AActor , flags7 ) ,
2016-04-23 15:16:37 +00:00
DEFINE_FLAG ( MF7 , ALLOWTHRUFLAGS , AActor , flags7 ) ,
2016-07-23 08:21:04 +00:00
DEFINE_FLAG ( MF7 , USEKILLSCRIPTS , AActor , flags7 ) ,
DEFINE_FLAG ( MF7 , NOKILLSCRIPTS , AActor , flags7 ) ,
2016-07-28 20:52:20 +00:00
DEFINE_FLAG ( MF7 , SPRITEANGLE , AActor , flags7 ) ,
2016-11-24 12:45:43 +00:00
DEFINE_FLAG ( MF7 , SMASHABLE , AActor , flags7 ) ,
2016-11-26 12:18:48 +00:00
DEFINE_FLAG ( MF7 , NOSHIELDREFLECT , AActor , flags7 ) ,
2017-02-19 22:20:09 +00:00
DEFINE_FLAG ( MF7 , FORCEZERORADIUSDMG , AActor , flags7 ) ,
2017-02-25 19:12:30 +00:00
DEFINE_FLAG ( MF7 , NOINFIGHTSPECIES , AActor , flags7 ) ,
2017-02-26 18:05:20 +00:00
DEFINE_FLAG ( MF7 , FORCEINFIGHTING , AActor , flags7 ) ,
2016-03-01 15:47:10 +00:00
2017-05-14 16:26:31 +00:00
DEFINE_FLAG ( MF8 , FRIGHTENING , AActor , flags8 ) ,
2018-06-03 19:11:47 +00:00
DEFINE_FLAG ( MF8 , BLOCKASPLAYER , AActor , flags8 ) ,
2018-07-22 09:32:45 +00:00
DEFINE_FLAG ( MF8 , DONTFACETALKER , AActor , flags8 ) ,
2018-08-17 17:03:50 +00:00
DEFINE_FLAG ( MF8 , HITOWNER , AActor , flags8 ) ,
2018-11-17 23:34:27 +00:00
DEFINE_FLAG ( MF8 , NOFRICTION , AActor , flags8 ) ,
DEFINE_FLAG ( MF8 , NOFRICTIONBOUNCE , AActor , flags8 ) ,
2017-05-14 16:26:31 +00:00
2016-03-01 15:47:10 +00:00
// Effect flags
DEFINE_FLAG ( FX , VISIBILITYPULSE , AActor , effects ) ,
DEFINE_FLAG2 ( FX_ROCKET , ROCKETTRAIL , AActor , effects ) ,
DEFINE_FLAG2 ( FX_GRENADE , GRENADETRAIL , AActor , effects ) ,
DEFINE_FLAG ( RF , INVISIBLE , AActor , renderflags ) ,
DEFINE_FLAG ( RF , FORCEYBILLBOARD , AActor , renderflags ) ,
DEFINE_FLAG ( RF , FORCEXYBILLBOARD , AActor , renderflags ) ,
2018-08-22 07:52:11 +00:00
DEFINE_FLAG ( RF , ROLLSPRITE , AActor , renderflags ) , // [marrub] roll the sprite billboard
2016-05-01 13:45:50 +00:00
// [fgsfds] Flat sprites
DEFINE_FLAG ( RF , FLATSPRITE , AActor , renderflags ) ,
DEFINE_FLAG ( RF , WALLSPRITE , AActor , renderflags ) ,
2016-06-05 20:21:19 +00:00
DEFINE_FLAG ( RF , DONTFLIP , AActor , renderflags ) ,
2016-07-04 18:58:49 +00:00
DEFINE_FLAG ( RF , ROLLCENTER , AActor , renderflags ) ,
2016-09-18 20:07:08 +00:00
DEFINE_FLAG ( RF , MASKROTATION , AActor , renderflags ) ,
DEFINE_FLAG ( RF , ABSMASKANGLE , AActor , renderflags ) ,
DEFINE_FLAG ( RF , ABSMASKPITCH , AActor , renderflags ) ,
2017-01-20 00:11:36 +00:00
DEFINE_FLAG ( RF , XFLIP , AActor , renderflags ) ,
DEFINE_FLAG ( RF , YFLIP , AActor , renderflags ) ,
2017-02-01 18:17:56 +00:00
DEFINE_FLAG ( RF , INTERPOLATEANGLES , AActor , renderflags ) ,
2017-02-26 19:01:39 +00:00
DEFINE_FLAG ( RF , DONTINTERPOLATE , AActor , renderflags ) ,
2017-06-01 17:13:30 +00:00
DEFINE_FLAG ( RF , SPRITEFLIP , AActor , renderflags ) ,
DEFINE_FLAG ( RF , ZDOOMTRANS , AActor , renderflags ) ,
2016-03-01 15:47:10 +00:00
// Bounce flags
DEFINE_FLAG2 ( BOUNCE_Walls , BOUNCEONWALLS , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_Floors , BOUNCEONFLOORS , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_Ceilings , BOUNCEONCEILINGS , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_Actors , ALLOWBOUNCEONACTORS , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_AutoOff , BOUNCEAUTOOFF , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_HereticType , BOUNCELIKEHERETIC , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_CanBounceWater , CANBOUNCEWATER , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_NoWallSound , NOWALLBOUNCESND , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_Quiet , NOBOUNCESOUND , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_AllActors , BOUNCEONACTORS , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_ExplodeOnWater , EXPLODEONWATER , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_MBF , MBFBOUNCER , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_AutoOffFloorOnly , BOUNCEAUTOOFFFLOORONLY , AActor , BounceFlags ) ,
DEFINE_FLAG2 ( BOUNCE_UseBounceState , USEBOUNCESTATE , AActor , BounceFlags ) ,
2017-02-26 21:31:43 +00:00
DEFINE_FLAG2 ( BOUNCE_NotOnShootables , DONTBOUNCEONSHOOTABLES , AActor , BounceFlags ) ,
2018-11-09 09:19:40 +00:00
DEFINE_FLAG2 ( BOUNCE_BounceOnUnrips , BOUNCEONUNRIPPABLES , AActor , BounceFlags ) ,
2018-11-30 10:22:34 +00:00
DEFINE_FLAG2 ( BOUNCE_NotOnSky , DONTBOUNCEONSKY , AActor , BounceFlags ) ,
2016-10-25 11:29:58 +00:00
} ;
// These won't be accessible through bitfield variables
static FFlagDef MoreFlagDefs [ ] =
{
2016-03-01 15:47:10 +00:00
// Deprecated flags. Handling must be performed in HandleDeprecatedFlags
DEFINE_DEPRECATED_FLAG ( FIREDAMAGE ) ,
DEFINE_DEPRECATED_FLAG ( ICEDAMAGE ) ,
DEFINE_DEPRECATED_FLAG ( LOWGRAVITY ) ,
DEFINE_DEPRECATED_FLAG ( SHORTMISSILERANGE ) ,
DEFINE_DEPRECATED_FLAG ( LONGMELEERANGE ) ,
DEFINE_DEPRECATED_FLAG ( QUARTERGRAVITY ) ,
DEFINE_DEPRECATED_FLAG ( FIRERESIST ) ,
DEFINE_DEPRECATED_FLAG ( HERETICBOUNCE ) ,
DEFINE_DEPRECATED_FLAG ( HEXENBOUNCE ) ,
DEFINE_DEPRECATED_FLAG ( DOOMBOUNCE ) ,
// Deprecated flags with no more existing functionality.
2016-10-24 15:18:20 +00:00
DEFINE_DUMMY_FLAG ( FASTER , true ) , // obsolete, replaced by 'Fast' state flag
DEFINE_DUMMY_FLAG ( FASTMELEE , true ) , // obsolete, replaced by 'Fast' state flag
2016-03-01 15:47:10 +00:00
2016-12-31 21:48:10 +00:00
// Deprecated name as an alias
DEFINE_FLAG2_DEPRECATED ( MF4_DONTHARMCLASS , DONTHURTSPECIES , AActor , flags4 ) ,
2016-03-01 15:47:10 +00:00
// Various Skulltag flags that are quite irrelevant to ZDoom
2016-12-31 21:48:10 +00:00
// [BC] New DECORATE flag defines here.
DEFINE_DUMMY_FLAG ( BLUETEAM , false ) ,
DEFINE_DUMMY_FLAG ( REDTEAM , false ) ,
DEFINE_DUMMY_FLAG ( USESPECIAL , false ) ,
DEFINE_DUMMY_FLAG ( BASEHEALTH , false ) ,
DEFINE_DUMMY_FLAG ( SUPERHEALTH , false ) ,
DEFINE_DUMMY_FLAG ( BASEARMOR , false ) ,
DEFINE_DUMMY_FLAG ( SUPERARMOR , false ) ,
DEFINE_DUMMY_FLAG ( SCOREPILLAR , false ) ,
DEFINE_DUMMY_FLAG ( NODE , false ) ,
DEFINE_DUMMY_FLAG ( USESTBOUNCESOUND , false ) ,
DEFINE_DUMMY_FLAG ( EXPLODEONDEATH , true ) ,
DEFINE_DUMMY_FLAG ( DONTIDENTIFYTARGET , false ) , // [CK]
// Skulltag netcode-based flags.
// [BB] New DECORATE network related flag defines here.
DEFINE_DUMMY_FLAG ( NONETID , false ) ,
DEFINE_DUMMY_FLAG ( ALLOWCLIENTSPAWN , false ) ,
DEFINE_DUMMY_FLAG ( CLIENTSIDEONLY , false ) ,
DEFINE_DUMMY_FLAG ( SERVERSIDEONLY , false ) ,
2016-03-01 15:47:10 +00:00
} ;
static FFlagDef PlayerPawnFlagDefs [ ] =
{
// PlayerPawn flags
DEFINE_FLAG ( PPF , NOTHRUSTWHENINVUL , APlayerPawn , PlayerFlags ) ,
DEFINE_FLAG ( PPF , CANSUPERMORPH , APlayerPawn , PlayerFlags ) ,
DEFINE_FLAG ( PPF , CROUCHABLEMORPH , APlayerPawn , PlayerFlags ) ,
} ;
2017-03-19 23:34:19 +00:00
static FFlagDef DynLightFlagDefs [ ] =
{
// PlayerPawn flags
2017-06-18 08:15:31 +00:00
DEFINE_FLAG ( LF , SUBTRACTIVE , ADynamicLight , lightflags ) ,
DEFINE_FLAG ( LF , ADDITIVE , ADynamicLight , lightflags ) ,
DEFINE_FLAG ( LF , DONTLIGHTSELF , ADynamicLight , lightflags ) ,
DEFINE_FLAG ( LF , ATTENUATE , ADynamicLight , lightflags ) ,
DEFINE_FLAG ( LF , NOSHADOWMAP , ADynamicLight , lightflags ) ,
DEFINE_FLAG ( LF , DONTLIGHTACTORS , ADynamicLight , lightflags ) ,
2018-01-04 16:58:11 +00:00
DEFINE_FLAG ( LF , SPOT , ADynamicLight , lightflags ) ,
2017-03-19 23:34:19 +00:00
} ;
2016-11-22 22:42:32 +00:00
static const struct FFlagList { const PClass * const * Type ; FFlagDef * Defs ; int NumDefs ; int Use ; } FlagLists [ ] =
2016-03-01 15:47:10 +00:00
{
2016-11-22 22:42:32 +00:00
{ & RUNTIME_CLASS_CASTLESS ( AActor ) , ActorFlagDefs , countof ( ActorFlagDefs ) , 3 } , // -1 to account for the terminator
{ & RUNTIME_CLASS_CASTLESS ( AActor ) , MoreFlagDefs , countof ( MoreFlagDefs ) , 1 } ,
{ & RUNTIME_CLASS_CASTLESS ( AActor ) , InternalActorFlagDefs , countof ( InternalActorFlagDefs ) , 2 } ,
{ & RUNTIME_CLASS_CASTLESS ( APlayerPawn ) , PlayerPawnFlagDefs , countof ( PlayerPawnFlagDefs ) , 3 } ,
2017-04-12 20:46:49 +00:00
{ & RUNTIME_CLASS_CASTLESS ( ADynamicLight ) , DynLightFlagDefs , countof ( DynLightFlagDefs ) , 3 } ,
2016-03-01 15:47:10 +00:00
} ;
# define NUM_FLAG_LISTS (countof(FlagLists))
2018-11-25 08:29:12 +00:00
static FFlagDef forInternalFlags ;
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Find a flag by name using a binary search
//
//==========================================================================
static FFlagDef * FindFlag ( FFlagDef * flags , int numflags , const char * flag )
{
int min = 0 , max = numflags - 1 ;
while ( min < = max )
{
int mid = ( min + max ) / 2 ;
int lexval = stricmp ( flag , flags [ mid ] . name ) ;
if ( lexval = = 0 )
{
return & flags [ mid ] ;
}
else if ( lexval > 0 )
{
min = mid + 1 ;
}
else
{
max = mid - 1 ;
}
}
return NULL ;
}
//==========================================================================
//
// Finds a flag that may have a qualified name
//
//==========================================================================
2016-10-10 22:56:47 +00:00
FFlagDef * FindFlag ( const PClass * type , const char * part1 , const char * part2 , bool strict )
2016-03-01 15:47:10 +00:00
{
2018-11-25 08:29:12 +00:00
if ( part2 = = nullptr )
{
FStringf internalname ( " @flagdef@%s " , part1 ) ;
FName name ( internalname , true ) ;
if ( name ! = NAME_None )
{
auto field = dyn_cast < PPropFlag > ( type - > FindSymbol ( name , true ) ) ;
if ( field ! = nullptr & & ( ! strict | | ! field - > decorateOnly ) )
{
forInternalFlags . fieldsize = 4 ;
forInternalFlags . name = " " ;
2018-12-04 17:06:09 +00:00
forInternalFlags . flagbit = field - > Offset ? 1 < < field - > bitval : field - > bitval ;
2018-11-25 09:06:00 +00:00
forInternalFlags . structoffset = field - > Offset ? ( int ) field - > Offset - > Offset : - 1 ;
2018-12-04 17:06:09 +00:00
forInternalFlags . varflags = field - > Offset = = nullptr & & field - > bitval > 0 ? VARF_Deprecated : 0 ;
2018-11-25 08:29:12 +00:00
return & forInternalFlags ;
}
}
}
else
{
FStringf internalname ( " @flagdef@%s.%s " , part1 , part2 ) ;
FName name ( internalname , true ) ;
if ( name ! = NAME_None )
{
auto field = dyn_cast < PPropFlag > ( type - > FindSymbol ( name , true ) ) ;
if ( field ! = nullptr )
{
forInternalFlags . fieldsize = 4 ;
forInternalFlags . name = " " ;
2018-12-04 17:06:09 +00:00
forInternalFlags . flagbit = field - > Offset ? 1 < < field - > bitval : field - > bitval ;
2018-11-25 09:06:00 +00:00
forInternalFlags . structoffset = field - > Offset ? ( int ) field - > Offset - > Offset : - 1 ;
2018-12-04 17:06:09 +00:00
forInternalFlags . varflags = field - > Offset = = nullptr & & field - > bitval > 0 ? VARF_Deprecated : 0 ;
2018-11-25 08:29:12 +00:00
return & forInternalFlags ;
}
}
}
// Not found. Try the internal flag definitions.
2016-03-01 15:47:10 +00:00
FFlagDef * def ;
if ( part2 = = NULL )
{ // Search all lists
2016-10-24 15:18:20 +00:00
int max = strict ? 2 : NUM_FLAG_LISTS ;
2016-10-27 22:32:52 +00:00
for ( int i = 0 ; i < max ; + + i )
2016-03-01 15:47:10 +00:00
{
2016-11-22 22:42:32 +00:00
if ( ( FlagLists [ i ] . Use & 1 ) & & type - > IsDescendantOf ( * FlagLists [ i ] . Type ) )
2016-03-01 15:47:10 +00:00
{
def = FindFlag ( FlagLists [ i ] . Defs , FlagLists [ i ] . NumDefs , part1 ) ;
if ( def ! = NULL )
{
return def ;
}
}
}
}
else
{ // Search just the named list
2016-10-27 22:32:52 +00:00
for ( size_t i = 0 ; i < NUM_FLAG_LISTS ; + + i )
2016-03-01 15:47:10 +00:00
{
if ( stricmp ( ( * FlagLists [ i ] . Type ) - > TypeName . GetChars ( ) , part1 ) = = 0 )
{
if ( type - > IsDescendantOf ( * FlagLists [ i ] . Type ) )
{
return FindFlag ( FlagLists [ i ] . Defs , FlagLists [ i ] . NumDefs , part2 ) ;
}
else
{
return NULL ;
}
}
}
}
2017-01-17 00:50:31 +00:00
2016-03-01 15:47:10 +00:00
return NULL ;
}
//==========================================================================
//
2018-08-22 07:52:11 +00:00
// Gets the name of an actor flag
2016-03-01 15:47:10 +00:00
//
//==========================================================================
const char * GetFlagName ( unsigned int flagnum , int flagoffset )
{
for ( size_t i = 0 ; i < countof ( ActorFlagDefs ) ; i + + )
{
if ( ActorFlagDefs [ i ] . flagbit = = flagnum & & ActorFlagDefs [ i ] . structoffset = = flagoffset )
{
return ActorFlagDefs [ i ] . name ;
}
}
return " (unknown) " ; // return something printable
}
//==========================================================================
//
// Find a property by name using a binary search
//
//==========================================================================
FPropertyInfo * FindProperty ( const char * string )
{
int min = 0 , max = properties . Size ( ) - 1 ;
while ( min < = max )
{
int mid = ( min + max ) / 2 ;
int lexval = stricmp ( string , properties [ mid ] - > name ) ;
if ( lexval = = 0 )
{
return properties [ mid ] ;
}
else if ( lexval > 0 )
{
min = mid + 1 ;
}
else
{
max = mid - 1 ;
}
}
return NULL ;
}
2017-03-14 12:40:20 +00:00
//==========================================================================
//
//
//
//==========================================================================
template < typename Desc >
static int CompareClassNames ( const char * const aname , const Desc & b )
{
// ++ to get past the prefix letter of the native class name, which gets omitted by the FName for the class.
const char * bname = b . ClassName ;
if ( ' \0 ' ! = * bname ) + + bname ;
return stricmp ( aname , bname ) ;
}
template < typename Desc >
static int CompareClassNames ( const Desc & a , const Desc & b )
{
// ++ to get past the prefix letter of the native class name, which gets omitted by the FName for the class.
const char * aname = a . ClassName ;
if ( ' \0 ' ! = * aname ) + + aname ;
return CompareClassNames ( aname , b ) ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Find a function by name using a binary search
//
//==========================================================================
2017-04-12 15:21:13 +00:00
AFuncDesc * FindFunction ( PContainerType * cls , const char * string )
2016-03-01 15:47:10 +00:00
{
2016-12-02 17:52:58 +00:00
int min = 0 , max = AFTable . Size ( ) - 1 ;
while ( min < = max )
2016-03-01 15:47:10 +00:00
{
2016-12-02 17:52:58 +00:00
int mid = ( min + max ) / 2 ;
2017-03-14 12:40:20 +00:00
int lexval = CompareClassNames ( cls - > TypeName . GetChars ( ) , AFTable [ mid ] ) ;
2016-12-02 17:52:58 +00:00
if ( lexval = = 0 ) lexval = stricmp ( string , AFTable [ mid ] . FuncName ) ;
if ( lexval = = 0 )
2016-11-21 18:09:58 +00:00
{
2016-12-02 17:52:58 +00:00
return & AFTable [ mid ] ;
2016-11-21 18:09:58 +00:00
}
2016-12-02 17:52:58 +00:00
else if ( lexval > 0 )
2016-03-01 15:47:10 +00:00
{
2016-12-02 17:52:58 +00:00
min = mid + 1 ;
}
else
{
max = mid - 1 ;
2016-03-01 15:47:10 +00:00
}
}
2016-11-16 00:36:21 +00:00
return nullptr ;
2016-03-01 15:47:10 +00:00
}
2016-11-22 18:20:31 +00:00
//==========================================================================
//
// Find a function by name using a binary search
//
//==========================================================================
2017-04-12 15:21:13 +00:00
FieldDesc * FindField ( PContainerType * cls , const char * string )
2016-11-22 18:20:31 +00:00
{
int min = 0 , max = FieldTable . Size ( ) - 1 ;
2017-03-13 13:42:14 +00:00
const char * cname = cls ? cls - > TypeName . GetChars ( ) : " " ;
2016-11-22 18:20:31 +00:00
while ( min < = max )
{
int mid = ( min + max ) / 2 ;
2017-03-14 12:40:20 +00:00
int lexval = CompareClassNames ( cname , FieldTable [ mid ] ) ;
2016-11-22 18:20:31 +00:00
if ( lexval = = 0 ) lexval = stricmp ( string , FieldTable [ mid ] . FieldName ) ;
if ( lexval = = 0 )
{
return & FieldTable [ mid ] ;
}
else if ( lexval > 0 )
{
min = mid + 1 ;
}
else
{
max = mid - 1 ;
}
}
return nullptr ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Find an action function in AActor's table
//
//==========================================================================
2016-11-06 10:36:12 +00:00
VMFunction * FindVMFunction ( PClass * cls , const char * name )
2016-03-01 15:47:10 +00:00
{
2017-04-12 11:08:41 +00:00
auto f = dyn_cast < PFunction > ( cls - > FindSymbol ( name , true ) ) ;
2016-11-06 10:36:12 +00:00
return f = = nullptr ? nullptr : f - > Variants [ 0 ] . Implementation ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
// Sorting helpers
//
//==========================================================================
2016-04-11 08:46:30 +00:00
static int flagcmp ( const void * a , const void * b )
2016-03-01 15:47:10 +00:00
{
return stricmp ( ( ( FFlagDef * ) a ) - > name , ( ( FFlagDef * ) b ) - > name ) ;
}
2016-04-11 08:46:30 +00:00
static int propcmp ( const void * a , const void * b )
2016-03-01 15:47:10 +00:00
{
return stricmp ( ( * ( FPropertyInfo * * ) a ) - > name , ( * ( FPropertyInfo * * ) b ) - > name ) ;
}
2016-04-11 08:46:30 +00:00
static int funccmp ( const void * a , const void * b )
2016-03-01 15:47:10 +00:00
{
2017-03-14 12:40:20 +00:00
int res = CompareClassNames ( * ( AFuncDesc * ) a , * ( AFuncDesc * ) b ) ;
2016-11-21 18:09:58 +00:00
if ( res = = 0 ) res = stricmp ( ( ( AFuncDesc * ) a ) - > FuncName , ( ( AFuncDesc * ) b ) - > FuncName ) ;
return res ;
2016-03-01 15:47:10 +00:00
}
2016-11-22 18:20:31 +00:00
static int fieldcmp ( const void * a , const void * b )
{
2017-03-14 12:40:20 +00:00
int res = CompareClassNames ( * ( FieldDesc * ) a , * ( FieldDesc * ) b ) ;
2016-11-22 18:20:31 +00:00
if ( res = = 0 ) res = stricmp ( ( ( FieldDesc * ) a ) - > FieldName , ( ( FieldDesc * ) b ) - > FieldName ) ;
return res ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Initialization
//
//==========================================================================
void InitThingdef ( )
{
2017-03-13 13:42:14 +00:00
// Some native types need size and serialization information added before the scripts get compiled.
2017-04-12 13:12:41 +00:00
auto secplanestruct = NewStruct ( " Secplane " , nullptr , true ) ;
2017-01-07 20:29:43 +00:00
secplanestruct - > Size = sizeof ( secplane_t ) ;
secplanestruct - > Align = alignof ( secplane_t ) ;
2017-01-08 13:39:16 +00:00
2017-04-12 13:12:41 +00:00
auto sectorstruct = NewStruct ( " Sector " , nullptr , true ) ;
2017-01-07 20:29:43 +00:00
sectorstruct - > Size = sizeof ( sector_t ) ;
sectorstruct - > Align = alignof ( sector_t ) ;
2017-03-03 19:11:13 +00:00
NewPointer ( sectorstruct , false ) - > InstallHandlers (
[ ] ( FSerializer & ar , const char * key , const void * addr )
{
ar ( key , * ( sector_t * * ) addr ) ;
} ,
[ ] ( FSerializer & ar , const char * key , void * addr )
{
Serialize < sector_t > ( ar , key , * ( sector_t * * ) addr , nullptr ) ;
return true ;
}
) ;
2017-01-07 20:29:43 +00:00
2017-04-12 13:12:41 +00:00
auto linestruct = NewStruct ( " Line " , nullptr , true ) ;
2017-01-08 13:39:16 +00:00
linestruct - > Size = sizeof ( line_t ) ;
linestruct - > Align = alignof ( line_t ) ;
2017-03-03 19:11:13 +00:00
NewPointer ( linestruct , false ) - > InstallHandlers (
[ ] ( FSerializer & ar , const char * key , const void * addr )
{
ar ( key , * ( line_t * * ) addr ) ;
} ,
[ ] ( FSerializer & ar , const char * key , void * addr )
{
Serialize < line_t > ( ar , key , * ( line_t * * ) addr , nullptr ) ;
return true ;
}
) ;
2017-01-08 13:39:16 +00:00
2017-04-12 13:12:41 +00:00
auto sidestruct = NewStruct ( " Side " , nullptr , true ) ;
2017-01-08 20:42:26 +00:00
sidestruct - > Size = sizeof ( side_t ) ;
sidestruct - > Align = alignof ( side_t ) ;
2017-03-03 19:11:13 +00:00
NewPointer ( sidestruct , false ) - > InstallHandlers (
[ ] ( FSerializer & ar , const char * key , const void * addr )
{
ar ( key , * ( side_t * * ) addr ) ;
} ,
[ ] ( FSerializer & ar , const char * key , void * addr )
{
Serialize < side_t > ( ar , key , * ( side_t * * ) addr , nullptr ) ;
return true ;
}
) ;
2017-01-08 20:42:26 +00:00
2017-04-12 13:12:41 +00:00
auto vertstruct = NewStruct ( " Vertex " , nullptr , true ) ;
2017-01-08 23:46:16 +00:00
vertstruct - > Size = sizeof ( vertex_t ) ;
vertstruct - > Align = alignof ( vertex_t ) ;
2017-03-03 19:11:13 +00:00
NewPointer ( vertstruct , false ) - > InstallHandlers (
[ ] ( FSerializer & ar , const char * key , const void * addr )
{
ar ( key , * ( vertex_t * * ) addr ) ;
} ,
[ ] ( FSerializer & ar , const char * key , void * addr )
{
Serialize < vertex_t > ( ar , key , * ( vertex_t * * ) addr , nullptr ) ;
return true ;
}
) ;
2017-01-08 23:46:16 +00:00
2017-04-12 13:12:41 +00:00
auto sectorportalstruct = NewStruct ( " SectorPortal " , nullptr , true ) ;
2017-01-14 15:05:40 +00:00
sectorportalstruct - > Size = sizeof ( FSectorPortal ) ;
sectorportalstruct - > Align = alignof ( FSectorPortal ) ;
2017-01-07 20:29:43 +00:00
2017-04-12 13:12:41 +00:00
auto playerclassstruct = NewStruct ( " PlayerClass " , nullptr , true ) ;
2017-02-11 15:11:48 +00:00
playerclassstruct - > Size = sizeof ( FPlayerClass ) ;
playerclassstruct - > Align = alignof ( FPlayerClass ) ;
2017-04-12 13:12:41 +00:00
auto playerskinstruct = NewStruct ( " PlayerSkin " , nullptr , true ) ;
2017-02-17 20:51:23 +00:00
playerskinstruct - > Size = sizeof ( FPlayerSkin ) ;
playerskinstruct - > Align = alignof ( FPlayerSkin ) ;
2017-04-12 13:12:41 +00:00
auto teamstruct = NewStruct ( " Team " , nullptr , true ) ;
2017-02-18 00:20:07 +00:00
teamstruct - > Size = sizeof ( FTeam ) ;
teamstruct - > Align = alignof ( FTeam ) ;
2017-04-12 13:12:41 +00:00
PStruct * pstruct = NewStruct ( " PlayerInfo " , nullptr , true ) ;
2017-03-03 19:11:13 +00:00
pstruct - > Size = sizeof ( player_t ) ;
pstruct - > Align = alignof ( player_t ) ;
NewPointer ( pstruct , false ) - > InstallHandlers (
[ ] ( FSerializer & ar , const char * key , const void * addr )
{
ar ( key , * ( player_t * * ) addr ) ;
} ,
[ ] ( FSerializer & ar , const char * key , void * addr )
{
Serialize < player_t > ( ar , key , * ( player_t * * ) addr , nullptr ) ;
return true ;
}
) ;
2017-04-12 13:12:41 +00:00
auto fontstruct = NewStruct ( " FFont " , nullptr , true ) ;
2017-03-03 19:11:13 +00:00
fontstruct - > Size = sizeof ( FFont ) ;
fontstruct - > Align = alignof ( FFont ) ;
NewPointer ( fontstruct , false ) - > InstallHandlers (
[ ] ( FSerializer & ar , const char * key , const void * addr )
{
ar ( key , * ( FFont * * ) addr ) ;
} ,
[ ] ( FSerializer & ar , const char * key , void * addr )
{
Serialize < FFont > ( ar , key , * ( FFont * * ) addr , nullptr ) ;
return true ;
}
) ;
2017-04-12 13:12:41 +00:00
auto wbplayerstruct = NewStruct ( " WBPlayerStruct " , nullptr , true ) ;
2017-03-18 18:34:03 +00:00
wbplayerstruct - > Size = sizeof ( wbplayerstruct_t ) ;
wbplayerstruct - > Align = alignof ( wbplayerstruct_t ) ;
2016-11-22 22:42:32 +00:00
2016-11-19 08:24:54 +00:00
FAutoSegIterator probe ( CRegHead , CRegTail ) ;
while ( * + + probe ! = NULL )
{
if ( ( ( ClassReg * ) * probe ) - > InitNatives )
( ( ClassReg * ) * probe ) - > InitNatives ( ) ;
}
2016-03-01 15:47:10 +00:00
// Sort the flag lists
for ( size_t i = 0 ; i < NUM_FLAG_LISTS ; + + i )
{
qsort ( FlagLists [ i ] . Defs , FlagLists [ i ] . NumDefs , sizeof ( FFlagDef ) , flagcmp ) ;
}
// Create a sorted list of properties
if ( properties . Size ( ) = = 0 )
{
FAutoSegIterator probe ( GRegHead , GRegTail ) ;
while ( * + + probe ! = NULL )
{
properties . Push ( ( FPropertyInfo * ) * probe ) ;
}
properties . ShrinkToFit ( ) ;
qsort ( & properties [ 0 ] , properties . Size ( ) , sizeof ( properties [ 0 ] ) , propcmp ) ;
}
// Create a sorted list of native action functions
AFTable . Clear ( ) ;
if ( AFTable . Size ( ) = = 0 )
{
FAutoSegIterator probe ( ARegHead , ARegTail ) ;
while ( * + + probe ! = NULL )
{
AFuncDesc * afunc = ( AFuncDesc * ) * probe ;
assert ( afunc - > VMPointer ! = NULL ) ;
2016-11-21 18:09:58 +00:00
* ( afunc - > VMPointer ) = new VMNativeFunction ( afunc - > Function , afunc - > FuncName ) ;
( * ( afunc - > VMPointer ) ) - > PrintableName . Format ( " %s.%s [Native] " , afunc - > ClassName + 1 , afunc - > FuncName ) ;
2018-11-25 10:41:29 +00:00
( * ( afunc - > VMPointer ) ) - > DirectNativeCall = afunc - > DirectNative ;
2016-03-01 15:47:10 +00:00
AFTable . Push ( * afunc ) ;
}
AFTable . ShrinkToFit ( ) ;
qsort ( & AFTable [ 0 ] , AFTable . Size ( ) , sizeof ( AFTable [ 0 ] ) , funccmp ) ;
}
2016-11-22 18:20:31 +00:00
2017-01-11 22:46:03 +00:00
// Add the constructor and destructor to FCheckPosition.
auto fcp = NewStruct ( " FCheckPosition " , nullptr ) ;
fcp - > mConstructor = * FindFunction ( fcp , " _Constructor " ) - > VMPointer ;
fcp - > mDestructor = * FindFunction ( fcp , " _Destructor " ) - > VMPointer ;
2018-11-18 16:10:55 +00:00
static const uint8_t reguse [ ] = { REGT_POINTER } ;
fcp - > mConstructor - > RegTypes = fcp - > mDestructor - > RegTypes = reguse ;
2017-01-11 22:46:03 +00:00
fcp - > Size = sizeof ( FCheckPosition ) ;
fcp - > Align = alignof ( FCheckPosition ) ;
2018-11-24 14:12:30 +00:00
//This must also have its size set.
auto frp = NewStruct ( " FRailParams " , nullptr ) ;
frp - > Size = sizeof ( FRailParams ) ;
frp - > Align = alignof ( FRailParams ) ;
2017-01-11 22:46:03 +00:00
2016-11-22 18:20:31 +00:00
FieldTable . Clear ( ) ;
if ( FieldTable . Size ( ) = = 0 )
{
FAutoSegIterator probe ( FRegHead , FRegTail ) ;
while ( * + + probe ! = NULL )
{
FieldDesc * afield = ( FieldDesc * ) * probe ;
FieldTable . Push ( * afield ) ;
}
FieldTable . ShrinkToFit ( ) ;
qsort ( & FieldTable [ 0 ] , FieldTable . Size ( ) , sizeof ( FieldTable [ 0 ] ) , fieldcmp ) ;
}
2016-03-01 15:47:10 +00:00
}
2016-11-26 00:14:47 +00:00
2017-04-12 20:46:49 +00:00
void SynthesizeFlagFields ( )
{
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
for ( auto & fl : FlagLists )
{
auto cls = const_cast < PClass * > ( * fl . Type ) ;
if ( fl . Use & 2 )
{
for ( int i = 0 ; i < fl . NumDefs ; i + + )
{
if ( fl . Defs [ i ] . structoffset > 0 ) // skip the deprecated entries in this list
{
cls - > VMType - > AddNativeField ( FStringf ( " b%s " , fl . Defs [ i ] . name ) , ( fl . Defs [ i ] . fieldsize = = 4 ? TypeSInt32 : TypeSInt16 ) , fl . Defs [ i ] . structoffset , fl . Defs [ i ] . varflags , fl . Defs [ i ] . flagbit ) ;
}
}
}
}
}
2016-11-28 17:15:18 +00:00
2016-11-29 16:17:10 +00:00
DEFINE_ACTION_FUNCTION ( DObject , BAM )
{
PARAM_PROLOGUE ;
PARAM_FLOAT ( ang ) ;
ACTION_RETURN_INT ( DAngle ( ang ) . BAMs ( ) ) ;
}
2018-11-18 18:31:13 +00:00
FString FStringFormat ( VM_ARGS , int offset )
2017-01-21 00:07:44 +00:00
{
2018-11-18 18:31:13 +00:00
PARAM_VA_POINTER ( va_reginfo ) // Get the hidden type information array
assert ( va_reginfo [ offset ] = = REGT_STRING ) ;
FString fmtstring = param [ offset ] . s ( ) . GetChars ( ) ;
param + = offset ;
numparam - = offset ;
va_reginfo + = offset ;
2017-01-21 00:07:44 +00:00
// note: we don't need a real printf format parser.
// enough to simply find the subtitution tokens and feed them to the real printf after checking types.
// https://en.wikipedia.org/wiki/Printf_format_string#Format_placeholder_specification
FString output ;
bool in_fmt = false ;
FString fmt_current ;
int argnum = 1 ;
int argauto = 1 ;
// % = starts
// [0-9], -, +, \s, 0, #, . continue
// %, s, d, i, u, fF, eE, gG, xX, o, c, p, aA terminate
// various type flags are not supported. not like stuff like 'hh' modifier is to be used in the VM.
// the only combination that is parsed locally is %n$...
bool haveargnums = false ;
for ( size_t i = 0 ; i < fmtstring . Len ( ) ; i + + )
{
char c = fmtstring [ i ] ;
if ( in_fmt )
{
2018-12-02 08:31:26 +00:00
if ( c = = ' * ' & & ( fmt_current . Len ( ) = = 1 | | ( fmt_current . Len ( ) = = 2 & & fmt_current [ 1 ] = = ' 0 ' ) ) )
{
fmt_current + = c ;
}
else if ( ( c > = ' 0 ' & & c < = ' 9 ' ) | |
2017-10-23 08:55:20 +00:00
c = = ' - ' | | c = = ' + ' | | ( c = = ' ' & & fmt_current . Back ( ) ! = ' ' ) | | c = = ' # ' | | c = = ' . ' )
2017-01-21 00:07:44 +00:00
{
fmt_current + = c ;
}
else if ( c = = ' $ ' ) // %number$format
{
if ( ! haveargnums & & argauto > 1 )
ThrowAbortException ( X_FORMAT_ERROR , " Cannot mix explicit and implicit arguments. " ) ;
FString argnumstr = fmt_current . Mid ( 1 ) ;
if ( ! argnumstr . IsInt ( ) ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for argument number, got '%s'. " , argnumstr . GetChars ( ) ) ;
argnum = argnumstr . ToLong ( ) ;
if ( argnum < 1 | | argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format (tried to access argument %d, %d total). " , argnum , numparam ) ;
fmt_current = " % " ;
haveargnums = true ;
}
else
{
fmt_current + = c ;
switch ( c )
{
// string
case ' s ' :
{
if ( argnum < 0 & & haveargnums )
ThrowAbortException ( X_FORMAT_ERROR , " Cannot mix explicit and implicit arguments. " ) ;
in_fmt = false ;
// fail if something was found, but it's not a string
if ( argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
2018-11-18 18:31:13 +00:00
if ( va_reginfo [ argnum ] ! = REGT_STRING ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a string for format %s. " , fmt_current . GetChars ( ) ) ;
2017-01-21 00:07:44 +00:00
// append
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . s ( ) . GetChars ( ) ) ;
if ( ! haveargnums ) argnum = + + argauto ;
else argnum = - 1 ;
break ;
}
// pointer
case ' p ' :
{
if ( argnum < 0 & & haveargnums )
ThrowAbortException ( X_FORMAT_ERROR , " Cannot mix explicit and implicit arguments. " ) ;
in_fmt = false ;
// fail if something was found, but it's not a string
if ( argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
2018-11-18 18:31:13 +00:00
if ( va_reginfo [ argnum ] ! = REGT_POINTER ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a pointer for format %s. " , fmt_current . GetChars ( ) ) ;
2017-01-21 00:07:44 +00:00
// append
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . a ) ;
if ( ! haveargnums ) argnum = + + argauto ;
else argnum = - 1 ;
break ;
}
// int formats (including char)
case ' d ' :
case ' i ' :
case ' u ' :
case ' x ' :
case ' X ' :
case ' o ' :
case ' c ' :
2018-12-02 08:31:26 +00:00
case ' B ' :
2017-01-21 00:07:44 +00:00
{
if ( argnum < 0 & & haveargnums )
ThrowAbortException ( X_FORMAT_ERROR , " Cannot mix explicit and implicit arguments. " ) ;
in_fmt = false ;
// append
2018-12-02 08:31:26 +00:00
if ( fmt_current [ 1 ] = = ' * ' | | fmt_current [ 2 ] = = ' * ' )
{
// fail if something was found, but it's not an int
if ( argnum + 1 > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
if ( va_reginfo [ argnum ] ! = REGT_INT & &
va_reginfo [ argnum ] ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
if ( va_reginfo [ argnum + 1 ] ! = REGT_INT & &
va_reginfo [ argnum + 1 ] ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . ToInt ( va_reginfo [ argnum ] ) , param [ argnum + 1 ] . ToInt ( va_reginfo [ argnum + 1 ] ) ) ;
argauto + + ;
}
else
{
// fail if something was found, but it's not an int
if ( argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
if ( va_reginfo [ argnum ] ! = REGT_INT & &
va_reginfo [ argnum ] ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . ToInt ( va_reginfo [ argnum ] ) ) ;
}
2017-01-21 00:07:44 +00:00
if ( ! haveargnums ) argnum = + + argauto ;
else argnum = - 1 ;
break ;
}
// double formats
case ' f ' :
case ' F ' :
case ' e ' :
case ' E ' :
case ' g ' :
case ' G ' :
case ' a ' :
case ' A ' :
{
if ( argnum < 0 & & haveargnums )
ThrowAbortException ( X_FORMAT_ERROR , " Cannot mix explicit and implicit arguments. " ) ;
in_fmt = false ;
2018-12-02 08:31:26 +00:00
if ( fmt_current [ 1 ] = = ' * ' | | fmt_current [ 2 ] = = ' * ' )
{
// fail if something was found, but it's not an int
if ( argnum + 1 > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
if ( va_reginfo [ argnum ] ! = REGT_INT & &
va_reginfo [ argnum ] ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
if ( va_reginfo [ argnum + 1 ] ! = REGT_INT & &
va_reginfo [ argnum + 1 ] ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . ToInt ( va_reginfo [ argnum ] ) , param [ argnum + 1 ] . ToDouble ( va_reginfo [ argnum + 1 ] ) ) ;
argauto + + ;
}
else
{
// fail if something was found, but it's not a float
if ( argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
if ( va_reginfo [ argnum ] ! = REGT_INT & &
va_reginfo [ argnum ] ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
// append
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . ToDouble ( va_reginfo [ argnum ] ) ) ;
}
2017-01-21 00:07:44 +00:00
if ( ! haveargnums ) argnum = + + argauto ;
else argnum = - 1 ;
break ;
}
default :
// invalid character
output + = fmt_current ;
in_fmt = false ;
break ;
}
}
}
else
{
if ( c = = ' % ' )
{
if ( i + 1 < fmtstring . Len ( ) & & fmtstring [ i + 1 ] = = ' % ' )
{
output + = ' % ' ;
i + + ;
}
else
{
in_fmt = true ;
fmt_current = " % " ;
}
}
else
{
output + = c ;
}
}
}
return output ;
}
2017-01-23 18:09:36 +00:00
DEFINE_ACTION_FUNCTION ( FStringStruct , Format )
2017-01-21 00:07:44 +00:00
{
PARAM_PROLOGUE ;
2018-11-18 18:31:13 +00:00
FString s = FStringFormat ( VM_ARGS_NAMES ) ;
2017-01-21 00:07:44 +00:00
ACTION_RETURN_STRING ( s ) ;
}
2017-01-23 18:09:36 +00:00
DEFINE_ACTION_FUNCTION ( FStringStruct , AppendFormat )
2017-01-21 00:07:44 +00:00
{
PARAM_SELF_STRUCT_PROLOGUE ( FString ) ;
// first parameter is the self pointer
2018-11-18 18:31:13 +00:00
FString s = FStringFormat ( VM_ARGS_NAMES , 1 ) ;
2017-01-21 00:07:44 +00:00
( * self ) + = s ;
return 0 ;
2017-02-06 11:18:10 +00:00
}