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"
# include "autosegs.h"
2016-11-27 17:52:24 +00:00
# include "p_maputl.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"
# include "zstring.h"
2016-11-29 11:17:05 +00:00
# include "d_event.h"
2017-01-08 17:45:30 +00:00
# include "g_levellocals.h"
2017-01-11 22:46:03 +00:00
# include "vm.h"
# include "p_checkposition.h"
2017-01-12 23:35:56 +00:00
# include "r_sky.h"
2017-02-03 23:46:22 +00:00
# include "v_font.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 ;
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 ) ,
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 ) ,
2016-05-01 13:45:50 +00:00
DEFINE_FLAG ( RF , ROLLSPRITE , AActor , renderflags ) , // [marrub] roll the sprite billboard
// [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 ) ,
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 ) ,
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 InventoryFlagDefs [ ] =
{
// Inventory flags
DEFINE_FLAG ( IF , QUIET , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , AUTOACTIVATE , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , UNDROPPABLE , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , INVBAR , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , HUBPOWER , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , UNTOSSABLE , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , ADDITIVETIME , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , ALWAYSPICKUP , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , FANCYPICKUPSOUND , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , BIGPOWERUP , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , KEEPDEPLETED , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , IGNORESKILL , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , NOATTENPICKUPSOUND , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , PERSISTENTPOWER , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , RESTRICTABSOLUTELY , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , NEVERRESPAWN , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , NOSCREENFLASH , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , TOSSED , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , ALWAYSRESPAWN , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , TRANSFER , AInventory , ItemFlags ) ,
DEFINE_FLAG ( IF , NOTELEPORTFREEZE , AInventory , ItemFlags ) ,
2017-01-10 18:57:51 +00:00
DEFINE_FLAG ( IF , NOSCREENBLINK , AInventory , ItemFlags ) ,
2016-03-01 15:47:10 +00:00
2016-12-31 21:48:10 +00:00
DEFINE_DUMMY_FLAG ( FORCERESPAWNINSURVIVAL , false ) ,
2016-03-01 15:47:10 +00:00
DEFINE_DEPRECATED_FLAG ( PICKUPFLASH ) ,
DEFINE_DEPRECATED_FLAG ( INTERHUBSTRIP ) ,
} ;
2016-11-22 22:42:32 +00:00
static FFlagDef WeaponFlagDefs [ ] =
2016-03-01 15:47:10 +00:00
{
// Weapon flags
DEFINE_FLAG ( WIF , NOAUTOFIRE , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , READYSNDHALF , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , DONTBOB , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , AXEBLOOD , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , NOALERT , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , AMMO_OPTIONAL , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , ALT_AMMO_OPTIONAL , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , PRIMARY_USES_BOTH , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , WIMPY_WEAPON , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , POWERED_UP , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , STAFF2_KICKBACK , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF_BOT , EXPLOSIVE , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , MELEEWEAPON , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF_BOT , BFG , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , CHEATNOTWEAPON , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , NO_AUTO_SWITCH , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , AMMO_CHECKBOTH , AWeapon , WeaponFlags ) ,
DEFINE_FLAG ( WIF , NOAUTOAIM , AWeapon , WeaponFlags ) ,
2016-07-22 14:37:32 +00:00
DEFINE_FLAG ( WIF , NODEATHDESELECT , AWeapon , WeaponFlags ) ,
2016-07-01 21:43:30 +00:00
DEFINE_FLAG ( WIF , NODEATHINPUT , AWeapon , WeaponFlags ) ,
2016-03-01 15:47:10 +00:00
DEFINE_FLAG ( WIF , ALT_USES_BOTH , AWeapon , WeaponFlags ) ,
2016-11-19 00:23:56 +00:00
DEFINE_DUMMY_FLAG ( NOLMS , false ) ,
2016-10-24 15:18:20 +00:00
DEFINE_DUMMY_FLAG ( ALLOW_WITH_RESPAWN_INVUL , false ) ,
2016-03-01 15:47:10 +00:00
} ;
2016-11-19 00:23:56 +00:00
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 ) ,
} ;
static FFlagDef PowerSpeedFlagDefs [ ] =
{
// PowerSpeed flags
2017-01-17 00:50:31 +00:00
DEFINE_DEPRECATED_FLAG ( NOTRAIL ) ,
2016-03-01 15:47:10 +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 ( AInventory ) , InventoryFlagDefs , countof ( InventoryFlagDefs ) , 3 } ,
{ & RUNTIME_CLASS_CASTLESS ( AWeapon ) , WeaponFlagDefs , countof ( WeaponFlagDefs ) , 3 } ,
{ & RUNTIME_CLASS_CASTLESS ( APlayerPawn ) , PlayerPawnFlagDefs , countof ( PlayerPawnFlagDefs ) , 3 } ,
2016-03-01 15:47:10 +00:00
} ;
# define NUM_FLAG_LISTS (countof(FlagLists))
//==========================================================================
//
// 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
{
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
// Handle that lone PowerSpeed flag - this should be more generalized but it's just this one flag and unlikely to become more so an explicit check will do.
if ( ( ! stricmp ( part1 , " NOTRAIL " ) & & ! strict ) | | ( ! stricmp ( part1 , " POWERSPEED " ) & & ! stricmp ( part2 , " NOTRAIL " ) ) )
{
return & PowerSpeedFlagDefs [ 0 ] ;
}
2016-03-01 15:47:10 +00:00
return NULL ;
}
//==========================================================================
//
// Gets the name of an actor flag
//
//==========================================================================
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 ;
}
//==========================================================================
//
// Find a function by name using a binary search
//
//==========================================================================
2016-11-19 11:12:29 +00:00
AFuncDesc * FindFunction ( PStruct * 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 ;
int lexval = stricmp ( cls - > TypeName . GetChars ( ) , AFTable [ mid ] . ClassName + 1 ) ;
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
//
//==========================================================================
FieldDesc * FindField ( PStruct * cls , const char * string )
{
int min = 0 , max = FieldTable . Size ( ) - 1 ;
while ( min < = max )
{
int mid = ( min + max ) / 2 ;
int lexval = stricmp ( cls - > TypeName . GetChars ( ) , FieldTable [ mid ] . ClassName + 1 ) ;
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
{
2016-11-06 10:36:12 +00:00
auto f = dyn_cast < PFunction > ( cls - > Symbols . FindSymbol ( name , true ) ) ;
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
{
2016-11-21 18:09:58 +00:00
// +1 to get past the prefix letter of the native class name, which gets omitted by the FName for the class.
int res = stricmp ( ( ( AFuncDesc * ) a ) - > ClassName + 1 , ( ( AFuncDesc * ) b ) - > ClassName + 1 ) ;
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 )
{
// +1 to get past the prefix letter of the native class name, which gets omitted by the FName for the class.
int res = stricmp ( ( ( FieldDesc * ) a ) - > ClassName + 1 , ( ( FieldDesc * ) b ) - > ClassName + 1 ) ;
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-01-02 20:40:52 +00:00
// Create all global variables here because this cannot be done on the script side and really isn't worth adding support for.
2017-01-07 20:29:43 +00:00
// Also create all special fields here that cannot be declared by script syntax.
auto secplanestruct = NewNativeStruct ( " Secplane " , nullptr ) ;
secplanestruct - > Size = sizeof ( secplane_t ) ;
secplanestruct - > Align = alignof ( secplane_t ) ;
2017-01-08 13:39:16 +00:00
2017-01-07 20:29:43 +00:00
auto sectorstruct = NewNativeStruct ( " Sector " , nullptr ) ;
sectorstruct - > Size = sizeof ( sector_t ) ;
sectorstruct - > Align = alignof ( sector_t ) ;
2017-01-08 13:39:16 +00:00
auto linestruct = NewNativeStruct ( " Line " , nullptr ) ;
linestruct - > Size = sizeof ( line_t ) ;
linestruct - > Align = alignof ( line_t ) ;
2017-01-08 20:42:26 +00:00
auto sidestruct = NewNativeStruct ( " Side " , nullptr ) ;
sidestruct - > Size = sizeof ( side_t ) ;
sidestruct - > Align = alignof ( side_t ) ;
2017-01-08 23:46:16 +00:00
auto vertstruct = NewNativeStruct ( " Vertex " , nullptr ) ;
vertstruct - > Size = sizeof ( vertex_t ) ;
vertstruct - > Align = alignof ( vertex_t ) ;
2017-01-14 15:05:40 +00:00
auto sectorportalstruct = NewNativeStruct ( " SectorPortal " , nullptr ) ;
sectorportalstruct - > Size = sizeof ( FSectorPortal ) ;
sectorportalstruct - > Align = alignof ( FSectorPortal ) ;
2017-01-07 20:29:43 +00:00
// set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well...
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
2017-01-08 13:39:16 +00:00
sectorstruct - > AddNativeField ( " lines " , NewPointer ( NewResizableArray ( NewPointer ( linestruct , false ) ) , false ) , myoffsetof ( sector_t , Lines ) , VARF_Native ) ;
2017-01-07 20:29:43 +00:00
2017-01-12 23:35:56 +00:00
sectorstruct - > AddNativeField ( " ceilingplane " , secplanestruct , myoffsetof ( sector_t , ceilingplane ) , VARF_Native ) ;
sectorstruct - > AddNativeField ( " floorplane " , secplanestruct , myoffsetof ( sector_t , floorplane ) , VARF_Native ) ;
2017-01-07 20:29:43 +00:00
2016-11-19 08:24:54 +00:00
2016-11-27 17:52:24 +00:00
// expose the global validcount variable.
PField * vcf = new PField ( " validcount " , TypeSInt32 , VARF_Native | VARF_Static , ( intptr_t ) & validcount ) ;
2017-01-23 18:09:36 +00:00
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( vcf ) ;
2016-11-27 17:52:24 +00:00
// expose the global Multiplayer variable.
2016-11-25 15:05:03 +00:00
PField * multif = new PField ( " multiplayer " , TypeBool , VARF_Native | VARF_ReadOnly | VARF_Static , ( intptr_t ) & multiplayer ) ;
2017-01-23 18:09:36 +00:00
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( multif ) ;
2016-11-19 08:24:54 +00:00
2016-11-22 23:35:06 +00:00
// set up a variable for the global level data structure
PStruct * lstruct = NewNativeStruct ( " LevelLocals " , nullptr ) ;
PField * levelf = new PField ( " level " , lstruct , VARF_Native | VARF_Static , ( intptr_t ) & level ) ;
2017-01-23 18:09:36 +00:00
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( levelf ) ;
2016-11-19 08:24:54 +00:00
2017-01-14 15:05:40 +00:00
// Add the game data arrays to LevelLocals.
2017-01-07 20:29:43 +00:00
lstruct - > AddNativeField ( " sectors " , NewPointer ( NewResizableArray ( sectorstruct ) , false ) , myoffsetof ( FLevelLocals , sectors ) , VARF_Native ) ;
2017-01-08 13:39:16 +00:00
lstruct - > AddNativeField ( " lines " , NewPointer ( NewResizableArray ( linestruct ) , false ) , myoffsetof ( FLevelLocals , lines ) , VARF_Native ) ;
2017-01-08 20:42:26 +00:00
lstruct - > AddNativeField ( " sides " , NewPointer ( NewResizableArray ( sidestruct ) , false ) , myoffsetof ( FLevelLocals , sides ) , VARF_Native ) ;
2017-01-08 23:46:16 +00:00
lstruct - > AddNativeField ( " vertexes " , NewPointer ( NewResizableArray ( vertstruct ) , false ) , myoffsetof ( FLevelLocals , vertexes ) , VARF_Native | VARF_ReadOnly ) ;
2017-01-14 15:05:40 +00:00
lstruct - > AddNativeField ( " sectorportals " , NewPointer ( NewResizableArray ( sectorportalstruct ) , false ) , myoffsetof ( FLevelLocals , sectorPortals ) , VARF_Native ) ;
2017-01-07 20:29:43 +00:00
2017-01-14 22:34:47 +00:00
auto aact = NewPointer ( NewResizableArray ( NewClassPointer ( RUNTIME_CLASS ( AActor ) ) ) , true ) ;
PField * aacf = new PField ( " AllActorClasses " , aact , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & PClassActor : : AllActorClasses ) ;
2017-01-23 18:09:36 +00:00
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( aacf ) ;
2017-01-14 22:34:47 +00:00
2016-11-25 00:33:04 +00:00
// set up a variable for the DEH data
PStruct * dstruct = NewNativeStruct ( " DehInfo " , nullptr ) ;
2016-11-25 15:05:03 +00:00
PField * dehf = new PField ( " deh " , dstruct , VARF_Native | VARF_Static , ( intptr_t ) & deh ) ;
2017-01-23 18:09:36 +00:00
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( dehf ) ;
2016-11-25 00:33:04 +00:00
2017-01-17 16:31:54 +00:00
// set up a variable for the global gameinfo data
PStruct * gistruct = NewNativeStruct ( " GameInfoStruct " , nullptr ) ;
PField * gi = new PField ( " gameinfo " , gistruct , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & gameinfo ) ;
2017-01-23 18:09:36 +00:00
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( gi ) ;
2017-01-17 16:31:54 +00:00
2016-11-22 22:42:32 +00:00
// set up a variable for the global players array.
PStruct * pstruct = NewNativeStruct ( " PlayerInfo " , nullptr ) ;
pstruct - > Size = sizeof ( player_t ) ;
pstruct - > Align = alignof ( player_t ) ;
PArray * parray = NewArray ( pstruct , MAXPLAYERS ) ;
2017-02-03 23:46:22 +00:00
PField * fieldptr = new PField ( " players " , parray , VARF_Native | VARF_Static , ( intptr_t ) & players ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2016-11-26 00:14:47 +00:00
2017-01-17 16:31:54 +00:00
pstruct - > AddNativeField ( " weapons " , NewNativeStruct ( " WeaponSlots " , nullptr ) , myoffsetof ( player_t , weapons ) , VARF_Native ) ;
2016-11-26 00:14:47 +00:00
parray = NewArray ( TypeBool , MAXPLAYERS ) ;
2017-02-03 23:46:22 +00:00
fieldptr = new PField ( " playeringame " , parray , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & playeringame ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2016-11-22 22:42:32 +00:00
2017-02-03 23:46:22 +00:00
fieldptr = new PField ( " gameaction " , TypeUInt8 , VARF_Native | VARF_Static , ( intptr_t ) & gameaction ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2016-11-29 11:17:05 +00:00
2017-02-03 23:46:22 +00:00
fieldptr = new PField ( " skyflatnum " , TypeTextureID , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & skyflatnum ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2017-01-12 23:35:56 +00:00
2017-02-03 23:46:22 +00:00
fieldptr = new PField ( " globalfreeze " , TypeUInt8 , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & bglobal . freeze ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2017-01-12 23:35:56 +00:00
2017-02-03 23:46:22 +00:00
fieldptr = new PField ( " consoleplayer " , TypeSInt32 , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & consoleplayer ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
auto fontptr = NewPointer ( NewNativeStruct ( " Font " , nullptr ) ) ;
fieldptr = new PField ( " smallfont " , fontptr , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & SmallFont ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
fieldptr = new PField ( " smallfont2 " , fontptr , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & SmallFont2 ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
fieldptr = new PField ( " bigfont " , fontptr , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & BigFont ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
fieldptr = new PField ( " confont " , fontptr , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & ConFont ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
fieldptr = new PField ( " intermissionfont " , fontptr , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & IntermissionFont ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2016-11-29 11:17:05 +00:00
2016-11-28 22:30:14 +00:00
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it and reference that in the script. Yuck!!!
static AWeapon * wpnochg = WP_NOCHANGE ;
2017-02-03 23:46:22 +00:00
fieldptr = new PField ( " WP_NOCHANGE " , NewPointer ( RUNTIME_CLASS ( AWeapon ) , false ) , VARF_Native | VARF_Static | VARF_ReadOnly , ( intptr_t ) & wpnochg ) ;
Namespaces . GlobalNamespace - > Symbols . AddSymbol ( fieldptr ) ;
2016-11-22 22:42:32 +00:00
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
for ( auto & fl : FlagLists )
{
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
{
const_cast < PClass * > ( * fl . Type ) - > 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-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 ) ;
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 ;
fcp - > Size = sizeof ( FCheckPosition ) ;
fcp - > Align = alignof ( FCheckPosition ) ;
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
DEFINE_ACTION_FUNCTION ( DObject , GameType )
{
PARAM_PROLOGUE ;
ACTION_RETURN_INT ( gameinfo . gametype ) ;
}
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 ( ) ) ;
}
2016-11-28 17:15:18 +00:00
DEFINE_ACTION_FUNCTION ( FStringTable , Localize )
{
PARAM_PROLOGUE ;
PARAM_STRING ( label ) ;
2017-01-15 09:37:54 +00:00
PARAM_BOOL_DEF ( prefixed ) ;
if ( ! prefixed ) ACTION_RETURN_STRING ( GStrings ( label ) ) ;
if ( label [ 0 ] ! = ' $ ' ) ACTION_RETURN_STRING ( label ) ;
ACTION_RETURN_STRING ( GStrings ( & label [ 1 ] ) ) ;
2016-11-28 17:15:18 +00:00
}
2017-01-23 18:09:36 +00:00
DEFINE_ACTION_FUNCTION ( FStringStruct , Replace )
2016-11-28 17:15:18 +00:00
{
PARAM_SELF_STRUCT_PROLOGUE ( FString ) ;
PARAM_STRING ( s1 ) ;
PARAM_STRING ( s2 ) ;
2017-01-17 08:56:45 +00:00
self - > Substitute ( s1 , s2 ) ;
2016-11-28 17:15:18 +00:00
return 0 ;
2016-11-29 16:17:10 +00:00
}
2017-01-21 00:07:44 +00:00
static FString FStringFormat ( VM_ARGS )
{
assert ( param [ 0 ] . Type = = REGT_STRING ) ;
FString fmtstring = param [ 0 ] . s ( ) . GetChars ( ) ;
// 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 )
{
if ( ( c > = ' 0 ' & & c < = ' 9 ' ) | |
c = = ' - ' | | c = = ' + ' | | ( c = = ' ' & & fmt_current [ fmt_current . Len ( ) - 1 ] ! = ' ' ) | | c = = ' # ' | | c = = ' . ' )
{
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. " ) ;
if ( param [ argnum ] . Type ! = REGT_STRING ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a string for format %s. " , fmt_current . GetChars ( ) ) ;
// 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. " ) ;
if ( param [ argnum ] . Type ! = REGT_POINTER ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a pointer for format %s. " , fmt_current . GetChars ( ) ) ;
// 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 ' :
{
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 an int
if ( argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
if ( param [ argnum ] . Type ! = REGT_INT & &
param [ argnum ] . Type ! = REGT_FLOAT ) ThrowAbortException ( X_FORMAT_ERROR , " Expected a numeric value for format %s. " , fmt_current . GetChars ( ) ) ;
// append
output . AppendFormat ( fmt_current . GetChars ( ) , param [ argnum ] . ToInt ( ) ) ;
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 ;
// fail if something was found, but it's not a float
if ( argnum > = numparam ) ThrowAbortException ( X_FORMAT_ERROR , " Not enough arguments for format. " ) ;
if ( param [ argnum ] . Type ! = REGT_INT & &
param [ argnum ] . Type ! = 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 ( ) ) ;
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 ;
FString s = FStringFormat ( param , defaultparam , numparam , ret , numret ) ;
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
FString s = FStringFormat ( param + 1 , defaultparam , numparam - 1 , ret , numret ) ;
( * self ) + = s ;
return 0 ;
2017-02-06 11:18:10 +00:00
}
DEFINE_ACTION_FUNCTION ( FStringStruct , Mid )
{
PARAM_SELF_STRUCT_PROLOGUE ( FString ) ;
2017-02-07 13:48:27 +00:00
PARAM_UINT ( pos ) ;
PARAM_UINT ( len ) ;
2017-02-06 11:18:10 +00:00
FString s = self - > Mid ( pos , len ) ;
ACTION_RETURN_STRING ( s ) ;
}
DEFINE_ACTION_FUNCTION ( FStringStruct , Len )
{
PARAM_SELF_STRUCT_PROLOGUE ( FString ) ;
2017-02-07 13:48:27 +00:00
ACTION_RETURN_INT ( ( int ) self - > Len ( ) ) ;
2017-02-06 11:18:10 +00:00
}
// CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int.
DEFINE_ACTION_FUNCTION ( FStringStruct , CharAt )
{
PARAM_SELF_STRUCT_PROLOGUE ( FString ) ;
PARAM_INT ( pos ) ;
2017-02-07 13:48:27 +00:00
int slen = ( int ) self - > Len ( ) ;
2017-02-06 11:18:10 +00:00
if ( pos < 0 | | pos > = slen )
ACTION_RETURN_STRING ( " " ) ;
ACTION_RETURN_STRING ( FString ( ( * self ) [ pos ] ) ) ;
}
DEFINE_ACTION_FUNCTION ( FStringStruct , CharCodeAt )
{
PARAM_SELF_STRUCT_PROLOGUE ( FString ) ;
PARAM_INT ( pos ) ;
2017-02-07 13:48:27 +00:00
int slen = ( int ) self - > Len ( ) ;
2017-02-06 11:18:10 +00:00
if ( pos < 0 | | pos > = slen )
ACTION_RETURN_INT ( 0 ) ;
ACTION_RETURN_INT ( ( * self ) [ pos ] ) ;
}