2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
2011-12-06 18:20:15 +00:00
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
2011-11-22 21:28:15 +00:00
2011-12-06 16:14:59 +00:00
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
2011-11-22 21:28:15 +00:00
Doom 3 Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2011-12-06 18:20:15 +00:00
2011-12-16 22:28:29 +00:00
# include "sys/platform.h"
# include "renderer/ModelManager.h"
2011-11-22 21:28:15 +00:00
2011-12-16 22:28:29 +00:00
# include "gamesys/SysCvar.h"
# include "script/Script_Thread.h"
# include "ai/AI.h"
# include "Player.h"
# include "Mover.h"
# include "SmokeParticles.h"
2018-08-26 03:41:08 +00:00
# include "framework/DeclEntityDef.h"
2011-12-16 22:28:29 +00:00
# include "Projectile.h"
2011-11-22 21:28:15 +00:00
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
# include "BrittleFracture.h"
# include "Moveable.h"
# endif
2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idProjectile
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
static const int BFG_DAMAGE_FREQUENCY = 333 ;
2018-08-26 03:41:08 +00:00
static const float BOUNCE_SOUND_MIN_VELOCITY = 100.0f ; //200
static const float BOUNCE_SOUND_MAX_VELOCITY = 600.0f ; //400
2011-11-22 21:28:15 +00:00
const idEventDef EV_Explode ( " <explode> " , NULL ) ;
const idEventDef EV_Fizzle ( " <fizzle> " , NULL ) ;
const idEventDef EV_RadiusDamage ( " <radiusdmg> " , " e " ) ;
const idEventDef EV_GetProjectileState ( " getProjectileState " , NULL , ' d ' ) ;
CLASS_DECLARATION ( idEntity , idProjectile )
EVENT ( EV_Explode , idProjectile : : Event_Explode )
EVENT ( EV_Fizzle , idProjectile : : Event_Fizzle )
EVENT ( EV_Touch , idProjectile : : Event_Touch )
EVENT ( EV_RadiusDamage , idProjectile : : Event_RadiusDamage )
EVENT ( EV_GetProjectileState , idProjectile : : Event_GetProjectileState )
END_CLASS
/*
= = = = = = = = = = = = = = = =
idProjectile : : idProjectile
= = = = = = = = = = = = = = = =
*/
idProjectile : : idProjectile ( void ) {
owner = NULL ;
lightDefHandle = - 1 ;
thrust = 0.0f ;
thrust_end = 0 ;
smokeFly = NULL ;
smokeFlyTime = 0 ;
state = SPAWNED ;
lightOffset = vec3_zero ;
lightStartTime = 0 ;
lightEndTime = 0 ;
lightColor = vec3_zero ;
state = SPAWNED ;
damagePower = 1.0f ;
2018-08-26 03:41:08 +00:00
damageDef = NULL ; // new
2011-11-22 21:28:15 +00:00
memset ( & projectileFlags , 0 , sizeof ( projectileFlags ) ) ;
memset ( & renderLight , 0 , sizeof ( renderLight ) ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
tracerEffect = NULL ;
# endif
2011-11-22 21:28:15 +00:00
// note: for net_instanthit projectiles, we will force this back to false at spawn time
fl . networkSync = true ;
netSyncPhysics = false ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Spawn
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Spawn ( void ) {
physicsObj . SetSelf ( this ) ;
physicsObj . SetClipModel ( new idClipModel ( GetPhysics ( ) - > GetClipModel ( ) ) , 1.0f ) ;
physicsObj . SetContents ( 0 ) ;
physicsObj . SetClipMask ( 0 ) ;
physicsObj . PutToRest ( ) ;
SetPhysics ( & physicsObj ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Save
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Save ( idSaveGame * savefile ) const {
owner . Save ( savefile ) ;
projectileFlags_s flags = projectileFlags ;
LittleBitField ( & flags , sizeof ( flags ) ) ;
savefile - > Write ( & flags , sizeof ( flags ) ) ;
savefile - > WriteFloat ( thrust ) ;
savefile - > WriteInt ( thrust_end ) ;
savefile - > WriteRenderLight ( renderLight ) ;
savefile - > WriteInt ( ( int ) lightDefHandle ) ;
savefile - > WriteVec3 ( lightOffset ) ;
savefile - > WriteInt ( lightStartTime ) ;
savefile - > WriteInt ( lightEndTime ) ;
savefile - > WriteVec3 ( lightColor ) ;
savefile - > WriteParticle ( smokeFly ) ;
savefile - > WriteInt ( smokeFlyTime ) ;
savefile - > WriteInt ( ( int ) state ) ;
savefile - > WriteFloat ( damagePower ) ;
savefile - > WriteStaticObject ( physicsObj ) ;
savefile - > WriteStaticObject ( thruster ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Restore
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Restore ( idRestoreGame * savefile ) {
owner . Restore ( savefile ) ;
savefile - > Read ( & projectileFlags , sizeof ( projectileFlags ) ) ;
LittleBitField ( & projectileFlags , sizeof ( projectileFlags ) ) ;
savefile - > ReadFloat ( thrust ) ;
savefile - > ReadInt ( thrust_end ) ;
savefile - > ReadRenderLight ( renderLight ) ;
savefile - > ReadInt ( ( int & ) lightDefHandle ) ;
savefile - > ReadVec3 ( lightOffset ) ;
savefile - > ReadInt ( lightStartTime ) ;
savefile - > ReadInt ( lightEndTime ) ;
savefile - > ReadVec3 ( lightColor ) ;
savefile - > ReadParticle ( smokeFly ) ;
savefile - > ReadInt ( smokeFlyTime ) ;
savefile - > ReadInt ( ( int & ) state ) ;
savefile - > ReadFloat ( damagePower ) ;
savefile - > ReadStaticObject ( physicsObj ) ;
RestorePhysics ( & physicsObj ) ;
savefile - > ReadStaticObject ( thruster ) ;
thruster . SetPhysics ( & physicsObj ) ;
if ( smokeFly ! = NULL ) {
idVec3 dir ;
dir = physicsObj . GetLinearVelocity ( ) ;
dir . NormalizeFast ( ) ;
gameLocal . smokeParticles - > EmitSmoke ( smokeFly , gameLocal . time , gameLocal . random . RandomFloat ( ) , GetPhysics ( ) - > GetOrigin ( ) , GetPhysics ( ) - > GetAxis ( ) ) ;
}
2018-08-26 03:41:08 +00:00
//Reinitialize the damage Def--- By Clone JC Denton
damageDef = gameLocal . FindEntityDef ( spawnArgs . GetString ( " def_damage " ) ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : GetOwner
= = = = = = = = = = = = = = = =
*/
idEntity * idProjectile : : GetOwner ( void ) const {
return owner . GetEntity ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Create
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Create ( idEntity * owner , const idVec3 & start , const idVec3 & dir ) {
idDict args ;
idStr shaderName ;
idVec3 light_color ;
2018-08-26 03:41:08 +00:00
// idVec3 light_offset; // was delcared unnecessarily, removed by Clone JC Denton
2011-11-22 21:28:15 +00:00
idVec3 tmp ;
idMat3 axis ;
Unbind ( ) ;
// align z-axis of model with the direction
axis = dir . ToMat3 ( ) ;
tmp = axis [ 2 ] ;
axis [ 2 ] = axis [ 0 ] ;
axis [ 0 ] = - tmp ;
physicsObj . SetOrigin ( start ) ;
physicsObj . SetAxis ( axis ) ;
physicsObj . GetClipModel ( ) - > SetOwner ( owner ) ;
this - > owner = owner ;
memset ( & renderLight , 0 , sizeof ( renderLight ) ) ;
shaderName = spawnArgs . GetString ( " mtr_light_shader " ) ;
if ( * ( const char * ) shaderName ) {
renderLight . shader = declManager - > FindMaterial ( shaderName , false ) ;
renderLight . pointLight = true ;
renderLight . lightRadius [ 0 ] =
renderLight . lightRadius [ 1 ] =
renderLight . lightRadius [ 2 ] = spawnArgs . GetFloat ( " light_radius " ) ;
spawnArgs . GetVector ( " light_color " , " 1 1 1 " , light_color ) ;
renderLight . shaderParms [ 0 ] = light_color [ 0 ] ;
renderLight . shaderParms [ 1 ] = light_color [ 1 ] ;
renderLight . shaderParms [ 2 ] = light_color [ 2 ] ;
renderLight . shaderParms [ 3 ] = 1.0f ;
}
spawnArgs . GetVector ( " light_offset " , " 0 0 0 " , lightOffset ) ;
lightStartTime = 0 ;
lightEndTime = 0 ;
smokeFlyTime = 0 ;
damagePower = 1.0f ;
2018-08-26 03:41:08 +00:00
damageDef = NULL ; // New
2011-11-22 21:28:15 +00:00
UpdateVisuals ( ) ;
state = CREATED ;
if ( spawnArgs . GetBool ( " net_fullphysics " ) ) {
netSyncPhysics = true ;
}
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : ~ idProjectile
= = = = = = = = = = = = = = = = =
*/
idProjectile : : ~ idProjectile ( ) {
StopSound ( SND_CHANNEL_ANY , false ) ;
FreeLightDef ( ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
if ( tracerEffect ) {
delete tracerEffect ;
}
# endif
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : FreeLightDef
= = = = = = = = = = = = = = = = =
*/
void idProjectile : : FreeLightDef ( void ) {
if ( lightDefHandle ! = - 1 ) {
gameRenderWorld - > FreeLightDef ( lightDefHandle ) ;
lightDefHandle = - 1 ;
}
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : Launch
= = = = = = = = = = = = = = = = =
*/
void idProjectile : : Launch ( const idVec3 & start , const idVec3 & dir , const idVec3 & pushVelocity , const float timeSinceFire , const float launchPower , const float dmgPower ) {
float fuse ;
float endthrust ;
idVec3 velocity ;
idAngles angular_velocity ;
float linear_friction ;
float angular_friction ;
float contact_friction ;
float bounce ;
float mass ;
float speed ;
float gravity ;
idVec3 gravVec ;
idVec3 tmp ;
idMat3 axis ;
int contents ;
int clipMask ;
// allow characters to throw projectiles during cinematics, but not the player
if ( owner . GetEntity ( ) & & ! owner . GetEntity ( ) - > IsType ( idPlayer : : Type ) ) {
cinematic = owner . GetEntity ( ) - > cinematic ;
} else {
cinematic = false ;
}
thrust = spawnArgs . GetFloat ( " thrust " ) ;
endthrust = spawnArgs . GetFloat ( " thrust_end " ) ;
spawnArgs . GetVector ( " velocity " , " 0 0 0 " , velocity ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
speed = velocity . Length ( ) * launchPower ;
damagePower = dmgPower ;
spawnArgs . GetAngles ( " angular_velocity " , " 0 0 0 " , angular_velocity ) ;
linear_friction = spawnArgs . GetFloat ( " linear_friction " ) ;
angular_friction = spawnArgs . GetFloat ( " angular_friction " ) ;
contact_friction = spawnArgs . GetFloat ( " contact_friction " ) ;
bounce = spawnArgs . GetFloat ( " bounce " ) ;
mass = spawnArgs . GetFloat ( " mass " ) ;
gravity = spawnArgs . GetFloat ( " gravity " ) ;
fuse = spawnArgs . GetFloat ( " fuse " ) ;
projectileFlags . detonate_on_world = spawnArgs . GetBool ( " detonate_on_world " ) ;
projectileFlags . detonate_on_actor = spawnArgs . GetBool ( " detonate_on_actor " ) ;
projectileFlags . randomShaderSpin = spawnArgs . GetBool ( " random_shader_spin " ) ;
if ( mass < = 0 ) {
gameLocal . Error ( " Invalid mass on '%s' \n " , GetEntityDefName ( ) ) ;
}
thrust * = mass ;
thrust_end = SEC2MS ( endthrust ) + gameLocal . time ;
lightStartTime = 0 ;
lightEndTime = 0 ;
if ( health ) {
fl . takedamage = true ;
}
gravVec = gameLocal . GetGravity ( ) ;
gravVec . NormalizeFast ( ) ;
Unbind ( ) ;
// align z-axis of model with the direction
axis = dir . ToMat3 ( ) ;
tmp = axis [ 2 ] ;
axis [ 2 ] = axis [ 0 ] ;
axis [ 0 ] = - tmp ;
contents = 0 ;
clipMask = MASK_SHOT_RENDERMODEL ;
if ( spawnArgs . GetBool ( " detonate_on_trigger " ) ) {
contents | = CONTENTS_TRIGGER ;
}
if ( ! spawnArgs . GetBool ( " no_contents " ) ) {
contents | = CONTENTS_PROJECTILE ;
clipMask | = CONTENTS_PROJECTILE ;
}
// don't do tracers on client, we don't know origin and direction
2018-08-26 03:41:08 +00:00
// if ( spawnArgs.GetBool( "tracers" ) && gameLocal.random.RandomFloat() > 0.5f ) {
2011-11-22 21:28:15 +00:00
physicsObj . SetMass ( mass ) ;
physicsObj . SetFriction ( linear_friction , angular_friction , contact_friction ) ;
if ( contact_friction = = 0.0f ) {
physicsObj . NoContact ( ) ;
}
physicsObj . SetBouncyness ( bounce ) ;
physicsObj . SetGravity ( gravVec * gravity ) ;
physicsObj . SetContents ( contents ) ;
physicsObj . SetClipMask ( clipMask ) ;
physicsObj . SetLinearVelocity ( axis [ 2 ] * speed + pushVelocity ) ;
physicsObj . SetAngularVelocity ( angular_velocity . ToAngularVelocity ( ) * axis ) ;
physicsObj . SetOrigin ( start ) ;
physicsObj . SetAxis ( axis ) ;
thruster . SetPosition ( & physicsObj , 0 , idVec3 ( GetPhysics ( ) - > GetBounds ( ) [ 0 ] . x , 0 , 0 ) ) ;
2018-08-26 03:41:08 +00:00
// Find and store the damage def only once- --- New
// place this line before checking the fuse- for beam weapons
damageDef = gameLocal . FindEntityDef ( spawnArgs . GetString ( " def_damage " ) ) ;
2011-11-22 21:28:15 +00:00
if ( ! gameLocal . isClient ) {
if ( fuse < = 0 ) {
// run physics for 1 second
RunPhysics ( ) ;
PostEventMS ( & EV_Remove , spawnArgs . GetInt ( " remove_time " , " 1500 " ) ) ;
} else if ( spawnArgs . GetBool ( " detonate_on_fuse " ) ) {
fuse - = timeSinceFire ;
if ( fuse < 0.0f ) {
fuse = 0.0f ;
}
PostEventSec ( & EV_Explode , fuse ) ;
} else {
fuse - = timeSinceFire ;
if ( fuse < 0.0f ) {
fuse = 0.0f ;
}
PostEventSec ( & EV_Fizzle , fuse ) ;
}
}
2018-08-26 03:41:08 +00:00
const idDict * damageDict = damageDef ! = NULL ? & damageDef - > dict : & spawnArgs ;
idStr sound ;
if ( spawnArgs . GetBool ( " tracers " ) ) {
if ( ! damageDict - > GetString ( " snd_tracer " , " " , sound ) ) {
spawnArgs . GetString ( " snd_tracer " , " " , sound ) ;
}
# ifdef _DENTONMOD
if ( spawnArgs . GetBool ( " launchFromBarrel " ) ) {
idStr tracerModel ;
if ( spawnArgs . GetString ( " beam_skin " , NULL ) ! = NULL ) { // See if there's a beam_skin
tracerEffect = new dnBarrelLaunchedBeamTracer ( this ) ;
}
else if ( tracerEffect = = NULL & & spawnArgs . GetString ( " model_tracer " , " " , tracerModel ) ) {
SetModel ( tracerModel ) ;
}
}
# else
idStr tracerModel ;
if ( spawnArgs . GetString ( " model_tracer " , " " , tracerModel ) ) {
SetModel ( tracerModel ) ;
}
# endif
2011-11-22 21:28:15 +00:00
} else {
2018-08-26 03:41:08 +00:00
if ( ! damageDict - > GetString ( " snd_fly " , " " , sound ) ) {
spawnArgs . GetString ( " snd_fly " , " " , sound ) ;
}
2011-11-22 21:28:15 +00:00
}
2018-08-26 03:41:08 +00:00
StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
//StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
2011-11-22 21:28:15 +00:00
smokeFlyTime = 0 ;
const char * smokeName = spawnArgs . GetString ( " smoke_fly " ) ;
if ( * smokeName ! = ' \0 ' ) {
smokeFly = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , smokeName ) ) ;
smokeFlyTime = gameLocal . time ;
}
// used for the plasma bolts but may have other uses as well
if ( projectileFlags . randomShaderSpin ) {
float f = gameLocal . random . RandomFloat ( ) ;
f * = 0.5f ;
renderEntity . shaderParms [ SHADERPARM_DIVERSITY ] = f ;
}
UpdateVisuals ( ) ;
state = LAUNCHED ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Think
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Think ( void ) {
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
if ( state ! = EXPLODED ) { // update & run physics until projectile is not exploded. -Clone JC Denton
# endif
if ( thinkFlags & TH_THINK ) {
if ( thrust & & ( gameLocal . time < thrust_end ) ) {
// evaluate force
thruster . SetForce ( GetPhysics ( ) - > GetAxis ( ) [ 0 ] * thrust ) ;
thruster . Evaluate ( gameLocal . time ) ;
}
2011-11-22 21:28:15 +00:00
}
2018-08-26 03:41:08 +00:00
// run physics until projectile is not exploded. -Clone JC Denton
RunPhysics ( ) ;
2011-11-22 21:28:15 +00:00
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
}
2011-11-22 21:28:15 +00:00
2018-08-26 03:41:08 +00:00
if ( tracerEffect ) {
tracerEffect - > Think ( ) ;
}
# endif
2011-11-22 21:28:15 +00:00
Present ( ) ;
// add the particles
if ( smokeFly ! = NULL & & smokeFlyTime & & ! IsHidden ( ) ) {
idVec3 dir = - GetPhysics ( ) - > GetLinearVelocity ( ) ;
dir . Normalize ( ) ;
if ( ! gameLocal . smokeParticles - > EmitSmoke ( smokeFly , smokeFlyTime , gameLocal . random . RandomFloat ( ) , GetPhysics ( ) - > GetOrigin ( ) , dir . ToMat3 ( ) ) ) {
smokeFlyTime = gameLocal . time ;
}
}
// add the light
if ( renderLight . lightRadius . x > 0.0f & & g_projectileLights . GetBool ( ) ) {
renderLight . origin = GetPhysics ( ) - > GetOrigin ( ) + GetPhysics ( ) - > GetAxis ( ) * lightOffset ;
renderLight . axis = GetPhysics ( ) - > GetAxis ( ) ;
if ( ( lightDefHandle ! = - 1 ) ) {
if ( lightEndTime > 0 & & gameLocal . time < = lightEndTime + gameLocal . GetMSec ( ) ) {
idVec3 color ( 0 , 0 , 0 ) ;
if ( gameLocal . time < lightEndTime ) {
float frac = ( float ) ( gameLocal . time - lightStartTime ) / ( float ) ( lightEndTime - lightStartTime ) ;
color . Lerp ( lightColor , color , frac ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
renderLight . shaderParms [ SHADERPARM_RED ] = color . x ;
renderLight . shaderParms [ SHADERPARM_GREEN ] = color . y ;
renderLight . shaderParms [ SHADERPARM_BLUE ] = color . z ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
gameRenderWorld - > UpdateLightDef ( lightDefHandle , & renderLight ) ;
} else {
lightDefHandle = gameRenderWorld - > AddLightDef ( & renderLight ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : Collide
= = = = = = = = = = = = = = = = =
*/
bool idProjectile : : Collide ( const trace_t & collision , const idVec3 & velocity ) {
idEntity * ent ;
idEntity * ignore ;
const char * damageDefName ;
idVec3 dir ;
float push ;
float damageScale ;
2018-08-26 03:41:08 +00:00
/*idDict &damageArgs;
if ( damageDef ! = NULL ) {
damageArgs = damageDef - > dict ;
}
else {
damageArgs = spawnArgs ;
} */
2011-11-22 21:28:15 +00:00
if ( state = = EXPLODED | | state = = FIZZLED ) {
return true ;
}
// predict the explosion
if ( gameLocal . isClient ) {
2018-08-26 03:41:08 +00:00
if ( ClientPredictionCollide ( this , damageDef ! = NULL ? damageDef - > dict : spawnArgs , collision , velocity , ! spawnArgs . GetBool ( " net_instanthit " ) ) ) {
2011-11-22 21:28:15 +00:00
Explode ( collision , NULL ) ;
return true ;
}
return false ;
}
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
if ( tracerEffect ! = NULL & & tracerEffect - > IsType ( dnRailBeam : : Type ( ) ) ) {
static_cast < dnRailBeam * > ( tracerEffect ) - > Create ( collision . c . point ) ;
}
# endif
2011-11-22 21:28:15 +00:00
// remove projectile when a 'noimpact' surface is hit
if ( ( collision . c . material ! = NULL ) & & ( collision . c . material - > GetSurfaceFlags ( ) & SURF_NOIMPACT ) ) {
PostEventMS ( & EV_Remove , 0 ) ;
common - > DPrintf ( " Projectile collision no impact \n " ) ;
return true ;
}
// get the entity the projectile collided with
ent = gameLocal . entities [ collision . c . entityNum ] ;
if ( ent = = owner . GetEntity ( ) ) {
assert ( 0 ) ;
return true ;
}
// just get rid of the projectile when it hits a player in noclip
if ( ent - > IsType ( idPlayer : : Type ) & & static_cast < idPlayer * > ( ent ) - > noclip ) {
PostEventMS ( & EV_Remove , 0 ) ;
return true ;
}
// direction of projectile
dir = velocity ;
dir . Normalize ( ) ;
// projectiles can apply an additional impulse next to the rigid body physics impulse
if ( spawnArgs . GetFloat ( " push " , " 0 " , push ) & & push > 0.0f ) {
ent - > ApplyImpulse ( this , collision . c . id , collision . c . point , push * dir ) ;
}
// MP: projectiles open doors
if ( gameLocal . isMultiplayer & & ent - > IsType ( idDoor : : Type ) & & ! static_cast < idDoor * > ( ent ) - > IsOpen ( ) & & ! ent - > spawnArgs . GetBool ( " no_touch " ) ) {
ent - > ProcessEvent ( & EV_Activate , this ) ;
}
if ( ent - > IsType ( idActor : : Type ) | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < const idAFAttachment * > ( ent ) - > GetBody ( ) - > IsType ( idActor : : Type ) ) ) {
if ( ! projectileFlags . detonate_on_actor ) {
return false ;
}
} else {
if ( ! projectileFlags . detonate_on_world ) {
if ( ! StartSound ( " snd_ricochet " , SND_CHANNEL_ITEM , 0 , true , NULL ) ) {
float len = velocity . Length ( ) ;
if ( len > BOUNCE_SOUND_MIN_VELOCITY ) {
SetSoundVolume ( len > BOUNCE_SOUND_MAX_VELOCITY ? 1.0f : idMath : : Sqrt ( len - BOUNCE_SOUND_MIN_VELOCITY ) * ( 1.0f / idMath : : Sqrt ( BOUNCE_SOUND_MAX_VELOCITY - BOUNCE_SOUND_MIN_VELOCITY ) ) ) ;
StartSound ( " snd_bounce " , SND_CHANNEL_ANY , 0 , true , NULL ) ;
}
}
return false ;
}
}
SetOrigin ( collision . endpos ) ;
SetAxis ( collision . endAxis ) ;
// unlink the clip model because we no longer need it
GetPhysics ( ) - > UnlinkClip ( ) ;
2018-08-26 03:41:08 +00:00
// damageDefName = spawnArgs.GetString( "def_damage" );
2011-11-22 21:28:15 +00:00
2018-08-26 03:41:08 +00:00
if ( damageDef ! = NULL ) {
damageDefName = damageDef - > GetName ( ) ;
}
else {
damageDefName = NULL ;
}
2011-11-22 21:28:15 +00:00
ignore = NULL ;
2018-08-26 03:41:08 +00:00
// if the projectile causes a damage effect
// The Damage effects were previously applied after applying damage but we are applying before it
// because we wanted it so in idAnimatedEntity::AddLocalDamageEffect - By Clone JCD
if ( spawnArgs . GetBool ( " impact_damage_effect " ) ) {
// if the hit entity has a special damage effect
# ifdef _DENTONMOD
StopSound ( SND_CHANNEL_BODY , false ) ; // stop projectile flying sound upon impact, useful when is a looping sound.
// FIXME: need to restart this sound when projectile is bouncing off of surfaces
if ( ( ent - > IsType ( idBrittleFracture : : Type ) | | ent - > IsType ( idAnimatedEntity : : Type ) | | ent - > IsType ( idMoveable : : Type ) | | ent - > IsType ( idMoveableItem : : Type ) ) & & ent - > spawnArgs . GetBool ( " bleed " , " 1 " ) ) { // This ensures that if an entity does not have bleed key defined, it will be considered true by default
projectileFlags . impact_fx_played = true ;
ent - > AddDamageEffect ( collision , velocity , damageDefName , this ) ;
# else
if ( ent - > spawnArgs . GetBool ( " bleed " ) ) {
ent - > AddDamageEffect ( collision , velocity , damageDefName ) ;
# endif
} else {
AddDefaultDamageEffect ( collision , velocity ) ;
}
}
2011-11-22 21:28:15 +00:00
// if the hit entity takes damage
if ( ent - > fl . takedamage ) {
if ( damagePower ) {
damageScale = damagePower ;
} else {
damageScale = 1.0f ;
}
// if the projectile owner is a player
if ( owner . GetEntity ( ) & & owner . GetEntity ( ) - > IsType ( idPlayer : : Type ) ) {
// if the projectile hit an actor
if ( ent - > IsType ( idActor : : Type ) ) {
idPlayer * player = static_cast < idPlayer * > ( owner . GetEntity ( ) ) ;
player - > AddProjectileHits ( 1 ) ;
damageScale * = player - > PowerUpModifier ( PROJECTILE_DAMAGE ) ;
}
}
if ( damageDefName [ 0 ] ! = ' \0 ' ) {
ent - > Damage ( this , owner . GetEntity ( ) , dir , damageDefName , damageScale , CLIPMODEL_ID_TO_JOINT_HANDLE ( collision . c . id ) ) ;
2018-08-26 03:41:08 +00:00
if ( spawnArgs . GetBool ( " ignore_splash_damage " , " 1 " ) ) { // Added by Clone JCD for letting projectile def decide the ignore behaviour.
ignore = ent ;
}
2011-11-22 21:28:15 +00:00
}
}
Explode ( collision , ignore ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : DefaultDamageEffect
= = = = = = = = = = = = = = = = =
*/
void idProjectile : : DefaultDamageEffect ( idEntity * soundEnt , const idDict & projectileDef , const trace_t & collision , const idVec3 & velocity ) {
const char * decal , * sound , * typeName ;
surfTypes_t materialType ;
if ( collision . c . material ! = NULL ) {
materialType = collision . c . material - > GetSurfaceType ( ) ;
} else {
materialType = SURFTYPE_METAL ;
}
// get material type name
typeName = gameLocal . sufaceTypeNames [ materialType ] ;
// play impact sound
sound = projectileDef . GetString ( va ( " snd_%s " , typeName ) ) ;
if ( * sound = = ' \0 ' ) {
sound = projectileDef . GetString ( " snd_metal " ) ;
}
if ( * sound = = ' \0 ' ) {
sound = projectileDef . GetString ( " snd_impact " ) ;
}
if ( * sound ! = ' \0 ' ) {
soundEnt - > StartSoundShader ( declManager - > FindSound ( sound ) , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
// project decal
2018-08-26 03:41:08 +00:00
// Note that decal info is taken from projectile def, as projectDecal and projectOverlay work differently.
decal = projectileDef . GetString ( va ( " mtr_wound_%s " , typeName ) ) ;
if ( g_debugDamage . GetBool ( ) & & collision . c . material ! = NULL ) { // If this check is not performed game may crash at ocassions
gameLocal . Printf ( " \n Collision Material Type: %s " , typeName ) ;
gameLocal . Printf ( " \n File: %s " , collision . c . material - > GetFileName ( ) ) ;
gameLocal . Printf ( " \n Collision material: %s " , collision . c . material - > ImageName ( ) ) ;
}
2011-11-22 21:28:15 +00:00
if ( * decal = = ' \0 ' ) {
2018-08-26 03:41:08 +00:00
decal = projectileDef . GetString ( " mtr_wound " ) ; // Default decal
2011-11-22 21:28:15 +00:00
}
2018-08-26 03:41:08 +00:00
2011-11-22 21:28:15 +00:00
if ( * decal ! = ' \0 ' ) {
2018-08-26 03:41:08 +00:00
float size ;
if ( ! projectileDef . GetFloat ( va ( " size_wound_%s " , typeName ) , " 6.0 " , size ) ) { // If Material Specific decal size not found, look for default size
size = projectileDef . GetFloat ( " size_wound " , " 6.0 " ) ;
}
2018-09-01 23:17:57 +00:00
// decals with size 0 don't make sense and even cause trouble by triggering assertions because the winding ends up broken or sth
if ( size > 0.0f )
gameLocal . ProjectDecal ( collision . c . point , - collision . c . normal , 8.0f , true , size , decal ) ;
2011-11-22 21:28:15 +00:00
}
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : AddDefaultDamageEffect
= = = = = = = = = = = = = = = = =
*/
void idProjectile : : AddDefaultDamageEffect ( const trace_t & collision , const idVec3 & velocity ) {
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
DefaultDamageEffect ( this , damageDef ! = NULL ? damageDef - > dict : spawnArgs , collision , velocity ) ;
# else
2011-11-22 21:28:15 +00:00
DefaultDamageEffect ( this , spawnArgs , collision , velocity ) ;
2018-08-26 03:41:08 +00:00
# endif
2011-11-22 21:28:15 +00:00
if ( gameLocal . isServer & & fl . networkSync ) {
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
int excludeClient ;
if ( spawnArgs . GetBool ( " net_instanthit " ) ) {
excludeClient = owner . GetEntityNum ( ) ;
} else {
excludeClient = - 1 ;
}
msg . Init ( msgBuf , sizeof ( msgBuf ) ) ;
msg . BeginWriting ( ) ;
msg . WriteFloat ( collision . c . point [ 0 ] ) ;
msg . WriteFloat ( collision . c . point [ 1 ] ) ;
msg . WriteFloat ( collision . c . point [ 2 ] ) ;
msg . WriteDir ( collision . c . normal , 24 ) ;
2012-06-28 11:15:40 +00:00
msg . WriteInt ( ( collision . c . material ! = NULL ) ? gameLocal . ServerRemapDecl ( - 1 , DECL_MATERIAL , collision . c . material - > Index ( ) ) : - 1 ) ;
2011-11-22 21:28:15 +00:00
msg . WriteFloat ( velocity [ 0 ] , 5 , 10 ) ;
msg . WriteFloat ( velocity [ 1 ] , 5 , 10 ) ;
msg . WriteFloat ( velocity [ 2 ] , 5 , 10 ) ;
ServerSendEvent ( EVENT_DAMAGE_EFFECT , & msg , false , excludeClient ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Killed
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location ) {
if ( spawnArgs . GetBool ( " detonate_on_death " ) ) {
trace_t collision ;
memset ( & collision , 0 , sizeof ( collision ) ) ;
collision . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
collision . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . point = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . normal . Set ( 0 , 0 , 1 ) ;
Explode ( collision , NULL ) ;
physicsObj . ClearContacts ( ) ;
physicsObj . PutToRest ( ) ;
} else {
Fizzle ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Fizzle
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Fizzle ( void ) {
if ( state = = EXPLODED | | state = = FIZZLED ) {
return ;
}
StopSound ( SND_CHANNEL_BODY , false ) ;
StartSound ( " snd_fizzle " , SND_CHANNEL_BODY , 0 , false , NULL ) ;
// fizzle FX
const char * psystem = spawnArgs . GetString ( " smoke_fuse " ) ;
if ( psystem & & * psystem ) {
//FIXME:SMOKE gameLocal.particles->SpawnParticles( GetPhysics()->GetOrigin(), vec3_origin, psystem );
}
// we need to work out how long the effects last and then remove them at that time
// for example, bullets have no real effects
if ( smokeFly & & smokeFlyTime ) {
smokeFlyTime = 0 ;
}
fl . takedamage = false ;
physicsObj . SetContents ( 0 ) ;
physicsObj . GetClipModel ( ) - > Unlink ( ) ;
physicsObj . PutToRest ( ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
BecomeInactive ( TH_PHYSICS ) ; // This causes the physics not to update when it's fizzled
# endif
2011-11-22 21:28:15 +00:00
Hide ( ) ;
FreeLightDef ( ) ;
state = FIZZLED ;
if ( gameLocal . isClient ) {
return ;
}
CancelEvents ( & EV_Fizzle ) ;
PostEventMS ( & EV_Remove , spawnArgs . GetInt ( " remove_time " , " 1500 " ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Event_RadiusDamage
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Event_RadiusDamage ( idEntity * ignore ) {
const char * splash_damage = spawnArgs . GetString ( " def_splash_damage " ) ;
if ( splash_damage [ 0 ] ! = ' \0 ' ) {
gameLocal . RadiusDamage ( physicsObj . GetOrigin ( ) , this , owner . GetEntity ( ) , ignore , this , splash_damage , damagePower ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Event_RadiusDamage
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Event_GetProjectileState ( void ) {
idThread : : ReturnInt ( state ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Explode
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Explode ( const trace_t & collision , idEntity * ignore ) {
const char * fxname , * light_shader , * sndExplode ;
float light_fadetime ;
idVec3 normal ;
int removeTime ;
if ( state = = EXPLODED | | state = = FIZZLED ) {
return ;
}
// stop sound
StopSound ( SND_CHANNEL_BODY2 , false ) ;
// play explode sound
switch ( ( int ) damagePower ) {
case 2 : sndExplode = " snd_explode2 " ; break ;
case 3 : sndExplode = " snd_explode3 " ; break ;
case 4 : sndExplode = " snd_explode4 " ; break ;
default : sndExplode = " snd_explode " ; break ;
}
StartSound ( sndExplode , SND_CHANNEL_BODY , 0 , true , NULL ) ;
// we need to work out how long the effects last and then remove them at that time
// for example, bullets have no real effects
if ( smokeFly & & smokeFlyTime ) {
smokeFlyTime = 0 ;
}
Hide ( ) ;
FreeLightDef ( ) ;
if ( spawnArgs . GetVector ( " detonation_axis " , " " , normal ) ) {
GetPhysics ( ) - > SetAxis ( normal . ToMat3 ( ) ) ;
}
2018-08-26 03:41:08 +00:00
else { //Added by Clone JCD for setting proper direction of fx.
GetPhysics ( ) - > SetAxis ( collision . c . normal . ToMat3 ( ) ) ;
}
// GetPhysics()->SetOrigin( collision.endpos + 2.0f * collision.c.normal ); // Actual effect starts a little away object.
GetPhysics ( ) - > SetOrigin ( collision . endpos + 0.5f * collision . c . normal ) ; // By Clone JC Denton
2011-11-22 21:28:15 +00:00
// default remove time
removeTime = spawnArgs . GetInt ( " remove_time " , " 1500 " ) ;
// change the model, usually to a PRT
fxname = NULL ;
if ( g_testParticle . GetInteger ( ) = = TEST_PARTICLE_IMPACT ) {
fxname = g_testParticleName . GetString ( ) ;
} else {
fxname = spawnArgs . GetString ( " model_detonate " ) ;
}
2018-08-26 03:41:08 +00:00
if ( ! projectileFlags . impact_fx_played ) { // New flag added by Clone JCD,this wont play damage effects when model_detonate key is in place.
// which is esp. useful for exploding projectiles like rockets, grenades etc.
if ( ! ( fxname & & * fxname ) ) {
// fx shall be played from def from now on------- By Clone JCD
if ( damageDef ! = NULL ) {
int type = collision . c . material ! = NULL ? collision . c . material - > GetSurfaceType ( ) : SURFTYPE_METAL ;
if ( type = = SURFTYPE_NONE ) {
type = SURFTYPE_METAL ;
}
const char * materialType = gameLocal . sufaceTypeNames [ type ] ;
fxname = damageDef - > dict . GetString ( va ( " smoke_wound_%s " , materialType ) ) ;
if ( * fxname = = ' \0 ' ) {
fxname = damageDef - > dict . GetString ( " smoke_wound " ) ;
}
}
2011-11-22 21:28:15 +00:00
}
}
if ( fxname & & * fxname ) {
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
if ( tracerEffect ! = NULL & & tracerEffect - > IsType ( dnBeamTracer : : Type ( ) ) ) { // check whether we used beam model as tracer
memset ( & renderEntity , 0 , sizeof ( renderEntity ) ) ;
}
# endif
2011-11-22 21:28:15 +00:00
SetModel ( fxname ) ;
2011-12-06 18:20:15 +00:00
renderEntity . shaderParms [ SHADERPARM_RED ] =
renderEntity . shaderParms [ SHADERPARM_GREEN ] =
renderEntity . shaderParms [ SHADERPARM_BLUE ] =
2011-11-22 21:28:15 +00:00
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = 1.0f ;
renderEntity . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
renderEntity . shaderParms [ SHADERPARM_DIVERSITY ] = gameLocal . random . CRandomFloat ( ) ;
Show ( ) ;
removeTime = ( removeTime > 3000 ) ? removeTime : 3000 ;
}
// explosion light
light_shader = spawnArgs . GetString ( " mtr_explode_light_shader " ) ;
if ( * light_shader ) {
renderLight . shader = declManager - > FindMaterial ( light_shader , false ) ;
renderLight . pointLight = true ;
renderLight . lightRadius [ 0 ] =
renderLight . lightRadius [ 1 ] =
renderLight . lightRadius [ 2 ] = spawnArgs . GetFloat ( " explode_light_radius " ) ;
spawnArgs . GetVector ( " explode_light_color " , " 1 1 1 " , lightColor ) ;
renderLight . shaderParms [ SHADERPARM_RED ] = lightColor . x ;
renderLight . shaderParms [ SHADERPARM_GREEN ] = lightColor . y ;
renderLight . shaderParms [ SHADERPARM_BLUE ] = lightColor . z ;
renderLight . shaderParms [ SHADERPARM_ALPHA ] = 1.0f ;
renderLight . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
light_fadetime = spawnArgs . GetFloat ( " explode_light_fadetime " , " 0.5 " ) ;
lightStartTime = gameLocal . time ;
lightEndTime = gameLocal . time + SEC2MS ( light_fadetime ) ;
BecomeActive ( TH_THINK ) ;
}
fl . takedamage = false ;
physicsObj . SetContents ( 0 ) ;
physicsObj . PutToRest ( ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
if ( tracerEffect )
{
if ( tracerEffect - > IsType ( dnSpeedTracer : : Type ( ) ) & & ! static_cast < dnSpeedTracer * > ( tracerEffect ) - > IsDead ( ) ) {
BecomeActive ( TH_UPDATEPARTICLES ) ;
}
else if ( ! tracerEffect - > IsType ( dnRailBeam : : Type ( ) ) ) {
delete tracerEffect ;
tracerEffect = NULL ;
}
}
# endif
2011-11-22 21:28:15 +00:00
state = EXPLODED ;
if ( gameLocal . isClient ) {
return ;
}
// alert the ai
gameLocal . AlertAI ( owner . GetEntity ( ) ) ;
// bind the projectile to the impact entity if necesary
if ( gameLocal . entities [ collision . c . entityNum ] & & spawnArgs . GetBool ( " bindOnImpact " ) ) {
Bind ( gameLocal . entities [ collision . c . entityNum ] , true ) ;
}
// splash damage
if ( ! projectileFlags . noSplashDamage ) {
float delay = spawnArgs . GetFloat ( " delay_splash " ) ;
if ( delay ) {
if ( removeTime < delay * 1000 ) {
removeTime = ( delay + 0.10 ) * 1000 ;
}
PostEventSec ( & EV_RadiusDamage , delay , ignore ) ;
} else {
Event_RadiusDamage ( ignore ) ;
}
}
// spawn debris entities
int fxdebris = spawnArgs . GetInt ( " debris_count " ) ;
if ( fxdebris ) {
2018-08-26 03:41:08 +00:00
// const idDict *debris = gameLocal.FindEntityDefDict( "projectile_debris", false );
const idDict * debris = gameLocal . FindEntityDefDict ( spawnArgs . GetString ( " def_debris " ) , false ) ;
2011-11-22 21:28:15 +00:00
if ( debris ) {
int amount = gameLocal . random . RandomInt ( fxdebris ) ;
for ( int i = 0 ; i < amount ; i + + ) {
idEntity * ent ;
idVec3 dir ;
dir . x = gameLocal . random . CRandomFloat ( ) * 4.0f ;
dir . y = gameLocal . random . CRandomFloat ( ) * 4.0f ;
dir . z = gameLocal . random . RandomFloat ( ) * 8.0f ;
dir . Normalize ( ) ;
gameLocal . SpawnEntityDef ( * debris , & ent , false ) ;
if ( ! ent | | ! ent - > IsType ( idDebris : : Type ) ) {
gameLocal . Error ( " 'projectile_debris' is not an idDebris " ) ;
}
idDebris * debris = static_cast < idDebris * > ( ent ) ;
debris - > Create ( owner . GetEntity ( ) , physicsObj . GetOrigin ( ) , dir . ToMat3 ( ) ) ;
debris - > Launch ( ) ;
}
}
2018-08-26 03:41:08 +00:00
// debris = gameLocal.FindEntityDefDict( "projectile_shrapnel", false );
debris = gameLocal . FindEntityDefDict ( spawnArgs . GetString ( " def_shrapnel " ) , false ) ;
2011-11-22 21:28:15 +00:00
if ( debris ) {
int amount = gameLocal . random . RandomInt ( fxdebris ) ;
for ( int i = 0 ; i < amount ; i + + ) {
idEntity * ent ;
idVec3 dir ;
dir . x = gameLocal . random . CRandomFloat ( ) * 8.0f ;
dir . y = gameLocal . random . CRandomFloat ( ) * 8.0f ;
dir . z = gameLocal . random . RandomFloat ( ) * 8.0f + 8.0f ;
dir . Normalize ( ) ;
gameLocal . SpawnEntityDef ( * debris , & ent , false ) ;
if ( ! ent | | ! ent - > IsType ( idDebris : : Type ) ) {
gameLocal . Error ( " 'projectile_shrapnel' is not an idDebris " ) ;
}
idDebris * debris = static_cast < idDebris * > ( ent ) ;
debris - > Create ( owner . GetEntity ( ) , physicsObj . GetOrigin ( ) , dir . ToMat3 ( ) ) ;
debris - > Launch ( ) ;
}
}
}
CancelEvents ( & EV_Explode ) ;
PostEventMS ( & EV_Remove , removeTime ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : GetVelocity
= = = = = = = = = = = = = = = =
*/
idVec3 idProjectile : : GetVelocity ( const idDict * projectile ) {
idVec3 velocity ;
projectile - > GetVector ( " velocity " , " 0 0 0 " , velocity ) ;
return velocity ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : GetGravity
= = = = = = = = = = = = = = = =
*/
idVec3 idProjectile : : GetGravity ( const idDict * projectile ) {
float gravity ;
gravity = projectile - > GetFloat ( " gravity " ) ;
return idVec3 ( 0 , 0 , - gravity ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Event_Explode
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Event_Explode ( void ) {
trace_t collision ;
memset ( & collision , 0 , sizeof ( collision ) ) ;
collision . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
collision . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . point = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . normal . Set ( 0 , 0 , 1 ) ;
AddDefaultDamageEffect ( collision , collision . c . normal ) ;
Explode ( collision , NULL ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Event_Fizzle
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Event_Fizzle ( void ) {
Fizzle ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Event_Touch
= = = = = = = = = = = = = = = =
*/
void idProjectile : : Event_Touch ( idEntity * other , trace_t * trace ) {
if ( IsHidden ( ) ) {
return ;
}
if ( other ! = owner . GetEntity ( ) ) {
trace_t collision ;
memset ( & collision , 0 , sizeof ( collision ) ) ;
collision . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
collision . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . point = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . normal . Set ( 0 , 0 , 1 ) ;
AddDefaultDamageEffect ( collision , collision . c . normal ) ;
Explode ( collision , NULL ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idProjectile : : ClientPredictionCollide
= = = = = = = = = = = = = = = = =
*/
bool idProjectile : : ClientPredictionCollide ( idEntity * soundEnt , const idDict & projectileDef , const trace_t & collision , const idVec3 & velocity , bool addDamageEffect ) {
idEntity * ent ;
// remove projectile when a 'noimpact' surface is hit
if ( collision . c . material & & ( collision . c . material - > GetSurfaceFlags ( ) & SURF_NOIMPACT ) ) {
return false ;
}
// get the entity the projectile collided with
ent = gameLocal . entities [ collision . c . entityNum ] ;
if ( ent = = NULL ) {
return false ;
}
// don't do anything if hitting a noclip player
if ( ent - > IsType ( idPlayer : : Type ) & & static_cast < idPlayer * > ( ent ) - > noclip ) {
return false ;
}
if ( ent - > IsType ( idActor : : Type ) | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < const idAFAttachment * > ( ent ) - > GetBody ( ) - > IsType ( idActor : : Type ) ) ) {
if ( ! projectileDef . GetBool ( " detonate_on_actor " ) ) {
return false ;
}
} else {
if ( ! projectileDef . GetBool ( " detonate_on_world " ) ) {
return false ;
}
}
// if the projectile causes a damage effect
if ( addDamageEffect & & projectileDef . GetBool ( " impact_damage_effect " ) ) {
// if the hit entity does not have a special damage effect
if ( ! ent - > spawnArgs . GetBool ( " bleed " ) ) {
// predict damage effect
DefaultDamageEffect ( soundEnt , projectileDef , collision , velocity ) ;
}
}
return true ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : ClientPredictionThink
= = = = = = = = = = = = = = = =
*/
void idProjectile : : ClientPredictionThink ( void ) {
if ( ! renderEntity . hModel ) {
return ;
}
Think ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
void idProjectile : : WriteToSnapshot ( idBitMsgDelta & msg ) const {
msg . WriteBits ( owner . GetSpawnId ( ) , 32 ) ;
msg . WriteBits ( state , 3 ) ;
msg . WriteBits ( fl . hidden , 1 ) ;
if ( netSyncPhysics ) {
msg . WriteBits ( 1 , 1 ) ;
physicsObj . WriteToSnapshot ( msg ) ;
} else {
msg . WriteBits ( 0 , 1 ) ;
const idVec3 & origin = physicsObj . GetOrigin ( ) ;
const idVec3 & velocity = physicsObj . GetLinearVelocity ( ) ;
msg . WriteFloat ( origin . x ) ;
msg . WriteFloat ( origin . y ) ;
msg . WriteFloat ( origin . z ) ;
msg . WriteDeltaFloat ( 0.0f , velocity [ 0 ] , RB_VELOCITY_EXPONENT_BITS , RB_VELOCITY_MANTISSA_BITS ) ;
msg . WriteDeltaFloat ( 0.0f , velocity [ 1 ] , RB_VELOCITY_EXPONENT_BITS , RB_VELOCITY_MANTISSA_BITS ) ;
2011-12-06 18:20:15 +00:00
msg . WriteDeltaFloat ( 0.0f , velocity [ 2 ] , RB_VELOCITY_EXPONENT_BITS , RB_VELOCITY_MANTISSA_BITS ) ;
2011-11-22 21:28:15 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
void idProjectile : : ReadFromSnapshot ( const idBitMsgDelta & msg ) {
projectileState_t newState ;
owner . SetSpawnId ( msg . ReadBits ( 32 ) ) ;
newState = ( projectileState_t ) msg . ReadBits ( 3 ) ;
if ( msg . ReadBits ( 1 ) ) {
Hide ( ) ;
} else {
Show ( ) ;
}
while ( state ! = newState ) {
switch ( state ) {
case SPAWNED : {
Create ( owner . GetEntity ( ) , vec3_origin , idVec3 ( 1 , 0 , 0 ) ) ;
break ;
}
case CREATED : {
// the right origin and direction are required if you want bullet traces
Launch ( vec3_origin , idVec3 ( 1 , 0 , 0 ) , vec3_origin ) ;
break ;
}
case LAUNCHED : {
if ( newState = = FIZZLED ) {
Fizzle ( ) ;
} else {
trace_t collision ;
memset ( & collision , 0 , sizeof ( collision ) ) ;
collision . endAxis = GetPhysics ( ) - > GetAxis ( ) ;
collision . endpos = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . point = GetPhysics ( ) - > GetOrigin ( ) ;
collision . c . normal . Set ( 0 , 0 , 1 ) ;
Explode ( collision , NULL ) ;
}
break ;
}
case FIZZLED :
case EXPLODED : {
StopSound ( SND_CHANNEL_BODY2 , false ) ;
gameEdit - > ParseSpawnArgsToRenderEntity ( & spawnArgs , & renderEntity ) ;
state = SPAWNED ;
break ;
}
}
}
if ( msg . ReadBits ( 1 ) ) {
physicsObj . ReadFromSnapshot ( msg ) ;
} else {
idVec3 origin ;
idVec3 velocity ;
idVec3 tmp ;
idMat3 axis ;
origin . x = msg . ReadFloat ( ) ;
origin . y = msg . ReadFloat ( ) ;
origin . z = msg . ReadFloat ( ) ;
velocity . x = msg . ReadDeltaFloat ( 0.0f , RB_VELOCITY_EXPONENT_BITS , RB_VELOCITY_MANTISSA_BITS ) ;
velocity . y = msg . ReadDeltaFloat ( 0.0f , RB_VELOCITY_EXPONENT_BITS , RB_VELOCITY_MANTISSA_BITS ) ;
velocity . z = msg . ReadDeltaFloat ( 0.0f , RB_VELOCITY_EXPONENT_BITS , RB_VELOCITY_MANTISSA_BITS ) ;
physicsObj . SetOrigin ( origin ) ;
physicsObj . SetLinearVelocity ( velocity ) ;
// align z-axis of model with the direction
velocity . NormalizeFast ( ) ;
axis = velocity . ToMat3 ( ) ;
tmp = axis [ 2 ] ;
axis [ 2 ] = axis [ 0 ] ;
axis [ 0 ] = - tmp ;
physicsObj . SetAxis ( axis ) ;
}
if ( msg . HasChanged ( ) ) {
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
bool idProjectile : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg ) {
trace_t collision ;
idVec3 velocity ;
switch ( event ) {
case EVENT_DAMAGE_EFFECT : {
memset ( & collision , 0 , sizeof ( collision ) ) ;
collision . c . point [ 0 ] = msg . ReadFloat ( ) ;
collision . c . point [ 1 ] = msg . ReadFloat ( ) ;
collision . c . point [ 2 ] = msg . ReadFloat ( ) ;
collision . c . normal = msg . ReadDir ( 24 ) ;
2012-06-28 11:19:14 +00:00
int index = gameLocal . ClientRemapDecl ( DECL_MATERIAL , msg . ReadInt ( ) ) ;
2011-11-22 21:28:15 +00:00
collision . c . material = ( index ! = - 1 ) ? static_cast < const idMaterial * > ( declManager - > DeclByIndex ( DECL_MATERIAL , index ) ) : NULL ;
velocity [ 0 ] = msg . ReadFloat ( 5 , 10 ) ;
velocity [ 1 ] = msg . ReadFloat ( 5 , 10 ) ;
velocity [ 2 ] = msg . ReadFloat ( 5 , 10 ) ;
2018-08-26 03:41:08 +00:00
// DefaultDamageEffect( this, spawnArgs, collision, velocity );
DefaultDamageEffect ( this , damageDef ! = NULL ? damageDef - > dict : spawnArgs , collision , velocity ) ; // new
2011-11-22 21:28:15 +00:00
return true ;
}
2012-01-15 12:39:23 +00:00
default :
break ;
2011-11-22 21:28:15 +00:00
}
2012-01-15 12:39:23 +00:00
return idEntity : : ClientReceiveEvent ( event , time , msg ) ;
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idGuidedProjectile
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
CLASS_DECLARATION ( idProjectile , idGuidedProjectile )
END_CLASS
/*
= = = = = = = = = = = = = = = =
idGuidedProjectile : : idGuidedProjectile
= = = = = = = = = = = = = = = =
*/
idGuidedProjectile : : idGuidedProjectile ( void ) {
enemy = NULL ;
speed = 0.0f ;
turn_max = 0.0f ;
clamp_dist = 0.0f ;
rndScale = ang_zero ;
rndAng = ang_zero ;
rndUpdateTime = 0 ;
angles = ang_zero ;
burstMode = false ;
burstDist = 0 ;
burstVelocity = 0.0f ;
unGuided = false ;
}
/*
= = = = = = = = = = = = = = = = =
idGuidedProjectile : : ~ idGuidedProjectile
= = = = = = = = = = = = = = = = =
*/
idGuidedProjectile : : ~ idGuidedProjectile ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idGuidedProjectile : : Spawn
= = = = = = = = = = = = = = = =
*/
void idGuidedProjectile : : Spawn ( void ) {
}
/*
= = = = = = = = = = = = = = = =
idGuidedProjectile : : Save
= = = = = = = = = = = = = = = =
*/
void idGuidedProjectile : : Save ( idSaveGame * savefile ) const {
enemy . Save ( savefile ) ;
savefile - > WriteFloat ( speed ) ;
savefile - > WriteAngles ( rndScale ) ;
savefile - > WriteAngles ( rndAng ) ;
savefile - > WriteInt ( rndUpdateTime ) ;
savefile - > WriteFloat ( turn_max ) ;
savefile - > WriteFloat ( clamp_dist ) ;
savefile - > WriteAngles ( angles ) ;
savefile - > WriteBool ( burstMode ) ;
savefile - > WriteBool ( unGuided ) ;
savefile - > WriteFloat ( burstDist ) ;
savefile - > WriteFloat ( burstVelocity ) ;
}
/*
= = = = = = = = = = = = = = = =
idGuidedProjectile : : Restore
= = = = = = = = = = = = = = = =
*/
void idGuidedProjectile : : Restore ( idRestoreGame * savefile ) {
enemy . Restore ( savefile ) ;
savefile - > ReadFloat ( speed ) ;
savefile - > ReadAngles ( rndScale ) ;
savefile - > ReadAngles ( rndAng ) ;
savefile - > ReadInt ( rndUpdateTime ) ;
savefile - > ReadFloat ( turn_max ) ;
savefile - > ReadFloat ( clamp_dist ) ;
savefile - > ReadAngles ( angles ) ;
savefile - > ReadBool ( burstMode ) ;
savefile - > ReadBool ( unGuided ) ;
savefile - > ReadFloat ( burstDist ) ;
savefile - > ReadFloat ( burstVelocity ) ;
}
/*
= = = = = = = = = = = = = = = =
idGuidedProjectile : : GetSeekPos
= = = = = = = = = = = = = = = =
*/
void idGuidedProjectile : : GetSeekPos ( idVec3 & out ) {
idEntity * enemyEnt = enemy . GetEntity ( ) ;
if ( enemyEnt ) {
if ( enemyEnt - > IsType ( idActor : : Type ) ) {
out = static_cast < idActor * > ( enemyEnt ) - > GetEyePosition ( ) ;
out . z - = 12.0f ;
} else {
out = enemyEnt - > GetPhysics ( ) - > GetOrigin ( ) ;
}
} else {
out = GetPhysics ( ) - > GetOrigin ( ) + physicsObj . GetLinearVelocity ( ) * 2.0f ;
}
}
/*
= = = = = = = = = = = = = = = =
idGuidedProjectile : : Think
= = = = = = = = = = = = = = = =
*/
void idGuidedProjectile : : Think ( void ) {
idVec3 dir ;
idVec3 seekPos ;
idVec3 velocity ;
idVec3 nose ;
idVec3 tmp ;
idMat3 axis ;
idAngles dirAng ;
idAngles diff ;
float dist ;
float frac ;
int i ;
if ( state = = LAUNCHED & & ! unGuided ) {
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
GetSeekPos ( seekPos ) ;
if ( rndUpdateTime < gameLocal . time ) {
rndAng [ 0 ] = rndScale [ 0 ] * gameLocal . random . CRandomFloat ( ) ;
rndAng [ 1 ] = rndScale [ 1 ] * gameLocal . random . CRandomFloat ( ) ;
rndAng [ 2 ] = rndScale [ 2 ] * gameLocal . random . CRandomFloat ( ) ;
rndUpdateTime = gameLocal . time + 200 ;
}
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 / clamp_dist ;
if ( frac > 1.0f ) {
frac = 1.0f ;
}
diff = dirAng - angles + rndAng * 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 ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
idGuidedProjectile : : Launch
= = = = = = = = = = = = = = = = =
*/
void idGuidedProjectile : : 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 ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
// 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 ( ) ;
angles = vel . ToAngles ( ) ;
speed = vel . Length ( ) ;
rndScale = spawnArgs . GetAngles ( " random " , " 15 15 0 " ) ;
turn_max = spawnArgs . GetFloat ( " turn_max " , " 180 " ) / ( float ) USERCMD_HZ ;
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 ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idSoulCubeMissile
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
CLASS_DECLARATION ( idGuidedProjectile , idSoulCubeMissile )
END_CLASS
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : Spawn ( void )
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : Spawn ( void ) {
startingVelocity . Zero ( ) ;
endingVelocity . Zero ( ) ;
accelTime = 0.0f ;
launchTime = 0 ;
killPhase = false ;
returnPhase = false ;
smokeKillTime = 0 ;
smokeKill = NULL ;
}
/*
= = = = = = = = = = = = = = = = =
idSoulCubeMissile : : ~ idSoulCubeMissile
= = = = = = = = = = = = = = = = =
*/
idSoulCubeMissile : : ~ idSoulCubeMissile ( ) {
}
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : Save
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : Save ( idSaveGame * savefile ) const {
savefile - > WriteVec3 ( startingVelocity ) ;
savefile - > WriteVec3 ( endingVelocity ) ;
savefile - > WriteFloat ( accelTime ) ;
savefile - > WriteInt ( launchTime ) ;
savefile - > WriteBool ( killPhase ) ;
savefile - > WriteBool ( returnPhase ) ;
savefile - > WriteVec3 ( destOrg ) ;
savefile - > WriteInt ( orbitTime ) ;
savefile - > WriteVec3 ( orbitOrg ) ;
savefile - > WriteInt ( smokeKillTime ) ;
savefile - > WriteParticle ( smokeKill ) ;
}
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : Restore
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : Restore ( idRestoreGame * savefile ) {
savefile - > ReadVec3 ( startingVelocity ) ;
savefile - > ReadVec3 ( endingVelocity ) ;
savefile - > ReadFloat ( accelTime ) ;
savefile - > ReadInt ( launchTime ) ;
savefile - > ReadBool ( killPhase ) ;
savefile - > ReadBool ( returnPhase ) ;
savefile - > ReadVec3 ( destOrg ) ;
savefile - > ReadInt ( orbitTime ) ;
savefile - > ReadVec3 ( orbitOrg ) ;
savefile - > ReadInt ( smokeKillTime ) ;
savefile - > ReadParticle ( smokeKill ) ;
}
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : KillTarget
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : KillTarget ( const idVec3 & dir ) {
idEntity * ownerEnt ;
const char * smokeName ;
idActor * act ;
ReturnToOwner ( ) ;
if ( enemy . GetEntity ( ) & & enemy . GetEntity ( ) - > IsType ( idActor : : Type ) ) {
act = static_cast < idActor * > ( enemy . GetEntity ( ) ) ;
killPhase = true ;
orbitOrg = act - > GetPhysics ( ) - > GetAbsBounds ( ) . GetCenter ( ) ;
orbitTime = gameLocal . time ;
smokeKillTime = 0 ;
smokeName = spawnArgs . GetString ( " smoke_kill " ) ;
if ( * smokeName ! = ' \0 ' ) {
smokeKill = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , smokeName ) ) ;
smokeKillTime = gameLocal . time ;
}
ownerEnt = owner . GetEntity ( ) ;
if ( ( act - > health > 0 ) & & ownerEnt & & ownerEnt - > IsType ( idPlayer : : Type ) & & ( ownerEnt - > health > 0 ) & & ! act - > spawnArgs . GetBool ( " boss " ) ) {
static_cast < idPlayer * > ( ownerEnt ) - > GiveHealthPool ( act - > health ) ;
}
act - > Damage ( this , owner . GetEntity ( ) , dir , spawnArgs . GetString ( " def_damage " ) , 1.0f , INVALID_JOINT ) ;
act - > GetAFPhysics ( ) - > SetTimeScale ( 0.25 ) ;
StartSound ( " snd_explode " , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : Think
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : Think ( void ) {
float pct ;
idVec3 seekPos ;
idEntity * ownerEnt ;
if ( state = = LAUNCHED ) {
if ( killPhase ) {
// orbit the mob, cascading down
if ( gameLocal . time < orbitTime + 1500 ) {
if ( ! gameLocal . smokeParticles - > EmitSmoke ( smokeKill , smokeKillTime , gameLocal . random . CRandomFloat ( ) , orbitOrg , mat3_identity ) ) {
smokeKillTime = gameLocal . time ;
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
} else {
if ( accelTime & & gameLocal . time < launchTime + accelTime * 1000 ) {
pct = ( gameLocal . time - launchTime ) / ( accelTime * 1000 ) ;
speed = ( startingVelocity + ( startingVelocity + endingVelocity ) * pct ) . Length ( ) ;
2011-12-06 18:20:15 +00:00
}
}
2011-11-22 21:28:15 +00:00
idGuidedProjectile : : Think ( ) ;
GetSeekPos ( seekPos ) ;
if ( ( seekPos - physicsObj . GetOrigin ( ) ) . Length ( ) < 32.0f ) {
if ( returnPhase ) {
StopSound ( SND_CHANNEL_ANY , false ) ;
StartSound ( " snd_return " , SND_CHANNEL_BODY2 , 0 , false , NULL ) ;
Hide ( ) ;
PostEventSec ( & EV_Remove , 2.0f ) ;
ownerEnt = owner . GetEntity ( ) ;
if ( ownerEnt & & ownerEnt - > IsType ( idPlayer : : Type ) ) {
static_cast < idPlayer * > ( ownerEnt ) - > SetSoulCubeProjectile ( NULL ) ;
}
state = FIZZLED ;
} else if ( ! killPhase ) {
KillTarget ( physicsObj . GetAxis ( ) [ 0 ] ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : GetSeekPos
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : GetSeekPos ( idVec3 & out ) {
if ( returnPhase & & owner . GetEntity ( ) & & owner . GetEntity ( ) - > IsType ( idActor : : Type ) ) {
idActor * act = static_cast < idActor * > ( owner . GetEntity ( ) ) ;
out = act - > GetEyePosition ( ) ;
return ;
}
if ( destOrg ! = vec3_zero ) {
out = destOrg ;
return ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
idGuidedProjectile : : GetSeekPos ( out ) ;
}
/*
= = = = = = = = = = = = = = = =
idSoulCubeMissile : : Event_ReturnToOwner
= = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : ReturnToOwner ( ) {
speed * = 0.65f ;
killPhase = false ;
returnPhase = true ;
smokeFlyTime = 0 ;
}
/*
= = = = = = = = = = = = = = = = =
idSoulCubeMissile : : Launch
= = = = = = = = = = = = = = = = =
*/
void idSoulCubeMissile : : Launch ( const idVec3 & start , const idVec3 & dir , const idVec3 & pushVelocity , const float timeSinceFire , const float launchPower , float dmgPower ) {
idVec3 newStart ;
idVec3 offs ;
idEntity * ownerEnt ;
// push it out a little
newStart = start + dir * spawnArgs . GetFloat ( " launchDist " ) ;
offs = spawnArgs . GetVector ( " launchOffset " , " 0 0 -4 " ) ;
newStart + = offs ;
idGuidedProjectile : : Launch ( newStart , dir , pushVelocity , timeSinceFire , launchPower , dmgPower ) ;
if ( enemy . GetEntity ( ) = = NULL | | ! enemy . GetEntity ( ) - > IsType ( idActor : : Type ) ) {
destOrg = start + dir * 256.0f ;
} else {
destOrg . Zero ( ) ;
}
physicsObj . SetClipMask ( 0 ) ; // never collide.. think routine will decide when to detonate
startingVelocity = spawnArgs . GetVector ( " startingVelocity " , " 15 0 0 " ) ;
endingVelocity = spawnArgs . GetVector ( " endingVelocity " , " 1500 0 0 " ) ;
accelTime = spawnArgs . GetFloat ( " accelTime " , " 5 " ) ;
physicsObj . SetLinearVelocity ( startingVelocity . Length ( ) * physicsObj . GetAxis ( ) [ 2 ] ) ;
launchTime = gameLocal . time ;
killPhase = false ;
UpdateVisuals ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
ownerEnt = owner . GetEntity ( ) ;
if ( ownerEnt & & ownerEnt - > IsType ( idPlayer : : Type ) ) {
static_cast < idPlayer * > ( ownerEnt ) - > SetSoulCubeProjectile ( this ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idBFGProjectile
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const idEventDef EV_RemoveBeams ( " <removeBeams> " , NULL ) ;
CLASS_DECLARATION ( idProjectile , idBFGProjectile )
EVENT ( EV_RemoveBeams , idBFGProjectile : : Event_RemoveBeams )
END_CLASS
/*
= = = = = = = = = = = = = = = = =
idBFGProjectile : : idBFGProjectile
= = = = = = = = = = = = = = = = =
*/
idBFGProjectile : : idBFGProjectile ( ) {
memset ( & secondModel , 0 , sizeof ( secondModel ) ) ;
secondModelDefHandle = - 1 ;
nextDamageTime = 0 ;
}
/*
= = = = = = = = = = = = = = = = =
idBFGProjectile : : ~ idBFGProjectile
= = = = = = = = = = = = = = = = =
*/
idBFGProjectile : : ~ idBFGProjectile ( ) {
FreeBeams ( ) ;
if ( secondModelDefHandle > = 0 ) {
gameRenderWorld - > FreeEntityDef ( secondModelDefHandle ) ;
secondModelDefHandle = - 1 ;
}
}
/*
= = = = = = = = = = = = = = = =
idBFGProjectile : : Spawn
= = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Spawn ( void ) {
beamTargets . Clear ( ) ;
memset ( & secondModel , 0 , sizeof ( secondModel ) ) ;
secondModelDefHandle = - 1 ;
const char * temp = spawnArgs . GetString ( " model_two " ) ;
if ( temp & & * temp ) {
secondModel . hModel = renderModelManager - > FindModel ( temp ) ;
secondModel . bounds = secondModel . hModel - > Bounds ( & secondModel ) ;
secondModel . shaderParms [ SHADERPARM_RED ] =
secondModel . shaderParms [ SHADERPARM_GREEN ] =
secondModel . shaderParms [ SHADERPARM_BLUE ] =
secondModel . shaderParms [ SHADERPARM_ALPHA ] = 1.0f ;
secondModel . noSelfShadow = true ;
secondModel . noShadow = true ;
}
nextDamageTime = 0 ;
damageFreq = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idBFGProjectile : : Save
= = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Save ( idSaveGame * savefile ) const {
int i ;
savefile - > WriteInt ( beamTargets . Num ( ) ) ;
for ( i = 0 ; i < beamTargets . Num ( ) ; i + + ) {
beamTargets [ i ] . target . Save ( savefile ) ;
savefile - > WriteRenderEntity ( beamTargets [ i ] . renderEntity ) ;
savefile - > WriteInt ( beamTargets [ i ] . modelDefHandle ) ;
}
savefile - > WriteRenderEntity ( secondModel ) ;
savefile - > WriteInt ( secondModelDefHandle ) ;
savefile - > WriteInt ( nextDamageTime ) ;
savefile - > WriteString ( damageFreq ) ;
}
/*
= = = = = = = = = = = = = = = =
idBFGProjectile : : Restore
= = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Restore ( idRestoreGame * savefile ) {
int i , num ;
savefile - > ReadInt ( num ) ;
beamTargets . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
beamTargets [ i ] . target . Restore ( savefile ) ;
savefile - > ReadRenderEntity ( beamTargets [ i ] . renderEntity ) ;
savefile - > ReadInt ( beamTargets [ i ] . modelDefHandle ) ;
if ( beamTargets [ i ] . modelDefHandle > = 0 ) {
beamTargets [ i ] . modelDefHandle = gameRenderWorld - > AddEntityDef ( & beamTargets [ i ] . renderEntity ) ;
}
}
savefile - > ReadRenderEntity ( secondModel ) ;
savefile - > ReadInt ( secondModelDefHandle ) ;
savefile - > ReadInt ( nextDamageTime ) ;
savefile - > ReadString ( damageFreq ) ;
if ( secondModelDefHandle > = 0 ) {
secondModelDefHandle = gameRenderWorld - > AddEntityDef ( & secondModel ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idBFGProjectile : : FreeBeams
= = = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : FreeBeams ( ) {
for ( int i = 0 ; i < beamTargets . Num ( ) ; i + + ) {
if ( beamTargets [ i ] . modelDefHandle > = 0 ) {
gameRenderWorld - > FreeEntityDef ( beamTargets [ i ] . modelDefHandle ) ;
beamTargets [ i ] . modelDefHandle = - 1 ;
}
}
idPlayer * player = gameLocal . GetLocalPlayer ( ) ;
if ( player ) {
player - > playerView . EnableBFGVision ( false ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idBFGProjectile : : Think
= = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Think ( void ) {
if ( state = = LAUNCHED ) {
// update beam targets
for ( int i = 0 ; i < beamTargets . Num ( ) ; i + + ) {
if ( beamTargets [ i ] . target . GetEntity ( ) = = NULL ) {
continue ;
}
idPlayer * player = ( beamTargets [ i ] . target . GetEntity ( ) - > IsType ( idPlayer : : Type ) ) ? static_cast < idPlayer * > ( beamTargets [ i ] . target . GetEntity ( ) ) : NULL ;
idVec3 org = beamTargets [ i ] . target . GetEntity ( ) - > GetPhysics ( ) - > GetAbsBounds ( ) . GetCenter ( ) ;
beamTargets [ i ] . renderEntity . origin = GetPhysics ( ) - > GetOrigin ( ) ;
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_BEAM_END_X ] = org . x ;
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_BEAM_END_Y ] = org . y ;
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_BEAM_END_Z ] = org . z ;
2011-12-06 18:20:15 +00:00
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_RED ] =
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_GREEN ] =
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_BLUE ] =
2011-11-22 21:28:15 +00:00
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_ALPHA ] = 1.0f ;
if ( gameLocal . time > nextDamageTime ) {
bool bfgVision = true ;
if ( damageFreq & & * ( const char * ) damageFreq & & beamTargets [ i ] . target . GetEntity ( ) & & beamTargets [ i ] . target . GetEntity ( ) - > CanDamage ( GetPhysics ( ) - > GetOrigin ( ) , org ) ) {
org = beamTargets [ i ] . target . GetEntity ( ) - > GetPhysics ( ) - > GetOrigin ( ) - GetPhysics ( ) - > GetOrigin ( ) ;
org . Normalize ( ) ;
beamTargets [ i ] . target . GetEntity ( ) - > Damage ( this , owner . GetEntity ( ) , org , damageFreq , ( damagePower ) ? damagePower : 1.0f , INVALID_JOINT ) ;
} else {
2011-12-06 18:20:15 +00:00
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_RED ] =
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_GREEN ] =
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_BLUE ] =
2011-11-22 21:28:15 +00:00
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_ALPHA ] = 0.0f ;
bfgVision = false ;
}
if ( player ) {
player - > playerView . EnableBFGVision ( bfgVision ) ;
}
nextDamageTime = gameLocal . time + BFG_DAMAGE_FREQUENCY ;
}
gameRenderWorld - > UpdateEntityDef ( beamTargets [ i ] . modelDefHandle , & beamTargets [ i ] . renderEntity ) ;
}
if ( secondModelDefHandle > = 0 ) {
secondModel . origin = GetPhysics ( ) - > GetOrigin ( ) ;
gameRenderWorld - > UpdateEntityDef ( secondModelDefHandle , & secondModel ) ;
}
idAngles ang ;
ang . pitch = ( gameLocal . time & 4095 ) * 360.0f / - 4096.0f ;
ang . yaw = ang . pitch ;
ang . roll = 0.0f ;
SetAngles ( ang ) ;
ang . pitch = ( gameLocal . time & 2047 ) * 360.0f / - 2048.0f ;
ang . yaw = ang . pitch ;
ang . roll = 0.0f ;
secondModel . axis = ang . ToMat3 ( ) ;
UpdateVisuals ( ) ;
}
idProjectile : : Think ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
idBFGProjectile : : Launch
= = = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Launch ( const idVec3 & start , const idVec3 & dir , const idVec3 & pushVelocity , const float timeSinceFire , const float power , const float dmgPower ) {
idProjectile : : Launch ( start , dir , pushVelocity , 0.0f , power , dmgPower ) ;
// dmgPower * radius is the target acquisition area
2011-12-06 18:20:15 +00:00
// acquisition should make sure that monsters are not dormant
2011-11-22 21:28:15 +00:00
// which will cut down on hitting monsters not actively fighting
// but saves on the traces making sure they are visible
// damage is not applied until the projectile explodes
idEntity * ent ;
idEntity * entityList [ MAX_GENTITIES ] ;
int numListedEntities ;
idBounds bounds ;
idVec3 damagePoint ;
float radius ;
spawnArgs . GetFloat ( " damageRadius " , " 512 " , radius ) ;
bounds = idBounds ( GetPhysics ( ) - > GetOrigin ( ) ) . Expand ( radius ) ;
float beamWidth = spawnArgs . GetFloat ( " beam_WidthFly " ) ;
const char * skin = spawnArgs . GetString ( " skin_beam " ) ;
memset ( & secondModel , 0 , sizeof ( secondModel ) ) ;
secondModelDefHandle = - 1 ;
const char * temp = spawnArgs . GetString ( " model_two " ) ;
if ( temp & & * temp ) {
secondModel . hModel = renderModelManager - > FindModel ( temp ) ;
secondModel . bounds = secondModel . hModel - > Bounds ( & secondModel ) ;
secondModel . shaderParms [ SHADERPARM_RED ] =
secondModel . shaderParms [ SHADERPARM_GREEN ] =
secondModel . shaderParms [ SHADERPARM_BLUE ] =
secondModel . shaderParms [ SHADERPARM_ALPHA ] = 1.0f ;
secondModel . noSelfShadow = true ;
secondModel . noShadow = true ;
secondModel . origin = GetPhysics ( ) - > GetOrigin ( ) ;
secondModel . axis = GetPhysics ( ) - > GetAxis ( ) ;
secondModelDefHandle = gameRenderWorld - > AddEntityDef ( & secondModel ) ;
}
idVec3 delta ( 15.0f , 15.0f , 15.0f ) ;
//physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, physicsObj.GetAxis().ToAngles(), delta, ang_zero );
// get all entities touching the bounds
numListedEntities = gameLocal . clip . EntitiesTouchingBounds ( bounds , CONTENTS_BODY , entityList , MAX_GENTITIES ) ;
for ( int e = 0 ; e < numListedEntities ; e + + ) {
ent = entityList [ e ] ;
assert ( ent ) ;
if ( ent = = this | | ent = = owner . GetEntity ( ) | | ent - > IsHidden ( ) | | ! ent - > IsActive ( ) | | ! ent - > fl . takedamage | | ent - > health < = 0 | | ! ent - > IsType ( idActor : : Type ) ) {
continue ;
}
if ( ! ent - > CanDamage ( GetPhysics ( ) - > GetOrigin ( ) , damagePoint ) ) {
continue ;
}
if ( ent - > IsType ( idPlayer : : Type ) ) {
idPlayer * player = static_cast < idPlayer * > ( ent ) ;
player - > playerView . EnableBFGVision ( true ) ;
}
beamTarget_t bt ;
memset ( & bt . renderEntity , 0 , sizeof ( renderEntity_t ) ) ;
bt . renderEntity . origin = GetPhysics ( ) - > GetOrigin ( ) ;
bt . renderEntity . axis = GetPhysics ( ) - > GetAxis ( ) ;
bt . renderEntity . shaderParms [ SHADERPARM_BEAM_WIDTH ] = beamWidth ;
bt . renderEntity . shaderParms [ SHADERPARM_RED ] = 1.0f ;
bt . renderEntity . shaderParms [ SHADERPARM_GREEN ] = 1.0f ;
bt . renderEntity . shaderParms [ SHADERPARM_BLUE ] = 1.0f ;
bt . renderEntity . shaderParms [ SHADERPARM_ALPHA ] = 1.0f ;
bt . renderEntity . shaderParms [ SHADERPARM_DIVERSITY ] = gameLocal . random . CRandomFloat ( ) * 0.75 ;
bt . renderEntity . hModel = renderModelManager - > FindModel ( " _beam " ) ;
bt . renderEntity . callback = NULL ;
bt . renderEntity . numJoints = 0 ;
bt . renderEntity . joints = NULL ;
bt . renderEntity . bounds . Clear ( ) ;
bt . renderEntity . customSkin = declManager - > FindSkin ( skin ) ;
bt . target = ent ;
bt . modelDefHandle = gameRenderWorld - > AddEntityDef ( & bt . renderEntity ) ;
beamTargets . Append ( bt ) ;
}
if ( numListedEntities ) {
StartSound ( " snd_beam " , SND_CHANNEL_BODY2 , 0 , false , NULL ) ;
}
damageFreq = spawnArgs . GetString ( " def_damageFreq " ) ;
nextDamageTime = gameLocal . time + BFG_DAMAGE_FREQUENCY ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Event_RemoveBeams
= = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Event_RemoveBeams ( ) {
FreeBeams ( ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idProjectile : : Explode
= = = = = = = = = = = = = = = =
*/
void idBFGProjectile : : Explode ( const trace_t & collision , idEntity * ignore ) {
int i ;
idVec3 dmgPoint ;
idVec3 dir ;
float beamWidth ;
float damageScale ;
const char * damage ;
idPlayer * player ;
idEntity * ownerEnt ;
ownerEnt = owner . GetEntity ( ) ;
if ( ownerEnt & & ownerEnt - > IsType ( idPlayer : : Type ) ) {
player = static_cast < idPlayer * > ( ownerEnt ) ;
} else {
player = NULL ;
}
beamWidth = spawnArgs . GetFloat ( " beam_WidthExplode " ) ;
damage = spawnArgs . GetString ( " def_damage " ) ;
for ( i = 0 ; i < beamTargets . Num ( ) ; i + + ) {
if ( ( beamTargets [ i ] . target . GetEntity ( ) = = NULL ) | | ( ownerEnt = = NULL ) ) {
continue ;
}
if ( ! beamTargets [ i ] . target . GetEntity ( ) - > CanDamage ( GetPhysics ( ) - > GetOrigin ( ) , dmgPoint ) ) {
continue ;
}
beamTargets [ i ] . renderEntity . shaderParms [ SHADERPARM_BEAM_WIDTH ] = beamWidth ;
// if the hit entity takes damage
if ( damagePower ) {
damageScale = damagePower ;
} else {
damageScale = 1.0f ;
}
// if the projectile owner is a player
if ( player ) {
// if the projectile hit an actor
if ( beamTargets [ i ] . target . GetEntity ( ) - > IsType ( idActor : : Type ) ) {
player - > SetLastHitTime ( gameLocal . time ) ;
player - > AddProjectileHits ( 1 ) ;
damageScale * = player - > PowerUpModifier ( PROJECTILE_DAMAGE ) ;
}
}
if ( damage [ 0 ] & & ( beamTargets [ i ] . target . GetEntity ( ) - > entityNumber > gameLocal . numClients - 1 ) ) {
dir = beamTargets [ i ] . target . GetEntity ( ) - > GetPhysics ( ) - > GetOrigin ( ) - GetPhysics ( ) - > GetOrigin ( ) ;
dir . Normalize ( ) ;
beamTargets [ i ] . target . GetEntity ( ) - > Damage ( this , ownerEnt , dir , damage , damageScale , ( collision . c . id < 0 ) ? CLIPMODEL_ID_TO_JOINT_HANDLE ( collision . c . id ) : INVALID_JOINT ) ;
}
}
if ( secondModelDefHandle > = 0 ) {
gameRenderWorld - > FreeEntityDef ( secondModelDefHandle ) ;
secondModelDefHandle = - 1 ;
}
2018-08-26 03:41:08 +00:00
/* if ( ignore == NULL ) { // This causes trouble like splash damage not working at all
2011-11-22 21:28:15 +00:00
projectileFlags . noSplashDamage = true ;
2018-08-26 03:41:08 +00:00
} */
2011-11-22 21:28:15 +00:00
if ( ! gameLocal . isClient ) {
if ( ignore ! = NULL ) {
PostEventMS ( & EV_RemoveBeams , 750 ) ;
} else {
PostEventMS ( & EV_RemoveBeams , 0 ) ;
}
}
return idProjectile : : Explode ( collision , ignore ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idDebris
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
CLASS_DECLARATION ( idEntity , idDebris )
EVENT ( EV_Explode , idDebris : : Event_Explode )
EVENT ( EV_Fizzle , idDebris : : Event_Fizzle )
END_CLASS
/*
= = = = = = = = = = = = = = = =
idDebris : : Spawn
= = = = = = = = = = = = = = = =
*/
void idDebris : : Spawn ( void ) {
owner = NULL ;
smokeFly = NULL ;
smokeFlyTime = 0 ;
2018-08-26 03:41:08 +00:00
nextSoundTime = 0 ; // BY Clone JCD
soundTimeDifference = 0 ; //
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Create
= = = = = = = = = = = = = = = =
*/
void idDebris : : Create ( idEntity * owner , const idVec3 & start , const idMat3 & axis ) {
Unbind ( ) ;
GetPhysics ( ) - > SetOrigin ( start ) ;
GetPhysics ( ) - > SetAxis ( axis ) ;
GetPhysics ( ) - > SetContents ( 0 ) ;
this - > owner = owner ;
smokeFly = NULL ;
smokeFlyTime = 0 ;
2018-08-26 03:41:08 +00:00
nextSoundTime = 0 ; // BY Clone JCD
soundTimeDifference = 0 ; //
2011-11-22 21:28:15 +00:00
sndBounce = NULL ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDebris : : idDebris
= = = = = = = = = = = = = = = = =
*/
idDebris : : idDebris ( void ) {
owner = NULL ;
smokeFly = NULL ;
smokeFlyTime = 0 ;
sndBounce = NULL ;
2018-08-26 03:41:08 +00:00
nextSoundTime = 0 ; // BY Clone JCD
soundTimeDifference = 0 ; //
2011-11-22 21:28:15 +00:00
}
/*
= = = = = = = = = = = = = = = = =
idDebris : : ~ idDebris
= = = = = = = = = = = = = = = = =
*/
idDebris : : ~ idDebris ( void ) {
}
/*
= = = = = = = = = = = = = = = = =
idDebris : : Save
= = = = = = = = = = = = = = = = =
*/
void idDebris : : Save ( idSaveGame * savefile ) const {
owner . Save ( savefile ) ;
savefile - > WriteStaticObject ( physicsObj ) ;
savefile - > WriteParticle ( smokeFly ) ;
savefile - > WriteInt ( smokeFlyTime ) ;
2018-08-26 03:41:08 +00:00
// savefile->WriteInt( nextSoundTime ); // No need to store this value, BY Clone JCD
savefile - > WriteInt ( soundTimeDifference ) ; //
2011-11-22 21:28:15 +00:00
savefile - > WriteSoundShader ( sndBounce ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDebris : : Restore
= = = = = = = = = = = = = = = = =
*/
void idDebris : : Restore ( idRestoreGame * savefile ) {
owner . Restore ( savefile ) ;
savefile - > ReadStaticObject ( physicsObj ) ;
RestorePhysics ( & physicsObj ) ;
savefile - > ReadParticle ( smokeFly ) ;
savefile - > ReadInt ( smokeFlyTime ) ;
2018-08-26 03:41:08 +00:00
//savefile->ReadInt( nextSoundTime ); // No need to store this value, BY Clone JCD
savefile - > ReadInt ( soundTimeDifference ) ; //
2011-11-22 21:28:15 +00:00
savefile - > ReadSoundShader ( sndBounce ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDebris : : Launch
= = = = = = = = = = = = = = = = =
*/
void idDebris : : Launch ( void ) {
float fuse ;
idVec3 velocity ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
idVec3 angular_velocity_vect ;
# else
2011-11-22 21:28:15 +00:00
idAngles angular_velocity ;
2018-08-26 03:41:08 +00:00
# endif
2011-11-22 21:28:15 +00:00
float linear_friction ;
float angular_friction ;
float contact_friction ;
float bounce ;
float mass ;
float gravity ;
idVec3 gravVec ;
bool randomVelocity ;
idMat3 axis ;
renderEntity . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
spawnArgs . GetVector ( " velocity " , " 0 0 0 " , velocity ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
angular_velocity_vect = spawnArgs . GetAngles ( " angular_velocity " , " 0 0 0 " ) . ToAngularVelocity ( ) ;
# else
2011-11-22 21:28:15 +00:00
spawnArgs . GetAngles ( " angular_velocity " , " 0 0 0 " , angular_velocity ) ;
2018-08-26 03:41:08 +00:00
# endif
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
linear_friction = spawnArgs . GetFloat ( " linear_friction " ) ;
angular_friction = spawnArgs . GetFloat ( " angular_friction " ) ;
contact_friction = spawnArgs . GetFloat ( " contact_friction " ) ;
bounce = spawnArgs . GetFloat ( " bounce " ) ;
mass = spawnArgs . GetFloat ( " mass " ) ;
gravity = spawnArgs . GetFloat ( " gravity " ) ;
fuse = spawnArgs . GetFloat ( " fuse " ) ;
randomVelocity = spawnArgs . GetBool ( " random_velocity " ) ;
2018-08-26 03:41:08 +00:00
continuousSmoke = spawnArgs . GetBool ( " smoke_continuous " ) ;
2011-11-22 21:28:15 +00:00
if ( mass < = 0 ) {
gameLocal . Error ( " Invalid mass on '%s' \n " , GetEntityDefName ( ) ) ;
}
if ( randomVelocity ) {
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
float rand = spawnArgs . GetFloat ( " linear_velocity_rand " , " 0.35 " ) ;
// sets velocity randomly between ((1-rand)*100)% and ((1+rand)*100)%
// e.g.1: if rand = 0.2, velocity will be randomly set between 80% and 120%
// e.g.2: if rand = 0.3, velocity will be randomly set between 70% and 130%
// and so on.
velocity . x * = gameLocal . random . RandomFloat ( ) * rand * 2.0 + 1.0 - rand ;
velocity . y * = gameLocal . random . RandomFloat ( ) * rand * 2.0 + 1.0 - rand ;
velocity . z * = gameLocal . random . RandomFloat ( ) * rand * 2.0 + 1.0 - rand ;
// do not perform following calculations unless there's key in decl that says so.
if ( spawnArgs . GetFloat ( " angular_velocity_rand " , " 0.0 " , rand ) & & rand > 0.0f ) {
angular_velocity_vect . x * = gameLocal . random . RandomFloat ( ) * rand * 2.0 + 1.0 - rand ;
angular_velocity_vect . y * = gameLocal . random . RandomFloat ( ) * rand * 2.0 + 1.0 - rand ;
angular_velocity_vect . z * = gameLocal . random . RandomFloat ( ) * rand * 2.0 + 1.0 - rand ;
}
# else
2011-11-22 21:28:15 +00:00
velocity . x * = gameLocal . random . RandomFloat ( ) + 0.5f ;
velocity . y * = gameLocal . random . RandomFloat ( ) + 0.5f ;
velocity . z * = gameLocal . random . RandomFloat ( ) + 0.5f ;
2018-08-26 03:41:08 +00:00
# endif
2011-11-22 21:28:15 +00:00
}
if ( health ) {
fl . takedamage = true ;
}
gravVec = gameLocal . GetGravity ( ) ;
gravVec . NormalizeFast ( ) ;
axis = GetPhysics ( ) - > GetAxis ( ) ;
Unbind ( ) ;
physicsObj . SetSelf ( this ) ;
// check if a clip model is set
const char * clipModelName ;
idTraceModel trm ;
spawnArgs . GetString ( " clipmodel " , " " , & clipModelName ) ;
if ( ! clipModelName [ 0 ] ) {
clipModelName = spawnArgs . GetString ( " model " ) ; // use the visual model
}
// load the trace model
if ( ! collisionModelManager - > TrmFromModel ( clipModelName , trm ) ) {
// default to a box
physicsObj . SetClipBox ( renderEntity . bounds , 1.0f ) ;
} else {
physicsObj . SetClipModel ( new idClipModel ( trm ) , 1.0f ) ;
}
physicsObj . GetClipModel ( ) - > SetOwner ( owner . GetEntity ( ) ) ;
physicsObj . SetMass ( mass ) ;
physicsObj . SetFriction ( linear_friction , angular_friction , contact_friction ) ;
if ( contact_friction = = 0.0f ) {
physicsObj . NoContact ( ) ;
}
physicsObj . SetBouncyness ( bounce ) ;
physicsObj . SetGravity ( gravVec * gravity ) ;
physicsObj . SetContents ( 0 ) ;
physicsObj . SetClipMask ( MASK_SOLID | CONTENTS_MOVEABLECLIP ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
// Make sure that the linear velocity is added with
// owner's linear velocity for more accurate physics simulation.
idEntity * ownerEnt = owner . GetEntity ( ) ;
if ( ownerEnt ! = NULL ) {
physicsObj . SetLinearVelocity ( ( axis [ 0 ] * velocity [ 0 ] + axis [ 1 ] * velocity [ 1 ] + axis [ 2 ] * velocity [ 2 ] ) + ownerEnt - > GetPhysics ( ) - > GetLinearVelocity ( ) ) ;
}
else {
physicsObj . SetLinearVelocity ( axis [ 0 ] * velocity [ 0 ] + axis [ 1 ] * velocity [ 1 ] + axis [ 2 ] * velocity [ 2 ] ) ;
}
physicsObj . SetAngularVelocity ( angular_velocity_vect * axis ) ;
# else
2011-11-22 21:28:15 +00:00
physicsObj . SetLinearVelocity ( axis [ 0 ] * velocity [ 0 ] + axis [ 1 ] * velocity [ 1 ] + axis [ 2 ] * velocity [ 2 ] ) ;
physicsObj . SetAngularVelocity ( angular_velocity . ToAngularVelocity ( ) * axis ) ;
2018-08-26 03:41:08 +00:00
# endif
2011-11-22 21:28:15 +00:00
physicsObj . SetOrigin ( GetPhysics ( ) - > GetOrigin ( ) ) ;
physicsObj . SetAxis ( axis ) ;
SetPhysics ( & physicsObj ) ;
if ( ! gameLocal . isClient ) {
if ( fuse < = 0 ) {
// run physics for 1 second
RunPhysics ( ) ;
PostEventMS ( & EV_Remove , 0 ) ;
} else if ( spawnArgs . GetBool ( " detonate_on_fuse " ) ) {
if ( fuse < 0.0f ) {
fuse = 0.0f ;
}
RunPhysics ( ) ;
PostEventSec ( & EV_Explode , fuse ) ;
} else {
if ( fuse < 0.0f ) {
fuse = 0.0f ;
}
PostEventSec ( & EV_Fizzle , fuse ) ;
}
}
StartSound ( " snd_fly " , SND_CHANNEL_BODY , 0 , false , NULL ) ;
smokeFly = NULL ;
smokeFlyTime = 0 ;
const char * smokeName = spawnArgs . GetString ( " smoke_fly " ) ;
if ( * smokeName ! = ' \0 ' ) {
smokeFly = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , smokeName ) ) ;
smokeFlyTime = gameLocal . time ;
gameLocal . smokeParticles - > EmitSmoke ( smokeFly , smokeFlyTime , gameLocal . random . CRandomFloat ( ) , GetPhysics ( ) - > GetOrigin ( ) , GetPhysics ( ) - > GetAxis ( ) ) ;
}
const char * sndName = spawnArgs . GetString ( " snd_bounce " ) ;
2018-08-26 03:41:08 +00:00
nextSoundTime = 0 ; // BY Clone JCD
soundTimeDifference = spawnArgs . GetInt ( " next_sound_time " ) ; //
2011-11-22 21:28:15 +00:00
if ( * sndName ! = ' \0 ' ) {
sndBounce = declManager - > FindSound ( sndName ) ;
}
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Think
= = = = = = = = = = = = = = = =
*/
void idDebris : : Think ( void ) {
// run physics
RunPhysics ( ) ;
Present ( ) ;
2018-08-26 03:41:08 +00:00
if ( smokeFly & & smokeFlyTime & & ! IsHidden ( ) ) { // Emit particles only when visible
idVec3 dir = - GetPhysics ( ) - > GetLinearVelocity ( ) ;
dir . Normalize ( ) ;
if ( ! gameLocal . smokeParticles - > EmitSmoke ( smokeFly , smokeFlyTime , gameLocal . random . CRandomFloat ( ) , GetPhysics ( ) - > GetOrigin ( ) , dir . ToMat3 ( ) ) ) {
if ( continuousSmoke ) {
smokeFlyTime = gameLocal . time ; // Emit particles continuously - Clone JC Denton
}
else {
smokeFlyTime = 0 ;
}
2011-11-22 21:28:15 +00:00
}
}
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Killed
= = = = = = = = = = = = = = = =
*/
void idDebris : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location ) {
if ( spawnArgs . GetBool ( " detonate_on_death " ) ) {
Explode ( ) ;
} else {
Fizzle ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idDebris : : Collide
= = = = = = = = = = = = = = = = =
*/
bool idDebris : : Collide ( const trace_t & collision , const idVec3 & velocity ) {
2018-08-26 03:41:08 +00:00
if ( sndBounce ! = NULL ) {
if ( ! soundTimeDifference ) {
StartSoundShader ( sndBounce , SND_CHANNEL_BODY , 0 , false , NULL ) ;
sndBounce = NULL ;
return false ;
}
if ( gameLocal . time > nextSoundTime ) {
float v = - ( velocity * collision . c . normal ) ;
if ( v > BOUNCE_SOUND_MIN_VELOCITY ) {
float f = v > BOUNCE_SOUND_MAX_VELOCITY ? 1.0f : idMath : : Sqrt ( v - BOUNCE_SOUND_MIN_VELOCITY ) * ( 1.0f / idMath : : Sqrt ( BOUNCE_SOUND_MAX_VELOCITY - BOUNCE_SOUND_MIN_VELOCITY ) ) ;
if ( StartSoundShader ( sndBounce , SND_CHANNEL_BODY , 0 , false , NULL ) )
SetSoundVolume ( f ) ;
}
else {
float f = ( 0.5f / idMath : : Sqrt ( BOUNCE_SOUND_MAX_VELOCITY - BOUNCE_SOUND_MIN_VELOCITY ) ) ;
if ( StartSoundShader ( sndBounce , SND_CHANNEL_BODY , 0 , false , NULL ) )
SetSoundVolume ( f ) ;
sndBounce = NULL ;
return false ;
}
nextSoundTime = gameLocal . time + soundTimeDifference ;
}
2011-11-22 21:28:15 +00:00
}
2018-08-26 03:41:08 +00:00
2011-11-22 21:28:15 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Fizzle
= = = = = = = = = = = = = = = =
*/
void idDebris : : Fizzle ( void ) {
if ( IsHidden ( ) ) {
// already exploded
return ;
}
StopSound ( SND_CHANNEL_ANY , false ) ;
StartSound ( " snd_fizzle " , SND_CHANNEL_BODY , 0 , false , NULL ) ;
// fizzle FX
const char * smokeName = spawnArgs . GetString ( " smoke_fuse " ) ;
if ( * smokeName ! = ' \0 ' ) {
smokeFly = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , smokeName ) ) ;
smokeFlyTime = gameLocal . time ;
gameLocal . smokeParticles - > EmitSmoke ( smokeFly , smokeFlyTime , gameLocal . random . CRandomFloat ( ) , GetPhysics ( ) - > GetOrigin ( ) , GetPhysics ( ) - > GetAxis ( ) ) ;
}
fl . takedamage = false ;
physicsObj . SetContents ( 0 ) ;
physicsObj . PutToRest ( ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
BecomeInactive ( TH_PHYSICS ) ; // This causes the physics not to update after explosion
# endif
2011-11-22 21:28:15 +00:00
Hide ( ) ;
if ( gameLocal . isClient ) {
return ;
}
CancelEvents ( & EV_Fizzle ) ;
PostEventMS ( & EV_Remove , 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Explode
= = = = = = = = = = = = = = = =
*/
void idDebris : : Explode ( void ) {
if ( IsHidden ( ) ) {
// already exploded
return ;
}
StopSound ( SND_CHANNEL_ANY , false ) ;
StartSound ( " snd_explode " , SND_CHANNEL_BODY , 0 , false , NULL ) ;
Hide ( ) ;
// these must not be "live forever" particle systems
smokeFly = NULL ;
smokeFlyTime = 0 ;
const char * smokeName = spawnArgs . GetString ( " smoke_detonate " ) ;
if ( * smokeName ! = ' \0 ' ) {
smokeFly = static_cast < const idDeclParticle * > ( declManager - > FindType ( DECL_PARTICLE , smokeName ) ) ;
smokeFlyTime = gameLocal . time ;
gameLocal . smokeParticles - > EmitSmoke ( smokeFly , smokeFlyTime , gameLocal . random . CRandomFloat ( ) , GetPhysics ( ) - > GetOrigin ( ) , GetPhysics ( ) - > GetAxis ( ) ) ;
}
fl . takedamage = false ;
physicsObj . SetContents ( 0 ) ;
physicsObj . PutToRest ( ) ;
2018-08-26 03:41:08 +00:00
# ifdef _DENTONMOD
BecomeInactive ( TH_PHYSICS ) ; // This causes the physics not to update after explosion
# endif
2011-11-22 21:28:15 +00:00
CancelEvents ( & EV_Explode ) ;
PostEventMS ( & EV_Remove , 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Event_Explode
= = = = = = = = = = = = = = = =
*/
void idDebris : : Event_Explode ( void ) {
Explode ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idDebris : : Event_Fizzle
= = = = = = = = = = = = = = = =
*/
void idDebris : : Event_Fizzle ( void ) {
Fizzle ( ) ;
}