260 lines
6.9 KiB
Text
260 lines
6.9 KiB
Text
|
|
||
|
object deployable_shield_generator : deployable_base {
|
||
|
void preinit();
|
||
|
void init();
|
||
|
void destroy();
|
||
|
|
||
|
void Idle();
|
||
|
void DestroyMissiles();
|
||
|
void DestroyTarget( entity targetEnt );
|
||
|
|
||
|
void FreeRangeIdentifier();
|
||
|
void SetupRangeIdentifier();
|
||
|
|
||
|
void vOnDeploy();
|
||
|
|
||
|
void SpawnDestroyEffect( vector position );
|
||
|
void IdleEffects();
|
||
|
|
||
|
void CreateFireStateThread();
|
||
|
void UpdateFireStateThread();
|
||
|
|
||
|
float maxRange;
|
||
|
|
||
|
float commandmapRangeHandle;
|
||
|
|
||
|
float toolTipDestroyedMissile;
|
||
|
|
||
|
boolean noStartJoint;
|
||
|
boolean disabledEffect;
|
||
|
|
||
|
float fireStateThread;
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::preinit() {
|
||
|
commandmapRangeHandle = -1;
|
||
|
|
||
|
maxRange = MetresToInches( getFloatKeyWithDefault( "range_max", 130 ) );
|
||
|
noStartJoint = getIntKey( "no_start_joint" );
|
||
|
|
||
|
toolTipDestroyedMissile = GetToolTip( getKey( "tt_destroyed_missile" ) );
|
||
|
|
||
|
fireStateThread = -1;
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::init() {
|
||
|
setState( "Idle" );
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::destroy() {
|
||
|
FreeRangeIdentifier();
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::Idle() {
|
||
|
if ( !getIntKey( "no_idle_effects" ) ) {
|
||
|
thread IdleEffects();
|
||
|
}
|
||
|
|
||
|
while ( true ) {
|
||
|
sys.waitFrame();
|
||
|
|
||
|
if ( !disabledState ) {
|
||
|
DestroyMissiles();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::vOnDeploy() {
|
||
|
SetupRangeIdentifier();
|
||
|
|
||
|
thread DoDeploy();
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::DestroyMissiles() {
|
||
|
entitiesOfCollection( "antiair" );
|
||
|
filterEntitiesByAllegiance( TA_FLAG_ENEMY, 1 ); // only damage enemies
|
||
|
filterEntitiesByRadius( getWorldOrigin(), maxRange, 1 ); // find entities within maxRange radius
|
||
|
float count = getBoundsCacheCount(); // number of remaining entities
|
||
|
|
||
|
float savedCache = saveCachedEntities();
|
||
|
|
||
|
float i;
|
||
|
for ( i = 0; i < count; i++ ) {
|
||
|
DestroyTarget( getSavedCacheEntity( savedCache, i ) );
|
||
|
}
|
||
|
|
||
|
freeSavedCache( savedCache );
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::SpawnDestroyEffect( vector position ) {
|
||
|
vector startPos;
|
||
|
if ( noStartJoint ) {
|
||
|
startPos = getWorldOrigin();
|
||
|
} else {
|
||
|
startPos = getJointPos( getJointHandle( "joint2" ) ); // start at the roof of the deployable
|
||
|
}
|
||
|
|
||
|
vector diff = startPos - position;
|
||
|
vector forward = '1 0 0';
|
||
|
vector angles;
|
||
|
object effect;
|
||
|
diff = sys.vecNormalize( diff );
|
||
|
angles = sys.vecToAngles( diff );
|
||
|
|
||
|
// Chage up and cool down effect
|
||
|
playOriginEffect( "fx_charge", "", startPos, forward, false );
|
||
|
|
||
|
// The electrial beam and shockwave
|
||
|
effect = spawnClientEffect( "fx_hit" );
|
||
|
if ( effect != $null_entity ) {
|
||
|
effect.setEffectLooping( 0 );
|
||
|
effect.setOrigin( position );
|
||
|
effect.setEffectEndOrigin( startPos );
|
||
|
effect.setAngles( angles );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::IdleEffects() {
|
||
|
float jointHandle = getJointHandle( "joint2" );
|
||
|
vector startPos;
|
||
|
vector angles0 = g_vectorZero;
|
||
|
|
||
|
vector angles1 = g_vectorZero;
|
||
|
vector angles2 = g_vectorZero;
|
||
|
|
||
|
vector pos1;
|
||
|
vector pos2;
|
||
|
float radius = 125; // Lengt of spikes from centre of symmetry of the model
|
||
|
object effect;
|
||
|
vector diff;
|
||
|
float rand;
|
||
|
|
||
|
startSound( "snd_idle", SND_DEPLOYABLE_IDLE );
|
||
|
|
||
|
while ( true ) {
|
||
|
|
||
|
if ( !disabledState ) {
|
||
|
if ( disabledEffect ) {
|
||
|
stopEffect( "fx_disabled_1" );
|
||
|
stopEffect( "fx_disabled_2" );
|
||
|
disabledEffect = false;
|
||
|
}
|
||
|
|
||
|
// Get these again as the object may have moved
|
||
|
startPos = getJointPos( jointHandle );
|
||
|
startPos_z += 12; // The joint is slightly below the spikes
|
||
|
vector angleOffset = getAngles(); // Base rotation of the spikes
|
||
|
|
||
|
float spikeIndex = int( sys.random( 4.4 ) ); //Int between [0..4] is the spike
|
||
|
|
||
|
// Start position of spark
|
||
|
angles1_y = spikeIndex * 72 + angleOffset_y; // 5 spikes == one spike every 72 degrees
|
||
|
pos1 = startPos + sys.angToForward( angles1 ) * radius;
|
||
|
|
||
|
// Select a random end position
|
||
|
rand = sys.random( 1.0 );
|
||
|
if ( rand < 0.9 ) {
|
||
|
if ( rand < 0.45 ) {
|
||
|
angles2_y = (spikeIndex+1) * 72 + angleOffset_y;
|
||
|
} else {
|
||
|
angles2_y = (spikeIndex-1) * 72 + angleOffset_y;
|
||
|
}
|
||
|
pos2 = startPos + sys.angToForward( angles2 ) * radius;
|
||
|
} else {
|
||
|
// 1 in 10 change it goes to the roof instead of another spike
|
||
|
pos2 = startPos;
|
||
|
pos2_z += 25; // Roof is even higher above the joing
|
||
|
}
|
||
|
|
||
|
// Rotate efect along the axis between the two positions
|
||
|
diff = pos2 - pos1;
|
||
|
diff = sys.vecNormalize( diff );
|
||
|
angles0 = sys.vecToAngles( diff );
|
||
|
|
||
|
// The electrial beam and shockwave
|
||
|
effect = spawnClientEffect( "fx_idle" );
|
||
|
if ( effect != $null_entity ) {
|
||
|
effect.setEffectLooping( 0 );
|
||
|
effect.setOrigin( pos1 );
|
||
|
effect.setEffectEndOrigin( pos2 );
|
||
|
effect.setAngles( angles0 );
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
if ( !disabledEffect ) {
|
||
|
playEffect( "fx_disabled_1", "fx1", true );
|
||
|
playEffect( "fx_disabled_2", "fx2", true );
|
||
|
disabledEffect = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sys.wait( 1 + sys.random( 1 ) );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::DestroyTarget( entity targetEnt ) {
|
||
|
if ( targetEnt.vGetDestroyed() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( owner != $null_entity ) {
|
||
|
float destroyProficiency = targetEnt.vGetDestroyProficiency();
|
||
|
if ( destroyProficiency != -1 ) {
|
||
|
owner.giveProficiency( destroyProficiency, 1.f, $null, "shield generator bonus" );
|
||
|
}
|
||
|
|
||
|
sys.increaseStatInt( sys.allocStatInt( "antimissile_strogg_uses" ), owner.getEntityNumber(), 1 );
|
||
|
}
|
||
|
|
||
|
SpawnDestroyEffect( targetEnt.getWorldOrigin() );
|
||
|
targetEnt.vSetDestroyed();
|
||
|
CreateFireStateThread();
|
||
|
|
||
|
player p = targetEnt.getOwner();
|
||
|
if ( p != $null_entity ) {
|
||
|
if ( p.isLocalPlayer() ) {
|
||
|
if ( !p.isToolTipPlaying() ) {
|
||
|
p.sendToolTip( toolTipDestroyedMissile );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::FreeRangeIdentifier() {
|
||
|
if ( commandmapRangeHandle != -1 ) {
|
||
|
sys.freeCMIcon( self, commandmapRangeHandle );
|
||
|
commandmapRangeHandle = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::SetupRangeIdentifier() {
|
||
|
FreeRangeIdentifier();
|
||
|
|
||
|
commandmapRangeHandle = sys.allocCMIcon( self, 100 );
|
||
|
sys.setCMIconSizeMode( commandmapRangeHandle, SM_WORLD );
|
||
|
sys.setCMIconColor( commandmapRangeHandle, g_colorRed, 0.25f );
|
||
|
sys.setCMIconSides( commandmapRangeHandle, 24 );
|
||
|
sys.setCMIconDrawMode( commandmapRangeHandle, DM_CIRCLE );
|
||
|
sys.setCMIconMaterial( commandmapRangeHandle, GetMaterial( "_white_depth" ) );
|
||
|
sys.setCMIconUnknownMaterial( commandmapRangeHandle, GetMaterial( "_white_depth" ) );
|
||
|
sys.setCMIconSize( commandmapRangeHandle, maxRange );
|
||
|
sys.setCMIconUnknownSize( commandmapRangeHandle, maxRange );
|
||
|
sys.setCMIconFlag( commandmapRangeHandle, CMF_ENEMYONLY | CMF_ONLYSHOWKNOWN );
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::CreateFireStateThread() {
|
||
|
if ( fireStateThread != -1 ) {
|
||
|
sys.terminate( fireStateThread );
|
||
|
}
|
||
|
|
||
|
fireStateThread = thread UpdateFireStateThread();
|
||
|
}
|
||
|
|
||
|
void deployable_shield_generator::UpdateFireStateThread() {
|
||
|
fireSupportState = MPS_FIRING;
|
||
|
sys.wait( 3.0f );
|
||
|
fireSupportState = MPS_READY;
|
||
|
fireStateThread = -1;
|
||
|
}
|