Merge branch 'master' into scripting

Conflicts:
	src/actor.h
	src/p_local.h
	src/thingdef/thingdef_codeptr.cpp
This commit is contained in:
Christoph Oelckers 2016-01-19 20:17:34 +01:00
commit b73e1e65f5
5 changed files with 164 additions and 146 deletions

View file

@ -1264,6 +1264,21 @@ public:
y = yy; y = yy;
z = zz; z = zz;
} }
void SetXY(const fixedvec2 &npos)
{
x = npos.x;
y = npos.y;
}
void SetXYZ(const fixedvec3 &npos)
{
x = npos.x;
y = npos.y;
z = npos.z;
}
void SetMovement(fixed_t x, fixed_t y, fixed_t z)
{
// not yet implemented
}
}; };

View file

@ -139,6 +139,10 @@ inline AActor *P_SpawnPuff(AActor *source, PClassActor *pufftype, const fixedvec
return P_SpawnPuff(source, pufftype, pos.x, pos.y, pos.z, dir, updown, flags, vict); return P_SpawnPuff(source, pufftype, pos.x, pos.y, pos.z, dir, updown, flags, vict);
} }
void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator); void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator);
inline void P_SpawnBlood(const fixedvec3 &pos, angle_t dir, int damage, AActor *originator)
{
P_SpawnBlood(pos.x, pos.y, pos.z, dir, damage, originator);
}
void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator); void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator); void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
void P_RipperBlood (AActor *mo, AActor *bleeder); void P_RipperBlood (AActor *mo, AActor *bleeder);

View file

@ -903,6 +903,10 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag);
// P_TELEPT // P_TELEPT
// //
void P_SpawnTeleportFog(AActor *mobj, fixed_t x, fixed_t y, fixed_t z, bool beforeTele = true, bool setTarget = false); //Spawns teleport fog. Pass the actor to pluck TeleFogFromType and TeleFogToType. 'from' determines if this is the fog to spawn at the old position (true) or new (false). void P_SpawnTeleportFog(AActor *mobj, fixed_t x, fixed_t y, fixed_t z, bool beforeTele = true, bool setTarget = false); //Spawns teleport fog. Pass the actor to pluck TeleFogFromType and TeleFogToType. 'from' determines if this is the fog to spawn at the old position (true) or new (false).
inline void P_SpawnTeleportFog(AActor *mobj, const fixedvec3 &pos, bool beforeTele = true, bool setTarget = false)
{
P_SpawnTeleportFog(mobj, pos.x, pos.y, pos.z, beforeTele, setTarget);
}
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false); bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false);
bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool fog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false); bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool fog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false);
bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse); bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse);

View file

@ -2640,10 +2640,7 @@ CCMD (loopsound)
} }
else else
{ {
AActor *icon = Spawn("SpeakerIcon", players[consoleplayer].mo->x, AActor *icon = Spawn("SpeakerIcon", players[consoleplayer].mo->PosPlusZ(32*FRACUNIT), ALLOW_REPLACE);
players[consoleplayer].mo->y,
players[consoleplayer].mo->z + 32*FRACUNIT,
ALLOW_REPLACE);
if (icon != NULL) if (icon != NULL)
{ {
S_Sound(icon, CHAN_BODY | CHAN_LOOP, id, 1.f, ATTN_IDLE); S_Sound(icon, CHAN_BODY | CHAN_LOOP, id, 1.f, ATTN_IDLE);

View file

@ -422,9 +422,9 @@ static void DoAttack (AActor *self, bool domelee, bool domissile,
else if (domissile && MissileType != NULL) else if (domissile && MissileType != NULL)
{ {
// This seemingly senseless code is needed for proper aiming. // This seemingly senseless code is needed for proper aiming.
self->z += MissileHeight + self->GetBobOffset() - 32*FRACUNIT; self->AddZ(MissileHeight + self->GetBobOffset() - 32*FRACUNIT);
AActor *missile = P_SpawnMissileXYZ (self->x, self->y, self->z + 32*FRACUNIT, self, self->target, MissileType, false); AActor *missile = P_SpawnMissileXYZ (self->PosPlusZ(32*FRACUNIT), self, self->target, MissileType, false);
self->z -= MissileHeight + self->GetBobOffset() - 32*FRACUNIT; self->AddZ(-(MissileHeight + self->GetBobOffset() - 32*FRACUNIT));
if (missile) if (missile)
{ {
@ -798,8 +798,8 @@ static int DoJumpIfCloser(AActor *target, VM_ARGS)
return numret; return numret;
if (self->AproxDistance(target) < dist && if (self->AproxDistance(target) < dist &&
(noz || (noz ||
((self->z > target->z && self->z - (target->z + target->height) < dist) || ((self->Z() > target->Z() && self->Z() - target->Top() < dist) ||
(self->z <= target->z && target->z - (self->z + self->height) < dist)))) (self->Z() <= target->Z() && target->Z() - self->Top() < dist))))
{ {
ACTION_JUMP(jump); ACTION_JUMP(jump);
} }
@ -1079,30 +1079,25 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
fixed_t y = spawnofs_xy * finesine[ang]; fixed_t y = spawnofs_xy * finesine[ang];
fixed_t z = spawnheight + self->GetBobOffset() - 32*FRACUNIT + (self->player? self->player->crouchoffset : 0); fixed_t z = spawnheight + self->GetBobOffset() - 32*FRACUNIT + (self->player? self->player->crouchoffset : 0);
fixedvec3 pos = self->Pos();
switch (aimmode) switch (aimmode)
{ {
case 0: case 0:
default: default:
// same adjustment as above (in all 3 directions this time) - for better aiming! // same adjustment as above (in all 3 directions this time) - for better aiming!
self->x += x; self->SetXYZ(self->Vec3Offset(x, y, z));
self->y += y; missile = P_SpawnMissileXYZ(self->PosPlusZ(32*FRACUNIT), self, ref, ti, false);
self->z += z; self->SetXYZ(pos);
missile = P_SpawnMissileXYZ(self->x, self->y, self->z + 32*FRACUNIT, self, ref, ti, false);
self->x -= x;
self->y -= y;
self->z -= z;
break; break;
case 1: case 1:
missile = P_SpawnMissileXYZ(self->x+x, self->y+y, self->z + self->GetBobOffset() + spawnheight, self, ref, ti, false); missile = P_SpawnMissileXYZ(self->Vec3Offset(x, y, self->GetBobOffset() + spawnheight), self, ref, ti, false);
break; break;
case 2: case 2:
self->x += x; self->SetXYZ(self->Vec3Offset(x, y, self->Z()));
self->y += y; missile = P_SpawnMissileAngleZSpeed(self, self->Z() + self->GetBobOffset() + spawnheight, ti, self->angle, 0, GetDefaultByType(ti)->Speed, self, false);
missile = P_SpawnMissileAngleZSpeed(self, self->z + self->GetBobOffset() + spawnheight, ti, self->angle, 0, GetDefaultByType(ti)->Speed, self, false); self->SetXYZ(pos);
self->x -= x;
self->y -= y;
flags |= CMF_ABSOLUTEPITCH; flags |= CMF_ABSOLUTEPITCH;
@ -1336,9 +1331,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack)
else if (ti) else if (ti)
{ {
// This seemingly senseless code is needed for proper aiming. // This seemingly senseless code is needed for proper aiming.
self->z += spawnheight + self->GetBobOffset() - 32*FRACUNIT; self->AddZ(spawnheight + self->GetBobOffset() - 32*FRACUNIT);
AActor *missile = P_SpawnMissileXYZ (self->x, self->y, self->z + 32*FRACUNIT, self, self->target, ti, false); AActor *missile = P_SpawnMissileXYZ (self->PosPlusZ(32*FRACUNIT), self, self->target, ti, false);
self->z -= spawnheight + self->GetBobOffset() - 32*FRACUNIT; self->AddZ(-(spawnheight + self->GetBobOffset() - 32*FRACUNIT));
if (missile) if (missile)
{ {
@ -1766,8 +1761,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
AActor *linetarget; AActor *linetarget;
fixed_t saved_x = self->x; fixedvec3 savedpos = self->Pos();
fixed_t saved_y = self->y;
angle_t saved_angle = self->angle; angle_t saved_angle = self->angle;
fixed_t saved_pitch = self->pitch; fixed_t saved_pitch = self->pitch;
@ -1792,9 +1786,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
if (linetarget == NULL && aim) if (linetarget == NULL && aim)
{ {
// We probably won't hit the target, but aim at it anyway so we don't look stupid. // We probably won't hit the target, but aim at it anyway so we don't look stupid.
TVector2<double> xydiff(self->target->x - self->x, self->target->y - self->y); fixedvec2 pos = self->Vec2To(self->target);
double zdiff = (self->target->z + (self->target->height>>1)) - TVector2<double> xydiff(pos.x, pos.y);
(self->z + (self->height>>1) - self->floorclip); double zdiff = (self->target->Z() + (self->target->height>>1)) -
(self->Z() + (self->height>>1) - self->floorclip);
self->pitch = int(atan2(zdiff, xydiff.Length()) * ANGLE_180 / -M_PI); self->pitch = int(atan2(zdiff, xydiff.Length()) * ANGLE_180 / -M_PI);
} }
// Let the aim trail behind the player // Let the aim trail behind the player
@ -1806,8 +1801,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
{ {
// Tricky: We must offset to the angle of the current position // Tricky: We must offset to the angle of the current position
// but then change the angle again to ensure proper aim. // but then change the angle again to ensure proper aim.
self->x += spawnofs_xy * finecosine[self->angle]; self->SetXY(self->Vec2Offset(
self->y += spawnofs_xy * finesine[self->angle]; spawnofs_xy * finecosine[self->angle],
spawnofs_xy * finesine[self->angle]));
spawnofs_xy = 0; spawnofs_xy = 0;
self->angle = self->AngleTo(self->target,- self->target->velx * 3, -self->target->vely * 3); self->angle = self->AngleTo(self->target,- self->target->velx * 3, -self->target->vely * 3);
} }
@ -1838,8 +1834,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angleoffset, slopeoffset, range, duration, sparsity, driftspeed, spawnclass,SpiralOffset); P_RailAttack (self, damage, spawnofs_xy, spawnofs_z, color1, color2, maxdiff, flags, pufftype, angleoffset, slopeoffset, range, duration, sparsity, driftspeed, spawnclass,SpiralOffset);
self->x = saved_x; self->SetXYZ(savedpos);
self->y = saved_y;
self->angle = saved_angle; self->angle = saved_angle;
self->pitch = saved_pitch; self->pitch = saved_pitch;
return 0; return 0;
@ -2147,7 +2142,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
} }
if (flags & SIXF_TELEFRAG) if (flags & SIXF_TELEFRAG)
{ {
P_TeleportMove(mo, mo->x, mo->y, mo->z, true); P_TeleportMove(mo, mo->Pos(), true);
// This is needed to ensure consistent behavior. // This is needed to ensure consistent behavior.
// Otherwise it will only spawn if nothing gets telefragged // Otherwise it will only spawn if nothing gets telefragged
flags |= SIXF_NOCHECKPOSITION; flags |= SIXF_NOCHECKPOSITION;
@ -2322,10 +2317,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
return numret; return numret;
} }
AActor *mo = Spawn(missile, AActor *mo = Spawn( missile, self->Vec3Angle(distance, self->angle, -self->floorclip + self->GetBobOffset() + zheight), ALLOW_REPLACE);
self->x + FixedMul(distance, finecosine[self->angle>>ANGLETOFINESHIFT]),
self->y + FixedMul(distance, finesine[self->angle>>ANGLETOFINESHIFT]),
self->z - self->floorclip + self->GetBobOffset() + zheight, ALLOW_REPLACE);
int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0); int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0);
bool res = InitSpawnedItem(self, mo, flags); bool res = InitSpawnedItem(self, mo, flags);
@ -2369,7 +2361,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
if (self->DamageType == NAME_Massacre && (GetDefaultByType(missile)->flags3 & MF3_ISMONSTER)) if (self->DamageType == NAME_Massacre && (GetDefaultByType(missile)->flags3 & MF3_ISMONSTER))
return numret; return numret;
fixed_t x, y; fixedvec2 pos;
if (!(flags & SIXF_ABSOLUTEANGLE)) if (!(flags & SIXF_ABSOLUTEANGLE))
{ {
@ -2380,15 +2372,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
if (flags & SIXF_ABSOLUTEPOSITION) if (flags & SIXF_ABSOLUTEPOSITION)
{ {
x = self->x + xofs; pos = self->Vec2Offset(xofs, yofs);
y = self->y + yofs;
} }
else else
{ {
// in relative mode negative y values mean 'left' and positive ones mean 'right' // in relative mode negative y values mean 'left' and positive ones mean 'right'
// This is the inverse orientation of the absolute mode! // This is the inverse orientation of the absolute mode!
x = self->x + FixedMul(xofs, finecosine[ang]) + FixedMul(yofs, finesine[ang]); pos = self->Vec2Offset(
y = self->y + FixedMul(xofs, finesine[ang]) - FixedMul(yofs, finecosine[ang]); FixedMul(xofs, finecosine[ang]) + FixedMul(yofs, finesine[ang]),
FixedMul(xofs, finesine[ang]) - FixedMul(yofs, finecosine[ang]));
} }
if (!(flags & SIXF_ABSOLUTEVELOCITY)) if (!(flags & SIXF_ABSOLUTEVELOCITY))
@ -2399,7 +2391,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
xvel = newxvel; xvel = newxvel;
} }
AActor *mo = Spawn(missile, x, y, self->z - self->floorclip + self->GetBobOffset() + zofs, ALLOW_REPLACE); AActor *mo = Spawn(missile, pos.x, pos.y, self->Z() - self->floorclip + self->GetBobOffset() + zofs, ALLOW_REPLACE);
bool res = InitSpawnedItem(self, mo, flags); bool res = InitSpawnedItem(self, mo, flags);
ACTION_SET_RESULT(res); // for an inventory item's use state ACTION_SET_RESULT(res); // for an inventory item's use state
if (res) if (res)
@ -2460,8 +2452,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
AActor *bo; AActor *bo;
bo = Spawn(missile, self->x, self->y, bo = Spawn(missile,
self->z - self->floorclip + self->GetBobOffset() + zheight + 35*FRACUNIT + (self->player? self->player->crouchoffset : 0), self->PosPlusZ(-self->floorclip + self->GetBobOffset() + zheight + 35*FRACUNIT + (self->player? self->player->crouchoffset : 0)),
ALLOW_REPLACE); ALLOW_REPLACE);
if (bo) if (bo)
{ {
@ -2862,9 +2854,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris)
for (i = 0; i < GetDefaultByType(debris)->health; i++) for (i = 0; i < GetDefaultByType(debris)->health; i++)
{ {
mo = Spawn(debris, self->x+((pr_spawndebris()-128)<<12), mo = Spawn(debris, self->Vec3Offset(
self->y + ((pr_spawndebris()-128)<<12), ((pr_spawndebris()-128)<<12),
self->z + (pr_spawndebris()*self->height/256+self->GetBobOffset()), ALLOW_REPLACE); ((pr_spawndebris()-128)<<12),
(pr_spawndebris()*self->height/256+self->GetBobOffset())), ALLOW_REPLACE);
if (mo) if (mo)
{ {
if (transfer_translation) if (transfer_translation)
@ -2933,23 +2926,22 @@ static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range, bool
return false; return false;
} }
// Check distance first, since it's cheaper than checking sight. // Check distance first, since it's cheaper than checking sight.
double dx = self->x - camera->x; fixedvec2 pos = camera->Vec2To(self);
double dy = self->y - camera->y; fixed_t dz;
double dz; fixed_t eyez = (camera->Top() - (camera->height>>2)); // same eye height as P_CheckSight
fixed_t eyez = (camera->z + camera->height - (camera->height>>2)); // same eye height as P_CheckSight if (eyez > self->Top())
if (eyez > self->z + self->height)
{ {
dz = self->z + self->height - eyez; dz = self->Top() - eyez;
} }
else if (eyez < self->z) else if (eyez < self->Z())
{ {
dz = self->z - eyez; dz = self->Z() - eyez;
} }
else else
{ {
dz = 0; dz = 0;
} }
double distance = (dx * dx) + (dy * dy) + (twodi == 0? (dz * dz) : 0); double distance = ((double)pos.x * pos.x) + ((double)pos.y * pos.y) + (twodi == 0? ((double)dz * dz) : 0);
if (distance <= range){ if (distance <= range){
// Within range // Within range
return true; return true;
@ -3007,20 +2999,23 @@ static bool DoCheckRange(AActor *self, AActor *camera, double range, bool twodi)
return false; return false;
} }
// Check distance first, since it's cheaper than checking sight. // Check distance first, since it's cheaper than checking sight.
double dx = self->x - camera->x; fixedvec2 pos = camera->Vec2To(self);
double dy = self->y - camera->y; fixed_t dz;
double dz; fixed_t eyez = (camera->Top() - (camera->height>>2)); // same eye height as P_CheckSight
fixed_t eyez = (camera->z + camera->height - (camera->height>>2)); // same eye height as P_CheckSight if (eyez > self->Top())
if (eyez > self->z + self->height){ {
dz = self->z + self->height - eyez; dz = self->Top() - eyez;
} }
else if (eyez < self->z){ else if (eyez < self->Z())
dz = self->z - eyez; {
dz = self->Z() - eyez;
} }
else{ else
{
dz = 0; dz = 0;
} }
double distance = (dx * dx) + (dy * dy) + (twodi == 0? (dz * dz) : 0); double distance = ((double)pos.x * pos.x) + ((double)pos.y * pos.y) + (twodi == 0? ((double)dz * dz) : 0);
if (distance <= range){ if (distance <= range){
// Within range // Within range
return true; return true;
@ -3193,14 +3188,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
i = (pr_burst.Random2()) % (numChunks/4); i = (pr_burst.Random2()) % (numChunks/4);
for (i = MAX (24, numChunks + i); i >= 0; i--) for (i = MAX (24, numChunks + i); i >= 0; i--)
{ {
mo = Spawn(chunk, mo = Spawn(chunk, self->Vec3Offset(
self->x + (((pr_burst()-128)*self->radius)>>7), (((pr_burst()-128)*self->radius)>>7),
self->y + (((pr_burst()-128)*self->radius)>>7), (((pr_burst()-128)*self->radius)>>7),
self->z + (pr_burst()*self->height/255 + self->GetBobOffset()), ALLOW_REPLACE); (pr_burst()*self->height/255 + self->GetBobOffset())), ALLOW_REPLACE);
if (mo) if (mo)
{ {
mo->velz = FixedDiv(mo->z - self->z, self->height)<<2; mo->velz = FixedDiv(mo->Z() - self->Z(), self->height)<<2;
mo->velx = pr_burst.Random2 () << (FRACBITS-7); mo->velx = pr_burst.Random2 () << (FRACBITS-7);
mo->vely = pr_burst.Random2 () << (FRACBITS-7); mo->vely = pr_burst.Random2 () << (FRACBITS-7);
mo->RenderStyle = self->RenderStyle; mo->RenderStyle = self->RenderStyle;
@ -3232,7 +3227,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFloor)
PARAM_STATE(jump); PARAM_STATE(jump);
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 (self->z <= self->floorz) if (self->Z() <= self->floorz)
{ {
ACTION_JUMP(jump); ACTION_JUMP(jump);
} }
@ -3252,7 +3247,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckCeiling)
PARAM_STATE(jump); PARAM_STATE(jump);
ACTION_SET_RESULT(false); ACTION_SET_RESULT(false);
if (self->z + self->height >= self->ceilingz) // Height needs to be counted if (self->Top() >= self->ceilingz) // Height needs to be counted
{ {
ACTION_JUMP(jump); ACTION_JUMP(jump);
} }
@ -3310,9 +3305,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
PARAM_INT_OPT(flags) { flags = RSF_FOG; } PARAM_INT_OPT(flags) { flags = RSF_FOG; }
bool oktorespawn = false; bool oktorespawn = false;
fixed_t oldx = self->x; fixedvec3 pos = self->Pos();
fixed_t oldy = self->y;
fixed_t oldz = self->z;
self->flags |= MF_SOLID; self->flags |= MF_SOLID;
self->height = self->GetDefault()->height; self->height = self->GetDefault()->height;
@ -3322,11 +3315,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
if (flags & RSF_TELEFRAG) if (flags & RSF_TELEFRAG)
{ {
// [KS] DIE DIE DIE DIE erm *ahem* =) // [KS] DIE DIE DIE DIE erm *ahem* =)
oktorespawn = P_TeleportMove(self, self->x, self->y, self->z, true, false); oktorespawn = P_TeleportMove(self, self->Pos(), true, false);
} }
else else
{ {
oktorespawn = P_CheckPosition(self, self->x, self->y, true); oktorespawn = P_CheckPosition(self, self->X(), self->Y(), true);
} }
if (oktorespawn) if (oktorespawn)
@ -3363,8 +3356,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
if (flags & RSF_FOG) if (flags & RSF_FOG)
{ {
P_SpawnTeleportFog(self, oldx, oldy, oldz, true, true); P_SpawnTeleportFog(self, pos, true, true);
P_SpawnTeleportFog(self, self->x, self->y, self->z, false, true); P_SpawnTeleportFog(self, self->Pos(), false, true);
} }
if (self->CountsAsKill()) if (self->CountsAsKill())
{ {
@ -3568,9 +3561,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
*/ */
AActor *target; AActor *target;
fixed_t fixedvec3 pos;
x1, y1, z1, fixed_t vx, vy, vz;
vx, vy, vz;
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump); PARAM_STATE (jump);
@ -3605,29 +3597,27 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
offsetwidth = FixedMul(self->radius, offsetwidth); offsetwidth = FixedMul(self->radius, offsetwidth);
} }
x1 = self->x; pos = self->PosPlusZ(offsetheight - self->floorclip);
y1 = self->y;
z1 = self->z + offsetheight - self->floorclip;
if (!(flags & CLOFF_FROMBASE)) if (!(flags & CLOFF_FROMBASE))
{ // default to hitscan origin { // default to hitscan origin
// Synced with hitscan: self->height is strangely NON-conscientious about getting the right actor for player // Synced with hitscan: self->height is strangely NON-conscientious about getting the right actor for player
z1 += (self->height >> 1); pos.z += (self->height >> 1);
if (self->player != NULL) if (self->player != NULL)
{ {
z1 += FixedMul (self->player->mo->AttackZOffset, self->player->crouchfactor); pos.z += FixedMul (self->player->mo->AttackZOffset, self->player->crouchfactor);
} }
else else
{ {
z1 += 8*FRACUNIT; pos.z += 8*FRACUNIT;
} }
} }
if (target) if (target)
{ {
fixed_t xydist = self->Distance2D(target); fixed_t xydist = self->Distance2D(target);
fixed_t distance = P_AproxDistance(xydist, target->z - z1); fixed_t distance = P_AproxDistance(xydist, target->Z() - pos.z);
if (range && !(flags & CLOFF_CHECKPARTIAL)) if (range && !(flags & CLOFF_CHECKPARTIAL))
{ {
@ -3647,8 +3637,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
angle += ang; angle += ang;
ang >>= ANGLETOFINESHIFT; ang >>= ANGLETOFINESHIFT;
x1 += FixedMul(offsetwidth, finesine[ang]);
y1 -= FixedMul(offsetwidth, finecosine[ang]); fixedvec2 xy = self->Vec2Offset(
FixedMul(offsetwidth, finesine[ang]),
-FixedMul(offsetwidth, finecosine[ang]));
pos.x = xy.x;
pos.y = xy.y;
} }
if (flags & CLOFF_NOAIM_VERT) if (flags & CLOFF_NOAIM_VERT)
@ -3657,11 +3652,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
} }
else if (flags & CLOFF_AIM_VERT_NOOFFSET) else if (flags & CLOFF_AIM_VERT_NOOFFSET)
{ {
pitch += R_PointToAngle2 (0,0, xydist, target->z - z1 + offsetheight + target->height / 2); pitch += R_PointToAngle2 (0,0, xydist, target->Z() - pos.z + offsetheight + target->height / 2);
} }
else else
{ {
pitch += R_PointToAngle2 (0,0, xydist, target->z - z1 + target->height / 2); pitch += R_PointToAngle2 (0,0, xydist, target->Z() - pos.z + target->height / 2);
} }
} }
else if (flags & CLOFF_ALLOWNULL) else if (flags & CLOFF_ALLOWNULL)
@ -3670,8 +3665,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
pitch += self->pitch; pitch += self->pitch;
angle_t ang = self->angle >> ANGLETOFINESHIFT; angle_t ang = self->angle >> ANGLETOFINESHIFT;
x1 += FixedMul(offsetwidth, finesine[ang]);
y1 -= FixedMul(offsetwidth, finecosine[ang]); fixedvec2 xy = self->Vec2Offset(
FixedMul(offsetwidth, finesine[ang]),
-FixedMul(offsetwidth, finecosine[ang]));
pos.x = xy.x;
pos.y = xy.y;
} }
else else
{ {
@ -3694,7 +3694,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
range range
*/ */
sector_t *sec = P_PointInSector(x1, y1); sector_t *sec = P_PointInSector(pos.x, pos.y);
if (range == 0) if (range == 0)
{ {
@ -3709,7 +3709,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
lof_data.Flags = flags; lof_data.Flags = flags;
lof_data.BadActor = false; lof_data.BadActor = false;
Trace(x1, y1, z1, sec, vx, vy, vz, range, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, 0, Trace(pos.x, pos.y, pos.z, sec, vx, vy, vz, range, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, 0,
CheckLOFTraceFunc, &lof_data); CheckLOFTraceFunc, &lof_data);
if (trace.HitType == TRACE_HitActor || if (trace.HitType == TRACE_HitActor ||
@ -4638,30 +4638,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
target_type = PClass::FindActor("BossSpot"); target_type = PClass::FindActor("BossSpot");
} }
AActor * spot = state->GetSpotWithMinMaxDistance(target_type, ref->x, ref->y, mindist, maxdist); AActor * spot = state->GetSpotWithMinMaxDistance(target_type, ref->X(), ref->Y(), mindist, maxdist);
if (spot == NULL) if (spot == NULL)
{ {
return numret; return numret;
} }
fixed_t prevX = ref->x; fixedvec3 prev = ref->Pos();
fixed_t prevY = ref->y; fixed_t aboveFloor = spot->Z() - spot->floorz;
fixed_t prevZ = ref->z;
fixed_t aboveFloor = spot->z - spot->floorz;
fixed_t finalz = spot->floorz + aboveFloor; fixed_t finalz = spot->floorz + aboveFloor;
if (spot->z + ref->height > spot->ceilingz) if (spot->Z() + ref->height > spot->ceilingz)
finalz = spot->ceilingz - ref->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 tele_result = P_TeleportMove(ref, spot->x, spot->y, finalz, flags & TF_TELEFRAG); bool tele_result = P_TeleportMove(ref, spot->X(), spot->Y(), finalz, flags & TF_TELEFRAG);
if (!tele_result && (flags & TF_FORCED)) if (!tele_result && (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.
ref->SetOrigin(spot->x, spot->y, finalz); ref->SetOrigin(spot->X(), spot->Y(), finalz, false);
tele_result = true; tele_result = true;
} }
@ -4675,10 +4673,10 @@ 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(ref, prevX, prevY, prevZ, true, true); P_SpawnTeleportFog(ref, prev, true, true);
else else
{ {
fog1 = Spawn(fog_type, prevX, prevY, prevZ, ALLOW_REPLACE); fog1 = Spawn(fog_type, prev, ALLOW_REPLACE);
if (fog1 != NULL) if (fog1 != NULL)
fog1->target = ref; fog1->target = ref;
} }
@ -4686,22 +4684,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
if (!(flags & TF_NODESTFOG)) if (!(flags & TF_NODESTFOG))
{ {
if (flags & TF_USEACTORFOG) if (flags & TF_USEACTORFOG)
P_SpawnTeleportFog(ref, ref->x, ref->y, ref->z, false, true); P_SpawnTeleportFog(ref, ref->Pos(), false, true);
else else
{ {
fog2 = Spawn(fog_type, ref->x, ref->y, ref->z, ALLOW_REPLACE); fog2 = Spawn(fog_type, ref->Pos(), ALLOW_REPLACE);
if (fog2 != NULL) if (fog2 != NULL)
fog2->target = ref; fog2->target = ref;
} }
} }
} }
if (flags & TF_USESPOTZ) ref->SetZ((flags & TF_USESPOTZ) ? spot->Z() : ref->floorz, false);
ref->z = spot->z; self->SetZ((flags & TF_USESPOTZ) ? spot->Z() : self->floorz, false);
else
ref->z = ref->floorz;
self->z = (flags & TF_USESPOTZ) ? spot->z : self->floorz;
if (!(flags & TF_KEEPANGLE)) if (!(flags & TF_KEEPANGLE))
ref->angle = spot->angle; ref->angle = spot->angle;
@ -4809,8 +4803,8 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdis
if (xydist != 0 && xyspeed != 0) if (xydist != 0 && xyspeed != 0)
{ {
dist = MulScale13(finesine[weaveXY << BOBTOFINESHIFT], xydist); dist = MulScale13(finesine[weaveXY << BOBTOFINESHIFT], xydist);
newX = self->x - FixedMul (finecosine[angle], dist); newX = self->X() - FixedMul (finecosine[angle], dist);
newY = self->y - FixedMul (finesine[angle], dist); newY = self->Y() - FixedMul (finesine[angle], dist);
weaveXY = (weaveXY + xyspeed) & 63; weaveXY = (weaveXY + xyspeed) & 63;
dist = MulScale13(finesine[weaveXY << BOBTOFINESHIFT], xydist); dist = MulScale13(finesine[weaveXY << BOBTOFINESHIFT], xydist);
newX += FixedMul (finecosine[angle], dist); newX += FixedMul (finecosine[angle], dist);
@ -4823,17 +4817,22 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdis
{ {
self->UnlinkFromWorld (); self->UnlinkFromWorld ();
self->flags |= MF_NOBLOCKMAP; self->flags |= MF_NOBLOCKMAP;
self->x = newX; // the following 4 lines are for future-proofing this for both interpolation overhaul and line portals.
self->y = newY; // For portals we need to calculate the destination including the portal offset
// and for interpolation we need to set the performed movement explicitly, because SetXY cannot do that.
newX -= self->X();
newY -= self->Y();
self->SetXY(self->Vec2Offset(newX, newY));
self->SetMovement(newX, newY, 0);
self->LinkToWorld (); self->LinkToWorld ();
} }
self->WeaveIndexXY = weaveXY; self->WeaveIndexXY = weaveXY;
} }
if (zdist != 0 && zspeed != 0) if (zdist != 0 && zspeed != 0)
{ {
self->z -= MulScale13(finesine[weaveZ << BOBTOFINESHIFT], zdist); self->AddZ(-MulScale13(finesine[weaveZ << BOBTOFINESHIFT], zdist));
weaveZ = (weaveZ + zspeed) & 63; weaveZ = (weaveZ + zspeed) & 63;
self->z += MulScale13(finesine[weaveZ << BOBTOFINESHIFT], zdist); self->AddZ(MulScale13(finesine[weaveZ << BOBTOFINESHIFT], zdist));
self->WeaveIndexZ = weaveZ; self->WeaveIndexZ = weaveZ;
} }
} }
@ -4924,8 +4923,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
bool dodge = (P_CheckSight(self->target, self) && (angle>226 || angle<30)); bool dodge = (P_CheckSight(self->target, self) && (angle>226 || angle<30));
// Distance check is simplistic // Distance check is simplistic
fixed_t dx = abs (self->x - self->target->x); fixedvec2 vec = self->Vec2To(self->target);
fixed_t dy = abs (self->y - self->target->y); fixed_t dx = abs (vec.x);
fixed_t dy = abs (vec.y);
fixed_t dz; fixed_t dz;
fixed_t dist = dx > dy ? dx : dy; fixed_t dist = dx > dy ? dx : dy;
@ -4955,13 +4955,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
if (pr_cabullet() < hitchance) if (pr_cabullet() < hitchance)
{ {
// Compute position for spawning blood/puff // Compute position for spawning blood/puff
dx = self->target->x;
dy = self->target->y;
dz = self->target->z + (self->target->height>>1);
angle = self->target->AngleTo(self); angle = self->target->AngleTo(self);
dx += FixedMul(self->target->radius, finecosine[angle>>ANGLETOFINESHIFT]); fixedvec3 bloodpos = self->target->Vec3Angle(self->target->radius, angle, self->target->height >> 1);
dy += FixedMul(self->target->radius, finesine[angle>>ANGLETOFINESHIFT]);
int damage = flags & WAF_NORANDOM ? maxdamage : (1 + (pr_cabullet() % maxdamage)); int damage = flags & WAF_NORANDOM ? maxdamage : (1 + (pr_cabullet() % maxdamage));
if (dist >= pointblank) if (dist >= pointblank)
@ -4982,7 +4979,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
if ((0 && dpuff->flags3 & MF3_PUFFONACTORS) || !spawnblood) if ((0 && dpuff->flags3 & MF3_PUFFONACTORS) || !spawnblood)
{ {
spawnblood = false; spawnblood = false;
P_SpawnPuff(self, pufftype, dx, dy, dz, angle, 0); P_SpawnPuff(self, pufftype, bloodpos, angle, 0);
} }
} }
else if (self->target->flags3 & MF3_GHOST) else if (self->target->flags3 & MF3_GHOST)
@ -4992,7 +4989,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
int newdam = P_DamageMobj(self->target, self, self, damage, mod, DMG_THRUSTLESS); int newdam = P_DamageMobj(self->target, self, self, damage, mod, DMG_THRUSTLESS);
if (spawnblood) if (spawnblood)
{ {
P_SpawnBlood(dx, dy, dz, angle, newdam > 0 ? newdam : damage, self->target); P_SpawnBlood(bloodpos, angle, newdam > 0 ? newdam : damage, self->target);
P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self->AngleTo(dx, dy, self->target), 0); P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self->AngleTo(dx, dy, self->target), 0);
} }
} }
@ -5234,7 +5231,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{ {
amount = 1; amount = 1;
} }
FBlockThingsIterator it(FBoundingBox(self->x, self->y, distance)); FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance));
AActor *thing; AActor *thing;
bool given = false; bool given = false;
@ -5307,11 +5304,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass) if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass)
{ {
fixedvec3 diff = self->Vec3To(thing);
diff.z += (thing->height - self->height) / 2;
if (flags & RGF_CUBE) if (flags & RGF_CUBE)
{ // check if inside a cube { // check if inside a cube
double dx = fabs((double)(thing->x - self->x)); double dx = fabs((double)(diff.x));
double dy = fabs((double)(thing->y - self->y)); double dy = fabs((double)(diff.y));
double dz = fabs((double)(thing->z + thing->height / 2) - (self->z + self->height / 2)); double dz = fabs((double)(diff.z));
double dist = (double)distance; double dist = (double)distance;
double min = (double)mindist; double min = (double)mindist;
if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min))) if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min)))
@ -5323,9 +5322,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{ // check if inside a sphere { // check if inside a sphere
double distsquared = double(distance) * double(distance); double distsquared = double(distance) * double(distance);
double minsquared = double(mindist) * double(mindist); double minsquared = double(mindist) * double(mindist);
TVector3<double> tpos(thing->x, thing->y, thing->z + thing->height / 2); double lengthsquared = TVector3<double>(diff.x, diff.y, diff.z).LengthSquared();
TVector3<double> spos(self->x, self->y, self->z + self->height / 2); if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared)))
if ((tpos - spos).LengthSquared() > distsquared || (minsquared && ((tpos - spos).LengthSquared() < minsquared)))
{ {
continue; continue;
} }
@ -6163,9 +6161,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower)
ACTION_SET_RESULT(false); //No inventory jump chains please. ACTION_SET_RESULT(false); //No inventory jump chains please.
if (mobj != NULL && mobj != self) //AAPTR_DEFAULT is completely useless in this regard. if (mobj != NULL && mobj != self) //AAPTR_DEFAULT is completely useless in this regard.
{ {
if ((high) && (mobj->z > ((includeHeight ? self->height : 0) + self->z + offsethigh))) if ((high) && (mobj->Z() > ((includeHeight ? self->height : 0) + self->Z() + offsethigh)))
ACTION_JUMP(high); ACTION_JUMP(high);
else if ((low) && (mobj->z + (includeHeight ? mobj->height : 0)) < (self->z + offsetlow)) else if ((low) && (mobj->Z() + (includeHeight ? mobj->height : 0)) < (self->Z() + offsetlow))
ACTION_JUMP(low); ACTION_JUMP(low);
} }
return numret; return numret;
@ -6294,8 +6292,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
//Make sure it's in range and respect the desire for Z or not. //Make sure it's in range and respect the desire for Z or not.
if (ref->AproxDistance(mo) < distance && if (ref->AproxDistance(mo) < distance &&
((flags & CPXF_NOZ) || ((flags & CPXF_NOZ) ||
((ref->z > mo->z && ref->z - (mo->z + mo->height) < distance) || ((ref->Z() > mo->Z() && ref->Top() < distance) ||
(ref->z <= mo->z && mo->z - (ref->z + ref->height) < distance)))) (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))
{ {
if (mo->flags6 & MF6_KILLED) if (mo->flags6 & MF6_KILLED)
{ {