CheckSolidFooting
Jump to navigation
Jump to search
bool CheckSolidFooting (int tid, int flags)
Usage
Returns true if the actor with the specified tid is standing on the ground, an actor or a 3D floor. If tid is 0, the function uses the activator.
This custom function is a ZDoom 2.8-compatible ACS equivalent of A_CheckSolidFooting
Parameters
- tid: TID of the actor.
- flags: The following flags can be combined by using | between the constant names:
- CSF_SOLIDGROUND — Checks if the actor is standing on solid ground
- CSF_SOLIDACTORS — Checks if the actor is standing on a shootable actor
- CSF_ALL — Combination of CSF_SOLIDGROUND and CSF_SOLIDACTORS
Implementation
Define the following actors in DECORATE:
actor CheckSolidFooting { +PUFFONACTORS +BLOODLESSIMPACT +HITTARGET +PAINLESS Height 0 states { Spawn: TNT1 A 0 stop } } actor UnSetShootable : CustomInventory { states { Pickup: TNT1 A 0 A_ChangeFlag("SHOOTABLE", false) stop } } actor SetShootable : CustomInventory { states { Pickup: TNT1 A 0 A_ChangeFlag("SHOOTABLE", true) stop } }
If using standard ACC, define the following constants:
#define CSF_SOLIDGROUND 1 #define CSF_SOLIDACTORS 2 #define CSF_ALL (CSF_SOLIDGROUND|CSF_SOLIDACTORS)
If using GDCC-ACC, define the following enum:
enum ECheckSolidFootingFlags { CSF_SOLIDGROUND = 1, CSF_SOLIDACTORS = 2, CSF_ALL = CSF_SOLIDGROUND|CSF_SOLIDACTORS, }
If using standard ACC, then use the following version of the function:
function bool CheckSolidFooting(int tid, int flags) { int x = GetActorX(0); int y = GetActorY(0); int z = GetActorZ(0); int fz = GetActorFloorZ(0); int vz = GetActorVelZ(0); int radius = GetActorProperty(0, APROP_Radius); // we need to remember the activator if (!tid) { Thing_ChangeTID(tid, UniqueTID()); tid = ActivatorTID(); } // remember this for later bool shootable = CheckFlag(0, "SHOOTABLE"); // unset shootable on actor GiveInventory("UnSetShootable", 1); for (int px = -radius; px <= radius; px += radius) for (int py = -radius; py <= radius; py += radius) { int point = UniqueTID(); SpawnForced("CheckSolidFooting", x + px, y + py, z, point); int check = UniqueTID(); LineAttack(point, 0, 0.25, 0, "CheckSolidFooting", "", 9.0, FHF_NORANDOMPUFFZ|FHF_NOIMPACTDECAL, check); if (ThingCount(T_NONE, check) > 0) { if ((flags & CSF_SOLIDACTORS) && SetActivatorToTarget(check)) { int height = GetActorProperty(0, APROP_Height); int hitzpos = GetActorZ(0); int hitzvel = GetActorVelZ(0); // restore activator SetActivator(tid); // restore shootable flag if (shootable) GiveInventory("SetShootable", 1); if (z == hitzpos + height && vz == hitzvel) return true; else return false; } // restore shootable flag if (shootable) GiveInventory("SetShootable", 1); if (flags & CSF_SOLIDGROUND) return true; } } // restore shootable flag if (shootable) GiveInventory("SetShootable", 1); if (flags & CSF_SOLIDGROUND) return z <= fz; return false; }
If using GDCC-ACC with #pragma fixed on, use this version of the function:
function bool CheckSolidFooting(int tid, int flags) { fixed x = GetActorX(0); fixed y = GetActorY(0); fixed z = GetActorZ(0); fixed fz = GetActorFloorZ(0); fixed vz = GetActorVelZ(0); fixed radius = GetActorPropertyFixed(0, APROP_Radius); // we need to remember the activator if (!tid) { Thing_ChangeTID(tid, UniqueTID()); tid = ActivatorTID(); } // remember this for later bool shootable = CheckFlag(0, "SHOOTABLE"); // unset shootable on actor GiveInventory("UnSetShootable", 1); for (fixed px = -radius; px <= radius; px += radius) for (fixed py = -radius; py <= radius; py += radius) { int point = UniqueTID(); SpawnForced("CheckSolidFooting", x + px, y + py, z, point); int check = UniqueTID(); LineAttack(point, 0, 0.25, 0, "CheckSolidFooting", "", 9.0, FHF_NORANDOMPUFFZ|FHF_NOIMPACTDECAL, check); if (ThingCount(T_NONE, check) > 0) { if ((flags & CSF_SOLIDACTORS) && SetActivatorToTarget(check)) { fixed height = GetActorPropertyFixed(0, APROP_Height); fixed hitzpos = GetActorZ(0); fixed hitzvel = GetActorVelZ(0); // restore activator SetActivator(tid); // restore shootable flag if (shootable) GiveInventory("SetShootable", 1); if (z == hitzpos + height && vz == hitzvel) return true; else return false; } // restore shootable flag if (shootable) GiveInventory("SetShootable", 1); if (flags & CSF_SOLIDGROUND) return true; } } // restore shootable flag if (shootable) GiveInventory("SetShootable", 1); return flags & CSF_SOLIDGROUND ? z <= fz : false; }
Examples
The following example will force the player into the first frame of their Death state when on the ground, and the first frame of their Spawn state when in the air.
script "CheckSolidFootingExample" enter { for (;;) { if (CheckSolidFooting(0, CSF_ALL)) SetActorState(0, "Death"); else SetActorState(0, "Spawn"); Delay(1); } }