Merge pull request #310 from MajorCooke/telefogfix

- Allow teleport fogs to set the teleporting actors as their targets, so...
This commit is contained in:
coelckers 2015-04-30 09:02:10 +02:00
commit c2e91293d2
5 changed files with 72 additions and 38 deletions

View file

@ -105,7 +105,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
morphed->flags |= actor->flags & (MF_SHADOW|MF_NOGRAVITY); morphed->flags |= actor->flags & (MF_SHADOW|MF_NOGRAVITY);
morphed->flags2 |= actor->flags2 & MF2_FLY; morphed->flags2 |= actor->flags2 & MF2_FLY;
morphed->flags3 |= actor->flags3 & MF3_GHOST; morphed->flags3 |= actor->flags3 & MF3_GHOST;
Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE); AActor *eflash = Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE);
actor->player = NULL; actor->player = NULL;
actor->flags &= ~(MF_SOLID|MF_SHOOTABLE); actor->flags &= ~(MF_SOLID|MF_SHOOTABLE);
actor->flags |= MF_UNMORPHED; actor->flags |= MF_UNMORPHED;
@ -151,6 +151,8 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
p->camera = morphed; p->camera = morphed;
} }
morphed->ScoreIcon = actor->ScoreIcon; // [GRB] morphed->ScoreIcon = actor->ScoreIcon; // [GRB]
if (eflash)
eflash->target = p->mo;
return true; return true;
} }
@ -305,9 +307,11 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
} }
angle = mo->angle >> ANGLETOFINESHIFT; angle = mo->angle >> ANGLETOFINESHIFT;
AActor *eflash = NULL;
if (exit_flash != NULL) if (exit_flash != NULL)
{ {
Spawn(exit_flash, pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE); eflash = Spawn(exit_flash, pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE);
if (eflash) eflash->target = mo;
} }
mo->SetupWeaponSlots(); // Use original class's weapon slots. mo->SetupWeaponSlots(); // Use original class's weapon slots.
beastweap = player->ReadyWeapon; beastweap = player->ReadyWeapon;
@ -406,7 +410,9 @@ bool P_MorphMonster (AActor *actor, const PClass *spawntype, int duration, int s
actor->flags &= ~(MF_SOLID|MF_SHOOTABLE); actor->flags &= ~(MF_SOLID|MF_SHOOTABLE);
actor->flags |= MF_UNMORPHED; actor->flags |= MF_UNMORPHED;
actor->renderflags |= RF_INVISIBLE; actor->renderflags |= RF_INVISIBLE;
Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE); AActor *eflash = Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE);
if (eflash)
eflash->target = morphed;
return true; return true;
} }
@ -466,7 +472,9 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
DObject::StaticPointerSubstitution (beast, actor); DObject::StaticPointerSubstitution (beast, actor);
const PClass *exit_flash = beast->MorphExitFlash; const PClass *exit_flash = beast->MorphExitFlash;
beast->Destroy (); beast->Destroy ();
Spawn(exit_flash, beast->x, beast->y, beast->z + TELEFOGHEIGHT, ALLOW_REPLACE); AActor *eflash = Spawn(exit_flash, beast->x, beast->y, beast->z + TELEFOGHEIGHT, ALLOW_REPLACE);
if (eflash)
eflash->target = actor;
return true; return true;
} }

View file

@ -2750,10 +2750,10 @@ void P_NightmareRespawn (AActor *mobj)
mo->PrevZ = z; // Do not interpolate Z position if we changed it since spawning. 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? // 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 // 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 // remove the old monster
mobj->Destroy (); mobj->Destroy ();

View file

@ -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); mobj->angle = (angle != ANGLE_MAX ? angle : spot->angle);
if (fog) 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) if (mobj->flags & MF_SPECIAL)
mobj->flags |= MF_DROPPED; // Don't respawn 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) if (fog)
{ {
P_SpawnTeleportFog(source, x, y, z); P_SpawnTeleportFog(source, x, y, z, false, true);
P_SpawnTeleportFog(source, oldx, oldy, oldz, false); P_SpawnTeleportFog(source, oldx, oldy, oldz, true, true);
} }
source->PrevX = x; source->PrevX = x;
source->PrevY = y; source->PrevY = y;

View file

@ -3056,8 +3056,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
if (flags & RSF_FOG) if (flags & RSF_FOG)
{ {
P_SpawnTeleportFog(self, oldx, oldy, oldz, true); P_SpawnTeleportFog(self, oldx, oldy, oldz, true, true);
P_SpawnTeleportFog(self, self->x, self->y, self->z, false); P_SpawnTeleportFog(self, self->x, self->y, self->z, false, true);
} }
if (self->CountsAsKill()) if (self->CountsAsKill())
{ {
@ -4228,9 +4228,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray)
//=========================================================================== //===========================================================================
// //
// A_Teleport(optional state teleportstate, optional class targettype, // A_Teleport([state teleportstate, [class targettype,
// optional class fogtype, optional int flags, optional fixed mindist, // [class fogtype, [int flags, [fixed mindist,
// optional fixed maxdist) // [fixed maxdist]]]]]])
// //
// Attempts to teleport to a targettype at least mindist away and at most // 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 // maxdist away (0 means unlimited). If successful, spawn a fogtype at old
@ -4253,13 +4253,25 @@ enum T_Flags
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
{ {
ACTION_PARAM_START(6); ACTION_PARAM_START(7);
ACTION_PARAM_STATE(TeleportState, 0); ACTION_PARAM_STATE(TeleportState, 0);
ACTION_PARAM_CLASS(TargetType, 1); ACTION_PARAM_CLASS(TargetType, 1);
ACTION_PARAM_CLASS(FogType, 2); ACTION_PARAM_CLASS(FogType, 2);
ACTION_PARAM_INT(Flags, 3); ACTION_PARAM_INT(Flags, 3);
ACTION_PARAM_FIXED(MinDist, 4); ACTION_PARAM_FIXED(MinDist, 4);
ACTION_PARAM_FIXED(MaxDist, 5); 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. // Randomly choose not to teleport like A_Srcr2Decide.
if (Flags & TF_RANDOMDECIDE) if (Flags & TF_RANDOMDECIDE)
@ -4269,7 +4281,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
192, 120, 120, 120, 64, 64, 32, 16, 0 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)) if (chanceindex >= countof(chance))
{ {
@ -4280,37 +4292,42 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
} }
DSpotState *state = DSpotState::GetSpotState(); 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); AActor * spot = state->GetSpotWithMinMaxDistance(TargetType, ref->x, ref->y, MinDist, MaxDist);
if (spot == NULL) return; if (spot == NULL)
return;
fixed_t prevX = self->x; fixed_t prevX = ref->x;
fixed_t prevY = self->y; fixed_t prevY = ref->y;
fixed_t prevZ = self->z; fixed_t prevZ = ref->z;
fixed_t aboveFloor = spot->z - spot->floorz; fixed_t aboveFloor = spot->z - spot->floorz;
fixed_t finalz = spot->floorz + aboveFloor; fixed_t finalz = spot->floorz + aboveFloor;
if (spot->z + self->height > spot->ceilingz) if (spot->z + ref->height > spot->ceilingz)
finalz = spot->ceilingz - self->height; finalz = spot->ceilingz - ref->height;
else if (spot->z < spot->floorz) else if (spot->z < spot->floorz)
finalz = spot->floorz; finalz = spot->floorz;
//Take precedence and cooperate with telefragging first. //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. //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; teleResult = true;
} }
AActor *fog1 = NULL, *fog2 = NULL;
if (teleResult) if (teleResult)
{ {
//If a fog type is defined in the parameter, or the user wants to use the actor's predefined fogs, //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. //and if there's no desire to be fogless, spawn a fog based upon settings.
if (FogType || (Flags & TF_USEACTORFOG)) if (FogType || (Flags & TF_USEACTORFOG))
@ -4318,31 +4335,40 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
if (!(Flags & TF_NOSRCFOG)) if (!(Flags & TF_NOSRCFOG))
{ {
if (Flags & TF_USEACTORFOG) if (Flags & TF_USEACTORFOG)
P_SpawnTeleportFog(self, prevX, prevY, prevZ, true); P_SpawnTeleportFog(ref, prevX, prevY, prevZ, true, true);
else 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_NODESTFOG))
{ {
if (Flags & TF_USEACTORFOG) 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 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) if (Flags & TF_USESPOTZ)
self->z = spot->z; ref->z = spot->z;
else else
self->z = self->floorz; ref->z = ref->floorz;
if (!(Flags & TF_KEEPANGLE)) if (!(Flags & TF_KEEPANGLE))
self->angle = spot->angle; ref->angle = spot->angle;
if (!(Flags & TF_KEEPVELOCITY)) 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! ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (TeleportState == NULL) if (TeleportState == NULL)

View file

@ -248,7 +248,7 @@ ACTOR Actor native //: Thinker
action native A_CheckCeiling(state label); action native A_CheckCeiling(state label);
action native A_PlayerSkinCheck(state label); action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight); action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0); action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> 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_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<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); action native A_ThrowGrenade(class<Actor> 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); action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);