mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 14:51:46 +00:00
- added a virtual CanCollideWith script method that can be overridden to do class specific collision checks.
This will get called for both actors taking part in a collision, if one of the two calls returns false it will immediately abort PIT_CheckThing with no collision taking place at all.
This commit is contained in:
parent
04f5be6249
commit
94287518e0
3 changed files with 53 additions and 6 deletions
|
@ -650,7 +650,6 @@ public:
|
|||
virtual void Touch(AActor *toucher);
|
||||
void CallTouch(AActor *toucher);
|
||||
|
||||
|
||||
// Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
|
||||
// Made a metadata property so no longer virtual
|
||||
void Howl ();
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "r_utility.h"
|
||||
#include "p_blockmap.h"
|
||||
#include "p_3dmidtex.h"
|
||||
#include "virtual.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
#include "decallib.h"
|
||||
|
@ -1134,6 +1135,12 @@ 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;
|
||||
|
@ -1222,15 +1229,55 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
|
|||
(thing->flags5 & MF5_DONTRIP) ||
|
||||
((tm.thing->flags6 & MF6_NOBOSSRIP) && (thing->flags2 & MF2_BOSS)))
|
||||
{
|
||||
if (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP)
|
||||
{ // Some things prefer not to overlap each other, if possible
|
||||
return unblocking;
|
||||
// Some things prefer not to overlap each other, if possible (Q: Is this even needed anymore? It was just for dealing with some deficiencies in the code below in Heretic.)
|
||||
if (!(tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP))
|
||||
{
|
||||
if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z()))
|
||||
return true;
|
||||
}
|
||||
if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z()))
|
||||
return true;
|
||||
// If they are not allowed to overlap, the rest of this function still needs to be executed.
|
||||
}
|
||||
}
|
||||
|
||||
// Call the script callback. This must be done before any other checks that perform some actual action or may already return a 'block'.
|
||||
// The checks here are to do this only for conditions that would later result in an action, calling this for everything would be too much of a drag if
|
||||
// too many scripted overrides were being used, as PIT_CheckThing is even called for touching all the monster corpses lying around.
|
||||
if (((thing->flags & MF_SOLID) || (thing->flags6 & (MF6_TOUCHY | MF6_BUMPSPECIAL))) &&
|
||||
((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (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 (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING))
|
||||
{
|
||||
// touchy object is alive, toucher is solid
|
||||
|
|
|
@ -268,6 +268,7 @@ class Actor : Thinker native
|
|||
virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0);
|
||||
virtual native bool Slam(Actor victim);
|
||||
virtual native void Touch(Actor toucher);
|
||||
virtual native bool CanCollideWith(Actor other, bool passive); // This is an empty native function, it's native for the sole reason of performance as this is in a performance critical spot.
|
||||
|
||||
// Called when an actor is to be reflected by a disc of repulsion.
|
||||
// Returns true to continue normal blast processing.
|
||||
|
|
Loading…
Reference in a new issue