Fixed web hit detection

Fix for issue #94.

Gorge web strands now have hit detection which matches their visible component. This is for both ensnaring marines, and for cutting them with a welder.

This has the following impacts:

* Webs are easier for marines to avoid since they can safely jump or duck under angled strands, however...
* Webs are harder for marines to cut as they can no longer clear a while corridor with a single click but have to actually aim at each strand
This commit is contained in:
RGreenlees 2023-09-04 15:23:27 +01:00 committed by pierow
parent 5a04d595e3
commit 472e2c8d13
5 changed files with 125 additions and 16 deletions

View File

@ -1712,32 +1712,55 @@ void AvHWebStrand::Spawn(void)
CBeam::Spawn(); CBeam::Spawn();
// Spawn code // Spawn code
this->SetTouch(&AvHWebStrand::StrandTouch); this->SetTouch(NULL);
this->pev->solid = SOLID_TRIGGER; this->pev->solid = SOLID_NOT;
//this->pev->solid = SOLID_BBOX;
this->pev->health = kWebHitPoints; this->pev->health = kWebHitPoints;
this->pev->takedamage = DAMAGE_YES; this->pev->takedamage = DAMAGE_YES;
this->mSolid=false; this->mSolid=false;
this->pev->nextthink = gpGlobals->time + BALANCE_VAR(kWebWarmupTime); this->mHardenTime = gpGlobals->time + BALANCE_VAR(kWebWarmupTime);
this->pev->nextthink = gpGlobals->time + kWebThinkInterval;
SetThink(&AvHWebStrand::StrandThink); SetThink(&AvHWebStrand::StrandThink);
//SetBits(this->pev->flags, FL_MONSTER);
this->RelinkBeam(); this->RelinkBeam();
EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandFormSound, 1.0, ATTN_IDLE); EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandFormSound, 1.0, ATTN_IDLE);
//SetThink(StrandExpire);
//this->pev->nextthink = gpGlobals->time + kWebStrandLifetime;
} }
void AvHWebStrand::StrandThink() void AvHWebStrand::StrandThink()
{ {
EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandHardenSound, 1.0, ATTN_IDLE); TraceResult Hit;
this->SetBrightness( 32 );
this->SetColor( 255, 255, 255 ); Vector StartTrace = this->GetStartPos();
this->SetFrame(1); Vector EndTrace = this->GetEndPos();
this->mSolid=true;
SetThink(NULL); UTIL_TraceLine(StartTrace, EndTrace, dont_ignore_monsters, nullptr, &Hit);
if (!FNullEnt(Hit.pHit))
{
edict_t* webbedEdict = Hit.pHit;
AvHPlayer* theWebbedPlayer = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(webbedEdict));
if (theWebbedPlayer)
{
StrandTouch(theWebbedPlayer);
}
}
if (!this->mSolid)
{
if (gpGlobals->time >= this->mHardenTime)
{
EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandHardenSound, 1.0, ATTN_IDLE);
this->SetBrightness(32);
this->SetColor(255, 255, 255);
this->SetFrame(1);
this->mSolid = true;
}
}
this->pev->nextthink = gpGlobals->time + kWebThinkInterval;
} }
void AvHWebStrand::StrandExpire() void AvHWebStrand::StrandExpire()
{ {
@ -1749,7 +1772,7 @@ void AvHWebStrand::StrandTouch( CBaseEntity *pOther )
{ {
// Webs can never break on friendlies // Webs can never break on friendlies
//if(GetGameRules()->CanEntityDoDamageTo(this, pOther)) //if(GetGameRules()->CanEntityDoDamageTo(this, pOther))
if(pOther->pev->team != this->pev->team) if (pOther->pev->team != this->pev->team)
{ {
if ( this->mSolid ) { if ( this->mSolid ) {
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(pOther); AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(pOther);

View File

@ -526,6 +526,7 @@ public:
private: private:
bool mSolid; bool mSolid;
float mHardenTime;
}; };
class AvHFuncResource : public CBaseAnimating class AvHFuncResource : public CBaseAnimating

View File

@ -51,6 +51,7 @@
#include "AvHMarineEquipmentConstants.h" #include "AvHMarineEquipmentConstants.h"
#include "AvHWeldable.h" #include "AvHWeldable.h"
#include "AvHSpecials.h" #include "AvHSpecials.h"
#include "MathUtil.h"
#ifdef AVH_SERVER #ifdef AVH_SERVER
#include "AvHPlayerUpgrade.h" #include "AvHPlayerUpgrade.h"
@ -179,16 +180,34 @@ void AvHWelder::FireProjectiles(void)
} }
} }
// Scan area for webs, and clear them. I can't make the webs solid, and it seems like the welder might do this, so why not? Also // Scan area for webs, and clear them. I can't make the webs solid, and it seems like the welder might do this, so why not? Also
// adds neat element of specialization where a guy with a welder might be needed to clear an area before an attack, kinda RPS // adds neat element of specialization where a guy with a welder might be needed to clear an area before an attack, kinda RPS
const float kWebClearingRadius = 75; const float kWebClearingRadius = 75;
const float kWebCuttingDistance = 10.0f;
CBaseEntity* thePotentialWebStrand = NULL; CBaseEntity* thePotentialWebStrand = NULL;
while((thePotentialWebStrand = UTIL_FindEntityInSphere(thePotentialWebStrand, theWelderBarrel, kWebClearingRadius)) != NULL) while((thePotentialWebStrand = UTIL_FindEntityInSphere(thePotentialWebStrand, theWelderBarrel, kWebClearingRadius)) != NULL)
{ {
AvHWebStrand* theWebStrand = dynamic_cast<AvHWebStrand*>(thePotentialWebStrand); AvHWebStrand* theWebStrand = dynamic_cast<AvHWebStrand*>(thePotentialWebStrand);
if(theWebStrand) if(theWebStrand)
{ {
theWebStrand->Break(); //theWebStrand->Break();
Vector WelderCheckPoint;
VectorGetMidPointOnLine(theWelderBarrel, vecEnd, WelderCheckPoint);
Vector ClosestPointOnStrand;
VectorGetClosestPointOnLine(theWebStrand->GetStartPos(), theWebStrand->GetEndPos(), WelderCheckPoint, ClosestPointOnStrand);
float DistCuttingLineToStrand = VectorDistanceFromLine(theWelderBarrel, vecEnd, ClosestPointOnStrand);
if (DistCuttingLineToStrand <= kWebCuttingDistance)
{
theWebStrand->Break();
}
} }
} }

View File

@ -349,6 +349,69 @@ double VectorDistance2D(const float* in1, const float* in2)
return sqrt(theXDiff*theXDiff + theYDiff*theYDiff); return sqrt(theXDiff*theXDiff + theYDiff*theYDiff);
} }
// Added by Neoptolemus
void VectorGetClosestPointOnLine(const float* inLineFrom, const float* inLineTo, const float* inTestPosition, float *outClosestPoint)
{
float vVector1[3];
VectorSubtract(inTestPosition, inLineFrom, vVector1);
float vVector2[3];
VectorSubtract(inLineTo, inLineFrom, vVector2);
VectorNormalize(vVector2);
float d = VectorDistance(inLineTo, inLineFrom);
float t = DotProduct(vVector2, vVector1);
if (t <= 0)
{
outClosestPoint[0] = inLineFrom[0];
outClosestPoint[1] = inLineFrom[1];
outClosestPoint[2] = inLineFrom[2];
return;
}
if (t >= d)
{
outClosestPoint[0] = inLineTo[0];
outClosestPoint[1] = inLineTo[1];
outClosestPoint[2] = inLineTo[2];
return;
}
float vVector3[3];
VectorScale(vVector2, t, vVector3);
outClosestPoint[0] = inLineFrom[0] + vVector3[0];
outClosestPoint[1] = inLineFrom[1] + vVector3[1];
outClosestPoint[2] = inLineFrom[2] + vVector3[2];
}
float VectorDistanceFromLine(const float* inLineFrom, const float* inLineTo, const float* inTestPosition)
{
float nearestPointToLine[3];
VectorGetClosestPointOnLine(inLineFrom, inLineTo, inTestPosition, nearestPointToLine);
return VectorDistance(inTestPosition, nearestPointToLine);
}
void VectorGetMidPointOnLine(const float* inLineFrom, const float* inLineTo, float* outPosition)
{
float vVector1[3];
VectorSubtract(inLineTo, inLineFrom, vVector1);
VectorScale(vVector1, 0.5f, vVector1);
VectorAdd(inLineFrom, vVector1, outPosition);
}
// Added by mmcguire. // Added by mmcguire.
void VectorsToAngles(const float forward[3], const float right[3], const float up[3], float angles[3]) void VectorsToAngles(const float forward[3], const float right[3], const float up[3], float angles[3])

View File

@ -47,6 +47,9 @@ bool IsVectorBetweenBoundingVectors(const float* inOrigin, const float* inRay, c
void VectorRotate (const float* in1, const float in2[3][4], float* out); void VectorRotate (const float* in1, const float in2[3][4], float* out);
double VectorDistance(const float* in1, const float* in2); double VectorDistance(const float* in1, const float* in2);
double VectorDistance2D(const float* in1, const float* in2); double VectorDistance2D(const float* in1, const float* in2);
void VectorGetClosestPointOnLine(const float* inLineFrom, const float* inLineTo, const float* inTestPosition, float* outClosestPoint);
float VectorDistanceFromLine(const float* inLineFrom, const float* inLineTo, const float* inTestPosition);
void VectorGetMidPointOnLine(const float* inLineFrom, const float* inLineTo, float* outPosition);
// Added by mmcguire. // Added by mmcguire.
/** /**