Update to ZDoom r1165:

- Fixed: The chat sound for Strife was misnamed in the gameinfo structure.
- fixed a few DECORATE bugs.
- Changed the action function declaration parser so that optional parameters
  can be given a default value. The 'optional' keyword is no longer needed
  and was removed, as well as 'evalnot'.
- Restructured the action function interface to remove the dependence on
  the global CallingState variable.
- Changed handling of AUTOPAGE texture so that it is properly inserted into
  the texture manager even if it is from Raven's IWADs.
- Removed code related to internal ActorInfo definitions from dobjtype.cpp.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@156 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2008-08-12 23:22:08 +00:00
parent 078314ac80
commit cd15b90021
52 changed files with 1613 additions and 1600 deletions

View file

@ -1,3 +1,49 @@
August 12, 2008 (Changes by Graf Zahl)
- Fixed: The chat sound for Strife was misnamed in the gameinfo structure.
- fixed a few DECORATE bugs.
- Changed the action function declaration parser so that optional parameters
can be given a default value. The 'optional' keyword is no longer needed
and was removed, as well as 'evalnot'.
- Restructured the action function interface to remove the dependence on
the global CallingState variable.
- Changed handling of AUTOPAGE texture so that it is properly inserted into
the texture manager even if it is from Raven's IWADs.
- Removed code related to internal ActorInfo definitions from dobjtype.cpp.
- removed unneeded file dehackedactions.h
August 11, 2008
- Ported asm_x86_64/tmap3.nas to AT&T syntax so it can be compiled with gas.
After finding out that gas does have directives to describe the .eh_frame
metadata, I figured that would be significantly easier and quicker than
trying to locate all the scattered docs needed to construct it by hand.
Unfortunately, this now means I have to maintain two versions of exactly
the same code. :(
August 11, 2008 (Changes by Graf Zahl)
- Removed 'eval' modifier from DECORATE. All int, float and bool parameters are
'eval' now by default.
- Did a thorough check of all DECORATE conversions and fixed the errors I found.
August 10, 2008 (Changes by Graf Zahl)
- Macro-fied all access to action functions.
- Changed action function definition so that they have to be defined with a
DEFINE_ACTION_FUNCTION macro. This should make it easier to improve the
whole system.
- Removed DECORATE's ParseClass because it was only used to add data to fully
internal actor classes which no longer exist.
- Changed the state structure so that the Tics value doesn't need to be hacked
into misc1 with SF_BIGTIC anymore.
- Changed sprite processing so that sprite names are converted to indices
during parsing so that an additional postprocessing step is no longer needed.
- Fixed: Sprite names in DECORATE were case sensitive.
- Exported AActor's defaults to DECORATE and removed all code for the
internal property parser which is no longer needed.
- Converted the Heresiarch to DECORATE.
- Added an Active and Inactive state for monsters.
- Made the speed a parameter to A_RaiseMobj and A_SinkMobj and deleted
GetRaiseSpeed and GetSinkSpeed.
- Added some remaining DECORATE conversions for Hexen by Karate Chris.
August 10, 2008 August 10, 2008
- Changed Windows to use the performance counter instead of rdtsc. - Changed Windows to use the performance counter instead of rdtsc.
- Changed Linux to use clock_gettime for profiling instead of rdtsc. This - Changed Linux to use clock_gettime for profiling instead of rdtsc. This

View file

@ -337,7 +337,7 @@ static int markpointnum = 0; // next point to be assigned
static int followplayer = 1; // specifies whether to follow the player around static int followplayer = 1; // specifies whether to follow the player around
static FTexture *mapback; // the automap background static FTextureID mapback; // the automap background
static fixed_t mapystart=0; // y-value for the start of the map bitmap...used in the parallax stuff. static fixed_t mapystart=0; // y-value for the start of the map bitmap...used in the parallax stuff.
static fixed_t mapxstart=0; //x-value for the bitmap. static fixed_t mapxstart=0; //x-value for the bitmap.
@ -534,19 +534,24 @@ static void AM_ScrollParchment (fixed_t dmapx, fixed_t dmapy)
mapxstart -= MulScale12 (dmapx, scale_mtof); mapxstart -= MulScale12 (dmapx, scale_mtof);
mapystart -= MulScale12 (dmapy, scale_mtof); mapystart -= MulScale12 (dmapy, scale_mtof);
if (mapback != NULL) if (mapback.isValid())
{ {
int pwidth = mapback->GetWidth() << MAPBITS; FTexture *backtex = TexMan[mapback];
int pheight = mapback->GetHeight() << MAPBITS;
while(mapxstart > 0) if (backtex != NULL)
mapxstart -= pwidth; {
while(mapxstart <= -pwidth) int pwidth = backtex->GetWidth() << MAPBITS;
mapxstart += pwidth; int pheight = backtex->GetHeight() << MAPBITS;
while(mapystart > 0)
mapystart -= pheight; while(mapxstart > 0)
while(mapystart <= -pheight) mapxstart -= pwidth;
mapystart += pheight; while(mapxstart <= -pwidth)
mapxstart += pwidth;
while(mapystart > 0)
mapystart -= pheight;
while(mapystart <= -pheight)
mapystart += pheight;
}
} }
} }
@ -737,23 +742,7 @@ void AM_loadPics ()
marknums[i] = TexMan.CheckForTexture (namebuf, FTexture::TEX_MiscPatch); marknums[i] = TexMan.CheckForTexture (namebuf, FTexture::TEX_MiscPatch);
} }
if (mapback == NULL) mapback = TexMan.CheckForTexture("AUTOPAGE", FTexture::TEX_MiscPatch);
{
i = Wads.CheckNumForName ("AUTOPAGE");
if (i >= 0)
{
mapback = FTexture::CreateTexture(i, FTexture::TEX_Autopage);
}
}
}
void AM_unloadPics ()
{
if (mapback != NULL)
{
delete mapback;
mapback = NULL;
}
} }
bool AM_clearMarks () bool AM_clearMarks ()
@ -788,7 +777,6 @@ void AM_LevelInit ()
// //
void AM_Stop () void AM_Stop ()
{ {
AM_unloadPics ();
automapactive = false; automapactive = false;
stopped = true; stopped = true;
BorderNeedRefresh = screen->GetPageCount (); BorderNeedRefresh = screen->GetPageCount ();
@ -1063,22 +1051,26 @@ void AM_Ticker ()
// //
void AM_clearFB (const AMColor &color) void AM_clearFB (const AMColor &color)
{ {
if (mapback == NULL || !am_drawmapback) if (!mapback.isValid() || !am_drawmapback)
{ {
screen->Clear (0, 0, f_w, f_h, color.Index, color.RGB); screen->Clear (0, 0, f_w, f_h, color.Index, color.RGB);
} }
else else
{ {
int pwidth = mapback->GetWidth(); FTexture *backtex = TexMan[mapback];
int pheight = mapback->GetHeight(); if (backtex != NULL)
int x, y;
//blit the automap background to the screen.
for (y = mapystart >> MAPBITS; y < f_h; y += pheight)
{ {
for (x = mapxstart >> MAPBITS; x < f_w; x += pwidth) int pwidth = backtex->GetWidth();
int pheight = backtex->GetHeight();
int x, y;
//blit the automap background to the screen.
for (y = mapystart >> MAPBITS; y < f_h; y += pheight)
{ {
screen->DrawTexture (mapback, x, y, DTA_ClipBottom, f_h, DTA_TopOffset, 0, DTA_LeftOffset, 0, TAG_DONE); for (x = mapxstart >> MAPBITS; x < f_w; x += pwidth)
{
screen->DrawTexture (backtex, x, y, DTA_ClipBottom, f_h, DTA_TopOffset, 0, DTA_LeftOffset, 0, TAG_DONE);
}
} }
} }
} }

View file

@ -1457,24 +1457,20 @@ static void SetPointer(FState *state, PSymbol *sym)
{ {
if (sym==NULL) if (sym==NULL)
{ {
state->Action = NULL; state->SetAction(NULL);
state->ParameterIndex=0;
} }
else switch (sym->SymbolType) else switch (sym->SymbolType)
{ {
case SYM_ActionFunction: case SYM_ActionFunction:
state->Action = static_cast<PSymbolActionFunction*>(sym)->Function; state->SetAction(static_cast<PSymbolActionFunction*>(sym));
state->ParameterIndex=0; // No parameters for patched code pointers
break; break;
/* /*
case SYM_ExternalFunction: case SYM_ExternalFunction:
state->Action = A_CallExtFunction; state->Action = A_CallExtFunction;
state->ParameterIndex = static_cast<PSymbolExternalFunction*>(sym->Data);
break; break;
*/ */
default: default:
state->Action = NULL; state->SetAction(NULL);
state->ParameterIndex=0;
} }
} }
@ -1498,7 +1494,7 @@ static int PatchPointer (int ptrNum)
{ {
int index = atoi(Line2); int index = atoi(Line2);
if ((unsigned)(index) >= (unsigned)NumActions) if ((unsigned)(index) >= (unsigned)NumActions)
state->Action = NULL; state->SetAction(NULL);
else else
{ {
SetPointer(state, CodePtrSymbols[ActionList[index]]); SetPointer(state, CodePtrSymbols[ActionList[index]]);
@ -1800,7 +1796,7 @@ static int PatchCodePtrs (int dummy)
if (name == -1) if (name == -1)
{ {
state->Action = NULL; state->SetAction(NULL);
Printf ("Frame %d: Unknown code pointer: %s\n", frame, Line2); Printf ("Frame %d: Unknown code pointer: %s\n", frame, Line2);
} }
else else
@ -1821,7 +1817,7 @@ static int PatchCodePtrs (int dummy)
} }
if (min > max) if (min > max)
{ {
state->Action = NULL; state->SetAction(NULL);
Printf ("Frame %d: Unknown code pointer: %s\n", frame, Line2); Printf ("Frame %d: Unknown code pointer: %s\n", frame, Line2);
} }
else else

View file

@ -123,36 +123,29 @@ void PClass::StaticFreeData (PClass *type)
} }
type->FreeStateList (); type->FreeStateList ();
if (type->ActorInfo != NULL)
{
if (type->ActorInfo->OwnedStates != NULL)
{
delete[] type->ActorInfo->OwnedStates;
type->ActorInfo->OwnedStates = NULL;
}
if (type->ActorInfo->DamageFactors != NULL)
{
delete type->ActorInfo->DamageFactors;
type->ActorInfo->DamageFactors = NULL;
}
if (type->ActorInfo->PainChances != NULL)
{
delete type->ActorInfo->PainChances;
type->ActorInfo->PainChances = NULL;
}
delete type->ActorInfo;
type->ActorInfo = NULL;
}
if (type->bRuntimeClass) if (type->bRuntimeClass)
{ {
if (type->ActorInfo != NULL) delete type;
{
if (type->ActorInfo->OwnedStates != NULL)
{
delete[] type->ActorInfo->OwnedStates;
type->ActorInfo->OwnedStates = NULL;
}
if (type->ActorInfo->DamageFactors != NULL)
{
delete type->ActorInfo->DamageFactors;
type->ActorInfo->DamageFactors = NULL;
}
if (type->ActorInfo->PainChances != NULL)
{
delete type->ActorInfo->PainChances;
type->ActorInfo->PainChances = NULL;
}
delete type->ActorInfo;
type->ActorInfo = NULL;
}
if (type->bRuntimeClass != 2)
{
delete type;
}
else
{
type->Symbols.ReleaseSymbols();
}
} }
else else
{ {
@ -315,8 +308,6 @@ void PClass::InitializeActorInfo ()
memset (Defaults, 0, Size); memset (Defaults, 0, Size);
} }
bRuntimeClass = 2; // Class is internal but actor data external
FActorInfo *info = ActorInfo = new FActorInfo; FActorInfo *info = ActorInfo = new FActorInfo;
info->Class = this; info->Class = this;
info->GameFilter = GAME_Any; info->GameFilter = GAME_Any;
@ -398,7 +389,7 @@ const PClass *PClass::NativeClass() const
{ {
const PClass *cls = this; const PClass *cls = this;
while (cls && cls->bRuntimeClass == 1) while (cls && cls->bRuntimeClass)
cls = cls->ParentClass; cls = cls->ParentClass;
return cls; return cls;

View file

@ -46,11 +46,14 @@ struct PSymbolConst : public PSymbol
// If the final character is a +, the previous parameter is repeated indefinitely, // If the final character is a +, the previous parameter is repeated indefinitely,
// and an "imaginary" first parameter is inserted containing the total number of // and an "imaginary" first parameter is inserted containing the total number of
// parameters passed. // parameters passed.
struct FState;
typedef void (*actionf_p)(AActor *self, FState *state, int parameters);
struct PSymbolActionFunction : public PSymbol struct PSymbolActionFunction : public PSymbol
{ {
FString Arguments; FString Arguments;
void (*Function)(AActor*); actionf_p Function;
int defaultparameterindex;
}; };
// A symbol table ----------------------------------------------------------- // A symbol table -----------------------------------------------------------
@ -103,7 +106,7 @@ struct PClass
PClass *HashNext; PClass *HashNext;
FMetaTable Meta; FMetaTable Meta;
BYTE *Defaults; BYTE *Defaults;
BYTE bRuntimeClass; // class was defined at run-time, not compile-time bool bRuntimeClass; // class was defined at run-time, not compile-time
unsigned short ClassIndex; unsigned short ClassIndex;
PSymbolTable Symbols; PSymbolTable Symbols;

View file

@ -40,8 +40,7 @@
class AActor; class AActor;
class player_t; class player_t;
struct pspdef_s; struct pspdef_s;
struct FState;
typedef void (*actionf_p)( AActor* );
class FThinkerIterator; class FThinkerIterator;

View file

@ -76,11 +76,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainDie)
G_ExitLevel (0, false); G_ExitLevel (0, false);
} }
DEFINE_ACTION_FUNCTION(AActor, A_BrainSpit) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
{ {
DSpotState *state = DSpotState::GetSpotState(); DSpotState *state = DSpotState::GetSpotState();
AActor *targ; AActor *targ;
AActor *spit; AActor *spit;
bool isdefault = false;
// shoot a cube at current target // shoot a cube at current target
targ = state->GetNextInList(PClass::FindClass("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain)); targ = state->GetNextInList(PClass::FindClass("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain));
@ -88,9 +89,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainSpit)
if (targ != NULL) if (targ != NULL)
{ {
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index = CheckIndex (1, NULL); int index = CheckIndex (1);
if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]); if (index < 0) return;
if (spawntype == NULL) spawntype = PClass::FindClass("SpawnShot");
spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
if (spawntype == NULL)
{
spawntype = PClass::FindClass("SpawnShot");
isdefault = true;
}
// spawn brain missile // spawn brain missile
spit = P_SpawnMissile (self, targ, spawntype); spit = P_SpawnMissile (self, targ, spawntype);
@ -117,7 +125,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainSpit)
spit->reactiontime += level.maptime; spit->reactiontime += level.maptime;
} }
if (index >= 0) if (!isdefault)
{ {
S_Sound(self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NONE); S_Sound(self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NONE);
} }
@ -129,7 +137,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainSpit)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_SpawnFly) static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
{ {
AActor *newmobj; AActor *newmobj;
AActor *fog; AActor *fog;
@ -143,22 +151,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnFly)
targ = self->target; targ = self->target;
const PClass *spawntype = NULL; if (spawntype != NULL)
int index = CheckIndex (1, NULL);
// First spawn teleport fire.
if (index >= 0)
{ {
spawntype = PClass::FindClass ((ENamedName)StateParameters[index]); fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
if (spawntype != NULL) if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM);
{
fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
if (fog != NULL) S_Sound (fog, CHAN_BODY, fog->SeeSound, 1, ATTN_NORM);
}
}
else
{
fog = Spawn("SpawnFire", targ->x, targ->y, targ->z, ALLOW_REPLACE);
if (fog != NULL) S_Sound (fog, CHAN_BODY, "brain/spawn", 1, ATTN_NORM);
} }
FName SpawnName; FName SpawnName;
@ -245,9 +241,31 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnFly)
self->Destroy (); self->Destroy ();
} }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly)
{
const PClass *spawntype = NULL;
FSoundID sound;
int index = CheckIndex (1);
// First spawn teleport fire.
if (index < 0) return;
spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
if (spawntype != NULL)
{
sound = GetDefaultByType(spawntype)->SeeSound;
}
else
{
spawntype = PClass::FindClass ("SpawnFire");
sound = "brain/spawn";
}
SpawnFly(self, spawntype, sound);
}
// travelling cube sound // travelling cube sound
DEFINE_ACTION_FUNCTION(AActor, A_SpawnSound) DEFINE_ACTION_FUNCTION(AActor, A_SpawnSound)
{ {
S_Sound (self, CHAN_BODY, "brain/cube", 1, ATTN_IDLE); S_Sound (self, CHAN_BODY, "brain/cube", 1, ATTN_IDLE);
CALL_ACTION(A_SpawnFly, self); SpawnFly(self, PClass::FindClass("SpawnFire"), "brain/spawn");
} }

View file

@ -96,7 +96,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
// //
// A_Saw // A_Saw
// //
DEFINE_ACTION_FUNCTION(AActor, A_Saw) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
{ {
angle_t angle; angle_t angle;
int damage=0; int damage=0;
@ -119,19 +119,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_Saw)
return; return;
} }
int index = CheckIndex (4, NULL); int index = CheckIndex (4);
if (index >= 0) if (index < 0) return;
{
fullsound = FSoundID(StateParameters[index]); fullsound = FSoundID(StateParameters[index]);
hitsound = FSoundID(StateParameters[index+1]); hitsound = FSoundID(StateParameters[index+1]);
damage = EvalExpressionI (StateParameters[index+2], self); damage = EvalExpressionI (StateParameters[index+2], self);
pufftype = PClass::FindClass ((ENamedName)StateParameters[index+3]); pufftype = PClass::FindClass ((ENamedName)StateParameters[index+3]);
}
else
{
fullsound = "weapons/sawfull";
hitsound = "weapons/sawhit";
}
if (pufftype == NULL) pufftype = PClass::FindClass(NAME_BulletPuff); if (pufftype == NULL) pufftype = PClass::FindClass(NAME_BulletPuff);
if (damage == 0) damage = 2; if (damage == 0) damage = 2;
@ -487,7 +481,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBFG)
// A_BFGSpray // A_BFGSpray
// Spawn a BFG explosion on every monster in view // Spawn a BFG explosion on every monster in view
// //
DEFINE_ACTION_FUNCTION(AActor, A_BFGSpray) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
{ {
int i; int i;
int j; int j;
@ -499,21 +493,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_BFGSpray)
int damagecnt = 15; int damagecnt = 15;
AActor *linetarget; AActor *linetarget;
int index = CheckIndex (3, NULL); int index = CheckIndex (3);
if (index >= 0) if (index < 0) return;
{
spraytype = PClass::FindClass ((ENamedName)StateParameters[index]); spraytype = PClass::FindClass ((ENamedName)StateParameters[index]);
numrays = EvalExpressionI (StateParameters[index+1], self);
if (numrays <= 0)
numrays = 40;
damagecnt = EvalExpressionI (StateParameters[index+2], self);
if (damagecnt <= 0)
damagecnt = 15;
}
if (spraytype == NULL) if (spraytype == NULL)
{
spraytype = PClass::FindClass("BFGExtra"); spraytype = PClass::FindClass("BFGExtra");
} numrays = EvalExpressionI (StateParameters[index+1], self);
if (numrays <= 0)
numrays = 40;
damagecnt = EvalExpressionI (StateParameters[index+2], self);
if (damagecnt <= 0)
damagecnt = 15;
// [RH] Don't crash if no target // [RH] Don't crash if no target
if (!self->target) if (!self->target)

View file

@ -21,7 +21,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatRaise)
S_Sound (self, CHAN_WEAPON, "fatso/raiseguns", 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, "fatso/raiseguns", 1, ATTN_NORM);
} }
DEFINE_ACTION_FUNCTION(AActor, A_FatAttack1) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1)
{ {
AActor *missile; AActor *missile;
angle_t an; angle_t an;
@ -30,7 +30,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatAttack1)
return; return;
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index = CheckIndex (1, NULL); int index = CheckIndex (1);
if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]); if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); if (spawntype == NULL) spawntype = PClass::FindClass("FatShot");
@ -49,7 +49,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatAttack1)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_FatAttack2) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack2)
{ {
AActor *missile; AActor *missile;
angle_t an; angle_t an;
@ -58,7 +58,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatAttack2)
return; return;
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index = CheckIndex (1, NULL); int index = CheckIndex (1);
if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]); if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); if (spawntype == NULL) spawntype = PClass::FindClass("FatShot");
@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatAttack2)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_FatAttack3) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3)
{ {
AActor *missile; AActor *missile;
angle_t an; angle_t an;
@ -86,7 +86,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatAttack3)
return; return;
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index = CheckIndex (1, NULL); int index = CheckIndex (1);
if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]); if (index >= 0) spawntype = PClass::FindClass ((ENamedName)StateParameters[index]);
if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); if (spawntype == NULL) spawntype = PClass::FindClass("FatShot");
@ -116,12 +116,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FatAttack3)
// Original idea: Linguica // Original idea: Linguica
// //
DEFINE_ACTION_FUNCTION(AActor, A_Mushroom) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
{ {
int i, j, n = self->GetMissileDamage (0, 1); int i, j, n = self->GetMissileDamage (0, 1);
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index = CheckIndex (2, NULL); int index = CheckIndex (2);
if (index >= 0) if (index >= 0)
{ {
spawntype = PClass::FindClass((ENamedName)StateParameters[index]); spawntype = PClass::FindClass((ENamedName)StateParameters[index]);

View file

@ -19,40 +19,45 @@
// //
#define SKULLSPEED (20*FRACUNIT) #define SKULLSPEED (20*FRACUNIT)
DEFINE_ACTION_FUNCTION(AActor, A_SkullAttack) void A_SkullAttack(AActor *self, fixed_t speed)
{ {
AActor *dest; AActor *dest;
angle_t an; angle_t an;
int dist; int dist;
int n;
if (!self->target) if (!self->target)
return; return;
int index = CheckIndex (1, NULL);
if (index >= 0)
{
n = FLOAT2FIXED(EvalExpressionF (StateParameters[index], self));
if (n == 0) n = SKULLSPEED;
}
else n = SKULLSPEED;
dest = self->target; dest = self->target;
self->flags |= MF_SKULLFLY; self->flags |= MF_SKULLFLY;
S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM); S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM);
A_FaceTarget (self); A_FaceTarget (self);
an = self->angle >> ANGLETOFINESHIFT; an = self->angle >> ANGLETOFINESHIFT;
self->momx = FixedMul (n, finecosine[an]); self->momx = FixedMul (speed, finecosine[an]);
self->momy = FixedMul (n, finesine[an]); self->momy = FixedMul (speed, finesine[an]);
dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
dist = dist / n; dist = dist / speed;
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
self->momz = (dest->z+(dest->height>>1) - self->z) / dist; self->momz = (dest->z+(dest->height>>1) - self->z) / dist;
} }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack)
{
int n = 0;
int index = CheckIndex (1);
if (index >= 0)
{
n = FLOAT2FIXED(EvalExpressionF (StateParameters[index], self));
}
if (n == 0) n = SKULLSPEED;
A_SkullAttack(self, n);
}
//========================================================================== //==========================================================================
// //
// CVAR transsouls // CVAR transsouls

View file

@ -10,10 +10,10 @@
DECLARE_ACTION(A_SkullAttack) DECLARE_ACTION(A_SkullAttack)
static const PClass *GetSpawnType() static const PClass *GetSpawnType(DECLARE_PARAMINFO)
{ {
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index>=0) if (index>=0)
{ {
spawntype = PClass::FindClass((ENamedName)StateParameters[index]); spawntype = PClass::FindClass((ENamedName)StateParameters[index]);
@ -23,6 +23,9 @@ static const PClass *GetSpawnType()
} }
#define SKULLSPEED (20*FRACUNIT)
void A_SkullAttack(AActor *self, fixed_t speed);
// //
// A_PainShootSkull // A_PainShootSkull
// Spawn a lost soul and launch it at the target // Spawn a lost soul and launch it at the target
@ -127,7 +130,7 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype)
// [RH] Lost souls hate the same things as their pain elementals // [RH] Lost souls hate the same things as their pain elementals
other->CopyFriendliness (self, true); other->CopyFriendliness (self, true);
CALL_ACTION(A_SkullAttack, other); A_SkullAttack(other, SKULLSPEED);
} }
@ -135,34 +138,34 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype)
// A_PainAttack // A_PainAttack
// Spawn a lost soul and launch it at the target // Spawn a lost soul and launch it at the target
// //
DEFINE_ACTION_FUNCTION(AActor, A_PainAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack)
{ {
if (!self->target) if (!self->target)
return; return;
const PClass *spawntype = GetSpawnType(); const PClass *spawntype = GetSpawnType(PUSH_PARAMINFO);
A_FaceTarget (self); A_FaceTarget (self);
A_PainShootSkull (self, self->angle, spawntype); A_PainShootSkull (self, self->angle, spawntype);
} }
DEFINE_ACTION_FUNCTION(AActor, A_DualPainAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack)
{ {
if (!self->target) if (!self->target)
return; return;
const PClass *spawntype = GetSpawnType(); const PClass *spawntype = GetSpawnType(PUSH_PARAMINFO);
A_FaceTarget (self); A_FaceTarget (self);
A_PainShootSkull (self, self->angle + ANG45, spawntype); A_PainShootSkull (self, self->angle + ANG45, spawntype);
A_PainShootSkull (self, self->angle - ANG45, spawntype); A_PainShootSkull (self, self->angle - ANG45, spawntype);
} }
DEFINE_ACTION_FUNCTION(AActor, A_PainDie) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie)
{ {
if (self->target != NULL && self->IsFriend (self->target)) if (self->target != NULL && self->IsFriend (self->target))
{ // And I thought you were my friend! { // And I thought you were my friend!
self->flags &= ~MF_FRIENDLY; self->flags &= ~MF_FRIENDLY;
} }
const PClass *spawntype = GetSpawnType(); const PClass *spawntype = GetSpawnType(PUSH_PARAMINFO);
CALL_ACTION(A_NoBlocking, self); CALL_ACTION(A_NoBlocking, self);
A_PainShootSkull (self, self->angle + ANG90, spawntype); A_PainShootSkull (self, self->angle + ANG90, spawntype);
A_PainShootSkull (self, self->angle + ANG180, spawntype); A_PainShootSkull (self, self->angle + ANG180, spawntype);

View file

@ -325,7 +325,7 @@ static void MarinePunch(AActor *self, int damagemul)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_M_Punch) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Punch)
{ {
int index=CheckIndex(1); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
@ -361,7 +361,7 @@ void P_GunShot2 (AActor *mo, bool accurate, int pitch, const PClass *pufftype)
// //
//============================================================================ //============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_M_FirePistol) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FirePistol)
{ {
if (self->target == NULL) if (self->target == NULL)
return; return;
@ -451,7 +451,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2)
// //
//============================================================================ //============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_M_FireCGun) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_FireCGun)
{ {
if (self->target == NULL) if (self->target == NULL)
return; return;

View file

@ -49,7 +49,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_TimeBomb)
self->z += 32*FRACUNIT; self->z += 32*FRACUNIT;
self->RenderStyle = STYLE_Add; self->RenderStyle = STYLE_Add;
self->alpha = FRACUNIT; self->alpha = FRACUNIT;
CALL_ACTION(A_Explode, self); P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true);
if (self->z <= self->floorz + (128<<FRACBITS))
{
P_HitFloor (self);
}
} }
class AArtiTimeBomb : public AInventory class AArtiTimeBomb : public AInventory

View file

@ -59,7 +59,7 @@ extern bool P_AutoUseChaosDevice (player_t *player);
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_StaffAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
{ {
angle_t angle; angle_t angle;
int damage; int damage;
@ -72,7 +72,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StaffAttack)
return; return;
} }
int index = CheckIndex (2, NULL); int index = CheckIndex (2);
if (index < 0) return; if (index < 0) return;
damage = EvalExpressionI (StateParameters[index], self); damage = EvalExpressionI (StateParameters[index], self);
@ -233,7 +233,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_GauntletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
{ {
angle_t angle; angle_t angle;
int damage; int damage;
@ -250,7 +250,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GauntletAttack)
return; return;
} }
int index = CheckIndex (1, NULL); int index = CheckIndex (1);
if (index < 0) return; if (index < 0) return;
power = EvalExpressionI (StateParameters[index], self); power = EvalExpressionI (StateParameters[index], self);

View file

@ -185,13 +185,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink)
DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink) DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink)
{ {
if (!--self->special1) if (self->player && self->player->ReadyWeapon)
{ {
P_SetPsprite (self->player, ps_weapon, self->FindState ("Blink")); if (!--self->special1)
self->special1 = (pr_blink()+50)>>2; {
} P_SetPsprite (self->player, ps_weapon, self->player->ReadyWeapon->FindState ("Blink"));
else self->special1 = (pr_blink()+50)>>2;
{ }
CALL_ACTION(A_WeaponReady, self); else
{
CALL_ACTION(A_WeaponReady, self);
}
} }
} }

View file

@ -60,7 +60,7 @@ bool AFighterWeaponPiece::TryPickup (AActor *toucher)
// //
//============================================================================ //============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_DropWeaponPieces) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropWeaponPieces)
{ {
int index=CheckIndex(3); int index=CheckIndex(3);
if (index<0) return; if (index<0) return;

View file

@ -160,9 +160,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode)
for (i = (pr_foo()&3)+3; i; i--) for (i = (pr_foo()&3)+3; i; i--)
{ {
mo = Spawn ("CorpseBit", self->x, self->y, self->z, ALLOW_REPLACE); mo = Spawn ("CorpseBit", self->x, self->y, self->z, ALLOW_REPLACE);
mo->SetState (mo->SpawnState + (pr_foo()%3));
if (mo) if (mo)
{ {
mo->SetState (mo->SpawnState + (pr_foo()%3));
mo->momz = ((pr_foo()&7)+5)*(3*FRACUNIT/4); mo->momz = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
mo->momx = pr_foo.Random2()<<(FRACBITS-6); mo->momx = pr_foo.Random2()<<(FRACBITS-6);
mo->momy = pr_foo.Random2()<<(FRACBITS-6); mo->momy = pr_foo.Random2()<<(FRACBITS-6);
@ -170,9 +170,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode)
} }
// Spawn a skull // Spawn a skull
mo = Spawn ("CorpseBit", self->x, self->y, self->z, ALLOW_REPLACE); mo = Spawn ("CorpseBit", self->x, self->y, self->z, ALLOW_REPLACE);
mo->SetState (mo->SpawnState + 3);
if (mo) if (mo)
{ {
mo->SetState (mo->SpawnState + 3);
mo->momz = ((pr_foo()&7)+5)*(3*FRACUNIT/4); mo->momz = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
mo->momx = pr_foo.Random2()<<(FRACBITS-6); mo->momx = pr_foo.Random2()<<(FRACBITS-6);
mo->momy = pr_foo.Random2()<<(FRACBITS-6); mo->momy = pr_foo.Random2()<<(FRACBITS-6);
@ -277,9 +277,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode)
mo = Spawn ("ZArmorChunk", self->x+((pr_soaexplode()-128)<<12), mo = Spawn ("ZArmorChunk", self->x+((pr_soaexplode()-128)<<12),
self->y+((pr_soaexplode()-128)<<12), self->y+((pr_soaexplode()-128)<<12),
self->z+(pr_soaexplode()*self->height/256), ALLOW_REPLACE); self->z+(pr_soaexplode()*self->height/256), ALLOW_REPLACE);
mo->SetState (mo->SpawnState + i);
if (mo) if (mo)
{ {
mo->SetState (mo->SpawnState + i);
mo->momz = ((pr_soaexplode()&7)+5)*FRACUNIT; mo->momz = ((pr_soaexplode()&7)+5)*FRACUNIT;
mo->momx = pr_soaexplode.Random2()<<(FRACBITS-6); mo->momx = pr_soaexplode.Random2()<<(FRACBITS-6);
mo->momy = pr_soaexplode.Random2()<<(FRACBITS-6); mo->momy = pr_soaexplode.Random2()<<(FRACBITS-6);

View file

@ -100,10 +100,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeOrbit)
} }
static const PClass *GetBallType() static const PClass *GetBallType(DECLARE_PARAMINFO)
{ {
const PClass *balltype = NULL; const PClass *balltype = NULL;
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index>=0) if (index>=0)
{ {
balltype = PClass::FindClass((ENamedName)StateParameters[index]); balltype = PClass::FindClass((ENamedName)StateParameters[index]);
@ -114,7 +114,7 @@ static const PClass *GetBallType()
DEFINE_ACTION_FUNCTION(AActor, A_BridgeInit) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit)
{ {
angle_t startangle; angle_t startangle;
AActor *ball; AActor *ball;
@ -128,7 +128,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BridgeInit)
// Spawn triad into world -- may be more than a triad now. // Spawn triad into world -- may be more than a triad now.
int ballcount = self->args[2]==0 ? 3 : self->args[2]; int ballcount = self->args[2]==0 ? 3 : self->args[2];
const PClass *balltype = GetBallType(); const PClass *balltype = GetBallType(PUSH_PARAMINFO);
for (int i = 0; i < ballcount; i++) for (int i = 0; i < ballcount; i++)
{ {
ball = Spawn(balltype, cx, cy, cz, ALLOW_REPLACE); ball = Spawn(balltype, cx, cy, cz, ALLOW_REPLACE);

View file

@ -381,7 +381,7 @@ void ASpecialSpot::Destroy()
// will build a list of all mace spots in the level and spawn a // will build a list of all mace spots in the level and spawn a
// mace. The rest of the spots will do nothing. // mace. The rest of the spots will do nothing.
DEFINE_ACTION_FUNCTION(AActor, A_SpawnSingleItem) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnSingleItem)
{ {
AActor *spot = NULL; AActor *spot = NULL;
DSpotState *state = DSpotState::GetSpotState(); DSpotState *state = DSpotState::GetSpotState();

View file

@ -751,19 +751,7 @@ static bool FindMostRecentWeapon (player_t *player, int *slot, int *index)
{ {
if (player->PendingWeapon != WP_NOCHANGE) if (player->PendingWeapon != WP_NOCHANGE)
{ {
if (player->psprites[ps_weapon].state != NULL && return LocalWeapons.LocateWeapon (player->PendingWeapon->GetClass(), slot, index);
player->psprites[ps_weapon].state->GetAction() == GET_ACTION(A_Raise))
{
if (LocalWeapons.LocateWeapon (player->PendingWeapon->GetClass(), slot, index))
{
return true;
}
return false;
}
else
{
return LocalWeapons.LocateWeapon (player->PendingWeapon->GetClass(), slot, index);
}
} }
else if (player->ReadyWeapon != NULL) else if (player->ReadyWeapon != NULL)
{ {

View file

@ -211,7 +211,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShowElectricFlash)
// //
//============================================================================ //============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FireArrow) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireArrow)
{ {
angle_t savedangle; angle_t savedangle;
@ -632,7 +632,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burnination)
// //
//============================================================================ //============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FireGrenade) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade)
{ {
const PClass *grenadetype; const PClass *grenadetype;
player_t *player = self->player; player_t *player = self->player;

View file

@ -25,7 +25,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Bang4Cloud)
// ------------------------------------------------------------------- // -------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_GiveQuestItem) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveQuestItem)
{ {
int index=CheckIndex(1); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;

View file

@ -311,7 +311,7 @@ gameinfo_t StrifeGameInfo =
280/35, 280/35,
0, 0,
200/35, 200/35,
"Chat", "misc/chat",
"d_intro", "d_intro",
"-NOFLAT", "-NOFLAT",
"CREDIT", "CREDIT",
@ -340,7 +340,7 @@ gameinfo_t StrifeTeaserGameInfo =
280/35, 280/35,
0, 0,
200/35, 200/35,
"Chat", "misc/chat",
"d_intro", "d_intro",
"-NOFLAT", "-NOFLAT",
"CREDIT", "CREDIT",
@ -369,7 +369,7 @@ gameinfo_t StrifeTeaser2GameInfo =
280/35, 280/35,
0, 0,
200/35, 200/35,
"Chat", "misc/chat",
"d_intro", "d_intro",
"-NOFLAT", "-NOFLAT",
"CREDIT", "CREDIT",

View file

@ -81,6 +81,10 @@
const BYTE SF_FULLBRIGHT = 0x40; const BYTE SF_FULLBRIGHT = 0x40;
struct Baggage;
class FScanner;
struct FActorInfo;
struct FState struct FState
{ {
WORD sprite; WORD sprite;
@ -88,8 +92,8 @@ struct FState
SBYTE Misc1; SBYTE Misc1;
BYTE Misc2; BYTE Misc2;
BYTE Frame; BYTE Frame;
actionf_p Action;
FState *NextState; FState *NextState;
actionf_p ActionFunc;
int ParameterIndex; int ParameterIndex;
inline int GetFrame() const inline int GetFrame() const
@ -116,15 +120,35 @@ struct FState
{ {
return NextState; return NextState;
} }
inline actionf_p GetAction() const
{
return Action;
}
inline void SetFrame(BYTE frame) inline void SetFrame(BYTE frame)
{ {
Frame = (Frame & SF_FULLBRIGHT) | (frame-'A'); Frame = (Frame & SF_FULLBRIGHT) | (frame-'A');
} }
void SetAction(PSymbolActionFunction *func, bool setdefaultparams = true)
{
if (func != NULL)
{
ActionFunc = func->Function;
if (setdefaultparams) ParameterIndex = func->defaultparameterindex+1;
}
else
{
ActionFunc = NULL;
if (setdefaultparams) ParameterIndex = 0;
}
}
inline bool CallAction(AActor *self)
{
if (ActionFunc != NULL)
{
ActionFunc(self, this, ParameterIndex);
return true;
}
else
{
return false;
}
}
static const PClass *StaticFindStateOwner (const FState *state); static const PClass *StaticFindStateOwner (const FState *state);
static const PClass *StaticFindStateOwner (const FState *state, const FActorInfo *info); static const PClass *StaticFindStateOwner (const FState *state, const FActorInfo *info);
}; };

View file

@ -2231,16 +2231,19 @@ enum ChaseFlags
CHF_DONTMOVE = 16, CHF_DONTMOVE = 16,
}; };
DEFINE_ACTION_FUNCTION(AActor, A_Chase) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase)
{ {
int index=CheckIndex(3, &CallingState); int index=CheckIndex(3);
if (index>=0) if (index < 0) return;
if (StateParameters[index] != INT_MIN)
{ {
FState *melee = P_GetState(self, CallingState, StateParameters[index]);
FState *missile = P_GetState(self, CallingState, StateParameters[index+1]);
int flags = EvalExpressionI (StateParameters[index+2], self); int flags = EvalExpressionI (StateParameters[index+2], self);
if (flags & CHF_RESURRECT && P_CheckForResurrection(self, false)) return; if (flags & CHF_RESURRECT && P_CheckForResurrection(self, false)) return;
FState *melee = P_GetState(self, CallingState, StateParameters[index]);
FState *missile = P_GetState(self, CallingState, StateParameters[index+1]);
A_DoChase(self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE), A_DoChase(self, !!(flags&CHF_FASTCHASE), melee, missile, !(flags&CHF_NOPLAYACTIVE),
!!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE)); !!(flags&CHF_NIGHTMAREFAST), !!(flags&CHF_DONTMOVE));
@ -2262,16 +2265,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileChase)
A_DoChase (self, false, self->MeleeState, self->MissileState, true, !!(gameinfo.gametype & GAME_Raven), false); A_DoChase (self, false, self->MeleeState, self->MissileState, true, !!(gameinfo.gametype & GAME_Raven), false);
} }
DEFINE_ACTION_FUNCTION(AActor, A_ExtChase) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase)
{ {
// Now that A_Chase can handle state label parameters, this function has become rather useless... // Now that A_Chase can handle state label parameters, this function has become rather useless...
int index=CheckIndex(4, &CallingState); int index=CheckIndex(4);
if (index<0) return; if (index<0) return;
A_DoChase(self, false, A_DoChase(self, false,
EvalExpressionI (StateParameters[index], self) ? self->MeleeState:NULL, EvalExpressionI (StateParameters[index], self) ? self->MeleeState:NULL,
EvalExpressionI (StateParameters[index+1], self) ? self->MissileState:NULL, EvalExpressionI (StateParameters[index+1], self) ? self->MissileState:NULL,
EvalExpressionN (StateParameters[index+2], self), !!EvalExpressionI (StateParameters[index+2], self),
!!EvalExpressionI (StateParameters[index+3], self), false); !!EvalExpressionI (StateParameters[index+3], self), false);
} }
@ -2378,6 +2381,44 @@ DEFINE_ACTION_FUNCTION(AActor, A_XScream)
S_Sound (self, CHAN_VOICE, "misc/gibbed", 1, ATTN_NORM); S_Sound (self, CHAN_VOICE, "misc/gibbed", 1, ATTN_NORM);
} }
//===========================================================================
//
// A_ScreamAndUnblock
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ScreamAndUnblock)
{
CALL_ACTION(A_Scream, self);
CALL_ACTION(A_NoBlocking, self);
}
//===========================================================================
//
// A_ActiveSound
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound)
{
if (self->ActiveSound)
{
S_Sound (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM);
}
}
//===========================================================================
//
// A_ActiveAndUnblock
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ActiveAndUnblock)
{
CALL_ACTION(A_ActiveSound, self);
CALL_ACTION(A_NoBlocking, self);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Modifies the drop amount of this item according to the current skill's // Modifies the drop amount of this item according to the current skill's
@ -2549,11 +2590,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain)
} }
// killough 11/98: kill an object // killough 11/98: kill an object
DEFINE_ACTION_FUNCTION(AActor, A_Die) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die)
{ {
ENamedName name; ENamedName name;
int index=CheckIndex(1, &CallingState); int index=CheckIndex(1);
if (index<0) if (index<0)
{ {
name = NAME_None; name = NAME_None;

View file

@ -41,7 +41,6 @@ DECLARE_ACTION(A_BossDeath)
DECLARE_ACTION(A_Pain) DECLARE_ACTION(A_Pain)
DECLARE_ACTION(A_MonsterRail) DECLARE_ACTION(A_MonsterRail)
DECLARE_ACTION(A_NoBlocking) DECLARE_ACTION(A_NoBlocking)
DECLARE_ACTION(A_Explode)
DECLARE_ACTION(A_Scream) DECLARE_ACTION(A_Scream)
DECLARE_ACTION(A_FreezeDeath) DECLARE_ACTION(A_FreezeDeath)
DECLARE_ACTION(A_FreezeDeathChunks) DECLARE_ACTION(A_FreezeDeathChunks)

View file

@ -713,9 +713,9 @@ enum LO_Flags
LOF_FULLVOLSEESOUND = 16, LOF_FULLVOLSEESOUND = 16,
}; };
DEFINE_ACTION_FUNCTION(AActor, A_LookEx) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
{ {
int index=CheckIndex(6, &CallingState); int index=CheckIndex(6);
if (index<0) return; if (index<0) return;
int flags = EvalExpressionI (StateParameters[index], self); int flags = EvalExpressionI (StateParameters[index], self);

View file

@ -521,17 +521,8 @@ bool AActor::SetState (FState *newstate)
} }
} }
if (newstate->GetAction()) if (newstate->CallAction(this))
{ {
// The parameterized action functions need access to the current state and
// if a function is supposed to work with both actors and weapons
// there is no real means to get to it reliably so I store it in a global variable here.
// Yes, I know this is truly awful but it is the only method I can think of
// that does not involve changing stuff throughout the code.
// Of course this should be rewritten ASAP.
CallingState = newstate;
newstate->GetAction() (this);
// Check whether the called action function resulted in destroying the actor // Check whether the called action function resulted in destroying the actor
if (ObjectFlags & OF_EuthanizeMe) if (ObjectFlags & OF_EuthanizeMe)
return false; return false;
@ -539,7 +530,6 @@ bool AActor::SetState (FState *newstate)
newstate = newstate->GetNextState(); newstate = newstate->GetNextState();
} while (tics == 0); } while (tics == 0);
gl_SetActorLights(this);
return true; return true;
} }

View file

@ -83,7 +83,7 @@ void P_SetPsprite (player_t *player, int position, FState *state)
psp->state = state; psp->state = state;
if (sv_fastweapons >= 2 && position == ps_weapon) if (sv_fastweapons >= 2 && position == ps_weapon)
psp->tics = (state->Action == NULL) ? 0 : 1; psp->tics = state->ActionFunc == NULL? 0 : 1;
else if (sv_fastweapons) else if (sv_fastweapons)
psp->tics = 1; // great for producing decals :) psp->tics = 1; // great for producing decals :)
else else
@ -98,25 +98,17 @@ void P_SetPsprite (player_t *player, int position, FState *state)
psp->sy = state->GetMisc2()<<FRACBITS; psp->sy = state->GetMisc2()<<FRACBITS;
} }
if (state->GetAction()) if (player->mo != NULL)
{ {
// The parameterized action functions need access to the current state and if (state->CallAction(player->mo))
// if a function is supposed to work with both actors and weapons
// there is no real means to get to it reliably so I store it in a global variable here.
// Yes, I know this is truly awful but it is the only method I can think of
// that does not involve changing stuff throughout the code.
// Of course this should be rewritten ASAP.
CallingState = state;
// Call action routine.
if (player->mo != NULL)
{ {
state->GetAction() (player->mo); if (!psp->state)
} {
if (!psp->state) break;
{ }
break;
} }
} }
state = psp->state->GetNextState(); state = psp->state->GetNextState();
} while (!psp->tics); // An initial state of 0 could cycle through. } while (!psp->tics); // An initial state of 0 could cycle through.
} }
@ -713,9 +705,9 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Light2)
} }
} }
DEFINE_ACTION_FUNCTION(AInventory, A_Light) DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_Light)
{ {
int index=CheckIndex(1, &CallingState); int index=CheckIndex(1);
if (self->player != NULL && index > 0) if (self->player != NULL && index > 0)
{ {

View file

@ -1243,14 +1243,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_SkullPop) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop)
{ {
APlayerPawn *mo; APlayerPawn *mo;
player_t *player; player_t *player;
// [GRB] Parameterized version // [GRB] Parameterized version
const PClass *spawntype = NULL; const PClass *spawntype = NULL;
int index = CheckIndex (1, NULL); int index = CheckIndex (1);
if (index >= 0) if (index >= 0)
spawntype = PClass::FindClass((ENamedName)StateParameters[index]); spawntype = PClass::FindClass((ENamedName)StateParameters[index]);
if (!spawntype || !spawntype->IsDescendantOf (RUNTIME_CLASS (APlayerChunk))) if (!spawntype || !spawntype->IsDescendantOf (RUNTIME_CLASS (APlayerChunk)))

View file

@ -910,8 +910,6 @@ FString FScanner::TokenName (int token, const char *string)
"'global'", "'global'",
"'self'", "'self'",
"'stop'", "'stop'",
"'eval'",
"'evalnot'",
"'pickup'", "'pickup'",
"'breakable'", "'breakable'",
"'projectile'", "'projectile'",

File diff suppressed because it is too large Load diff

View file

@ -138,8 +138,6 @@ std2:
'stop' { RET(TK_Stop); } 'stop' { RET(TK_Stop); }
/* Needed for decorate action functions */ /* Needed for decorate action functions */
'eval' { RET(TK_Eval); }
'evalnot' { RET(TK_EvalNot); }
'action' { RET(TK_Action); } 'action' { RET(TK_Action); }
/* other DECORATE top level keywords */ /* other DECORATE top level keywords */

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the // This file was automatically generated by the
// updaterevision tool. Do not edit by hand. // updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "1161" #define ZD_SVN_REVISION_STRING "1165"
#define ZD_SVN_REVISION_NUMBER 1161 #define ZD_SVN_REVISION_NUMBER 1165

View file

@ -70,13 +70,15 @@ private:
//========================================================================== //==========================================================================
// //
// // This texture type will only be used for the AUTOPAGE lump if no other
// format matches.
// //
//========================================================================== //==========================================================================
FTexture *AutomapTexture_TryCreate(FileReader &data, int lumpnum) FTexture *AutomapTexture_TryCreate(FileReader &data, int lumpnum)
{ {
if (data.GetLength() < 320) return NULL; if (data.GetLength() < 320) return NULL;
if (!Wads.CheckLumpName(lumpnum, "AUTOPAGE")) return NULL;
return new FAutomapTexture(lumpnum); return new FAutomapTexture(lumpnum);
} }
@ -89,6 +91,9 @@ FTexture *AutomapTexture_TryCreate(FileReader &data, int lumpnum)
FAutomapTexture::FAutomapTexture (int lumpnum) FAutomapTexture::FAutomapTexture (int lumpnum)
: Pixels(NULL), LumpNum(lumpnum) : Pixels(NULL), LumpNum(lumpnum)
{ {
Wads.GetLumpName (Name, lumpnum);
Name[8] = 0;
Width = 320; Width = 320;
Height = WORD(Wads.LumpLength(lumpnum) / 320); Height = WORD(Wads.LumpLength(lumpnum) / 320);
CalcBitSize (); CalcBitSize ();

View file

@ -87,7 +87,7 @@ FTexture * FTexture::CreateTexture (int lumpnum, int usetype)
{ RawPageTexture_TryCreate, TEX_MiscPatch }, { RawPageTexture_TryCreate, TEX_MiscPatch },
{ FlatTexture_TryCreate, TEX_Flat }, { FlatTexture_TryCreate, TEX_Flat },
{ PatchTexture_TryCreate, TEX_Any }, { PatchTexture_TryCreate, TEX_Any },
{ AutomapTexture_TryCreate, TEX_Autopage }, { AutomapTexture_TryCreate, TEX_MiscPatch },
}; };
if (lumpnum == -1) return NULL; if (lumpnum == -1) return NULL;

View file

@ -100,9 +100,7 @@ IMPLEMENT_CLASS (AFakeInventory)
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
DECLARE_ACTION(A_ScreamAndUnblock) PSymbolActionFunction *FindGlobalActionFunction(const char *name);
DECLARE_ACTION(A_ActiveAndUnblock)
DECLARE_ACTION(A_ActiveSound)
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
@ -367,24 +365,24 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{ {
if (extra.bExplosive) if (extra.bExplosive)
{ {
info->OwnedStates[extra.DeathStart].Action = GET_ACTION(A_Explode); info->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Explode"));
} }
} }
else else
{ {
// The first frame plays the death sound and // The first frame plays the death sound and
// the second frame makes it nonsolid. // the second frame makes it nonsolid.
info->OwnedStates[extra.DeathStart].Action= GET_ACTION(A_Scream); info->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Scream"));
if (extra.bSolidOnDeath) if (extra.bSolidOnDeath)
{ {
} }
else if (extra.DeathStart + 1 < extra.DeathEnd) else if (extra.DeathStart + 1 < extra.DeathEnd)
{ {
info->OwnedStates[extra.DeathStart+1].Action = GET_ACTION(A_NoBlocking); info->OwnedStates[extra.DeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking"));
} }
else else
{ {
info->OwnedStates[extra.DeathStart].Action = GET_ACTION(A_ScreamAndUnblock); info->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_ScreamAndUnblock"));
} }
if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height; if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height;
@ -412,17 +410,17 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
// The first frame plays the burn sound and // The first frame plays the burn sound and
// the second frame makes it nonsolid. // the second frame makes it nonsolid.
info->OwnedStates[extra.FireDeathStart].Action = GET_ACTION(A_ActiveSound); info->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveSound"));
if (extra.bSolidOnBurn) if (extra.bSolidOnBurn)
{ {
} }
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd) else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
{ {
info->OwnedStates[extra.FireDeathStart+1].Action = GET_ACTION(A_NoBlocking); info->OwnedStates[extra.FireDeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking"));
} }
else else
{ {
info->OwnedStates[extra.FireDeathStart].Action = GET_ACTION(A_ActiveAndUnblock); info->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveAndUnblock"));
} }
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height; if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
@ -442,13 +440,13 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
info->OwnedStates[i].NextState = &info->OwnedStates[info->NumOwnedStates-1]; info->OwnedStates[i].NextState = &info->OwnedStates[info->NumOwnedStates-1];
info->OwnedStates[i].Tics = 5; info->OwnedStates[i].Tics = 5;
info->OwnedStates[i].Misc1 = 0; info->OwnedStates[i].Misc1 = 0;
info->OwnedStates[i].Action = GET_ACTION(A_FreezeDeath); info->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeath"));
i = info->NumOwnedStates - 1; i = info->NumOwnedStates - 1;
info->OwnedStates[i].NextState = &info->OwnedStates[i]; info->OwnedStates[i].NextState = &info->OwnedStates[i];
info->OwnedStates[i].Tics = 1; info->OwnedStates[i].Tics = 1;
info->OwnedStates[i].Misc1 = 0; info->OwnedStates[i].Misc1 = 0;
info->OwnedStates[i].Action = GET_ACTION(A_FreezeDeathChunks); info->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks"));
AddState("Ice", &info->OwnedStates[extra.IceDeathStart]); AddState("Ice", &info->OwnedStates[extra.IceDeathStart]);
} }
else if (extra.bGenericIceDeath) else if (extra.bGenericIceDeath)
@ -859,40 +857,3 @@ static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states, FScanne
} }
} }
//===========================================================================
//
// A_ScreamAndUnblock
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ScreamAndUnblock)
{
CALL_ACTION(A_Scream, self);
CALL_ACTION(A_NoBlocking, self);
}
//===========================================================================
//
// A_ActiveAndUnblock
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ActiveAndUnblock)
{
CALL_ACTION(A_ActiveSound, self);
CALL_ACTION(A_NoBlocking, self);
}
//===========================================================================
//
// A_ActiveSound
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound)
{
if (self->ActiveSound)
{
S_Sound (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM);
}
}

View file

@ -146,6 +146,144 @@ void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
sc.MustGetToken(';'); sc.MustGetToken(';');
} }
//==========================================================================
//
// ParseParameter
//
// Parses aparameter - either a default in a function declaration
// or an argument in a function call.
//
//==========================================================================
int ParseParameter(FScanner &sc, PClass *cls, char type, bool constant)
{
int v;
switch(type)
{
case 'S':
case 's': // Sound name
sc.MustGetString();
return S_FindSound(sc.String);
case 'M':
case 'm': // Actor name
case 'T':
case 't': // String
sc.SetEscape(true);
sc.MustGetString();
sc.SetEscape(false);
return (int)(sc.String[0] ? FName(sc.String) : NAME_None);
case 'C':
case 'c': // Color
sc.MustGetString ();
if (sc.Compare("none"))
{
return -1;
}
else if (sc.Compare(""))
{
return 0;
}
else
{
int c = V_GetColor (NULL, sc.String);
// 0 needs to be the default so we have to mark the color.
return MAKEARGB(1, RPART(c), GPART(c), BPART(c));
}
case 'L':
case 'l':
{
if (JumpParameters.Size()==0) JumpParameters.Push(NAME_None);
v = -(int)JumpParameters.Size();
// This forces quotation marks around the state name.
sc.MustGetToken(TK_StringConst);
if (sc.String[0] == 0 || sc.Compare("None"))
{
return 0;
}
if (sc.Compare("*"))
{
if (constant) return INT_MIN;
else sc.ScriptError("Invalid state name '*'");
}
FString statestring = sc.String; // ParseStateString(sc);
const PClass *stype=NULL;
int scope = statestring.IndexOf("::");
if (scope >= 0)
{
FName scopename = FName(statestring, scope, false);
if (scopename == NAME_Super)
{
// Super refers to the direct superclass
scopename = cls->ParentClass->TypeName;
}
JumpParameters.Push(scopename);
statestring = statestring.Right(statestring.Len()-scope-2);
stype = PClass::FindClass (scopename);
if (stype == NULL)
{
sc.ScriptError ("%s is an unknown class.", scopename.GetChars());
}
if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
{
sc.ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
}
if (!stype->IsAncestorOf (cls))
{
sc.ScriptError ("%s is not derived from %s so cannot access its states.",
cls->TypeName.GetChars(), stype->TypeName.GetChars());
}
}
else
{
// No class name is stored. This allows 'virtual' jumps to
// labels in subclasses.
// It also means that the validity of the given state cannot
// be checked here.
JumpParameters.Push(NAME_None);
}
TArray<FName> names;
MakeStateNameList(statestring, &names);
if (stype != NULL)
{
if (!stype->ActorInfo->FindState(names.Size(), &names[0]))
{
sc.ScriptError("Jump to unknown state '%s' in class '%s'",
statestring.GetChars(), stype->TypeName.GetChars());
}
}
JumpParameters.Push((ENamedName)names.Size());
for(unsigned i=0;i<names.Size();i++)
{
JumpParameters.Push(names[i]);
}
// No offsets here. The point of jumping to labels is to avoid such things!
return v;
}
case 'X':
case 'x':
v = ParseExpression (sc, false, cls);
if (constant && !IsExpressionConst(v))
{
sc.ScriptError("Default parameter must be constant.");
}
return v;
default:
assert(false);
return -1;
}
}
//========================================================================== //==========================================================================
// //
// ActorActionDef // ActorActionDef
@ -158,12 +296,16 @@ void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
static void ParseActionDef (FScanner &sc, PClass *cls) static void ParseActionDef (FScanner &sc, PClass *cls)
{ {
#define OPTIONAL 1 enum
#define EVALNOT 4 {
OPTIONAL = 1
};
AFuncDesc *afd; AFuncDesc *afd;
FName funcname; FName funcname;
FString args; FString args;
TArray<int> DefaultParams;
bool hasdefaults = false;
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
{ {
@ -189,15 +331,7 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
// Retrieve flags before type name // Retrieve flags before type name
for (;;) for (;;)
{ {
if (sc.CheckToken(TK_Optional)) if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native))
{
flags |= OPTIONAL;
}
else if (sc.CheckToken(TK_EvalNot))
{
flags |= EVALNOT;
}
else if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native))
{ {
} }
else else
@ -212,7 +346,7 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
case TK_Bool: case TK_Bool:
case TK_Int: case TK_Int:
case TK_Float: case TK_Float:
type = (flags & EVALNOT)? 'y' : 'x'; type = 'x';
break; break;
case TK_Sound: type = 's'; break; case TK_Sound: type = 's'; break;
@ -244,13 +378,24 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
{ {
sc.UnGet(); sc.UnGet();
} }
int def;
if (sc.CheckToken('='))
{
hasdefaults = true;
flags|=OPTIONAL;
def = ParseParameter(sc, cls, type, true);
}
else
{
def = 0;
}
DefaultParams.Push(def);
if (!(flags & OPTIONAL) && type != '+') if (!(flags & OPTIONAL) && type != '+')
{ {
type -= 'a' - 'A'; type -= 'a' - 'A';
} }
#undef OPTIONAL
#undef EVAL
#undef EVALNOT
args += type; args += type;
sc.MustGetAnyToken(); sc.MustGetAnyToken();
if (sc.TokenType != ',' && sc.TokenType != ')') if (sc.TokenType != ',' && sc.TokenType != ')')
@ -265,6 +410,15 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
sym->SymbolType = SYM_ActionFunction; sym->SymbolType = SYM_ActionFunction;
sym->Arguments = args; sym->Arguments = args;
sym->Function = afd->Function; sym->Function = afd->Function;
if (hasdefaults)
{
sym->defaultparameterindex = StateParameters.Size();
for(int i = 0; i < DefaultParams.Size(); i++) StateParameters.Push(DefaultParams[i]);
}
else
{
sym->defaultparameterindex = -1;
}
if (cls->Symbols.AddSymbol (sym) == NULL) if (cls->Symbols.AddSymbol (sym) == NULL)
{ {
delete sym; delete sym;

View file

@ -84,6 +84,7 @@ struct AFuncDesc
AFuncDesc * FindFunction(const char * string); AFuncDesc * FindFunction(const char * string);
//========================================================================== //==========================================================================
// //
// State parser // State parser
@ -116,20 +117,16 @@ void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag);
void ParseConstant (FScanner &sc, PSymbolTable *symt, PClass *cls); void ParseConstant (FScanner &sc, PSymbolTable *symt, PClass *cls);
void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls); void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls);
int ParseParameter(FScanner &sc, PClass *cls, char type, bool constant);
int ParseExpression (FScanner &sc, bool _not, PClass *cls); int ParseExpression (FScanner &sc, bool _not, PClass *cls);
bool IsExpressionConst(int id);
int EvalExpressionI (int id, AActor *self, const PClass *cls=NULL); int EvalExpressionI (int id, AActor *self, const PClass *cls=NULL);
float EvalExpressionF (int id, AActor *self, const PClass *cls=NULL); float EvalExpressionF (int id, AActor *self, const PClass *cls=NULL);
bool EvalExpressionN (int id, AActor *self, const PClass *cls=NULL);
// A truly awful hack to get to the state that called an action function
// without knowing whether it has been called from a weapon or actor.
extern FState * CallingState;
int CheckIndex(int paramsize, FState ** pcallstate=NULL);
enum enum
{ {
ACMETA_BASE = 0x83000, ACMETA_BASE = 0x83000,
@ -167,42 +164,51 @@ enum EDefinitionType
// Macros to handle action functions. These are here so that I don't have to // Macros to handle action functions. These are here so that I don't have to
// change every single use in case the parameters change. // change every single use in case the parameters change.
#define DECLARE_ACTION(name) void AF_##name(AActor *self); #define DECLARE_ACTION(name) void AF_##name(AActor *self, FState *, int);
// This distinction is here so that CALL_ACTION produces errors when trying to
// access a function that requires parameters.
#define DEFINE_ACTION_FUNCTION(cls, name) \ #define DEFINE_ACTION_FUNCTION(cls, name) \
void AF_##name (AActor *); \ void AF_##name (AActor *self, FState *, int); \
AFuncDesc info_##cls##_##name = { #name, AF_##name }; \ AFuncDesc info_##cls##_##name = { #name, AF_##name }; \
MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \ MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \
void AF_##name (AActor *self) void AF_##name (AActor *self, FState *, int)
#define CALL_ACTION(name,self) AF_##name(self) #define DEFINE_ACTION_FUNCTION_PARAMS(cls, name) \
#define GET_ACTION(name) AF_##name void AFP_##name (AActor *self, FState *CallingState, int ParameterIndex); \
AFuncDesc info_##cls##_##name = { #name, AFP_##name }; \
MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \
void AFP_##name (AActor *self, FState *CallingState, int ParameterIndex)
#define DECLARE_PARAMINFO FState *CallingState, int ParameterIndex
#define PUSH_PARAMINFO CallingState, ParameterIndex
#define CALL_ACTION(name,self) AF_##name(self, NULL, 0)
#define CheckIndex(count) (ParameterIndex-1)
#define ACTION_PARAM_START(count) \ #define ACTION_PARAM_START(count) \
int index = CheckIndex(count); \ int ap_index_ = CheckIndex(count); \
if (index <= 0) return; if (ap_index_ <= 0) return;
#define ACTION_PARAM_START_OPTIONAL(count) \ #define ACTION_PARAM_START_OPTIONAL(count) \
int index = CheckIndex(count); int ap_index_ = CheckIndex(count);
#define ACTION_INT_PARAM(var) \
int var = EvalExpressionI(StateParameters[index++], self);
#define ACTION_BOOL_PARAM(var) \
bool var = !!EvalExpressionI(StateParameters[index++], self);
#define ACTION_NOT_BOOL_PARAM(var) \
bool var = EvalExpressionN(StateParameters[index++], self);
#define ACTION_FIXED_PARAM(var) \
fixed_t var = fixed_t(EvalExpressionF(StateParameters[index++], self)*65536.f);
#define ACTION_FLOAT_PARAM(var) \
float var = EvalExpressionF(StateParameters[index++], self);
#define ACTION_CLASS_PARAM(var) \
const PClass *var = PClass::FindClass(ENamedName(StateParameters[index++]));
#define ACTION_STATE_PARAM(var) \
int var = StateParameters[index++];
#define ACTION_SOUND_PARAM(var) \
FSoundID var = StateParameters[index++];
#define ACTION_STRING_PARAM(var) \
const char *var = FName(ENamedName(StateParameters[index++]));
#define ACTION_PARAM_INT(var) \
int var = EvalExpressionI(StateParameters[ap_index_++], self);
#define ACTION_PARAM_BOOL(var) \
bool var = !!EvalExpressionI(StateParameters[ap_index_++], self);
#define ACTION_PARAM_FIXED(var) \
fixed_t var = fixed_t(EvalExpressionF(StateParameters[ap_index_++], self)*65536.f);
#define ACTION_PARAM_FLOAT(var) \
float var = EvalExpressionF(StateParameters[ap_index_++], self);
#define ACTION_PARAM_CLASS(var) \
const PClass *var = PClass::FindClass(ENamedName(StateParameters[ap_index_++]));
#define ACTION_PARAM_STATE(var) \
int var = StateParameters[ap_index_++];
#define ACTION_PARAM_SOUND(var) \
FSoundID var = StateParameters[ap_index_++];
#define ACTION_PARAM_STRING(var) \
const char *var = FName(ENamedName(StateParameters[ap_index_++]));
#endif #endif

View file

@ -82,7 +82,6 @@ static FRandom pr_burst ("Burst");
// A truly awful hack to get to the state that called an action function // A truly awful hack to get to the state that called an action function
// without knowing whether it has been called from a weapon or actor. // without knowing whether it has been called from a weapon or actor.
FState * CallingState;
struct StateCallData struct StateCallData
{ {
@ -114,11 +113,10 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState * State)
while (State != NULL) while (State != NULL)
{ {
// Assume success. The code pointer will set this to false if necessary // Assume success. The code pointer will set this to false if necessary
CallingState = StateCall.State = State; StateCall.State = State;
if (State->GetAction() != NULL) StateCall.Result = true;
if (State->CallAction(actor))
{ {
StateCall.Result = true;
State->GetAction() (actor);
// collect all the results. Even one successful call signifies overall success. // collect all the results. Even one successful call signifies overall success.
result |= StateCall.Result; result |= StateCall.Result;
} }
@ -150,23 +148,6 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState * State)
return result; return result;
} }
//==========================================================================
//
// Let's isolate all handling of CallingState in this one place
// so that removing it later becomes easier
//
//==========================================================================
int CheckIndex(int paramsize, FState ** pcallstate)
{
if (CallingState->ParameterIndex == 0) return -1;
unsigned int index = (unsigned int) CallingState->ParameterIndex-1;
if (index > StateParameters.Size()-paramsize) return -1;
if (pcallstate) *pcallstate=CallingState;
return index;
}
//========================================================================== //==========================================================================
// //
// Simple flag changers // Simple flag changers
@ -195,34 +176,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_UnsetFloat)
//========================================================================== //==========================================================================
// //
// Customizable attack functions which use actor parameters. // Customizable attack functions which use actor parameters.
// I think this is among the most requested stuff ever ;-)
// //
//========================================================================== //==========================================================================
static void DoAttack (AActor *self, bool domelee, bool domissile) static void DoAttack (AActor *self, bool domelee, bool domissile,
int MeleeDamage, FSoundID MeleeSound, const PClass *MissileType,fixed_t MissileHeight)
{ {
int index=CheckIndex(4);
int MeleeDamage;
int MeleeSound;
FName MissileName;
fixed_t MissileHeight;
if (self->target == NULL) return; if (self->target == NULL) return;
if (index > 0)
{
MeleeDamage=EvalExpressionI(StateParameters[index], self);
MeleeSound=StateParameters[index+1];
MissileName=(ENamedName)StateParameters[index+2];
MissileHeight=fixed_t(EvalExpressionF(StateParameters[index+3], self)/65536.f);
}
else
{
MeleeDamage = self->GetClass()->Meta.GetMetaInt (ACMETA_MeleeDamage, 0);
MeleeSound = self->GetClass()->Meta.GetMetaInt (ACMETA_MeleeSound, 0);
MissileName=(ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None);
MissileHeight= self->GetClass()->Meta.GetMetaFixed (ACMETA_MissileHeight, 32*FRACUNIT);
}
A_FaceTarget (self); A_FaceTarget (self);
if (domelee && MeleeDamage>0 && self->CheckMeleeRange ()) if (domelee && MeleeDamage>0 && self->CheckMeleeRange ())
{ {
@ -231,52 +191,65 @@ static void DoAttack (AActor *self, bool domelee, bool domissile)
P_DamageMobj (self->target, self, self, damage, NAME_Melee); P_DamageMobj (self->target, self, self, damage, NAME_Melee);
P_TraceBleed (damage, self->target, self); P_TraceBleed (damage, self->target, self);
} }
else if (domissile && MissileName != NAME_None) else if (domissile && MissileType != NULL)
{ {
const PClass * ti=PClass::FindClass(MissileName); // This seemingly senseless code is needed for proper aiming.
if (ti) self->z+=MissileHeight-32*FRACUNIT;
{ AActor * missile = P_SpawnMissileXYZ (self->x, self->y, self->z + 32*FRACUNIT, self, self->target, MissileType, false);
// This seemingly senseless code is needed for proper aiming. self->z-=MissileHeight-32*FRACUNIT;
self->z+=MissileHeight-32*FRACUNIT;
AActor * missile = P_SpawnMissileXYZ (self->x, self->y, self->z + 32*FRACUNIT, self, self->target, ti, false);
self->z-=MissileHeight-32*FRACUNIT;
if (missile) if (missile)
{
// automatic handling of seeker missiles
if (missile->flags2&MF2_SEEKERMISSILE)
{ {
// automatic handling of seeker missiles missile->tracer=self->target;
if (missile->flags2&MF2_SEEKERMISSILE)
{
missile->tracer=self->target;
}
// set the health value so that the missile works properly
if (missile->flags4&MF4_SPECTRAL)
{
missile->health=-2;
}
P_CheckMissileSpawn(missile);
} }
// set the health value so that the missile works properly
if (missile->flags4&MF4_SPECTRAL)
{
missile->health=-2;
}
P_CheckMissileSpawn(missile);
} }
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack) DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack)
{ {
DoAttack(self, true, false); int MeleeDamage = self->GetClass()->Meta.GetMetaInt (ACMETA_MeleeDamage, 0);
FSoundID MeleeSound = self->GetClass()->Meta.GetMetaInt (ACMETA_MeleeSound, 0);
DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0);
} }
DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack) DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack)
{ {
DoAttack(self, false, true); const PClass *MissileType=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None));
fixed_t MissileHeight= self->GetClass()->Meta.GetMetaFixed (ACMETA_MissileHeight, 32*FRACUNIT);
DoAttack(self, false, true, 0, 0, MissileType, MissileHeight);
} }
DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack) DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack)
{ {
DoAttack(self, true, true); int MeleeDamage = self->GetClass()->Meta.GetMetaInt (ACMETA_MeleeDamage, 0);
FSoundID MeleeSound = self->GetClass()->Meta.GetMetaInt (ACMETA_MeleeSound, 0);
const PClass *MissileType=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None));
fixed_t MissileHeight= self->GetClass()->Meta.GetMetaFixed (ACMETA_MissileHeight, 32*FRACUNIT);
DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
} }
DEFINE_ACTION_FUNCTION(AActor, A_BasicAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack)
{ {
DoAttack(self, true, true); int index=CheckIndex(4);
if (index > 0)
{
int MeleeDamage=EvalExpressionI(StateParameters[index], self);
FSoundID MeleeSound=StateParameters[index+1];
const PClass *MissileType=PClass::FindClass((ENamedName)StateParameters[index+2]);
fixed_t MissileHeight=fixed_t(EvalExpressionF(StateParameters[index+3], self)/65536.f);
DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
}
} }
//========================================================================== //==========================================================================
@ -286,23 +259,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_BasicAttack)
// misc field directly so they can be used in weapon states // misc field directly so they can be used in weapon states
// //
//========================================================================== //==========================================================================
static void DoPlaySound(AActor * self, int channel)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound)
{ {
int index=CheckIndex(1); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
int soundid = StateParameters[index]; int soundid = StateParameters[index];
S_Sound (self, channel, soundid, 1, ATTN_NORM); S_Sound (self, CHAN_BODY, soundid, 1, ATTN_NORM);
} }
DEFINE_ACTION_FUNCTION(AActor, A_PlaySound) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayWeaponSound)
{ {
DoPlaySound(self, CHAN_BODY); int index=CheckIndex(1);
} if (index<0) return;
DEFINE_ACTION_FUNCTION(AActor, A_PlayWeaponSound) int soundid = StateParameters[index];
{ S_Sound (self, CHAN_WEAPON, soundid, 1, ATTN_NORM);
DoPlaySound(self, CHAN_WEAPON);
} }
DEFINE_ACTION_FUNCTION(AActor, A_StopSound) DEFINE_ACTION_FUNCTION(AActor, A_StopSound)
@ -310,7 +283,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StopSound)
S_StopSound(self, CHAN_VOICE); S_StopSound(self, CHAN_VOICE);
} }
DEFINE_ACTION_FUNCTION(AActor, A_PlaySoundEx) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx)
{ {
int index = CheckIndex(4); int index = CheckIndex(4);
if (index < 0) return; if (index < 0) return;
@ -348,7 +321,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlaySoundEx)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_StopSoundEx) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSoundEx)
{ {
int index = CheckIndex (1); int index = CheckIndex (1);
if (index < 0) return; if (index < 0) return;
@ -366,7 +339,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StopSoundEx)
// Generic seeker missile function // Generic seeker missile function
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SeekerMissile) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile)
{ {
int index=CheckIndex(2); int index=CheckIndex(2);
if (index<0) return; if (index<0) return;
@ -381,7 +354,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SeekerMissile)
// Hitscan attack with a customizable amount of bullets (specified in damage) // Hitscan attack with a customizable amount of bullets (specified in damage)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BulletAttack)
{ {
int i; int i;
int bangle; int bangle;
@ -413,7 +386,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack)
FState *P_GetState(AActor *self, FState *CallingState, int offset) FState *P_GetState(AActor *self, FState *CallingState, int offset)
{ {
if (offset == 0) if (offset == 0 || offset == INT_MIN)
{ {
return NULL; // 0 means 'no state' return NULL; // 0 means 'no state'
} }
@ -488,10 +461,9 @@ static void DoJump(AActor * self, FState * CallingState, int offset)
// State jump function // State jump function
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_Jump) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump)
{ {
FState * CallingState; int index = CheckIndex(3);
int index = CheckIndex(3, &CallingState);
int maxchance; int maxchance;
if (index >= 0 && if (index >= 0 &&
@ -516,10 +488,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Jump)
// State jump function // State jump function
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfHealthLower) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower)
{ {
FState * CallingState; int index=CheckIndex(2);
int index=CheckIndex(2, &CallingState);
if (index>=0 && self->health < EvalExpressionI (StateParameters[index], self)) if (index>=0 && self->health < EvalExpressionI (StateParameters[index], self))
DoJump(self, CallingState, StateParameters[index+1]); DoJump(self, CallingState, StateParameters[index+1]);
@ -532,10 +503,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_JumpIfHealthLower)
// State jump function // State jump function
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfCloser) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfCloser)
{ {
FState * CallingState = NULL; int index = CheckIndex(2);
int index = CheckIndex(2, &CallingState);
AActor * target; AActor * target;
if (!self->player) if (!self->player)
@ -567,10 +537,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_JumpIfCloser)
// State jump function // State jump function
// //
//========================================================================== //==========================================================================
void DoJumpIfInventory(AActor * self, AActor * owner) void DoJumpIfInventory(AActor * self, AActor * owner, DECLARE_PARAMINFO)
{ {
FState * CallingState; int index=CheckIndex(3);
int index=CheckIndex(3, &CallingState);
if (index<0) return; if (index<0) return;
ENamedName ItemType=(ENamedName)StateParameters[index]; ENamedName ItemType=(ENamedName)StateParameters[index];
@ -591,14 +560,14 @@ void DoJumpIfInventory(AActor * self, AActor * owner)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfInventory) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInventory)
{ {
DoJumpIfInventory(self, self); DoJumpIfInventory(self, self, PUSH_PARAMINFO);
} }
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfInTargetInventory) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetInventory)
{ {
DoJumpIfInventory(self, self->target); DoJumpIfInventory(self, self->target, PUSH_PARAMINFO);
} }
//========================================================================== //==========================================================================
@ -607,7 +576,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JumpIfInTargetInventory)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_Explode) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{ {
int damage; int damage;
int distance; int distance;
@ -615,22 +584,24 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode)
bool alert; bool alert;
int index=CheckIndex(4); int index=CheckIndex(4);
if (index>=0) if (index < 0) return;
{
damage = EvalExpressionI (StateParameters[index], self); damage = EvalExpressionI (StateParameters[index], self);
distance = EvalExpressionI (StateParameters[index+1], self); distance = EvalExpressionI (StateParameters[index+1], self);
hurtSource = EvalExpressionN (StateParameters[index+2], self); hurtSource = !!EvalExpressionI (StateParameters[index+2], self);
if (damage == 0) damage = 128; alert = !!EvalExpressionI (StateParameters[index+3], self);
if (distance == 0) distance = damage;
alert = !!EvalExpressionI (StateParameters[index+3], self); if (damage < 0) // get parameters from metadata
}
else
{ {
damage = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionDamage, 128); damage = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionDamage, 128);
distance = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionRadius, damage); distance = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionRadius, damage);
hurtSource = !self->GetClass()->Meta.GetMetaInt (ACMETA_DontHurtShooter); hurtSource = !self->GetClass()->Meta.GetMetaInt (ACMETA_DontHurtShooter);
alert = false; alert = false;
} }
else
{
if (distance <= 0) distance = damage;
}
P_RadiusAttack (self, self->target, damage, distance, self->DamageType, hurtSource); P_RadiusAttack (self, self->target, damage, distance, self->DamageType, hurtSource);
if (self->z <= self->floorz + (distance<<FRACBITS)) if (self->z <= self->floorz + (distance<<FRACBITS))
@ -650,21 +621,21 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_RadiusThrust) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust)
{ {
int force = 0; int force = 0;
int distance = 0; int distance = 0;
bool affectSource = true; bool affectSource = true;
int index=CheckIndex(3); int index=CheckIndex(3);
if (index>=0) if (index < 0) return;
{
force = EvalExpressionI (StateParameters[index], self); force = EvalExpressionI (StateParameters[index], self);
distance = EvalExpressionI (StateParameters[index+1], self); distance = EvalExpressionI (StateParameters[index+1], self);
affectSource = EvalExpressionN (StateParameters[index+2], self); affectSource = !!EvalExpressionI (StateParameters[index+2], self);
}
if (force == 0) force = 128; if (force <= 0) force = 128;
if (distance == 0) distance = force; if (distance <= 0) distance = force;
P_RadiusAttack (self, self->target, force, distance, self->DamageType, affectSource, false); P_RadiusAttack (self, self->target, force, distance, self->DamageType, affectSource, false);
if (self->z <= self->floorz + (distance<<FRACBITS)) if (self->z <= self->floorz + (distance<<FRACBITS))
@ -678,7 +649,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RadiusThrust)
// Execute a line special / script // Execute a line special / script
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CallSpecial) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CallSpecial)
{ {
int index=CheckIndex(6); int index=CheckIndex(6);
if (index<0) return; if (index<0) return;
@ -718,7 +689,7 @@ enum CM_Flags
CMF_CHECKTARGETDEAD = 8, CMF_CHECKTARGETDEAD = 8,
}; };
DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
{ {
int index=CheckIndex(6); int index=CheckIndex(6);
if (index<0) return; if (index<0) return;
@ -840,7 +811,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile)
// An even more customizable hitscan attack // An even more customizable hitscan attack
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CustomBulletAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack)
{ {
int index=CheckIndex(7); int index=CheckIndex(7);
if (index<0) return; if (index<0) return;
@ -887,7 +858,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomBulletAttack)
// A fully customizable melee attack // A fully customizable melee attack
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CustomMeleeAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMeleeAttack)
{ {
int index=CheckIndex(5); int index=CheckIndex(5);
if (index<0) return; if (index<0) return;
@ -896,7 +867,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMeleeAttack)
int MeleeSound = StateParameters[index+1]; int MeleeSound = StateParameters[index+1];
int MissSound = StateParameters[index+2]; int MissSound = StateParameters[index+2];
ENamedName DamageType = (ENamedName)StateParameters[index+3]; ENamedName DamageType = (ENamedName)StateParameters[index+3];
bool bleed = EvalExpressionN (StateParameters[index+4], self); bool bleed = !!EvalExpressionI (StateParameters[index+4], self);
if (DamageType==NAME_None) DamageType = NAME_Melee; // Melee is the default type if (DamageType==NAME_None) DamageType = NAME_Melee; // Melee is the default type
@ -921,7 +892,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMeleeAttack)
// A fully customizable combo attack // A fully customizable combo attack
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack)
{ {
int index=CheckIndex(6); int index=CheckIndex(6);
if (index<0) return; if (index<0) return;
@ -931,7 +902,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack)
int damage = EvalExpressionI (StateParameters[index+2], self); int damage = EvalExpressionI (StateParameters[index+2], self);
int MeleeSound = StateParameters[index+3]; int MeleeSound = StateParameters[index+3];
ENamedName DamageType = (ENamedName)StateParameters[index+4]; ENamedName DamageType = (ENamedName)StateParameters[index+4];
bool bleed = EvalExpressionN (StateParameters[index+5], self); bool bleed = !!EvalExpressionI (StateParameters[index+5], self);
if (!self->target) if (!self->target)
@ -978,10 +949,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack)
// State jump function // State jump function
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfNoAmmo) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo)
{ {
FState * CallingState = NULL; int index=CheckIndex(1);
int index=CheckIndex(1, &CallingState);
if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains!
if (index<0 || !self->player || !self->player->ReadyWeapon || pStateCall != NULL) return; // only for weapons! if (index<0 || !self->player || !self->player->ReadyWeapon || pStateCall != NULL) return; // only for weapons!
@ -997,7 +967,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JumpIfNoAmmo)
// An even more customizable hitscan attack // An even more customizable hitscan attack
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FireBullets) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets)
{ {
int index=CheckIndex(7); int index=CheckIndex(7);
if (index<0 || !self->player) return; if (index<0 || !self->player) return;
@ -1007,7 +977,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBullets)
int NumberOfBullets=EvalExpressionI (StateParameters[index+2], self); int NumberOfBullets=EvalExpressionI (StateParameters[index+2], self);
int DamagePerBullet=EvalExpressionI (StateParameters[index+3], self); int DamagePerBullet=EvalExpressionI (StateParameters[index+3], self);
ENamedName PuffTypeName=(ENamedName)StateParameters[index+4]; ENamedName PuffTypeName=(ENamedName)StateParameters[index+4];
bool UseAmmo=EvalExpressionN (StateParameters[index+5], self); bool UseAmmo=!!EvalExpressionI (StateParameters[index+5], self);
fixed_t Range=fixed_t(EvalExpressionF (StateParameters[index+6], self) * FRACUNIT); fixed_t Range=fixed_t(EvalExpressionF (StateParameters[index+6], self) * FRACUNIT);
const PClass * PuffType; const PClass * PuffType;
@ -1060,14 +1030,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBullets)
// A_FireProjectile // A_FireProjectile
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FireCustomMissile) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
{ {
int index=CheckIndex(6); int index=CheckIndex(6);
if (index<0 || !self->player) return; if (index<0 || !self->player) return;
ENamedName MissileName=(ENamedName)StateParameters[index]; ENamedName MissileName=(ENamedName)StateParameters[index];
angle_t Angle=angle_t(EvalExpressionF (StateParameters[index+1], self) * ANGLE_1); angle_t Angle=angle_t(EvalExpressionF (StateParameters[index+1], self) * ANGLE_1);
bool UseAmmo=EvalExpressionN (StateParameters[index+2], self); bool UseAmmo=!!EvalExpressionI (StateParameters[index+2], self);
int SpawnOfs_XY=EvalExpressionI (StateParameters[index+3], self); int SpawnOfs_XY=EvalExpressionI (StateParameters[index+3], self);
fixed_t SpawnHeight=fixed_t(EvalExpressionF (StateParameters[index+4], self) * FRACUNIT); fixed_t SpawnHeight=fixed_t(EvalExpressionF (StateParameters[index+4], self) * FRACUNIT);
INTBOOL AimAtAngle=EvalExpressionI (StateParameters[index+5], self); INTBOOL AimAtAngle=EvalExpressionI (StateParameters[index+5], self);
@ -1120,14 +1090,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCustomMissile)
// Berserk is not handled here. That can be done with A_CheckIfInventory // Berserk is not handled here. That can be done with A_CheckIfInventory
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
{ {
int index=CheckIndex(5); int index=CheckIndex(5);
if (index<0 || !self->player) return; if (index<0 || !self->player) return;
int Damage=EvalExpressionI (StateParameters[index], self); int Damage=EvalExpressionI (StateParameters[index], self);
bool norandom=!!EvalExpressionI (StateParameters[index+1], self); bool norandom=!!EvalExpressionI (StateParameters[index+1], self);
bool UseAmmo=EvalExpressionN (StateParameters[index+2], self); bool UseAmmo=!!EvalExpressionI (StateParameters[index+2], self);
ENamedName PuffTypeName=(ENamedName)StateParameters[index+3]; ENamedName PuffTypeName=(ENamedName)StateParameters[index+3];
fixed_t Range=fixed_t(EvalExpressionF (StateParameters[index+4], self) * FRACUNIT); fixed_t Range=fixed_t(EvalExpressionF (StateParameters[index+4], self) * FRACUNIT);
@ -1177,14 +1147,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomPunch)
// customizable railgun attack function // customizable railgun attack function
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_RailAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
{ {
int index=CheckIndex(7); int index=CheckIndex(7);
if (index<0 || !self->player) return; if (index<0 || !self->player) return;
int Damage=EvalExpressionI (StateParameters[index], self); int Damage=EvalExpressionI (StateParameters[index], self);
int Spawnofs_XY=EvalExpressionI (StateParameters[index+1], self); int Spawnofs_XY=EvalExpressionI (StateParameters[index+1], self);
bool UseAmmo=EvalExpressionN (StateParameters[index+2], self); bool UseAmmo=!!EvalExpressionI (StateParameters[index+2], self);
int Color1=StateParameters[index+3]; int Color1=StateParameters[index+3];
int Color2=StateParameters[index+4]; int Color2=StateParameters[index+4];
bool Silent=!!EvalExpressionI (StateParameters[index+5], self); bool Silent=!!EvalExpressionI (StateParameters[index+5], self);
@ -1208,7 +1178,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RailAttack)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
{ {
int index = CheckIndex(7); int index = CheckIndex(7);
if (index < 0) return; if (index < 0) return;
@ -1267,7 +1237,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun)
// //
//=========================================================================== //===========================================================================
static void DoGiveInventory(AActor * self, AActor * receiver) static void DoGiveInventory(AActor * self, AActor * receiver, DECLARE_PARAMINFO)
{ {
int index=CheckIndex(2); int index=CheckIndex(2);
bool res=true; bool res=true;
@ -1307,14 +1277,14 @@ static void DoGiveInventory(AActor * self, AActor * receiver)
} }
DEFINE_ACTION_FUNCTION(AActor, A_GiveInventory) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveInventory)
{ {
DoGiveInventory(self, self); DoGiveInventory(self, self, PUSH_PARAMINFO);
} }
DEFINE_ACTION_FUNCTION(AActor, A_GiveToTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget)
{ {
DoGiveInventory(self, self->target); DoGiveInventory(self, self->target, PUSH_PARAMINFO);
} }
//=========================================================================== //===========================================================================
@ -1323,7 +1293,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GiveToTarget)
// //
//=========================================================================== //===========================================================================
void DoTakeInventory(AActor * self, AActor * receiver) void DoTakeInventory(AActor * self, AActor * receiver, DECLARE_PARAMINFO)
{ {
int index=CheckIndex(2); int index=CheckIndex(2);
if (index<0 || receiver == NULL) return; if (index<0 || receiver == NULL) return;
@ -1347,14 +1317,14 @@ void DoTakeInventory(AActor * self, AActor * receiver)
} }
} }
DEFINE_ACTION_FUNCTION(AActor, A_TakeInventory) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeInventory)
{ {
DoTakeInventory(self, self); DoTakeInventory(self, self, PUSH_PARAMINFO);
} }
DEFINE_ACTION_FUNCTION(AActor, A_TakeFromTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget)
{ {
DoTakeInventory(self, self->target); DoTakeInventory(self, self->target, PUSH_PARAMINFO);
} }
//=========================================================================== //===========================================================================
@ -1450,16 +1420,15 @@ static void InitSpawnedItem(AActor *self, AActor *mo, int flags)
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
{ {
FState * CallingState; int index=CheckIndex(5);
int index=CheckIndex(5, &CallingState);
if (index<0) return; if (index<0) return;
const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]); const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]);
fixed_t distance = fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT); fixed_t distance = fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT);
fixed_t zheight = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT); fixed_t zheight = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT);
bool useammo = EvalExpressionN (StateParameters[index+3], self); bool useammo = !!EvalExpressionI (StateParameters[index+3], self);
INTBOOL transfer_translation = EvalExpressionI (StateParameters[index+4], self); INTBOOL transfer_translation = EvalExpressionI (StateParameters[index+4], self);
if (!missile) if (!missile)
@ -1502,10 +1471,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem)
// Enhanced spawning function // Enhanced spawning function
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
{ {
FState * CallingState; int index=CheckIndex(9);
int index=CheckIndex(9, &CallingState);
if (index<0) return; if (index<0) return;
const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]); const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]);
@ -1579,17 +1547,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx)
// Throws a grenade (like Hexen's fighter flechette) // Throws a grenade (like Hexen's fighter flechette)
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
{ {
FState * CallingState; int index=CheckIndex(5);
int index=CheckIndex(5, &CallingState);
if (index<0) return; if (index<0) return;
const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]); const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]);
fixed_t zheight = fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT); fixed_t zheight = fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT);
fixed_t xymom = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT); fixed_t xymom = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT);
fixed_t zmom = fixed_t(EvalExpressionF (StateParameters[index+3], self) * FRACUNIT); fixed_t zmom = fixed_t(EvalExpressionF (StateParameters[index+3], self) * FRACUNIT);
bool useammo = EvalExpressionN (StateParameters[index+4], self); bool useammo = !!EvalExpressionI (StateParameters[index+4], self);
if (self->player && CallingState != self->state && (pStateCall==NULL || CallingState != pStateCall->State)) if (self->player && CallingState != self->state && (pStateCall==NULL || CallingState != pStateCall->State))
{ {
@ -1635,9 +1602,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade)
// A_Recoil // A_Recoil
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_Recoil) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Recoil)
{ {
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
fixed_t xymom = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT); fixed_t xymom = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT);
@ -1653,9 +1620,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Recoil)
// A_SelectWeapon // A_SelectWeapon
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SelectWeapon) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon)
{ {
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index<0 || self->player == NULL) return; if (index<0 || self->player == NULL) return;
AWeapon * weaponitem = static_cast<AWeapon*>(self->FindInventory((ENamedName)StateParameters[index])); AWeapon * weaponitem = static_cast<AWeapon*>(self->FindInventory((ENamedName)StateParameters[index]));
@ -1678,9 +1645,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectWeapon)
//=========================================================================== //===========================================================================
EXTERN_CVAR(Float, con_midtime) EXTERN_CVAR(Float, con_midtime)
DEFINE_ACTION_FUNCTION(AActor, A_Print) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print)
{ {
int index=CheckIndex(3, NULL); int index=CheckIndex(3);
if (index<0) return; if (index<0) return;
if (self->CheckLocalView (consoleplayer) || if (self->CheckLocalView (consoleplayer) ||
@ -1714,9 +1681,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Print)
// A_SetTranslucent // A_SetTranslucent
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SetTranslucent) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslucent)
{ {
int index=CheckIndex(2, NULL); int index=CheckIndex(2);
if (index<0) return; if (index<0) return;
fixed_t alpha = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT); fixed_t alpha = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT);
@ -1735,11 +1702,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetTranslucent)
// Fades the actor in // Fades the actor in
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FadeIn) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeIn)
{ {
fixed_t reduce = 0; fixed_t reduce = 0;
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index>=0) if (index>=0)
{ {
reduce = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT); reduce = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT);
@ -1759,11 +1726,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_FadeIn)
// fades the actor out and destroys it when done // fades the actor out and destroys it when done
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FadeOut) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeOut)
{ {
fixed_t reduce = 0; fixed_t reduce = 0;
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index>=0) if (index>=0)
{ {
reduce = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT); reduce = fixed_t(EvalExpressionF (StateParameters[index], self) * FRACUNIT);
@ -1781,13 +1748,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FadeOut)
// A_SpawnDebris // A_SpawnDebris
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SpawnDebris) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris)
{ {
int i; int i;
AActor * mo; AActor * mo;
const PClass * debris; const PClass * debris;
int index=CheckIndex(4, NULL); int index=CheckIndex(4);
if (index<0) return; if (index<0) return;
debris = PClass::FindClass((ENamedName)StateParameters[index]); debris = PClass::FindClass((ENamedName)StateParameters[index]);
@ -1827,7 +1794,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnDebris)
// jumps if no player can see this actor // jumps if no player can see this actor
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CheckSight) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight)
{ {
if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains!
@ -1836,8 +1803,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckSight)
if (playeringame[i] && P_CheckSight(players[i].camera,self,true)) return; if (playeringame[i] && P_CheckSight(players[i].camera,self,true)) return;
} }
FState * CallingState; int index=CheckIndex(1);
int index=CheckIndex(1, &CallingState);
if (index>=0) DoJump(self, CallingState, StateParameters[index]); if (index>=0) DoJump(self, CallingState, StateParameters[index]);
@ -1849,9 +1815,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckSight)
// Inventory drop // Inventory drop
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_DropInventory) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropInventory)
{ {
int index=CheckIndex(1, &CallingState); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
AInventory * inv = self->FindInventory((ENamedName)StateParameters[index]); AInventory * inv = self->FindInventory((ENamedName)StateParameters[index]);
@ -1867,7 +1833,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DropInventory)
// A_SetBlend // A_SetBlend
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SetBlend) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetBlend)
{ {
int index=CheckIndex(3); int index=CheckIndex(3);
if (index<0) return; if (index<0) return;
@ -1892,10 +1858,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetBlend)
// A_JumpIf // A_JumpIf
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_JumpIf) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIf)
{ {
FState * CallingState; int index=CheckIndex(2);
int index=CheckIndex(2, &CallingState);
if (index<0) return; if (index<0) return;
INTBOOL expression = EvalExpressionI (StateParameters[index], self); INTBOOL expression = EvalExpressionI (StateParameters[index], self);
@ -1941,7 +1906,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KillChildren)
// A_CountdownArg // A_CountdownArg
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CountdownArg) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg)
{ {
int index=CheckIndex(1); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
@ -1972,11 +1937,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_CountdownArg)
// //
//============================================================================ //============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_Burst) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
{ {
int i, numChunks; int i, numChunks;
AActor * mo; AActor * mo;
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
const PClass * chunk = PClass::FindClass((ENamedName)StateParameters[index]); const PClass * chunk = PClass::FindClass((ENamedName)StateParameters[index]);
if (chunk == NULL) return; if (chunk == NULL) return;
@ -2025,10 +1990,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burst)
// [GRB] Jumps if actor is standing on floor // [GRB] Jumps if actor is standing on floor
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CheckFloor) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFloor)
{ {
FState *CallingState = NULL; int index = CheckIndex (1);
int index = CheckIndex (1, &CallingState);
if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains!
if (self->z <= self->floorz && index >= 0) if (self->z <= self->floorz && index >= 0)
@ -2060,7 +2024,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Stop)
// A_Respawn // A_Respawn
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_Respawn) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
{ {
fixed_t x = self->SpawnPoint[0]; fixed_t x = self->SpawnPoint[0];
fixed_t y = self->SpawnPoint[1]; fixed_t y = self->SpawnPoint[1];
@ -2083,8 +2047,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_Respawn)
self->SetState (self->SpawnState); self->SetState (self->SpawnState);
self->renderflags &= ~RF_INVISIBLE; self->renderflags &= ~RF_INVISIBLE;
int index=CheckIndex(1, NULL); int index=CheckIndex(1);
if (index<0 || EvalExpressionN (StateParameters[index], self)) if (index<0 || EvalExpressionI (StateParameters[index], self))
{ {
Spawn<ATeleportFog> (x, y, self->z + TELEFOGHEIGHT, ALLOW_REPLACE); Spawn<ATeleportFog> (x, y, self->z + TELEFOGHEIGHT, ALLOW_REPLACE);
} }
@ -2103,13 +2067,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_Respawn)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_PlayerSkinCheck) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayerSkinCheck)
{ {
if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains!
if (self->player != NULL && if (self->player != NULL &&
skins[self->player->userinfo.skin].othergame) skins[self->player->userinfo.skin].othergame)
{ {
int index = CheckIndex(1, &CallingState); int index = CheckIndex(1);
if (index >= 0) if (index >= 0)
{ {
@ -2123,7 +2087,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerSkinCheck)
// A_SetGravity // A_SetGravity
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SetGravity) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetGravity)
{ {
int index=CheckIndex(1); int index=CheckIndex(1);
if (index<0) return; if (index<0) return;
@ -2160,10 +2124,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearTarget)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_JumpIfTargetInLOS) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{ {
FState * CallingState = NULL; int index = CheckIndex(3);
int index = CheckIndex(3, &CallingState); if (index < 0) return;
angle_t an; angle_t an;
angle_t fov = angle_t(EvalExpressionF (StateParameters[index+1], self) * ANGLE_1); angle_t fov = angle_t(EvalExpressionF (StateParameters[index+1], self) * ANGLE_1);
INTBOOL projtarg = EvalExpressionI (StateParameters[index+2], self); INTBOOL projtarg = EvalExpressionI (StateParameters[index+2], self);
@ -2222,7 +2187,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JumpIfTargetInLOS)
// Damages the master of this child by the specified amount. Negative values heal. // Damages the master of this child by the specified amount. Negative values heal.
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_DamageMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
{ {
int index = CheckIndex(2); int index = CheckIndex(2);
if (index<0) return; if (index<0) return;
@ -2250,7 +2215,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DamageMaster)
// Damages the children of this master by the specified amount. Negative values heal. // Damages the children of this master by the specified amount. Negative values heal.
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_DamageChildren) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
{ {
TThinkerIterator<AActor> it; TThinkerIterator<AActor> it;
AActor * mo; AActor * mo;
@ -2286,7 +2251,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DamageChildren)
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CheckForReload) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload)
{ {
if ( self->player == NULL || self->player->ReadyWeapon == NULL ) if ( self->player == NULL || self->player->ReadyWeapon == NULL )
return; return;

View file

@ -404,15 +404,6 @@ int ParseExpression (FScanner &sc, bool _not, PClass *cls)
ExpData *data = ParseExpressionM (sc, cls); ExpData *data = ParseExpressionM (sc, cls);
if (_not)
{
ExpData *tmp = data;
data = new ExpData;
data->Type = EX_Not;
data->Children[0] = tmp;
data->EvalConst (cls);
}
for (unsigned int i = 0; i < StateExpressions.Size (); i++) for (unsigned int i = 0; i < StateExpressions.Size (); i++)
{ {
if (StateExpressions[i]->Compare (data)) if (StateExpressions[i]->Compare (data))
@ -666,6 +657,24 @@ static ExpData *ParseExpressionA (FScanner &sc, const PClass *cls)
sc.MustGetToken(')'); sc.MustGetToken(')');
return data; return data;
} }
else if (sc.CheckToken(TK_True))
{
ExpData *data = new ExpData;
data->Type = EX_Const;
data->Value.Type = VAL_Int;
data->Value.Int = 1;
return data;
}
else if (sc.CheckToken(TK_False))
{
ExpData *data = new ExpData;
data->Type = EX_Const;
data->Value.Type = VAL_Int;
data->Value.Int = 0;
return data;
}
else if (sc.CheckToken(TK_IntConst)) else if (sc.CheckToken(TK_IntConst))
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
@ -895,6 +904,13 @@ static ExpData *ParseExpressionA (FScanner &sc, const PClass *cls)
// [GRB] Evaluates previously stored expression // [GRB] Evaluates previously stored expression
// //
bool IsExpressionConst(int id)
{
if (StateExpressions.Size() <= (unsigned int)id) return false;
return StateExpressions[id]->Type == EX_Const;
}
int EvalExpressionI (int id, AActor *self, const PClass *cls) int EvalExpressionI (int id, AActor *self, const PClass *cls)
{ {
if (StateExpressions.Size() <= (unsigned int)id) return 0; if (StateExpressions.Size() <= (unsigned int)id) return 0;
@ -916,11 +932,6 @@ int EvalExpressionI (int id, AActor *self, const PClass *cls)
} }
} }
bool EvalExpressionN(int id, AActor *self, const PClass *cls)
{
return !EvalExpressionI(id, self, cls);
}
float EvalExpressionF (int id, AActor *self, const PClass *cls) float EvalExpressionF (int id, AActor *self, const PClass *cls)
{ {
if (StateExpressions.Size() <= (unsigned int)id) return 0.f; if (StateExpressions.Size() <= (unsigned int)id) return 0.f;

View file

@ -456,9 +456,10 @@ static void HandleDeprecatedFlags(AActor *defaults, bool set, int index)
// This cannot be placed in thingdef_codeptr because it needs the flag table // This cannot be placed in thingdef_codeptr because it needs the flag table
// //
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ChangeFlag) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
{ {
int index=CheckIndex(2); int index=CheckIndex(2);
if (index < 0) return;
const char * flagname = FName((ENamedName)StateParameters[index]).GetChars(); const char * flagname = FName((ENamedName)StateParameters[index]).GetChars();
int expression = EvalExpressionI (StateParameters[index+1], self); int expression = EvalExpressionI (StateParameters[index+1], self);
@ -2172,7 +2173,7 @@ static void PowerupColor (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
} }
else else
{ {
sc.ScriptError("\"%s\" requires an actor of type \"Powerup\"\n", sc.String); sc.ScriptError("\"%s\" requires an actor of type \"Powerup\"\n", sc.String);
return; return;
} }
@ -2232,7 +2233,7 @@ static void PowerupDuration (FScanner &sc, APowerupGiver *defaults, Baggage &bag
{ {
int *pEffectTics; int *pEffectTics;
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup))) if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
{ {
pEffectTics = &((APowerup*)defaults)->EffectTics; pEffectTics = &((APowerup*)defaults)->EffectTics;
@ -2243,7 +2244,7 @@ static void PowerupDuration (FScanner &sc, APowerupGiver *defaults, Baggage &bag
} }
else else
{ {
sc.ScriptError("\"%s\" requires an actor of type \"Powerup\"\n", sc.String); sc.ScriptError("\"%s\" requires an actor of type \"Powerup\"\n", sc.String);
return; return;
} }

View file

@ -119,6 +119,21 @@ AFuncDesc * FindFunction(const char * string)
} }
//==========================================================================
//
// Find an action function in AActor's table
//
//==========================================================================
PSymbolActionFunction *FindGlobalActionFunction(const char *name)
{
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false);
if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
return static_cast<PSymbolActionFunction*>(sym);
else
return NULL;
}
//========================================================================== //==========================================================================
// //
// Find a state address // Find a state address
@ -371,7 +386,6 @@ int PrepareStateParameters(FState * state, int numparams)
return paramindex; return paramindex;
} }
void A_CallSpecial(AActor * self);
//========================================================================== //==========================================================================
// //
// DoActionSpecials // DoActionSpecials
@ -414,7 +428,8 @@ bool DoActionSpecials(FScanner &sc, FState & state, bool multistate, int * state
{ {
sc.ScriptError ("Too many arguments to %s", specname.GetChars()); sc.ScriptError ("Too many arguments to %s", specname.GetChars());
} }
state.Action = GET_ACTION(A_CallSpecial);
state.SetAction(FindGlobalActionFunction("A_CallSpecial"), false);
return true; return true;
} }
return false; return false;
@ -650,7 +665,7 @@ do_stop:
if (sym != NULL && sym->SymbolType == SYM_ActionFunction) if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
{ {
PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym); PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym);
state.Action = afd->Function; state.SetAction(afd, false);
if (!afd->Arguments.IsEmpty()) if (!afd->Arguments.IsEmpty())
{ {
const char *params = afd->Arguments.GetChars(); const char *params = afd->Arguments.GetChars();
@ -664,171 +679,51 @@ do_stop:
} }
else else
{ {
if (!sc.CheckString("(")) goto endofstate; if (!sc.CheckString("("))
{
state.ParameterIndex = afd->defaultparameterindex+1;
goto endofstate;
}
} }
int paramindex = PrepareStateParameters(&state, numparams); int paramindex = PrepareStateParameters(&state, numparams);
int paramstart = paramindex; int paramstart = paramindex;
bool varargs = params[numparams - 1] == '+'; bool varargs = params[numparams - 1] == '+';
if (varargs) if (varargs)
{ {
StateParameters[paramindex++] = 0; StateParameters[paramindex++] = 0;
} }
else if (afd->defaultparameterindex > -1)
{
memcpy(&StateParameters[paramindex], &StateParameters[afd->defaultparameterindex],
afd->Arguments.Len() * sizeof (StateParameters[0]));
}
while (*params) while (*params)
{ {
switch(*params) if ((*params == 'l' || *params == 'L') && sc.CheckNumber())
{ {
case 'I': // Special case: State label as an offset
case 'i': // Integer if (sc.Number > 0 && strlen(statestring)>0)
sc.MustGetNumber();
v = sc.Number;
break;
case 'F':
case 'f': // Fixed point
sc.MustGetFloat();
v = fixed_t(sc.Float*FRACUNIT);
break;
case 'S':
case 's': // Sound name
sc.MustGetString();
v = S_FindSound(sc.String);
break;
case 'M':
case 'm': // Actor name
case 'T':
case 't': // String
sc.SetEscape(true);
sc.MustGetString();
sc.SetEscape(false);
v = (int)(sc.String[0] ? FName(sc.String) : NAME_None);
break;
case 'L':
case 'l': // Jump label
if (sc.CheckNumber())
{ {
if (sc.Number > 0 && strlen(statestring)>0) sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
{
sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
}
v=sc.Number;
if (v<0)
{
sc.ScriptError("Negative jump offsets are not allowed");
}
{
int minreq=count+v;
if (minreq>minrequiredstate) minrequiredstate=minreq;
}
}
else
{
if (JumpParameters.Size()==0) JumpParameters.Push(NAME_None);
v = -(int)JumpParameters.Size();
// This forces quotation marks around the state name.
sc.MustGetToken(TK_StringConst);
if (sc.String[0] == 0 || sc.Compare("None"))
{
v = 0; // an empty string means 'no state'.
break;
}
FString statestring = sc.String; // ParseStateString(sc);
const PClass *stype=NULL;
int scope = statestring.IndexOf("::");
if (scope >= 0)
{
FName scopename = FName(statestring, scope, false);
if (scopename == NAME_Super)
{
// Super refers to the direct superclass
scopename = actor->Class->ParentClass->TypeName;
}
JumpParameters.Push(scopename);
statestring = statestring.Right(statestring.Len()-scope-2);
stype = PClass::FindClass (scopename);
if (stype == NULL)
{
sc.ScriptError ("%s is an unknown class.", scopename.GetChars());
}
if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
{
sc.ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
}
if (!stype->IsAncestorOf (actor->Class))
{
sc.ScriptError ("%s is not derived from %s so cannot access its states.",
actor->Class->TypeName.GetChars(), stype->TypeName.GetChars());
}
}
else
{
// No class name is stored. This allows 'virtual' jumps to
// labels in subclasses.
// It also means that the validity of the given state cannot
// be checked here.
JumpParameters.Push(NAME_None);
}
TArray<FName> names;
MakeStateNameList(statestring, &names);
if (stype != NULL)
{
if (!stype->ActorInfo->FindState(names.Size(), &names[0]))
{
sc.ScriptError("Jump to unknown state '%s' in class '%s'",
statestring.GetChars(), stype->TypeName.GetChars());
}
}
JumpParameters.Push((ENamedName)names.Size());
for(unsigned i=0;i<names.Size();i++)
{
JumpParameters.Push(names[i]);
}
// No offsets here. The point of jumping to labels is to avoid such things!
} }
break; v=sc.Number;
if (v<0)
case 'C':
case 'c': // Color
sc.MustGetString ();
if (sc.Compare("none"))
{ {
v = -1; sc.ScriptError("Negative jump offsets are not allowed");
} }
else
{
int c = V_GetColor (NULL, sc.String);
// 0 needs to be the default so we have to mark the color.
v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
}
break;
case 'X': int minreq=count+v;
case 'x': if (minreq>minrequiredstate) minrequiredstate=minreq;
v = ParseExpression (sc, false, bag.Info->Class); }
break; else
{
case 'Y': // Use the generic parameter parser for everything else
case 'y': v = ParseParameter(sc, bag.Info->Class, *params, false);
v = ParseExpression (sc, true, bag.Info->Class);
break;
default:
assert(false);
v = -1;
break;
} }
StateParameters[paramindex++] = v; StateParameters[paramindex++] = v;
params++; params++;

View file

@ -19,12 +19,12 @@ ACTOR Actor native //: Thinker
Gravity 1 Gravity 1
action native A_MonsterRail(); action native A_MonsterRail();
action native A_BFGSpray(optional class<Actor> spraytype, optional int numrays, optional int damagecount); action native A_BFGSpray(class<Actor> spraytype = "BFGExtra", int numrays = 40, int damagecount = 15);
action native A_Pain(); action native A_Pain();
action native A_NoBlocking(); action native A_NoBlocking();
action native A_XScream(); action native A_XScream();
action native A_Look(); action native A_Look();
action native A_Chase(optional state melee, optional state missile, optional int flags); action native A_Chase(state melee = "*", state missile = "none", int flags = 0);
action native A_FaceTarget(); action native A_FaceTarget();
action native A_PosAttack(); action native A_PosAttack();
action native A_Scream(); action native A_Scream();
@ -42,9 +42,9 @@ ACTOR Actor native //: Thinker
action native A_SkelFist(); action native A_SkelFist();
action native A_SkelMissile(); action native A_SkelMissile();
action native A_FatRaise(); action native A_FatRaise();
action native A_FatAttack1(optional class<Actor> spawntype); action native A_FatAttack1(class<Actor> spawntype = "FatShot");
action native A_FatAttack2(optional class<Actor> spawntype); action native A_FatAttack2(class<Actor> spawntype = "FatShot");
action native A_FatAttack3(optional class<Actor> spawntype); action native A_FatAttack3(class<Actor> spawntype = "FatShot");
action native A_BossDeath(); action native A_BossDeath();
action native A_CPosAttack(); action native A_CPosAttack();
action native A_CPosRefire(); action native A_CPosRefire();
@ -52,28 +52,28 @@ ACTOR Actor native //: Thinker
action native A_SargAttack(); action native A_SargAttack();
action native A_HeadAttack(); action native A_HeadAttack();
action native A_BruisAttack(); action native A_BruisAttack();
action native A_SkullAttack(optional float speed); action native A_SkullAttack(float speed = 20);
action native A_Metal(); action native A_Metal();
action native A_SpidRefire(); action native A_SpidRefire();
action native A_BabyMetal(); action native A_BabyMetal();
action native A_BspiAttack(); action native A_BspiAttack();
action native A_Hoof(); action native A_Hoof();
action native A_CyberAttack(); action native A_CyberAttack();
action native A_PainAttack(optional class<Actor> spawntype); action native A_PainAttack(class<Actor> spawntype = "LostSoul");
action native A_DualPainAttack(optional class<Actor> spawntype); action native A_DualPainAttack(class<Actor> spawntype = "LostSoul");
action native A_PainDie(optional class<Actor> spawntype); action native A_PainDie(class<Actor> spawntype = "LostSoul");
action native A_KeenDie(); action native A_KeenDie();
action native A_BrainPain(); action native A_BrainPain();
action native A_BrainScream(); action native A_BrainScream();
action native A_BrainDie(); action native A_BrainDie();
action native A_BrainAwake(); action native A_BrainAwake();
action native A_BrainSpit(optional class<Actor> spawntype); action native A_BrainSpit(class<Actor> spawntype = "none"); // needs special treatment for default
action native A_SpawnSound(); action native A_SpawnSound();
action native A_SpawnFly(optional class<Actor> spawntype); action native A_SpawnFly(class<Actor> spawntype = "none"); // needs special treatment for default
action native A_BrainExplode(); action native A_BrainExplode();
action native A_Die(optional name damagetype); action native A_Die(name damagetype = "none");
action native A_Detonate(); action native A_Detonate();
action native A_Mushroom(optional class<Actor> spawntype, optional int numspawns); action native A_Mushroom(class<Actor> spawntype = "FatShot", int numspawns = 0);
action native A_SetFloorClip(); action native A_SetFloorClip();
action native A_UnSetFloorClip(); action native A_UnSetFloorClip();
@ -112,7 +112,7 @@ ACTOR Actor native //: Thinker
action native A_BishopMissileWeave(); action native A_BishopMissileWeave();
action native A_CStaffMissileSlither(); action native A_CStaffMissileSlither();
action native A_PlayerScream(); action native A_PlayerScream();
action native A_SkullPop(optional class<Actor> skulltype); action native A_SkullPop(class<Actor> skulltype = "BloodySkull");
action native A_CheckPlayerDone(); action native A_CheckPlayerDone();
action native A_Wander(); action native A_Wander();
@ -141,29 +141,29 @@ ACTOR Actor native //: Thinker
action native A_FLoopActiveSound(); action native A_FLoopActiveSound();
action native A_LoopActiveSound(); action native A_LoopActiveSound();
action native A_StopSound(); action native A_StopSound();
action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional bool looping, optional int attenuation); action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
action native A_StopSoundEx(coerce name slot); action native A_StopSoundEx(coerce name slot);
action native A_SeekerMissile(int threshold, int turnmax); action native A_SeekerMissile(int threshold, int turnmax);
action native A_Jump(int chance, state label, ...); action native A_Jump(int chance, state label, ...);
action native A_CustomMissile(class<Actor> missiletype, float spawnheight, int spawnofs_xy, optional float angle, optional int flags, optional float pitch); action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0);
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, optional class<Actor> pufftype, optional float range, optional bool aimfacing); action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, bool aimfacing = false);
action native A_CustomRailgun(int damage, optional int spawnofs_xy, optional color color1, optional color color2, optional bool silent, optional bool aim, optional float maxdiff, optional class<Actor> pufftype); action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", bool silent = false, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
action native A_JumpIfHealthLower(int health, state label); action native A_JumpIfHealthLower(int health, state label);
action native A_JumpIfCloser(float distance, state label); action native A_JumpIfCloser(float distance, state label);
action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label); action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label);
action native A_GiveInventory(class<Inventory> itemtype, optional int amount); action native A_GiveInventory(class<Inventory> itemtype, int amount = 0);
action native A_TakeInventory(class<Inventory> itemtype, optional int amount); action native A_TakeInventory(class<Inventory> itemtype, int amount = 0);
action native A_SpawnItem(class<Actor> itemtype, optional float distance, optional float zheight, optional evalnot bool useammo, optional bool transfer_translation); action native A_SpawnItem(class<Actor> itemtype, float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
action native A_SpawnItemEx(class<Actor> itemtype, optional float xofs, optional float yofs, optional float zofs, optional float xmom, optional float ymom, optional float zmom, optional float angle, optional int flags, optional int chance); action native A_SpawnItemEx(class<Actor> itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xmom = 0, float ymom = 0, float zmom = 0, float angle = 0, int flags = 0, int failchance = 0);
action native A_Print(string whattoprint, optional float time, optional string fontname); action native A_Print(string whattoprint, float time = 0, string fontname = "");
action native A_SetTranslucent(float alpha, optional int style); action native A_SetTranslucent(float alpha, int style = 0);
action native A_FadeIn(optional float reduce); action native A_FadeIn(float reduce = 0.1);
action native A_FadeOut(optional float reduce); action native A_FadeOut(float reduce = 0.1);
action native A_SpawnDebris(class<Actor> spawntype, optional bool transfer_translation, optional float mult_h, optional float mult_v); action native A_SpawnDebris(class<Actor> spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1);
action native A_CheckSight(state label); action native A_CheckSight(state label);
action native A_ExtChase(bool usemelee, bool usemissile, optional evalnot bool playactive, optional bool nightmarefast); action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
action native A_DropInventory(class<Inventory> itemtype); action native A_DropInventory(class<Inventory> itemtype);
action native A_SetBlend(color color1, float alpha, int tics, optional color color2); action native A_SetBlend(color color1, float alpha, int tics, color color2 = "");
action native A_ChangeFlag(string flagname, bool value); action native A_ChangeFlag(string flagname, bool value);
action native A_JumpIf(bool expression, state label); action native A_JumpIf(bool expression, state label);
action native A_KillMaster(); action native A_KillMaster();
@ -171,28 +171,28 @@ ACTOR Actor native //: Thinker
action native A_CheckFloor(state label); action native A_CheckFloor(state label);
action native A_PlayerSkinCheck(state label); action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight); action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_ThrowGrenade(class<Actor> itemtype, optional float zheight, optional float xymom, optional float zmom, optional evalnot bool useammo); action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xymom = 0, float zmom = 0, bool useammo = true);
action native A_Recoil(float xymom); action native A_Recoil(float xymom);
action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label); action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label);
action native A_GiveToTarget(class<Inventory> itemtype, optional int amount); action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromTarget(class<Inventory> itemtype, optional int amount); action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0);
action native A_CountdownArg(int argnum); action native A_CountdownArg(int argnum);
action native A_CustomMeleeAttack(int damage, optional sound meleesound, optional sound misssound, optional name damagetype, optional evalnot bool bleed); action native A_CustomMeleeAttack(int damage, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
action native A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, optional sound meleesound, optional name damagetype, optional evalnot bool bleed); action native A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
action native A_Burst(class<Actor> chunktype); action native A_Burst(class<Actor> chunktype);
action native A_RadiusThrust(optional int force, optional int distance, optional evalnot bool affectsource); action native A_RadiusThrust(int force = 128, int distance = -1, bool affectsource = true);
action native A_Explode(optional int damage, optional int distance, optional evalnot bool hurtsource, optional bool alert); action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false);
action native A_Stop(); action native A_Stop();
action native A_Respawn(optional evalnot bool fog); action native A_Respawn(bool fog = true);
action native A_BarrelDestroy(); action native A_BarrelDestroy();
action native A_QueueCorpse(); action native A_QueueCorpse();
action native A_DeQueueCorpse(); action native A_DeQueueCorpse();
action native A_LookEx(optional int flags, optional float minseedist, optional float maxseedist, optional float maxheardist, optional float fov, optional state label); action native A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = "");
action native A_ClearTarget(); action native A_ClearTarget();
action native A_JumpIfTargetInLOS (state label, optional float fov, optional bool projectiletarget); action native A_JumpIfTargetInLOS (state label, float fov = 0, bool projectiletarget = false);
action native A_DamageMaster(int amount, optional name damagetype); action native A_DamageMaster(int amount, name damagetype = "none");
action native A_DamageChildren(int amount, optional name damagetype); action native A_DamageChildren(int amount, name damagetype = "none");
action native A_SelectWeapon(class<Weapon> whichweapon); action native A_SelectWeapon(class<Weapon> whichweapon);
action native A_Punch(); action native A_Punch();
action native A_Feathers(); action native A_Feathers();

View file

@ -7,12 +7,6 @@
ACTOR DoomWeapon : Weapon ACTOR DoomWeapon : Weapon
{ {
Weapon.Kickback 100 Weapon.Kickback 100
States
{
LightDone:
SHTG E 0 A_Light0
Stop
}
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------

View file

@ -270,6 +270,7 @@ ACTOR ZCorpseSitting 110
Spawn: Spawn:
CPS6 A -1 CPS6 A -1
Stop Stop
Death:
CPS6 A 1 A_CorpseExplode CPS6 A 1 A_CorpseExplode
Stop Stop
} }
@ -522,6 +523,7 @@ ACTOR ZSuitOfArmor 8064
Spawn: Spawn:
ZSUI A -1 ZSUI A -1
Stop Stop
Death:
ZSUI A 1 A_SoAExplode ZSUI A 1 A_SoAExplode
Stop Stop
} }

View file

@ -16,7 +16,7 @@ ACTOR ArtiTeleport : Inventory 36 native
States States
{ {
Spawn: Spawn:
ATLP ABCD 4 ATLP ABCB 4
Loop Loop
} }
} }

View file

@ -30,7 +30,7 @@ ACTOR CustomBridge 9991 native
Height 2 Height 2
RenderStyle None RenderStyle None
action native A_BridgeInit(optional class<Actor> balltype); action native A_BridgeInit(class<Actor> balltype = "BridgeBall");
states states
{ {

View file

@ -6,10 +6,10 @@ ACTOR Inventory native
Inventory.PickupSound "misc/i_pkup" Inventory.PickupSound "misc/i_pkup"
action native A_JumpIfNoAmmo(state label); action native A_JumpIfNoAmmo(state label);
action native A_CustomPunch(int damage, optional bool norandom, optional evalnot bool useammo, optional class<Actor> pufftype, optional float range); action native A_CustomPunch(int damage, bool norandom = false, bool useammo = true, class<Actor> pufftype = "BulletPuff", float range = 0);
action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, optional class<Actor> pufftype, optional evalnot bool useammo, optional float range); action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", bool useammo = true, float range = 0);
action native A_FireCustomMissile(class<Actor> missiletype, optional float angle, optional evalnot bool useammo, optional int spawnofs_xy, optional float spawnheight, optional bool aimatangle); action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false);
action native A_RailAttack(int damage, optional int spawnofs_xy, optional evalnot int useammo, optional color color1, optional color color2, optional bool silent, optional float maxdiff, optional class<Actor> pufftype); action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", bool silent = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
action native A_Light(int extralight); action native A_Light(int extralight);
action native A_Light0(); action native A_Light0();
action native A_Light1(); action native A_Light1();
@ -37,7 +37,7 @@ ACTOR Inventory native
action native A_ClearReFire(); action native A_ClearReFire();
action native A_CheckReload(); action native A_CheckReload();
action native A_GunFlash(); action native A_GunFlash();
action native A_Saw(optional coerce sound fullsound, optional coerce sound hitsound, optional int damage, optional class<Actor> pufftype); action native A_Saw(sound fullsound = "misc/sawfull", sound hitsound = "misc/sawhit", int damage = 2, class<Actor> pufftype = "BulletPuff");
action native A_CheckForReload(int counter, state label); action native A_CheckForReload(int counter, state label);
action native A_ResetReloadCounter(); action native A_ResetReloadCounter();
action native A_RestoreSpecialPosition(); action native A_RestoreSpecialPosition();

View file

@ -1,5 +1,5 @@
ACTOR SpecialSpot native ACTOR SpecialSpot native
{ {
action native A_SpawnSingleItem(class<Actor> type, optional int fail_sp, optional int fail_co, optional int fail_dm); action native A_SpawnSingleItem(class<Actor> type, int fail_sp = 0, int fail_co = 0, int fail_dm = 0);
} }

View file

@ -1,6 +1,7 @@
ACTOR StrifeWeapon : DoomWeapon ACTOR StrifeWeapon : Weapon
{ {
Weapon.Kickback 100
} }
// Same as the bullet puff for Doom ----------------------------------------- // Same as the bullet puff for Doom -----------------------------------------

Binary file not shown.