982 lines
26 KiB
Text
982 lines
26 KiB
Text
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
|
||
|
destructible_objective.script
|
||
|
|
||
|
generic script for objectives which have to be destroyed
|
||
|
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
|
||
|
destructible_objective_base
|
||
|
|
||
|
=====================================================================
|
||
|
*/
|
||
|
|
||
|
object destructible_objective_base {
|
||
|
void preinit();
|
||
|
void init();
|
||
|
void destroy();
|
||
|
|
||
|
void OnComplete( entity inflictor, entity other );
|
||
|
|
||
|
void vCreateMission();
|
||
|
void vFreeMission();
|
||
|
void vCompleteMission();
|
||
|
|
||
|
boolean vDisablePlantCharge() { return ( objManager.gameState != GS_GAMEON ); }
|
||
|
|
||
|
void vOnContextDefend( entity p );
|
||
|
void vOnContextDestroy( entity p );
|
||
|
|
||
|
float objectiveIndex;
|
||
|
|
||
|
handle destroyMessage;
|
||
|
|
||
|
task missionTask;
|
||
|
|
||
|
float destructionProficiency;
|
||
|
|
||
|
float splashDamageIndex;
|
||
|
|
||
|
flashpoint_obj flashpoint;
|
||
|
}
|
||
|
|
||
|
|
||
|
void destructible_objective_base::preinit() {
|
||
|
destructionProficiency = GetProficiency( getKey( "prof_destroy" ) );
|
||
|
splashDamageIndex = GetDamage( getKey( "dmg_splash_damage" ) );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::init() {
|
||
|
setGameTeam( sys.getTeam( getKey( "team" ) ) );
|
||
|
|
||
|
objectiveIndex = getFloatKeyWithDefault( "objective_index", -1 );
|
||
|
|
||
|
string destroyMessageKey = getKey( "destroy_message" );
|
||
|
if ( destroyMessageKey != "" ) {
|
||
|
destroyMessage = sys.localizeString( destroyMessageKey );
|
||
|
} else {
|
||
|
destroyMessage = invalid_handle;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::destroy() {
|
||
|
vFreeMission();
|
||
|
if ( flashpoint != $null ) {
|
||
|
delete flashpoint;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::OnComplete( entity inflictor, entity other ) {
|
||
|
if ( sys.isClient() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
boolean increaseStat = true;
|
||
|
if ( inflictor != $null_entity ) {
|
||
|
if ( inflictor.vInhibitStats() ) {
|
||
|
increaseStat = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
player p = other;
|
||
|
if ( p != $null_entity && increaseStat ) {
|
||
|
if ( destructionProficiency != -1 ) {
|
||
|
p.giveProficiency( destructionProficiency, 1.f, missionTask, "destruction objective completed" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
team_base team = other.getGameTeam();
|
||
|
string statName = team.getName();
|
||
|
|
||
|
if ( objectiveIndex != -1 ) {
|
||
|
statName = statName + "_primary";
|
||
|
} else {
|
||
|
if ( destroyMessage != invalid_handle ) {
|
||
|
if ( p == $null_entity ) {
|
||
|
objManager.PushCPrintHandle( g_locStr_Someone );
|
||
|
} else {
|
||
|
objManager.PushCPrintString( other.getUserName() );
|
||
|
}
|
||
|
objManager.CPrintEvent( destroyMessage, $null );
|
||
|
}
|
||
|
|
||
|
statName = statName + "_secondary";
|
||
|
}
|
||
|
statName = statName + "_objective_destroyed";
|
||
|
|
||
|
if ( p != $null_entity && increaseStat ) {
|
||
|
sys.increaseStatInt( sys.allocStatInt( statName ), p.getEntityNumber(), 1 );
|
||
|
sys.increaseStatInt( sys.allocStatInt( "total_objectives_completed" ), p.getEntityNumber(), 1 );
|
||
|
}
|
||
|
|
||
|
if ( objectiveIndex != -1 ) {
|
||
|
objManager.CompleteObjective( objectiveIndex, other );
|
||
|
}
|
||
|
objManager.OnDestructionComplete( self );
|
||
|
|
||
|
G_PlayObjectiveCompletedRollEnt( self );
|
||
|
objManager.PlaySound( getKey( "snd_destroyed_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_destroyed_gdf" ), gdfTeam );
|
||
|
|
||
|
if ( splashDamageIndex != -1 ) {
|
||
|
sys.applyRadiusDamage( getWorldOrigin(), self, $null_entity, self, $null_entity, splashDamageIndex, 1.0f, 1.0f );
|
||
|
}
|
||
|
|
||
|
remove();
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::vCreateMission() {
|
||
|
vFreeMission();
|
||
|
missionTask = taskManager.allocEntityTask( GetPlayerTask( getKey( "task_destroy" ) ), self );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::vFreeMission() {
|
||
|
if ( missionTask != $null ) {
|
||
|
missionTask.free();
|
||
|
missionTask = $null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::vCompleteMission() {
|
||
|
if ( missionTask != $null ) {
|
||
|
missionTask.complete();
|
||
|
missionTask.free();
|
||
|
missionTask = $null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::vOnContextDefend( entity p ) {
|
||
|
player local = sys.getLocalViewPlayer();
|
||
|
if ( local == $null_entity || p == $null_entity ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( flashpoint != $null ) {
|
||
|
delete flashpoint;
|
||
|
}
|
||
|
|
||
|
flashpoint = new flashpoint_obj;
|
||
|
flashpoint.SetOwner( self );
|
||
|
flashpoint.SetMaterial( getKey( "mtr_icon_flash_defend" ) );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_base::vOnContextDestroy( entity p ) {
|
||
|
player local = sys.getLocalViewPlayer();
|
||
|
if ( local == $null_entity || p == $null_entity ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( flashpoint != $null ) {
|
||
|
delete flashpoint;
|
||
|
}
|
||
|
|
||
|
flashpoint = new flashpoint_obj;
|
||
|
flashpoint.SetOwner( self );
|
||
|
flashpoint.SetMaterial( getKey( "mtr_icon_flash" ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
|
||
|
destructible_objective_strategic
|
||
|
|
||
|
Used for Scud targets and the like
|
||
|
|
||
|
=====================================================================
|
||
|
*/
|
||
|
object destructible_objective_strategic : destructible_objective_base {
|
||
|
void preinit();
|
||
|
void syncFields();
|
||
|
|
||
|
boolean OnPreDamage( entity inflictor, entity attacker );
|
||
|
void OnKilled( entity inflictor, entity attacker, float damage, vector direction, float location );
|
||
|
|
||
|
void vSetState( float state );
|
||
|
|
||
|
void UpdateObjectiveProgress();
|
||
|
void SetObjectiveIndicator();
|
||
|
void OnIsPrimaryObjectiveChanged();
|
||
|
void vMakePrimaryObjective( boolean value );
|
||
|
void UpdateObjectiveThread();
|
||
|
void ClearObjectiveIndicator();
|
||
|
void SetObjectiveReminderTime( float time );
|
||
|
|
||
|
string vGetObjectiveString();
|
||
|
|
||
|
float nextObjectiveReminderTime;
|
||
|
float progress;
|
||
|
boolean isPrimaryObjective;
|
||
|
|
||
|
string guiStr;
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::preinit() {
|
||
|
guiStr = "destroyObjective1";
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::syncFields() {
|
||
|
syncBroadcast( "progress" );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::vSetState( float state ) {
|
||
|
progress = state;
|
||
|
}
|
||
|
|
||
|
boolean destructible_objective_strategic::OnPreDamage( entity inflictor, entity attacker ) {
|
||
|
if( getEntityAllegiance( inflictor ) == TA_FRIEND ) {
|
||
|
// e.g. stop stogg destroying the last objective and then winning the map :)
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::OnKilled( entity inflictor, entity attacker, float damage, vector direction, float location ) {
|
||
|
OnComplete( inflictor, attacker );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::UpdateObjectiveThread() {
|
||
|
waitUntil( objManager.gameState == GS_GAMEON );
|
||
|
|
||
|
objManager.PlaySound( getKey( "snd_intro_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_intro_gdf" ), gdfTeam );
|
||
|
|
||
|
SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
|
||
|
|
||
|
while ( true ) {
|
||
|
UpdateObjectiveProgress();
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
if ( sys.getTime() >= nextObjectiveReminderTime ) {
|
||
|
if ( objManager.gameState == GS_GAMEON ) {
|
||
|
objManager.PlaySound( getKey( "snd_reminder_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_reminder_gdf" ), gdfTeam );
|
||
|
}
|
||
|
|
||
|
SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::SetObjectiveIndicator() {
|
||
|
UpdateObjectiveProgress();
|
||
|
|
||
|
thread UpdateObjectiveThread();
|
||
|
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, guiStr + ".active", 1.f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::UpdateObjectiveProgress() {
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, guiStr + ".progress", progress );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, guiStr + ".disarmProgress", 0.f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::OnIsPrimaryObjectiveChanged() {
|
||
|
ClearObjectiveIndicator();
|
||
|
|
||
|
if ( isPrimaryObjective ) {
|
||
|
SetObjectiveIndicator();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::ClearObjectiveIndicator() {
|
||
|
sys.killThread( "UpdateObjectiveThread_" + getName() );
|
||
|
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, guiStr + ".active", 0.f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::vMakePrimaryObjective( boolean value ) {
|
||
|
isPrimaryObjective = value;
|
||
|
OnIsPrimaryObjectiveChanged();
|
||
|
}
|
||
|
|
||
|
void destructible_objective_strategic::SetObjectiveReminderTime( float time ) {
|
||
|
if ( time > nextObjectiveReminderTime ) {
|
||
|
nextObjectiveReminderTime = time;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string destructible_objective_strategic::vGetObjectiveString() {
|
||
|
return guiStr;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
|
||
|
destructible_flyerhive_objective_strategic
|
||
|
|
||
|
Flyerhive objective
|
||
|
|
||
|
=====================================================================
|
||
|
*/
|
||
|
object destructible_flyerhive_objective_strategic : destructible_objective_strategic {
|
||
|
void preinit();
|
||
|
}
|
||
|
|
||
|
void destructible_flyerhive_objective_strategic::preinit() {
|
||
|
guiStr = "flyerhiveObjective";
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
|
||
|
destructible_objective
|
||
|
|
||
|
Destructibles that you use an HE charge on
|
||
|
|
||
|
=====================================================================
|
||
|
*/
|
||
|
|
||
|
object destructible_objective : destructible_objective_base {
|
||
|
void preinit();
|
||
|
void destroy();
|
||
|
void syncFields();
|
||
|
|
||
|
float OnUpdateCrosshairInfo( entity p );
|
||
|
float OnActivate( entity p, float distance );
|
||
|
float GetActivateCode( entity p, float distance );
|
||
|
|
||
|
boolean vChargePlaced( entity charge, entity other );
|
||
|
void vChargeDisarmed( entity charge, entity other );
|
||
|
void vChargeExploded( entity charge, entity other );
|
||
|
|
||
|
boolean HasDestroyContext( entity other );
|
||
|
|
||
|
boolean vIsDestructibleObjective() { return true; }
|
||
|
|
||
|
void UpdateCurrentCharge( entity ignoreEnt );
|
||
|
|
||
|
void UpdateObjectiveProgress();
|
||
|
void SetObjectiveIndicator();
|
||
|
void OnIsPrimaryObjectiveChanged();
|
||
|
void vMakePrimaryObjective( boolean value );
|
||
|
void vSetObjectiveString( string message );
|
||
|
void UpdateObjectiveThread();
|
||
|
void ClearObjectiveIndicator();
|
||
|
void SetObjectiveReminderTime( float time );
|
||
|
|
||
|
float vGetDisarmProficiency();
|
||
|
|
||
|
string vGetObjectiveString();
|
||
|
|
||
|
handle objectName;
|
||
|
|
||
|
handle progressMessage;
|
||
|
handle disarmMessage;
|
||
|
|
||
|
entity currentCharge;
|
||
|
|
||
|
boolean isPrimaryObjective;
|
||
|
|
||
|
boolean vIsPrimaryObjective() { return isPrimaryObjective; }
|
||
|
entity vGetSpectateEntity() { return currentCharge; }
|
||
|
|
||
|
float disarmProficiency;
|
||
|
|
||
|
float useMeToolTip1;
|
||
|
float useMeToolTip2;
|
||
|
|
||
|
float nextObjectiveReminderTime;
|
||
|
|
||
|
string objString;
|
||
|
|
||
|
entity proxy;
|
||
|
}
|
||
|
|
||
|
void destructible_objective::preinit() {
|
||
|
useMeToolTip1 = GetToolTip( getKey( "tt_intro_use_me_1" ) );
|
||
|
useMeToolTip2 = GetToolTip( getKey( "tt_intro_use_me_2" ) );
|
||
|
|
||
|
disarmProficiency = GetProficiency( getKey( "prof_disarm" ) );
|
||
|
|
||
|
objectName = sys.localizeString( getKey( "object_name" ) );
|
||
|
progressMessage = sys.localizeString( getKeyWithDefault( "progress_message", "maps/generic/obj_planted" ) );
|
||
|
disarmMessage = sys.localizeString( getKeyWithDefault( "disarm_message", "maps/generic/obj_disarmed" ) );
|
||
|
|
||
|
objString = "destroyObjective1";
|
||
|
}
|
||
|
|
||
|
void destructible_objective::destroy() {
|
||
|
if ( isPrimaryObjective ) {
|
||
|
ClearObjectiveIndicator();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::syncFields() {
|
||
|
syncBroadcast( "currentCharge" );
|
||
|
}
|
||
|
|
||
|
float destructible_objective::vGetDisarmProficiency() {
|
||
|
return disarmProficiency;
|
||
|
}
|
||
|
|
||
|
void destructible_objective::vSetObjectiveString( string message ) {
|
||
|
objString = message;
|
||
|
}
|
||
|
|
||
|
string destructible_objective::vGetObjectiveString() {
|
||
|
return objString;
|
||
|
}
|
||
|
|
||
|
void destructible_objective::SetObjectiveReminderTime( float time ) {
|
||
|
if ( proxy != $null_entity ) {
|
||
|
proxy.vSetObjectiveReminderTime( time );
|
||
|
} else if ( time > nextObjectiveReminderTime ) {
|
||
|
nextObjectiveReminderTime = time;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
boolean destructible_objective::HasDestroyContext( entity other ) {
|
||
|
if ( !takesDamage() ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
float allegiance = getEntityAllegiance( other );
|
||
|
|
||
|
if ( allegiance == TA_ENEMY ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
float destructible_objective::GetActivateCode( entity p, float distance ) {
|
||
|
if ( objManager.gameState != GS_GAMEON ) {
|
||
|
return AK_INWARMUP;
|
||
|
}
|
||
|
|
||
|
if ( !takesDamage() ) {
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
if ( p.getHealth() <= 0 ) {
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
if ( p.getViewingEntity() != p ) {
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
float allegiance = getEntityAllegiance( p );
|
||
|
|
||
|
if ( distance < DISTANCE_FOR_ACTION ) {
|
||
|
if ( allegiance == TA_ENEMY ) {
|
||
|
if ( p.vHasActionItem( AK_PLANT ) ) {
|
||
|
return AK_PLANT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
float destructible_objective::OnActivate( entity p, float distance ) {
|
||
|
if ( p.vSelectActionItem( GetActivateCode( p, distance ) ) ) {
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
float destructible_objective::OnUpdateCrosshairInfo( entity p ) {
|
||
|
if ( !sys.doClientSideStuff() ) {
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
if ( !takesDamage() ) {
|
||
|
return 0.0f;
|
||
|
}
|
||
|
|
||
|
float allegiance = getEntityAllegiance( p );
|
||
|
vector color = GetAllegianceColor( allegiance );
|
||
|
float distance = chGetDistance();
|
||
|
|
||
|
chSetNumLines( 0 );
|
||
|
float index;
|
||
|
|
||
|
if ( p != $null_entity ) {
|
||
|
if ( p.isLocalPlayer() && objectiveIndex != -1 ) {
|
||
|
p.sendToolTip( GetToolTip( getKey( "tt_intro_info" ) ) );
|
||
|
}
|
||
|
|
||
|
// see if theres a valid action to perform
|
||
|
float code = GetActivateCode( p, distance );
|
||
|
if ( code != AK_NONE && p.vHasActionItem( code ) ) {
|
||
|
index = chAddLine();
|
||
|
chSetLineMaterial( index, p.vGetActionIcon( code ) );
|
||
|
chSetLineType( index, CI_IMAGE );
|
||
|
chSetLineSize( index, 64, 64 );
|
||
|
chSetLineColor( index, g_colorWhite, 0.9f );
|
||
|
|
||
|
if ( p.isLocalPlayer() ) {
|
||
|
if ( !p.isToolTipPlaying() ) {
|
||
|
if ( sys.getTime() - p.getCrosshairStartTime() > 1.f ) {
|
||
|
if ( p.getCurrentWeapon() != p.vGetActionItem( code ) ) {
|
||
|
p.sendToolTip( useMeToolTip1 );
|
||
|
} else {
|
||
|
p.sendToolTip( useMeToolTip2 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else if ( code == AK_INWARMUP ) {
|
||
|
if ( p.isLocalPlayer() && distance < DISTANCE_FOR_ACTION ) {
|
||
|
team_base team = p.getGameTeam();
|
||
|
if ( team != $null_entity ) {
|
||
|
p.sendToolTip( GetToolTip( getKey( "tt_noobjective" ) ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
index = chAddLine();
|
||
|
chSetLineTextIndex( index, objectName );
|
||
|
chSetLineColor( index, color, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
boolean destructible_objective::vChargePlaced( entity charge, entity other ) {
|
||
|
|
||
|
if ( !takesDamage() ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
|
||
|
|
||
|
if ( currentCharge == $null_entity ) {
|
||
|
currentCharge = charge;
|
||
|
|
||
|
// direct set so we always get a sound in 5 seconds
|
||
|
nextObjectiveReminderTime = sys.getTime() + 5.f;
|
||
|
}
|
||
|
|
||
|
if ( other != $null_entity ) { //mal: this player has an armed charge out there in the world on an obj - mark it as such so that the bots can understand!
|
||
|
objManager.setBotActionStateForEvent( ACTION_STATE_PLANTED, charge );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
objManager.PushCPrintString( other.getUserName() );
|
||
|
objManager.CPrintEvent( progressMessage, $null );
|
||
|
|
||
|
objManager.PlaySound( getKey( "snd_planted_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_planted_gdf" ), gdfTeam );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void destructible_objective::vChargeExploded( entity charge, entity other ) {
|
||
|
if ( !takesDamage() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
OnComplete( charge, other );
|
||
|
}
|
||
|
|
||
|
void destructible_objective::UpdateCurrentCharge( entity ignoreEnt ) {
|
||
|
float count = entitiesOfCollection( "charges" );
|
||
|
float i;
|
||
|
float bestTime = 99999999.f;
|
||
|
|
||
|
for ( i = 0; i < count; i++ ) {
|
||
|
entity charge = getBoundsCacheEntity( i );
|
||
|
|
||
|
if ( charge == ignoreEnt ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
entity target = charge.vGetCurrentTarget();
|
||
|
|
||
|
if ( target != self ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
float t = charge.vGetFuseRemaining();
|
||
|
if ( t > bestTime ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
bestTime = t;
|
||
|
currentCharge = charge;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::vChargeDisarmed( entity charge, entity other ) {
|
||
|
if ( !takesDamage() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
if ( currentCharge == charge ) {
|
||
|
UpdateCurrentCharge( currentCharge );
|
||
|
}
|
||
|
objManager.setBotActionStateForEvent( ACTION_STATE_DEFUSED, charge ); //mal: a charge that was planted has been defused. Let the action know.
|
||
|
}
|
||
|
|
||
|
objManager.PushCPrintString( other.getUserName() );
|
||
|
objManager.CPrintEvent( disarmMessage, $null );
|
||
|
|
||
|
objManager.PlaySound( getKey( "snd_disarmed_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_disarmed_gdf" ), gdfTeam );
|
||
|
}
|
||
|
|
||
|
void destructible_objective::UpdateObjectiveThread() {
|
||
|
waitUntil( objManager.gameState == GS_GAMEON );
|
||
|
sys.wait( 2.0f );
|
||
|
|
||
|
if ( proxy == $null_entity ) {
|
||
|
objManager.PlaySound( getKey( "snd_intro_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_intro_gdf" ), gdfTeam );
|
||
|
}
|
||
|
|
||
|
SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
|
||
|
|
||
|
while ( true ) {
|
||
|
UpdateObjectiveProgress();
|
||
|
|
||
|
if ( !sys.isClient() && proxy == $null_entity ) {
|
||
|
if ( sys.getTime() >= nextObjectiveReminderTime ) {
|
||
|
if ( objManager.gameState == GS_GAMEON ) {
|
||
|
if ( currentCharge == $null_entity ) {
|
||
|
objManager.PlaySound( getKey( "snd_reminder_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_reminder_gdf" ), gdfTeam );
|
||
|
} else {
|
||
|
objManager.PlaySound( getKey( "snd_defend_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_defend_gdf" ), gdfTeam );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::SetObjectiveIndicator() {
|
||
|
UpdateObjectiveProgress();
|
||
|
|
||
|
thread UpdateObjectiveThread();
|
||
|
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, objString + ".active", 1.f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::UpdateObjectiveProgress() {
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
if ( currentCharge == $null_entity ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, objString + ".progress", 0.f );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, objString + ".disarmProgress", 0.f );
|
||
|
} else {
|
||
|
float frac = ( currentCharge.vGetFuseRemaining() / currentCharge.vGetFuseLength() );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, objString + ".progress", 1.f - frac );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, objString + ".disarmProgress", currentCharge.vGetPliersProgressBarValue( AC_DISARM ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::OnIsPrimaryObjectiveChanged() {
|
||
|
ClearObjectiveIndicator();
|
||
|
|
||
|
if ( isPrimaryObjective ) {
|
||
|
SetObjectiveIndicator();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::ClearObjectiveIndicator() {
|
||
|
sys.killThread( "UpdateObjectiveThread_" + getName() );
|
||
|
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, objString + ".active", 0.f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective::vMakePrimaryObjective( boolean value ) {
|
||
|
isPrimaryObjective = value;
|
||
|
OnIsPrimaryObjectiveChanged();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
|
||
|
destructible_objective_trigger
|
||
|
|
||
|
Trigger zone around a destructible objective describing the area
|
||
|
that you can plant it in that will destroy the objective
|
||
|
|
||
|
=====================================================================
|
||
|
*/
|
||
|
|
||
|
object destructible_objective_trigger {
|
||
|
void OnPostMapSpawn();
|
||
|
void syncFields();
|
||
|
|
||
|
boolean vChargePlaced( entity charge, entity other );
|
||
|
entity vGetCurrentTarget();
|
||
|
|
||
|
entity theObjective;
|
||
|
}
|
||
|
|
||
|
void destructible_objective_trigger::syncFields() {
|
||
|
syncBroadcast( "theObjective" );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_trigger::OnPostMapSpawn() {
|
||
|
if ( !sys.isClient() ) {
|
||
|
theObjective = getEntityKey( "target" );
|
||
|
if ( theObjective == $null_entity ) {
|
||
|
sys.error( "destructible_objective_trigger could not find target: " + getKey( "target" ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
boolean destructible_objective_trigger::vChargePlaced( entity charge, entity other ) {
|
||
|
|
||
|
if ( theObjective.getEntityAllegiance( charge ) != TA_ENEMY ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return theObjective.vChargePlaced( charge, other );
|
||
|
}
|
||
|
|
||
|
entity destructible_objective_trigger::vGetCurrentTarget() {
|
||
|
return theObjective;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
|
||
|
destructible_objective_dual_proxy
|
||
|
|
||
|
=====================================================================
|
||
|
*/
|
||
|
|
||
|
object destructible_objective_dual_proxy {
|
||
|
void syncFields();
|
||
|
void destroy();
|
||
|
void preinit();
|
||
|
|
||
|
void OnTarget1Changed();
|
||
|
void OnTarget2Changed();
|
||
|
|
||
|
destructible_objective target1;
|
||
|
destructible_objective target2;
|
||
|
|
||
|
task defendTask;
|
||
|
|
||
|
boolean isPrimaryObjective;
|
||
|
|
||
|
float nextObjectiveReminderTime;
|
||
|
float objectiveIndex;
|
||
|
|
||
|
void UpdateObjectiveThread();
|
||
|
|
||
|
void vInitDefendMission( object missionTask );
|
||
|
void vCompleteSubMission( entity other );
|
||
|
entity vGetSpectateEntity();
|
||
|
boolean vIsObjectiveComplete();
|
||
|
|
||
|
void OnPostMapSpawn();
|
||
|
void OnIsPrimaryObjectiveChanged();
|
||
|
void vMakePrimaryObjective( boolean value );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::preinit() {
|
||
|
objectiveIndex = getFloatKeyWithDefault( "objective_index", -1 );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::syncFields() {
|
||
|
syncBroadcast( "target1" );
|
||
|
syncCallback( "target1", "OnTarget1Changed" );
|
||
|
|
||
|
syncBroadcast( "target2" );
|
||
|
syncCallback( "target2", "OnTarget2Changed" );
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::destroy() {
|
||
|
vFreeMission();
|
||
|
|
||
|
if ( isPrimaryObjective ) {
|
||
|
if ( target1 != $null_entity ) {
|
||
|
target1.vMakePrimaryObjective( false );
|
||
|
}
|
||
|
|
||
|
if ( target2 != $null_entity ) {
|
||
|
target2.vMakePrimaryObjective( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::vMakePrimaryObjective( boolean value ) {
|
||
|
if ( isPrimaryObjective == value ) {
|
||
|
return;
|
||
|
}
|
||
|
isPrimaryObjective = value;
|
||
|
OnIsPrimaryObjectiveChanged();
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::UpdateObjectiveThread() {
|
||
|
waitUntil( objManager.gameState == GS_GAMEON );
|
||
|
sys.wait( 2.0f );
|
||
|
|
||
|
objManager.PlaySound( getKey( "snd_intro_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_intro_gdf" ), gdfTeam );
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
while ( true ) {
|
||
|
if ( sys.getTime() >= nextObjectiveReminderTime ) {
|
||
|
if ( objManager.gameState == GS_GAMEON ) {
|
||
|
objManager.PlaySound( getKey( "snd_reminder_strogg" ), stroggTeam );
|
||
|
objManager.PlaySound( getKey( "snd_reminder_gdf" ), gdfTeam );
|
||
|
}
|
||
|
|
||
|
vSetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
|
||
|
}
|
||
|
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::OnIsPrimaryObjectiveChanged() {
|
||
|
if ( target1 != $null_entity ) {
|
||
|
target1.vMakePrimaryObjective( isPrimaryObjective );
|
||
|
}
|
||
|
if ( target2 != $null_entity ) {
|
||
|
target2.vMakePrimaryObjective( isPrimaryObjective );
|
||
|
}
|
||
|
|
||
|
if ( isPrimaryObjective ) {
|
||
|
thread UpdateObjectiveThread();
|
||
|
} else {
|
||
|
sys.killThread( "UpdateObjectiveThread_" + getName() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::OnTarget1Changed() {
|
||
|
if ( target1 != $null_entity ) {
|
||
|
target1.vSetObjectiveString( "destroyObjective1" );
|
||
|
target1.proxy = self;
|
||
|
if ( isPrimaryObjective ) {
|
||
|
target1.vMakePrimaryObjective( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::OnTarget2Changed() {
|
||
|
if ( target2 != $null_entity ) {
|
||
|
target2.vSetObjectiveString( "destroyObjective2" );
|
||
|
target2.proxy = self;
|
||
|
if ( isPrimaryObjective ) {
|
||
|
target2.vMakePrimaryObjective( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::OnPostMapSpawn() {
|
||
|
if ( !sys.isClient() ) {
|
||
|
target1 = getEntityKey( "target1" );
|
||
|
if ( target1 == $null_entity ) {
|
||
|
sys.error( "destructible_objective_dual_proxy::OnPostMapSpawn target1 not found or is not a destructible objective" );
|
||
|
} else {
|
||
|
OnTarget1Changed();
|
||
|
}
|
||
|
|
||
|
target2 = getEntityKey( "target2" );
|
||
|
if ( target2 == $null_entity ) {
|
||
|
sys.error( "destructible_objective_dual_proxy::OnPostMapSpawn target2 not found or is not a destructible objective" );
|
||
|
} else {
|
||
|
OnTarget2Changed();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::vSetObjectiveReminderTime( float time ) {
|
||
|
if ( time > nextObjectiveReminderTime ) {
|
||
|
nextObjectiveReminderTime = time;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::vInitDefendMission( object missionTask ) {
|
||
|
defendTask = missionTask;
|
||
|
|
||
|
if ( target1 == $null_entity ) {
|
||
|
defendTask.setWayPointState( 0, false );
|
||
|
} else {
|
||
|
defendTask.setLocation( 0, target1.getWorldOrigin() );
|
||
|
}
|
||
|
|
||
|
if ( target2 == $null_entity ) {
|
||
|
defendTask.setWayPointState( 1, false );
|
||
|
} else {
|
||
|
defendTask.setLocation( 1, target2.getWorldOrigin() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void destructible_objective_dual_proxy::vCompleteSubMission( entity other ) {
|
||
|
if ( other == target1 ) {
|
||
|
defendTask.setWayPointState( 0, false );
|
||
|
} else if ( other == target2 ) {
|
||
|
defendTask.setWayPointState( 1, false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
entity destructible_objective_dual_proxy::vGetSpectateEntity() {
|
||
|
if ( target1 == $null_entity ) {
|
||
|
return target2.vGetSpectateEntity();
|
||
|
}
|
||
|
if ( target2 == $null_entity ) {
|
||
|
return target1.vGetSpectateEntity();
|
||
|
}
|
||
|
|
||
|
entity charge1 = target1.vGetSpectateEntity();
|
||
|
entity charge2 = target2.vGetSpectateEntity();
|
||
|
|
||
|
if ( charge1 == $null_entity ) {
|
||
|
return charge2;
|
||
|
}
|
||
|
if ( charge2 == $null_entity ) {
|
||
|
return charge1;
|
||
|
}
|
||
|
|
||
|
if ( charge1.vGetFuseRemaining() <= charge2.vGetFuseRemaining() ) {
|
||
|
return charge1;
|
||
|
}
|
||
|
|
||
|
return charge2;
|
||
|
}
|
||
|
|
||
|
boolean destructible_objective_dual_proxy::vIsObjectiveComplete() {
|
||
|
if ( target1 == $null_entity && target2 == $null_entity ) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|