mirror of
https://github.com/dhewm/dhewm3-sdk.git
synced 2025-02-16 17:11:24 +00:00
Import changes from Doom3: The Lost Mission
Straight from the diff of their released source vs vanilla SDK 1.3.1 Completely untested so far. Thanks to the Doom3: Lost Mission team for releasing the source and allowing me to relicense their changes under the GPL! (see https://github.com/dhewm/dhewm3/issues/265)
This commit is contained in:
parent
c198d4ebeb
commit
aac103aa31
13 changed files with 677 additions and 0 deletions
|
@ -208,6 +208,12 @@ public:
|
|||
|
||||
idEntityPtr<type> & operator=( type *ent );
|
||||
|
||||
//added for LM
|
||||
idEntityPtr & operator=( const idEntityPtr & ep );
|
||||
bool operator==( const idEntityPtr & ep ) { return spawnId == ep.spawnId; }
|
||||
type * operator->() const { return GetEntity(); }
|
||||
operator type * () const { return GetEntity(); }
|
||||
|
||||
// synchronize entity pointers over the network
|
||||
int GetSpawnId( void ) const { return spawnId; }
|
||||
bool SetSpawnId( int id );
|
||||
|
@ -653,6 +659,13 @@ ID_INLINE idEntityPtr<type> &idEntityPtr<type>::operator=( type *ent ) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
//added for LM
|
||||
template< class type >
|
||||
ID_INLINE idEntityPtr< type > &idEntityPtr<type>::operator=( const idEntityPtr & ep ) {
|
||||
spawnId = ep.spawnId;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< class type >
|
||||
ID_INLINE bool idEntityPtr<type>::SetSpawnId( int id ) {
|
||||
// the reason for this first check is unclear:
|
||||
|
|
|
@ -385,6 +385,12 @@ void idGrabber::StopDrag( bool dropOnly ) {
|
|||
ent->GetPhysics()->SetContents( savedContents );
|
||||
ent->GetPhysics()->SetClipMask( savedClipmask );
|
||||
|
||||
//added for LM
|
||||
idProjectile *projectile = static_cast< idProjectile* >( ent );
|
||||
if ( projectile != NULL ) {
|
||||
projectile->SetLaunchedFromGrabber( true );
|
||||
}
|
||||
|
||||
} else if ( ent->IsType( idMoveable::Type ) ) {
|
||||
// Turn on damage for this object
|
||||
idMoveable *obj = static_cast<idMoveable*>(ent);
|
||||
|
|
155
d3xp/Misc.cpp
155
d3xp/Misc.cpp
|
@ -1747,6 +1747,161 @@ void idFuncEmitter::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
|||
}
|
||||
}
|
||||
|
||||
//added for LM
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
idFuncShootProjectile
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
CLASS_DECLARATION( idStaticEntity, idFuncShootProjectile )
|
||||
EVENT( EV_Activate, idFuncShootProjectile::Event_Activate )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
===============
|
||||
idFuncShootProjectile::idFuncShootProjectile
|
||||
===============
|
||||
*/
|
||||
idFuncShootProjectile::idFuncShootProjectile() {
|
||||
mRespawnDelay = 1000;
|
||||
mRespawnTime = 0;
|
||||
mShootSpeed = 1000;
|
||||
mShootDir = idVec3( 0.0f, 0.0f, 1.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idFuncShootProjectile::Spawn
|
||||
===============
|
||||
*/
|
||||
void idFuncShootProjectile::Spawn() {
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idFuncShootProjectile::Think
|
||||
===============
|
||||
*/
|
||||
void idFuncShootProjectile::Think() {
|
||||
if ( thinkFlags & TH_THINK ) {
|
||||
// time to spawn a new projectile?
|
||||
if ( mRespawnTime > 0 && mRespawnTime <= gameLocal.GetTime() ) {
|
||||
const idDict *dict = gameLocal.FindEntityDefDict( mEntityDefName );
|
||||
idEntity *ent = NULL;
|
||||
gameLocal.SpawnEntityDef( *dict, &ent );
|
||||
if ( ent != NULL ) {
|
||||
idProjectile *proj = static_cast<idProjectile *>(ent);
|
||||
|
||||
idVec3 pushVel = mShootDir * mShootSpeed;
|
||||
proj->Create( this, GetPhysics()->GetOrigin(), mShootDir );
|
||||
proj->Launch( GetPhysics()->GetOrigin(), mShootDir, pushVel );
|
||||
if ( mShootSpeed == 0.0f ) {
|
||||
proj->GetPhysics()->SetLinearVelocity( vec3_zero );
|
||||
} else {
|
||||
proj->GetPhysics()->SetLinearVelocity( pushVel );
|
||||
}
|
||||
|
||||
mLastProjectile = proj;
|
||||
}
|
||||
if ( mShootSpeed == 0.0f ) {
|
||||
mRespawnTime = 0; // stationary, respawn when triggered
|
||||
} else {
|
||||
mRespawnTime = gameLocal.GetTime() + mRespawnDelay; // moving, respawn after delay
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idFuncShootProjectile::Save
|
||||
===============
|
||||
*/
|
||||
void idFuncShootProjectile::Save( idSaveGame *savefile ) const {
|
||||
savefile->WriteInt( mRespawnDelay );
|
||||
savefile->WriteInt( mRespawnTime );
|
||||
savefile->WriteFloat( mShootSpeed );
|
||||
savefile->WriteVec3( mShootDir );
|
||||
savefile->WriteString( mEntityDefName );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idFuncShootProjectile::Restore
|
||||
===============
|
||||
*/
|
||||
void idFuncShootProjectile::Restore( idRestoreGame *savefile ) {
|
||||
savefile->ReadInt( mRespawnDelay );
|
||||
savefile->ReadInt( mRespawnTime );
|
||||
savefile->ReadFloat( mShootSpeed );
|
||||
savefile->ReadVec3( mShootDir );
|
||||
savefile->ReadString( mEntityDefName );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idFuncShootProjectile::Event_Activate
|
||||
================
|
||||
*/
|
||||
void idFuncShootProjectile::Event_Activate( idEntity *activator ) {
|
||||
if ( ( thinkFlags & TH_THINK ) != 0 ) {
|
||||
if ( mShootSpeed == 0.0f && mRespawnTime == 0 ) {
|
||||
mRespawnTime = gameLocal.GetTime();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mRespawnDelay = spawnArgs.GetInt( "spawn_delay_ms" );
|
||||
mShootSpeed = spawnArgs.GetFloat( "speed" );
|
||||
mEntityDefName = spawnArgs.GetString( "def_projectile" );
|
||||
if ( targets.Num() > 0 && targets[0].IsValid() ) {
|
||||
mShootDir = targets[0]->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
|
||||
//mShootDir = targets[0].GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
|
||||
mShootDir.Normalize();
|
||||
} else {
|
||||
// stationary projectile, doesn't move and only respawns when triggered
|
||||
mShootSpeed = 0.0f;
|
||||
mRespawnTime = 0;
|
||||
}
|
||||
|
||||
if ( ( thinkFlags & TH_THINK ) != 0 ) {
|
||||
// currently active, deactivate
|
||||
BecomeInactive( TH_THINK );
|
||||
} else {
|
||||
// currently inactive, activate
|
||||
BecomeActive( TH_THINK );
|
||||
mRespawnTime = gameLocal.GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idFuncShootProjectile::WriteToSnapshot
|
||||
================
|
||||
*/
|
||||
void idFuncShootProjectile::WriteToSnapshot( idBitMsg &msg ) const {
|
||||
// msg.WriteBits( hidden ? 1 : 0, 1 );
|
||||
// msg.WriteFloat( renderEntity.shaderParms[ SHADERPARM_PARTICLE_STOPTIME ] );
|
||||
// msg.WriteFloat( renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idFuncShootProjectile::ReadFromSnapshot
|
||||
================
|
||||
*/
|
||||
void idFuncShootProjectile::ReadFromSnapshot( const idBitMsg &msg ) {
|
||||
// hidden = msg.ReadBits( 1 ) != 0;
|
||||
// renderEntity.shaderParms[ SHADERPARM_PARTICLE_STOPTIME ] = msg.ReadFloat();
|
||||
// renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = msg.ReadFloat();
|
||||
// if ( msg.HasChanged() ) {
|
||||
// UpdateVisuals();
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
|
36
d3xp/Misc.h
36
d3xp/Misc.h
|
@ -345,6 +345,42 @@ private:
|
|||
};
|
||||
|
||||
|
||||
|
||||
//added for LM
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
idFuncShootProjectile
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idFuncShootProjectile : public idStaticEntity {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idFuncShootProjectile );
|
||||
|
||||
idFuncShootProjectile();
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
void Spawn();
|
||||
void Event_Activate( idEntity *activator );
|
||||
|
||||
virtual void Think();
|
||||
|
||||
virtual void WriteToSnapshot( idBitMsg &msg ) const;
|
||||
virtual void ReadFromSnapshot( const idBitMsg &msg );
|
||||
|
||||
private:
|
||||
int mRespawnDelay;
|
||||
int mRespawnTime;
|
||||
float mShootSpeed;
|
||||
idVec3 mShootDir;
|
||||
idStr mEntityDefName;
|
||||
idEntityPtr< idEntity > mLastProjectile;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
|
|
@ -1901,6 +1901,13 @@ void idPlayer::Spawn( void ) {
|
|||
inventory.selPDA = 0;
|
||||
|
||||
if ( !gameLocal.isMultiplayer ) {
|
||||
|
||||
|
||||
int startingHealth = gameLocal.world->spawnArgs.GetInt( "startingHealth", "0");
|
||||
if ( (startingHealth > 0) && (health > startingHealth) ) {
|
||||
health = startingHealth;
|
||||
}
|
||||
|
||||
if ( g_skill.GetInteger() < 2 ) {
|
||||
if ( health < 25 ) {
|
||||
health = 25;
|
||||
|
|
|
@ -98,6 +98,11 @@ idProjectile::idProjectile( void ) {
|
|||
memset( &projectileFlags, 0, sizeof( projectileFlags ) );
|
||||
memset( &renderLight, 0, sizeof( renderLight ) );
|
||||
|
||||
//added for LM
|
||||
launchedFromGrabber = false;
|
||||
mTouchTriggers = false;
|
||||
mNoExplodeDisappear = false;
|
||||
|
||||
// note: for net_instanthit projectiles, we will force this back to false at spawn time
|
||||
fl.networkSync = true;
|
||||
|
||||
|
@ -116,6 +121,10 @@ void idProjectile::Spawn( void ) {
|
|||
physicsObj.SetClipMask( 0 );
|
||||
physicsObj.PutToRest();
|
||||
SetPhysics( &physicsObj );
|
||||
|
||||
//added for LM
|
||||
mNoExplodeDisappear = spawnArgs.GetBool( "no_explode_disappear", mNoExplodeDisappear );
|
||||
mTouchTriggers = spawnArgs.GetBool( "touch_triggers", mTouchTriggers );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -487,6 +496,11 @@ void idProjectile::Think( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
//Added for LM
|
||||
if ( mTouchTriggers ) {
|
||||
TouchTriggers();
|
||||
}
|
||||
|
||||
// run physics
|
||||
RunPhysics();
|
||||
|
||||
|
@ -2654,3 +2668,211 @@ idDebris::Event_Fizzle
|
|||
void idDebris::Event_Fizzle( void ) {
|
||||
Fizzle();
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
idHomingProjectile
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
CLASS_DECLARATION( idProjectile, idHomingProjectile )
|
||||
EVENT( EV_SetEnemy, idHomingProjectile::Event_SetEnemy )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idHomingProjectile::idHomingProjectile
|
||||
================
|
||||
*/
|
||||
idHomingProjectile::idHomingProjectile() {
|
||||
enemy = NULL;
|
||||
speed = 0.0f;
|
||||
turn_max = 0.0f;
|
||||
clamp_dist = 0.0f;
|
||||
rndScale = ang_zero;
|
||||
rndAng = ang_zero;
|
||||
angles = ang_zero;
|
||||
burstMode = false;
|
||||
burstDist = 0;
|
||||
burstVelocity = 0.0f;
|
||||
unGuided = false;
|
||||
seekPos = vec3_origin;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idHomingProjectile::~idHomingProjectile
|
||||
=================
|
||||
*/
|
||||
idHomingProjectile::~idHomingProjectile() {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idHomingProjectile::Spawn
|
||||
================
|
||||
*/
|
||||
void idHomingProjectile::Spawn() {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idHomingProjectile::Save
|
||||
================
|
||||
*/
|
||||
void idHomingProjectile::Save( idSaveGame *savefile ) const {
|
||||
enemy.Save( savefile );
|
||||
savefile->WriteFloat( speed );
|
||||
savefile->WriteAngles( rndScale );
|
||||
savefile->WriteAngles( rndAng );
|
||||
savefile->WriteFloat( turn_max );
|
||||
savefile->WriteFloat( clamp_dist );
|
||||
savefile->WriteAngles( angles );
|
||||
savefile->WriteBool( burstMode );
|
||||
savefile->WriteBool( unGuided );
|
||||
savefile->WriteFloat( burstDist );
|
||||
savefile->WriteFloat( burstVelocity );
|
||||
savefile->WriteVec3( seekPos );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idHomingProjectile::Restore
|
||||
================
|
||||
*/
|
||||
void idHomingProjectile::Restore( idRestoreGame *savefile ) {
|
||||
enemy.Restore( savefile );
|
||||
savefile->ReadFloat( speed );
|
||||
savefile->ReadAngles( rndScale );
|
||||
savefile->ReadAngles( rndAng );
|
||||
savefile->ReadFloat( turn_max );
|
||||
savefile->ReadFloat( clamp_dist );
|
||||
savefile->ReadAngles( angles );
|
||||
savefile->ReadBool( burstMode );
|
||||
savefile->ReadBool( unGuided );
|
||||
savefile->ReadFloat( burstDist );
|
||||
savefile->ReadFloat( burstVelocity );
|
||||
savefile->ReadVec3( seekPos );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idHomingProjectile::Think
|
||||
================
|
||||
*/
|
||||
void idHomingProjectile::Think() {
|
||||
if ( seekPos == vec3_zero ) {
|
||||
// ai def uses a single def_projectile .. guardian has two projectile types so when seekPos is zero, just run regular projectile
|
||||
idProjectile::Think();
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 dir;
|
||||
idVec3 velocity;
|
||||
idVec3 nose;
|
||||
idVec3 tmp;
|
||||
idMat3 axis;
|
||||
idAngles dirAng;
|
||||
idAngles diff;
|
||||
float dist;
|
||||
float frac;
|
||||
int i;
|
||||
|
||||
|
||||
nose = physicsObj.GetOrigin() + 10.0f * physicsObj.GetAxis()[0];
|
||||
|
||||
dir = seekPos - nose;
|
||||
dist = dir.Normalize();
|
||||
dirAng = dir.ToAngles();
|
||||
|
||||
// make it more accurate as it gets closer
|
||||
frac = ( dist * 2.0f ) / clamp_dist;
|
||||
if ( frac > 1.0f ) {
|
||||
frac = 1.0f;
|
||||
}
|
||||
|
||||
diff = dirAng - angles * frac;
|
||||
|
||||
// clamp the to the max turn rate
|
||||
diff.Normalize180();
|
||||
for( i = 0; i < 3; i++ ) {
|
||||
if ( diff[ i ] > turn_max ) {
|
||||
diff[ i ] = turn_max;
|
||||
} else if ( diff[ i ] < -turn_max ) {
|
||||
diff[ i ] = -turn_max;
|
||||
}
|
||||
}
|
||||
angles += diff;
|
||||
|
||||
// make the visual model always points the dir we're traveling
|
||||
dir = angles.ToForward();
|
||||
velocity = dir * speed;
|
||||
|
||||
if ( burstMode && dist < burstDist ) {
|
||||
unGuided = true;
|
||||
velocity *= burstVelocity;
|
||||
}
|
||||
|
||||
physicsObj.SetLinearVelocity( velocity );
|
||||
|
||||
// align z-axis of model with the direction
|
||||
axis = dir.ToMat3();
|
||||
tmp = axis[2];
|
||||
axis[2] = axis[0];
|
||||
axis[0] = -tmp;
|
||||
|
||||
GetPhysics()->SetAxis( axis );
|
||||
|
||||
idProjectile::Think();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idHomingProjectile::Launch
|
||||
=================
|
||||
*/
|
||||
void idHomingProjectile::Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire, const float launchPower, float dmgPower ) {
|
||||
idProjectile::Launch( start, dir, pushVelocity, timeSinceFire, launchPower, dmgPower );
|
||||
if ( owner.GetEntity() ) {
|
||||
if ( owner.GetEntity()->IsType( idAI::Type ) ) {
|
||||
enemy = static_cast<idAI *>( owner.GetEntity() )->GetEnemy();
|
||||
} else if ( owner.GetEntity()->IsType( idPlayer::Type ) ) {
|
||||
trace_t tr;
|
||||
idPlayer *player = static_cast<idPlayer*>( owner.GetEntity() );
|
||||
idVec3 start = player->GetEyePosition();
|
||||
idVec3 end = start + player->viewAxis[0] * 1000.0f;
|
||||
gameLocal.clip.TracePoint( tr, start, end, MASK_SHOT_RENDERMODEL | CONTENTS_BODY, owner.GetEntity() );
|
||||
if ( tr.fraction < 1.0f ) {
|
||||
enemy = gameLocal.GetTraceEntity( tr );
|
||||
}
|
||||
// ignore actors on the player's team
|
||||
if ( enemy.GetEntity() == NULL || !enemy.GetEntity()->IsType( idActor::Type ) || ( static_cast<idActor *>( enemy.GetEntity() )->team == player->team ) ) {
|
||||
enemy = player->EnemyWithMostHealth();
|
||||
}
|
||||
}
|
||||
}
|
||||
const idVec3 &vel = physicsObj.GetLinearVelocity();
|
||||
float com_engineHz_latched = 60.0f;
|
||||
|
||||
angles = vel.ToAngles();
|
||||
speed = vel.Length();
|
||||
rndScale = spawnArgs.GetAngles( "random", "15 15 0" );
|
||||
turn_max = spawnArgs.GetFloat( "turn_max", "180" ) / com_engineHz_latched;
|
||||
clamp_dist = spawnArgs.GetFloat( "clamp_dist", "256" );
|
||||
burstMode = spawnArgs.GetBool( "burstMode" );
|
||||
unGuided = false;
|
||||
burstDist = spawnArgs.GetFloat( "burstDist", "64" );
|
||||
burstVelocity = spawnArgs.GetFloat( "burstVelocity", "1.25" );
|
||||
UpdateVisuals();
|
||||
}
|
||||
|
||||
void idHomingProjectile::SetEnemy( idEntity *ent ) {
|
||||
enemy = ent;
|
||||
}
|
||||
void idHomingProjectile::SetSeekPos( idVec3 pos ) {
|
||||
seekPos = pos;
|
||||
}
|
||||
void idHomingProjectile::Event_SetEnemy(idEntity *ent) {
|
||||
SetEnemy(ent);
|
||||
}
|
|
@ -82,6 +82,10 @@ public :
|
|||
EVENT_MAXEVENTS
|
||||
};
|
||||
|
||||
//Added for LM
|
||||
void SetLaunchedFromGrabber( bool bl ) { launchedFromGrabber = bl; }
|
||||
bool GetLaunchedFromGrabber() { return launchedFromGrabber; }
|
||||
|
||||
static void DefaultDamageEffect( idEntity *soundEnt, const idDict &projectileDef, const trace_t &collision, const idVec3 &velocity );
|
||||
static bool ClientPredictionCollide( idEntity *soundEnt, const idDict &projectileDef, const trace_t &collision, const idVec3 &velocity, bool addDamageEffect );
|
||||
virtual void ClientPredictionThink( void );
|
||||
|
@ -100,6 +104,9 @@ protected:
|
|||
bool noSplashDamage : 1;
|
||||
} projectileFlags;
|
||||
|
||||
//Added for LM
|
||||
bool launchedFromGrabber;
|
||||
|
||||
float thrust;
|
||||
int thrust_end;
|
||||
float damagePower;
|
||||
|
@ -117,6 +124,10 @@ protected:
|
|||
const idDeclParticle * smokeFly;
|
||||
int smokeFlyTime;
|
||||
|
||||
//Code for LM
|
||||
bool mNoExplodeDisappear;
|
||||
bool mTouchTriggers;
|
||||
|
||||
#ifdef _D3XP
|
||||
int originalTimeGroup;
|
||||
#endif
|
||||
|
@ -243,6 +254,43 @@ private:
|
|||
void ApplyDamage();
|
||||
};
|
||||
|
||||
//Added for LM (Lost mission)
|
||||
|
||||
class idHomingProjectile : public idProjectile {
|
||||
public :
|
||||
CLASS_PROTOTYPE( idHomingProjectile );
|
||||
|
||||
idHomingProjectile();
|
||||
~idHomingProjectile();
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
void Spawn();
|
||||
virtual void Think();
|
||||
virtual void Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire = 0.0f, const float launchPower = 1.0f, const float dmgPower = 1.0f );
|
||||
void SetEnemy( idEntity *ent );
|
||||
void SetSeekPos( idVec3 pos );
|
||||
void Event_SetEnemy(idEntity *ent);
|
||||
|
||||
protected:
|
||||
float speed;
|
||||
idEntityPtr<idEntity> enemy;
|
||||
idVec3 seekPos;
|
||||
|
||||
private:
|
||||
idAngles rndScale;
|
||||
idAngles rndAng;
|
||||
idAngles angles;
|
||||
float turn_max;
|
||||
float clamp_dist;
|
||||
bool burstMode;
|
||||
bool unGuided;
|
||||
float burstDist;
|
||||
float burstVelocity;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
|
|
@ -537,6 +537,9 @@ idTrigger_EntityName::idTrigger_EntityName( void ) {
|
|||
random_delay = 0.0f;
|
||||
nextTriggerTime = 0;
|
||||
triggerFirst = false;
|
||||
|
||||
//added for LM
|
||||
testPartialName = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -552,6 +555,8 @@ void idTrigger_EntityName::Save( idSaveGame *savefile ) const {
|
|||
savefile->WriteInt( nextTriggerTime );
|
||||
savefile->WriteBool( triggerFirst );
|
||||
savefile->WriteString( entityName );
|
||||
//added For LM
|
||||
savefile->WriteBool( testPartialName );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -567,6 +572,8 @@ void idTrigger_EntityName::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadInt( nextTriggerTime );
|
||||
savefile->ReadBool( triggerFirst );
|
||||
savefile->ReadString( entityName );
|
||||
//added for LM
|
||||
savefile->ReadBool( testPartialName );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -602,6 +609,9 @@ void idTrigger_EntityName::Spawn( void ) {
|
|||
if ( !spawnArgs.GetBool( "noTouch" ) ) {
|
||||
GetPhysics()->SetContents( CONTENTS_TRIGGER );
|
||||
}
|
||||
|
||||
//added for LM
|
||||
testPartialName = spawnArgs.GetBool( "testPartialName", testPartialName );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -648,9 +658,24 @@ void idTrigger_EntityName::Event_Trigger( idEntity *activator ) {
|
|||
return;
|
||||
}
|
||||
|
||||
//added for LM
|
||||
bool validEntity = false;
|
||||
if ( activator ) {
|
||||
if ( testPartialName ) {
|
||||
if ( activator->name.Find( entityName, false ) >= 0 ) {
|
||||
validEntity = true;
|
||||
}
|
||||
}
|
||||
if ( activator->name == entityName ) {
|
||||
validEntity = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if ( !activator || ( activator->name != entityName ) ) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if ( triggerFirst ) {
|
||||
triggerFirst = false;
|
||||
|
@ -684,9 +709,27 @@ void idTrigger_EntityName::Event_Touch( idEntity *other, trace_t *trace ) {
|
|||
return;
|
||||
}
|
||||
|
||||
//added for LM
|
||||
bool validEntity = false;
|
||||
if ( other ) {
|
||||
if ( testPartialName ) {
|
||||
if ( other->name.Find( entityName, false ) >= 0 ) {
|
||||
validEntity = true;
|
||||
}
|
||||
}
|
||||
if ( other->name == entityName ) {
|
||||
validEntity = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !validEntity ) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
if ( !other || ( other->name != entityName ) ) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
nextTriggerTime = gameLocal.time + 1;
|
||||
if ( delay > 0 ) {
|
||||
|
|
|
@ -142,6 +142,8 @@ private:
|
|||
int nextTriggerTime;
|
||||
bool triggerFirst;
|
||||
idStr entityName;
|
||||
//added for LM
|
||||
bool testPartialName;
|
||||
|
||||
void TriggerAction( idEntity *activator );
|
||||
void Event_TriggerAction( idEntity *activator );
|
||||
|
|
|
@ -359,6 +359,8 @@ protected:
|
|||
idVec3 projectileGravity;
|
||||
idEntityPtr<idProjectile> projectile;
|
||||
idStr attack;
|
||||
//Added for the LM
|
||||
idVec3 homingMissileGoal;
|
||||
|
||||
// chatter/talking
|
||||
const idSoundShader *chat_snd;
|
||||
|
@ -585,8 +587,14 @@ protected:
|
|||
void Event_AttackMissile( const char *jointname );
|
||||
void Event_FireMissileAtTarget( const char *jointname, const char *targetname );
|
||||
void Event_LaunchMissile( const idVec3 &muzzle, const idAngles &ang );
|
||||
|
||||
#ifdef _D3XP
|
||||
|
||||
//Added for the LM
|
||||
void Event_LaunchHomingMissile();
|
||||
void Event_SetHomingMissileGoal();
|
||||
void Event_LaunchProjectile( const char *entityDefName );
|
||||
|
||||
#endif
|
||||
void Event_AttackMelee( const char *meleeDefName );
|
||||
void Event_DirectDamage( idEntity *damageTarget, const char *damageDefName );
|
||||
|
|
|
@ -51,8 +51,14 @@ const idEventDef AI_CreateMissile( "createMissile", "s", 'e' );
|
|||
const idEventDef AI_AttackMissile( "attackMissile", "s", 'e' );
|
||||
const idEventDef AI_FireMissileAtTarget( "fireMissileAtTarget", "ss", 'e' );
|
||||
const idEventDef AI_LaunchMissile( "launchMissile", "vv", 'e' );
|
||||
|
||||
#ifdef _D3XP
|
||||
|
||||
//Added for the LM
|
||||
const idEventDef AI_LaunchHomingMissile( "launchHomingMissile" );
|
||||
const idEventDef AI_SetHomingMissileGoal( "setHomingMissileGoal" );
|
||||
const idEventDef AI_LaunchProjectile( "launchProjectile", "s" );
|
||||
|
||||
#endif
|
||||
const idEventDef AI_AttackMelee( "attackMelee", "s", 'd' );
|
||||
const idEventDef AI_DirectDamage( "directDamage", "es" );
|
||||
|
@ -191,6 +197,11 @@ CLASS_DECLARATION( idActor, idAI )
|
|||
EVENT( AI_AttackMissile, idAI::Event_AttackMissile )
|
||||
EVENT( AI_FireMissileAtTarget, idAI::Event_FireMissileAtTarget )
|
||||
EVENT( AI_LaunchMissile, idAI::Event_LaunchMissile )
|
||||
|
||||
//Added for the LM
|
||||
EVENT( AI_LaunchHomingMissile, idAI::Event_LaunchHomingMissile )
|
||||
EVENT( AI_SetHomingMissileGoal, idAI::Event_SetHomingMissileGoal )
|
||||
|
||||
#ifdef _D3XP
|
||||
EVENT( AI_LaunchProjectile, idAI::Event_LaunchProjectile )
|
||||
#endif
|
||||
|
@ -2903,4 +2914,95 @@ void idAI::Event_StopEmitter( const char* name ) {
|
|||
StopEmitter(name);
|
||||
}
|
||||
|
||||
|
||||
//Added for LM (Lost mission)
|
||||
|
||||
/*
|
||||
=====================
|
||||
idAI::Event_LaunchHomingMissile
|
||||
=====================
|
||||
*/
|
||||
void idAI::Event_LaunchHomingMissile() {
|
||||
idVec3 start;
|
||||
trace_t tr;
|
||||
idBounds projBounds;
|
||||
const idClipModel *projClip;
|
||||
idMat3 axis;
|
||||
float distance;
|
||||
|
||||
if ( !projectileDef ) {
|
||||
gameLocal.Warning( "%s (%s) doesn't have a projectile specified", name.c_str(), GetEntityDefName() );
|
||||
idThread::ReturnEntity( NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
idActor *enemy = GetEnemy();
|
||||
if ( enemy == NULL ) {
|
||||
idThread::ReturnEntity( NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 org = GetPhysics()->GetOrigin() + idVec3( 0.0f, 0.0f, 250.0f );
|
||||
idVec3 goal = enemy->GetPhysics()->GetOrigin();
|
||||
homingMissileGoal = goal;
|
||||
|
||||
// axis = ( goal - org ).ToMat3();
|
||||
// axis.Identity();
|
||||
if ( !projectile.GetEntity() ) {
|
||||
idHomingProjectile *homing = ( idHomingProjectile * ) CreateProjectile( org, idVec3( 0.0f, 0.0f, 1.0f ) );
|
||||
if ( homing != NULL ) {
|
||||
homing->SetEnemy( enemy );
|
||||
homing->SetSeekPos( homingMissileGoal );
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the projectile starts inside the monster bounding box
|
||||
const idBounds &ownerBounds = physicsObj.GetAbsBounds();
|
||||
projClip = projectile.GetEntity()->GetPhysics()->GetClipModel();
|
||||
projBounds = projClip->GetBounds().Rotate( projClip->GetAxis() );
|
||||
|
||||
// check if the owner bounds is bigger than the projectile bounds
|
||||
if ( ( ( ownerBounds[1][0] - ownerBounds[0][0] ) > ( projBounds[1][0] - projBounds[0][0] ) ) &&
|
||||
( ( ownerBounds[1][1] - ownerBounds[0][1] ) > ( projBounds[1][1] - projBounds[0][1] ) ) &&
|
||||
( ( ownerBounds[1][2] - ownerBounds[0][2] ) > ( projBounds[1][2] - projBounds[0][2] ) ) ) {
|
||||
if ( (ownerBounds - projBounds).RayIntersection( org, viewAxis[ 0 ], distance ) ) {
|
||||
start = org + distance * viewAxis[ 0 ];
|
||||
} else {
|
||||
start = ownerBounds.GetCenter();
|
||||
}
|
||||
} else {
|
||||
// projectile bounds bigger than the owner bounds, so just start it from the center
|
||||
start = ownerBounds.GetCenter();
|
||||
}
|
||||
|
||||
gameLocal.clip.Translation( tr, start, org, projClip, projClip->GetAxis(), MASK_SHOT_RENDERMODEL, this );
|
||||
|
||||
// launch the projectile
|
||||
idThread::ReturnEntity( projectile.GetEntity() );
|
||||
idVec3 dir = homingMissileGoal - org;
|
||||
idAngles ang = dir.ToAngles();
|
||||
ang.pitch = -45.0f;
|
||||
projectile.GetEntity()->Launch( org, ang.ToForward(), vec3_origin );
|
||||
projectile = NULL;
|
||||
|
||||
TriggerWeaponEffects( tr.endpos );
|
||||
|
||||
lastAttackTime = gameLocal.time;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idAI::Event_SetHomingMissileGoal
|
||||
=====================
|
||||
*/
|
||||
void idAI::Event_SetHomingMissileGoal() {
|
||||
idActor *enemy = GetEnemy();
|
||||
if ( enemy == NULL ) {
|
||||
idThread::ReturnEntity( NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
homingMissileGoal = enemy->GetPhysics()->GetOrigin();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -339,6 +339,24 @@ bool idDict::GetBool( const char *key, const char *defaultString, bool &out ) co
|
|||
return found;
|
||||
}
|
||||
|
||||
//Added for LM
|
||||
|
||||
/*
|
||||
================
|
||||
idDict::GetBool
|
||||
================
|
||||
*/
|
||||
bool idDict::GetBool( const char *key, const bool defaultBool, bool &out ) const {
|
||||
const idKeyValue *kv = FindKey( key );
|
||||
if ( kv ) {
|
||||
out = ( atoi( kv->GetValue() ) != 0 );
|
||||
return true;
|
||||
} else {
|
||||
out = defaultBool;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idDict::GetAngles
|
||||
|
|
17
idlib/Dict.h
17
idlib/Dict.h
|
@ -117,6 +117,9 @@ public:
|
|||
idAngles GetAngles( const char *key, const char *defaultString = NULL ) const;
|
||||
idMat3 GetMatrix( const char *key, const char *defaultString = NULL ) const;
|
||||
|
||||
//added for LM
|
||||
bool GetBool( const char *key, const bool defaultBool ) const;
|
||||
|
||||
bool GetString( const char *key, const char *defaultString, const char **out ) const;
|
||||
bool GetString( const char *key, const char *defaultString, idStr &out ) const;
|
||||
bool GetFloat( const char *key, const char *defaultString, float &out ) const;
|
||||
|
@ -128,6 +131,10 @@ public:
|
|||
bool GetAngles( const char *key, const char *defaultString, idAngles &out ) const;
|
||||
bool GetMatrix( const char *key, const char *defaultString, idMat3 &out ) const;
|
||||
|
||||
|
||||
//added for LM
|
||||
bool GetBool( const char *key, const bool defaultBool, bool &out ) const;
|
||||
|
||||
int GetNumKeyVals( void ) const;
|
||||
const idKeyValue * GetKeyVal( int index ) const;
|
||||
// returns the key/value pair with the given key
|
||||
|
@ -263,6 +270,16 @@ ID_INLINE bool idDict::GetBool( const char *key, const char *defaultString ) con
|
|||
return ( atoi( GetString( key, defaultString ) ) != 0 );
|
||||
}
|
||||
|
||||
//Added for LM
|
||||
ID_INLINE bool idDict::GetBool( const char *key, const bool defaultBool ) const {
|
||||
const idKeyValue *kv = FindKey( key );
|
||||
if ( kv ) {
|
||||
return atoi( kv->GetValue() ) != 0;
|
||||
}
|
||||
return defaultBool;
|
||||
}
|
||||
|
||||
|
||||
ID_INLINE idVec3 idDict::GetVector( const char *key, const char *defaultString ) const {
|
||||
idVec3 out;
|
||||
GetVector( key, defaultString, out );
|
||||
|
|
Loading…
Reference in a new issue