etqw-sdk/base/script/deployables/antipersonnel.script
2008-05-29 00:00:00 +00:00

469 lines
No EOL
11 KiB
Text

/*
===============================================================================
deployable_antipersonnel - anti-personnel turret
===============================================================================
*/
object deployable_antipersonnel : deployable_turret {
entity OnAcquireTarget();
boolean TargetIsValid( entity targetEnt );
void preinit();
void destroy();
void syncFields();
void OnPostDamage_AP( entity attacker, float oldHealth, float newHealth );
void OnPostDamage( entity attacker, float oldHealth, float newHealth ) {
OnPostDamage_AP( attacker, oldHealth, newHealth );
}
void OnSetTarget( entity oldTarget, entity newTarget );
void CheckRetribution( entity attacker );
float playerClass;
void OnFullChargeTimeChanged();
boolean ShouldSpinBarrel();
void OnBeginAttack();
void OnEndAttack();
void SpinBarrelThread();
boolean CanFire();
void Fired();
void FireMissile();
void UpdateCharge();
float fullChargeTime;
float cooldownTime;
float chargeTime;
float chargePerShot;
float overheatPenalty;
float spinBarrelJoint;
vector barrelAngles;
float tracerCounter;
float tracerInterval;
boolean barrelThreadActive;
boolean updateChargeThreadActive;
entity lockEntity;
}
void deployable_antipersonnel::preinit() {
playerClass = sys.getTypeHandle( "idPlayer" );
fullChargeTime = -1;
cooldownTime = -1;
chargeTime = getFloatKeyWithDefault( "charge_time", 10 );
chargePerShot = getFloatKeyWithDefault( "charge_per_shot", 0.7 );
overheatPenalty = getFloatKeyWithDefault( "overheat_penalty", 5 );
spinBarrelJoint = -1;
string barrelJointName = getKey( "joint_spin_barrel" );
if ( barrelJointName != "" ) {
spinBarrelJoint = getJointHandle( barrelJointName );
}
tracerCounter = 0;
tracerInterval = sys.getEntityDefIntKey( projectileIndex, "tracer_interval" );
}
void deployable_antipersonnel::destroy() {
if ( lockEntity != $null_entity ) {
lockEntity.vStopTargetLockAlarm( self );
lockEntity = $null_entity;
}
}
void deployable_antipersonnel::syncFields() {
syncBroadcast( "cooldownTime" );
sync( "fullChargeTime" );
syncCallback( "fullChargeTime", "OnFullChargeTimeChanged" );
}
void deployable_antipersonnel::OnFullChargeTimeChanged() {
if ( !updateChargeThreadActive ) {
if ( myUser == sys.getLocalPlayer() ) {
thread UpdateCharge();
}
}
}
void deployable_antipersonnel::CheckRetribution( entity attacker ) {
if ( !TargetIsValid( attacker ) ) {
return;
}
if ( !InRange( attacker.getWorldOrigin() ) ) {
return;
}
setTurretEnemy( attacker, retributionDelay );
}
void deployable_antipersonnel::OnPostDamage_AP( entity attacker, float oldHealth, float newHealth ) {
boolean oldDisabled = disabledState;
UpdateState( newHealth );
if ( !disabledState ) {
if ( getEnemy() == $null_entity && newHealth < oldHealth ) {
CheckRetribution( attacker );
}
}
UpdateDisabledStats( attacker, oldDisabled );
}
boolean deployable_antipersonnel::TargetIsValid( entity targetEnt ) {
player testPlayer = targetEnt;
if ( testPlayer == $null_entity ) {
return false;
}
if ( testPlayer.getHealth() <= 0 ) {
return false;
}
if ( testPlayer.getVehicle() != $null_entity ) {
return false;
}
if ( testPlayer.isDisguised() ) {
return false;
}
if ( getEntityAllegiance( testPlayer ) != TA_ENEMY ) {
return false;
}
if ( testPlayer.isInvulnerable() ) {
return false;
}
if ( !TraceCheck( testPlayer ) ) {
return false;
}
return true;
}
entity deployable_antipersonnel::OnAcquireTarget() {
if ( !finishedDeploying || disabledState ) {
return $null_entity;
}
float i;
float count;
entity ent;
entity targetingRangeEnt;
vector targetDir;
vector selfDir;
entitiesOfClass( playerClass, 0 );
filterEntitiesByDisguiseAllegiance( TA_FLAG_ENEMY, 1 ); // only damage enemies
filterEntitiesByRadius( getWorldOrigin(), maxRange, 1 ); // find entities within maxRange radius
selfDir = getWorldAxis( 0 );
selfDir_z = 0;
count = getBoundsCacheCount(); // number of remaining entities
for ( i = 0; i < count; i++ ) {
ent = getBoundsCacheEntity( i );
targetDir = sys.vecNormalize( ent.getWorldOrigin() - getWorldOrigin() );
targetDir_z = 0;
if ( targetDir * selfDir < angleRange ) {
continue;
}
if ( !TargetIsValid( ent ) ) {
continue;
}
if ( !InRange( ent.getWorldOrigin() ) ) {
continue;
}
if ( InFiringRange( ent.getWorldOrigin() ) ) {
return ent;
}
if ( targetingRangeEnt == $null_entity ) {
targetingRangeEnt = ent;
}
}
return targetingRangeEnt;
}
void deployable_antipersonnel::UpdateCharge() {
sys.assert( false );
updateChargeThreadActive = true;
while ( true ) {
if ( myUser != sys.getLocalPlayer() ) {
break;
}
float time = sys.getTime();
float chargeAmount = ( chargeTime - ( fullChargeTime - time ) ) / chargeTime;
if ( chargeAmount > 1 ) {
chargeAmount = 1;
}
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "weapons.energyBarCharge", chargeAmount );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "weapons.energyAvailable", time >= cooldownTime );
if ( chargeAmount == 1.f ) {
break;
}
sys.waitFrame();
}
updateChargeThreadActive = false;
}
boolean deployable_antipersonnel::CanFire() {
if ( myUser == $null_entity ) {
return true;
}
float time = sys.getTime();
float chargeAmount = ( chargeTime - ( fullChargeTime - time ) ) / chargeTime;
if ( chargeAmount >= chargePerShot && time > cooldownTime ) {
return true;
}
return false;
}
void deployable_antipersonnel::Fired() {
if ( myUser == $null_entity ) {
return;
}
if ( !sys.isClient() ) {
float timePerShot = chargeTime * chargePerShot;
if ( fullChargeTime < sys.getTime() ) {
fullChargeTime = sys.getTime();
}
fullChargeTime = fullChargeTime + timePerShot;
float time = sys.getTime();
if ( fullChargeTime >= time + chargeTime - timePerShot ) {
cooldownTime = sys.getTime() + overheatPenalty;
}
}
if ( !updateChargeThreadActive ) {
if ( myUser == sys.getLocalPlayer() ) {
thread UpdateCharge();
}
}
}
void deployable_antipersonnel::FireMissile() {
float muzzleJoint;
float forceTracer = TRACER_CHANCE;
if ( tracerInterval > 0 ) {
if ( tracerCounter % tracerInterval == 0 ) {
forceTracer = TRACER_FORCE;
}
}
entity controller = owner;
if ( controller == $null_entity ) {
controller = self;
}
launchBullet( controller, self, projectileIndex, spread, getJointPos( jointBarrel ), getJointAxis( jointBarrel, 0 ), forceTracer, false ); // hit scan
tracerCounter++;
playJointEffect( "fx_fire", jointBarrel, 0 );
if( numTracerJoints > 1 ) {
muzzleJoint = int( sys.random( numTracerJoints ) ) + 1;
} else {
muzzleJoint = numTracerJoints;
}
playEffect( "fx_muzzle", getKey( "joint_tracer" + muzzleJoint ), 0 );
Fired();
}
void deployable_antipersonnel::OnBeginAttack() {
KillAttackThread();
thread AttackThread();
if ( lockEntity != $null_entity ) {
lockEntity.vTargetLockAttack( self );
}
attacking = true;
if ( spinBarrelJoint != -1 && !barrelThreadActive ) {
thread SpinBarrelThread();
}
playCycle( ANIMCHANNEL_ALL, "fire" );
}
void deployable_antipersonnel::OnEndAttack() {
attacking = false;
playAnim( ANIMCHANNEL_ALL, "base" );
KillAttackThread();
}
boolean deployable_antipersonnel::ShouldSpinBarrel() {
return attacking && sys.getTime() > cooldownTime;
}
void deployable_antipersonnel::SpinBarrelThread() {
barrelThreadActive = true;
float speed = 0.f;
float maxSpeed = 900;
float frameTime;
while ( attacking ) {
if ( ShouldSpinBarrel() ) {
startSound( "snd_fire_start", SND_DEPLOYABLE_FIRE );
startSound( "snd_fire_far", SND_DEPLOYABLE_FIRE_FAR );
startSound( "snd_brass", SND_DEPLOYABLE_BRASS );
while ( ShouldSpinBarrel() ) {
frameTime = sys.getFrameTime();
speed = speed + ( frameTime * 600 );
if ( speed > maxSpeed ) {
speed = maxSpeed;
}
barrelAngles_y = ( barrelAngles_y + ( frameTime * speed ) ) % 360;
setJointAngle( spinBarrelJoint, JOINTMOD_LOCAL, barrelAngles );
sys.waitFrame();
}
startSound( "snd_brass_stop", SND_DEPLOYABLE_BRASS );
startSound( "snd_fire_stop", SND_DEPLOYABLE_FIRE );
startSound( "snd_fire_far_stop", SND_DEPLOYABLE_FIRE_FAR );
}
while ( !ShouldSpinBarrel() ) {
sys.waitFrame();
frameTime = sys.getFrameTime();
speed = speed - ( frameTime * 600 );
if ( speed < 0 ) {
speed = 0;
break;
}
barrelAngles_y = ( barrelAngles_y + ( frameTime * speed ) ) % 360;
setJointAngle( spinBarrelJoint, JOINTMOD_LOCAL, barrelAngles );
}
}
barrelThreadActive = false;
}
void deployable_antipersonnel::OnSetTarget( entity oldTarget, entity newTarget ) {
if ( g_aptWarning.getIntValue() == 0 ) {
return;
}
if ( lockEntity != newTarget ) {
if ( lockEntity != $null_entity ) {
lockEntity.vStopTargetLockAlarm( self );
lockEntity = $null_entity;
}
if ( newTarget != $null_entity ) {
lockEntity = newTarget;
lockEntity.vTargetLockAlarm( self );
}
}
}
/*
===============================================================================
deployable_antipersonnel_salvage - anti-personnel turret that can't be destroyed
starts with zero health though
===============================================================================
*/
object deployable_antipersonnel_salvage : deployable_antipersonnel {
void init();
void UpdateState( float health );
void CreateDestroyThread() { }
void OnPostDamage( entity attacker, float oldHealth, float newHealth );
};
void deployable_antipersonnel_salvage::init() {
setHealth( 1 );
UpdateState( 1 );
}
void deployable_antipersonnel_salvage::OnPostDamage( entity attacker, float oldHealth, float newHealth ) {
if ( newHealth <= 0 ) {
setHealth( 1 );
newHealth = 1;
}
OnPostDamage_AP( attacker, oldHealth, newHealth );
}
void deployable_antipersonnel_salvage::UpdateState( float health ) {
float frac = health / getMaxHealth();
float newState;
player p = sys.getLocalPlayer();
boolean showHealthStatus = false;
if ( p != $null_entity ) {
team_base team = p.getGameTeam();
float allegiance = getEntityAllegiance( p );
if ( allegiance == TA_FRIEND ) {
showHealthStatus = true;
}
}
float healthStatusParm = 0;
if ( frac < ( 2.f / 3.f ) ) {
newState = DS_DAMAGED;
healthStatusParm = frac * 2;
} else {
newState = DS_NORMAL;
}
if ( showHealthStatus && !disabledState ) {
sys.setCMIconShaderParm( commandMapHandle, 5, healthStatusParm );
}
SetDeployableState( newState );
}