- 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.
This commit is contained in:
Christoph Oelckers 2017-01-20 12:39:51 +01:00
parent 02cfdbc29c
commit 314e49f791
4 changed files with 69 additions and 47 deletions

View file

@ -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);
}

View file

@ -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)

View file

@ -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<Actor> 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<Actor> 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<Actor> pufftype = "BulletPuff", double range = 0, int flags = 0, int ptr = AAPTR_TARGET, class<Actor> 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<Actor> 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<Actor> spawnclass = null, double spawnofs_z = 0, int spiraloffset = 270, int limit = 0, double veleffect = 3);
native bool A_SetInventory(class<Inventory> itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false);
native bool A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT);
native bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
action native bool A_SpawnItem(class<Actor> itemtype = "Unknown", double distance = 0, double zheight = 0, bool useammo = true, bool transfer_translation = false);
native bool A_SpawnItemEx(class<Actor> 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<Actor> itemtype = "Unknown", double distance = 0, double zheight = 0, bool useammo = true, bool transfer_translation = false);
native bool, Actor A_SpawnItemEx(class<Actor> 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<actor> missiletype, double missileheight);
action native bool A_ThrowGrenade(class<Actor> itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true);
action native bool, Actor A_ThrowGrenade(class<Actor> 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);

View file

@ -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<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "");
action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, double range = 0, class<Actor> missile = null, double Spawnheight = 32, double Spawnofs_xy = 0);
action native void A_FireProjectile(class<Actor> 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<Actor> 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<Actor> 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<Actor> spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
action native void A_WeaponReady(int flags = 0);