738 lines
17 KiB
Text
738 lines
17 KiB
Text
|
|
object deployable_artillery : deployable_base {
|
|
void preinit();
|
|
void init();
|
|
void destroy();
|
|
void syncFields();
|
|
|
|
void vDoneDeploy();
|
|
|
|
void TurningThread();
|
|
|
|
void ServerIdle();
|
|
void ServerAiming();
|
|
void ServerFiring();
|
|
|
|
void ClientIdle();
|
|
void ClientFiring();
|
|
|
|
void StopRotationSounds();
|
|
|
|
void vTargetSetTarget( vector targetPos, entity targetEnt );
|
|
boolean vTargetGetValid( vector targetPos );
|
|
boolean vTargetPlayerEligible( entity p );
|
|
|
|
float vGetFireSupportMode();
|
|
|
|
//
|
|
boolean InRange( vector targetPos );
|
|
boolean InFiringRange( vector targetPos ) { return InRange( targetPos ); }
|
|
void UpdateTurning();
|
|
boolean UpdateYaw();
|
|
boolean UpdatePitch();
|
|
void ResetAngles();
|
|
void TurnToward( float yaw, float pitch );
|
|
boolean PitchValid( float pitch );
|
|
boolean CalcTargetAngles( vector targetPos );
|
|
string MuzzleForMissile( float missileIndex );
|
|
|
|
// utility funcs ( none of these should be blocking )
|
|
void Launch( float missileIndex );
|
|
void FireMissile( float missileIndex );
|
|
void LaunchForEffect();
|
|
|
|
float GetMissileBarrelLength( float index );
|
|
void SetMissileBarrelLength( float index, float value );
|
|
float GetMissileSideOffset( float index );
|
|
void SetMissileSideOffset( float index, float value );
|
|
|
|
void OnFireSupportStateChanged();
|
|
|
|
target_marker vCreateTargetMarker();
|
|
|
|
void ClearFiringDecal();
|
|
void CreateFiringDecal();
|
|
|
|
void ReloadThread( float delay );
|
|
|
|
float recycle;
|
|
float fireCount;
|
|
float reloadWait;
|
|
float numMissiles;
|
|
float fireSyncDelay;
|
|
float nextFire;
|
|
|
|
float jointYaw;
|
|
float idealYaw;
|
|
float currentYaw;
|
|
float oldIdealYaw;
|
|
float minYawRate;
|
|
float maxYawRate;
|
|
|
|
float jointPitch;
|
|
float idealPitch;
|
|
float currentPitch;
|
|
float oldIdealPitch;
|
|
float minPitchRate;
|
|
float maxPitchRate;
|
|
|
|
float jointBarrel;
|
|
|
|
float minPitch;
|
|
float maxPitch;
|
|
|
|
float minRange;
|
|
float maxRange;
|
|
|
|
float missileSpeed;
|
|
|
|
float spread;
|
|
|
|
float clientState;
|
|
|
|
float targetYaw;
|
|
float targetPitch;
|
|
vector targetDiff;
|
|
|
|
float baseYaw;
|
|
float barrelPitch;
|
|
vector firingOffset;
|
|
vector firingVelocity;
|
|
boolean hasTarget;
|
|
entity targetPlayerEnemy;
|
|
vector targetLocation;
|
|
float projectileIndex;
|
|
float projectileForEffectIndex;
|
|
|
|
generic_target_marker firingDecal;
|
|
entity firingMarker;
|
|
|
|
boolean anglesLocked;
|
|
}
|
|
|
|
float deployable_artillery::GetMissileBarrelLength( float index ) {
|
|
return getFloatKey( "missile" + ( index + 1 ) + "_barrel_length" );
|
|
}
|
|
|
|
void deployable_artillery::SetMissileBarrelLength( float index, float value ) {
|
|
setKey( "missile" + ( index + 1 ) + "_barrel_length", value );
|
|
}
|
|
|
|
float deployable_artillery::GetMissileSideOffset( float index ) {
|
|
return getFloatKey( "missile" + ( index + 1 ) + "_side_offset" );
|
|
}
|
|
|
|
void deployable_artillery::SetMissileSideOffset( float index, float value ) {
|
|
setKey( "missile" + ( index + 1 ) + "_side_offset", value );
|
|
}
|
|
|
|
void deployable_artillery::OnFireSupportStateChanged() {
|
|
if ( fireSupportState == MPS_FIRING ) {
|
|
if ( clientState != ART_CS_FIRING ) {
|
|
setState( "ClientFiring" );
|
|
}
|
|
} else {
|
|
if ( clientState != ART_CS_IDLE ) {
|
|
setState( "ClientIdle" );
|
|
}
|
|
}
|
|
}
|
|
|
|
void deployable_artillery::syncFields() {
|
|
syncBroadcast( "nextFire" );
|
|
syncBroadcast( "targetLocation" );
|
|
syncBroadcast( "fireSupportState" );
|
|
syncBroadcast( "idealYaw" );
|
|
syncBroadcast( "idealPitch" );
|
|
syncBroadcast( "oldIdealYaw" );
|
|
syncBroadcast( "oldIdealPitch" );
|
|
|
|
syncCallback( "fireSupportState", "OnFireSupportStateChanged" );
|
|
|
|
sync( "currentYaw" );
|
|
sync( "currentPitch" );
|
|
}
|
|
|
|
void deployable_artillery::destroy() {
|
|
ClearFiringDecal();
|
|
delete fsStatus;
|
|
}
|
|
|
|
float deployable_artillery::vGetFireSupportMode() {
|
|
return TARGET_ARTILLERY;
|
|
}
|
|
|
|
void deployable_artillery::preinit() {
|
|
recycle = getFloatKey( "missile_recycle" );
|
|
fireCount = getFloatKey( "missile_firecount" );
|
|
reloadWait = getFloatKey( "missile_reload" );
|
|
numMissiles = getFloatKey( "num_missiles" );
|
|
fireSyncDelay = getFloatKey( "sync_delay" );
|
|
spread = getFloatKey( "spread" );
|
|
|
|
if ( fireCount <= 0 ) {
|
|
fireCount = 6;
|
|
}
|
|
if ( reloadWait <= 0 ) {
|
|
reloadWait = 30;
|
|
}
|
|
if ( fireSyncDelay <= 0 ) {
|
|
fireSyncDelay = 0.5;
|
|
}
|
|
|
|
jointYaw = getJointHandle( getKey( "joint_yaw" ) );
|
|
jointPitch = getJointHandle( getKey( "joint_pitch" ) );
|
|
jointBarrel = getJointHandle( getKey( "joint_barrel" ) );
|
|
|
|
projectileIndex = GetEntityDef( getKey( "def_projectile" ) );
|
|
projectileForEffectIndex = GetEntityDef( getKey( "def_projectile_foreffect" ) );
|
|
|
|
currentYaw = 0;
|
|
idealYaw = 0;
|
|
oldIdealYaw = 0;
|
|
maxYawRate = getFloatKey( "max_yaw_turn" );
|
|
minYawRate = getFloatKey( "min_yaw_turn" );
|
|
|
|
currentPitch = 0;
|
|
idealPitch = 0;
|
|
oldIdealPitch = 0;
|
|
maxPitchRate = getFloatKey( "max_pitch_turn" );
|
|
minPitchRate = getFloatKey( "min_pitch_turn" );
|
|
|
|
minPitch = getFloatKey( "min_pitch" );
|
|
maxPitch = getFloatKey( "max_pitch" );
|
|
|
|
minRange = getFloatKey( "range_min" );
|
|
maxRange = getFloatKey( "range_max" );
|
|
|
|
missileSpeed = getFloatKey( "missile_speed" );
|
|
|
|
hasTarget = false;
|
|
|
|
nextFire = 0;
|
|
|
|
fsStatus = new fireSupportStatus;
|
|
|
|
thread TurningThread();
|
|
}
|
|
|
|
void deployable_artillery::vDoneDeploy() {
|
|
vector barrel;
|
|
float i;
|
|
float muzzleHandle;
|
|
vector pitchJointPos;
|
|
float sideOffset;
|
|
float barrelLength;
|
|
|
|
pitchJointPos = getLocalJointPos( jointPitch );
|
|
barrel = getLocalJointPos( jointBarrel ) - pitchJointPos;
|
|
barrelPitch = sys.atan2( barrel_z, barrel_x );
|
|
|
|
for ( i = 0; i < numMissiles; i++ ) {
|
|
muzzleHandle = getJointHandle( MuzzleForMissile( i ) );
|
|
barrel = getLocalJointPos( muzzleHandle ) - pitchJointPos;
|
|
sideOffset = barrel_y;
|
|
barrel_y = 0;
|
|
barrelLength = sys.vecLength( barrel );
|
|
|
|
SetMissileSideOffset( i, sideOffset );
|
|
SetMissileBarrelLength( i, barrelLength );
|
|
}
|
|
|
|
vector angles = getAngles();
|
|
baseYaw = angles_y;
|
|
|
|
SetDeployingFinished();
|
|
}
|
|
|
|
void deployable_artillery::init() {
|
|
fadeSound( SND_DEPLOYABLE_YAW, -60.f, 0.f );
|
|
fadeSound( SND_DEPLOYABLE_PITCH, -60.f, 0.f );
|
|
startSound( "snd_turret_yaw", SND_DEPLOYABLE_YAW );
|
|
startSound( "snd_turret_pitch", SND_DEPLOYABLE_PITCH );
|
|
|
|
if ( sys.isClient() ) {
|
|
setState( "ClientIdle" );
|
|
} else {
|
|
setState( "ServerIdle" );
|
|
}
|
|
}
|
|
|
|
// ==========================================
|
|
// States
|
|
// ==========================================
|
|
|
|
void deployable_artillery::TurningThread() {
|
|
while( true ) {
|
|
sys.waitFrame();
|
|
|
|
if ( disabledState ) {
|
|
StopRotationSounds();
|
|
} else {
|
|
UpdateTurning();
|
|
}
|
|
}
|
|
}
|
|
|
|
void deployable_artillery::ClientIdle() {
|
|
clientState = ART_CS_IDLE;
|
|
|
|
ClearFiringDecal();
|
|
}
|
|
|
|
void deployable_artillery::ServerIdle() {
|
|
hasTarget = false;
|
|
ResetAngles();
|
|
|
|
ClearFiringDecal();
|
|
}
|
|
|
|
void deployable_artillery::ReloadThread( float delay ) {
|
|
fireSupportState = MPS_RELOADING;
|
|
|
|
sys.wait( delay );
|
|
|
|
fireSupportState = MPS_READY;
|
|
}
|
|
|
|
void deployable_artillery::StopRotationSounds() {
|
|
DEPLOYABLE_STOP_YAW_SOUND
|
|
DEPLOYABLE_STOP_PITCH_SOUND
|
|
}
|
|
|
|
void deployable_artillery::UpdateTurning() {
|
|
boolean yawDone;
|
|
boolean pitchDone;
|
|
vector angles;
|
|
|
|
yawDone = UpdateYaw();
|
|
pitchDone = UpdatePitch();
|
|
|
|
if ( !yawDone ) {
|
|
angles_x = 0;
|
|
angles_y = currentYaw;
|
|
angles_z = 0;
|
|
setJointAngle( jointYaw, JOINTMOD_LOCAL, angles );
|
|
|
|
DEPLOYABLE_PLAY_YAW_SOUND
|
|
} else {
|
|
DEPLOYABLE_STOP_YAW_SOUND
|
|
}
|
|
|
|
if ( !pitchDone ) {
|
|
angles_x = currentPitch;
|
|
angles_y = 0;
|
|
angles_z = 0;
|
|
setJointAngle( jointPitch, JOINTMOD_LOCAL, angles );
|
|
|
|
DEPLOYABLE_PLAY_PITCH_SOUND
|
|
} else {
|
|
DEPLOYABLE_STOP_PITCH_SOUND
|
|
}
|
|
|
|
if ( yawDone && pitchDone ) {
|
|
anglesLocked = true;
|
|
} else {
|
|
anglesLocked = false;
|
|
}
|
|
}
|
|
|
|
void deployable_artillery::ServerAiming() {
|
|
fireSupportState = MPS_FIRING_PREPARE;
|
|
|
|
while ( !anglesLocked ) {
|
|
sys.waitFrame();
|
|
|
|
if ( disabledState ) {
|
|
fireSupportState = MPS_READY;
|
|
|
|
setState( "ServerIdle" );
|
|
}
|
|
}
|
|
|
|
setState( "ServerFiring" );
|
|
}
|
|
|
|
void deployable_artillery::ClientFiring() {
|
|
float nextMiniFire = 0;
|
|
float nextMiniCount = 0;
|
|
float baseFireTime = 0;
|
|
|
|
CreateFiringDecal();
|
|
|
|
clientState = ART_CS_FIRING;
|
|
|
|
if ( projectileForEffectIndex >= 0 ) {
|
|
LaunchForEffect();
|
|
sys.wait( getFloatKey( "foreffect_wait" ) );
|
|
}
|
|
|
|
while( true ) {
|
|
if ( nextFire < sys.getTime() ) {
|
|
baseFireTime = sys.getTime();
|
|
nextFire = baseFireTime + recycle;
|
|
|
|
nextMiniCount = 0;
|
|
nextMiniFire = baseFireTime + getFloatKey( "missile" + ( nextMiniCount + 1 ) + "_delay" );
|
|
}
|
|
|
|
if ( nextMiniCount < numMissiles ) {
|
|
if( nextMiniFire < sys.getTime() ) {
|
|
|
|
Launch( nextMiniCount );
|
|
|
|
nextMiniCount++;
|
|
nextMiniFire = baseFireTime + getFloatKey( "missile" + ( nextMiniCount + 1 ) + "_delay" );
|
|
}
|
|
}
|
|
|
|
sys.waitFrame();
|
|
}
|
|
}
|
|
|
|
void deployable_artillery::ServerFiring() {
|
|
float count = fireCount;
|
|
float nextMiniFire = 0;
|
|
float nextMiniCount = 0;
|
|
float baseFireTime = 0;
|
|
|
|
fireSupportState = MPS_FIRING;
|
|
|
|
nextFire = sys.getTime() + 1.f;
|
|
|
|
if ( projectileForEffectIndex >= 0 ) {
|
|
LaunchForEffect();
|
|
sys.wait( getFloatKey( "foreffect_wait" ) );
|
|
}
|
|
|
|
objManager.PlaySoundForPlayer( getKey( "snd_firing" ), owner );
|
|
|
|
while( true ) {
|
|
if ( disabledState ) {
|
|
break;
|
|
}
|
|
|
|
if ( nextFire < sys.getTime() ) {
|
|
baseFireTime = sys.getTime();
|
|
nextFire = baseFireTime + recycle;
|
|
count = count - 1;
|
|
if ( count < 0 ) {
|
|
break;
|
|
}
|
|
|
|
nextMiniCount = 0;
|
|
nextMiniFire = baseFireTime + getFloatKey( "missile" + ( nextMiniCount + 1 ) + "_delay" );
|
|
}
|
|
|
|
if ( nextMiniCount < numMissiles ) {
|
|
if ( nextMiniFire != 0 && nextMiniFire < sys.getTime() ) {
|
|
|
|
Launch( nextMiniCount );
|
|
|
|
nextMiniCount++;
|
|
nextMiniFire = baseFireTime + getFloatKey( "missile" + ( nextMiniCount + 1 ) + "_delay" );
|
|
}
|
|
}
|
|
|
|
sys.waitFrame();
|
|
}
|
|
|
|
nextFire = 0;
|
|
|
|
thread ReloadThread( reloadWait );
|
|
|
|
setState( "ServerIdle" );
|
|
}
|
|
|
|
// ==========================================
|
|
// Utility Funcs
|
|
// ==========================================
|
|
|
|
string deployable_artillery::MuzzleForMissile( float missileIndex ) {
|
|
return getKey( "missile" + ( missileIndex + 1 ) + "_barrel" );
|
|
}
|
|
|
|
void deployable_artillery::FireMissile( float missileIndex ) {
|
|
vector org;
|
|
|
|
org = getJointPos( jointPitch ) + firingOffset + ( getWorldAxis( 1 ) * GetMissileSideOffset( missileIndex ) );
|
|
|
|
launchMissileSimple( owner, self, targetPlayerEnemy, projectileIndex, -1, spread, org, firingVelocity );
|
|
|
|
playEffect( "fx_fire", MuzzleForMissile( missileIndex ), 0 );
|
|
}
|
|
|
|
void deployable_artillery::Launch( float missileIndex ) {
|
|
string anim;
|
|
float channel;
|
|
|
|
FireMissile( missileIndex );
|
|
|
|
anim = getKey( "missile" + ( missileIndex + 1 ) + "_anim" );
|
|
if ( anim != "" ) {
|
|
channel = getIntKey( "missile" + ( missileIndex + 1 ) + "_channel" );
|
|
|
|
playAnim( channel, anim );
|
|
}
|
|
}
|
|
|
|
void deployable_artillery::LaunchForEffect() {
|
|
string anim;
|
|
float channel;
|
|
vector org;
|
|
|
|
org = getJointPos( jointPitch ) + firingOffset + ( getWorldAxis( 1 ) * GetMissileSideOffset( 0 ) );
|
|
|
|
launchMissileSimple( owner, self, $null_entity, projectileForEffectIndex, -1, 0.0, org, firingVelocity );
|
|
|
|
// objManager.PlaySoundForPlayer( getKey( "snd_effect" ), owner );
|
|
|
|
playEffect( "fx_fire", MuzzleForMissile( 0 ), 0 );
|
|
|
|
anim = getKey( "missile1_anim" );
|
|
if ( anim != "" ) {
|
|
channel = getIntKey( "missile1_channel" );
|
|
playAnim( channel, anim );
|
|
}
|
|
}
|
|
|
|
// ==========================================
|
|
// ==========================================
|
|
|
|
boolean deployable_artillery::UpdateYaw() {
|
|
float ang;
|
|
float maxTurn;
|
|
float frac;
|
|
|
|
if ( idealYaw == currentYaw ) {
|
|
return true;
|
|
}
|
|
|
|
ang = sys.angleNormalize180( idealYaw - currentYaw );
|
|
frac = sys.sin( sys.fabs( ang / sys.angleNormalize180( idealYaw - oldIdealYaw ) ) * 180.f );
|
|
|
|
maxTurn = ( minYawRate + ( maxYawRate - minYawRate ) * frac ) * sys.getFrameTime();
|
|
|
|
if ( ang < -maxTurn ) {
|
|
currentYaw = currentYaw - maxTurn;
|
|
} else if ( ang > maxTurn ) {
|
|
currentYaw = currentYaw + maxTurn;
|
|
} else {
|
|
currentYaw = idealYaw;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
boolean deployable_artillery::UpdatePitch() {
|
|
float ang;
|
|
float maxTurn;
|
|
float frac;
|
|
|
|
if ( idealPitch == currentPitch ) {
|
|
return true;
|
|
}
|
|
|
|
ang = sys.angleNormalize180( idealPitch - currentPitch );
|
|
frac = sys.sin( sys.fabs( ang / sys.angleNormalize180( idealPitch - oldIdealPitch ) ) * 180.f );
|
|
|
|
maxTurn = ( minPitchRate + ( maxPitchRate - minPitchRate ) * frac ) * sys.getFrameTime();
|
|
|
|
if ( ang < -maxTurn ) {
|
|
currentPitch = currentPitch - maxTurn;
|
|
} else if ( ang > maxTurn ) {
|
|
currentPitch = currentPitch + maxTurn;
|
|
} else {
|
|
currentPitch = idealPitch;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void deployable_artillery::TurnToward( float yaw, float pitch ) {
|
|
oldIdealYaw = currentYaw;
|
|
oldIdealPitch = currentPitch;
|
|
idealYaw = sys.angleNormalize180( yaw );
|
|
idealPitch = sys.angleNormalize180( pitch );
|
|
anglesLocked = false;
|
|
}
|
|
|
|
void deployable_artillery::ResetAngles() {
|
|
TurnToward( 0, 0 );
|
|
}
|
|
|
|
void deployable_artillery::vTargetSetTarget( vector targetPos, entity targetEnt ) {
|
|
float firingPitch;
|
|
float t;
|
|
vector gravity;
|
|
vector velocity;
|
|
vector temp;
|
|
float i;
|
|
|
|
if( !CalcTargetAngles( targetPos ) ) {
|
|
return;
|
|
}
|
|
|
|
gravity_x = 0;
|
|
gravity_y = 0;
|
|
gravity_z = -1066;
|
|
|
|
firingPitch = targetPitch - barrelPitch;
|
|
|
|
for ( i = 0; i < numMissiles; i++ ) {
|
|
|
|
firingVelocity = targetDiff * ( sys.cos( targetPitch ) * missileSpeed );
|
|
firingVelocity_z = sys.sin( targetPitch ) * missileSpeed;
|
|
|
|
t = GetMissileBarrelLength( i ) / missileSpeed;
|
|
|
|
gravity = gravity * t * t * 0.5f;
|
|
|
|
temp = firingVelocity * t;
|
|
|
|
firingOffset = temp + gravity;
|
|
firingVelocity = firingVelocity + ( gravity * t );
|
|
}
|
|
|
|
TurnToward( targetYaw - baseYaw, -firingPitch );
|
|
|
|
targetPlayerEnemy = owner.getEnemy();
|
|
owner.lastValidTarget = targetPos;
|
|
targetLocation = targetPos;
|
|
|
|
Base_TargetSetTarget( targetPos, targetEnt );
|
|
|
|
CreateFiringDecal();
|
|
|
|
setState( "ServerAiming" );
|
|
}
|
|
|
|
boolean deployable_artillery::vTargetGetValid( vector targetPos ) {
|
|
if ( !InRange( targetPos ) ) {
|
|
return 0;
|
|
}
|
|
|
|
return CalcTargetAngles( targetPos );
|
|
}
|
|
|
|
boolean deployable_artillery::CalcTargetAngles( vector targetPos ) {
|
|
vector barrelOrg;
|
|
vector temp;
|
|
float diffY;
|
|
float diffX;
|
|
float rootA;
|
|
float count;
|
|
float root1;
|
|
float root2;
|
|
|
|
barrelOrg = getJointPos( jointPitch );
|
|
|
|
targetDiff = targetPos - barrelOrg;
|
|
|
|
targetYaw = sys.angleNormalize180( sys.atan2( targetDiff_y, targetDiff_x ) );
|
|
|
|
temp = targetDiff;
|
|
|
|
diffY = temp_z;
|
|
temp_z = 0.f;
|
|
targetDiff = sys.vecNormalize( temp );
|
|
diffX = sys.vecLength( temp );
|
|
|
|
// FIXME: Expose default gravity
|
|
rootA = ( 1066 * diffX * diffX ) / ( 2 * missileSpeed * missileSpeed );
|
|
|
|
count = sys.solveRoots( rootA, -diffX, rootA + diffY );
|
|
if ( count == 0 ) {
|
|
return false;
|
|
}
|
|
|
|
if ( count == 1 ) {
|
|
targetPitch = sys.atan( sys.getRoot( 0 ) );
|
|
return PitchValid( targetPitch );
|
|
}
|
|
|
|
targetPitch = sys.atan( sys.getRoot( 0 ) );
|
|
if ( PitchValid( targetPitch ) ) {
|
|
return true;
|
|
}
|
|
|
|
targetPitch = sys.atan( sys.getRoot( 1 ) );
|
|
return PitchValid( targetPitch );
|
|
}
|
|
|
|
boolean deployable_artillery::PitchValid( float pitch ) {
|
|
return pitch < maxPitch && pitch > minPitch;
|
|
}
|
|
|
|
boolean deployable_artillery::InRange( vector targetPos ) {
|
|
return true;
|
|
}
|
|
|
|
boolean deployable_artillery::vTargetPlayerEligible( entity p ) {
|
|
if ( disabledState || !finishedDeploying ) {
|
|
return 0.f;
|
|
}
|
|
|
|
return 1.f;
|
|
}
|
|
|
|
target_marker deployable_artillery::vCreateTargetMarker() {
|
|
string entityDef = getKey( "def_marker" );
|
|
if ( entityDef == "" ) {
|
|
return $null;
|
|
}
|
|
|
|
generic_target_marker marker = new generic_target_marker;
|
|
marker.Init( self, entityDef, getKey( "mtr_marker_cm" ), getFloatKey( "cm_marker_sort" ) );
|
|
if ( vGetFireSupportMode() == TARGET_ROCKETS ) {
|
|
marker.SetLocalOnly( true );
|
|
}
|
|
return marker;
|
|
}
|
|
|
|
void deployable_artillery::ClearFiringDecal() {
|
|
if ( firingDecal != $null_entity ) {
|
|
delete firingDecal;
|
|
}
|
|
|
|
if ( firingMarker != $null_entity ) {
|
|
thread G_DelayRemoveEntity( firingMarker, 5.f );
|
|
firingMarker = $null_entity;
|
|
}
|
|
}
|
|
|
|
void deployable_artillery::CreateFiringDecal() {
|
|
if ( !sys.isClient() ) {
|
|
firingMarker = G_CreateFiringMarker( self, firingMarker, targetLocation );
|
|
}
|
|
|
|
if ( vGetFireSupportMode() == TARGET_ROCKETS ) {
|
|
return;
|
|
}
|
|
|
|
entity p = sys.getLocalPlayer();
|
|
if ( p == $null_entity ) {
|
|
return;
|
|
}
|
|
|
|
if ( getEntityAllegiance( p ) != TA_FRIEND ) {
|
|
return;
|
|
}
|
|
|
|
if ( firingDecal == $null_entity ) {
|
|
firingDecal = vCreateTargetMarker();
|
|
}
|
|
|
|
if ( firingDecal != $null_entity ) {
|
|
firingDecal.SetTargetPosition( targetLocation );
|
|
}
|
|
}
|
|
|
|
|
|
object deployable_rockets : deployable_artillery {
|
|
float vGetFireSupportMode();
|
|
}
|
|
|
|
float deployable_rockets::vGetFireSupportMode() {
|
|
return TARGET_ROCKETS;
|
|
}
|