- floatified the rest of thingdef_codeptr.cpp and got rid of the remaining fixed_t and angle_t parameters in VM-accessed function. The VM should now be free of those types completely.

This commit is contained in:
Christoph Oelckers 2016-03-25 12:57:22 +01:00
parent f76524f459
commit 21340c6eba
11 changed files with 297 additions and 377 deletions

View file

@ -5990,7 +5990,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
if (activator == NULL || !reference) if (activator == NULL || !reference)
return false; return false;
if (P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch)) if (P_Thing_Warp(activator, reference, ACSToDouble(xofs), ACSToDouble(yofs), ACSToDouble(zofs), ACSToAngle(angle), flags, ACSToDouble(heightoffset), ACSToDouble(radiusoffset), ACSToAngle(pitch)))
{ {
if (state && argCount > 6) if (state && argCount > 6)
{ {

View file

@ -313,7 +313,7 @@ void P_ThinkParticles ()
} }
} }
void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fixed_t vz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, WORD size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz) void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fixed_t vz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, int size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz)
{ {
particle_t *particle = NewParticle(); particle_t *particle = NewParticle();
@ -334,7 +334,7 @@ void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fi
particle->accy = accely; particle->accy = accely;
particle->accz = accelz; particle->accz = accelz;
particle->bright = fullbright; particle->bright = fullbright;
particle->size = size; particle->size = (WORD)size;
} }
} }

View file

@ -83,7 +83,12 @@ particle_t *JitterParticle (int ttl);
particle_t *JitterParticle (int ttl, double drift); particle_t *JitterParticle (int ttl, double drift);
void P_ThinkParticles (void); void P_ThinkParticles (void);
void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fixed_t vz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, WORD size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz); void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fixed_t vz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, int size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz);
inline void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, bool fullbright, double startalpha, int lifetime, WORD size, double fadestep)
{
P_SpawnParticle(FLOAT2FIXED(pos.X), FLOAT2FIXED(pos.Y), FLOAT2FIXED(pos.Z), FLOAT2FIXED(vel.X), FLOAT2FIXED(vel.Y), FLOAT2FIXED(vel.Z),
color, fullbright, BYTE(startalpha * 255), BYTE(lifetime), WORD(size), fadestep < 0 ? -1 : int(fadestep * 255), FLOAT2FIXED(accel.X), FLOAT2FIXED(accel.Y), FLOAT2FIXED(accel.Z));
}
void P_InitEffects (void); void P_InitEffects (void);
void P_RunEffects (void); void P_RunEffects (void);

View file

@ -1165,23 +1165,23 @@ void P_RandomChaseDir (AActor *actor)
bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams *params) bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams *params)
{ {
fixed_t maxdist; double maxdist;
fixed_t mindist; double mindist;
angle_t fov; DAngle fov;
if (params != NULL) if (params != NULL)
{ {
maxdist = params->maxdist; maxdist = params->maxDist;
mindist = params->mindist; mindist = params->minDist;
fov = params->fov; fov = params->Fov;
} }
else else
{ {
mindist = maxdist = 0; mindist = maxdist = 0;
fov = allaround ? 0 : ANGLE_180; fov = allaround ? 0. : 180.;
} }
fixed_t dist = lookee->AproxDistance (other); double dist = lookee->Distance2D (other);
if (maxdist && dist > maxdist) if (maxdist && dist > maxdist)
return false; // [KS] too far return false; // [KS] too far
@ -1189,15 +1189,15 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
if (mindist && dist < mindist) if (mindist && dist < mindist)
return false; // [KS] too close return false; // [KS] too close
if (fov && fov < ANGLE_MAX) if (fov != 0)
{ {
angle_t an = lookee->__f_AngleTo(other) - lookee->_f_angle(); DAngle an = absangle(lookee->AngleTo(other), lookee->Angles.Yaw);
if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) if (an > (fov / 2))
{ {
// if real close, react anyway // if real close, react anyway
// [KS] but respect minimum distance rules // [KS] but respect minimum distance rules
if (mindist || dist > FLOAT2FIXED(lookee->meleerange + lookee->radius)) if (mindist || dist > lookee->meleerange + lookee->radius)
return false; // outside of fov return false; // outside of fov
} }
} }
@ -1887,15 +1887,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (minseedist) { minseedist = 0; } PARAM_FLOAT_OPT (minseedist) { minseedist = 0; }
PARAM_FIXED_OPT (maxseedist) { maxseedist = 0; } PARAM_FLOAT_OPT (maxseedist) { maxseedist = 0; }
PARAM_FIXED_OPT (maxheardist) { maxheardist = 0; } PARAM_FLOAT_OPT (maxheardist) { maxheardist = 0; }
PARAM_FLOAT_OPT (fov_f) { fov_f = 0; } PARAM_DANGLE_OPT (fov) { fov = 0.; }
PARAM_STATE_OPT (seestate) { seestate = NULL; } PARAM_STATE_OPT (seestate) { seestate = NULL; }
AActor *targ = NULL; // Shuts up gcc AActor *targ = NULL; // Shuts up gcc
fixed_t dist; fixed_t dist;
angle_t fov = (fov_f == 0) ? ANGLE_180 : FLOAT2ANGLE(fov_f); if (fov == 0) fov = 180.;
FLookExParams params = { fov, minseedist, maxseedist, maxheardist, flags, seestate }; FLookExParams params = { fov, minseedist, maxseedist, maxheardist, flags, seestate };
if (self->flags5 & MF5_INCONVERSATION) if (self->flags5 & MF5_INCONVERSATION)
@ -2817,7 +2817,7 @@ enum FAF_Flags
FAF_TOP = 4, FAF_TOP = 4,
FAF_NODISTFACTOR = 8, // deprecated FAF_NODISTFACTOR = 8, // deprecated
}; };
void A_Face (AActor *self, AActor *other, angle_t _max_turn, angle_t _max_pitch, angle_t _ang_offset, angle_t _pitch_offset, int flags, fixed_t z_add) void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAngle ang_offset, DAngle pitch_offset, int flags, double z_add)
{ {
if (!other) if (!other)
return; return;
@ -2830,12 +2830,7 @@ void A_Face (AActor *self, AActor *other, angle_t _max_turn, angle_t _max_pitch,
self->flags &= ~MF_AMBUSH; self->flags &= ~MF_AMBUSH;
DAngle max_turn = ANGLE2DBL(_max_turn);
DAngle ang_offset = ANGLE2DBL(_ang_offset);
DAngle max_pitch = ANGLE2DBL(_max_pitch);
DAngle pitch_offset = ANGLE2DBL(_pitch_offset);
DAngle other_angle = self->AngleTo(other); DAngle other_angle = self->AngleTo(other);
DAngle delta = deltaangle(self->Angles.Yaw, other_angle); DAngle delta = deltaangle(self->Angles.Yaw, other_angle);
// 0 means no limit. Also, if we turn in a single step anyways, no need to go through the algorithms. // 0 means no limit. Also, if we turn in a single step anyways, no need to go through the algorithms.
@ -2882,7 +2877,7 @@ void A_Face (AActor *self, AActor *other, angle_t _max_turn, angle_t _max_pitch,
if (flags & FAF_TOP) if (flags & FAF_TOP)
target_z = other->Top() + other->GetBobOffset(); target_z = other->Top() + other->GetBobOffset();
target_z += FIXED2FLOAT(z_add); target_z += z_add;
double dist_z = target_z - source_z; double dist_z = target_z - source_z;
double ddist = g_sqrt(dist.X*dist.X + dist.Y*dist.Y + dist_z*dist_z); double ddist = g_sqrt(dist.X*dist.X + dist.Y*dist.Y + dist_z*dist_z);
@ -2926,12 +2921,12 @@ void A_FaceTarget(AActor *self)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; } PARAM_DANGLE_OPT(max_turn) { max_turn = 0.; }
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; } PARAM_DANGLE_OPT(max_pitch) { max_pitch = 270.; }
PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0; } PARAM_DANGLE_OPT(ang_offset) { ang_offset = 0.; }
PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0; } PARAM_DANGLE_OPT(pitch_offset) { pitch_offset = 0.; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_FIXED_OPT(z_add) { z_add = 0; } PARAM_FLOAT_OPT(z_add) { z_add = 0; }
A_Face(self, self->target, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); A_Face(self, self->target, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add);
return 0; return 0;
@ -2940,12 +2935,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; } PARAM_DANGLE_OPT(max_turn) { max_turn = 0.; }
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; } PARAM_DANGLE_OPT(max_pitch) { max_pitch = 270.; }
PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0; } PARAM_DANGLE_OPT(ang_offset) { ang_offset = 0.; }
PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0; } PARAM_DANGLE_OPT(pitch_offset) { pitch_offset = 0.; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_FIXED_OPT(z_add) { z_add = 0; } PARAM_FLOAT_OPT(z_add) { z_add = 0; }
A_Face(self, self->master, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); A_Face(self, self->master, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add);
return 0; return 0;
@ -2954,12 +2949,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; } PARAM_DANGLE_OPT(max_turn) { max_turn = 0.; }
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; } PARAM_DANGLE_OPT(max_pitch) { max_pitch = 270.; }
PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0; } PARAM_DANGLE_OPT(ang_offset) { ang_offset = 0.; }
PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0; } PARAM_DANGLE_OPT(pitch_offset) { pitch_offset = 0.; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_FIXED_OPT(z_add) { z_add = 0; } PARAM_FLOAT_OPT(z_add) { z_add = 0; }
A_Face(self, self->tracer, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); A_Face(self, self->tracer, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add);
return 0; return 0;

View file

@ -38,10 +38,10 @@ enum LO_Flags
struct FLookExParams struct FLookExParams
{ {
angle_t fov; DAngle Fov;
fixed_t mindist; double minDist;
fixed_t maxdist; double maxDist;
fixed_t maxheardist; double maxHeardist;
int flags; int flags;
FState *seestate; FState *seestate;
}; };
@ -78,7 +78,7 @@ void A_BossDeath(AActor *self);
void A_Wander(AActor *self, int flags = 0); void A_Wander(AActor *self, int flags = 0);
void A_Chase(VMFrameStack *stack, AActor *self); void A_Chase(VMFrameStack *stack, AActor *self);
void A_FaceTarget(AActor *actor); void A_FaceTarget(AActor *actor);
void A_Face(AActor *self, AActor *other, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270, angle_t ang_offset = 0, angle_t pitch_offset = 0, int flags = 0, fixed_t z_add = 0); void A_Face(AActor *self, AActor *other, DAngle max_turn = 0., DAngle max_pitch = 270., DAngle ang_offset = 0., DAngle pitch_offset = 0., int flags = 0, double z_add = 0);
bool A_RaiseMobj (AActor *, double speed); bool A_RaiseMobj (AActor *, double speed);
bool A_SinkMobj (AActor *, double speed); bool A_SinkMobj (AActor *, double speed);

View file

@ -221,7 +221,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser);
bool P_Thing_CanRaise(AActor *thing); bool P_Thing_CanRaise(AActor *thing);
PClassActor *P_GetSpawnableType(int spawnnum); PClassActor *P_GetSpawnableType(int spawnnum);
void InitSpawnablesFromMapinfo(); void InitSpawnablesFromMapinfo();
int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset, fixed_t radiusoffset, angle_t pitch); int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch);
enum WARPF enum WARPF
{ {
@ -302,6 +302,10 @@ inline bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const sec
return P_TryMove(thing, FLOAT2FIXED(pos.X), FLOAT2FIXED(pos.Y), dropoff, onfloor, tm, missileCheck); return P_TryMove(thing, FLOAT2FIXED(pos.X), FLOAT2FIXED(pos.Y), dropoff, onfloor, tm, missileCheck);
} }
bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y); bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y);
inline bool P_CheckMove(AActor *thing, double x, double y)
{
return P_CheckMove(thing, FLOAT2FIXED(x), FLOAT2FIXED(y));
}
void P_ApplyTorque(AActor *mo); void P_ApplyTorque(AActor *mo);
bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag, bool modifyactor = true); // [RH] Added z and telefrag parameters bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag, bool modifyactor = true); // [RH] Added z and telefrag parameters
inline bool P_TeleportMove(AActor* thing, const fixedvec3 &pos, bool telefrag, bool modifyactor = true) inline bool P_TeleportMove(AActor* thing, const fixedvec3 &pos, bool telefrag, bool modifyactor = true)

View file

@ -356,6 +356,10 @@ public:
FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1, bool ignorerestricted = false); FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1, bool ignorerestricted = false);
FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted, sector_t *newsec); FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted, sector_t *newsec);
FMultiBlockThingsIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec)
: FMultiBlockThingsIterator(check, FLOAT2FIXED(checkx), FLOAT2FIXED(checky), FLOAT2FIXED(checkz), FLOAT2FIXED(checkh), FLOAT2FIXED(checkradius), ignorerestricted, newsec)
{
}
bool Next(CheckResult *item); bool Next(CheckResult *item);
void Reset(); void Reset();
const FBoundingBox &Box() const const FBoundingBox &Box() const

View file

@ -419,7 +419,7 @@ void P_BobWeapon (player_t *player, pspdef_t *psp, float *x, float *y)
{ {
float bobx = float(player->bob * Rangex); float bobx = float(player->bob * Rangex);
float boby = float(player->bob * Rangey); float boby = float(player->bob * Rangey);
switch (level.levelnum)//bobstyle) switch (bobstyle)
{ {
case AWeapon::BobNormal: case AWeapon::BobNormal:
*x = bobx * angle.Cos(); *x = bobx * angle.Cos();

View file

@ -670,7 +670,7 @@ void InitSpawnablesFromMapinfo()
} }
int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset, fixed_t radiusoffset, angle_t pitch) int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch)
{ {
if (flags & WARPF_MOVEPTR) if (flags & WARPF_MOVEPTR)
{ {
@ -679,32 +679,33 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
caller = temp; caller = temp;
} }
fixedvec3 old = caller->_f_Pos(); DVector3 old = caller->Pos();
int oldpgroup = caller->Sector->PortalGroup; int oldpgroup = caller->Sector->PortalGroup;
zofs += FixedMul(reference->_f_height(), heightoffset); zofs += reference->Height * heightoffset;
if (!(flags & WARPF_ABSOLUTEANGLE)) if (!(flags & WARPF_ABSOLUTEANGLE))
{ {
angle += (flags & WARPF_USECALLERANGLE) ? caller->_f_angle() : reference->_f_angle(); angle += (flags & WARPF_USECALLERANGLE) ? caller->Angles.Yaw: reference->Angles.Yaw;
} }
const fixed_t rad = FixedMul(radiusoffset, reference->_f_radius()); const double rad = radiusoffset * reference->radius;
const angle_t fineangle = angle >> ANGLETOFINESHIFT; const double s = angle.Sin();
const double c = angle.Cos();
if (!(flags & WARPF_ABSOLUTEPOSITION)) if (!(flags & WARPF_ABSOLUTEPOSITION))
{ {
if (!(flags & WARPF_ABSOLUTEOFFSET)) if (!(flags & WARPF_ABSOLUTEOFFSET))
{ {
fixed_t xofs1 = xofs; double xofs1 = xofs;
// (borrowed from A_SpawnItemEx, assumed workable) // (borrowed from A_SpawnItemEx, assumed workable)
// 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!
xofs = FixedMul(xofs1, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]); xofs = xofs1 * c + yofs * s;
yofs = FixedMul(xofs1, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]); yofs = xofs1 * s - yofs * c;
} }
if (flags & WARPF_TOFLOOR) if (flags & WARPF_TOFLOOR)
@ -713,30 +714,21 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
// now the caller's floorz should be appropriate for the assigned xy-position // now the caller's floorz should be appropriate for the assigned xy-position
// assigning position again with. // assigning position again with.
// extra unlink, link and environment calculation // extra unlink, link and environment calculation
caller->SetOrigin(reference->Vec3Offset( caller->SetOrigin(reference->Vec3Offset(xofs + rad * c, yofs + rad * s, 0.), true);
xofs + FixedMul(rad, finecosine[fineangle]), // The two-step process is important.
yofs + FixedMul(rad, finesine[fineangle]), caller->SetZ(caller->floorz + zofs);
0), true);
caller->_f_SetZ(caller->_f_floorz() + zofs);
} }
else else
{ {
caller->SetOrigin(reference->Vec3Offset( caller->SetOrigin(reference->Vec3Offset(xofs + rad * c, yofs + rad * s, zofs), true);
xofs + FixedMul(rad, finecosine[fineangle]),
yofs + FixedMul(rad, finesine[fineangle]),
zofs), true);
} }
} }
else // [MC] The idea behind "absolute" is meant to be "absolute". Override everything, just like A_SpawnItemEx's. else // [MC] The idea behind "absolute" is meant to be "absolute". Override everything, just like A_SpawnItemEx's.
{ {
caller->SetOrigin(xofs + rad * c, yofs + rad * s, zofs, true);
if (flags & WARPF_TOFLOOR) if (flags & WARPF_TOFLOOR)
{ {
caller->SetOrigin(xofs + FixedMul(rad, finecosine[fineangle]), yofs + FixedMul(rad, finesine[fineangle]), zofs, true); caller->SetZ(caller->floorz + zofs);
caller->_f_SetZ(caller->_f_floorz() + zofs);
}
else
{
caller->SetOrigin(xofs + FixedMul(rad, finecosine[fineangle]), yofs + FixedMul(rad, finesine[fineangle]), zofs, true);
} }
} }
@ -748,13 +740,13 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
} }
else else
{ {
caller->Angles.Yaw = ANGLE2DBL(angle); caller->Angles.Yaw = angle;
if (flags & WARPF_COPYPITCH) if (flags & WARPF_COPYPITCH)
caller->SetPitch(reference->Angles.Pitch, false); caller->SetPitch(reference->Angles.Pitch, false);
if (pitch) if (pitch != 0)
caller->SetPitch(caller->Angles.Pitch + ANGLE2DBL(pitch), false); caller->SetPitch(caller->Angles.Pitch + pitch, false);
if (flags & WARPF_COPYVELOCITY) if (flags & WARPF_COPYVELOCITY)
{ {
@ -765,6 +757,7 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
caller->Vel.Zero(); caller->Vel.Zero();
} }
#if 0 // needs fixing
// this is no fun with line portals // this is no fun with line portals
if (flags & WARPF_WARPINTERPOLATION) if (flags & WARPF_WARPINTERPOLATION)
{ {
@ -789,9 +782,11 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
{ {
caller->ClearInterpolation(); caller->ClearInterpolation();
} }
#endif
if ((flags & WARPF_BOB) && (reference->flags2 & MF2_FLOATBOB)) if ((flags & WARPF_BOB) && (reference->flags2 & MF2_FLOATBOB))
{ {
caller->_f_AddZ(reference->_f_GetBobOffset()); caller->AddZ(reference->GetBobOffset());
} }
} }
return true; return true;

View file

@ -1893,7 +1893,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
PARAM_FLOAT_OPT (spawnofs_z) { spawnofs_z = 0; } PARAM_FLOAT_OPT (spawnofs_z) { spawnofs_z = 0; }
PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; } PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; }
if (range == 0) range = 8192*FRACUNIT; if (range == 0) range = 8192.;
if (sparsity == 0) sparsity = 1; if (sparsity == 0) sparsity = 1;
FTranslatedLineTarget t; FTranslatedLineTarget t;
@ -2254,7 +2254,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
} }
if (flags & SIXF_TELEFRAG) if (flags & SIXF_TELEFRAG)
{ {
P_TeleportMove(mo, mo->_f_Pos(), 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;
@ -2393,7 +2393,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_CLASS_OPT (missile, AActor) { missile = PClass::FindActor("Unknown"); } PARAM_CLASS_OPT (missile, AActor) { missile = PClass::FindActor("Unknown"); }
PARAM_FIXED_OPT (distance) { distance = 0; } PARAM_FLOAT_OPT (distance) { distance = 0; }
PARAM_FLOAT_OPT (zheight) { zheight = 0; } PARAM_FLOAT_OPT (zheight) { zheight = 0; }
PARAM_BOOL_OPT (useammo) { useammo = true; } PARAM_BOOL_OPT (useammo) { useammo = true; }
PARAM_BOOL_OPT (transfer_translation) { transfer_translation = false; } PARAM_BOOL_OPT (transfer_translation) { transfer_translation = false; }
@ -2412,7 +2412,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
if (distance == 0) if (distance == 0)
{ {
// use the minimum distance that does not result in an overlap // use the minimum distance that does not result in an overlap
distance = (self->_f_radius() + GetDefaultByType(missile)->_f_radius()) >> FRACBITS; distance = (self->radius + GetDefaultByType(missile)->radius);
} }
if (ACTION_CALL_FROM_WEAPON()) if (ACTION_CALL_FROM_WEAPON())
@ -2531,9 +2531,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_CLASS (missile, AActor); PARAM_CLASS (missile, AActor);
PARAM_FIXED_OPT (zheight) { zheight = 0; } PARAM_FLOAT_OPT (zheight) { zheight = 0; }
PARAM_FLOAT_OPT (xyvel) { xyvel = 0; } PARAM_FLOAT_OPT (xyvel) { xyvel = 0; }
PARAM_FIXED_OPT (zvel) { zvel = 0; } PARAM_FLOAT_OPT (zvel) { zvel = 0; }
PARAM_BOOL_OPT (useammo) { useammo = true; } PARAM_BOOL_OPT (useammo) { useammo = true; }
if (missile == NULL) if (missile == NULL)
@ -2995,51 +2995,51 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_INT_OPT (lifetime) { lifetime = 35; } PARAM_INT_OPT (lifetime) { lifetime = 35; }
PARAM_INT_OPT (size) { size = 1; } PARAM_INT_OPT (size) { size = 1; }
PARAM_ANGLE_OPT (angle) { angle = 0; } PARAM_DANGLE_OPT(angle) { angle = 0.; }
PARAM_FIXED_OPT (xoff) { xoff = 0; } PARAM_FLOAT_OPT (xoff) { xoff = 0; }
PARAM_FIXED_OPT (yoff) { yoff = 0; } PARAM_FLOAT_OPT (yoff) { yoff = 0; }
PARAM_FIXED_OPT (zoff) { zoff = 0; } PARAM_FLOAT_OPT (zoff) { zoff = 0; }
PARAM_FIXED_OPT (xvel) { xvel = 0; } PARAM_FLOAT_OPT (xvel) { xvel = 0; }
PARAM_FIXED_OPT (yvel) { yvel = 0; } PARAM_FLOAT_OPT (yvel) { yvel = 0; }
PARAM_FIXED_OPT (zvel) { zvel = 0; } PARAM_FLOAT_OPT (zvel) { zvel = 0; }
PARAM_FIXED_OPT (accelx) { accelx = 0; } PARAM_FLOAT_OPT (accelx) { accelx = 0; }
PARAM_FIXED_OPT (accely) { accely = 0; } PARAM_FLOAT_OPT (accely) { accely = 0; }
PARAM_FIXED_OPT (accelz) { accelz = 0; } PARAM_FLOAT_OPT (accelz) { accelz = 0; }
PARAM_FIXED_OPT (startalphaf) { startalphaf = FRACUNIT; } PARAM_FLOAT_OPT (startalpha) { startalpha = 1.; }
PARAM_FIXED_OPT (fadestepf) { fadestepf = -FRACUNIT; } PARAM_FLOAT_OPT (fadestep) { fadestep = -1.; }
BYTE startalpha = (BYTE)(clamp(startalphaf, 0, FRACUNIT) * 255 / FRACUNIT); startalpha = clamp(startalpha, 0., 1.);
int fadestep = fadestepf < 0 ? -1 : clamp(fadestepf, 0, FRACUNIT) * 255 / FRACUNIT; if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.);
lifetime = clamp<int>(lifetime, 0, 255); // Clamp to byte
size = clamp<int>(size, 0, 65535); // Clamp to word size = clamp<int>(size, 0, 65535); // Clamp to word
if (lifetime != 0) if (lifetime != 0)
{ {
const angle_t ang = (angle + ((flags & SPF_RELANG) ? self->_f_angle() : 0)) >> ANGLETOFINESHIFT; if (flags & SPF_RELANG) angle += self->Angles.Yaw;
fixedvec3 pos; double s = angle.Sin();
double c = angle.Cos();
DVector3 pos(xoff, yoff, zoff);
DVector3 vel(xvel, yvel, zvel);
DVector3 acc(accelx, accely, accelz);
//[MC] Code ripped right out of A_SpawnItemEx. //[MC] Code ripped right out of A_SpawnItemEx.
if (flags & SPF_RELPOS) if (flags & SPF_RELPOS)
{ {
// 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!
const fixed_t xof1 = xoff; pos.X = xoff * c + yoff * s;
xoff = FixedMul(xof1, finecosine[ang]) + FixedMul(yoff, finesine[ang]); pos.Y = xoff * s - yoff * c;
yoff = FixedMul(xof1, finesine[ang]) - FixedMul(yoff, finecosine[ang]);
} }
if (flags & SPF_RELVEL) if (flags & SPF_RELVEL)
{ {
const fixed_t newxvel = FixedMul(xvel, finecosine[ang]) + FixedMul(yvel, finesine[ang]); vel.X = xvel * c + yvel * s;
yvel = FixedMul(xvel, finesine[ang]) - FixedMul(yvel, finecosine[ang]); vel.Y = xvel * s - yvel * c;
xvel = newxvel;
} }
if (flags & SPF_RELACCEL) if (flags & SPF_RELACCEL)
{ {
fixed_t newaccelx = FixedMul(accelx, finecosine[ang]) + FixedMul(accely, finesine[ang]); acc.X = accelx * c + accely * s;
accely = FixedMul(accelx, finesine[ang]) - FixedMul(accely, finecosine[ang]); acc.Y = accelx * s - accely * c;
accelx = newaccelx;
} }
pos = self->Vec3Offset(xoff, yoff, zoff); pos = self->Vec3Offset(xoff, yoff, zoff);
P_SpawnParticle(pos.x, pos.y, pos.z, xvel, yvel, zvel, color, !!(flags & SPF_FULLBRIGHT), startalpha, lifetime, size, fadestep, accelx, accely, accelz); P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, !!(flags & SPF_FULLBRIGHT), startalpha, lifetime, size, fadestep);
} }
return 0; return 0;
} }
@ -3082,36 +3082,37 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight)
// Useful for maps with many multi-actor special effects. // Useful for maps with many multi-actor special effects.
// //
//=========================================================================== //===========================================================================
static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range, bool twodi) static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range, bool twodi, bool checksight)
{ {
if (camera == NULL) if (camera == NULL)
{ {
return false; return false;
} }
// Check distance first, since it's cheaper than checking sight. // Check distance first, since it's cheaper than checking sight.
fixedvec2 pos = camera->_f_Vec2To(self); DVector2 pos = camera->Vec2To(self);
fixed_t dz; double dz;
fixed_t eyez = (camera->_f_Top() - (camera->_f_height()>>2)); // same eye height as P_CheckSight double eyez = camera->Center();
if (eyez > self->_f_Top()) if (eyez > self->Top())
{ {
dz = self->_f_Top() - eyez; dz = self->Top() - eyez;
} }
else if (eyez < self->_f_Z()) else if (eyez < self->Z())
{ {
dz = self->_f_Z() - eyez; dz = self->Z() - eyez;
} }
else else
{ {
dz = 0; dz = 0;
} }
double distance = ((double)pos.x * pos.x) + ((double)pos.y * pos.y) + (twodi == 0? ((double)dz * dz) : 0); double distance = DVector3(pos, twodi? 0. : dz).LengthSquared();
if (distance <= range){ if (distance <= range*range)
{
// Within range // Within range
return true; return true;
} }
// Now check LOS. // Now check LOS.
if (P_CheckSight(camera, self, SF_IGNOREVISIBILITY)) if (checksight && P_CheckSight(camera, self, SF_IGNOREVISIBILITY))
{ // Visible { // Visible
return true; return true;
} }
@ -3125,19 +3126,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange)
PARAM_STATE(jump); PARAM_STATE(jump);
PARAM_BOOL_OPT(twodi) { twodi = false; } PARAM_BOOL_OPT(twodi) { twodi = false; }
range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots range *= range;
for (int i = 0; i < MAXPLAYERS; ++i) for (int i = 0; i < MAXPLAYERS; ++i)
{ {
if (playeringame[i]) if (playeringame[i])
{ {
// Always check from each player. // Always check from each player.
if (DoCheckSightOrRange(self, players[i].mo, range, twodi)) if (DoCheckSightOrRange(self, players[i].mo, range, twodi, true))
{ {
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
// If a player is viewing from a non-player, check that too. // If a player is viewing from a non-player, check that too.
if (players[i].camera != NULL && players[i].camera->player == NULL && if (players[i].camera != NULL && players[i].camera->player == NULL &&
DoCheckSightOrRange(self, players[i].camera, range, twodi)) DoCheckSightOrRange(self, players[i].camera, range, twodi, true))
{ {
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
@ -3146,42 +3147,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange)
ACTION_RETURN_STATE(jump); ACTION_RETURN_STATE(jump);
} }
//===========================================================================
//
// A_CheckRange
// Jumps if this actor is out of range of all players.
//
//===========================================================================
static bool DoCheckRange(AActor *self, AActor *camera, double range, bool twodi)
{
if (camera == NULL)
{
return false;
}
// Check distance first, since it's cheaper than checking sight.
fixedvec2 pos = camera->_f_Vec2To(self);
fixed_t dz;
fixed_t eyez = (camera->_f_Top() - (camera->_f_height()>>2)); // same eye height as P_CheckSight
if (eyez > self->_f_Top())
{
dz = self->_f_Top() - eyez;
}
else if (eyez < self->_f_Z())
{
dz = self->_f_Z() - eyez;
}
else
{
dz = 0;
}
double distance = ((double)pos.x * pos.x) + ((double)pos.y * pos.y) + (twodi == 0? ((double)dz * dz) : 0);
if (distance <= range){
// Within range
return true;
}
return false;
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange)
{ {
@ -3190,19 +3155,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange)
PARAM_STATE(jump); PARAM_STATE(jump);
PARAM_BOOL_OPT(twodi) { twodi = false; } PARAM_BOOL_OPT(twodi) { twodi = false; }
range = range * range * (double(FRACUNIT) * FRACUNIT); // no need for square roots range *= range;
for (int i = 0; i < MAXPLAYERS; ++i) for (int i = 0; i < MAXPLAYERS; ++i)
{ {
if (playeringame[i]) if (playeringame[i])
{ {
// Always check from each player. // Always check from each player.
if (DoCheckRange(self, players[i].mo, range, twodi)) if (DoCheckSightOrRange(self, players[i].mo, range, twodi, false))
{ {
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
// If a player is viewing from a non-player, check that too. // If a player is viewing from a non-player, check that too.
if (players[i].camera != NULL && players[i].camera->player == NULL && if (players[i].camera != NULL && players[i].camera->player == NULL &&
DoCheckRange(self, players[i].camera, range, twodi)) DoCheckSightOrRange(self, players[i].camera, range, twodi, false))
{ {
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
@ -3706,56 +3671,57 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
*/ */
AActor *target; AActor *target;
fixedvec3 pos; DVector3 pos;
fixed_t vx, vy, vz; DVector3 vel;
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump); PARAM_STATE (jump);
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FLOAT_OPT (range) { range = 0; } PARAM_FLOAT_OPT (range) { range = 0; }
PARAM_FLOAT_OPT (minrange) { minrange = 0; } PARAM_FLOAT_OPT (minrange) { minrange = 0; }
PARAM_DANGLE_OPT(angle) { angle = 0.; }
PARAM_DANGLE_OPT(pitch) { pitch = 0.; }
PARAM_FLOAT_OPT (offsetheight) { offsetheight = 0; }
PARAM_FLOAT_OPT (offsetwidth) { offsetwidth = 0; }
PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; }
PARAM_FLOAT_OPT (offsetforward) { offsetforward = 0; }
DAngle ang;
target = COPY_AAPTR(self, ptr_target == AAPTR_DEFAULT ? AAPTR_TARGET|AAPTR_PLAYER_GETTARGET|AAPTR_NULL : ptr_target); // no player-support by default
if (flags & CLOFF_MUL_HEIGHT)
{ {
PARAM_DANGLE_OPT(angle) { angle = 0.; } if (self->player != NULL)
PARAM_DANGLE_OPT(pitch) { pitch = 0.; }
PARAM_FIXED_OPT (offsetheight) { offsetheight = 0; }
PARAM_FIXED_OPT (offsetwidth) { offsetwidth = 0; }
PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; }
PARAM_FIXED_OPT (offsetforward) { offsetforward = 0; }
target = COPY_AAPTR(self, ptr_target == AAPTR_DEFAULT ? AAPTR_TARGET|AAPTR_PLAYER_GETTARGET|AAPTR_NULL : ptr_target); // no player-support by default
if (flags & CLOFF_MUL_HEIGHT)
{ {
if (self->player != NULL) // Synced with hitscan: self->player->mo->height is strangely conscientious about getting the right actor for player
{ offsetheight *= self->player->mo->Height * self->player->crouchfactor;
// Synced with hitscan: self->player->mo->_f_height() is strangely conscientious about getting the right actor for player
offsetheight = FixedMul(offsetheight, fixed_t(self->player->mo->_f_height() * self->player->crouchfactor));
}
else
{
offsetheight = FixedMul(offsetheight, self->_f_height());
}
} }
if (flags & CLOFF_MUL_WIDTH) else
{ {
offsetforward = FixedMul(self->_f_radius(), offsetforward); offsetheight *= self->Height;
offsetwidth = FixedMul(self->_f_radius(), offsetwidth);
} }
}
if (flags & CLOFF_MUL_WIDTH)
{
offsetforward *= self->radius;
offsetwidth *= self->radius;
}
pos = self->PosPlusZ(offsetheight - self->_f_floorclip()); pos = self->PosPlusZ(offsetheight - self->Floorclip);
if (!(flags & CLOFF_FROMBASE)) if (!(flags & CLOFF_FROMBASE))
{ // default to hitscan origin { // default to hitscan origin
// Synced with hitscan: self->_f_height() is strangely NON-conscientious about getting the right actor for player // Synced with hitscan: self->_f_height() is strangely NON-conscientious about getting the right actor for player
pos.z += (self->_f_height() >> 1); pos.Z += self->Height *0.5;
if (self->player != NULL) if (self->player != NULL)
{ {
pos.z += FLOAT2FIXED(self->player->mo->AttackZOffset * self->player->crouchfactor); pos.Z += self->player->mo->AttackZOffset * self->player->crouchfactor;
} }
else else
{ {
pos.z += 8*FRACUNIT; pos.Z += 8;
} }
} }
@ -3770,25 +3736,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
} }
} }
if (flags & CLOFF_NOAIM_HORZ)
{ {
DAngle ang; ang = self->Angles.Yaw;
if (flags & CLOFF_NOAIM_HORZ)
{
ang = self->Angles.Yaw;
}
else ang = self->AngleTo (target);
angle += ang;
double s = ang.Sin();
double c = ang.Cos();
fixedvec2 xy = self->Vec2Offset(fixed_t(offsetforward * c + offsetwidth * s), fixed_t(offsetforward * s - offsetwidth * c));
pos.x = xy.x;
pos.y = xy.y;
} }
else ang = self->AngleTo (target);
angle += ang;
double s = ang.Sin();
double c = ang.Cos();
DVector2 xy = self->Vec2Offset(offsetforward * c + offsetwidth * s, offsetforward * s - offsetwidth * c);
pos.X = xy.X;
pos.Y = xy.Y;
double xydist = self->Distance2D(target); double xydist = self->Distance2D(target);
if (flags & CLOFF_NOAIM_VERT) if (flags & CLOFF_NOAIM_VERT)
@ -3797,11 +3759,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
} }
else if (flags & CLOFF_AIM_VERT_NOOFFSET) else if (flags & CLOFF_AIM_VERT_NOOFFSET)
{ {
pitch -= VecToAngle(xydist, FIXED2FLOAT(target->_f_Z() - pos.z + offsetheight + target->_f_height() / 2)); pitch -= VecToAngle(xydist, target->Center() - pos.Z + offsetheight);
} }
else else
{ {
pitch -= VecToAngle(xydist, FIXED2FLOAT(target->_f_Z() - pos.z + target->_f_height() / 2)); pitch -= VecToAngle(xydist, target->Center());
} }
} }
else if (flags & CLOFF_ALLOWNULL) else if (flags & CLOFF_ALLOWNULL)
@ -3812,10 +3774,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
double s = angle.Sin(); double s = angle.Sin();
double c = angle.Cos(); double c = angle.Cos();
fixedvec2 xy = self->Vec2Offset(fixed_t(offsetforward * c + offsetwidth * s), fixed_t(offsetforward * s - offsetwidth * c)); DVector2 xy = self->Vec2Offset(offsetforward * c + offsetwidth * s, offsetforward * s - offsetwidth * c);
pos.x = xy.x; pos.X = xy.X;
pos.y = xy.y; pos.Y = xy.Y;
} }
else else
{ {
@ -3824,20 +3786,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
double cp = pitch.Cos(); double cp = pitch.Cos();
vx = FLOAT2FIXED(cp * angle.Cos()); vel = { cp * angle.Cos(), cp * angle.Sin(), -pitch.Sin() };
vy = FLOAT2FIXED(cp * angle.Sin());
vz = FLOAT2FIXED(-pitch.Sin());
}
/* Variable set: /* Variable set:
jump, flags, target jump, flags, target
x1,y1,z1 (trace point of origin) pos (trace point of origin)
vx,vy,vz (trace unit vector) vel (trace unit vector)
range range
*/ */
sector_t *sec = P_PointInSector(pos.x, pos.y); sector_t *sec = P_PointInSector(pos);
if (range == 0) if (range == 0)
{ {
@ -3852,7 +3811,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(pos.x, pos.y, pos.z, sec, vx, vy, vz, FLOAT2FIXED(range), ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, TRACE_PortalRestrict, Trace(pos, sec, vel, range, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, self, trace, TRACE_PortalRestrict,
CheckLOFTraceFunc, &lof_data); CheckLOFTraceFunc, &lof_data);
if (trace.HitType == TRACE_HitActor || if (trace.HitType == TRACE_HitActor ||
@ -3909,12 +3868,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump); PARAM_STATE (jump);
PARAM_ANGLE_OPT (fov) { fov = 0; } PARAM_DANGLE_OPT(fov) { fov = 0.; }
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (dist_max) { dist_max = 0; } PARAM_FLOAT_OPT (dist_max) { dist_max = 0; }
PARAM_FIXED_OPT (dist_close) { dist_close = 0; } PARAM_FLOAT_OPT (dist_close) { dist_close = 0; }
angle_t an;
AActor *target, *viewport; AActor *target, *viewport;
FTranslatedLineTarget t; FTranslatedLineTarget t;
@ -3964,14 +3922,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{ {
case JLOSF_TARGETLOS|JLOSF_FLIPFOV: case JLOSF_TARGETLOS|JLOSF_FLIPFOV:
// target makes sight check, player makes fov check; player has verified fov // target makes sight check, player makes fov check; player has verified fov
fov = 0; fov = 0.;
// fall-through // fall-through
case JLOSF_TARGETLOS: case JLOSF_TARGETLOS:
doCheckSight = !(flags & JLOSF_NOSIGHT); // The target is responsible for sight check and fov doCheckSight = !(flags & JLOSF_NOSIGHT); // The target is responsible for sight check and fov
break; break;
default: default:
// player has verified sight and fov // player has verified sight and fov
fov = 0; fov = 0.;
// fall-through // fall-through
case JLOSF_FLIPFOV: // Player has verified sight, but target must verify fov case JLOSF_FLIPFOV: // Player has verified sight, but target must verify fov
doCheckSight = false; doCheckSight = false;
@ -3989,7 +3947,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{ {
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
fixed_t distance = self->AproxDistance3D(target); double distance = self->Distance3D(target);
if (dist_max && (distance > dist_max)) if (dist_max && (distance > dist_max))
{ {
@ -4002,7 +3960,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
if (flags & JLOSF_CLOSENOFOV) if (flags & JLOSF_CLOSENOFOV)
fov = 0; fov = 0.;
if (flags & JLOSF_CLOSENOSIGHT) if (flags & JLOSF_CLOSENOSIGHT)
doCheckSight = false; doCheckSight = false;
@ -4022,11 +3980,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
else { target = viewport; viewport = self; } else { target = viewport; viewport = self; }
} }
if (fov && (fov < ANGLE_MAX)) if (fov > 0 && (fov < 360.))
{ {
an = viewport->__f_AngleTo(target) - viewport->_f_angle(); DAngle an = absangle(viewport->AngleTo(target), viewport->Angles.Yaw);
if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) if (an > (fov / 2))
{ {
ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return
} }
@ -4046,12 +4004,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump); PARAM_STATE (jump);
PARAM_ANGLE_OPT (fov) { fov = 0; } PARAM_DANGLE_OPT(fov) { fov = 0.; }
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (dist_max) { dist_max = 0; } PARAM_FLOAT_OPT (dist_max) { dist_max = 0; }
PARAM_FIXED_OPT (dist_close) { dist_close = 0; } PARAM_FLOAT_OPT (dist_close) { dist_close = 0; }
angle_t an;
AActor *target; AActor *target;
if (flags & JLOSF_CHECKMASTER) if (flags & JLOSF_CHECKMASTER)
@ -4080,7 +4037,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
fixed_t distance = self->AproxDistance3D(target); double distance = self->Distance3D(target);
if (dist_max && (distance > dist_max)) if (dist_max && (distance > dist_max))
{ {
@ -4096,17 +4053,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
if (flags & JLOSF_CLOSENOFOV) if (flags & JLOSF_CLOSENOFOV)
fov = 0; fov = 0.;
if (flags & JLOSF_CLOSENOSIGHT) if (flags & JLOSF_CLOSENOSIGHT)
doCheckSight = false; doCheckSight = false;
} }
if (fov && (fov < ANGLE_MAX)) if (fov > 0 && (fov < 360.))
{ {
an = target->__f_AngleTo(self) - target->_f_angle(); DAngle an = absangle(target->AngleTo(self), target->Angles.Yaw);
if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) if (an > (fov / 2))
{ {
ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return ACTION_RETURN_STATE(NULL); // [KS] Outside of FOV - return
} }
@ -4387,8 +4344,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings)
//=========================================================================== //===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_FaceConsolePlayer) DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_FaceConsolePlayer)
{ {
PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn_angle) { max_turn_angle = 0; }
// NOTE: It does nothing for zdoom. // NOTE: It does nothing for zdoom.
return 0; return 0;
} }
@ -5056,12 +5011,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_SOUND_OPT (sound) { sound = "weapons/pistol"; } PARAM_SOUND_OPT (sound) { sound = "weapons/pistol"; }
PARAM_FIXED_OPT (snipe) { snipe = FRACUNIT; } PARAM_FLOAT_OPT (snipe) { snipe = 1.; }
PARAM_INT_OPT (maxdamage) { maxdamage = 64; } PARAM_INT_OPT (maxdamage) { maxdamage = 64; }
PARAM_INT_OPT (blocksize) { blocksize = 128; } PARAM_INT_OPT (blocksize) { blocksize = 128; }
PARAM_INT_OPT (pointblank) { pointblank = 2; } PARAM_INT_OPT (pointblank) { pointblank = 2; }
PARAM_INT_OPT (longrange) { longrange = 4; } PARAM_INT_OPT (longrange) { longrange = 4; }
PARAM_FIXED_OPT (runspeed) { runspeed = 160*FRACUNIT; } PARAM_FLOAT_OPT (runspeed) { runspeed = 160; }
PARAM_CLASS_OPT (pufftype, AActor) { pufftype = PClass::FindActor(NAME_BulletPuff); } PARAM_CLASS_OPT (pufftype, AActor) { pufftype = PClass::FindActor(NAME_BulletPuff); }
if (!self->target) if (!self->target)
@ -5074,31 +5029,27 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
A_FaceTarget (self); A_FaceTarget (self);
// Target can dodge if it can see enemy // Target can dodge if it can see enemy
angle_t angle = self->target->__f_AngleTo(self) - self->target->_f_angle(); DAngle angle = absangle(self->target->Angles.Yaw, self->target->AngleTo(self));
angle >>= 24; bool dodge = (P_CheckSight(self->target, self) && angle < 30. * 256. / 360.); // 30 byteangles ~ 21°
bool dodge = (P_CheckSight(self->target, self) && (angle>226 || angle<30));
// Distance check is simplistic // Distance check is simplistic
fixedvec2 vec = self->_f_Vec2To(self->target); DVector2 vec = self->Vec2To(self->target);
fixed_t dx = abs (vec.x); double dx = fabs (vec.X);
fixed_t dy = abs (vec.y); double dy = fabs (vec.Y);
fixed_t dist = dx > dy ? dx : dy; double dist = dx > dy ? dx : dy;
// Some enemies are more precise // Some enemies are more precise
dist = FixedMul(dist, snipe); dist *= snipe;
// Convert distance into integer number of blocks // Convert distance into integer number of blocks
dist >>= FRACBITS; int idist = int(dist / blocksize);
dist /= blocksize;
// Now for the speed accuracy thingie // Now for the speed accuracy thingie
fixed_t speed = FixedMul(self->target->_f_velx(), self->target->_f_velx()) double speed = self->target->Vel.LengthSquared();
+ FixedMul(self->target->_f_vely(), self->target->_f_vely())
+ FixedMul(self->target->_f_velz(), self->target->_f_velz());
int hitchance = speed < runspeed ? 256 : 160; int hitchance = speed < runspeed ? 256 : 160;
// Distance accuracy (factoring dodge) // Distance accuracy (factoring dodge)
hitchance -= dist * (dodge ? 16 : 8); hitchance -= idist * (dodge ? 16 : 8);
// While we're here, we may as well do something for this: // While we're here, we may as well do something for this:
if (self->target->flags & MF_SHADOW) if (self->target->flags & MF_SHADOW)
@ -5110,9 +5061,8 @@ 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
angle = self->target->__f_AngleTo(self); DAngle angle = self->target->AngleTo(self);
DVector3 BloodPos = self->target->Vec3Angle(self->target->radius, angle, self->target->Height/2);
DVector3 BloodPos = self->target->Vec3Angle(self->target->radius, ANGLE2DBL(angle), self->target->Height/2);
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)
@ -5133,7 +5083,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, BloodPos, ANGLE2DBL(angle), ANGLE2DBL(angle), 0); P_SpawnPuff(self, pufftype, BloodPos, angle, angle, 0);
} }
} }
else if (self->target->flags3 & MF3_GHOST) else if (self->target->flags3 & MF3_GHOST)
@ -5143,7 +5093,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(BloodPos, ANGLE2DBL(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); P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self);
} }
} }
@ -5165,15 +5115,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_INT(destination_selector); PARAM_INT(destination_selector);
PARAM_FIXED_OPT(xofs) { xofs = 0; } PARAM_FLOAT_OPT(xofs) { xofs = 0; }
PARAM_FIXED_OPT(yofs) { yofs = 0; } PARAM_FLOAT_OPT(yofs) { yofs = 0; }
PARAM_FIXED_OPT(zofs) { zofs = 0; } PARAM_FLOAT_OPT(zofs) { zofs = 0; }
PARAM_ANGLE_OPT(angle) { angle = 0; } PARAM_DANGLE_OPT(angle) { angle = 0.; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_STATE_OPT(success_state) { success_state = NULL; } PARAM_STATE_OPT(success_state) { success_state = NULL; }
PARAM_FIXED_OPT(heightoffset) { heightoffset = 0; } PARAM_FLOAT_OPT(heightoffset) { heightoffset = 0; }
PARAM_FIXED_OPT(radiusoffset) { radiusoffset = 0; } PARAM_FLOAT_OPT(radiusoffset) { radiusoffset = 0; }
PARAM_ANGLE_OPT(pitch) { pitch = 0; } PARAM_DANGLE_OPT(pitch) { pitch = 0.; }
AActor *reference; AActor *reference;
@ -5374,7 +5324,7 @@ enum RadiusGiveFlags
RGF_CORPSES | RGF_MISSILES, RGF_CORPSES | RGF_MISSILES,
}; };
static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amount, fixed_t distance, int flags, PClassActor *filter, FName species, fixed_t mindist) static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amount, double distance, int flags, PClassActor *filter, FName species, double mindist)
{ {
// [MC] We only want to make an exception for missiles here. Nothing else. // [MC] We only want to make an exception for missiles here. Nothing else.
bool missilePass = !!((flags & RGF_MISSILES) && thing->flags & MF_MISSILE); bool missilePass = !!((flags & RGF_MISSILES) && thing->flags & MF_MISSILE);
@ -5448,26 +5398,22 @@ static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amo
if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass) if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass)
{ {
fixedvec3 diff = self->_f_Vec3To(thing); DVector3 diff = self->Vec3To(thing);
diff.z += (thing->_f_height() - self->_f_height()) / 2; diff.Z += thing->Height *0.5;
if (flags & RGF_CUBE) if (flags & RGF_CUBE)
{ // check if inside a cube { // check if inside a cube
double dx = fabs((double)(diff.x)); double dx = fabs(diff.X);
double dy = fabs((double)(diff.y)); double dy = fabs(diff.Y);
double dz = fabs((double)(diff.z)); double dz = fabs(diff.Z);
double dist = (double)distance; if ((dx > distance || dy > distance || dz > distance) || (mindist && (dx < mindist && dy < mindist && dz < mindist)))
double min = (double)mindist;
if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min)))
{ {
return false; return false;
} }
} }
else else
{ // check if inside a sphere { // check if inside a sphere
double distsquared = double(distance) * double(distance); double lengthsquared = diff.LengthSquared();
double minsquared = double(mindist) * double(mindist); if (lengthsquared > distance*distance || (mindist && (lengthsquared < mindist*mindist)))
double lengthsquared = DVector3(diff.x, diff.y, diff.z).LengthSquared();
if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared)))
{ {
return false; return false;
} }
@ -5504,12 +5450,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_CLASS (item, AInventory); PARAM_CLASS (item, AInventory);
PARAM_FIXED (distance); PARAM_FLOAT (distance);
PARAM_INT (flags); PARAM_INT (flags);
PARAM_INT_OPT (amount) { amount = 0; } PARAM_INT_OPT (amount) { amount = 0; }
PARAM_CLASS_OPT (filter, AActor) { filter = NULL; } PARAM_CLASS_OPT (filter, AActor) { filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } PARAM_NAME_OPT (species) { species = NAME_None; }
PARAM_FIXED_OPT (mindist) { mindist = 0; } PARAM_FLOAT_OPT (mindist) { mindist = 0; }
// We need a valid item, valid targets, and a valid range // We need a valid item, valid targets, and a valid range
if (item == NULL || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance) if (item == NULL || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance)
@ -5534,8 +5480,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
else else
{ {
FPortalGroupArray check(FPortalGroupArray::PGA_Full3d); FPortalGroupArray check(FPortalGroupArray::PGA_Full3d);
fixed_t mid = self->_f_Z() + self->_f_height() / 2; double mid = self->Center();
FMultiBlockThingsIterator it(check, self->_f_X(), self->_f_Y(), mid-distance, mid+distance, distance, false, self->Sector); FMultiBlockThingsIterator it(check, self->X(), self->Y(), mid-distance, mid+distance, distance, false, self->Sector);
FMultiBlockThingsIterator::CheckResult cres; FMultiBlockThingsIterator::CheckResult cres;
while ((it.Next(&cres))) while ((it.Next(&cres)))
@ -6356,8 +6302,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower)
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_STATE(high); PARAM_STATE(high);
PARAM_STATE(low); PARAM_STATE(low);
PARAM_FIXED_OPT(offsethigh) { offsethigh = 0; } PARAM_FLOAT_OPT(offsethigh) { offsethigh = 0; }
PARAM_FIXED_OPT(offsetlow) { offsetlow = 0; } PARAM_FLOAT_OPT(offsetlow) { offsetlow = 0; }
PARAM_BOOL_OPT(includeHeight) { includeHeight = true; } PARAM_BOOL_OPT(includeHeight) { includeHeight = true; }
PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; } PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; }
@ -6366,11 +6312,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower)
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->_f_Z() > ((includeHeight ? self->_f_height() : 0) + self->_f_Z() + offsethigh))) if ((high) && (mobj->Z() > ((includeHeight ? self->Height : 0) + self->Z() + offsethigh)))
{ {
ACTION_RETURN_STATE(high); ACTION_RETURN_STATE(high);
} }
else if ((low) && (mobj->_f_Z() + (includeHeight ? mobj->_f_height() : 0)) < (self->_f_Z() + offsetlow)) else if ((low) && (mobj->Z() + (includeHeight ? mobj->Height : 0)) < (self->Z() + offsetlow))
{ {
ACTION_RETURN_STATE(low); ACTION_RETURN_STATE(low);
} }
@ -6497,7 +6443,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_STATE(jump); PARAM_STATE(jump);
PARAM_CLASS(classname, AActor); PARAM_CLASS(classname, AActor);
PARAM_FIXED(distance); PARAM_FLOAT(distance);
PARAM_INT_OPT(count) { count = 1; } PARAM_INT_OPT(count) { count = 1; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
@ -6518,7 +6464,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
} }
int counter = 0; int counter = 0;
bool result = false; bool result = false;
fixed_t closer = distance, farther = 0, current = distance; double closer = distance, farther = 0, current = distance;
const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER));
const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST));
@ -6549,10 +6495,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
//[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use //[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use
//Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. //Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly.
//Ripped from sphere checking in A_RadiusGive (along with a number of things). //Ripped from sphere checking in A_RadiusGive (along with a number of things).
if ((ref->AproxDistance(mo) < distance && if ((ref->Distance2D(mo) < distance &&
((flags & CPXF_NOZ) || ((flags & CPXF_NOZ) ||
((ref->_f_Z() > mo->_f_Z() && ref->_f_Z() - mo->_f_Top() < distance) || ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) ||
(ref->_f_Z() <= mo->_f_Z() && mo->_f_Z() - ref->_f_Top() < distance))))) (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance)))))
{ {
if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)))
continue; continue;
@ -6656,10 +6602,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
PARAM_STATE(block) PARAM_STATE(block)
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
PARAM_FIXED_OPT(xofs) { xofs = 0; } PARAM_FLOAT_OPT(xofs) { xofs = 0; }
PARAM_FIXED_OPT(yofs) { yofs = 0; } PARAM_FLOAT_OPT(yofs) { yofs = 0; }
PARAM_FIXED_OPT(zofs) { zofs = 0; } PARAM_FLOAT_OPT(zofs) { zofs = 0; }
PARAM_ANGLE_OPT(angle) { angle = 0; } PARAM_DANGLE_OPT(angle) { angle = 0.; }
AActor *mobj = COPY_AAPTR(self, ptr); AActor *mobj = COPY_AAPTR(self, ptr);
@ -6669,28 +6615,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
#if 0 // this needs some work.
if (!(flags & CBF_ABSOLUTEANGLE)) if (!(flags & CBF_ABSOLUTEANGLE))
{ {
angle += self->angle; angle += self->Angles.Yaw;
} }
angle_t ang = angle >> ANGLETOFINESHIFT; DVector3 oldpos = mobj->Pos();
fixedvec3 oldpos = mobj->Pos(); DVector3 pos;
fixedvec3 pos;
if (flags & CBF_ABSOLUTEPOS) if (flags & CBF_ABSOLUTEPOS)
{ {
pos.x = xofs; pos = { xofs, yofs, zofs };
pos.y = yofs;
pos.z = zofs;
} }
else else
{ {
pos = mobj->Vec3Offset( double s = angle.Sin();
FixedMul(xofs, finecosine[ang]) + FixedMul(yofs, finesine[ang]), double c = angle.Cos();
FixedMul(xofs, finesine[ang]) - FixedMul(yofs, finecosine[ang]), pos = mobj->Vec3Offset(xofs * c + yofs * s, xofs * s - yofs * c, zofs);
mobj->Z() + zofs);
} }
// Next, try checking the position based on the sensitivity desired. // Next, try checking the position based on the sensitivity desired.
@ -6700,9 +6641,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
bool checker = false; bool checker = false;
if (flags & CBF_DROPOFF) if (flags & CBF_DROPOFF)
{ {
mobj->SetZ(pos.z); mobj->SetZ(pos.Z);
checker = P_CheckMove(mobj, pos.x, pos.y); checker = P_CheckMove(mobj, pos.X, pos.Y);
mobj->SetZ(oldpos.z); mobj->SetZ(oldpos.Z);
} }
else else
{ {
@ -6710,10 +6651,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
checker = P_TestMobjLocation(mobj); checker = P_TestMobjLocation(mobj);
mobj->SetOrigin(oldpos, true); mobj->SetOrigin(oldpos, true);
} }
#endif
//Nothing to block it so skip the rest.
bool checker = (flags & CBF_DROPOFF) ? P_CheckMove(mobj, mobj->_f_X(), mobj->_f_Y()) : P_TestMobjLocation(mobj);
if (checker) if (checker)
{ {
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
@ -6762,9 +6700,9 @@ enum FMDFlags
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(offset) { offset = 0; } PARAM_DANGLE_OPT(offset) { offset = 0.; }
PARAM_ANGLE_OPT(anglelimit) { anglelimit = 0; } PARAM_DANGLE_OPT(anglelimit) { anglelimit = 0.; }
PARAM_ANGLE_OPT(pitchlimit) { pitchlimit = 0; } PARAM_DANGLE_OPT(pitchlimit) { pitchlimit = 0.; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
@ -6779,78 +6717,65 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection)
//Don't bother calculating this if we don't have any horizontal movement. //Don't bother calculating this if we don't have any horizontal movement.
if (!(flags & FMDF_NOANGLE) && (mobj->Vel.X != 0 || mobj->Vel.Y != 0)) if (!(flags & FMDF_NOANGLE) && (mobj->Vel.X != 0 || mobj->Vel.Y != 0))
{ {
angle_t current = mobj->_f_angle(); DAngle current = mobj->Angles.Yaw;
const angle_t angle = R_PointToAngle2(0, 0, mobj->_f_velx(), mobj->_f_vely()); DAngle angle = mobj->Vel.Angle();
//Done because using anglelimit directly causes a signed/unsigned mismatch. //Done because using anglelimit directly causes a signed/unsigned mismatch.
const angle_t limit = anglelimit;
//Code borrowed from A_Face*. //Code borrowed from A_Face*.
if (limit > 0 && (absangle(current - angle) > limit)) if (anglelimit > 0)
{ {
if (current < angle) DAngle delta = deltaangle(current, angle);
if (fabs(delta) > anglelimit)
{ {
// [MC] This may appear backwards, but I assure any who if (delta < 0)
// reads this, it works. {
if (current - angle > ANGLE_180) current += anglelimit + offset;
current += limit + offset; }
else else if (delta > 0)
current -= limit + offset; {
mobj->SetAngle(ANGLE2DBL(current), !!(flags & FMDF_INTERPOLATE)); current -= anglelimit + offset;
}
else // huh???
{
current = angle + 180. + offset;
}
mobj->SetAngle(current, !!(flags & FMDF_INTERPOLATE));
} }
else if (current > angle)
{
if (angle - current > ANGLE_180)
current -= limit + offset;
else
current += limit + offset;
mobj->SetAngle(ANGLE2DBL(current), !!(flags & FMDF_INTERPOLATE));
}
else
mobj->SetAngle(ANGLE2DBL(angle + ANGLE_180 + offset), !!(flags & FMDF_INTERPOLATE));
} }
else else
mobj->SetAngle(ANGLE2DBL(angle + offset), !!(flags & FMDF_INTERPOLATE)); mobj->SetAngle(angle + offset, !!(flags & FMDF_INTERPOLATE));
} }
if (!(flags & FMDF_NOPITCH)) if (!(flags & FMDF_NOPITCH))
{ {
fixed_t current = mobj->_f_pitch(); DAngle current = mobj->Angles.Pitch;
const DVector2 velocity(mobj->_f_velx(), mobj->_f_vely()); const DVector2 velocity = mobj->Vel.XY();
const fixed_t pitch = R_PointToAngle2(0, 0, xs_CRoundToInt(velocity.Length()), -mobj->_f_velz()); DAngle pitch = VecToAngle(velocity.Length(), -mobj->Vel.Z);
if (pitchlimit > 0) if (pitchlimit > 0)
{ {
// [MC] angle_t for pitchlimit was required because otherwise DAngle pdelta = deltaangle(current, pitch);
// we would wind up with less than desirable turn rates that didn't
// match that of A_SetPitch. We want consistency. Also, I didn't know
// of a better way to convert from angle_t to fixed_t properly so I
// used this instead.
fixed_t plimit = fixed_t(pitchlimit);
if (abs(current - pitch) > plimit) if (fabs(pdelta) > pitchlimit)
{ {
fixed_t max = 0; if (pdelta > 0)
if (current > pitch)
{ {
max = MIN(plimit, (current - pitch)); current -= MIN(pitchlimit, pdelta);
current -= max;
} }
else //if (current > pitch) else //if (pdelta < 0)
{ {
max = MIN(plimit, (pitch - current)); current += MIN(pitchlimit, -pdelta);
current += max;
} }
mobj->SetPitch(ANGLE2DBL(current), !!(flags & FMDF_INTERPOLATE)); mobj->SetPitch(current, !!(flags & FMDF_INTERPOLATE));
} }
else else
{ {
mobj->SetPitch(ANGLE2DBL(pitch), !!(flags & FMDF_INTERPOLATE)); mobj->SetPitch(pitch, !!(flags & FMDF_INTERPOLATE));
} }
} }
else else
{ {
mobj->SetPitch(ANGLE2DBL(pitch), !!(flags & FMDF_INTERPOLATE)); mobj->SetPitch(pitch, !!(flags & FMDF_INTERPOLATE));
} }
} }
ACTION_RETURN_BOOL(true); ACTION_RETURN_BOOL(true);

View file

@ -894,8 +894,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
#define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FSoundID x = param[p].i; #define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FSoundID x = param[p].i;
#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i; #define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i;
#define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f; #define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f;
#define PARAM_FIXED_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); fixed_t x = FLOAT2FIXED(param[p].f);
#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); angle_t x = FLOAT2ANGLE(param[p].f);
#define PARAM_DANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); DAngle x = param[p].f; #define PARAM_DANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); DAngle x = param[p].f;
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s(); #define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s();
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a; #define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a;
@ -913,8 +911,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
#define PARAM_SOUND_OPT_AT(p,x) FSoundID x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = FSoundID(param[p].i); } else #define PARAM_SOUND_OPT_AT(p,x) FSoundID x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = FSoundID(param[p].i); } else
#define PARAM_COLOR_OPT_AT(p,x) PalEntry x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x.d = param[p].i; } else #define PARAM_COLOR_OPT_AT(p,x) PalEntry x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x.d = param[p].i; } else
#define PARAM_FLOAT_OPT_AT(p,x) double x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else #define PARAM_FLOAT_OPT_AT(p,x) double x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else
#define PARAM_FIXED_OPT_AT(p,x) fixed_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = FLOAT2FIXED(param[p].f); } else
#define PARAM_ANGLE_OPT_AT(p,x) angle_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = FLOAT2ANGLE(param[p].f); } else
#define PARAM_DANGLE_OPT_AT(p,x) DAngle x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else #define PARAM_DANGLE_OPT_AT(p,x) DAngle x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else
#define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else #define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else
#define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else #define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else
@ -931,8 +927,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
#define PARAM_SOUND(x) ++paramnum; PARAM_SOUND_AT(paramnum,x) #define PARAM_SOUND(x) ++paramnum; PARAM_SOUND_AT(paramnum,x)
#define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x) #define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x)
#define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x) #define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x)
#define PARAM_FIXED(x) ++paramnum; PARAM_FIXED_AT(paramnum,x)
#define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x)
#define PARAM_DANGLE(x) ++paramnum; PARAM_DANGLE_AT(paramnum,x) #define PARAM_DANGLE(x) ++paramnum; PARAM_DANGLE_AT(paramnum,x)
#define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x) #define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x)
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x) #define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
@ -946,8 +940,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
#define PARAM_SOUND_OPT(x) ++paramnum; PARAM_SOUND_OPT_AT(paramnum,x) #define PARAM_SOUND_OPT(x) ++paramnum; PARAM_SOUND_OPT_AT(paramnum,x)
#define PARAM_COLOR_OPT(x) ++paramnum; PARAM_COLOR_OPT_AT(paramnum,x) #define PARAM_COLOR_OPT(x) ++paramnum; PARAM_COLOR_OPT_AT(paramnum,x)
#define PARAM_FLOAT_OPT(x) ++paramnum; PARAM_FLOAT_OPT_AT(paramnum,x) #define PARAM_FLOAT_OPT(x) ++paramnum; PARAM_FLOAT_OPT_AT(paramnum,x)
#define PARAM_FIXED_OPT(x) ++paramnum; PARAM_FIXED_OPT_AT(paramnum,x)
#define PARAM_ANGLE_OPT(x) ++paramnum; PARAM_ANGLE_OPT_AT(paramnum,x)
#define PARAM_DANGLE_OPT(x) ++paramnum; PARAM_DANGLE_OPT_AT(paramnum,x) #define PARAM_DANGLE_OPT(x) ++paramnum; PARAM_DANGLE_OPT_AT(paramnum,x)
#define PARAM_STRING_OPT(x) ++paramnum; PARAM_STRING_OPT_AT(paramnum,x) #define PARAM_STRING_OPT(x) ++paramnum; PARAM_STRING_OPT_AT(paramnum,x)
#define PARAM_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x) #define PARAM_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x)