From b2ccd0bd28475793b8f16fb3324ed393bdef5e9a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 18 Feb 2016 20:39:40 -0600 Subject: [PATCH] Use action function return value to make state jumps happen - The A_Jump family of action functions now return the state to jump to (NULL if no jump is to be taken) instead of jumping directly. It is the caller's responsibility to handle the jump. This will make it possible to use their results in if statements and do something other than jump. - DECORATE return statements can now return the result of a function (but not any random expression--it must be a function call). To make a jump happen from inside a multi-action block, you must return the value of an A_Jump function. e.g.: { return A_Jump(128, "SomeState"); } - The VMFunction class now contains its prototype instead of storing it at a higher level in PFunction. This is so that FState::CallAction can easily tell if a function returns a state. - Removed the FxTailable class because with explicit return statements, it's not useful anymore. --- src/dobject.h | 1 - src/dobjgc.cpp | 2 +- src/dobjtype.cpp | 37 +- src/dobjtype.h | 6 +- src/info.cpp | 29 +- src/info.h | 2 +- src/p_mobj.cpp | 35 +- src/p_pspr.cpp | 11 +- src/thingdef/thingdef.cpp | 23 +- src/thingdef/thingdef.h | 12 +- src/thingdef/thingdef_codeptr.cpp | 549 +++++++++------------- src/thingdef/thingdef_exp.h | 51 +- src/thingdef/thingdef_expression.cpp | 118 ++--- src/thingdef/thingdef_parse.cpp | 70 ++- src/thingdef/thingdef_states.cpp | 142 +++++- src/zscript/vm.h | 6 +- wadsrc/static/actors/actor.txt | 100 ++-- wadsrc/static/actors/shared/inventory.txt | 4 +- 18 files changed, 663 insertions(+), 535 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 254891eb5..48cf6353e 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -207,7 +207,6 @@ enum EObjectFlags OF_JustSpawned = 1 << 8, // Thinker was spawned this tic OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list - OF_StateChanged = 1 << 11, // Used by A_Jump* functions to feed back to SetState() }; template class TObjPtr; diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index d9c977670..0094e3812 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -73,7 +73,7 @@ #include "po_man.h" #include "autosegs.h" #include "v_video.h" -#include "textures.h" +#include "textures/textures.h" #include "r_utility.h" #include "menu/menu.h" #include "intermission/intermission.h" diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 2c45f483c..84f890c79 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1222,6 +1222,38 @@ PStatePointer::PStatePointer() { } +//========================================================================== +// +// PStatePointer :: GetStoreOp +// +//========================================================================== + +int PStatePointer::GetStoreOp() const +{ + return OP_SP; +} + +//========================================================================== +// +// PStatePointer :: GetLoadOp +// +//========================================================================== + +int PStatePointer::GetLoadOp() const +{ + return OP_LP; +} + +//========================================================================== +// +// PStatePointer :: GetRegType +// +//========================================================================== + +int PStatePointer::GetRegType() const +{ + return REGT_POINTER; +} /* PPointer ***************************************************************/ @@ -1948,7 +1980,7 @@ size_t PFunction::PropagateMark() { for (unsigned i = 0; i < Variants.Size(); ++i) { - GC::Mark(Variants[i].Proto); + //GC::Mark(Variants[i].Proto); GC::Mark(Variants[i].Implementation); } return Variants.Size() * sizeof(Variants[0]) + Super::PropagateMark(); @@ -1967,9 +1999,10 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, VMFun { Variant variant; - variant.Proto = proto; + //variant.Proto = proto; variant.ArgFlags = argflags; variant.Implementation = impl; + impl->Proto = proto; return Variants.Push(variant); } diff --git a/src/dobjtype.h b/src/dobjtype.h index 9ba327658..1e982e74b 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -415,6 +415,10 @@ class PStatePointer : public PBasicType DECLARE_CLASS(PStatePointer, PBasicType); public: PStatePointer(); + + virtual int GetStoreOp() const; + virtual int GetLoadOp() const; + virtual int GetRegType() const; }; class PPointer : public PBasicType @@ -582,7 +586,7 @@ class PFunction : public PSymbol public: struct Variant { - PPrototype *Proto; + //PPrototype *Proto; VMFunction *Implementation; TArray ArgFlags; // Should be the same length as Proto->ArgumentTypes }; diff --git a/src/info.cpp b/src/info.cpp index 0f3da5d78..1ba21c5f7 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -52,7 +52,7 @@ #include "cmdlib.h" #include "g_level.h" #include "stats.h" -#include "thingdef.h" +#include "thingdef/thingdef.h" #include "d_player.h" extern void LoadActors (); @@ -69,14 +69,37 @@ void FState::SetAction(const char *name) ActionFunc = FindGlobalActionFunction(name)->Variants[0].Implementation; } -bool FState::CallAction(AActor *self, AActor *stateowner) +bool FState::CallAction(AActor *self, AActor *stateowner, FState **stateret) { if (ActionFunc != NULL) { ActionCycles.Clock(); + static VMFrameStack stack; VMValue params[3] = { self, stateowner, VMValue(this, ATAG_STATE) }; - stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL); + // If the function returns a state, store it at *stateret. + // If it doesn't return a state but stateret is non-NULL, we need + // to set *stateret to NULL. + if (stateret != NULL) + { + *stateret = NULL; + if (ActionFunc->Proto == NULL || + ActionFunc->Proto->ReturnTypes.Size() == 0 || + ActionFunc->Proto->ReturnTypes[0] != TypeState) + { + stateret = NULL; + } + } + if (stateret == NULL) + { + stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL); + } + else + { + VMReturn ret; + ret.PointerAt((void **)stateret); + stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL); + } ActionCycles.Unclock(); return true; } diff --git a/src/info.h b/src/info.h index 5d9d36879..eb828bcf0 100644 --- a/src/info.h +++ b/src/info.h @@ -128,7 +128,7 @@ struct FState void SetAction(VMFunction *func) { ActionFunc = func; } void ClearAction() { ActionFunc = NULL; } void SetAction(const char *name); - bool CallAction(AActor *self, AActor *stateowner); + bool CallAction(AActor *self, AActor *stateowner, FState **stateret); static PClassActor *StaticFindStateOwner (const FState *state); static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info); static FRandom pr_statetics; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 82326c39b..6baea65e2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -614,21 +614,22 @@ bool AActor::SetState (FState *newstate, bool nofunction) } } - if (!nofunction && newstate->CallAction(this, this)) + if (!nofunction) { - // Check whether the called action function resulted in destroying the actor - if (ObjectFlags & OF_EuthanizeMe) + FState *returned_state; + if (newstate->CallAction(this, this, &returned_state)) { - return false; - } - if (ObjectFlags & OF_StateChanged) - { // The action was an A_Jump-style function that wants to change the next state. - ObjectFlags &= ~OF_StateChanged; - FState *saved = newstate; - newstate = state; - state = saved; // we need this for comparison of sprites. - tics = 0; // make sure we loop and set the new state properly - continue; + // Check whether the called action function resulted in destroying the actor + if (ObjectFlags & OF_EuthanizeMe) + { + return false; + } + if (returned_state != NULL) + { // The action was an A_Jump-style function that wants to change the next state. + newstate = returned_state; + tics = 0; // make sure we loop and set the new state properly + continue; + } } } newstate = newstate->GetNextState(); @@ -3904,16 +3905,16 @@ bool AActor::CheckNoDelay() { // For immediately spawned objects with the NoDelay flag set for their // Spawn state, explicitly call the current state's function. - if (state->CallAction(this, this)) + FState *newstate; + if (state->CallAction(this, this, &newstate)) { if (ObjectFlags & OF_EuthanizeMe) { return false; // freed itself } - if (ObjectFlags & OF_StateChanged) + if (newstate != NULL) { - ObjectFlags &= ~OF_StateChanged; - return SetState(state); + return SetState(newstate); } } } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 7d52210ce..ec6c38f77 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -178,9 +178,16 @@ void P_SetPsprite (player_t *player, int position, FState *state, bool nofunctio if (!nofunction && player->mo != NULL) { - if (state->CallAction(player->mo, player->ReadyWeapon)) + FState *newstate; + if (state->CallAction(player->mo, player->ReadyWeapon, &newstate)) { - if (!psp->state) + if (newstate != NULL) + { + state = newstate; + psp->tics = 0; + continue; + } + if (psp->state == NULL) { break; } diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index a85f0ea08..4cb03111b 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -277,11 +277,11 @@ static void FinishThingdef() // Can we call this function directly without wrapping it in an // anonymous function? e.g. Are we passing any parameters to it? - func = tcall->Code->GetDirectFunction(); + func = NULL;//tcall->Code->GetDirectFunction(); if (func == NULL) { FCompileContext ctx(tcall->ActorClass); - tcall->Code = static_cast(tcall->Code->Resolve(ctx)); + tcall->Code = tcall->Code->Resolve(ctx); // Make sure resolving it didn't obliterate it. if (tcall->Code != NULL) @@ -292,11 +292,25 @@ static void FinishThingdef() // self, stateowner, state (all are pointers) buildit.Registers[REGT_POINTER].Get(3); - // Emit a tail call via FxVMFunctionCall - tcall->Code->Emit(&buildit, true); + // Emit code + tcall->Code->Emit(&buildit); VMScriptFunction *sfunc = buildit.MakeFunction(); sfunc->NumArgs = NAP; + + // Generate prototype for this anonymous function + TArray args(3); + SetImplicitArgs(&args, NULL, tcall->ActorClass, VARF_Method | VARF_Action); + if (tcall->Proto != NULL) + { + sfunc->Proto = NewPrototype(tcall->Proto->ReturnTypes, args); + } + else + { + TArray norets(0); + sfunc->Proto = NewPrototype(norets, args); + } + func = sfunc; if (dump != NULL) @@ -354,6 +368,7 @@ static void FinishThingdef() dmg->Emit(&buildit); sfunc = buildit.MakeFunction(); sfunc->NumArgs = 1; + sfunc->Proto = NULL; ///FIXME: Need a proper prototype here // Save this function in case this damage value was reused // (which happens quite easily with inheritance). dmg->SetFunction(sfunc); diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index aa6a54445..a9703ffa6 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -122,7 +122,8 @@ struct FStateTempCall FStateTempCall() : ActorClass(NULL), Code(NULL), FirstState(0), NumStates(0) {} PClassActor *ActorClass; - class FxTailable *Code; + class FxExpression *Code; + class PPrototype *Proto; int FirstState; int NumStates; }; @@ -189,8 +190,10 @@ AFuncDesc *FindFunction(const char * string); void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag); void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray &out_params, PFunction *afd, FString statestring, FStateDefinitions *statedef); -FxTailable *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag); +FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, PPrototype *&proto, bool &endswithret); class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); +void AddImplicitReturn(class FxSequence *code, const PPrototype *proto, FScanner &sc); +void SetImplicitArgs(TArray *args, TArray *argflags, PClassActor *cls, DWORD funcflags); PFunction *FindGlobalActionFunction(const char *name); @@ -354,8 +357,9 @@ int MatchString (const char *in, const char **strings); } -#define ACTION_SET_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(v); numret = 1; } } while(0) -#define ACTION_OR_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(*(int *)ret->Location | int(v)); numret = 1; } } while(0) +#define ACTION_RETURN_STATE(state) if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0 +#define ACTION_RETURN_INT(v) if (numret > 0) { assert(ret != NULL); ret->SetInt(v); return 1; } return 0 +#define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v) // Checks to see what called the current action function #define ACTION_CALL_FROM_ACTOR() (callingstate == self->state) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 4b9bb77de..778c758c6 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -728,49 +728,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) } -//========================================================================== -// -// Do the state jump -// -//========================================================================== -static void DoJump(AActor *self, AActor *stateowner, FState *callingstate, FState *jumpto) -{ - if (jumpto == NULL) return; - - if (stateowner->flags5 & MF5_INSTATECALL) - { - stateowner->state = jumpto; - } - else if (self->player != NULL && callingstate == self->player->psprites[ps_weapon].state) - { - P_SetPsprite(self->player, ps_weapon, jumpto); - } - else if (self->player != NULL && callingstate == self->player->psprites[ps_flash].state) - { - P_SetPsprite(self->player, ps_flash, jumpto); - } - else if (callingstate == self->state || (self->ObjectFlags & OF_StateChanged)) - { - // Rather than using self->SetState(jumpto) to set the state, - // set the state directly. Since this function is only called by - // action functions, which are only called by SetState(), we - // know that somewhere above us in the stack, a SetState() - // call is waiting for us to return. We use the flag OF_StateChanged - // to cause it to bypass the normal next state mechanism and use - // the one we set here instead. - self->state = jumpto; - self->ObjectFlags |= OF_StateChanged; - } - else - { // something went very wrong. This should never happen. - assert(false); - } -} - -// This is just to avoid having to directly reference the internally defined -// CallingState and statecall parameters in the code below. -#define ACTION_JUMP(offset) DoJump(self, stateowner, callingstate, offset) - //========================================================================== // // State jump function @@ -787,10 +744,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) { int jumpnum = (count == 1 ? 0 : (pr_cajump() % count)); PARAM_STATE_AT(paramnum + jumpnum, jumpto); - ACTION_JUMP(jumpto); + ACTION_RETURN_STATE(jumpto); } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - return numret; + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -811,10 +767,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower) if (measured != NULL && measured->health < health) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - return numret; + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -829,10 +784,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetOutsideMeleeRange) if (!self->CheckMeleeRange()) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - return numret; + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -847,10 +801,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInsideMeleeRange) if (self->CheckMeleeRange()) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - return numret; + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -865,19 +818,18 @@ static int DoJumpIfCloser(AActor *target, VM_ARGS) PARAM_STATE (jump); PARAM_BOOL_OPT(noz) { noz = false; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - - // No target - no jump if (!target) - return numret; + { // No target - no jump + ACTION_RETURN_STATE(NULL); + } if (self->AproxDistance(target) < dist && (noz || ((self->Z() > target->Z() && self->Z() - target->Top() < dist) || (self->Z() <= target->Z() && target->Z() - self->Top() < dist)))) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfCloser) @@ -923,16 +875,14 @@ int DoJumpIfInventory(AActor *owner, AActor *self, AActor *stateowner, FState *c PARAM_STATE (label); PARAM_INT_OPT (setowner) { setowner = AAPTR_DEFAULT; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - if (itemtype == NULL) { - return numret; + ACTION_RETURN_STATE(NULL); } owner = COPY_AAPTR(owner, setowner); if (owner == NULL) { - return numret; + ACTION_RETURN_STATE(NULL); } AInventory *item = owner->FindInventory(itemtype); @@ -942,14 +892,14 @@ int DoJumpIfInventory(AActor *owner, AActor *self, AActor *stateowner, FState *c if (itemamount > 0) { if (item->Amount >= itemamount) - ACTION_JUMP(label); + ACTION_RETURN_STATE(label); } else if (item->Amount >= item->MaxAmount) { - ACTION_JUMP(label); + ACTION_RETURN_STATE(label); } } - return numret; + ACTION_RETURN_STATE(NULL); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInventory) @@ -976,13 +926,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType) PARAM_STATE (label); PARAM_INT_OPT(amount) { amount = 1; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - ABasicArmor *armor = (ABasicArmor *)self->FindInventory(NAME_BasicArmor); if (armor && armor->ArmorType == type && armor->Amount >= amount) - ACTION_JUMP(label); - return numret; + { + ACTION_RETURN_STATE(label); + } + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -1104,8 +1054,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CallSpecial) bool res = !!P_ExecuteSpecial(special, NULL, self, false, arg1, arg2, arg3, arg4, arg5); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_BOOL(res); } //========================================================================== @@ -1432,15 +1381,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo) PARAM_ACTION_PROLOGUE; PARAM_STATE(jump); - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! if (!ACTION_CALL_FROM_WEAPON()) - return numret; + { + ACTION_RETURN_STATE(NULL); + } if (!self->player->ReadyWeapon->CheckAmmo(self->player->ReadyWeapon->bAltFire, false, true)) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } @@ -1920,7 +1870,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) // //=========================================================================== -static int DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) +static bool DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) { int paramnum = NAP-1; PARAM_CLASS (mi, AInventory); @@ -1933,8 +1883,7 @@ static int DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) } if (receiver == NULL) { // If there's nothing to receive it, it's obviously a fail, right? - ACTION_SET_RESULT(false); - return numret; + return false; } bool res = true; @@ -1948,8 +1897,7 @@ static int DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) AInventory *item = static_cast(Spawn(mi, 0, 0, 0, NO_REPLACE)); if (item == NULL) { - ACTION_SET_RESULT(false); - return numret; + return false; } if (item->IsKindOf(RUNTIME_CLASS(AHealth))) { @@ -1964,38 +1912,26 @@ static int DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS) if (!item->CallTryPickup(receiver)) { item->Destroy(); - res = false; + return false; } else { - res = true; + return true; } } - else - { - res = false; - } - if (!orresult) - { - ACTION_SET_RESULT(res); - } - else - { - ACTION_OR_RESULT(res); - } - return numret; + return false; } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveInventory) { PARAM_ACTION_PROLOGUE; - return DoGiveInventory(self, false, VM_ARGS_NAMES); + ACTION_RETURN_BOOL(DoGiveInventory(self, false, VM_ARGS_NAMES)); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget) { PARAM_ACTION_PROLOGUE; - return DoGiveInventory(self->target, false, VM_ARGS_NAMES); + ACTION_RETURN_BOOL(DoGiveInventory(self->target, false, VM_ARGS_NAMES)); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) @@ -2004,16 +1940,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) TThinkerIterator it; AActor *mo; + int count = 0; - ACTION_SET_RESULT(false); while ((mo = it.Next())) { if (mo->master == self) { - numret = DoGiveInventory(mo, true, VM_ARGS_NAMES); + count += DoGiveInventory(mo, true, VM_ARGS_NAMES); } } - return numret; + ACTION_RETURN_INT(count); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) @@ -2022,19 +1958,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) TThinkerIterator it; AActor *mo; + int count = 0; - ACTION_SET_RESULT(false); if (self->master != NULL) { while ((mo = it.Next())) { if (mo->master == self->master && mo != self) { - numret = DoGiveInventory(mo, true, VM_ARGS_NAMES); + count += DoGiveInventory(mo, true, VM_ARGS_NAMES); } } } - return numret; + ACTION_RETURN_INT(count); } //=========================================================================== @@ -2048,7 +1984,7 @@ enum TIF_NOTAKEINFINITE = 1, }; -int DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) +bool DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) { int paramnum = NAP-1; PARAM_CLASS (itemtype, AInventory); @@ -2057,8 +1993,7 @@ int DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) if (itemtype == NULL) { - ACTION_SET_RESULT(true); - return numret; + return true; } if (!orresult) { @@ -2067,60 +2002,47 @@ int DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS) } if (receiver == NULL) { - ACTION_SET_RESULT(false); - return numret; + return false; } - bool res = receiver->TakeInventory(itemtype, amount, true, (flags & TIF_NOTAKEINFINITE) != 0); - - if (!orresult) - { - ACTION_SET_RESULT(res); - } - else - { - ACTION_OR_RESULT(res); - } - return numret; + return receiver->TakeInventory(itemtype, amount, true, (flags & TIF_NOTAKEINFINITE) != 0); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeInventory) { PARAM_ACTION_PROLOGUE; - return DoTakeInventory(self, false, VM_ARGS_NAMES); + ACTION_RETURN_BOOL(DoTakeInventory(self, false, VM_ARGS_NAMES)); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget) { PARAM_ACTION_PROLOGUE; - return DoTakeInventory(self->target, false, VM_ARGS_NAMES); + ACTION_RETURN_BOOL(DoTakeInventory(self->target, false, VM_ARGS_NAMES)); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren) { PARAM_ACTION_PROLOGUE; - ACTION_SET_RESULT(false); - TThinkerIterator it; - AActor * mo; + AActor *mo; + int count = 0; while ((mo = it.Next())) { if (mo->master == self) { - DoTakeInventory(mo, true, VM_ARGS_NAMES); + count += DoTakeInventory(mo, true, VM_ARGS_NAMES); } } - return numret; + ACTION_RETURN_INT(count); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromSiblings) { PARAM_ACTION_PROLOGUE; - ACTION_SET_RESULT(false); - TThinkerIterator it; - AActor * mo; + AActor *mo; + int count = 0; if (self->master != NULL) { @@ -2128,11 +2050,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromSiblings) { if (mo->master == self->master && mo != self) { - DoTakeInventory(mo, true, VM_ARGS_NAMES); + count += DoTakeInventory(mo, true, VM_ARGS_NAMES); } } } - return numret; + ACTION_RETURN_INT(count); } //=========================================================================== @@ -2363,15 +2285,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) if (missile == NULL) { - ACTION_SET_RESULT(false); - return numret; + ACTION_RETURN_BOOL(false); } - ACTION_SET_RESULT(true); // Don't spawn monsters if this actor has been massacred if (self->DamageType == NAME_Massacre && (GetDefaultByType(missile)->flags3 & MF3_ISMONSTER)) { - return numret; + ACTION_RETURN_BOOL(true); } if (distance == 0) @@ -2386,17 +2306,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) AWeapon *weapon = self->player->ReadyWeapon; if (weapon == NULL) - return numret; + ACTION_RETURN_BOOL(true); if (useammo && !weapon->DepleteAmmo(weapon->bAltFire)) - return numret; + ACTION_RETURN_BOOL(true); } AActor *mo = Spawn( missile, self->Vec3Angle(distance, self->angle, -self->floorclip + self->GetBobOffset() + zheight), ALLOW_REPLACE); int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0); - bool res = InitSpawnedItem(self, mo, flags); - ACTION_SET_RESULT(res); // for an inventory item's use state - return numret; + ACTION_RETURN_BOOL(InitSpawnedItem(self, mo, flags)); // for an inventory item's use state } //=========================================================================== @@ -2423,17 +2341,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) if (missile == NULL) { - ACTION_SET_RESULT(false); - return numret; + ACTION_RETURN_BOOL(false); } - ACTION_SET_RESULT(true); if (chance > 0 && pr_spawnitemex() < chance) - return numret; + ACTION_RETURN_BOOL(true); // Don't spawn monsters if this actor has been massacred if (self->DamageType == NAME_Massacre && (GetDefaultByType(missile)->flags3 & MF3_ISMONSTER)) - return numret; + ACTION_RETURN_BOOL(true); fixedvec2 pos; @@ -2467,7 +2383,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) AActor *mo = Spawn(missile, pos.x, pos.y, self->Z() - self->floorclip + self->GetBobOffset() + zofs, ALLOW_REPLACE); bool res = InitSpawnedItem(self, mo, flags); - ACTION_SET_RESULT(res); // for an inventory item's use state if (res) { if (tid != 0) @@ -2490,7 +2405,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx) } mo->angle = angle; } - return numret; + ACTION_RETURN_BOOL(res); // for an inventory item's use state } //=========================================================================== @@ -2509,9 +2424,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) PARAM_FIXED_OPT (zvel) { zvel = 0; } PARAM_BOOL_OPT (useammo) { useammo = true; } - ACTION_SET_RESULT(true); if (missile == NULL) - return numret; + ACTION_RETURN_BOOL(true); if (ACTION_CALL_FROM_WEAPON()) { @@ -2519,9 +2433,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) AWeapon *weapon = self->player->ReadyWeapon; if (weapon == NULL) - return numret; + ACTION_RETURN_BOOL(true); if (useammo && !weapon->DepleteAmmo(weapon->bAltFire)) - return numret; + ACTION_RETURN_BOOL(true); } AActor *bo; @@ -2563,9 +2477,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) } else { - ACTION_SET_RESULT(false); + ACTION_RETURN_BOOL(false); } - return numret; + ACTION_RETURN_BOOL(true); } @@ -2599,8 +2513,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) if (cls == NULL || self->player == NULL) { - ACTION_SET_RESULT(false); - return numret; + ACTION_RETURN_BOOL(false); } AWeapon *weaponitem = static_cast(self->FindInventory(cls)); @@ -2611,13 +2524,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) { self->player->PendingWeapon = weaponitem; } - ACTION_SET_RESULT(true); + ACTION_RETURN_BOOL(true); } else { - ACTION_SET_RESULT(false); + ACTION_RETURN_BOOL(false); } - return numret; } @@ -2654,8 +2566,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print) C_MidPrint(font != NULL ? font : SmallFont, formatted.GetChars()); con_midtime = saved; } - ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! - return numret; + return 0; } //=========================================================================== @@ -2686,8 +2597,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold) FString formatted = strbin1(text); C_MidPrintBold(font != NULL ? font : SmallFont, formatted.GetChars()); con_midtime = saved; - ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! - return numret; + return 0; } //=========================================================================== @@ -2704,8 +2614,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) if (text[0] == '$') text = GStrings(&text[1]); FString formatted = strbin1(text); Printf("%s\n", formatted.GetChars()); - ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! - return numret; + return 0; } //========================================================================= @@ -2719,8 +2628,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt) PARAM_ACTION_PROLOGUE; PARAM_INT(num); Printf("%d\n", num); - ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! - return numret; + return 0; } //=========================================================================== @@ -3031,8 +2939,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) PARAM_ACTION_PROLOGUE; PARAM_STATE(jump); - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - for (int i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) @@ -3040,19 +2946,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) // Always check sight from each player. if (P_CheckSight(players[i].mo, self, SF_IGNOREVISIBILITY)) { - return numret; + ACTION_RETURN_STATE(NULL); } // If a player is viewing from a non-player, then check that too. if (players[i].camera != NULL && players[i].camera->player == NULL && P_CheckSight(players[i].camera, self, SF_IGNOREVISIBILITY)) { - return numret; + ACTION_RETURN_STATE(NULL); } } } - - ACTION_JUMP(jump); - return numret; + ACTION_RETURN_STATE(jump); } //=========================================================================== @@ -3105,8 +3009,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) PARAM_STATE(jump); PARAM_BOOL_OPT(twodi) { twodi = false; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots for (int i = 0; i < MAXPLAYERS; ++i) { @@ -3115,18 +3017,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) // Always check from each player. if (DoCheckSightOrRange(self, players[i].mo, range, twodi)) { - return numret; + ACTION_RETURN_STATE(NULL); } // If a player is viewing from a non-player, check that too. if (players[i].camera != NULL && players[i].camera->player == NULL && DoCheckSightOrRange(self, players[i].camera, range, twodi)) { - return numret; + ACTION_RETURN_STATE(NULL); } } } - ACTION_JUMP(jump); - return numret; + ACTION_RETURN_STATE(jump); } //=========================================================================== @@ -3173,8 +3074,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange) PARAM_STATE(jump); PARAM_BOOL_OPT(twodi) { twodi = false; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots for (int i = 0; i < MAXPLAYERS; ++i) { @@ -3183,18 +3082,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange) // Always check from each player. if (DoCheckRange(self, players[i].mo, range, twodi)) { - return numret; + ACTION_RETURN_STATE(NULL); } // If a player is viewing from a non-player, check that too. if (players[i].camera != NULL && players[i].camera->player == NULL && DoCheckRange(self, players[i].camera, range, twodi)) { - return numret; + ACTION_RETURN_STATE(NULL); } } } - ACTION_JUMP(jump); - return numret; + ACTION_RETURN_STATE(jump); } @@ -3258,10 +3156,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIf) PARAM_BOOL (condition); PARAM_STATE (jump); - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - if (condition) - ACTION_JUMP(jump); - return numret; + ACTION_RETURN_STATE(condition ? jump : NULL); } //=========================================================================== @@ -3369,12 +3264,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFloor) PARAM_ACTION_PROLOGUE; PARAM_STATE(jump); - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! if (self->Z() <= self->floorz) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } //=========================================================================== @@ -3389,12 +3283,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckCeiling) PARAM_ACTION_PROLOGUE; PARAM_STATE(jump); - ACTION_SET_RESULT(false); if (self->Top() >= self->ceilingz) // Height needs to be counted { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } //=========================================================================== @@ -3526,13 +3419,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayerSkinCheck) PARAM_ACTION_PROLOGUE; PARAM_STATE(jump); - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! if (self->player != NULL && skins[self->player->userinfo.GetSkin()].othergame) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } //=========================================================================== @@ -3719,8 +3611,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) PARAM_FIXED_OPT (offsetwidth) { offsetwidth = 0; } PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - target = COPY_AAPTR(self, ptr_target == AAPTR_DEFAULT ? AAPTR_TARGET|AAPTR_PLAYER_GETTARGET|AAPTR_NULL : ptr_target); // no player-support by default if (flags & CLOFF_MUL_HEIGHT) @@ -3765,7 +3655,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) if (range && !(flags & CLOFF_CHECKPARTIAL)) { if (distance > range) - return numret; + ACTION_RETURN_STATE(NULL); } { @@ -3818,7 +3708,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) } else { - return numret; + ACTION_RETURN_STATE(NULL); } angle >>= ANGLETOFINESHIFT; @@ -3860,7 +3750,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) { if (minrange > 0 && trace.Distance < minrange) { - return numret; + ACTION_RETURN_STATE(NULL); } if ((trace.HitType == TRACE_HitActor) && (trace.Actor != NULL) && !(lof_data.BadActor)) { @@ -3868,9 +3758,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) if (flags & (CLOFF_SETMASTER)) self->master = trace.Actor; if (flags & (CLOFF_SETTRACER)) self->tracer = trace.Actor; } - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -3917,8 +3807,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) angle_t an; AActor *target, *viewport; - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - bool doCheckSight; if (!self->player) @@ -3940,11 +3828,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) } if (target == NULL) - return numret; // [KS] Let's not call P_CheckSight unnecessarily in this case. + ACTION_RETURN_STATE(NULL); // [KS] Let's not call P_CheckSight unnecessarily in this case. if ((flags & JLOSF_DEADNOJUMP) && (target->health <= 0)) { - return numret; + ACTION_RETURN_STATE(NULL); } doCheckSight = !(flags & JLOSF_NOSIGHT); @@ -3954,7 +3842,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) // Does the player aim at something that can be shot? P_AimLineAttack(self, self->angle, MISSILERANGE, &target, (flags & JLOSF_NOAUTOAIM) ? ANGLE_1/2 : 0); - if (!target) return numret; + if (!target) ACTION_RETURN_STATE(NULL); switch (flags & (JLOSF_TARGETLOS|JLOSF_FLIPFOV)) { @@ -3977,21 +3865,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) // [FDARI] If target is not a combatant, don't jump if ( (flags & JLOSF_COMBATANTONLY) && (!target->player) && !(target->flags3 & MF3_ISMONSTER)) - return numret; + ACTION_RETURN_STATE(NULL); // [FDARI] If actors share team, don't jump if ((flags & JLOSF_ALLYNOJUMP) && self->IsFriend(target)) - return numret; + ACTION_RETURN_STATE(NULL); fixed_t distance = self->AproxDistance3D(target); if (dist_max && (distance > dist_max)) - return numret; + ACTION_RETURN_STATE(NULL); if (dist_close && (distance < dist_close)) { if (flags & JLOSF_CLOSENOJUMP) - return numret; + ACTION_RETURN_STATE(NULL); if (flags & JLOSF_CLOSENOFOV) fov = 0; @@ -4004,7 +3892,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) else { viewport = self; } if (doCheckSight && !P_CheckSight (viewport, target, SF_IGNOREVISIBILITY)) - return numret; + ACTION_RETURN_STATE(NULL); if (flags & JLOSF_FLIPFOV) { @@ -4018,13 +3906,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) { - return numret; // [KS] Outside of FOV - return + ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return } - } - - ACTION_JUMP(jump); - return numret; + ACTION_RETURN_STATE(jump); } @@ -4047,8 +3932,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) angle_t an; AActor *target; - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - if (flags & JLOSF_CHECKMASTER) { target = self->master; @@ -4067,19 +3950,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) if (target == NULL) { // [KS] Let's not call P_CheckSight unnecessarily in this case. - return numret; + ACTION_RETURN_STATE(NULL); } if ((flags & JLOSF_DEADNOJUMP) && (target->health <= 0)) { - return numret; + ACTION_RETURN_STATE(NULL); } fixed_t distance = self->AproxDistance3D(target); if (dist_max && (distance > dist_max)) { - return numret; + ACTION_RETURN_STATE(NULL); } bool doCheckSight = !(flags & JLOSF_NOSIGHT); @@ -4087,7 +3970,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) if (dist_close && (distance < dist_close)) { if (flags & JLOSF_CLOSENOJUMP) - return numret; + ACTION_RETURN_STATE(NULL); if (flags & JLOSF_CLOSENOFOV) fov = 0; @@ -4102,14 +3985,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) { - return numret; // [KS] Outside of FOV - return + ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return } } if (doCheckSight && !P_CheckSight (target, self, SF_IGNOREVISIBILITY)) - return numret; + ACTION_RETURN_STATE(NULL); - ACTION_JUMP(jump); - return numret; + ACTION_RETURN_STATE(jump); } //=========================================================================== @@ -4123,14 +4005,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) PARAM_ACTION_PROLOGUE; if ( self->player == NULL || self->player->ReadyWeapon == NULL ) - return 0; + ACTION_RETURN_STATE(NULL); PARAM_INT (count); PARAM_STATE (jump); PARAM_BOOL_OPT (dontincrement) { dontincrement = false; } - if (count <= 0) - return 0; + if (numret > 0) + { + ret->SetPointer(NULL, ATAG_STATE); + numret = 1; + } AWeapon *weapon = self->player->ReadyWeapon; @@ -4144,17 +4029,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) if (ReloadCounter != 0) { // Go back to the refire frames, instead of continuing on to the reload frames. - ACTION_JUMP(jump); + if (numret != 0) + { + ret->SetPointer(jump, ATAG_STATE); + } } else { // We need to reload. However, don't reload if we're out of ammo. weapon->CheckAmmo(false, false); } - if (!dontincrement) + { weapon->ReloadCounter = ReloadCounter; - return 0; + } + return numret; } //=========================================================================== @@ -4286,19 +4175,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) PARAM_STATE (jumpto); PARAM_INT_OPT (checkpointer) { checkpointer = AAPTR_DEFAULT; } - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - AActor *owner = COPY_AAPTR(self, checkpointer); if (owner == NULL) { - return numret; + ACTION_RETURN_STATE(NULL); } if (CheckActorFlag(owner, flagname)) { - ACTION_JUMP(jumpto); + ACTION_RETURN_STATE(jumpto); } - return numret; + ACTION_RETURN_STATE(NULL); } @@ -4394,20 +4281,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire) PARAM_INT (prob); PARAM_STATE (jump); - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! A_FaceTarget(self); if (pr_monsterrefire() < prob) - return numret; + ACTION_RETURN_STATE(NULL); if (self->target == NULL || P_HitFriend (self) || self->target->health <= 0 || !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) ) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } //=========================================================================== @@ -4739,7 +4625,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) AActor *ref = COPY_AAPTR(self, ptr); - ACTION_SET_RESULT(false); + // A_Teleport and A_Warp were the only codepointers that can state jump + // *AND* have a meaningful inventory state chain result. Grrr. + if (numret > 1) + { + ret[1].SetInt(false); + numret = 2; + } + if (numret > 0) + { + ret[0].SetPointer(NULL, ATAG_STATE); + } + if (!ref) { return numret; @@ -4782,7 +4679,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) target_type = PClass::FindActor("BossSpot"); } - AActor * spot = state->GetSpotWithMinMaxDistance(target_type, ref->X(), ref->Y(), mindist, maxdist); + AActor *spot = state->GetSpotWithMinMaxDistance(target_type, ref->X(), ref->Y(), mindist, maxdist); if (spot == NULL) { return numret; @@ -4860,7 +4757,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) if (!(flags & TF_NOJUMP)) //The state jump should only happen with the calling actor. { - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! if (teleport_state == NULL) { // Default to Teleport. @@ -4871,11 +4767,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) return numret; } } - ACTION_JUMP(teleport_state); + if (numret > 0) + { + ret[0].SetPointer(teleport_state, ATAG_STATE); + } return numret; } } - ACTION_SET_RESULT(tele_result); + if (numret > 1) + { + ret[1].SetInt(tele_result); + } return numret; } @@ -5035,8 +4937,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect) self->flags6 |= MF6_LINEDONE; // no more for this thing } } - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_BOOL(res); } //========================================================================== @@ -5177,6 +5078,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) AActor *reference; + // A_Teleport and A_Warp were the only codepointers that can state jump + // *AND* have a meaningful inventory state chain result. Grrr. + if (numret > 1) + { + ret[1].SetInt(false); + numret = 2; + } + if (numret > 0) + { + ret[0].SetPointer(NULL, ATAG_STATE); + } + if ((flags & WARPF_USETID)) { reference = SingleActorFromTID(destination_selector, self); @@ -5189,7 +5102,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) //If there is no actor to warp to, fail. if (!reference) { - ACTION_SET_RESULT(false); return numret; } @@ -5197,17 +5109,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) { if (success_state) { - ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! + // Jumps should never set the result for inventory state chains! // in this case, you have the statejump to help you handle all the success anyway. - ACTION_JUMP(success_state); - return numret; + if (numret > 0) + { + ret[0].SetPointer(success_state, ATAG_STATE); + } + } + else if (numret > 1) + { + ret[1].SetInt(true); } - - ACTION_SET_RESULT(true); - } - else - { - ACTION_SET_RESULT(false); } return numret; } @@ -5234,8 +5146,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecuteWithResult) PARAM_INT_OPT (arg4) { arg4 = 0; } int res = P_ExecuteSpecial(ACS_ExecuteWithResult, NULL, self, false, -scriptname, arg1, arg2, arg3, arg4); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecute) @@ -5248,8 +5159,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecute) PARAM_INT_OPT (arg3) { arg3 = 0; } int res = P_ExecuteSpecial(ACS_Execute, NULL, self, false, -scriptname, mapnum, arg1, arg2, arg3); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecuteAlways) @@ -5262,8 +5172,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedExecuteAlways) PARAM_INT_OPT (arg3) { arg3 = 0; } int res = P_ExecuteSpecial(ACS_ExecuteAlways, NULL, self, false, -scriptname, mapnum, arg1, arg2, arg3); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedLockedExecute) @@ -5276,8 +5185,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedLockedExecute) PARAM_INT_OPT (lock) { lock = 0; } int res = P_ExecuteSpecial(ACS_LockedExecute, NULL, self, false, -scriptname, mapnum, arg1, arg2, lock); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedLockedExecuteDoor) @@ -5290,8 +5198,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedLockedExecuteDoor) PARAM_INT_OPT (lock) { lock = 0; } int res = P_ExecuteSpecial(ACS_LockedExecuteDoor, NULL, self, false, -scriptname, mapnum, arg1, arg2, lock); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedSuspend) @@ -5301,8 +5208,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedSuspend) PARAM_INT_OPT (mapnum) { mapnum = 0; } int res = P_ExecuteSpecial(ACS_Suspend, NULL, self, false, -scriptname, mapnum, 0, 0, 0); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedTerminate) @@ -5312,8 +5218,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedTerminate) PARAM_INT_OPT (mapnum) { mapnum = 0; } int res = P_ExecuteSpecial(ACS_Terminate, NULL, self, false, -scriptname, mapnum, 0, 0, 0); - ACTION_SET_RESULT(res); - return numret; + ACTION_RETURN_INT(res); } @@ -5348,7 +5253,6 @@ enum RadiusGiveFlags RGF_OBJECTS = 1 << 3, RGF_VOODOO = 1 << 4, RGF_CORPSES = 1 << 5, - RGF_MASK = 2111, RGF_NOTARGET = 1 << 6, RGF_NOTRACER = 1 << 7, RGF_NOMASTER = 1 << 8, @@ -5361,6 +5265,14 @@ enum RadiusGiveFlags RGF_EXFILTER = 1 << 15, RGF_EXSPECIES = 1 << 16, RGF_EITHER = 1 << 17, + + RGF_MASK = /*2111*/ + RGF_GIVESELF | + RGF_PLAYERS | + RGF_MONSTERS | + RGF_OBJECTS | + RGF_VOODOO | + RGF_CORPSES | RGF_MISSILES, }; static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amount, fixed_t distance, int flags, PClassActor *filter, FName species, fixed_t mindist) @@ -5503,8 +5415,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) // We need a valid item, valid targets, and a valid range if (item == NULL || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance) { - ACTION_SET_RESULT(false); - return numret; + ACTION_RETURN_INT(0); } if (amount == 0) @@ -5512,13 +5423,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) amount = 1; } AActor *thing; - bool given = false; + int given = 0; if (flags & RGF_MISSILES) { TThinkerIterator it; while ((thing = it.Next())) { - given |= DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist); + given += DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist); } } else @@ -5526,11 +5437,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance)); while ((thing = it.Next())) { - given |= DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist); + given += DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist); } } - ACTION_SET_RESULT(given); - return numret; + ACTION_RETURN_INT(given); } //=========================================================================== @@ -5547,16 +5457,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSpecies) AActor *mobj = COPY_AAPTR(self, ptr); - ACTION_SET_RESULT(false); - // Needs at least one state jump to work. - if (mobj == NULL) - { - return numret; - } - - if (jump && mobj->GetSpecies() == species) - ACTION_JUMP(jump); - return numret; + if (mobj != NULL && jump && mobj->GetSpecies() == species) + ACTION_RETURN_STATE(jump); + ACTION_RETURN_STATE(NULL); } //========================================================================== @@ -5653,7 +5556,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatSpeed) if (!ref) { - ACTION_SET_RESULT(false); return 0; } @@ -5676,12 +5578,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPainThreshold) if (!ref) { - ACTION_SET_RESULT(false); - return numret; + return 0; } ref->PainThreshold = threshold; - return numret; + return 0; } //=========================================================================== @@ -6358,15 +6259,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower) AActor *mobj = COPY_AAPTR(self, ptr); - ACTION_SET_RESULT(false); //No inventory jump chains please. if (mobj != NULL && mobj != self) //AAPTR_DEFAULT is completely useless in this regard. { - if ((high) && (mobj->Z() > ((includeHeight ? self->height : 0) + self->Z() + offsethigh))) - ACTION_JUMP(high); - else if ((low) && (mobj->Z() + (includeHeight ? mobj->height : 0)) < (self->Z() + offsetlow)) - ACTION_JUMP(low); + if ((high) && (mobj->Z() > ((includeHeight ? self->height : 0) + self->Z() + offsethigh))) + { + ACTION_RETURN_STATE(high); + } + else if ((low) && (mobj->Z() + (includeHeight ? mobj->height : 0)) < (self->Z() + offsetlow)) + { + ACTION_RETURN_STATE(low); + } } - return numret; + ACTION_RETURN_STATE(NULL); } //=========================================================================== @@ -6383,7 +6287,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecies) AActor *mobj = COPY_AAPTR(self, ptr); if (!mobj) { - ACTION_SET_RESULT(false); return 0; } @@ -6452,7 +6355,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold) AActor *mobj = COPY_AAPTR(self, ptr); if (!mobj) { - ACTION_SET_RESULT(false); return 0; } if (def) @@ -6495,19 +6397,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } - ACTION_SET_RESULT(false); //No inventory chain results please. - - if (!jump) { if (!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER))) - return numret; + ACTION_RETURN_STATE(NULL); } AActor *ref = COPY_AAPTR(self, ptr); - //We need these to check out. + // We need these to check out. if (!ref || !classname || distance <= 0) - return numret; + ACTION_RETURN_STATE(NULL); int counter = 0; bool result = false; @@ -6617,9 +6516,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) if (result && jump) { - ACTION_JUMP(jump); + ACTION_RETURN_STATE(jump); } - return numret; + ACTION_RETURN_STATE(NULL); } /*=========================================================================== @@ -6649,16 +6548,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) AActor *mobj = COPY_AAPTR(self, ptr); - ACTION_SET_RESULT(false); //Needs at least one state jump to work. if (!mobj) { - return numret; + ACTION_RETURN_STATE(NULL); } //Nothing to block it so skip the rest. bool checker = (flags & CBF_DROPOFF) ? P_CheckMove(mobj, mobj->X(), mobj->Y()) : P_TestMobjLocation(mobj); - if (checker) return numret; + if (checker) ACTION_RETURN_STATE(NULL); if (mobj->BlockingMobj) { @@ -6675,14 +6573,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) //this point. I.e. A_CheckBlock("",CBF_SETTRACER) is like having CBF_NOLINES. //It gets the mobj blocking, if any, and doesn't jump at all. if (!block) - return numret; + ACTION_RETURN_STATE(NULL); //[MC] Easiest way to tell if an actor is blocking it, use the pointers. if (mobj->BlockingMobj || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL)) { - ACTION_JUMP(block); + ACTION_RETURN_STATE(block); } - return numret; + ACTION_RETURN_STATE(NULL); } //=========================================================================== @@ -6711,8 +6609,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) //Need an actor. if (!mobj || ((flags & FMDF_NOPITCH) && (flags & FMDF_NOANGLE))) { - ACTION_SET_RESULT(false); - return numret; + ACTION_RETURN_BOOL(false); } //Don't bother calculating this if we don't have any horizontal movement. @@ -6792,5 +6689,5 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) mobj->SetPitch(pitch, !!(flags & FMDF_INTERPOLATE)); } } - return numret; + ACTION_RETURN_BOOL(true); } diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 8901e35c3..0ec4c95d7 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -204,6 +204,7 @@ public: virtual bool isConstant() const; virtual void RequestAddress(); + virtual VMFunction *GetDirectFunction(); virtual ExpEmit Emit(VMFunctionBuilder *build); @@ -817,39 +818,22 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; -//========================================================================== -// -// FxTailable -// -// An expression that can produce a tail call -// -//========================================================================== - -class FxTailable : public FxExpression -{ -public: - FxTailable(const FScriptPosition &pos) : FxExpression(pos) {} - virtual ExpEmit Emit(VMFunctionBuilder *build, bool tailcall) = 0; - ExpEmit Emit(VMFunctionBuilder *build); - virtual VMFunction *GetDirectFunction(); -}; - //========================================================================== // // FxVMFunctionCall // //========================================================================== -class FxVMFunctionCall : public FxTailable +class FxVMFunctionCall : public FxExpression { PFunction *Function; FArgumentList *ArgList; - PType *ReturnType; public: FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build, bool tailcall); unsigned GetArgCount() { return ArgList == NULL ? 0 : ArgList->Size(); } VMFunction *GetVMFunction() { return Function->Variants[0].Implementation; } @@ -862,15 +846,15 @@ public: // //========================================================================== -class FxSequence : public FxTailable +class FxSequence : public FxExpression { - TDeletingArray Expressions; + TDeletingArray Expressions; public: - FxSequence(const FScriptPosition &pos) : FxTailable(pos) {} + FxSequence(const FScriptPosition &pos) : FxExpression(pos) {} FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build, bool tailcall); - void Add(FxTailable *expr) { if (expr != NULL) Expressions.Push(expr); } + ExpEmit Emit(VMFunctionBuilder *build); + void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); } VMFunction *GetDirectFunction(); }; @@ -880,17 +864,17 @@ public: // //========================================================================== -class FxIfStatement : public FxTailable +class FxIfStatement : public FxExpression { FxExpression *Condition; - FxTailable *WhenTrue; - FxTailable *WhenFalse; + FxExpression *WhenTrue; + FxExpression *WhenFalse; public: - FxIfStatement(FxExpression *cond, FxTailable *true_part, FxTailable *false_part, const FScriptPosition &pos); + FxIfStatement(FxExpression *cond, FxExpression *true_part, FxExpression *false_part, const FScriptPosition &pos); ~FxIfStatement(); FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build, bool tailcall); + ExpEmit Emit(VMFunctionBuilder *build); }; //========================================================================== @@ -899,11 +883,14 @@ public: // //========================================================================== -class FxReturnStatement : public FxTailable +class FxReturnStatement : public FxExpression { + FxVMFunctionCall *Call; + public: - FxReturnStatement(const FScriptPosition &pos); - ExpEmit Emit(VMFunctionBuilder *build, bool tailcall); + FxReturnStatement(FxVMFunctionCall *call, const FScriptPosition &pos); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); }; //========================================================================== diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 0d6e009fd..c94d6840d 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -129,6 +129,17 @@ bool FxExpression::isConstant() const // //========================================================================== +VMFunction *FxExpression::GetDirectFunction() +{ + return NULL; +} + +//========================================================================== +// +// +// +//========================================================================== + FxExpression *FxExpression::Resolve(FCompileContext &ctx) { isresolved = true; @@ -3064,28 +3075,6 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) return dest; } -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxTailable::Emit(VMFunctionBuilder *build) -{ - return Emit(build, false); -} - -//========================================================================== -// -// -// -//========================================================================== - -VMFunction *FxTailable::GetDirectFunction() -{ - return NULL; -} - //========================================================================== // // FxVMFunctionCall @@ -3093,7 +3082,7 @@ VMFunction *FxTailable::GetDirectFunction() //========================================================================== FxVMFunctionCall::FxVMFunctionCall(PFunction *func, FArgumentList *args, const FScriptPosition &pos) -: FxTailable(pos) +: FxExpression(pos) { Function = func; ArgList = args; @@ -3134,14 +3123,9 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) delete this; return NULL; } - TArray &rets = Function->Variants[0].Proto->ReturnTypes; - if (rets.Size() == 0) + TArray &rets = Function->Variants[0].Implementation->Proto->ReturnTypes; + if (rets.Size() > 0) { - ReturnType = TypeVoid; - } - else - { - ReturnType = rets[0]; // If more types are added to ParseNativeFunction(), add them here too. if (rets[0] == TypeSInt32) ValueType = VAL_Int; else if (rets[0] == TypeFloat64) ValueType = VAL_Float; @@ -3165,6 +3149,11 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) // //========================================================================== +ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) +{ + return Emit(build, false); +} + ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall) { assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3); @@ -3191,17 +3180,17 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall) } } // Get a constant register for this function - int funcaddr = build->GetConstantAddress(Function->Variants[0].Implementation, ATAG_OBJECT); + VMFunction *vmfunc = Function->Variants[0].Implementation; + int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT); // Emit the call if (tailcall) { // Tail call build->Emit(OP_TAIL_K, funcaddr, count, 0); return ExpEmit(); } - else if (ReturnType != TypeVoid) + else if (vmfunc->Proto->ReturnTypes.Size() > 0) { // Call, expecting one result - assert(ReturnType != NULL); - ExpEmit reg(build, ReturnType->GetRegType()); + ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType()); build->Emit(OP_CALL_K, funcaddr, count, 1); build->Emit(OP_RESULT, 0, reg.RegType, reg.RegNum); return reg; @@ -3331,7 +3320,7 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) CHECKRESOLVED(); for (unsigned i = 0; i < Expressions.Size(); ++i) { - if (NULL == (Expressions[i] = static_cast(Expressions[i]->Resolve(ctx)))) + if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx))) { delete this; return NULL; @@ -3346,11 +3335,11 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx) // //========================================================================== -ExpEmit FxSequence::Emit(VMFunctionBuilder *build, bool tailcall) +ExpEmit FxSequence::Emit(VMFunctionBuilder *build) { for (unsigned i = 0; i < Expressions.Size(); ++i) { - ExpEmit v = Expressions[i]->Emit(build, tailcall ? i == Expressions.Size()-1 : false); + ExpEmit v = Expressions[i]->Emit(build); // Throw away any result. We don't care about it. v.Free(build); } @@ -3378,9 +3367,9 @@ VMFunction *FxSequence::GetDirectFunction() // //========================================================================== -FxIfStatement::FxIfStatement(FxExpression *cond, FxTailable *true_part, - FxTailable *false_part, const FScriptPosition &pos) -: FxTailable(pos) +FxIfStatement::FxIfStatement(FxExpression *cond, FxExpression *true_part, + FxExpression *false_part, const FScriptPosition &pos) +: FxExpression(pos) { Condition = cond; WhenTrue = true_part; @@ -3407,12 +3396,12 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) ABORT(Condition); if (WhenTrue != NULL) { - WhenTrue = static_cast(WhenTrue->Resolve(ctx)); + WhenTrue = WhenTrue->Resolve(ctx); ABORT(WhenTrue); } if (WhenFalse != NULL) { - WhenFalse = static_cast(WhenFalse->Resolve(ctx)); + WhenFalse = WhenFalse->Resolve(ctx); ABORT(WhenFalse); } ValueType = VAL_Unknown; @@ -3422,7 +3411,7 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) ExpVal condval = static_cast(Condition)->GetValue(); bool result = condval.GetBool(); - FxTailable *e = result ? WhenTrue : WhenFalse; + FxExpression *e = result ? WhenTrue : WhenFalse; delete (result ? WhenFalse : WhenTrue); WhenTrue = WhenFalse = NULL; delete this; @@ -3431,11 +3420,11 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) return this; } -ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build, bool tailcall) +ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) { ExpEmit v; size_t jumpspot; - FxTailable *path1, *path2; + FxExpression *path1, *path2; int condcheck; // This is pretty much copied from FxConditional, except we don't @@ -3465,24 +3454,18 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build, bool tailcall) cond.Free(build); // Evaluate first path - v = path1->Emit(build, tailcall); + v = path1->Emit(build); v.Free(build); if (path2 != NULL) { size_t path1jump = build->Emit(OP_JMP, 0); // Evaluate second path build->BackpatchToHere(jumpspot); - v = path2->Emit(build, tailcall); + v = path2->Emit(build); v.Free(build); jumpspot = path1jump; } build->BackpatchToHere(jumpspot); - if (tailcall) - { - // When tailcall is true, execution is not expected to get past - // this if statement, so issue a RET. - build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); - } return ExpEmit(); } @@ -3490,14 +3473,35 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build, bool tailcall) // //========================================================================== -FxReturnStatement::FxReturnStatement(const FScriptPosition &pos) -: FxTailable(pos) +FxReturnStatement::FxReturnStatement(FxVMFunctionCall *call, const FScriptPosition &pos) +: FxExpression(pos), Call(call) { } -ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build, bool tailcall) +FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) { - build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); + CHECKRESOLVED(); + if (Call != NULL) + { + Call = static_cast(Call->Resolve(ctx)); + ABORT(Call); + } + return this; +} + +ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build) +{ + // If we return nothing, use a regular RET opcode. If we return + // something, use TAIL to call the function. Our return type + // should be compatible with the called function's return type. + if (Call == NULL) + { + build->Emit(OP_RET, RET_FINAL, REGT_NIL, 0); + } + else + { + Call->Emit(build, true); + } return ExpEmit(); } diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 255e2adaf..4774ac9d1 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -375,6 +375,42 @@ static void ParseArgListDef(FScanner &sc, PClassActor *cls, sc.MustGetToken(';'); } +//========================================================================== +// +// SetImplicitArgs +// +// Adds the parameters implied by the function flags. +// +//========================================================================== + +void SetImplicitArgs(TArray *args, TArray *argflags, PClassActor *cls, DWORD funcflags) +{ + // Must be called before adding any other arguments. + assert(args == NULL || args->Size() == 0); + assert(argflags == NULL || argflags->Size() == 0); + + if (funcflags & VARF_Method) + { + // implied self pointer + if (args != NULL) args->Push(NewClassPointer(cls)); + if (argflags != NULL) argflags->Push(0); + } + if (funcflags & VARF_Action) + { + // implied stateowner and callingstate pointers + if (args != NULL) + { + args->Push(NewClassPointer(RUNTIME_CLASS(AActor))); + args->Push(TypeState); + } + if (argflags != NULL) + { + argflags->Push(0); + argflags->Push(0); + } + } +} + //========================================================================== // // ParseFunctionDef @@ -401,15 +437,7 @@ void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname, } sc.MustGetToken('('); - if (funcflags & VARF_Method) - { - args.Push(NewClassPointer(cls)), argflags.Push(0); // implied self pointer - } - if (funcflags & VARF_Action) - { - args.Push(NewClassPointer(RUNTIME_CLASS(AActor))), argflags.Push(0); // implied stateowner pointer - args.Push(TypeState), argflags.Push(0); // implied callingstate pointer - } + SetImplicitArgs(&args, &argflags, cls, funcflags); ParseArgListDef(sc, cls, args, argflags); if (afd != NULL) @@ -1036,18 +1064,22 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls) sc.MustGetToken(TK_Native); // check for a return value - if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Bool)) + do { - rets.Push(TypeSInt32); - } - else if (sc.CheckToken(TK_State)) - { - rets.Push(TypeState); - } - else if (sc.CheckToken(TK_Float)) - { - rets.Push(TypeFloat64); + if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Bool)) + { + rets.Push(TypeSInt32); + } + else if (sc.CheckToken(TK_State)) + { + rets.Push(TypeState); + } + else if (sc.CheckToken(TK_Float)) + { + rets.Push(TypeFloat64); + } } + while (sc.CheckToken(',')); sc.MustGetToken(TK_Identifier); funcname = sc.String; ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action); diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index d6f3eb939..5b54d684d 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -314,7 +314,12 @@ do_stop: continue; } - tcall->Code = ParseActions(sc, state, statestring, bag); + bool hasfinalret; + tcall->Code = ParseActions(sc, state, statestring, bag, tcall->Proto, hasfinalret); + if (!hasfinalret) + { + AddImplicitReturn(static_cast(tcall->Code), tcall->Proto, sc); + } goto endofstate; } sc.UnGet(); @@ -348,49 +353,162 @@ endofstate: //========================================================================== // -// ParseActions +// AddImplicitReturn +// +// Adds an implied return; statement to the end of a code sequence. // //========================================================================== -FxTailable *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag) +void AddImplicitReturn(FxSequence *code, const PPrototype *proto, FScanner &sc) +{ + if (proto == NULL || proto->ReturnTypes.Size() == 0) + { // Returns nothing. Good. We can safely add an implied return. + code->Add(new FxReturnStatement(NULL, sc)); + } + else + { // Something was returned earlier in the sequence. Make it an error + // instead of adding an implicit one. + sc.ScriptError("Action list must end with a return statement"); + } +} + +//========================================================================== +// +// ReturnCheck +// +// If proto1 is NULL, returns proto2. If proto2 is NULL, returns proto1. +// If neither is null, checks if both prototypes define the same return +// types. If not, an error is flagged. +// +//========================================================================== + +static PPrototype *ReturnCheck(PPrototype *proto1, PPrototype *proto2, FScanner &sc) +{ + if (proto1 == NULL) + { + return proto2; + } + if (proto2 == NULL) + { + return proto1; + } + // A prototype that defines fewer return types can be compatible with + // one that defines more if the shorter one matches the initial types + // for the longer one. + if (proto2->ReturnTypes.Size() < proto1->ReturnTypes.Size()) + { // Make proto1 the shorter one to avoid code duplication below. + swapvalues(proto1, proto2); + } + // If one prototype returns nothing, they both must. + if (proto1->ReturnTypes.Size() == 0) + { + if (proto2->ReturnTypes.Size() == 0) + { + return proto1; + } + proto1 = NULL; + } + else + { + for (unsigned i = 0; i < proto1->ReturnTypes.Size(); ++i) + { + if (proto1->ReturnTypes[i] != proto2->ReturnTypes[i]) + { // Incompatible + proto1 = NULL; + break; + } + } + } + if (proto1 == NULL) + { + sc.ScriptError("Return types are incompatible"); + } + return proto1; +} + +//========================================================================== +// +// ParseActions +// +// If this action block contains any return statements, the prototype for +// one of them will be returned. This is used for deducing the return type +// of anonymous functions. All called functions passed to return must have +// matching return types. +// +//========================================================================== + +FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, + PPrototype *&retproto, bool &endswithret) { // If it's not a '{', then it should be a single action. // Otherwise, it's a sequence of actions. if (!sc.Compare("{")) { - return ParseAction(sc, state, statestring, bag); + FxVMFunctionCall *call = ParseAction(sc, state, statestring, bag); + retproto = call->GetVMFunction()->Proto; + endswithret = true; + return new FxReturnStatement(call, sc); } const FScriptPosition pos(sc); FxSequence *seq = NULL; + PPrototype *proto = NULL; + bool lastwasret = false; + sc.MustGetString(); while (!sc.Compare("}")) { - FxTailable *add; + FxExpression *add; + lastwasret = false; if (sc.Compare("if")) { // Hangle an if statement FxExpression *cond; - FxTailable *true_part, *false_part = NULL; + FxExpression *true_part, *false_part = NULL; + PPrototype *true_proto, *false_proto = NULL; + bool true_ret, false_ret = false; sc.MustGetStringName("("); cond = ParseExpression(sc, bag.Info); sc.MustGetStringName(")"); sc.MustGetStringName("{"); // braces are mandatory - true_part = ParseActions(sc, state, statestring, bag); + true_part = ParseActions(sc, state, statestring, bag, true_proto, true_ret); sc.MustGetString(); if (sc.Compare("else")) { sc.MustGetStringName("{"); // braces are still mandatory - false_part = ParseActions(sc, state, statestring, bag); + false_part = ParseActions(sc, state, statestring, bag, false_proto, false_ret); sc.MustGetString(); } add = new FxIfStatement(cond, true_part, false_part, sc); + proto = ReturnCheck(proto, true_proto, sc); + proto = ReturnCheck(proto, false_proto, sc); + // If one side does not end with a return, we don't consider the if statement + // to end with a return. + if (true_ret && (false_proto == NULL || false_ret)) + { + lastwasret = true; + } } else if (sc.Compare("return")) { // Handle a return statement - sc.MustGetStringName(";"); + lastwasret = true; + FxVMFunctionCall *retexp = NULL; + PPrototype *retproto; sc.MustGetString(); - add = new FxReturnStatement(sc); + if (!sc.Compare(";")) + { + retexp = ParseAction(sc, state, statestring, bag); + sc.MustGetStringName(";"); + retproto = retexp->GetVMFunction()->Proto; + } + else + { // Returning nothing; we still need a prototype for that. + TArray notypes(0); + retproto = NewPrototype(notypes, notypes); + } + proto = ReturnCheck(proto, retproto, sc); + sc.MustGetString(); + add = new FxReturnStatement(retexp, sc); } else { // Handle a regular action function call @@ -408,6 +526,8 @@ FxTailable *ParseActions(FScanner &sc, FState state, FString statestring, Baggag seq->Add(add); } } + endswithret = lastwasret; + retproto = proto; return seq; } @@ -460,7 +580,7 @@ FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, B void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray &out_params, PFunction *afd, FString statestring, FStateDefinitions *statedef) { - const TArray ¶ms = afd->Variants[0].Proto->ArgumentTypes; + const TArray ¶ms = afd->Variants[0].Implementation->Proto->ArgumentTypes; const TArray ¶mflags = afd->Variants[0].ArgFlags; int numparams = (int)params.Size(); int pnum = 0; diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 69cbe9d8d..ce5d5269a 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -162,8 +162,10 @@ public: bool Native; FName Name; - VMFunction() : Native(false), Name(NAME_None) {} - VMFunction(FName name) : Native(false), Name(name) {} + class PPrototype *Proto; + + VMFunction() : Native(false), Name(NAME_None), Proto(NULL) {} + VMFunction(FName name) : Native(false), Name(name), Proto(NULL) {} }; enum EVMOpMode diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 48ee9f68f..5b0f3a2de 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -46,7 +46,7 @@ ACTOR Actor native //: Thinker // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. action native A_Turn(float angle = 0); - action native A_LineEffect(int boomspecial = 0, int tag = 0); + action native bool A_LineEffect(int boomspecial = 0, int tag = 0); // End of MBF redundant functions. action native A_MonsterRail(); @@ -108,7 +108,7 @@ ACTOR Actor native //: Thinker action native A_Die(name damagetype = "none"); action native A_Detonate(); action native A_Mushroom(class spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5); - action native A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); + action native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); action native A_SetFloorClip(); action native A_UnSetFloorClip(); @@ -181,22 +181,22 @@ ACTOR Actor native //: Thinker 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_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); - action native A_Jump(int chance = 256, state label, ...); + action native state A_Jump(int chance = 256, state label, ...); action native A_CustomMissile(class missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET); action native A_CustomBulletAttack(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET); action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class pufftype = "BulletPuff", float/*angle*/ spread_xy = 0, float/*angle*/ spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270); - action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT); - action native A_JumpIfCloser(float distance, state label, bool noz = false); - action native A_JumpIfTracerCloser(float distance, state label, bool noz = false); - action native A_JumpIfMasterCloser(float distance, state label, bool noz = false); - action native A_JumpIfTargetOutsideMeleeRange(state label); - action native A_JumpIfTargetInsideMeleeRange(state label); - action native A_JumpIfInventory(class itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); - action native A_JumpIfArmorType(name Type, state label, int amount = 1); - action native A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); - action native A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); - action native A_SpawnItem(class itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); - action native A_SpawnItemEx(class itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0, int tid=0); + action native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT); + action native state A_JumpIfCloser(float distance, state label, bool noz = false); + action native state A_JumpIfTracerCloser(float distance, state label, bool noz = false); + action native state A_JumpIfMasterCloser(float distance, state label, bool noz = false); + action native state A_JumpIfTargetOutsideMeleeRange(state label); + action native state A_JumpIfTargetInsideMeleeRange(state label); + action native state A_JumpIfInventory(class itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); + action native state A_JumpIfArmorType(name Type, state label, int amount = 1); + action native bool A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); + action native bool A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); + action native bool A_SpawnItem(class itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); + action native bool A_SpawnItemEx(class itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0, int tid=0); action native A_Print(string whattoprint, float time = 0, name fontname = ""); action native A_PrintBold(string whattoprint, float time = 0, name fontname = ""); action native A_Log(string whattoprint); @@ -209,31 +209,31 @@ ACTOR Actor native //: Thinker action native A_SetMass(int mass); action native A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); action native A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, int size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1); - action native A_CheckSight(state label); + action native state A_CheckSight(state label); action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); action native A_DropInventory(class itemtype); action native A_SetBlend(color color1, float alpha, int tics, color color2 = ""); action native A_ChangeFlag(string flagname, bool value); - action native A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); - action native A_JumpIf(bool expression, state label); + action native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); + action native state A_JumpIf(bool expression, state label); action native A_RaiseMaster(bool copy = 0); action native A_RaiseChildren(bool copy = 0); action native A_RaiseSiblings(bool copy = 0); - action native A_CheckFloor(state label); - action native A_CheckCeiling(state label); - action native A_PlayerSkinCheck(state label); + action native state A_CheckFloor(state label); + action native state A_CheckCeiling(state label); + action native state A_PlayerSkinCheck(state label); action native A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - action native A_Teleport(state teleportstate = "", class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); - action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0); - action native A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); + action native state, bool A_Teleport(state teleportstate = "", class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT); + action native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0); + action native bool A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); action native A_Weave(int xspeed, int yspeed, float xdist, float ydist); action native A_Recoil(float xyvel); - action native A_JumpIfInTargetInventory(class itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT); - action native A_GiveToTarget(class itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); - action native A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); - action native A_RadiusGive(class itemtype, float distance, int flags, int amount = 0, class filter = "None", name species = "None", int mindist = 0); - action native A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT); + action native state A_JumpIfInTargetInventory(class itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT); + action native bool A_GiveToTarget(class itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); + action native bool A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); + action native int A_RadiusGive(class itemtype, float distance, int flags, int amount = 0, class filter = "None", name species = "None", int mindist = 0); + action native state A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT); action native A_CountdownArg(int argnum, state targstate = ""); action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); action native A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); @@ -249,10 +249,10 @@ ACTOR Actor native //: Thinker action native A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = ""); action native A_ClearLastHeard(); action native A_ClearTarget(); - action native A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT); - action native A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); - action native A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); - action native A_SelectWeapon(class whichweapon); + action native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT); + action native state A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); + action native state A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); + action native bool A_SelectWeapon(class whichweapon); action native A_Punch(); action native A_Feathers(); action native A_ClassBossHealth(); @@ -264,7 +264,7 @@ ACTOR Actor native //: Thinker action native A_RemoveForcefield(); action native A_DropWeaponPieces(class p1, class p2, class p3); action native A_PigPain (); - action native A_MonsterRefire(int chance, state label); + action native state A_MonsterRefire(int chance, state label); action native A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); action native A_SetPitch(float pitch, int flags = 0, int ptr = AAPTR_DEFAULT); action native A_SetRoll(float/*angle*/ roll, int flags = 0, int ptr = AAPTR_DEFAULT); @@ -299,37 +299,37 @@ ACTOR Actor native //: Thinker action native A_RemoveChildren(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); action native A_RemoveSiblings(bool removeall = false, int flags = 0, class filter = "None", name species = "None"); action native A_Remove(int removee, int flags = 0, class filter = "None", name species = "None"); - action native A_GiveToChildren(class itemtype, int amount = 0); - action native A_GiveToSiblings(class itemtype, int amount = 0); - action native A_TakeFromChildren(class itemtype, int amount = 0); - action native A_TakeFromSiblings(class itemtype, int amount = 0); + action native int A_GiveToChildren(class itemtype, int amount = 0); + action native int A_GiveToSiblings(class itemtype, int amount = 0); + action native int A_TakeFromChildren(class itemtype, int amount = 0); + action native int A_TakeFromSiblings(class itemtype, int amount = 0); action native A_SetTeleFog(class oldpos, class newpos); action native A_SwapTeleFog(); action native A_SetFloatBobPhase(int bob); action native A_SetHealth(int health, int ptr = AAPTR_DEFAULT); action native A_ResetHealth(int ptr = AAPTR_DEFAULT); - action native A_JumpIfHigherOrLower(state high, state low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET); + action native state A_JumpIfHigherOrLower(state high, state low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET); action native A_SetSpecies(name species, int ptr = AAPTR_DEFAULT); action native A_SetRipperLevel(int level); action native A_SetRipMin(int min); action native A_SetRipMax(int max); action native A_SetChaseThreshold(int threshold, bool def = false, int ptr = AAPTR_DEFAULT); - action native A_CheckProximity(state jump, class classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT); - action native A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT); - action native A_CheckSightOrRange(float distance, state label, bool two_dimension = false); - action native A_CheckRange(float distance, state label, bool two_dimension = false); - action native A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + action native state A_CheckProximity(state jump, class classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT); + action native state A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT); + action native state A_CheckSightOrRange(float distance, state label, bool two_dimension = false); + action native state A_CheckRange(float distance, state label, bool two_dimension = false); + action native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT); action native A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); action native A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); action native A_CopyFriendliness(int ptr_source = AAPTR_MASTER); - action native ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0); - action native ACS_NamedSuspend(name script, int mapnum=0); - action native ACS_NamedTerminate(name script, int mapnum=0); - action native ACS_NamedLockedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0); - action native ACS_NamedLockedExecuteDoor(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0); - action native ACS_NamedExecuteWithResult(name script, int arg1=0, int arg2=0, int arg3=0, int arg4=0); + action native int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0); + action native int ACS_NamedSuspend(name script, int mapnum=0); + action native int ACS_NamedTerminate(name script, int mapnum=0); + action native int ACS_NamedLockedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0); + action native int ACS_NamedLockedExecuteDoor(name script, int mapnum=0, int arg1=0, int arg2=0, int lock=0); + action native int ACS_NamedExecuteWithResult(name script, int arg1=0, int arg2=0, int arg3=0, int arg4=0); action native ACS_NamedExecuteAlways(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0); States diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index ee9a35446..111339bd9 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -7,7 +7,7 @@ ACTOR Inventory native Inventory.PickupSound "misc/i_pkup" Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG" - action native A_JumpIfNoAmmo(state label); + action native state A_JumpIfNoAmmo(state label); action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = ""); action native A_FireBullets(float/*angle*/ spread_xy, float/*angle*/ spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, float range = 0); action native A_FireCustomMissile(class missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0); @@ -42,7 +42,7 @@ ACTOR Inventory native action native A_CheckReload(); action native A_GunFlash(state flash = "", int flags = 0); action native A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, float range = 0, float/*angle*/ spread_xy = 2.8125, float/*angle*/ spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus"); - action native A_CheckForReload(int counter, state label, bool dontincrement = false); + action native state A_CheckForReload(int counter, state label, bool dontincrement = false); action native A_ResetReloadCounter(); action native A_RestoreSpecialPosition(); action native A_RestoreSpecialDoomThing();