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();