mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-29 23:23:07 +00:00
This commit is contained in:
commit
6b2ddb0f3a
4 changed files with 84 additions and 41 deletions
|
@ -1286,9 +1286,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode)
|
|||
{
|
||||
ang = i*360./nails;
|
||||
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
|
||||
P_LineAttack (self, ang, MISSILERANGE, 0.,
|
||||
P_LineAttack(self, ang, MISSILERANGE, 0.,
|
||||
//P_AimLineAttack (self, ang, MISSILERANGE),
|
||||
naildamage, NAME_Hitscan, pufftype);
|
||||
naildamage, NAME_Hitscan, pufftype, (self->flags & MF_MISSILE) ? LAF_TARGETISSOURCE : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -323,6 +323,7 @@ enum // P_LineAttack flags
|
|||
LAF_NORANDOMPUFFZ = 2,
|
||||
LAF_NOIMPACTDECAL = 4,
|
||||
LAF_NOINTERACT = 8,
|
||||
LAF_TARGETISSOURCE = 16,
|
||||
};
|
||||
|
||||
AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL);
|
||||
|
|
115
src/p_map.cpp
115
src/p_map.cpp
|
@ -82,6 +82,56 @@ static FRandom pr_crunch("DoCrunch");
|
|||
TArray<spechit_t> spechit;
|
||||
TArray<spechit_t> portalhit;
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CanCollideWith
|
||||
//
|
||||
// Checks if an actor can collide with another one, calling virtual script functions to check.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, CanCollideWith)
|
||||
{
|
||||
// No need to check the parameters, as they are not even used.
|
||||
ACTION_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
bool P_CanCollideWith(AActor *tmthing, AActor *thing)
|
||||
{
|
||||
static unsigned VIndex = ~0u;
|
||||
if (VIndex == ~0u)
|
||||
{
|
||||
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCollideWith");
|
||||
assert(VIndex != ~0u);
|
||||
}
|
||||
|
||||
VMValue params[3] = { tmthing, thing, false };
|
||||
VMReturn ret;
|
||||
int retval;
|
||||
ret.IntAt(&retval);
|
||||
|
||||
auto clss = tmthing->GetClass();
|
||||
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
|
||||
if (func != nullptr)
|
||||
{
|
||||
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
|
||||
if (!retval) return false;
|
||||
}
|
||||
std::swap(params[0].a, params[1].a);
|
||||
params[2].i = true;
|
||||
|
||||
// re-get for the other actor.
|
||||
clss = thing->GetClass();
|
||||
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
|
||||
if (func != nullptr)
|
||||
{
|
||||
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
|
||||
if (!retval) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FindRefPoint
|
||||
|
@ -402,6 +452,9 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi
|
|||
}
|
||||
}
|
||||
|
||||
if (!P_CanCollideWith(tmf.thing, th))
|
||||
continue;
|
||||
|
||||
// monsters don't stomp things except on boss level
|
||||
// [RH] Some Heretic/Hexen monsters can telestomp
|
||||
// ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them.
|
||||
|
@ -1147,12 +1200,6 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, CanCollideWith)
|
||||
{
|
||||
// No need to check the parameters, as they are not even used.
|
||||
ACTION_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm)
|
||||
{
|
||||
AActor *thing = cres.thing;
|
||||
|
@ -1257,36 +1304,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
if (((thing->flags & MF_SOLID) || (thing->flags6 & (MF6_TOUCHY | MF6_BUMPSPECIAL))) &&
|
||||
((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (tm.thing->flags2 & MF2_BLASTED) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS) || (tm.thing->BounceFlags & BOUNCE_MBF)))
|
||||
{
|
||||
static unsigned VIndex = ~0u;
|
||||
if (VIndex == ~0u)
|
||||
{
|
||||
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCollideWith");
|
||||
assert(VIndex != ~0u);
|
||||
}
|
||||
|
||||
VMValue params[3] = { tm.thing, thing, false };
|
||||
VMReturn ret;
|
||||
int retval;
|
||||
ret.IntAt(&retval);
|
||||
|
||||
auto clss = tm.thing->GetClass();
|
||||
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
|
||||
if (func != nullptr)
|
||||
{
|
||||
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
|
||||
if (!retval) return true;
|
||||
}
|
||||
std::swap(params[0].a, params[1].a);
|
||||
params[2].i = true;
|
||||
|
||||
// re-get for the other actor.
|
||||
clss = thing->GetClass();
|
||||
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
|
||||
if (func != nullptr)
|
||||
{
|
||||
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
|
||||
if (!retval) return true;
|
||||
}
|
||||
if (!P_CanCollideWith(tm.thing, thing)) return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1959,6 +1977,12 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj)
|
|||
{ // something higher is in the way
|
||||
continue;
|
||||
}
|
||||
else if (!P_CanCollideWith(actor, thing))
|
||||
{ // If they cannot collide, they cannot block each other.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
onmobj = thing;
|
||||
if (quick) break;
|
||||
}
|
||||
|
@ -4476,7 +4500,9 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
|
|||
puff = P_SpawnPuff(t1, pufftype, bleedpos, 0., 0., 2, puffFlags | PF_HITTHING | PF_TEMPORARY);
|
||||
killPuff = true;
|
||||
}
|
||||
newdam = P_DamageMobj(trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags|DMG_USEANGLE, trace.SrcAngleFromTarget);
|
||||
auto src = t1;
|
||||
if ((flags & LAF_TARGETISSOURCE) && t1 && t1->target) src = t1->target;
|
||||
newdam = P_DamageMobj(trace.Actor, puff ? puff : t1, src, damage, damageType, dmgflags|DMG_USEANGLE, trace.SrcAngleFromTarget);
|
||||
if (actualdamage != NULL)
|
||||
{
|
||||
*actualdamage = newdam;
|
||||
|
@ -5943,6 +5969,9 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
|
|||
continue;
|
||||
if ((thing->flags & MF_MISSILE) && (intersect->flags2 & MF2_REFLECTIVE) && (intersect->flags7 & MF7_THRUREFLECT))
|
||||
continue;
|
||||
if (!P_CanCollideWith(thing, intersect))
|
||||
continue;
|
||||
|
||||
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
|
||||
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
|
||||
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
|
||||
|
@ -5989,6 +6018,18 @@ int P_PushDown(AActor *thing, FChangePosition *cpos)
|
|||
for (; firstintersect < lastintersect; firstintersect++)
|
||||
{
|
||||
AActor *intersect = intersectors[firstintersect];
|
||||
|
||||
// [GZ] Skip this iteration for THRUSPECIES things
|
||||
// Should there be MF2_THRUGHOST / MF3_GHOST checks there too for consistency?
|
||||
// Or would that risk breaking established behavior? THRUGHOST, like MTHRUSPECIES,
|
||||
// is normally for projectiles which would have exploded by now anyway...
|
||||
if (thing->flags6 & MF6_THRUSPECIES && thing->GetSpecies() == intersect->GetSpecies())
|
||||
continue;
|
||||
if ((thing->flags & MF_MISSILE) && (intersect->flags2 & MF2_REFLECTIVE) && (intersect->flags7 & MF7_THRUREFLECT))
|
||||
continue;
|
||||
if (!P_CanCollideWith(thing, intersect))
|
||||
continue;
|
||||
|
||||
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
|
||||
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
|
||||
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
|
||||
|
|
|
@ -917,6 +917,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
|
|||
// the referenced sound so some additional checks are required
|
||||
int near_limit = sfx->NearLimit;
|
||||
float limit_range = sfx->LimitRange;
|
||||
auto pitchmask = sfx->PitchMask;
|
||||
rolloff = &sfx->Rolloff;
|
||||
|
||||
// Resolve player sounds, random sounds, and aliases
|
||||
|
@ -1081,9 +1082,9 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
|
|||
}
|
||||
|
||||
// Vary the sfx pitches.
|
||||
if (sfx->PitchMask != 0)
|
||||
if (pitchmask != 0)
|
||||
{
|
||||
pitch = NORM_PITCH - (M_Random() & sfx->PitchMask) + (M_Random() & sfx->PitchMask);
|
||||
pitch = NORM_PITCH - (M_Random() & pitchmask) + (M_Random() & pitchmask);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue