From 314e49f791c4837b60a12ce0ef4f4208ad272bfa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 20 Jan 2017 12:39:51 +0100 Subject: [PATCH] - let A_SpawnProjectile, A_FireProjectile, A_SpawnItem(Ex) and A_ThrowGrenade return the spawned actors to the calling code. - fixed the return type checks in CallStateChain. These made some bogus assumptions about what return prototypes to support and would have skipped any multi-return function whose first argument was actually usable. --- src/p_actionfunctions.cpp | 105 +++++++++++------- src/scripting/vm/vm.h | 1 - wadsrc/static/zscript/actor.txt | 8 +- .../zscript/inventory/stateprovider.txt | 2 +- 4 files changed, 69 insertions(+), 47 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 65f7be9a1..8b5916207 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -160,27 +160,23 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state) // we don't care about), we pretend they return true, // thanks to the values set just above. - if (proto->ReturnTypes.Size() == 1) - { - if (proto->ReturnTypes[0] == TypeState) - { // Function returns a state - wantret = &ret[0]; - retval = false; // this is a jump function which never affects the success state. - } - else if (proto->ReturnTypes[0] == TypeSInt32 || proto->ReturnTypes[0] == TypeBool) - { // Function returns an int or bool - wantret = &ret[1]; - } - numret = 1; + if (proto->ReturnTypes.Size() >= 2 && + proto->ReturnTypes[0] == TypeState && + (proto->ReturnTypes[1] == TypeSInt32 || proto->ReturnTypes[0] == TypeUInt32 || proto->ReturnTypes[1] == TypeBool)) + { // Function returns a state and an int or bool + wantret = &ret[0]; + numret = 2; } - else if (proto->ReturnTypes.Size() == 2) - { - if (proto->ReturnTypes[0] == TypeState && - (proto->ReturnTypes[1] == TypeSInt32 || proto->ReturnTypes[1] == TypeBool)) - { // Function returns a state and an int or bool - wantret = &ret[0]; - numret = 2; - } + else if (proto->ReturnTypes.Size() == 1 && proto->ReturnTypes[0] == TypeState) + { // Function returns a state + wantret = &ret[0]; + retval = false; // this is a jump function which never affects the success state. + } + else if (proto->ReturnTypes.Size() >= 1 && + (proto->ReturnTypes[0] == TypeSInt32 || proto->ReturnTypes[0] == TypeUInt32 || proto->ReturnTypes[0] == TypeBool)) + { // Function returns an int or bool + wantret = &ret[1]; + numret = 1; } try { @@ -1464,7 +1460,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnProjectile) int aimmode = flags & CMF_AIMMODE; AActor * targ; - AActor * missile; + AActor * missile = nullptr; if (ref != NULL || aimmode == 2) { @@ -1576,7 +1572,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnProjectile) if (self->SeeState != NULL && (self->health > 0 || !(self->flags3 & MF3_ISMONSTER))) self->SetState(self->SeeState); } - return 0; + ACTION_RETURN_OBJECT(missile); } //========================================================================== @@ -1990,7 +1986,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_FireProjectile) PARAM_ANGLE_DEF (pitch); if (!self->player) - return 0; + ACTION_RETURN_OBJECT(nullptr); player_t *player = self->player; AWeapon *weapon = player->ReadyWeapon; @@ -2000,7 +1996,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_FireProjectile) if (useammo && ACTION_CALL_FROM_PSPRITE() && weapon) { if (!weapon->DepleteAmmo(weapon->bAltFire, true)) - return 0; // out of ammo + ACTION_RETURN_OBJECT(nullptr); // out of ammo } if (ti) @@ -2032,8 +2028,9 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_FireProjectile) misl->VelFromAngle(misl->VelXYToSpeed()); } } + ACTION_RETURN_OBJECT(misl); } - return 0; + ACTION_RETURN_OBJECT(nullptr); } @@ -2861,17 +2858,21 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem) PARAM_FLOAT_DEF (distance) PARAM_FLOAT_DEF (zheight) PARAM_BOOL_DEF (useammo) - PARAM_BOOL_DEF (transfer_translation) + PARAM_BOOL_DEF (transfer_translation); + + if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT); if (missile == NULL) { - ACTION_RETURN_BOOL(false); + if (numret > 0) ret[0].SetInt(false); + return MIN(numret, 2); } // Don't spawn monsters if this actor has been massacred if (self->DamageType == NAME_Massacre && (GetDefaultByType(missile)->flags3 & MF3_ISMONSTER)) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } if (ACTION_CALL_FROM_PSPRITE()) @@ -2881,18 +2882,24 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem) if (weapon == NULL) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } if (useammo && !weapon->DepleteAmmo(weapon->bAltFire)) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } } AActor *mo = Spawn( missile, self->Vec3Angle(distance, self->Angles.Yaw, -self->Floorclip + self->GetBobOffset() + zheight), ALLOW_REPLACE); int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0); - ACTION_RETURN_BOOL(InitSpawnedItem(self, mo, flags)); // for an inventory item's use state + bool res = InitSpawnedItem(self, mo, flags); // for an inventory item's use state + if (numret > 0) ret[0].SetInt(res); + if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT); + return MIN(numret, 2); + } //=========================================================================== @@ -2917,18 +2924,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx) PARAM_INT_DEF (chance) PARAM_INT_DEF (tid) + if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT); + if (missile == NULL) { - ACTION_RETURN_BOOL(false); + if (numret > 0) ret[0].SetInt(false); + return MIN(numret, 2); } if (chance > 0 && pr_spawnitemex() < chance) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } // Don't spawn monsters if this actor has been massacred if (self->DamageType == NAME_Massacre && (GetDefaultByType(missile)->flags3 & MF3_ISMONSTER)) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } DVector2 pos; @@ -2976,7 +2988,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx) } mo->Angles.Yaw = angle; } - ACTION_RETURN_BOOL(res); // for an inventory item's use state + if (numret > 0) ret[0].SetInt(res); + if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT); + return MIN(numret, 2); } //=========================================================================== @@ -2995,9 +3009,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) PARAM_FLOAT_DEF (zvel) PARAM_BOOL_DEF (useammo) + if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT); + if (missile == NULL) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(false); + return MIN(numret, 2); } if (ACTION_CALL_FROM_PSPRITE()) { @@ -3006,11 +3023,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) if (weapon == NULL) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } if (useammo && !weapon->DepleteAmmo(weapon->bAltFire)) { - ACTION_RETURN_BOOL(true); + if (numret > 0) ret[0].SetInt(true); + return MIN(numret, 2); } } @@ -3049,13 +3068,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) bo->Vel.Z = xy_velz + z_velz; bo->target = self; - P_CheckMissileSpawn (bo, self->radius); + if (!P_CheckMissileSpawn(bo, self->radius)) bo = nullptr; + + if (numret > 0) ret[0].SetInt(true); + if (numret > 1) ret[1].SetPointer(bo, ATAG_OBJECT); + return MIN(numret, 2); } else { - ACTION_RETURN_BOOL(false); + if (numret > 0) ret[0].SetInt(false); + return MIN(numret, 2); } - ACTION_RETURN_BOOL(true); } diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index a9fdf3abe..060fa0a76 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -1148,7 +1148,6 @@ struct AFuncDesc class AActor; - #define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0) #define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_GENERIC); return 1; } return 0; } while(0) #define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 7df019fc3..24afe68e9 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -756,14 +756,14 @@ class Actor : Thinker native deprecated native void A_StopSoundEx(name slot); native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); native action state A_Jump(int chance, statelabel label, ...); - native void A_SpawnProjectile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); + native Actor A_SpawnProjectile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); native void A_CustomBulletAttack(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", double range = 0, int flags = 0, int ptr = AAPTR_TARGET, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = null, double spawnofs_z = 0, int spiraloffset = 270, int limit = 0, double veleffect = 3); native bool A_SetInventory(class itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false); native bool A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); native bool A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); - action native bool A_SpawnItem(class itemtype = "Unknown", double distance = 0, double zheight = 0, bool useammo = true, bool transfer_translation = false); - native bool A_SpawnItemEx(class itemtype, double xofs = 0, double yofs = 0, double zofs = 0, double xvel = 0, double yvel = 0, double zvel = 0, double angle = 0, int flags = 0, int failchance = 0, int tid=0); + action native bool, Actor A_SpawnItem(class itemtype = "Unknown", double distance = 0, double zheight = 0, bool useammo = true, bool transfer_translation = false); + native bool, Actor A_SpawnItemEx(class itemtype, double xofs = 0, double yofs = 0, double zofs = 0, double xvel = 0, double yvel = 0, double zvel = 0, double angle = 0, int flags = 0, int failchance = 0, int tid=0); native void A_Print(string whattoprint, double time = 0, name fontname = "none"); native void A_PrintBold(string whattoprint, double time = 0, name fontname = "none"); native void A_Log(string whattoprint, bool local = false); @@ -785,7 +785,7 @@ class Actor : Thinker native native void A_RaiseChildren(bool copy = 0); native void A_RaiseSiblings(bool copy = 0); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, double missileheight); - action native bool A_ThrowGrenade(class itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true); + action native bool, Actor A_ThrowGrenade(class itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, double xdist, double ydist); diff --git a/wadsrc/static/zscript/inventory/stateprovider.txt b/wadsrc/static/zscript/inventory/stateprovider.txt index 6f52f6696..dc261eaa9 100644 --- a/wadsrc/static/zscript/inventory/stateprovider.txt +++ b/wadsrc/static/zscript/inventory/stateprovider.txt @@ -4,7 +4,7 @@ class StateProvider : Inventory native action native state A_JumpIfNoAmmo(statelabel label); action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", int flags = 1, double range = 0, class missile = null, double Spawnheight = 32, double Spawnofs_xy = 0); - action native void A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0); + action native Actor A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0); action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); action native void A_WeaponReady(int flags = 0);