2016-03-01 15:47:10 +00:00
/*
* * thingdef - properties . cpp
* *
2016-03-24 19:56:59 +00:00
* * Actor denitions - properties and flags handling
2016-03-01 15:47:10 +00:00
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 2002 - 2007 Christoph Oelckers
* * Copyright 2004 - 2007 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 "gi.h"
2016-11-27 09:40:43 +00:00
# include "d_player.h"
2016-03-01 15:47:10 +00:00
# include "w_wad.h"
# include "cmdlib.h"
# include "p_lnspec.h"
# include "decallib.h"
# include "p_local.h"
# include "p_effect.h"
# include "v_text.h"
# include "thingdef.h"
# include "a_morph.h"
# include "teaminfo.h"
2017-02-08 11:24:08 +00:00
# include "backend/vmbuilder.h"
2016-11-30 12:36:13 +00:00
# include "a_keys.h"
2017-01-08 17:45:30 +00:00
# include "g_levellocals.h"
2017-04-12 23:12:04 +00:00
# include "types.h"
2019-01-31 01:05:16 +00:00
# include "a_dynlight.h"
2019-01-31 23:30:21 +00:00
# include "v_video.h"
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Gets a class pointer and performs an error check for correct type
//
//==========================================================================
2016-11-23 21:34:17 +00:00
static PClassActor * FindClassTentative ( const char * name , PClass * ancestor , bool optional = false )
2016-03-01 15:47:10 +00:00
{
// "" and "none" mean 'no class'
if ( name = = NULL | | * name = = 0 | | ! stricmp ( name , " none " ) )
{
return NULL ;
}
PClass * cls = ancestor - > FindClassTentative ( name ) ;
assert ( cls ! = NULL ) ; // cls can not be NULL here
if ( ! cls - > IsDescendantOf ( ancestor ) )
{
I_Error ( " %s does not inherit from %s \n " , name , ancestor - > TypeName . GetChars ( ) ) ;
}
2016-11-23 21:34:17 +00:00
if ( cls - > Size = = TentativeClass & & optional )
{
2017-04-12 20:46:49 +00:00
cls - > bOptional = true ;
2016-11-23 21:34:17 +00:00
}
2016-03-01 15:47:10 +00:00
return static_cast < PClassActor * > ( cls ) ;
}
//==========================================================================
//
// Sets or clears a flag, taking field width into account.
//
//==========================================================================
void ModActorFlag ( AActor * actor , FFlagDef * fd , bool set )
{
// Little-Endian machines only need one case, because all field sizes
// start at the same address. (Unless the machine has unaligned access
// exceptions, in which case you'll need multiple cases for it too.)
# ifdef __BIG_ENDIAN__
if ( fd - > fieldsize = = 4 )
# endif
{
2017-03-08 17:44:37 +00:00
uint32_t * flagvar = ( uint32_t * ) ( ( char * ) actor + fd - > structoffset ) ;
2016-03-01 15:47:10 +00:00
if ( set )
{
* flagvar | = fd - > flagbit ;
}
else
{
* flagvar & = ~ fd - > flagbit ;
}
}
# ifdef __BIG_ENDIAN__
else if ( fd - > fieldsize = = 2 )
{
2017-03-08 17:44:37 +00:00
uint16_t * flagvar = ( uint16_t * ) ( ( char * ) actor + fd - > structoffset ) ;
2016-03-01 15:47:10 +00:00
if ( set )
{
* flagvar | = fd - > flagbit ;
}
else
{
* flagvar & = ~ fd - > flagbit ;
}
}
else
{
assert ( fd - > fieldsize = = 1 ) ;
2017-03-08 17:44:37 +00:00
uint8_t * flagvar = ( uint8_t * ) ( ( char * ) actor + fd - > structoffset ) ;
2016-03-01 15:47:10 +00:00
if ( set )
{
* flagvar | = fd - > flagbit ;
}
else
{
* flagvar & = ~ fd - > flagbit ;
}
}
# endif
}
2016-08-24 10:21:46 +00:00
//==========================================================================
//
// Finds a flag by name and sets or clears it
//
// Returns true if the flag was found for the actor; else returns false
//
//==========================================================================
2018-12-01 09:29:23 +00:00
bool ModActorFlag ( AActor * actor , const FString & flagname , bool set , bool printerror )
2016-08-24 10:21:46 +00:00
{
bool found = false ;
if ( actor ! = NULL )
{
2019-01-27 18:16:14 +00:00
auto Level = actor - > Level ;
2016-08-24 10:21:46 +00:00
const char * dot = strchr ( flagname , ' . ' ) ;
FFlagDef * fd ;
PClassActor * cls = actor - > GetClass ( ) ;
if ( dot ! = NULL )
{
FString part1 ( flagname . GetChars ( ) , dot - flagname ) ;
fd = FindFlag ( cls , part1 , dot + 1 ) ;
}
else
{
fd = FindFlag ( cls , flagname , NULL ) ;
}
if ( fd ! = NULL )
{
found = true ;
2019-01-27 18:16:14 +00:00
if ( actor - > CountsAsKill ( ) & & actor - > health > 0 ) - - Level - > total_monsters ;
if ( actor - > flags & MF_COUNTITEM ) - - Level - > total_items ;
if ( actor - > flags5 & MF5_COUNTSECRET ) - - Level - > total_secrets ;
2016-08-24 10:21:46 +00:00
if ( fd - > structoffset = = - 1 )
{
HandleDeprecatedFlags ( actor , cls , set , fd - > flagbit ) ;
}
else
{
ActorFlags * flagp = ( ActorFlags * ) ( ( ( char * ) actor ) + fd - > structoffset ) ;
// If these 2 flags get changed we need to update the blockmap and sector links.
bool linkchange = flagp = = & actor - > flags & & ( fd - > flagbit = = MF_NOBLOCKMAP | | fd - > flagbit = = MF_NOSECTOR ) ;
2016-12-25 21:40:26 +00:00
FLinkContext ctx ;
if ( linkchange ) actor - > UnlinkFromWorld ( & ctx ) ;
2016-08-24 10:21:46 +00:00
ModActorFlag ( actor , fd , set ) ;
2016-12-25 21:40:26 +00:00
if ( linkchange ) actor - > LinkToWorld ( & ctx ) ;
2016-08-24 10:21:46 +00:00
}
2019-01-27 18:16:14 +00:00
if ( actor - > CountsAsKill ( ) & & actor - > health > 0 ) + + Level - > total_monsters ;
if ( actor - > flags & MF_COUNTITEM ) + + Level - > total_items ;
if ( actor - > flags5 & MF5_COUNTSECRET ) + + Level - > total_secrets ;
2016-08-24 10:21:46 +00:00
}
else if ( printerror )
{
DPrintf ( DMSG_ERROR , " ACS/DECORATE: '%s' is not a flag in '%s' \n " , flagname . GetChars ( ) , cls - > TypeName . GetChars ( ) ) ;
}
}
return found ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Returns whether an actor flag is true or not.
//
//==========================================================================
2018-12-03 23:22:26 +00:00
INTBOOL CheckActorFlag ( AActor * owner , FFlagDef * fd )
2016-03-01 15:47:10 +00:00
{
if ( fd - > structoffset = = - 1 )
{
return CheckDeprecatedFlags ( owner , owner - > GetClass ( ) , fd - > flagbit ) ;
}
else
# ifdef __BIG_ENDIAN__
if ( fd - > fieldsize = = 4 )
# endif
{
2017-03-08 17:44:37 +00:00
return fd - > flagbit & * ( uint32_t * ) ( ( ( char * ) owner ) + fd - > structoffset ) ;
2016-03-01 15:47:10 +00:00
}
# ifdef __BIG_ENDIAN__
else if ( fd - > fieldsize = = 2 )
{
2017-03-08 17:44:37 +00:00
return fd - > flagbit & * ( uint16_t * ) ( ( ( char * ) owner ) + fd - > structoffset ) ;
2016-03-01 15:47:10 +00:00
}
else
{
assert ( fd - > fieldsize = = 1 ) ;
2017-03-08 17:44:37 +00:00
return fd - > flagbit & * ( uint8_t * ) ( ( ( char * ) owner ) + fd - > structoffset ) ;
2016-03-01 15:47:10 +00:00
}
# endif
}
2018-12-03 23:22:26 +00:00
INTBOOL CheckActorFlag ( AActor * owner , const char * flagname , bool printerror )
2016-03-01 15:47:10 +00:00
{
const char * dot = strchr ( flagname , ' . ' ) ;
FFlagDef * fd ;
const PClass * cls = owner - > GetClass ( ) ;
if ( dot ! = NULL )
{
FString part1 ( flagname , dot - flagname ) ;
fd = FindFlag ( cls , part1 , dot + 1 ) ;
}
else
{
fd = FindFlag ( cls , flagname , NULL ) ;
}
if ( fd ! = NULL )
{
return CheckActorFlag ( owner , fd ) ;
}
else
{
if ( printerror ) Printf ( " Unknown flag '%s' in '%s' \n " , flagname , cls - > TypeName . GetChars ( ) ) ;
return false ;
}
}
//===========================================================================
//
// HandleDeprecatedFlags
//
// Handles the deprecated flags and sets the respective properties
// to appropriate values. This is solely intended for backwards
// compatibility so mixing this with code that is aware of the real
// properties is not recommended
//
//===========================================================================
void HandleDeprecatedFlags ( AActor * defaults , PClassActor * info , bool set , int index )
{
switch ( index )
{
case DEPF_FIREDAMAGE :
defaults - > DamageType = set ? NAME_Fire : NAME_None ;
break ;
case DEPF_ICEDAMAGE :
defaults - > DamageType = set ? NAME_Ice : NAME_None ;
break ;
case DEPF_LOWGRAVITY :
2016-03-20 23:51:19 +00:00
defaults - > Gravity = set ? 1. / 8 : 1. ;
2016-03-01 15:47:10 +00:00
break ;
case DEPF_SHORTMISSILERANGE :
2016-03-24 19:56:59 +00:00
defaults - > maxtargetrange = set ? 896. : 0. ;
2016-03-01 15:47:10 +00:00
break ;
case DEPF_LONGMELEERANGE :
2016-03-24 19:56:59 +00:00
defaults - > meleethreshold = set ? 196. : 0. ;
2016-03-01 15:47:10 +00:00
break ;
case DEPF_QUARTERGRAVITY :
2016-03-20 23:51:19 +00:00
defaults - > Gravity = set ? 1. / 4 : 1. ;
2016-03-01 15:47:10 +00:00
break ;
case DEPF_FIRERESIST :
2016-03-22 15:35:41 +00:00
info - > SetDamageFactor ( NAME_Fire , set ? 0.5 : 1. ) ;
2016-03-01 15:47:10 +00:00
break ;
// the bounce flags will set the compatibility bounce modes to remain compatible
case DEPF_HERETICBOUNCE :
defaults - > BounceFlags & = ~ ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ;
if ( set ) defaults - > BounceFlags | = BOUNCE_HereticCompat ;
break ;
case DEPF_HEXENBOUNCE :
defaults - > BounceFlags & = ~ ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ;
if ( set ) defaults - > BounceFlags | = BOUNCE_HexenCompat ;
break ;
case DEPF_DOOMBOUNCE :
defaults - > BounceFlags & = ~ ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ;
if ( set ) defaults - > BounceFlags | = BOUNCE_DoomCompat ;
break ;
case DEPF_PICKUPFLASH :
if ( set )
{
2018-12-03 23:22:26 +00:00
defaults - > PointerVar < PClass > ( NAME_PickupFlash ) = FindClassTentative ( " PickupFlash " , RUNTIME_CLASS ( AActor ) ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2018-12-03 23:22:26 +00:00
defaults - > PointerVar < PClass > ( NAME_PickupFlash ) = nullptr ;
2016-03-01 15:47:10 +00:00
}
break ;
case DEPF_INTERHUBSTRIP : // Old system was 0 or 1, so if the flag is cleared, assume 1.
2018-12-03 23:22:26 +00:00
defaults - > IntVar ( NAME_InterHubAmount ) = set ? 0 : 1 ;
2017-01-17 00:50:31 +00:00
break ;
2016-03-01 15:47:10 +00:00
default :
break ; // silence GCC
}
}
//===========================================================================
//
// CheckDeprecatedFlags
//
// Checks properties related to deprecated flags, and returns true only
// if the relevant properties are configured exactly as they would have
// been by setting the flag in HandleDeprecatedFlags.
//
//===========================================================================
2018-12-03 23:22:26 +00:00
bool CheckDeprecatedFlags ( AActor * actor , PClassActor * info , int index )
2016-03-01 15:47:10 +00:00
{
// A deprecated flag is false if
// a) it hasn't been added here
// b) any property of the actor differs from what it would be after setting the flag using HandleDeprecatedFlags
// Deprecated flags are normally replaced by something more flexible, which means a multitude of related configurations
// will report "false".
switch ( index )
{
case DEPF_FIREDAMAGE :
return actor - > DamageType = = NAME_Fire ;
case DEPF_ICEDAMAGE :
return actor - > DamageType = = NAME_Ice ;
case DEPF_LOWGRAVITY :
2016-03-20 23:51:19 +00:00
return actor - > Gravity = = 1. / 8 ;
2016-03-01 15:47:10 +00:00
case DEPF_SHORTMISSILERANGE :
2016-03-24 19:56:59 +00:00
return actor - > maxtargetrange = = 896. ;
2016-03-01 15:47:10 +00:00
case DEPF_LONGMELEERANGE :
2016-03-24 19:56:59 +00:00
return actor - > meleethreshold = = 196. ;
2016-03-01 15:47:10 +00:00
case DEPF_QUARTERGRAVITY :
2016-03-20 23:51:19 +00:00
return actor - > Gravity = = 1. / 4 ;
2016-03-01 15:47:10 +00:00
case DEPF_FIRERESIST :
2017-04-11 22:07:41 +00:00
for ( auto & df : info - > ActorInfo ( ) - > DamageFactors )
2016-03-01 15:47:10 +00:00
{
2017-04-11 21:29:37 +00:00
if ( df . first = = NAME_Fire ) return df . second = = 0.5 ;
2016-03-01 15:47:10 +00:00
}
return false ;
case DEPF_HERETICBOUNCE :
return ( actor - > BounceFlags & ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ) = = BOUNCE_HereticCompat ;
case DEPF_HEXENBOUNCE :
return ( actor - > BounceFlags & ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ) = = BOUNCE_HexenCompat ;
case DEPF_DOOMBOUNCE :
return ( actor - > BounceFlags & ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ) = = BOUNCE_DoomCompat ;
case DEPF_PICKUPFLASH :
2018-12-03 23:22:26 +00:00
return actor - > PointerVar < PClass > ( NAME_PickupFlash ) = = PClass : : FindClass ( NAME_PickupFlash ) ;
2016-03-01 15:47:10 +00:00
case DEPF_INTERHUBSTRIP :
2018-12-03 23:22:26 +00:00
return ! ( actor - > IntVar ( NAME_InterHubAmount ) ) ;
2016-03-01 15:47:10 +00:00
}
return false ; // Any entirely unknown flag is not set
}
//==========================================================================
//
//
//
//==========================================================================
int MatchString ( const char * in , const char * * strings )
{
int i ;
for ( i = 0 ; * strings ! = NULL ; i + + )
{
if ( ! stricmp ( in , * strings + + ) )
{
return i ;
}
}
return - 1 ;
}
2017-01-17 19:30:17 +00:00
//==========================================================================
//
2017-01-18 09:33:03 +00:00
// Get access to scripted pointers.
// They need a bit more work than other variables.
2017-01-17 19:30:17 +00:00
//
//==========================================================================
2017-01-17 23:11:04 +00:00
static bool PointerCheck ( PType * symtype , PType * checktype )
{
2017-04-13 13:13:14 +00:00
auto symptype = PType : : toClassPointer ( symtype ) ;
auto checkptype = PType : : toClassPointer ( checktype ) ;
2017-01-17 23:11:04 +00:00
return symptype ! = nullptr & & checkptype ! = nullptr & & symptype - > ClassRestriction - > IsDescendantOf ( checkptype - > ClassRestriction ) ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// Info Property handlers
//
//==========================================================================
2017-01-17 19:30:17 +00:00
2016-03-01 15:47:10 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_INFO_PROPERTY ( game , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
2017-04-11 21:29:37 +00:00
auto & GameFilter = info - > ActorInfo ( ) - > GameFilter ;
2016-03-01 15:47:10 +00:00
if ( ! stricmp ( str , " Doom " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter | = GAME_Doom ;
2016-03-01 15:47:10 +00:00
}
else if ( ! stricmp ( str , " Heretic " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter | = GAME_Heretic ;
2016-03-01 15:47:10 +00:00
}
else if ( ! stricmp ( str , " Hexen " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter | = GAME_Hexen ;
2016-03-01 15:47:10 +00:00
}
else if ( ! stricmp ( str , " Raven " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter | = GAME_Raven ;
2016-03-01 15:47:10 +00:00
}
else if ( ! stricmp ( str , " Strife " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter | = GAME_Strife ;
2016-03-01 15:47:10 +00:00
}
else if ( ! stricmp ( str , " Chex " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter | = GAME_Chex ;
2016-03-01 15:47:10 +00:00
}
else if ( ! stricmp ( str , " Any " ) )
{
2017-04-11 21:29:37 +00:00
GameFilter = GAME_Any ;
2016-03-01 15:47:10 +00:00
}
else
{
I_Error ( " Unknown game type %s " , str ) ;
}
}
//==========================================================================
//
//==========================================================================
DEFINE_INFO_PROPERTY ( spawnid , I , Actor )
{
PROP_INT_PARM ( id , 0 ) ;
if ( id < 0 | | id > 65535 )
{
I_Error ( " SpawnID must be in the range [0,65535] " ) ;
}
2017-04-11 21:29:37 +00:00
else info - > ActorInfo ( ) - > SpawnID = ( uint16_t ) id ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_INFO_PROPERTY ( conversationid , IiI , Actor )
{
PROP_INT_PARM ( convid , 0 ) ;
PROP_INT_PARM ( id1 , 1 ) ;
PROP_INT_PARM ( id2 , 2 ) ;
if ( convid < = 0 | | convid > 65535 ) return ; // 0 is not usable because the dialogue scripts use it as 'no object'.
2017-04-11 21:29:37 +00:00
else info - > ActorInfo ( ) - > ConversationID = ( uint16_t ) convid ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
// Property handlers
//
//==========================================================================
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( skip_super , 0 , Actor )
{
2016-10-10 22:56:47 +00:00
auto actorclass = RUNTIME_CLASS ( AActor ) ;
if ( info - > Size ! = actorclass - > Size )
2016-03-01 15:47:10 +00:00
{
2016-10-10 22:56:47 +00:00
bag . ScriptPosition . Message ( MSG_OPTERROR ,
2018-02-28 17:09:32 +00:00
" 'skip_super' is only allowed in subclasses of Actor with no additional fields and will be ignored in type %s. " , info - > TypeName . GetChars ( ) ) ;
2016-03-01 15:47:10 +00:00
return ;
}
if ( bag . StateSet )
{
2016-06-08 08:56:11 +00:00
bag . ScriptPosition . Message ( MSG_OPTERROR ,
2016-03-01 15:47:10 +00:00
" 'skip_super' must appear before any state definitions. " ) ;
return ;
}
2017-02-07 17:12:38 +00:00
* defaults = * GetDefault < AActor > ( ) ;
2016-03-01 15:47:10 +00:00
ResetBaggage ( & bag , RUNTIME_CLASS ( AActor ) ) ;
2018-02-28 17:09:32 +00:00
static_cast < PClassActor * > ( bag . Info ) - > ActorInfo ( ) - > SkipSuperSet = true ; // ZScript processes the states later so this property must be flagged for later handling.
2016-03-01 15:47:10 +00:00
}
2016-11-14 17:31:12 +00:00
//==========================================================================
// for internal use only - please do not document!
//==========================================================================
DEFINE_PROPERTY ( defaultstateusage , I , Actor )
{
PROP_INT_PARM ( use , 0 ) ;
2017-04-11 21:29:37 +00:00
static_cast < PClassActor * > ( bag . Info ) - > ActorInfo ( ) - > DefaultStateUsage = use ;
2016-11-14 17:31:12 +00:00
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( tag , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
defaults - > SetTag ( str ) ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( painchance , ZI , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
PROP_INT_PARM ( id , 1 ) ;
if ( str = = NULL )
{
defaults - > PainChance = id ;
}
else
{
2018-08-18 23:14:15 +00:00
FName painType = NAME_None ;
if ( stricmp ( str , " Normal " ) ) painType = str ;
2016-03-01 15:47:10 +00:00
info - > SetPainChance ( painType , id ) ;
}
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( defthreshold , I , Actor )
{
PROP_INT_PARM ( id , 0 ) ;
if ( id < 0 )
I_Error ( " DefThreshold cannot be negative. " ) ;
defaults - > DefThreshold = id ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( threshold , I , Actor )
{
PROP_INT_PARM ( id , 0 ) ;
if ( id < 0 )
I_Error ( " Threshold cannot be negative. " ) ;
defaults - > threshold = id ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( damage , X , Actor )
{
2016-09-19 01:36:51 +00:00
PROP_INT_PARM ( dmgval , 0 ) ;
PROP_EXP_PARM ( id , 1 ) ;
2016-03-01 15:47:10 +00:00
// Damage can either be a single number, in which case it is subject
// to the original damage calculation rules. Or, it can be an expression
// and will be calculated as-is, ignoring the original rules. For
// compatibility reasons, expressions must be enclosed within
// parentheses.
2016-09-19 01:36:51 +00:00
defaults - > DamageVal = dmgval ;
2016-10-26 12:04:49 +00:00
// Only DECORATE can get here with a valid expression.
2017-03-05 16:58:55 +00:00
CreateDamageFunction ( bag . Namespace , bag . Version , bag . Info , defaults , id , true , bag . Lumpnum ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( scale , F , Actor )
{
2016-03-20 11:13:00 +00:00
PROP_DOUBLE_PARM ( id , 0 ) ;
defaults - > Scale . X = defaults - > Scale . Y = id ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( floatbobphase , I , Actor )
{
PROP_INT_PARM ( id , 0 ) ;
if ( id < - 1 | | id > = 64 ) I_Error ( " FloatBobPhase must be in range [-1,63] " ) ;
defaults - > FloatBobPhase = id ;
}
2017-06-03 15:42:57 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( floatbobstrength , F , Actor )
{
PROP_DOUBLE_PARM ( id , 0 ) ;
defaults - > FloatBobStrength = id ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( args , Iiiii , Actor )
{
for ( int i = 0 ; i < PROP_PARM_COUNT ; i + + )
{
PROP_INT_PARM ( id , i ) ;
defaults - > args [ i ] = id ;
}
defaults - > flags2 | = MF2_ARGSDEFINED ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( dropitem , S_i_i , Actor )
{
PROP_STRING_PARM ( type , 0 ) ;
// create a linked list of dropitems
if ( ! bag . DropItemSet )
{
bag . DropItemSet = true ;
bag . DropItemList = NULL ;
}
2017-02-08 19:37:22 +00:00
FDropItem * di = ( FDropItem * ) ClassDataAllocator . Alloc ( sizeof ( FDropItem ) ) ;
2016-03-01 15:47:10 +00:00
di - > Name = type ;
di - > Probability = 255 ;
di - > Amount = - 1 ;
if ( PROP_PARM_COUNT > 1 )
{
PROP_INT_PARM ( prob , 1 ) ;
di - > Probability = prob ;
if ( PROP_PARM_COUNT > 2 )
{
PROP_INT_PARM ( amt , 2 ) ;
di - > Amount = amt ;
}
}
di - > Next = bag . DropItemList ;
bag . DropItemList = di ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( renderstyle , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
static const char * renderstyles [ ] = {
" NONE " , " NORMAL " , " FUZZY " , " SOULTRANS " , " OPTFUZZY " , " STENCIL " ,
2018-11-27 18:43:10 +00:00
" TRANSLUCENT " , " ADD " , " SHADED " , " SHADOW " , " SUBTRACT " , " ADDSTENCIL " ,
" ADDSHADED " , " COLORBLEND " , " COLORADD " , " MULTIPLY " , NULL } ;
2016-03-01 15:47:10 +00:00
static const int renderstyle_values [ ] = {
STYLE_None , STYLE_Normal , STYLE_Fuzzy , STYLE_SoulTrans , STYLE_OptFuzzy ,
STYLE_TranslucentStencil , STYLE_Translucent , STYLE_Add , STYLE_Shaded ,
2018-11-27 18:43:10 +00:00
STYLE_Shadow , STYLE_Subtract , STYLE_AddStencil , STYLE_AddShaded ,
STYLE_ColorBlend , STYLE_ColorAdd , STYLE_Multiply } ;
2016-03-01 15:47:10 +00:00
// make this work for old style decorations, too.
if ( ! strnicmp ( str , " style_ " , 6 ) ) str + = 6 ;
int style = MatchString ( str , renderstyles ) ;
if ( style < 0 ) I_Error ( " Unknown render style '%s' " , str ) ;
defaults - > RenderStyle = LegacyRenderStyles [ renderstyle_values [ style ] ] ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( defaultalpha , 0 , Actor )
{
2016-03-21 11:18:46 +00:00
defaults - > Alpha = gameinfo . gametype = = GAME_Heretic ? HR_SHADOW : HX_SHADOW ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( translation , L , Actor )
{
PROP_INT_PARM ( type , 0 ) ;
if ( type = = 0 )
{
PROP_INT_PARM ( trans , 1 ) ;
2017-04-11 21:29:37 +00:00
int max = 6 ;
2016-03-01 15:47:10 +00:00
if ( trans < 0 | | trans > max )
{
I_Error ( " Translation must be in the range [0,%d] " , max ) ;
}
defaults - > Translation = TRANSLATION ( TRANSLATION_Standard , trans ) ;
}
else
{
FRemapTable CurrentTranslation ;
CurrentTranslation . MakeIdentity ( ) ;
for ( int i = 1 ; i < PROP_PARM_COUNT ; i + + )
{
PROP_STRING_PARM ( str , i ) ;
2016-10-02 11:35:25 +00:00
int tnum ;
if ( i = = 1 & & PROP_PARM_COUNT = = 2 & & ( tnum = R_FindCustomTranslation ( str ) ) ! = - 1 )
2016-03-01 15:47:10 +00:00
{
2016-10-02 11:35:25 +00:00
defaults - > Translation = tnum ;
2016-03-01 15:47:10 +00:00
return ;
}
else
{
2018-03-12 18:14:56 +00:00
// parse all ranges to get a complete list of errors, if more than one range fails.
2018-12-16 08:56:53 +00:00
try
{
CurrentTranslation . AddToTranslation ( str ) ;
}
catch ( CRecoverableError & err )
{
bag . ScriptPosition . Message ( MSG_WARNING , " Error in translation '%s': \n " TEXTCOLOR_CYAN " %s \n " , str , err . GetMessage ( ) ) ;
}
2016-03-01 15:47:10 +00:00
}
}
2020-04-11 10:43:46 +00:00
defaults - > Translation = palMgr . StoreTranslation ( TRANSLATION_Decorate , & CurrentTranslation ) ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( stencilcolor , C , Actor )
{
PROP_COLOR_PARM ( color , 0 ) ;
defaults - > fillcolor = color | ( ColorMatcher . Pick ( RPART ( color ) , GPART ( color ) , BPART ( color ) ) < < 24 ) ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( bloodcolor , C , Actor )
{
PROP_COLOR_PARM ( color , 0 ) ;
2017-03-02 09:26:23 +00:00
defaults - > BloodColor = color ;
defaults - > BloodColor . a = 255 ; // a should not be 0.
defaults - > BloodTranslation = TRANSLATION ( TRANSLATION_Blood , CreateBloodTranslation ( color ) ) ;
2016-03-01 15:47:10 +00:00
}
2017-03-01 19:20:46 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( bloodtype , Sss , Actor )
{
PROP_STRING_PARM ( str , 0 )
PROP_STRING_PARM ( str1 , 1 )
PROP_STRING_PARM ( str2 , 2 )
FName blood = str ;
// normal blood
defaults - > NameVar ( " BloodType " ) = blood ;
if ( PROP_PARM_COUNT > 1 )
{
blood = str1 ;
}
// blood splatter
defaults - > NameVar ( " BloodType2 " ) = blood ;
if ( PROP_PARM_COUNT > 2 )
{
blood = str2 ;
}
// axe blood
defaults - > NameVar ( " BloodType3 " ) = blood ;
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( bouncetype , S , Actor )
{
static const char * names [ ] = { " None " , " Doom " , " Heretic " , " Hexen " , " DoomCompat " , " HereticCompat " , " HexenCompat " , " Grenade " , " Classic " , NULL } ;
static const ActorBounceFlag flags [ ] = { BOUNCE_None ,
BOUNCE_Doom , BOUNCE_Heretic , BOUNCE_Hexen ,
BOUNCE_DoomCompat , BOUNCE_HereticCompat , BOUNCE_HexenCompat ,
BOUNCE_Grenade , BOUNCE_Classic , } ;
PROP_STRING_PARM ( id , 0 ) ;
int match = MatchString ( id , names ) ;
if ( match < 0 )
{
I_Error ( " Unknown bouncetype %s " , id ) ;
match = 0 ;
}
defaults - > BounceFlags & = ~ ( BOUNCE_TypeMask | BOUNCE_UseSeeSound ) ;
defaults - > BounceFlags | = flags [ match ] ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( bouncefactor , F , Actor )
{
2016-03-24 19:43:35 +00:00
PROP_DOUBLE_PARM ( id , 0 ) ;
defaults - > bouncefactor = clamp < double > ( id , 0 , 1 ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( wallbouncefactor , F , Actor )
{
2016-03-24 19:43:35 +00:00
PROP_DOUBLE_PARM ( id , 0 ) ;
defaults - > wallbouncefactor = clamp < double > ( id , 0 , 1 ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( damagetype , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
if ( ! stricmp ( str , " Normal " ) ) defaults - > DamageType = NAME_None ;
else defaults - > DamageType = str ;
}
//==========================================================================
//==========================================================================
DEFINE_PROPERTY ( paintype , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
if ( ! stricmp ( str , " Normal " ) ) defaults - > PainType = NAME_None ;
else defaults - > PainType = str ;
}
//==========================================================================
//==========================================================================
DEFINE_PROPERTY ( deathtype , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
if ( ! stricmp ( str , " Normal " ) ) defaults - > DeathType = NAME_None ;
else defaults - > DeathType = str ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( damagefactor , ZF , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
2016-03-21 23:06:58 +00:00
PROP_DOUBLE_PARM ( id , 1 ) ;
2016-03-01 15:47:10 +00:00
2018-08-18 23:14:15 +00:00
if ( str = = nullptr )
2016-03-01 15:47:10 +00:00
{
defaults - > DamageFactor = id ;
}
else
{
2018-08-18 23:14:15 +00:00
FName dmgType = NAME_None ;
if ( stricmp ( str , " Normal " ) ) dmgType = str ;
2016-03-01 15:47:10 +00:00
info - > SetDamageFactor ( dmgType , id ) ;
}
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( decal , S , Actor )
{
PROP_STRING_PARM ( str , 0 ) ;
2020-04-11 10:58:38 +00:00
defaults - > DecalGenerator = ( FDecalBase * ) ( intptr_t ) FName ( str ) . GetIndex ( ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( poisondamage , Iii , Actor )
{
PROP_INT_PARM ( poisondamage , 0 ) ;
PROP_INT_PARM ( poisonduration , 1 ) ;
PROP_INT_PARM ( poisonperiod , 2 ) ;
defaults - > PoisonDamage = poisondamage ;
if ( PROP_PARM_COUNT = = 1 )
{
defaults - > PoisonDuration = INT_MIN ;
}
else
{
defaults - > PoisonDuration = poisonduration ;
if ( PROP_PARM_COUNT > 2 )
defaults - > PoisonPeriod = poisonperiod ;
else
defaults - > PoisonPeriod = 0 ;
}
}
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( gravity , F , Actor )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
PROP_DOUBLE_PARM ( i , 0 ) ;
2016-03-01 15:47:10 +00:00
2017-03-19 10:30:28 +00:00
if ( i < 0 ) I_Error ( " Gravity must not be negative. " ) ;
defaults - > Gravity = i ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( spriteangle , F , Actor )
2016-03-01 15:47:10 +00:00
{
2016-03-24 20:31:04 +00:00
PROP_DOUBLE_PARM ( i , 0 ) ;
2017-03-19 10:30:28 +00:00
defaults - > SpriteAngle = i ;
2016-03-01 15:47:10 +00:00
}
2017-02-27 10:22:51 +00:00
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( friction , F , Actor )
2017-02-27 10:22:51 +00:00
{
PROP_DOUBLE_PARM ( i , 0 ) ;
2017-03-19 10:30:28 +00:00
if ( i < 0 ) I_Error ( " Friction must not be negative. " ) ;
defaults - > Friction = i ;
2017-02-27 18:46:27 +00:00
}
2016-03-01 15:47:10 +00:00
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( clearflags , 0 , Actor )
2016-03-01 15:47:10 +00:00
{
defaults - > flags = 0 ;
defaults - > flags2 & = MF2_ARGSDEFINED ; // this flag must not be cleared
defaults - > flags3 = 0 ;
defaults - > flags4 = 0 ;
defaults - > flags5 = 0 ;
defaults - > flags6 = 0 ;
defaults - > flags7 = 0 ;
2017-05-14 16:26:31 +00:00
defaults - > flags8 = 0 ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( monster , 0 , Actor )
{
// sets the standard flags for a monster
defaults - > flags | = MF_SHOOTABLE | MF_COUNTKILL | MF_SOLID ;
defaults - > flags2 | = MF2_PUSHWALL | MF2_MCROSS | MF2_PASSMOBJ ;
defaults - > flags3 | = MF3_ISMONSTER ;
defaults - > flags4 | = MF4_CANUSEWALLS ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( projectile , 0 , Actor )
{
// sets the standard flags for a projectile
defaults - > flags | = MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF | MF_MISSILE ;
defaults - > flags2 | = MF2_IMPACT | MF2_PCROSS | MF2_NOTELEPORT ;
if ( gameinfo . gametype & GAME_Raven ) defaults - > flags5 | = MF5_BLOODSPLATTER ;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY ( activation , N , Actor )
{
// How the thing behaves when activated by death, USESPECIAL or BUMPSPECIAL
PROP_INT_PARM ( val , 0 ) ;
2017-03-19 10:30:28 +00:00
defaults - > activationtype = val ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( designatedteam , I , Actor )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
PROP_INT_PARM ( val , 0 ) ;
if ( val < 0 | | ( val > = ( signed ) Teams . Size ( ) & & val ! = TEAM_NONE ) )
I_Error ( " Invalid team designation. \n " ) ;
defaults - > DesignatedTeam = val ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2017-03-19 10:30:28 +00:00
// [BB]
2016-03-01 15:47:10 +00:00
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( visibletoteam , I , Actor )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
PROP_INT_PARM ( i , 0 ) ;
defaults - > VisibleToTeam = i + 1 ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2017-03-19 10:30:28 +00:00
// [BB]
2016-03-01 15:47:10 +00:00
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( visibletoplayerclass , Ssssssssssssssssssss , Actor )
2016-03-01 15:47:10 +00:00
{
2017-04-11 22:07:41 +00:00
info - > ActorInfo ( ) - > VisibleToPlayerClass . Clear ( ) ;
2017-03-19 10:30:28 +00:00
for ( int i = 0 ; i < PROP_PARM_COUNT ; + + i )
{
PROP_STRING_PARM ( n , i ) ;
if ( * n ! = 0 )
2019-01-03 21:05:49 +00:00
info - > ActorInfo ( ) - > VisibleToPlayerClass . Push ( FindClassTentative ( n , RUNTIME_CLASS ( AActor ) ) ) ;
2017-03-19 10:30:28 +00:00
}
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
DEFINE_PROPERTY ( distancecheck , S , Actor )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
PROP_STRING_PARM ( cvar , 0 ) ;
FBaseCVar * scratch ;
FBaseCVar * cv = FindCVar ( cvar , & scratch ) ;
if ( cv = = NULL )
{
I_Error ( " CVar %s not defined " , cvar ) ;
}
else if ( cv - > GetRealType ( ) = = CVAR_Int )
{
2017-04-12 08:29:04 +00:00
info - > ActorInfo ( ) - > distancecheck = static_cast < FIntCVar * > ( cv ) ;
2017-03-19 10:30:28 +00:00
}
else
{
I_Error ( " CVar %s must of type Int " , cvar ) ;
}
2016-03-01 15:47:10 +00:00
}
2017-07-29 17:59:36 +00:00
2016-03-01 15:47:10 +00:00
//==========================================================================
//
2017-03-19 10:30:28 +00:00
// Special inventory properties
//
2016-03-01 15:47:10 +00:00
//==========================================================================
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( restrictedto , Ssssssssssssssssssss , Inventory )
2016-03-01 15:47:10 +00:00
{
2017-04-11 13:11:13 +00:00
auto restrictarray = ( TArray < PClassActor * > * ) defaults - > ScriptVar ( NAME_RestrictedToPlayerClass , nullptr ) ;
restrictarray - > Clear ( ) ;
2017-03-19 10:30:28 +00:00
for ( int i = 0 ; i < PROP_PARM_COUNT ; + + i )
{
PROP_STRING_PARM ( n , i ) ;
if ( * n ! = 0 )
2019-01-03 21:05:49 +00:00
restrictarray - > Push ( FindClassTentative ( n , RUNTIME_CLASS ( AActor ) ) ) ;
2017-03-19 10:30:28 +00:00
}
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( forbiddento , Ssssssssssssssssssss , Inventory )
2016-03-01 15:47:10 +00:00
{
2017-04-11 13:11:13 +00:00
auto forbidarray = ( TArray < PClassActor * > * ) defaults - > ScriptVar ( NAME_ForbiddenToPlayerClass , nullptr ) ;
forbidarray - > Clear ( ) ;
2017-03-19 10:30:28 +00:00
for ( int i = 0 ; i < PROP_PARM_COUNT ; + + i )
{
PROP_STRING_PARM ( n , i ) ;
if ( * n ! = 0 )
2019-01-03 21:05:49 +00:00
forbidarray - > Push ( FindClassTentative ( n , RUNTIME_CLASS ( AActor ) ) ) ;
2017-03-19 10:30:28 +00:00
}
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2017-03-19 10:30:28 +00:00
static void SetIcon ( FTextureID & icon , Baggage & bag , const char * i )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
if ( i = = NULL | | i [ 0 ] = = ' \0 ' )
{
icon . SetNull ( ) ;
}
else
{
2018-03-25 18:26:16 +00:00
icon = TexMan . CheckForTexture ( i , ETextureType : : MiscPatch ) ;
2017-03-19 10:30:28 +00:00
if ( ! icon . isValid ( ) )
{
// Don't print warnings if the item is for another game or if this is a shareware IWAD.
// Strife's teaser doesn't contain all the icon graphics of the full game.
2017-04-11 21:29:37 +00:00
if ( ( bag . Info - > ActorInfo ( ) - > GameFilter = = GAME_Any | | bag . Info - > ActorInfo ( ) - > GameFilter & gameinfo . gametype ) & &
2020-04-11 11:24:34 +00:00
! ( gameinfo . flags & GI_SHAREWARE ) & & fileSystem . GetLumpFile ( bag . Lumpnum ) ! = 0 )
2017-03-19 10:30:28 +00:00
{
bag . ScriptPosition . Message ( MSG_WARNING ,
" Icon '%s' for '%s' not found \n " , i , bag . Info - > TypeName . GetChars ( ) ) ;
}
}
}
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( icon , S , Inventory )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
PROP_STRING_PARM ( i , 0 ) ;
2018-12-03 23:22:26 +00:00
SetIcon ( defaults - > TextureIDVar ( NAME_Icon ) , bag , i ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( althudicon , S , Inventory )
2016-03-01 15:47:10 +00:00
{
2017-03-19 10:30:28 +00:00
PROP_STRING_PARM ( i , 0 ) ;
2018-12-03 23:22:26 +00:00
SetIcon ( defaults - > TextureIDVar ( NAME_AltHUDIcon ) , bag , i ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( defmaxamount , 0 , Inventory )
2016-03-01 15:47:10 +00:00
{
2018-12-03 23:22:26 +00:00
defaults - > IntVar ( NAME_MaxAmount ) = gameinfo . definventorymaxamount ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2017-03-19 10:30:28 +00:00
// Dummy for Skulltag compatibility...
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( pickupannouncerentry , S , Inventory )
2016-03-01 15:47:10 +00:00
{
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( defaultkickback , 0 , Weapon )
2016-03-01 15:47:10 +00:00
{
2018-11-25 07:17:37 +00:00
defaults - > IntVar ( NAME_Kickback ) = gameinfo . defKickback ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( bobstyle , S , Weapon )
2016-03-01 15:47:10 +00:00
{
static const char * names [ ] = { " Normal " , " Inverse " , " Alpha " , " InverseAlpha " , " Smooth " , " InverseSmooth " , NULL } ;
2018-11-25 07:17:37 +00:00
static const EBobStyle styles [ ] = { EBobStyle : : BobNormal ,
EBobStyle : : BobInverse , EBobStyle : : BobAlpha , EBobStyle : : BobInverseAlpha ,
EBobStyle : : BobSmooth , EBobStyle : : BobInverseSmooth , } ;
2016-03-01 15:47:10 +00:00
PROP_STRING_PARM ( id , 0 ) ;
int match = MatchString ( id , names ) ;
if ( match < 0 )
{
I_Error ( " Unknown bobstyle %s " , id ) ;
match = 0 ;
}
2018-11-25 07:17:37 +00:00
defaults - > IntVar ( NAME_BobStyle ) = ( int ) styles [ match ] ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( preferredskin , S , Weapon )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
// NoOp - only for Skulltag compatibility
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY_PREFIX ( powerup , color , C_f , Inventory )
2016-03-01 15:47:10 +00:00
{
static const char * specialcolormapnames [ ] = {
" INVERSEMAP " , " GOLDMAP " , " REDMAP " , " GREENMAP " , " BLUEMAP " , NULL } ;
int alpha ;
PalEntry * pBlendColor ;
2017-02-08 14:47:22 +00:00
bool isgiver = info - > IsDescendantOf ( NAME_PowerupGiver ) ;
2016-03-01 15:47:10 +00:00
2017-02-08 14:47:22 +00:00
if ( info - > IsDescendantOf ( NAME_Powerup ) | | isgiver )
2016-03-01 15:47:10 +00:00
{
2017-01-18 09:33:03 +00:00
pBlendColor = & defaults - > ColorVar ( NAME_BlendColor ) ;
2016-03-01 15:47:10 +00:00
}
else
{
I_Error ( " \" powerup.color \" requires an actor of type \" Powerup \" \n " ) ;
return ;
}
PROP_INT_PARM ( mode , 0 ) ;
PROP_INT_PARM ( color , 1 ) ;
if ( mode = = 1 )
{
PROP_STRING_PARM ( name , 1 ) ;
// We must check the old special colormap names for compatibility
int v = MatchString ( name , specialcolormapnames ) ;
if ( v > = 0 )
{
* pBlendColor = MakeSpecialColormap ( v ) ;
return ;
}
2017-01-17 23:11:04 +00:00
else if ( ! stricmp ( name , " none " ) & & isgiver )
2016-03-01 15:47:10 +00:00
{
* pBlendColor = MakeSpecialColormap ( 65535 ) ;
return ;
}
2016-12-03 15:27:53 +00:00
color = V_GetColor ( NULL , name , & bag . ScriptPosition ) ;
2016-03-01 15:47:10 +00:00
}
if ( PROP_PARM_COUNT > 2 )
{
PROP_DOUBLE_PARM ( falpha , 2 ) ;
alpha = int ( falpha * 255 ) ;
}
else alpha = 255 / 3 ;
alpha = clamp < int > ( alpha , 0 , 255 ) ;
if ( alpha ! = 0 ) * pBlendColor = MAKEARGB ( alpha , 0 , 0 , 0 ) | color ;
else * pBlendColor = 0 ;
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY_PREFIX ( powerup , colormap , FFFfff , Inventory )
2016-03-01 15:47:10 +00:00
{
2017-01-18 09:33:03 +00:00
PalEntry BlendColor ;
2016-03-01 15:47:10 +00:00
2017-02-08 14:47:22 +00:00
if ( ! info - > IsDescendantOf ( NAME_Powerup ) & & ! info - > IsDescendantOf ( NAME_PowerupGiver ) )
2016-03-01 15:47:10 +00:00
{
I_Error ( " \" powerup.colormap \" requires an actor of type \" Powerup \" \n " ) ;
return ;
}
if ( PROP_PARM_COUNT = = 3 )
{
PROP_FLOAT_PARM ( r , 0 ) ;
PROP_FLOAT_PARM ( g , 1 ) ;
PROP_FLOAT_PARM ( b , 2 ) ;
2017-01-18 09:33:03 +00:00
BlendColor = MakeSpecialColormap ( AddSpecialColormap ( 0 , 0 , 0 , r , g , b ) ) ;
2016-03-01 15:47:10 +00:00
}
else if ( PROP_PARM_COUNT = = 6 )
{
PROP_FLOAT_PARM ( r1 , 0 ) ;
PROP_FLOAT_PARM ( g1 , 1 ) ;
PROP_FLOAT_PARM ( b1 , 2 ) ;
PROP_FLOAT_PARM ( r2 , 3 ) ;
PROP_FLOAT_PARM ( g2 , 4 ) ;
PROP_FLOAT_PARM ( b2 , 5 ) ;
2017-01-18 09:33:03 +00:00
BlendColor = MakeSpecialColormap ( AddSpecialColormap ( r1 , g1 , b1 , r2 , g2 , b2 ) ) ;
2016-03-01 15:47:10 +00:00
}
else
{
I_Error ( " \" power.colormap \" must have either 3 or 6 parameters \n " ) ;
}
2017-01-18 09:33:03 +00:00
defaults - > ColorVar ( NAME_BlendColor ) = BlendColor ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY_PREFIX ( powerup , duration , I , Inventory )
2016-03-01 15:47:10 +00:00
{
2017-02-08 14:47:22 +00:00
if ( ! info - > IsDescendantOf ( NAME_Powerup ) & & ! info - > IsDescendantOf ( NAME_PowerupGiver ) )
2016-03-01 15:47:10 +00:00
{
I_Error ( " \" powerup.duration \" requires an actor of type \" Powerup \" \n " ) ;
return ;
}
PROP_INT_PARM ( i , 0 ) ;
2017-01-18 09:33:03 +00:00
defaults - > IntVar ( NAME_EffectTics ) = ( i > = 0 ) ? i : - i * TICRATE ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY_PREFIX ( powerup , type , S , PowerupGiver )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
// Yuck! What was I thinking when I decided to prepend "Power" to the name?
// Now it's too late to change it...
PClassActor * cls = PClass : : FindActor ( str ) ;
2017-01-18 09:33:03 +00:00
auto pow = PClass : : FindActor ( NAME_Powerup ) ;
if ( cls = = nullptr | | ! cls - > IsDescendantOf ( pow ) )
2016-03-01 15:47:10 +00:00
{
2016-11-07 10:53:49 +00:00
if ( bag . fromDecorate )
{
FString st ;
st . Format ( " %s%s " , strnicmp ( str , " power " , 5 ) ? " Power " : " " , str ) ;
2017-01-18 09:33:03 +00:00
cls = FindClassTentative ( st , pow ) ;
2016-11-07 10:53:49 +00:00
}
else
{
I_Error ( " Unknown powerup type %s " , str ) ;
}
2016-03-01 15:47:10 +00:00
}
2017-01-18 17:46:24 +00:00
defaults - > PointerVar < PClassActor > ( NAME_PowerupType ) = cls ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
// [GRB] Special player properties
//
//==========================================================================
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , displayname , S , PlayerPawn )
{
PROP_STRING_PARM ( str , 0 ) ;
2017-04-11 22:07:41 +00:00
info - > ActorInfo ( ) - > DisplayName = str ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , soundclass , S , PlayerPawn )
{
PROP_STRING_PARM ( str , 0 ) ;
FString tmp = str ;
tmp . ReplaceChars ( ' ' , ' _ ' ) ;
2019-01-03 09:06:45 +00:00
defaults - > NameVar ( NAME_SoundClass ) = tmp . IsNotEmpty ( ) ? FName ( tmp ) : NAME_None ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , face , S , PlayerPawn )
{
PROP_STRING_PARM ( str , 0 ) ;
FString tmp = str ;
2019-01-03 09:06:45 +00:00
if ( tmp . Len ( ) = = 0 ) defaults - > NameVar ( NAME_Face ) = NAME_None ;
2017-02-08 15:42:13 +00:00
else
2016-03-01 15:47:10 +00:00
{
2017-02-08 15:42:13 +00:00
tmp . ToUpper ( ) ;
bool valid = ( tmp . Len ( ) = = 3 & &
( ( ( tmp [ 0 ] > = ' A ' ) & & ( tmp [ 0 ] < = ' Z ' ) ) | | ( ( tmp [ 0 ] > = ' 0 ' ) & & ( tmp [ 0 ] < = ' 9 ' ) ) ) & &
( ( ( tmp [ 1 ] > = ' A ' ) & & ( tmp [ 1 ] < = ' Z ' ) ) | | ( ( tmp [ 1 ] > = ' 0 ' ) & & ( tmp [ 1 ] < = ' 9 ' ) ) ) & &
( ( ( tmp [ 2 ] > = ' A ' ) & & ( tmp [ 2 ] < = ' Z ' ) ) | | ( ( tmp [ 2 ] > = ' 0 ' ) & & ( tmp [ 2 ] < = ' 9 ' ) ) )
) ;
if ( ! valid )
{
bag . ScriptPosition . Message ( MSG_OPTERROR ,
" Invalid face '%s' for '%s'; \n STF replacement codes must be 3 alphanumeric characters. \n " ,
tmp . GetChars ( ) , info - > TypeName . GetChars ( ) ) ;
}
2019-01-03 09:06:45 +00:00
defaults - > NameVar ( NAME_Face ) = tmp ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , colorrange , I_I , PlayerPawn )
{
PROP_INT_PARM ( start , 0 ) ;
PROP_INT_PARM ( end , 1 ) ;
if ( start > end )
2020-04-11 10:31:02 +00:00
std : : swap ( start , end ) ;
2016-03-01 15:47:10 +00:00
2019-01-02 21:13:25 +00:00
defaults - > IntVar ( NAME_ColorRangeStart ) = start ;
defaults - > IntVar ( NAME_ColorRangeEnd ) = end ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , colorset , ISIIIiiiiiiiiiiiiiiiiiiiiiiii , PlayerPawn )
{
PROP_INT_PARM ( setnum , 0 ) ;
PROP_STRING_PARM ( setname , 1 ) ;
PROP_INT_PARM ( rangestart , 2 ) ;
PROP_INT_PARM ( rangeend , 3 ) ;
PROP_INT_PARM ( representative_color , 4 ) ;
FPlayerColorSet color ;
color . Name = setname ;
color . Lump = - 1 ;
color . FirstColor = rangestart ;
color . LastColor = rangeend ;
color . RepresentativeColor = representative_color ;
color . NumExtraRanges = 0 ;
if ( PROP_PARM_COUNT > 5 )
{
int count = PROP_PARM_COUNT - 5 ;
int start = 5 ;
while ( count > = 4 )
{
PROP_INT_PARM ( range_start , start + 0 ) ;
PROP_INT_PARM ( range_end , start + 1 ) ;
PROP_INT_PARM ( first_color , start + 2 ) ;
PROP_INT_PARM ( last_color , start + 3 ) ;
int extra = color . NumExtraRanges + + ;
assert ( extra < ( int ) countof ( color . Extra ) ) ;
color . Extra [ extra ] . RangeStart = range_start ;
color . Extra [ extra ] . RangeEnd = range_end ;
color . Extra [ extra ] . FirstColor = first_color ;
color . Extra [ extra ] . LastColor = last_color ;
count - = 4 ;
start + = 4 ;
}
if ( count ! = 0 )
{
2016-10-10 22:56:47 +00:00
bag . ScriptPosition . Message ( MSG_OPTERROR , " Extra ranges require 4 parameters each. \n " ) ;
2016-03-01 15:47:10 +00:00
}
}
if ( setnum < 0 )
{
2016-10-10 22:56:47 +00:00
bag . ScriptPosition . Message ( MSG_OPTERROR , " Color set number must not be negative. \n " ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2017-02-08 18:10:11 +00:00
ColorSets . Push ( std : : make_tuple ( info , setnum , color ) ) ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , colorsetfile , ISSI , PlayerPawn )
{
PROP_INT_PARM ( setnum , 0 ) ;
PROP_STRING_PARM ( setname , 1 ) ;
PROP_STRING_PARM ( rangefile , 2 ) ;
PROP_INT_PARM ( representative_color , 3 ) ;
FPlayerColorSet color ;
color . Name = setname ;
2020-04-11 11:24:34 +00:00
color . Lump = fileSystem . CheckNumForName ( rangefile ) ;
2016-03-01 15:47:10 +00:00
color . RepresentativeColor = representative_color ;
color . NumExtraRanges = 0 ;
if ( setnum < 0 )
{
2016-10-10 22:56:47 +00:00
bag . ScriptPosition . Message ( MSG_OPTERROR , " Color set number must not be negative. \n " ) ;
2016-03-01 15:47:10 +00:00
}
else if ( color . Lump > = 0 )
{
2017-02-08 18:10:11 +00:00
ColorSets . Push ( std : : make_tuple ( info , setnum , color ) ) ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , clearcolorset , I , PlayerPawn )
{
PROP_INT_PARM ( setnum , 0 ) ;
if ( setnum < 0 )
{
2016-10-10 22:56:47 +00:00
bag . ScriptPosition . Message ( MSG_OPTERROR , " Color set number must not be negative. \n " ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2017-02-08 18:10:11 +00:00
FPlayerColorSet color ;
memset ( & color , 0 , sizeof ( color ) ) ;
ColorSets . Push ( std : : make_tuple ( info , setnum , color ) ) ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , spawnclass , L , PlayerPawn )
{
PROP_INT_PARM ( type , 0 ) ;
2019-01-03 17:01:58 +00:00
int & SpawnMask = defaults - > IntVar ( NAME_SpawnMask ) ;
2016-03-01 15:47:10 +00:00
if ( type = = 0 )
{
PROP_INT_PARM ( val , 1 ) ;
2019-01-03 17:01:58 +00:00
if ( val > 0 ) SpawnMask | = 1 < < ( val - 1 ) ;
2016-03-01 15:47:10 +00:00
}
else
{
for ( int i = 1 ; i < PROP_PARM_COUNT ; i + + )
{
PROP_STRING_PARM ( str , i ) ;
if ( ! stricmp ( str , " Any " ) )
2019-01-03 17:01:58 +00:00
SpawnMask = 0 ;
2016-03-01 15:47:10 +00:00
else if ( ! stricmp ( str , " Fighter " ) )
2019-01-03 17:01:58 +00:00
SpawnMask | = 1 ;
2016-03-01 15:47:10 +00:00
else if ( ! stricmp ( str , " Cleric " ) )
2019-01-03 17:01:58 +00:00
SpawnMask | = 2 ;
2016-03-01 15:47:10 +00:00
else if ( ! stricmp ( str , " Mage " ) )
2019-01-03 17:01:58 +00:00
SpawnMask | = 4 ;
2016-03-01 15:47:10 +00:00
}
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , forwardmove , F_f , PlayerPawn )
{
2016-03-19 23:54:18 +00:00
PROP_DOUBLE_PARM ( m , 0 ) ;
2019-01-03 07:27:41 +00:00
defaults - > FloatVar ( NAME_ForwardMove1 ) = defaults - > FloatVar ( NAME_ForwardMove2 ) = m ;
2016-03-01 15:47:10 +00:00
if ( PROP_PARM_COUNT > 1 )
{
2016-03-19 23:54:18 +00:00
PROP_DOUBLE_PARM ( m2 , 1 ) ;
2019-01-03 07:27:41 +00:00
defaults - > FloatVar ( NAME_ForwardMove2 ) = m2 ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , sidemove , F_f , PlayerPawn )
{
2016-03-19 23:54:18 +00:00
PROP_DOUBLE_PARM ( m , 0 ) ;
2019-01-03 07:27:41 +00:00
defaults - > FloatVar ( NAME_SideMove1 ) = defaults - > FloatVar ( NAME_SideMove2 ) = m ;
2016-03-01 15:47:10 +00:00
if ( PROP_PARM_COUNT > 1 )
{
2016-03-19 23:54:18 +00:00
PROP_DOUBLE_PARM ( m2 , 1 ) ;
2019-01-03 07:27:41 +00:00
defaults - > FloatVar ( NAME_SideMove2 ) = m2 ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , scoreicon , S , PlayerPawn )
{
PROP_STRING_PARM ( z , 0 ) ;
2019-01-03 17:01:58 +00:00
auto icon = TexMan . CheckForTexture ( z , ETextureType : : MiscPatch ) ;
defaults - > IntVar ( NAME_ScoreIcon ) = icon . GetIndex ( ) ;
if ( ! icon . isValid ( ) )
2016-03-01 15:47:10 +00:00
{
bag . ScriptPosition . Message ( MSG_WARNING ,
" Icon '%s' for '%s' not found \n " , z , info - > TypeName . GetChars ( ) ) ;
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , crouchsprite , S , PlayerPawn )
{
PROP_STRING_PARM ( z , 0 ) ;
if ( strlen ( z ) = = 4 )
{
2019-01-03 13:35:17 +00:00
defaults - > IntVar ( NAME_crouchsprite ) = GetSpriteIndex ( z ) ;
2016-03-01 15:47:10 +00:00
}
else if ( * z = = 0 )
{
2019-01-03 13:35:17 +00:00
defaults - > IntVar ( NAME_crouchsprite ) = 0 ;
2016-03-01 15:47:10 +00:00
}
else
{
I_Error ( " Sprite name must have exactly 4 characters " ) ;
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , damagescreencolor , Cfs , PlayerPawn )
{
PROP_COLOR_PARM ( c , 0 ) ;
PalEntry color = c ;
if ( PROP_PARM_COUNT < 3 ) // Because colors count as 2 parms
{
color . a = 255 ;
2019-01-03 11:47:34 +00:00
defaults - > IntVar ( NAME_DamageFade ) = color ;
2016-03-01 15:47:10 +00:00
}
else if ( PROP_PARM_COUNT < 4 )
{
PROP_DOUBLE_PARM ( a , 2 ) ;
2017-03-08 17:44:37 +00:00
color . a = uint8_t ( 255 * clamp < double > ( a , 0.f , 1.f ) ) ;
2019-01-03 11:47:34 +00:00
defaults - > IntVar ( NAME_DamageFade ) = color ;
2016-03-01 15:47:10 +00:00
}
else
{
PROP_DOUBLE_PARM ( a , 2 ) ;
PROP_STRING_PARM ( type , 3 ) ;
2017-03-08 17:44:37 +00:00
color . a = uint8_t ( 255 * clamp < double > ( a , 0.f , 1.f ) ) ;
2017-02-08 18:10:11 +00:00
PainFlashes . Push ( std : : make_tuple ( info , type , color ) ) ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
// [GRB] Store start items in drop item list
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , startitem , S_i , PlayerPawn )
{
PROP_STRING_PARM ( str , 0 ) ;
// create a linked list of startitems
if ( ! bag . DropItemSet )
{
bag . DropItemSet = true ;
bag . DropItemList = NULL ;
}
2017-02-08 19:37:22 +00:00
FDropItem * di = ( FDropItem * ) ClassDataAllocator . Alloc ( sizeof ( FDropItem ) ) ;
2016-03-01 15:47:10 +00:00
di - > Name = str ;
di - > Probability = 255 ;
di - > Amount = 1 ;
if ( PROP_PARM_COUNT > 1 )
{
PROP_INT_PARM ( amt , 1 ) ;
di - > Amount = amt ;
}
di - > Next = bag . DropItemList ;
bag . DropItemList = di ;
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , hexenarmor , FFFFF , PlayerPawn )
{
for ( int i = 0 ; i < 5 ; i + + )
{
2016-03-22 15:35:41 +00:00
PROP_DOUBLE_PARM ( val , i ) ;
2019-01-03 07:27:41 +00:00
auto hexarmor = & defaults - > FloatVar ( NAME_HexenArmor ) ;
hexarmor [ i ] = val ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX ( player , weaponslot , ISsssssssssssssssssssssssssssssssssssssssssss , PlayerPawn )
{
PROP_INT_PARM ( slot , 0 ) ;
if ( slot < 0 | | slot > 9 )
{
I_Error ( " Slot must be between 0 and 9. " ) ;
}
else
{
FString weapons ;
for ( int i = 1 ; i < PROP_PARM_COUNT ; + + i )
{
PROP_STRING_PARM ( str , i ) ;
weapons < < ' ' < < str ;
}
2019-01-03 09:06:45 +00:00
FName * slots = & defaults - > NameVar ( NAME_Slot ) ;
slots [ slot ] = weapons . IsEmpty ( ) ? NAME_None : FName ( weapons ) ;
2016-03-01 15:47:10 +00:00
}
}
//==========================================================================
2016-11-23 21:34:17 +00:00
// (non-fatal with non-existent types only in DECORATE)
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( playerclass , S , MorphProjectile )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2019-01-03 21:05:49 +00:00
defaults - > PointerVar < PClassActor > ( NAME_PlayerClass ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2016-11-23 21:34:17 +00:00
// (non-fatal with non-existent types only in DECORATE)
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( monsterclass , S , MorphProjectile )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2017-01-20 00:11:36 +00:00
defaults - > PointerVar < PClassActor > ( NAME_MonsterClass ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( duration , I , MorphProjectile )
2016-03-01 15:47:10 +00:00
{
PROP_INT_PARM ( i , 0 ) ;
2017-01-20 00:11:36 +00:00
defaults - > IntVar ( NAME_Duration ) = i > = 0 ? i : - i * TICRATE ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( morphstyle , M , MorphProjectile )
2016-03-01 15:47:10 +00:00
{
PROP_INT_PARM ( i , 0 ) ;
2017-01-20 00:11:36 +00:00
defaults - > IntVar ( NAME_MorphStyle ) = i ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2016-11-23 21:34:17 +00:00
// (non-fatal with non-existent types only in DECORATE)
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( morphflash , S , MorphProjectile )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2017-01-20 00:11:36 +00:00
defaults - > PointerVar < PClassActor > ( NAME_MorphFlash ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( unmorphflash , S , MorphProjectile )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2017-01-20 00:11:36 +00:00
defaults - > PointerVar < PClassActor > ( NAME_UnMorphFlash ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2016-11-23 21:34:17 +00:00
// (non-fatal with non-existent types only in DECORATE)
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( playerclass , S , PowerMorph )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2019-01-03 21:05:49 +00:00
defaults - > PointerVar < PClassActor > ( NAME_PlayerClass ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( morphstyle , M , PowerMorph )
2016-03-01 15:47:10 +00:00
{
PROP_INT_PARM ( i , 0 ) ;
2017-01-18 17:46:24 +00:00
defaults - > IntVar ( NAME_MorphStyle ) = i ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2016-11-23 21:34:17 +00:00
// (non-fatal with non-existent types only in DECORATE)
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( morphflash , S , PowerMorph )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2017-01-18 17:46:24 +00:00
defaults - > PointerVar < PClassActor > ( NAME_MorphFlash ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
2016-11-23 21:34:17 +00:00
// (non-fatal with non-existent types only in DECORATE)
2016-03-01 15:47:10 +00:00
//==========================================================================
2019-01-03 21:05:49 +00:00
DEFINE_CLASS_PROPERTY ( unmorphflash , S , PowerMorph )
2016-03-01 15:47:10 +00:00
{
PROP_STRING_PARM ( str , 0 ) ;
2017-01-18 17:46:24 +00:00
defaults - > PointerVar < PClassActor > ( NAME_UnMorphFlash ) = FindClassTentative ( str , RUNTIME_CLASS ( AActor ) , bag . fromDecorate ) ;
2016-03-01 15:47:10 +00:00
}
2019-01-31 01:05:16 +00:00
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY ( type , S , DynamicLight )
{
PROP_STRING_PARM ( str , 0 ) ;
static const char * ltype_names [ ] = {
" Point " , " Pulse " , " Flicker " , " Sector " , " RandomFlicker " , " ColorPulse " , " ColorFlicker " , " RandomColorFlicker " , nullptr } ;
static const int ltype_values [ ] = {
PointLight , PulseLight , FlickerLight , SectorLight , RandomFlickerLight , ColorPulseLight , ColorFlickerLight , RandomColorFlickerLight } ;
int style = MatchString ( str , ltype_names ) ;
if ( style < 0 ) I_Error ( " Unknown light type '%s' " , str ) ;
defaults - > IntVar ( NAME_lighttype ) = ltype_values [ style ] ;
}