mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- 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.
This commit is contained in:
parent
c5a4221b58
commit
1799ae91c9
4 changed files with 60 additions and 34 deletions
|
@ -2699,10 +2699,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 ();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -3077,8 +3077,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())
|
||||||
{
|
{
|
||||||
|
@ -4249,9 +4249,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
|
||||||
|
@ -4274,13 +4274,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)
|
||||||
|
@ -4290,7 +4302,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))
|
||||||
{
|
{
|
||||||
|
@ -4301,37 +4313,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))
|
||||||
|
@ -4339,31 +4356,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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue