mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-21 19:00:56 +00:00
- Splitting the pull request in half.
- Added THRUREFLECT, MIRRORREFLECT, and AIMREFLECT. All require REFLECTIVE to work. - THRUREFLECT prevents missiles from changing course if reflected, and takes precedence over all reflective flags. - MIRRORREFLECT causes missiles to perform a direct 180 turn-around. - AIMREFLECT turns the missile back to the original shooter, and does not slow the missile down.
This commit is contained in:
parent
b2452b806e
commit
e5340ad637
4 changed files with 78 additions and 20 deletions
|
@ -347,6 +347,11 @@ enum
|
||||||
MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
|
MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
|
||||||
MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
|
MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
|
||||||
MF7_CAUSEPAIN = 0x00000400, // Damage sources with this flag can cause similar effects like ALLOWPAIN.
|
MF7_CAUSEPAIN = 0x00000400, // Damage sources with this flag can cause similar effects like ALLOWPAIN.
|
||||||
|
MF7_THRUREFLECT = 0x00000800, // Actors who are reflective cause the missiles to not slow down or change angles.
|
||||||
|
MF7_MIRRORREFLECT = 0x00001000, // Actor is turned directly 180 degrees around when reflected.
|
||||||
|
MF7_AIMREFLECT = 0x00002000, // Actor is directly reflected straight back at the one who fired the projectile.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --- mobj.renderflags ---
|
// --- mobj.renderflags ---
|
||||||
|
|
||||||
|
@ -859,7 +864,7 @@ public:
|
||||||
DWORD flags4; // [RH] Even more flags!
|
DWORD flags4; // [RH] Even more flags!
|
||||||
DWORD flags5; // OMG! We need another one.
|
DWORD flags5; // OMG! We need another one.
|
||||||
DWORD flags6; // Shit! Where did all the flags go?
|
DWORD flags6; // Shit! Where did all the flags go?
|
||||||
DWORD flags7; //
|
DWORD flags7; // WHO WANTS TO BET ON 8!?
|
||||||
|
|
||||||
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
|
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
|
||||||
DWORD VisibleToTeam;
|
DWORD VisibleToTeam;
|
||||||
|
|
|
@ -1283,6 +1283,16 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
|
||||||
{
|
{
|
||||||
P_GiveBody(thing, -damage);
|
P_GiveBody(thing, -damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((thing->flags7 & MF7_THRUREFLECT) && (thing->flags2 & MF2_REFLECTIVE) && (tm.thing->flags & MF_MISSILE))
|
||||||
|
{
|
||||||
|
if (tm.thing->flags2 & MF2_SEEKERMISSILE)
|
||||||
|
{
|
||||||
|
tm.thing->tracer = tm.thing->target;
|
||||||
|
}
|
||||||
|
tm.thing->target = thing;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false; // don't traverse any more
|
return false; // don't traverse any more
|
||||||
}
|
}
|
||||||
if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH))
|
if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH))
|
||||||
|
@ -1643,7 +1653,7 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj)
|
||||||
{ // Don't clip against self
|
{ // Don't clip against self
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((actor->flags & MF_MISSILE) && thing == actor->target)
|
if ((actor->flags & MF_MISSILE) && (thing == actor->target))
|
||||||
{ // Don't clip against whoever shot the missile.
|
{ // Don't clip against whoever shot the missile.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2983,18 +2993,20 @@ bool P_BounceWall(AActor *mo)
|
||||||
extern FRandom pr_bounce;
|
extern FRandom pr_bounce;
|
||||||
bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
||||||
{
|
{
|
||||||
|
//Don't go through all of this if the actor is reflective and wants things to pass through them.
|
||||||
|
if (BlockingMobj && ((BlockingMobj->flags2 & MF2_REFLECTIVE) && (BlockingMobj->flags7 & MF7_THRUREFLECT))) return true;
|
||||||
if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors)
|
if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors)
|
||||||
|| ((mo->flags & MF_MISSILE) && (!(mo->flags2 & MF2_RIP) || (BlockingMobj->flags5 & MF5_DONTRIP) || ((mo->flags6 & MF6_NOBOSSRIP) && (BlockingMobj->flags2 & MF2_BOSS))) && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
|| ((mo->flags & MF_MISSILE) && (!(mo->flags2 & MF2_RIP)
|
||||||
|| ((BlockingMobj->player == NULL) && (!(BlockingMobj->flags3 & MF3_ISMONSTER)))
|
|| (BlockingMobj->flags5 & MF5_DONTRIP)
|
||||||
))
|
|| ((mo->flags6 & MF6_NOBOSSRIP) && (BlockingMobj->flags2 & MF2_BOSS))) && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||||
|
|| ((BlockingMobj->player == NULL) && (!(BlockingMobj->flags3 & MF3_ISMONSTER)))))
|
||||||
{
|
{
|
||||||
if (mo->bouncecount > 0 && --mo->bouncecount == 0) return false;
|
if (mo->bouncecount > 0 && --mo->bouncecount == 0) return false;
|
||||||
|
|
||||||
if (!ontop)
|
if (!ontop)
|
||||||
{
|
{
|
||||||
fixed_t speed;
|
fixed_t speed;
|
||||||
angle_t angle = R_PointToAngle2(BlockingMobj->x,
|
angle_t angle = R_PointToAngle2(BlockingMobj->x,BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce() % 16) - 8);
|
||||||
BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce() % 16) - 8);
|
|
||||||
speed = P_AproxDistance(mo->velx, mo->vely);
|
speed = P_AproxDistance(mo->velx, mo->vely);
|
||||||
speed = FixedMul(speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
speed = FixedMul(speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||||
mo->angle = angle;
|
mo->angle = angle;
|
||||||
|
@ -5090,6 +5102,8 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
|
||||||
// is normally for projectiles which would have exploded by now anyway...
|
// is normally for projectiles which would have exploded by now anyway...
|
||||||
if (thing->flags6 & MF6_THRUSPECIES && thing->GetSpecies() == intersect->GetSpecies())
|
if (thing->flags6 & MF6_THRUSPECIES && thing->GetSpecies() == intersect->GetSpecies())
|
||||||
continue;
|
continue;
|
||||||
|
if ((thing->flags & MF_MISSILE) && (intersect->flags2 & MF2_REFLECTIVE) && (intersect->flags7 & MF7_THRUREFLECT))
|
||||||
|
continue;
|
||||||
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
|
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
|
||||||
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
|
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
|
||||||
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
|
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
|
||||||
|
@ -5098,7 +5112,8 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
|
||||||
// Can't push bridges or things more massive than ourself
|
// Can't push bridges or things more massive than ourself
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
fixed_t oldz = intersect->z;
|
fixed_t oldz;
|
||||||
|
oldz = intersect->z;
|
||||||
P_AdjustFloorCeil(intersect, cpos);
|
P_AdjustFloorCeil(intersect, cpos);
|
||||||
intersect->z = thing->z + thing->height + 1;
|
intersect->z = thing->z + thing->height + 1;
|
||||||
if (P_PushUp(intersect, cpos))
|
if (P_PushUp(intersect, cpos))
|
||||||
|
|
|
@ -1660,6 +1660,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
||||||
int steps, step, totalsteps;
|
int steps, step, totalsteps;
|
||||||
fixed_t startx, starty;
|
fixed_t startx, starty;
|
||||||
fixed_t oldfloorz = mo->floorz;
|
fixed_t oldfloorz = mo->floorz;
|
||||||
|
fixed_t oldz = mo->z;
|
||||||
|
|
||||||
fixed_t maxmove = (mo->waterlevel < 1) || (mo->flags & MF_MISSILE) ||
|
fixed_t maxmove = (mo->waterlevel < 1) || (mo->flags & MF_MISSILE) ||
|
||||||
(mo->player && mo->player->crouchoffset<-10*FRACUNIT) ? MAXMOVE : MAXMOVE/4;
|
(mo->player && mo->player->crouchoffset<-10*FRACUNIT) ? MAXMOVE : MAXMOVE/4;
|
||||||
|
@ -1949,20 +1950,53 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
||||||
}
|
}
|
||||||
if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||||
{
|
{
|
||||||
angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
|
bool seeker = (mo->flags2 & MF2_SEEKERMISSILE) ? true : false;
|
||||||
|
// Don't change the angle if there's THRUREFLECT on the monster.
|
||||||
// Change angle for deflection/reflection
|
if (!(BlockingMobj->flags7 & MF7_THRUREFLECT))
|
||||||
if (mo->AdjustReflectionAngle (BlockingMobj, angle))
|
|
||||||
{
|
{
|
||||||
goto explode;
|
int dir;
|
||||||
}
|
angle_t delta;
|
||||||
|
|
||||||
|
if (BlockingMobj->flags7 & MF7_MIRRORREFLECT)
|
||||||
|
angle = mo->angle + ANG180;
|
||||||
|
else
|
||||||
|
angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
|
||||||
|
|
||||||
// Reflect the missile along angle
|
// Change angle for deflection/reflection
|
||||||
mo->angle = angle;
|
// AIMREFLECT calls precedence so make sure not to bother with adjusting here if declared.
|
||||||
angle >>= ANGLETOFINESHIFT;
|
if (!(BlockingMobj->flags7 & MF7_AIMREFLECT) && (mo->AdjustReflectionAngle(BlockingMobj, angle)))
|
||||||
mo->velx = FixedMul (mo->Speed>>1, finecosine[angle]);
|
{
|
||||||
mo->vely = FixedMul (mo->Speed>>1, finesine[angle]);
|
goto explode;
|
||||||
mo->velz = -mo->velz/2;
|
}
|
||||||
|
|
||||||
|
// Reflect the missile along angle
|
||||||
|
if (BlockingMobj->flags7 & MF7_AIMREFLECT)
|
||||||
|
{
|
||||||
|
dir = P_FaceMobj(mo, mo->target, &delta);
|
||||||
|
if (dir)
|
||||||
|
{ // Turn clockwise
|
||||||
|
mo->angle += delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Turn counter clockwise
|
||||||
|
mo->angle -= delta;
|
||||||
|
}
|
||||||
|
angle = mo->angle >> ANGLETOFINESHIFT;
|
||||||
|
mo->velx = FixedMul(mo->Speed, finecosine[angle]);
|
||||||
|
mo->vely = FixedMul(mo->Speed, finesine[angle]);
|
||||||
|
mo->velz = -mo->velz;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mo->angle = angle;
|
||||||
|
angle >>= ANGLETOFINESHIFT;
|
||||||
|
mo->velx = FixedMul(mo->Speed >> 1, finecosine[angle]);
|
||||||
|
mo->vely = FixedMul(mo->Speed >> 1, finesine[angle]);
|
||||||
|
mo->velz = -mo->velz / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
if (mo->flags2 & MF2_SEEKERMISSILE)
|
if (mo->flags2 & MF2_SEEKERMISSILE)
|
||||||
{
|
{
|
||||||
mo->tracer = mo->target;
|
mo->tracer = mo->target;
|
||||||
|
@ -2893,6 +2927,7 @@ int AActor::SpecialMissileHit (AActor *victim)
|
||||||
bool AActor::AdjustReflectionAngle (AActor *thing, angle_t &angle)
|
bool AActor::AdjustReflectionAngle (AActor *thing, angle_t &angle)
|
||||||
{
|
{
|
||||||
if (flags2 & MF2_DONTREFLECT) return true;
|
if (flags2 & MF2_DONTREFLECT) return true;
|
||||||
|
if (thing->flags7 & MF7_THRUREFLECT) return false;
|
||||||
|
|
||||||
// Change angle for reflection
|
// Change angle for reflection
|
||||||
if (thing->flags4&MF4_SHIELDREFLECT)
|
if (thing->flags4&MF4_SHIELDREFLECT)
|
||||||
|
|
|
@ -247,6 +247,9 @@ static FFlagDef ActorFlags[]=
|
||||||
DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7),
|
DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7),
|
||||||
DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7),
|
DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7),
|
||||||
DEFINE_FLAG(MF7, CAUSEPAIN, AActor, flags7),
|
DEFINE_FLAG(MF7, CAUSEPAIN, AActor, flags7),
|
||||||
|
DEFINE_FLAG(MF7, THRUREFLECT, AActor, flags7),
|
||||||
|
DEFINE_FLAG(MF7, MIRRORREFLECT, AActor, flags7),
|
||||||
|
DEFINE_FLAG(MF7, AIMREFLECT, AActor, flags7),
|
||||||
|
|
||||||
// Effect flags
|
// Effect flags
|
||||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||||
|
|
Loading…
Reference in a new issue