Files
2026-05-05 15:01:01 -07:00

158 lines
4.0 KiB
C++

#include "precompiled.h"
#pragma hdrstop
#include "prey_local.h"
//==========================================================================
//
// hhPod
//
// type of mine that can be spawned from a pod spawner
//==========================================================================
CLASS_DECLARATION(hhMine, hhPod)
END_CLASS
hhPod::hhPod() {
bMoverThink = false;
additionalAxis.Identity();
}
void hhPod::Spawn(void) {
// Uses clipModel because it is a moveable, which requires it
// Turn off collision with corpses
int oldMask = GetPhysics()->GetClipMask();
GetPhysics()->SetClipMask( oldMask & (~CONTENTS_CORPSE) );
// Rolling support
radius = (GetPhysics()->GetBounds()[1][0] - GetPhysics()->GetBounds()[0][0]) * 0.5f;
lastOrigin = GetPhysics()->GetOrigin();
additionalAxis.Identity();
BecomeActive(TH_THINK);
}
void hhPod::Save( idSaveGame *savefile ) const {
savefile->WriteFloat( radius );
savefile->WriteVec3( lastOrigin );
savefile->WriteMat3( additionalAxis );
savefile->WriteBool( bMoverThink );
}
void hhPod::Restore( idRestoreGame *savefile ) {
savefile->ReadFloat( radius );
savefile->ReadVec3( lastOrigin );
savefile->ReadMat3( additionalAxis );
savefile->ReadBool( bMoverThink );
}
bool hhPod::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
StartSound( "snd_pain", SND_CHANNEL_ANY );
float scale = 1.5f - (0.5f * health / spawnArgs.GetFloat("health"));
scale = idMath::ClampFloat(1.0f, 1.5f, scale);
SetShaderParm(SHADERPARM_ANY_DEFORM_PARM2, scale);
return( idEntity::Pain(inflictor, attacker, damage, dir, location) );
}
void hhPod::Release() {
idVec3 initLinearVelocity, initAngularVelocity;
spawnArgs.GetVector( "init_velocity", "0 0 0", initLinearVelocity );
spawnArgs.GetVector( "init_avelocity", "0 0 0", initAngularVelocity );
// Make the pod physics kick in
physicsObj.EnableImpact();
physicsObj.Activate();
physicsObj.SetLinearVelocity( initLinearVelocity );
physicsObj.SetAngularVelocity( initAngularVelocity );
// Start deforming again (disabled on pod spawners)
float parm1 = spawnArgs.GetFloat("deformParm1");
float parm2 = spawnArgs.GetFloat("deformParm2");
SetDeformation(DEFORMTYPE_POD, parm1, parm2);
}
bool hhPod::Collide( const trace_t &collision, const idVec3 &velocity ) {
AttemptToPlayBounceSound( collision, velocity );
return hhMine::Collide( collision, velocity );
}
void hhPod::RollThink( void ) {
float movedDistance, angle;
idVec3 curOrigin, gravityNormal, dir;
bool wasAtRest = IsAtRest();
RunPhysics();
// only need to give the visual model an additional rotation if the physics were run
if ( !wasAtRest ) {
// current physics state
curOrigin = GetPhysics()->GetOrigin();
dir = curOrigin - lastOrigin;
float movedDistanceSquared = dir.LengthSqr();
// if the pod moved
if ( movedDistanceSquared > 0.0f && movedDistanceSquared < 100.0f) {
gravityNormal = GetPhysics()->GetGravityNormal();
// movement since last frame
movedDistance = idMath::Sqrt( movedDistanceSquared );
dir *= 1.0f / movedDistance;
// Get local coordinate axes
idVec3 right = -dir.Cross(gravityNormal);
// Rotate about it proportional to the distance moved using axis/angle
angle = 180.0f * movedDistance / (radius*idMath::PI);
additionalAxis *= (idRotation( vec3_origin, right, angle).ToMat3());
}
// save state for next think
lastOrigin = curOrigin;
}
Present();
}
void hhPod::Event_HoverTo( const idVec3 &position ) {
bMoverThink = true;
hhMine::Event_HoverTo( position );
}
void hhPod::Event_Unhover() {
bDetonateOnCollision = true;
bMoverThink = false;
hhMine::Event_Unhover();
}
void hhPod::Think() {
if ( bMoverThink ) {
hhMoveable::Think();
} else {
RollThink();
}
}
void hhPod::ClientPredictionThink() {
if ( bMoverThink ) {
hhMoveable::Think();
} else {
RollThink();
}
}
bool hhPod::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
origin = vec3_origin;
axis = additionalAxis * GetPhysics()->GetAxis().Inverse();
return true;
}