diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index ad6a8b903..554ab0d64 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -825,6 +825,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) { int jumpnum = (count == 1 ? 0 : (pr_cajump() % count)); PARAM_STATE_AT(paramnum + jumpnum, jumpto); + if (jumpto == NULL) + { // Remap NULL state to the 'Null' state found in Actor, since + // returning NULL would not jump. + jumpto = RUNTIME_CLASS(AActor)->FindState(NAME_Null); + } ACTION_RETURN_STATE(jumpto); } ACTION_RETURN_STATE(NULL); @@ -838,9 +843,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower) { PARAM_ACTION_PROLOGUE; - PARAM_INT (health); - PARAM_STATE (jump); - PARAM_INT_OPT (ptr_selector) { ptr_selector = AAPTR_DEFAULT; } + PARAM_INT (health); + PARAM_STATE_NOT_NULL(jump); + PARAM_INT_OPT (ptr_selector) { ptr_selector = AAPTR_DEFAULT; } AActor *measured; @@ -861,7 +866,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetOutsideMeleeRange) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); if (!self->CheckMeleeRange()) { @@ -878,7 +883,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetOutsideMeleeRange) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInsideMeleeRange) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); if (self->CheckMeleeRange()) { @@ -895,9 +900,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInsideMeleeRange) static int DoJumpIfCloser(AActor *target, VM_ARGS) { PARAM_ACTION_PROLOGUE; - PARAM_FIXED (dist); - PARAM_STATE (jump); - PARAM_BOOL_OPT(noz) { noz = false; } + PARAM_FIXED (dist); + PARAM_STATE_NOT_NULL(jump); + PARAM_BOOL_OPT (noz) { noz = false; } if (!target) { // No target - no jump @@ -951,10 +956,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfMasterCloser) int DoJumpIfInventory(AActor *owner, AActor *self, AActor *stateowner, FState *callingstate, VMValue *param, int numparam, VMReturn *ret, int numret) { int paramnum = NAP-1; - PARAM_CLASS (itemtype, AInventory); - PARAM_INT (itemamount); - PARAM_STATE (label); - PARAM_INT_OPT (setowner) { setowner = AAPTR_DEFAULT; } + PARAM_CLASS (itemtype, AInventory); + PARAM_INT (itemamount); + PARAM_STATE_NOT_NULL(label); + PARAM_INT_OPT (setowner) { setowner = AAPTR_DEFAULT; } if (itemtype == NULL) { @@ -1005,9 +1010,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetInventory) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType) { PARAM_ACTION_PROLOGUE; - PARAM_NAME (type); - PARAM_STATE (label); - PARAM_INT_OPT(amount) { amount = 1; } + PARAM_NAME (type); + PARAM_STATE_NOT_NULL(label); + PARAM_INT_OPT (amount) { amount = 1; } ABasicArmor *armor = (ABasicArmor *)self->FindInventory(NAME_BasicArmor); @@ -1462,7 +1467,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfNoAmmo) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); if (!ACTION_CALL_FROM_WEAPON()) { @@ -3029,7 +3034,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); for (int i = 0; i < MAXPLAYERS; i++) { @@ -3097,9 +3102,9 @@ static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range, bool DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) { PARAM_ACTION_PROLOGUE; - PARAM_FLOAT(range); - PARAM_STATE(jump); - PARAM_BOOL_OPT(twodi) { twodi = false; } + PARAM_FLOAT (range); + PARAM_STATE_NOT_NULL(jump); + PARAM_BOOL_OPT (twodi) { twodi = false; } range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots for (int i = 0; i < MAXPLAYERS; ++i) @@ -3162,9 +3167,9 @@ static bool DoCheckRange(AActor *self, AActor *camera, double range, bool twodi) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange) { PARAM_ACTION_PROLOGUE; - PARAM_FLOAT(range); - PARAM_STATE(jump); - PARAM_BOOL_OPT(twodi) { twodi = false; } + PARAM_FLOAT (range); + PARAM_STATE_NOT_NULL(jump); + PARAM_BOOL_OPT (twodi) { twodi = false; } range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots for (int i = 0; i < MAXPLAYERS; ++i) @@ -3245,8 +3250,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetBlend) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIf) { PARAM_ACTION_PROLOGUE; - PARAM_BOOL (condition); - PARAM_STATE (jump); + PARAM_BOOL (condition); + PARAM_STATE_NOT_NULL(jump); ACTION_RETURN_STATE(condition ? jump : NULL); } @@ -3349,7 +3354,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFloor) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); if (self->Z() <= self->floorz) { @@ -3368,7 +3373,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFloor) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckCeiling) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); if (self->Top() >= self->ceilingz) // Height needs to be counted { @@ -3504,7 +3509,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayerSkinCheck) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); if (self->player != NULL && skins[self->player->userinfo.GetSkin()].othergame) @@ -3687,10 +3692,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF) fixed_t vx, vy, vz; PARAM_ACTION_PROLOGUE; - PARAM_STATE (jump); - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FIXED_OPT (range) { range = 0; } - PARAM_FIXED_OPT (minrange) { minrange = 0; } + PARAM_STATE_NOT_NULL(jump); + PARAM_INT_OPT (flags) { flags = 0; } + PARAM_FIXED_OPT (range) { range = 0; } + PARAM_FIXED_OPT (minrange) { minrange = 0; } { PARAM_ANGLE_OPT (angle) { angle = 0; } PARAM_ANGLE_OPT (pitch) { pitch = 0; } @@ -3887,11 +3892,11 @@ enum JLOS_flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) { PARAM_ACTION_PROLOGUE; - PARAM_STATE (jump); - PARAM_ANGLE_OPT (fov) { fov = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FIXED_OPT (dist_max) { dist_max = 0; } - PARAM_FIXED_OPT (dist_close) { dist_close = 0; } + PARAM_STATE_NOT_NULL(jump); + PARAM_ANGLE_OPT (fov) { fov = 0; } + PARAM_INT_OPT (flags) { flags = 0; } + PARAM_FIXED_OPT (dist_max) { dist_max = 0; } + PARAM_FIXED_OPT (dist_close) { dist_close = 0; } angle_t an; AActor *target, *viewport; @@ -4022,11 +4027,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS) { PARAM_ACTION_PROLOGUE; - PARAM_STATE (jump); - PARAM_ANGLE_OPT (fov) { fov = 0; } - PARAM_INT_OPT (flags) { flags = 0; } - PARAM_FIXED_OPT (dist_max) { dist_max = 0; } - PARAM_FIXED_OPT (dist_close) { dist_close = 0; } + PARAM_STATE_NOT_NULL(jump); + PARAM_ANGLE_OPT (fov) { fov = 0; } + PARAM_INT_OPT (flags) { flags = 0; } + PARAM_FIXED_OPT (dist_max) { dist_max = 0; } + PARAM_FIXED_OPT (dist_close) { dist_close = 0; } angle_t an; AActor *target; @@ -4109,9 +4114,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckForReload) { ACTION_RETURN_STATE(NULL); } - PARAM_INT (count); - PARAM_STATE (jump); - PARAM_BOOL_OPT (dontincrement) { dontincrement = false; } + PARAM_INT (count); + PARAM_STATE_NOT_NULL(jump); + PARAM_BOOL_OPT (dontincrement) { dontincrement = false; } if (numret > 0) { @@ -4273,9 +4278,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) { PARAM_ACTION_PROLOGUE; - PARAM_STRING (flagname); - PARAM_STATE (jumpto); - PARAM_INT_OPT (checkpointer) { checkpointer = AAPTR_DEFAULT; } + PARAM_STRING (flagname); + PARAM_STATE_NOT_NULL(jumpto); + PARAM_INT_OPT (checkpointer) { checkpointer = AAPTR_DEFAULT; } AActor *owner = COPY_AAPTR(self, checkpointer); if (owner == NULL) @@ -4380,8 +4385,8 @@ DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_FaceConsolePlayer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire) { PARAM_ACTION_PROLOGUE; - PARAM_INT (prob); - PARAM_STATE (jump); + PARAM_INT (prob); + PARAM_STATE_NOT_NULL(jump); A_FaceTarget(self); @@ -5210,7 +5215,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) if (P_Thing_Warp(self, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch)) { - if (success_state) + if (success_state != NULL) { // 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. @@ -5554,9 +5559,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSpecies) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); - PARAM_NAME_OPT(species) { species = NAME_None; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_STATE_NOT_NULL(jump); + PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; } AActor *mobj = COPY_AAPTR(self, ptr); @@ -6354,12 +6359,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(high); - PARAM_STATE(low); - PARAM_FIXED_OPT(offsethigh) { offsethigh = 0; } - PARAM_FIXED_OPT(offsetlow) { offsetlow = 0; } - PARAM_BOOL_OPT(includeHeight) { includeHeight = true; } - PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; } + PARAM_STATE_NOT_NULL(high); + PARAM_STATE_NOT_NULL(low); + PARAM_FIXED_OPT (offsethigh) { offsethigh = 0; } + PARAM_FIXED_OPT (offsetlow) { offsetlow = 0; } + PARAM_BOOL_OPT (includeHeight) { includeHeight = true; } + PARAM_INT_OPT (ptr) { ptr = AAPTR_TARGET; } AActor *mobj = COPY_AAPTR(self, ptr); @@ -6495,7 +6500,7 @@ enum CPXFflags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(jump); + PARAM_STATE_NOT_NULL(jump); PARAM_CLASS(classname, AActor); PARAM_FIXED(distance); PARAM_INT_OPT(count) { count = 1; } @@ -6650,7 +6655,7 @@ enum CBF DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) { PARAM_ACTION_PROLOGUE; - PARAM_STATE(block) + PARAM_STATE_NOT_NULL(block); PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } diff --git a/src/zscript/vm.h b/src/zscript/vm.h index f92906fd2..9a5e82b75 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -951,4 +951,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type) #define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base) +// For use in the A_Jump* family of functions. If the function is passed a NULL state, +// it still needs to be able to jump (and destroy the actor), so map it to Actor's +// 'Null' state. +#define PARAM_STATE_NOT_NULL(x) PARAM_STATE(x); do { if (x == NULL) { x = RUNTIME_CLASS(AActor)->FindState(NAME_Null); } } while(0) + #endif