From 1799ae91c92f24b03036c29ee7570f4679902a5f Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 7 Apr 2015 11:14:02 -0500 Subject: [PATCH] - Allow teleport fogs to set the teleporting actors as their targets, so modders can create interactions between the two. - Fixed: P_MoveThing had source and destination fog spawning backwards. - Fixed a case where the NOTELEPORT flag would be ignored on A_Teleport. - Added pointer selection to A_Teleport. Defaults to AAPTR_DEFAULT (calling actor). State jumps will only be done by the calling actor. --- src/p_mobj.cpp | 4 +- src/p_things.cpp | 6 +-- src/thingdef/thingdef_codeptr.cpp | 82 ++++++++++++++++++++----------- wadsrc/static/actors/actor.txt | 2 +- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2571413c8..bbf6e16bf 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2699,10 +2699,10 @@ void P_NightmareRespawn (AActor *mobj) mo->PrevZ = z; // Do not interpolate Z position if we changed it since spawning. // spawn a teleport fog at old spot because of removal of the body? - P_SpawnTeleportFog(mobj, mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, true); + P_SpawnTeleportFog(mobj, mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, true, true); // spawn a teleport fog at the new spot - P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false); + P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false, true); // remove the old monster mobj->Destroy (); diff --git a/src/p_things.cpp b/src/p_things.cpp index faf1091d5..982a57f16 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -94,7 +94,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, mobj->angle = (angle != ANGLE_MAX ? angle : spot->angle); if (fog) { - P_SpawnTeleportFog(mobj, spot->x, spot->y, spot->z + TELEFOGHEIGHT, false); + P_SpawnTeleportFog(mobj, spot->x, spot->y, spot->z + TELEFOGHEIGHT, false, true); } if (mobj->flags & MF_SPECIAL) mobj->flags |= MF_DROPPED; // Don't respawn @@ -132,8 +132,8 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog) { if (fog) { - P_SpawnTeleportFog(source, x, y, z); - P_SpawnTeleportFog(source, oldx, oldy, oldz, false); + P_SpawnTeleportFog(source, x, y, z, false, true); + P_SpawnTeleportFog(source, oldx, oldy, oldz, true, true); } source->PrevX = x; source->PrevY = y; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index cb59f8a1f..3d218083e 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3077,8 +3077,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) if (flags & RSF_FOG) { - P_SpawnTeleportFog(self, oldx, oldy, oldz, true); - P_SpawnTeleportFog(self, self->x, self->y, self->z, false); + P_SpawnTeleportFog(self, oldx, oldy, oldz, true, true); + P_SpawnTeleportFog(self, self->x, self->y, self->z, false, true); } if (self->CountsAsKill()) { @@ -4249,9 +4249,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray) //=========================================================================== // -// A_Teleport(optional state teleportstate, optional class targettype, -// optional class fogtype, optional int flags, optional fixed mindist, -// optional fixed maxdist) +// A_Teleport([state teleportstate, [class targettype, +// [class fogtype, [int flags, [fixed mindist, +// [fixed maxdist]]]]]]) // // Attempts to teleport to a targettype at least mindist away and at most // maxdist away (0 means unlimited). If successful, spawn a fogtype at old @@ -4274,13 +4274,25 @@ enum T_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) { - ACTION_PARAM_START(6); + ACTION_PARAM_START(7); ACTION_PARAM_STATE(TeleportState, 0); ACTION_PARAM_CLASS(TargetType, 1); ACTION_PARAM_CLASS(FogType, 2); ACTION_PARAM_INT(Flags, 3); ACTION_PARAM_FIXED(MinDist, 4); ACTION_PARAM_FIXED(MaxDist, 5); + ACTION_PARAM_INT(ptr, 6); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + + if (ref->flags2 & MF2_NOTELEPORT) + return; // Randomly choose not to teleport like A_Srcr2Decide. if (Flags & TF_RANDOMDECIDE) @@ -4290,7 +4302,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) 192, 120, 120, 120, 64, 64, 32, 16, 0 }; - unsigned int chanceindex = self->health / ((self->SpawnHealth()/8 == 0) ? 1 : self->SpawnHealth()/8); + unsigned int chanceindex = ref->health / ((ref->SpawnHealth()/8 == 0) ? 1 : ref->SpawnHealth()/8); if (chanceindex >= countof(chance)) { @@ -4301,37 +4313,42 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) } DSpotState *state = DSpotState::GetSpotState(); - if (state == NULL) return; + if (state == NULL) + return; - if (!TargetType) TargetType = PClass::FindClass("BossSpot"); + if (!TargetType) + TargetType = PClass::FindClass("BossSpot"); - AActor * spot = state->GetSpotWithMinMaxDistance(TargetType, self->x, self->y, MinDist, MaxDist); - if (spot == NULL) return; + AActor * spot = state->GetSpotWithMinMaxDistance(TargetType, ref->x, ref->y, MinDist, MaxDist); + if (spot == NULL) + return; - fixed_t prevX = self->x; - fixed_t prevY = self->y; - fixed_t prevZ = self->z; + fixed_t prevX = ref->x; + fixed_t prevY = ref->y; + fixed_t prevZ = ref->z; fixed_t aboveFloor = spot->z - spot->floorz; fixed_t finalz = spot->floorz + aboveFloor; - if (spot->z + self->height > spot->ceilingz) - finalz = spot->ceilingz - self->height; + if (spot->z + ref->height > spot->ceilingz) + finalz = spot->ceilingz - ref->height; else if (spot->z < spot->floorz) finalz = spot->floorz; //Take precedence and cooperate with telefragging first. - bool teleResult = P_TeleportMove(self, spot->x, spot->y, finalz, Flags & TF_TELEFRAG); + bool teleResult = P_TeleportMove(ref, spot->x, spot->y, finalz, Flags & TF_TELEFRAG); - if (Flags & TF_FORCED) + if (!teleResult && (Flags & TF_FORCED)) { //If for some reason the original move didn't work, regardless of telefrag, force it to move. - self->SetOrigin(spot->x, spot->y, finalz); + ref->SetOrigin(spot->x, spot->y, finalz); teleResult = true; } + AActor *fog1 = NULL, *fog2 = NULL; if (teleResult) { + //If a fog type is defined in the parameter, or the user wants to use the actor's predefined fogs, //and if there's no desire to be fogless, spawn a fog based upon settings. if (FogType || (Flags & TF_USEACTORFOG)) @@ -4339,31 +4356,40 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) if (!(Flags & TF_NOSRCFOG)) { if (Flags & TF_USEACTORFOG) - P_SpawnTeleportFog(self, prevX, prevY, prevZ, true); + P_SpawnTeleportFog(ref, prevX, prevY, prevZ, true, true); else - Spawn(FogType, prevX, prevY, prevZ, ALLOW_REPLACE); + { + fog1 = Spawn(FogType, prevX, prevY, prevZ, ALLOW_REPLACE); + if (fog1 != NULL) + fog1->target = ref; + } } if (!(Flags & TF_NODESTFOG)) { if (Flags & TF_USEACTORFOG) - P_SpawnTeleportFog(self, self->x, self->y, self->z, false); + P_SpawnTeleportFog(ref, ref->x, ref->y, ref->z, false, true); else - Spawn(FogType, self->x, self->y, self->z, ALLOW_REPLACE); + { + fog2 = Spawn(FogType, prevX, prevY, prevZ, ALLOW_REPLACE); + if (fog2 != NULL) + fog2->target = ref; + } } + } if (Flags & TF_USESPOTZ) - self->z = spot->z; + ref->z = spot->z; else - self->z = self->floorz; + ref->z = ref->floorz; if (!(Flags & TF_KEEPANGLE)) - self->angle = spot->angle; + ref->angle = spot->angle; if (!(Flags & TF_KEEPVELOCITY)) - self->velx = self->vely = self->velz = 0; + ref->velx = ref->vely = ref->velz = 0; - if (!(Flags & TF_NOJUMP)) + 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 (TeleportState == NULL) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 7d8fad5bf..0bd9ed31a 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -248,7 +248,7 @@ ACTOR Actor native //: Thinker action native A_CheckCeiling(state label); action native 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); + 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 = ""); action native 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);