etqw-sdk/base/script/vehicles/violator.script

592 lines
16 KiB
Plaintext

object vehicle_violator {
void preinit();
void init();
void destroy();
void syncFields();
void vBomberAttack( vector target, vector attackDir, float attackHeight, entity attacker );
void Update();
void CreateFiringMarker();
void ClearFiringMarker();
void BeamSounds();
void Idle();
vector startPos;
vector beamDir;
float beamStartTime;
float beamDuration;
float beamStartupDuration;
float beamCoreStartupDuration;
float beamFizzleDuration;
float beamEffectFizzleDuration;
float lastGroundEffectsTime;
float beamRotationSpeed;
entity owner;
float movementTableIndex;
boolean beamSoundsThread;
object beamStartEffect;
boolean beamStartEffectPlaying;
object beamEffect;
boolean beamEffectPlaying;
vector targetBase;
entity firingMarker;
float splashDamage;
float beamAreaLength;
// marker models
void CreateDirectionMarkers( vector startPosition, vector endPosition );
void FadeDirectionMarkers( float duration, float start, float end );
void RemoveDirectionMarkers();
void PulseDirectionMarkers( float currentTime );
void DirectionMarkerThread();
boolean directionMarkerDrawn;
boolean directionMarkerFaded;
float directionMarkerStartTime;
direction_marker directionMarker0;
direction_marker directionMarker1;
direction_marker directionMarker2;
direction_marker directionMarker3;
direction_marker directionMarker4;
direction_marker directionMarker5;
direction_marker directionMarker6;
direction_marker directionMarker7;
direction_marker directionMarker8;
direction_marker directionMarker9;
direction_marker directionMarker10;
direction_marker directionMarker11;
direction_marker directionMarker12;
direction_marker directionMarker13;
direction_marker directionMarker14;
direction_marker directionMarker15;
direction_marker directionMarker16;
direction_marker directionMarker17;
direction_marker directionMarker18;
direction_marker directionMarker19;
}
void vehicle_violator::syncFields() {
syncBroadcast( "startPos" );
syncBroadcast( "beamDir" );
syncBroadcast( "beamStartTime" );
syncBroadcast( "owner" );
}
void vehicle_violator::preinit() {
beamStartTime = -1;
lastGroundEffectsTime = -1.f;
beamStartupDuration = getFloatKey( "beam_startup_duration" );
beamCoreStartupDuration = getFloatKey( "beam_core_startup_duration" );
beamDuration = getFloatKey( "beam_duration" );
beamFizzleDuration = getFloatKey( "beam_fizzle_duration" );
beamEffectFizzleDuration = getFloatKey( "beam_effect_fizzle_duration" );
beamRotationSpeed = getFloatKey( "beam_rotation_speed" );
splashDamage = GetDamage( "damage_violator_splash" );
beamStartEffectPlaying = false;
beamEffectPlaying = false;
beamAreaLength = getFloatKey( "beam_area_length" );
movementTableIndex = GetTable( "exp_x2" );
}
void vehicle_violator::init() {
hide();
setState( "Idle" );
}
void vehicle_violator::Idle() {
while( true ) {
sys.waitFrame();
Update();
}
}
void vehicle_violator::vBomberAttack( vector target, vector attackDir, float attackHeight, entity attacker ) {
float arrivalDelay;
float arrivalDelayRandom;
vector dir;
vector endPos;
targetBase = target;
targetBase_z = attackHeight;
owner = attacker;
setGameTeam( attacker.getGameTeam() );
arrivalDelay = getFloatKey( "arrivaldelay" );
arrivalDelayRandom = getFloatKey( "arrivaldelay_random" );
if( arrivalDelayRandom < arrivalDelay ) {
arrivalDelayRandom = arrivalDelay;
}
arrivalDelay = arrivalDelay + sys.random( arrivalDelayRandom );
beamDuration = getFloatKey( "beam_duration" );
dir = sys.vecNormalize( attackDir );
startPos = target - dir * 0.5f * beamAreaLength;
sys.tracePoint( target, startPos, MASK_SOLID | MASK_OPAQUE, $null_entity );
startPos = sys.getTraceEndPos();
endPos = target + dir * beamAreaLength;
sys.tracePoint( target, endPos, MASK_SOLID | MASK_OPAQUE, $null_entity );
endPos = sys.getTraceEndPos();
// set proper flight height
endPos_z = attackHeight + 3072.f;
startPos_z = attackHeight + 3072.f;
beamDir = endPos - startPos;
beamStartTime = sys.getTime() + arrivalDelay + beamStartupDuration;
// initalise position
setOrigin( startPos );
CreateFiringMarker();
}
void vehicle_violator::Update() {
float currentTime = sys.getTime();
float frac;
vector currentPos;
vector angles;
object traceObject;
vector traceEndPos;
vector traceNormal;
entity collisionEnt;
if ( beamStartTime < 0 || currentTime < beamStartTime - beamStartupDuration ) {
return;
}
if ( currentTime < beamStartTime ) {
frac = 0.0f;
} else {
frac = ( currentTime - beamStartTime ) / beamDuration;
if ( !directionMarkerFaded ) {
if ( frac > 0.6f ) {
directionMarkerFaded = true;
FadeDirectionMarkers( 0.5f, 1.0f, 0.0f );
}
}
if ( frac >= 1.0f ) {
if ( currentTime - beamStartTime - beamDuration > 6 ) {
// give it some time for the particles to die
if ( beamStartEffect != $null_entity ) {
beamStartEffect.remove();
beamStartEffect = $null_entity;
}
if ( beamEffect != $null_entity ) {
beamEffect.remove();
beamEffect = $null_entity;
}
if ( !sys.isClient() ) {
remove();
}
return;
}
}
}
if ( frac < 1.0f ) {
CreateDirectionMarkers( startPos, startPos + beamDir );
frac = sys.getTableValueExact( movementTableIndex, frac );
}
currentPos = startPos + ( beamDir * frac );
setOrigin( currentPos );
sys.tracePoint( currentPos, currentPos + ( vec3_down * MAX_WORLD_SIZE ), MASK_SHOT_RENDERMODEL, $null_entity );
string surfaceTypeName = sys.getTraceSurfaceType();
traceEndPos = sys.getTraceEndPos();
traceNormal = sys.getTraceNormal();
collisionEnt = sys.getTraceEntity();
if( !beamSoundsThread ) {
beamSoundsThread = true;
thread BeamSounds();
}
// beam visualisation
if ( currentTime < beamStartTime ) {
// beam start effect
if ( beamStartEffect == $null_entity ) {
beamStartEffect = spawnClientEffect( "fx_beam_start" );
if ( beamStartEffect != $null_entity ) {
beamStartEffectPlaying = true;
}
}
if ( currentTime > ( beamStartTime - beamCoreStartupDuration ) ) {
if ( beamEffect == $null_entity ) {
beamEffect = spawnClientEffect( "fx_beam" );
if ( beamEffect != $null_entity ) {
beamEffectPlaying = true;
beamEffect.setEffectLooping( 1 );
}
}
}
} else {
if ( currentTime > ( beamStartTime + beamDuration - beamEffectFizzleDuration ) ) { // Xian Hack
if ( beamEffectPlaying ) {
beamEffect.endEffect( false );
beamEffectPlaying = false;
}
} else {
if ( beamStartEffectPlaying ) {
beamStartEffect.endEffect( false );
beamStartEffectPlaying = false;
}
/* if ( beamEffect == $null_entity ) {
beamEffect = spawnClientEffect( "fx_beam" );
beamEffect.setEffectLooping( 1 );
beamEffect.setAngles( sys.vecToAngles( vec3_up ) );
}*/
}
}
if ( beamStartEffect != $null_entity ) {
beamStartEffect.setOrigin( traceEndPos );
float acceleration = beamRotationSpeed / beamStartupDuration;
float time = currentTime - ( beamStartTime - beamStartupDuration );
angles_x = -90;
angles_y = 0.5 * acceleration * time * time;
angles_z = 0;
beamStartEffect.setAngles( angles );
}
if ( beamEffect != $null_entity ) {
beamEffect.setOrigin( traceEndPos );
angles_x = -90;
angles_y = beamRotationSpeed * currentTime;
angles_z = 0;
beamEffect.setAngles( angles );
if ( sys.getTime() >= ( lastGroundEffectsTime + 0.3f ) ) {
sys.tracePoint( currentPos, currentPos + ( vec3_down * MAX_WORLD_SIZE ), MASK_SHOT_RENDERMODEL|CONTENTS_WATER, $null_entity );
string fxsurfaceTypeName = sys.getTraceSurfaceType();
vector fxtraceEndPos = sys.getTraceEndPos();
vector fxtraceNormal = sys.getTraceNormal();
float beamTime = beamStartTime + ( beamDuration + 3.5 ) - beamFizzleDuration; // Xian Hack
if ( currentTime < beamTime ) {
playOriginEffect( "fx_groundeffect", fxsurfaceTypeName, fxtraceEndPos, fxtraceNormal, 0 );
lastGroundEffectsTime = sys.getTime();
}
}
}
if ( !sys.isClient() ) {
float damageScale;
float fizzleStartTime = beamStartTime + beamDuration - beamFizzleDuration;
if ( currentTime < beamStartTime ) {
damageScale = 0.0f;
} else if ( currentTime > fizzleStartTime ) {
damageScale = 1.0f - ( ( currentTime - fizzleStartTime ) / beamFizzleDuration );
} else {
damageScale = 1.0f;
}
if ( damageScale > 0.0f ) {
if ( collisionEnt != $null_entity ) {
collisionEnt.applyDamage( self, owner, vec3_down, GetDamage( "damage_violator" ), damageScale, traceObject );
}
sys.applyRadiusDamage( traceEndPos + ( vec3_up * 64.0f ), self, owner, $null_entity, self, splashDamage, damageScale, 1.f );
}
}
}
void vehicle_violator::destroy() {
ClearFiringMarker();
if ( beamStartEffect != $null_entity ) {
beamStartEffect.remove();
}
if ( beamEffect != $null_entity ) {
beamEffect.remove();
}
RemoveDirectionMarkers();
}
void vehicle_violator::BeamSounds() {
boolean playingBeamSound;
float beamTime = sys.getTime() + ( beamDuration + 3.5 ) - beamFizzleDuration; // Xian Hack
while ( sys.getTime() < beamTime ) {
sys.waitFrame();
if( !playingBeamSound ) {
playingBeamSound = true;
startSound( "snd_beam_start", SND_VEHICLE );
}
}
startSound( "snd_beam_stop", SND_VEHICLE );
}
void vehicle_violator::CreateFiringMarker() {
if ( !sys.isClient() ) {
firingMarker = G_CreateFiringMarker( self, firingMarker, targetBase );
}
}
void vehicle_violator::ClearFiringMarker() {
if ( firingMarker != $null_entity ) {
thread G_DelayRemoveEntity( firingMarker, 5.f );
firingMarker = $null_entity;
}
}
void vehicle_violator::CreateDirectionMarkers( vector startPosition, vector endPosition ) {
if ( directionMarkerDrawn ) {
return;
}
directionMarkerDrawn = true;
directionMarkerStartTime = sys.getTime();
entity p = sys.getLocalViewPlayer();
if ( p == $null_entity ) {
return;
}
if ( getEntityAllegiance( p ) != TA_FRIEND ) {
return;
}
string entityDef = getKey( "def_directionmarker" );
if ( entityDef == "" ) {
return;
}
vector targetDir = endPosition - startPosition;
vector basePosition = startPosition + 0.5f * targetDir;
targetDir = sys.vecNormalize( targetDir );
vector half;
float halfLength;
basePosition_z = startPosition_z;
// calculate marker start position
half = basePosition - startPosition;
halfLength = min( sys.vecLength( half ), 2048.0f );
vector markerStart = basePosition - halfLength * targetDir;
// calculate marker end position
half = endPosition - basePosition;
halfLength = min( sys.vecLength( half ), 2048.0f );
vector markerEnd = basePosition + halfLength * targetDir;
float markerLength = sys.vecLength( markerEnd - markerStart );
float numMarkers = rint( markerLength / 256.0f ) + 1.0f;
vector targetStep = targetDir * ( markerLength / numMarkers );
vector targetPos = markerStart;
// spawn direction markers
if ( numMarkers > 0.0f ) {
directionMarker0 = new direction_marker;
directionMarker0.Create( 0, entityDef, targetPos, targetDir );
}
#define CREATE_DIRECTION_MARKER( index ) \
if ( numMarkers > (index) ) { \
targetPos += targetStep; \
directionMarker##index = new direction_marker; \
directionMarker##index.Create( (index), entityDef, targetPos, targetDir ); \
}
CREATE_DIRECTION_MARKER( 1 )
CREATE_DIRECTION_MARKER( 2 )
CREATE_DIRECTION_MARKER( 3 )
CREATE_DIRECTION_MARKER( 4 )
CREATE_DIRECTION_MARKER( 5 )
CREATE_DIRECTION_MARKER( 6 )
CREATE_DIRECTION_MARKER( 7 )
CREATE_DIRECTION_MARKER( 8 )
CREATE_DIRECTION_MARKER( 9 )
CREATE_DIRECTION_MARKER( 10 )
CREATE_DIRECTION_MARKER( 11 )
CREATE_DIRECTION_MARKER( 12 )
CREATE_DIRECTION_MARKER( 13 )
CREATE_DIRECTION_MARKER( 14 )
CREATE_DIRECTION_MARKER( 15 )
CREATE_DIRECTION_MARKER( 16 )
CREATE_DIRECTION_MARKER( 17 )
CREATE_DIRECTION_MARKER( 18 )
CREATE_DIRECTION_MARKER( 19 )
#undef CREATE_DIRECTION_MARKER
FadeDirectionMarkers( 0.3f, 0.0f, 1.0f );
PulseDirectionMarkers( 0.0f ); // force an update
thread DirectionMarkerThread();
}
void vehicle_violator::FadeDirectionMarkers( float duration, float start, float end ) {
if ( !directionMarkerDrawn ) {
return;
}
float currentTime = sys.getTime() - directionMarkerStartTime;
#define FADE_DIRECTION_MARKER( index ) \
if ( directionMarker##index != $null ) { \
directionMarker##index.Fade( currentTime, duration, start, end ); \
}
FADE_DIRECTION_MARKER( 0 )
FADE_DIRECTION_MARKER( 1 )
FADE_DIRECTION_MARKER( 2 )
FADE_DIRECTION_MARKER( 3 )
FADE_DIRECTION_MARKER( 4 )
FADE_DIRECTION_MARKER( 5 )
FADE_DIRECTION_MARKER( 6 )
FADE_DIRECTION_MARKER( 7 )
FADE_DIRECTION_MARKER( 8 )
FADE_DIRECTION_MARKER( 9 )
FADE_DIRECTION_MARKER( 10 )
FADE_DIRECTION_MARKER( 11 )
FADE_DIRECTION_MARKER( 12 )
FADE_DIRECTION_MARKER( 13 )
FADE_DIRECTION_MARKER( 14 )
FADE_DIRECTION_MARKER( 15 )
FADE_DIRECTION_MARKER( 16 )
FADE_DIRECTION_MARKER( 17 )
FADE_DIRECTION_MARKER( 18 )
FADE_DIRECTION_MARKER( 19 )
#undef FADE_DIRECTION_MARKER
}
void vehicle_violator::RemoveDirectionMarkers() {
sys.killThread( "DirectionMarkerThread_" + getName() );
directionMarkerDrawn = false;
#define DELETE_DIRECTION_MARKER( index ) \
if ( directionMarker##index != $null ) { \
delete directionMarker##index; \
directionMarker##index = $null; \
}
DELETE_DIRECTION_MARKER( 0 )
DELETE_DIRECTION_MARKER( 1 )
DELETE_DIRECTION_MARKER( 2 )
DELETE_DIRECTION_MARKER( 3 )
DELETE_DIRECTION_MARKER( 4 )
DELETE_DIRECTION_MARKER( 5 )
DELETE_DIRECTION_MARKER( 6 )
DELETE_DIRECTION_MARKER( 7 )
DELETE_DIRECTION_MARKER( 8 )
DELETE_DIRECTION_MARKER( 9 )
DELETE_DIRECTION_MARKER( 10 )
DELETE_DIRECTION_MARKER( 11 )
DELETE_DIRECTION_MARKER( 12 )
DELETE_DIRECTION_MARKER( 13 )
DELETE_DIRECTION_MARKER( 14 )
DELETE_DIRECTION_MARKER( 15 )
DELETE_DIRECTION_MARKER( 16 )
DELETE_DIRECTION_MARKER( 17 )
DELETE_DIRECTION_MARKER( 18 )
DELETE_DIRECTION_MARKER( 19 )
#undef DELETE_DIRECTION_MARKER
}
void vehicle_violator::PulseDirectionMarkers( float currentTime ) {
if ( !directionMarkerDrawn ) {
return;
}
float pulseTime = currentTime - directionMarkerStartTime;
#define UPDATE_DIRECTION_MARKER( index ) \
if ( directionMarker##index != $null ) { \
directionMarker##index.Update( pulseTime ); \
}
UPDATE_DIRECTION_MARKER( 0 )
UPDATE_DIRECTION_MARKER( 1 )
UPDATE_DIRECTION_MARKER( 2 )
UPDATE_DIRECTION_MARKER( 3 )
UPDATE_DIRECTION_MARKER( 4 )
UPDATE_DIRECTION_MARKER( 5 )
UPDATE_DIRECTION_MARKER( 6 )
UPDATE_DIRECTION_MARKER( 7 )
UPDATE_DIRECTION_MARKER( 8 )
UPDATE_DIRECTION_MARKER( 9 )
UPDATE_DIRECTION_MARKER( 10 )
UPDATE_DIRECTION_MARKER( 11 )
UPDATE_DIRECTION_MARKER( 12 )
UPDATE_DIRECTION_MARKER( 13 )
UPDATE_DIRECTION_MARKER( 14 )
UPDATE_DIRECTION_MARKER( 15 )
UPDATE_DIRECTION_MARKER( 16 )
UPDATE_DIRECTION_MARKER( 17 )
UPDATE_DIRECTION_MARKER( 18 )
UPDATE_DIRECTION_MARKER( 19 )
#undef UPDATE_DIRECTION_MARKER
}
void vehicle_violator::DirectionMarkerThread() {
while ( true ) {
if ( directionMarkerDrawn ) {
float currentTime = sys.getTime();
PulseDirectionMarkers( currentTime );
}
sys.waitFrame();
}
}