- 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)
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)
{

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();
@ -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->accz = accelz;
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);
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_RunEffects (void);

View file

@ -1165,23 +1165,23 @@ void P_RandomChaseDir (AActor *actor)
bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams *params)
{
fixed_t maxdist;
fixed_t mindist;
angle_t fov;
double maxdist;
double mindist;
DAngle fov;
if (params != NULL)
{
maxdist = params->maxdist;
mindist = params->mindist;
fov = params->fov;
maxdist = params->maxDist;
mindist = params->minDist;
fov = params->Fov;
}
else
{
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)
return false; // [KS] too far
@ -1189,15 +1189,15 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
if (mindist && dist < mindist)
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
// [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
}
}
@ -1887,15 +1887,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (minseedist) { minseedist = 0; }
PARAM_FIXED_OPT (maxseedist) { maxseedist = 0; }
PARAM_FIXED_OPT (maxheardist) { maxheardist = 0; }
PARAM_FLOAT_OPT (fov_f) { fov_f = 0; }
PARAM_FLOAT_OPT (minseedist) { minseedist = 0; }
PARAM_FLOAT_OPT (maxseedist) { maxseedist = 0; }
PARAM_FLOAT_OPT (maxheardist) { maxheardist = 0; }
PARAM_DANGLE_OPT (fov) { fov = 0.; }
PARAM_STATE_OPT (seestate) { seestate = NULL; }
AActor *targ = NULL; // Shuts up gcc
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 };
if (self->flags5 & MF5_INCONVERSATION)
@ -2817,7 +2817,7 @@ enum FAF_Flags
FAF_TOP = 4,
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)
return;
@ -2830,12 +2830,7 @@ void A_Face (AActor *self, AActor *other, angle_t _max_turn, angle_t _max_pitch,
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 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.
@ -2882,7 +2877,7 @@ void A_Face (AActor *self, AActor *other, angle_t _max_turn, angle_t _max_pitch,
if (flags & FAF_TOP)
target_z = other->Top() + other->GetBobOffset();
target_z += FIXED2FLOAT(z_add);
target_z += z_add;
double dist_z = target_z - source_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)
{
PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; }
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; }
PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0; }
PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0; }
PARAM_DANGLE_OPT(max_turn) { max_turn = 0.; }
PARAM_DANGLE_OPT(max_pitch) { max_pitch = 270.; }
PARAM_DANGLE_OPT(ang_offset) { ang_offset = 0.; }
PARAM_DANGLE_OPT(pitch_offset) { pitch_offset = 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);
return 0;
@ -2940,12 +2935,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster)
{
PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; }
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; }
PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0; }
PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0; }
PARAM_DANGLE_OPT(max_turn) { max_turn = 0.; }
PARAM_DANGLE_OPT(max_pitch) { max_pitch = 270.; }
PARAM_DANGLE_OPT(ang_offset) { ang_offset = 0.; }
PARAM_DANGLE_OPT(pitch_offset) { pitch_offset = 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);
return 0;
@ -2954,12 +2949,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer)
{
PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; }
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; }
PARAM_ANGLE_OPT(ang_offset) { ang_offset = 0; }
PARAM_ANGLE_OPT(pitch_offset) { pitch_offset = 0; }
PARAM_DANGLE_OPT(max_turn) { max_turn = 0.; }
PARAM_DANGLE_OPT(max_pitch) { max_pitch = 270.; }
PARAM_DANGLE_OPT(ang_offset) { ang_offset = 0.; }
PARAM_DANGLE_OPT(pitch_offset) { pitch_offset = 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);
return 0;

View file

@ -38,10 +38,10 @@ enum LO_Flags
struct FLookExParams
{
angle_t fov;
fixed_t mindist;
fixed_t maxdist;
fixed_t maxheardist;
DAngle Fov;
double minDist;
double maxDist;
double maxHeardist;
int flags;
FState *seestate;
};
@ -78,7 +78,7 @@ void A_BossDeath(AActor *self);
void A_Wander(AActor *self, int flags = 0);
void A_Chase(VMFrameStack *stack, AActor *self);
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_SinkMobj (AActor *, double speed);

View file

@ -221,7 +221,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser);
bool P_Thing_CanRaise(AActor *thing);
PClassActor *P_GetSpawnableType(int spawnnum);
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
{
@ -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);
}
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);
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)

View file

@ -356,6 +356,10 @@ public:
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, 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);
void Reset();
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 boby = float(player->bob * Rangey);
switch (level.levelnum)//bobstyle)
switch (bobstyle)
{
case AWeapon::BobNormal:
*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)
{
@ -679,32 +679,33 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
caller = temp;
}
fixedvec3 old = caller->_f_Pos();
DVector3 old = caller->Pos();
int oldpgroup = caller->Sector->PortalGroup;
zofs += FixedMul(reference->_f_height(), heightoffset);
zofs += reference->Height * heightoffset;
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 angle_t fineangle = angle >> ANGLETOFINESHIFT;
const double rad = radiusoffset * reference->radius;
const double s = angle.Sin();
const double c = angle.Cos();
if (!(flags & WARPF_ABSOLUTEPOSITION))
{
if (!(flags & WARPF_ABSOLUTEOFFSET))
{
fixed_t xofs1 = xofs;
double xofs1 = xofs;
// (borrowed from A_SpawnItemEx, assumed workable)
// in relative mode negative y values mean 'left' and positive ones mean 'right'
// This is the inverse orientation of the absolute mode!
xofs = FixedMul(xofs1, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]);
yofs = FixedMul(xofs1, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]);
xofs = xofs1 * c + yofs * s;
yofs = xofs1 * s - yofs * c;
}
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
// assigning position again with.
// extra unlink, link and environment calculation
caller->SetOrigin(reference->Vec3Offset(
xofs + FixedMul(rad, finecosine[fineangle]),
yofs + FixedMul(rad, finesine[fineangle]),
0), true);
caller->_f_SetZ(caller->_f_floorz() + zofs);
caller->SetOrigin(reference->Vec3Offset(xofs + rad * c, yofs + rad * s, 0.), true);
// The two-step process is important.
caller->SetZ(caller->floorz + zofs);
}
else
{
caller->SetOrigin(reference->Vec3Offset(
xofs + FixedMul(rad, finecosine[fineangle]),
yofs + FixedMul(rad, finesine[fineangle]),
zofs), true);
caller->SetOrigin(reference->Vec3Offset(xofs + rad * c, yofs + rad * s, zofs), true);
}
}
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)
{
caller->SetOrigin(xofs + FixedMul(rad, finecosine[fineangle]), yofs + FixedMul(rad, finesine[fineangle]), zofs, true);
caller->_f_SetZ(caller->_f_floorz() + zofs);
}
else
{
caller->SetOrigin(xofs + FixedMul(rad, finecosine[fineangle]), yofs + FixedMul(rad, finesine[fineangle]), zofs, true);
caller->SetZ(caller->floorz + zofs);
}
}
@ -748,13 +740,13 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
}
else
{
caller->Angles.Yaw = ANGLE2DBL(angle);
caller->Angles.Yaw = angle;
if (flags & WARPF_COPYPITCH)
caller->SetPitch(reference->Angles.Pitch, false);
if (pitch)
caller->SetPitch(caller->Angles.Pitch + ANGLE2DBL(pitch), false);
if (pitch != 0)
caller->SetPitch(caller->Angles.Pitch + pitch, false);
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();
}
#if 0 // needs fixing
// this is no fun with line portals
if (flags & WARPF_WARPINTERPOLATION)
{
@ -789,9 +782,11 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
{
caller->ClearInterpolation();
}
#endif
if ((flags & WARPF_BOB) && (reference->flags2 & MF2_FLOATBOB))
{
caller->_f_AddZ(reference->_f_GetBobOffset());
caller->AddZ(reference->GetBobOffset());
}
}
return true;

View file

@ -1893,7 +1893,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
PARAM_FLOAT_OPT (spawnofs_z) { spawnofs_z = 0; }
PARAM_INT_OPT (SpiralOffset) { SpiralOffset = 270; }
if (range == 0) range = 8192*FRACUNIT;
if (range == 0) range = 8192.;
if (sparsity == 0) sparsity = 1;
FTranslatedLineTarget t;
@ -2254,7 +2254,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
}
if (flags & SIXF_TELEFRAG)
{
P_TeleportMove(mo, mo->_f_Pos(), true);
P_TeleportMove(mo, mo->Pos(), true);
// This is needed to ensure consistent behavior.
// Otherwise it will only spawn if nothing gets telefragged
flags |= SIXF_NOCHECKPOSITION;
@ -2393,7 +2393,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
{
PARAM_ACTION_PROLOGUE;
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_BOOL_OPT (useammo) { useammo = true; }
PARAM_BOOL_OPT (transfer_translation) { transfer_translation = false; }
@ -2412,7 +2412,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
if (distance == 0)
{
// 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())
@ -2531,9 +2531,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
{
PARAM_ACTION_PROLOGUE;
PARAM_CLASS (missile, AActor);
PARAM_FIXED_OPT (zheight) { zheight = 0; }
PARAM_FLOAT_OPT (zheight) { zheight = 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; }
if (missile == NULL)
@ -2995,51 +2995,51 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle)
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_INT_OPT (lifetime) { lifetime = 35; }
PARAM_INT_OPT (size) { size = 1; }
PARAM_ANGLE_OPT (angle) { angle = 0; }
PARAM_FIXED_OPT (xoff) { xoff = 0; }
PARAM_FIXED_OPT (yoff) { yoff = 0; }
PARAM_FIXED_OPT (zoff) { zoff = 0; }
PARAM_FIXED_OPT (xvel) { xvel = 0; }
PARAM_FIXED_OPT (yvel) { yvel = 0; }
PARAM_FIXED_OPT (zvel) { zvel = 0; }
PARAM_FIXED_OPT (accelx) { accelx = 0; }
PARAM_FIXED_OPT (accely) { accely = 0; }
PARAM_FIXED_OPT (accelz) { accelz = 0; }
PARAM_FIXED_OPT (startalphaf) { startalphaf = FRACUNIT; }
PARAM_FIXED_OPT (fadestepf) { fadestepf = -FRACUNIT; }
PARAM_DANGLE_OPT(angle) { angle = 0.; }
PARAM_FLOAT_OPT (xoff) { xoff = 0; }
PARAM_FLOAT_OPT (yoff) { yoff = 0; }
PARAM_FLOAT_OPT (zoff) { zoff = 0; }
PARAM_FLOAT_OPT (xvel) { xvel = 0; }
PARAM_FLOAT_OPT (yvel) { yvel = 0; }
PARAM_FLOAT_OPT (zvel) { zvel = 0; }
PARAM_FLOAT_OPT (accelx) { accelx = 0; }
PARAM_FLOAT_OPT (accely) { accely = 0; }
PARAM_FLOAT_OPT (accelz) { accelz = 0; }
PARAM_FLOAT_OPT (startalpha) { startalpha = 1.; }
PARAM_FLOAT_OPT (fadestep) { fadestep = -1.; }
BYTE startalpha = (BYTE)(clamp(startalphaf, 0, FRACUNIT) * 255 / FRACUNIT);
int fadestep = fadestepf < 0 ? -1 : clamp(fadestepf, 0, FRACUNIT) * 255 / FRACUNIT;
lifetime = clamp<int>(lifetime, 0, 255); // Clamp to byte
startalpha = clamp(startalpha, 0., 1.);
if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.);
size = clamp<int>(size, 0, 65535); // Clamp to word
if (lifetime != 0)
{
const angle_t ang = (angle + ((flags & SPF_RELANG) ? self->_f_angle() : 0)) >> ANGLETOFINESHIFT;
fixedvec3 pos;
if (flags & SPF_RELANG) angle += self->Angles.Yaw;
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.
if (flags & SPF_RELPOS)
{
// in relative mode negative y values mean 'left' and positive ones mean 'right'
// This is the inverse orientation of the absolute mode!
const fixed_t xof1 = xoff;
xoff = FixedMul(xof1, finecosine[ang]) + FixedMul(yoff, finesine[ang]);
yoff = FixedMul(xof1, finesine[ang]) - FixedMul(yoff, finecosine[ang]);
pos.X = xoff * c + yoff * s;
pos.Y = xoff * s - yoff * c;
}
if (flags & SPF_RELVEL)
{
const fixed_t newxvel = FixedMul(xvel, finecosine[ang]) + FixedMul(yvel, finesine[ang]);
yvel = FixedMul(xvel, finesine[ang]) - FixedMul(yvel, finecosine[ang]);
xvel = newxvel;
vel.X = xvel * c + yvel * s;
vel.Y = xvel * s - yvel * c;
}
if (flags & SPF_RELACCEL)
{
fixed_t newaccelx = FixedMul(accelx, finecosine[ang]) + FixedMul(accely, finesine[ang]);
accely = FixedMul(accelx, finesine[ang]) - FixedMul(accely, finecosine[ang]);
accelx = newaccelx;
acc.X = accelx * c + accely * s;
acc.Y = accelx * s - accely * c;
}
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;
}
@ -3082,36 +3082,37 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight)
// 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)
{
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())
DVector2 pos = camera->Vec2To(self);
double dz;
double eyez = camera->Center();
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
{
dz = 0;
}
double distance = ((double)pos.x * pos.x) + ((double)pos.y * pos.y) + (twodi == 0? ((double)dz * dz) : 0);
if (distance <= range){
double distance = DVector3(pos, twodi? 0. : dz).LengthSquared();
if (distance <= range*range)
{
// Within range
return true;
}
// Now check LOS.
if (P_CheckSight(camera, self, SF_IGNOREVISIBILITY))
if (checksight && P_CheckSight(camera, self, SF_IGNOREVISIBILITY))
{ // Visible
return true;
}
@ -3125,19 +3126,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange)
PARAM_STATE(jump);
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)
{
if (playeringame[i])
{
// 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);
}
// If a player is viewing from a non-player, check that too.
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);
}
@ -3146,42 +3147,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange)
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)
{
@ -3190,19 +3155,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckRange)
PARAM_STATE(jump);
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)
{
if (playeringame[i])
{
// 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);
}
// If a player is viewing from a non-player, check that too.
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);
}
@ -3706,21 +3671,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
*/
AActor *target;
fixedvec3 pos;
fixed_t vx, vy, vz;
DVector3 pos;
DVector3 vel;
PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump);
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FLOAT_OPT (range) { range = 0; }
PARAM_FLOAT_OPT (minrange) { minrange = 0; }
{
PARAM_DANGLE_OPT(angle) { angle = 0.; }
PARAM_DANGLE_OPT(pitch) { pitch = 0.; }
PARAM_FIXED_OPT (offsetheight) { offsetheight = 0; }
PARAM_FIXED_OPT (offsetwidth) { offsetwidth = 0; }
PARAM_FLOAT_OPT (offsetheight) { offsetheight = 0; }
PARAM_FLOAT_OPT (offsetwidth) { offsetwidth = 0; }
PARAM_INT_OPT (ptr_target) { ptr_target = AAPTR_DEFAULT; }
PARAM_FIXED_OPT (offsetforward) { offsetforward = 0; }
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
@ -3728,34 +3694,34 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
{
if (self->player != NULL)
{
// 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));
// 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;
}
else
{
offsetheight = FixedMul(offsetheight, self->_f_height());
offsetheight *= self->Height;
}
}
if (flags & CLOFF_MUL_WIDTH)
{
offsetforward = FixedMul(self->_f_radius(), offsetforward);
offsetwidth = FixedMul(self->_f_radius(), offsetwidth);
offsetforward *= self->radius;
offsetwidth *= self->radius;
}
pos = self->PosPlusZ(offsetheight - self->_f_floorclip());
pos = self->PosPlusZ(offsetheight - self->Floorclip);
if (!(flags & CLOFF_FROMBASE))
{ // default to hitscan origin
// 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)
{
pos.z += FLOAT2FIXED(self->player->mo->AttackZOffset * self->player->crouchfactor);
pos.Z += self->player->mo->AttackZOffset * self->player->crouchfactor;
}
else
{
pos.z += 8*FRACUNIT;
pos.Z += 8;
}
}
@ -3770,9 +3736,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
}
}
{
DAngle ang;
if (flags & CLOFF_NOAIM_HORZ)
{
ang = self->Angles.Yaw;
@ -3784,11 +3747,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
double s = ang.Sin();
double c = ang.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.y = xy.y;
}
pos.X = xy.X;
pos.Y = xy.Y;
double xydist = self->Distance2D(target);
if (flags & CLOFF_NOAIM_VERT)
@ -3797,11 +3759,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
}
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
{
pitch -= VecToAngle(xydist, FIXED2FLOAT(target->_f_Z() - pos.z + target->_f_height() / 2));
pitch -= VecToAngle(xydist, target->Center());
}
}
else if (flags & CLOFF_ALLOWNULL)
@ -3812,10 +3774,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
double s = angle.Sin();
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.y = xy.y;
pos.X = xy.X;
pos.Y = xy.Y;
}
else
{
@ -3824,20 +3786,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
double cp = pitch.Cos();
vx = FLOAT2FIXED(cp * angle.Cos());
vy = FLOAT2FIXED(cp * angle.Sin());
vz = FLOAT2FIXED(-pitch.Sin());
}
vel = { cp * angle.Cos(), cp * angle.Sin(), -pitch.Sin() };
/* Variable set:
jump, flags, target
x1,y1,z1 (trace point of origin)
vx,vy,vz (trace unit vector)
pos (trace point of origin)
vel (trace unit vector)
range
*/
sector_t *sec = P_PointInSector(pos.x, pos.y);
sector_t *sec = P_PointInSector(pos);
if (range == 0)
{
@ -3852,7 +3811,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
lof_data.Flags = flags;
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);
if (trace.HitType == TRACE_HitActor ||
@ -3909,12 +3868,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{
PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump);
PARAM_ANGLE_OPT (fov) { fov = 0; }
PARAM_DANGLE_OPT(fov) { fov = 0.; }
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (dist_max) { dist_max = 0; }
PARAM_FIXED_OPT (dist_close) { dist_close = 0; }
PARAM_FLOAT_OPT (dist_max) { dist_max = 0; }
PARAM_FLOAT_OPT (dist_close) { dist_close = 0; }
angle_t an;
AActor *target, *viewport;
FTranslatedLineTarget t;
@ -3964,14 +3922,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{
case JLOSF_TARGETLOS|JLOSF_FLIPFOV:
// target makes sight check, player makes fov check; player has verified fov
fov = 0;
fov = 0.;
// fall-through
case JLOSF_TARGETLOS:
doCheckSight = !(flags & JLOSF_NOSIGHT); // The target is responsible for sight check and fov
break;
default:
// player has verified sight and fov
fov = 0;
fov = 0.;
// fall-through
case JLOSF_FLIPFOV: // Player has verified sight, but target must verify fov
doCheckSight = false;
@ -3989,7 +3947,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{
ACTION_RETURN_STATE(NULL);
}
fixed_t distance = self->AproxDistance3D(target);
double distance = self->Distance3D(target);
if (dist_max && (distance > dist_max))
{
@ -4002,7 +3960,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
ACTION_RETURN_STATE(NULL);
}
if (flags & JLOSF_CLOSENOFOV)
fov = 0;
fov = 0.;
if (flags & JLOSF_CLOSENOSIGHT)
doCheckSight = false;
@ -4022,11 +3980,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
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
}
@ -4046,12 +4004,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
{
PARAM_ACTION_PROLOGUE;
PARAM_STATE (jump);
PARAM_ANGLE_OPT (fov) { fov = 0; }
PARAM_DANGLE_OPT(fov) { fov = 0.; }
PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (dist_max) { dist_max = 0; }
PARAM_FIXED_OPT (dist_close) { dist_close = 0; }
PARAM_FLOAT_OPT (dist_max) { dist_max = 0; }
PARAM_FLOAT_OPT (dist_close) { dist_close = 0; }
angle_t an;
AActor *target;
if (flags & JLOSF_CHECKMASTER)
@ -4080,7 +4037,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
ACTION_RETURN_STATE(NULL);
}
fixed_t distance = self->AproxDistance3D(target);
double distance = self->Distance3D(target);
if (dist_max && (distance > dist_max))
{
@ -4096,17 +4053,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
ACTION_RETURN_STATE(NULL);
}
if (flags & JLOSF_CLOSENOFOV)
fov = 0;
fov = 0.;
if (flags & JLOSF_CLOSENOSIGHT)
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
}
@ -4387,8 +4344,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings)
//===========================================================================
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.
return 0;
}
@ -5056,12 +5011,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT (flags) { flags = 0; }
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 (blocksize) { blocksize = 128; }
PARAM_INT_OPT (pointblank) { pointblank = 2; }
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); }
if (!self->target)
@ -5074,31 +5029,27 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
A_FaceTarget (self);
// Target can dodge if it can see enemy
angle_t angle = self->target->__f_AngleTo(self) - self->target->_f_angle();
angle >>= 24;
bool dodge = (P_CheckSight(self->target, self) && (angle>226 || angle<30));
DAngle angle = absangle(self->target->Angles.Yaw, self->target->AngleTo(self));
bool dodge = (P_CheckSight(self->target, self) && angle < 30. * 256. / 360.); // 30 byteangles ~ 21°
// Distance check is simplistic
fixedvec2 vec = self->_f_Vec2To(self->target);
fixed_t dx = abs (vec.x);
fixed_t dy = abs (vec.y);
fixed_t dist = dx > dy ? dx : dy;
DVector2 vec = self->Vec2To(self->target);
double dx = fabs (vec.X);
double dy = fabs (vec.Y);
double dist = dx > dy ? dx : dy;
// Some enemies are more precise
dist = FixedMul(dist, snipe);
dist *= snipe;
// Convert distance into integer number of blocks
dist >>= FRACBITS;
dist /= blocksize;
int idist = int(dist / blocksize);
// Now for the speed accuracy thingie
fixed_t speed = FixedMul(self->target->_f_velx(), self->target->_f_velx())
+ FixedMul(self->target->_f_vely(), self->target->_f_vely())
+ FixedMul(self->target->_f_velz(), self->target->_f_velz());
double speed = self->target->Vel.LengthSquared();
int hitchance = speed < runspeed ? 256 : 160;
// 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:
if (self->target->flags & MF_SHADOW)
@ -5110,9 +5061,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
if (pr_cabullet() < hitchance)
{
// Compute position for spawning blood/puff
angle = self->target->__f_AngleTo(self);
DVector3 BloodPos = self->target->Vec3Angle(self->target->radius, ANGLE2DBL(angle), self->target->Height/2);
DAngle angle = self->target->AngleTo(self);
DVector3 BloodPos = self->target->Vec3Angle(self->target->radius, angle, self->target->Height/2);
int damage = flags & WAF_NORANDOM ? maxdamage : (1 + (pr_cabullet() % maxdamage));
if (dist >= pointblank)
@ -5133,7 +5083,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
if ((0 && dpuff->flags3 & MF3_PUFFONACTORS) || !spawnblood)
{
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)
@ -5143,7 +5093,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
int newdam = P_DamageMobj(self->target, self, self, damage, mod, DMG_THRUSTLESS);
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);
}
}
@ -5165,15 +5115,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT(destination_selector);
PARAM_FIXED_OPT(xofs) { xofs = 0; }
PARAM_FIXED_OPT(yofs) { yofs = 0; }
PARAM_FIXED_OPT(zofs) { zofs = 0; }
PARAM_ANGLE_OPT(angle) { angle = 0; }
PARAM_FLOAT_OPT(xofs) { xofs = 0; }
PARAM_FLOAT_OPT(yofs) { yofs = 0; }
PARAM_FLOAT_OPT(zofs) { zofs = 0; }
PARAM_DANGLE_OPT(angle) { angle = 0.; }
PARAM_INT_OPT(flags) { flags = 0; }
PARAM_STATE_OPT(success_state) { success_state = NULL; }
PARAM_FIXED_OPT(heightoffset) { heightoffset = 0; }
PARAM_FIXED_OPT(radiusoffset) { radiusoffset = 0; }
PARAM_ANGLE_OPT(pitch) { pitch = 0; }
PARAM_FLOAT_OPT(heightoffset) { heightoffset = 0; }
PARAM_FLOAT_OPT(radiusoffset) { radiusoffset = 0; }
PARAM_DANGLE_OPT(pitch) { pitch = 0.; }
AActor *reference;
@ -5374,7 +5324,7 @@ enum RadiusGiveFlags
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.
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)
{
fixedvec3 diff = self->_f_Vec3To(thing);
diff.z += (thing->_f_height() - self->_f_height()) / 2;
DVector3 diff = self->Vec3To(thing);
diff.Z += thing->Height *0.5;
if (flags & RGF_CUBE)
{ // check if inside a cube
double dx = fabs((double)(diff.x));
double dy = fabs((double)(diff.y));
double dz = fabs((double)(diff.z));
double dist = (double)distance;
double min = (double)mindist;
if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min)))
double dx = fabs(diff.X);
double dy = fabs(diff.Y);
double dz = fabs(diff.Z);
if ((dx > distance || dy > distance || dz > distance) || (mindist && (dx < mindist && dy < mindist && dz < mindist)))
{
return false;
}
}
else
{ // check if inside a sphere
double distsquared = double(distance) * double(distance);
double minsquared = double(mindist) * double(mindist);
double lengthsquared = DVector3(diff.x, diff.y, diff.z).LengthSquared();
if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared)))
double lengthsquared = diff.LengthSquared();
if (lengthsquared > distance*distance || (mindist && (lengthsquared < mindist*mindist)))
{
return false;
}
@ -5504,12 +5450,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{
PARAM_ACTION_PROLOGUE;
PARAM_CLASS (item, AInventory);
PARAM_FIXED (distance);
PARAM_FLOAT (distance);
PARAM_INT (flags);
PARAM_INT_OPT (amount) { amount = 0; }
PARAM_CLASS_OPT (filter, AActor) { filter = NULL; }
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
if (item == NULL || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance)
@ -5534,8 +5480,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
else
{
FPortalGroupArray check(FPortalGroupArray::PGA_Full3d);
fixed_t mid = self->_f_Z() + self->_f_height() / 2;
FMultiBlockThingsIterator it(check, self->_f_X(), self->_f_Y(), mid-distance, mid+distance, distance, false, self->Sector);
double mid = self->Center();
FMultiBlockThingsIterator it(check, self->X(), self->Y(), mid-distance, mid+distance, distance, false, self->Sector);
FMultiBlockThingsIterator::CheckResult cres;
while ((it.Next(&cres)))
@ -6356,8 +6302,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower)
PARAM_ACTION_PROLOGUE;
PARAM_STATE(high);
PARAM_STATE(low);
PARAM_FIXED_OPT(offsethigh) { offsethigh = 0; }
PARAM_FIXED_OPT(offsetlow) { offsetlow = 0; }
PARAM_FLOAT_OPT(offsethigh) { offsethigh = 0; }
PARAM_FLOAT_OPT(offsetlow) { offsetlow = 0; }
PARAM_BOOL_OPT(includeHeight) { includeHeight = true; }
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 ((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);
}
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);
}
@ -6497,7 +6443,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
PARAM_ACTION_PROLOGUE;
PARAM_STATE(jump);
PARAM_CLASS(classname, AActor);
PARAM_FIXED(distance);
PARAM_FLOAT(distance);
PARAM_INT_OPT(count) { count = 1; }
PARAM_INT_OPT(flags) { flags = 0; }
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
@ -6518,7 +6464,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
}
int counter = 0;
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 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
//Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly.
//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) ||
((ref->_f_Z() > mo->_f_Z() && ref->_f_Z() - mo->_f_Top() < distance) ||
(ref->_f_Z() <= mo->_f_Z() && mo->_f_Z() - ref->_f_Top() < distance)))))
((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) ||
(ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance)))))
{
if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)))
continue;
@ -6656,10 +6602,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
PARAM_STATE(block)
PARAM_INT_OPT(flags) { flags = 0; }
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
PARAM_FIXED_OPT(xofs) { xofs = 0; }
PARAM_FIXED_OPT(yofs) { yofs = 0; }
PARAM_FIXED_OPT(zofs) { zofs = 0; }
PARAM_ANGLE_OPT(angle) { angle = 0; }
PARAM_FLOAT_OPT(xofs) { xofs = 0; }
PARAM_FLOAT_OPT(yofs) { yofs = 0; }
PARAM_FLOAT_OPT(zofs) { zofs = 0; }
PARAM_DANGLE_OPT(angle) { angle = 0.; }
AActor *mobj = COPY_AAPTR(self, ptr);
@ -6669,28 +6615,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
ACTION_RETURN_STATE(NULL);
}
#if 0 // this needs some work.
if (!(flags & CBF_ABSOLUTEANGLE))
{
angle += self->angle;
angle += self->Angles.Yaw;
}
angle_t ang = angle >> ANGLETOFINESHIFT;
fixedvec3 oldpos = mobj->Pos();
fixedvec3 pos;
DVector3 oldpos = mobj->Pos();
DVector3 pos;
if (flags & CBF_ABSOLUTEPOS)
{
pos.x = xofs;
pos.y = yofs;
pos.z = zofs;
pos = { xofs, yofs, zofs };
}
else
{
pos = mobj->Vec3Offset(
FixedMul(xofs, finecosine[ang]) + FixedMul(yofs, finesine[ang]),
FixedMul(xofs, finesine[ang]) - FixedMul(yofs, finecosine[ang]),
mobj->Z() + zofs);
double s = angle.Sin();
double c = angle.Cos();
pos = mobj->Vec3Offset(xofs * c + yofs * s, xofs * s - yofs * c, zofs);
}
// Next, try checking the position based on the sensitivity desired.
@ -6700,9 +6641,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
bool checker = false;
if (flags & CBF_DROPOFF)
{
mobj->SetZ(pos.z);
checker = P_CheckMove(mobj, pos.x, pos.y);
mobj->SetZ(oldpos.z);
mobj->SetZ(pos.Z);
checker = P_CheckMove(mobj, pos.X, pos.Y);
mobj->SetZ(oldpos.Z);
}
else
{
@ -6710,10 +6651,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock)
checker = P_TestMobjLocation(mobj);
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)
{
ACTION_RETURN_STATE(NULL);
@ -6762,9 +6700,9 @@ enum FMDFlags
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection)
{
PARAM_ACTION_PROLOGUE;
PARAM_ANGLE_OPT(offset) { offset = 0; }
PARAM_ANGLE_OPT(anglelimit) { anglelimit = 0; }
PARAM_ANGLE_OPT(pitchlimit) { pitchlimit = 0; }
PARAM_DANGLE_OPT(offset) { offset = 0.; }
PARAM_DANGLE_OPT(anglelimit) { anglelimit = 0.; }
PARAM_DANGLE_OPT(pitchlimit) { pitchlimit = 0.; }
PARAM_INT_OPT(flags) { flags = 0; }
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.
if (!(flags & FMDF_NOANGLE) && (mobj->Vel.X != 0 || mobj->Vel.Y != 0))
{
angle_t current = mobj->_f_angle();
const angle_t angle = R_PointToAngle2(0, 0, mobj->_f_velx(), mobj->_f_vely());
DAngle current = mobj->Angles.Yaw;
DAngle angle = mobj->Vel.Angle();
//Done because using anglelimit directly causes a signed/unsigned mismatch.
const angle_t limit = anglelimit;
//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
// reads this, it works.
if (current - angle > ANGLE_180)
current += limit + offset;
else
current -= limit + offset;
mobj->SetAngle(ANGLE2DBL(current), !!(flags & FMDF_INTERPOLATE));
if (delta < 0)
{
current += anglelimit + offset;
}
else if (current > angle)
else if (delta > 0)
{
if (angle - current > ANGLE_180)
current -= limit + offset;
else
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
mobj->SetAngle(ANGLE2DBL(angle + ANGLE_180 + offset), !!(flags & FMDF_INTERPOLATE));
}
else
mobj->SetAngle(ANGLE2DBL(angle + offset), !!(flags & FMDF_INTERPOLATE));
mobj->SetAngle(angle + offset, !!(flags & FMDF_INTERPOLATE));
}
if (!(flags & FMDF_NOPITCH))
{
fixed_t current = mobj->_f_pitch();
const DVector2 velocity(mobj->_f_velx(), mobj->_f_vely());
const fixed_t pitch = R_PointToAngle2(0, 0, xs_CRoundToInt(velocity.Length()), -mobj->_f_velz());
DAngle current = mobj->Angles.Pitch;
const DVector2 velocity = mobj->Vel.XY();
DAngle pitch = VecToAngle(velocity.Length(), -mobj->Vel.Z);
if (pitchlimit > 0)
{
// [MC] angle_t for pitchlimit was required because otherwise
// 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);
DAngle pdelta = deltaangle(current, pitch);
if (abs(current - pitch) > plimit)
if (fabs(pdelta) > pitchlimit)
{
fixed_t max = 0;
if (current > pitch)
if (pdelta > 0)
{
max = MIN(plimit, (current - pitch));
current -= max;
current -= MIN(pitchlimit, pdelta);
}
else //if (current > pitch)
else //if (pdelta < 0)
{
max = MIN(plimit, (pitch - current));
current += max;
current += MIN(pitchlimit, -pdelta);
}
mobj->SetPitch(ANGLE2DBL(current), !!(flags & FMDF_INTERPOLATE));
mobj->SetPitch(current, !!(flags & FMDF_INTERPOLATE));
}
else
{
mobj->SetPitch(ANGLE2DBL(pitch), !!(flags & FMDF_INTERPOLATE));
mobj->SetPitch(pitch, !!(flags & FMDF_INTERPOLATE));
}
}
else
{
mobj->SetPitch(ANGLE2DBL(pitch), !!(flags & FMDF_INTERPOLATE));
mobj->SetPitch(pitch, !!(flags & FMDF_INTERPOLATE));
}
}
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_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_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_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;
@ -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_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_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_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
@ -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_COLOR(x) ++paramnum; PARAM_COLOR_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_STRING(x) ++paramnum; PARAM_STRING_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_COLOR_OPT(x) ++paramnum; PARAM_COLOR_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_STRING_OPT(x) ++paramnum; PARAM_STRING_OPT_AT(paramnum,x)
#define PARAM_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x)