etqw-sdk/base/script/maps/generic/constructible_objective.script

1503 lines
36 KiB
Plaintext

/*
===============================================================================
constructible_objective
base class for objectives that get constructed
===============================================================================
*/
object constructible_objective {
void preinit();
void destroy();
void syncFields();
boolean CheckActionCode_Base( entity p, float actionCode );
boolean vCheckActionCode( entity p, float actionCode ) {
return CheckActionCode_Base( p, actionCode );
}
void vSetOwner( entity o ) { ; }
void vConstruct( entity p );
void OnConstructionStarted() {}
void OnConstructionFinished( entity p ) {}
void OnConstructionFizzled();
void vCreateMission();
void vFreeMission();
void vCompleteMission();
float OnActivate( entity p, float distance );
float GetActivateCode( entity p, float distance );
boolean HasConstructContext( entity other );
void OnDisabledChanged();
void OnIsPrimaryObjectiveChanged();
void OnCounterChanged();
void UpdateObjectiveProgress();
void UpdateObjectiveProgress_Base();
void SetObjectiveIndicator();
void ClearObjectiveIndicator();
float CalcObjectiveProgress();
void UpdateObjectiveThread();
void SetObjectiveReminderTime( float time );
float vGetPliersProgressBarValue( float action );
float OnUpdateCrosshairInfo( entity p );
void FinishObjective_Base();
void StartObjective_Base();
void vFinishObjective() { FinishObjective_Base(); }
void vStartObjective() { StartObjective_Base(); }
void vMakePrimaryObjective( boolean value );
void KillFizzleThread();
void CreateFizzleThread( float delay );
void FizzleThread( float delay );
entity GetConstructionStage() { return $null_entity; }
void OnConstructing() { }
void ShowAndEnableClip();
void HideAndDisableClip();
boolean vIsPrimaryObjective();
boolean IsPrimaryConstruction();
string vGetObjectiveString() { return "constructObjective"; }
boolean isPrimaryObjective;
float totalCount;
float constructionCount;
float counter;
float fizzleTime;
boolean fizzleThreadActive;
float fizzleEndTime;
float constructProficiency;
boolean constructed;
entity constructor;
float lastConstructTime;
float lastWarningUpdate;
float objectiveIndex;
handle progressMessage;
boolean forceShowProgress;
float nextProgressMessageTime;
boolean disabled;
float useMeToolTip1;
float useMeToolTip2;
float nextObjectiveReminderTime;
handle objectName;
handle constructedMessage;
task missionTask;
float dmgIndex;
boolean fizzling;
}
void constructible_objective::syncFields() {
sync( "counter" );
syncBroadcast( "fizzling" );
syncBroadcast( "disabled" );
syncCallback( "counter", "OnCounterChanged" );
syncCallback( "disabled", "OnDisabledChanged" );
}
void constructible_objective::OnDisabledChanged() {
if ( disabled ) {
vFinishObjective();
} else {
vStartObjective();
}
}
void constructible_objective::OnIsPrimaryObjectiveChanged() {
ClearObjectiveIndicator();
if ( isPrimaryObjective ) {
SetObjectiveIndicator();
}
}
void constructible_objective::OnCounterChanged() {
OnConstructing();
}
void constructible_objective::SetObjectiveReminderTime( float time ) {
if ( time > nextObjectiveReminderTime ) {
nextObjectiveReminderTime = time;
}
}
void constructible_objective::UpdateObjectiveProgress() {
UpdateObjectiveProgress_Base();
}
void constructible_objective::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 constructible_objective::SetObjectiveIndicator() {
UpdateObjectiveProgress();
thread UpdateObjectiveThread();
if ( sys.doClientSideStuff() ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.active", 1.f );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage1", 0.f );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage2", 0.f );
}
}
void constructible_objective::ClearObjectiveIndicator() {
sys.killThread( "UpdateObjectiveThread_" + getName() );
if ( sys.doClientSideStuff() ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.active", 0 );
}
}
void constructible_objective::UpdateObjectiveProgress_Base() {
if ( sys.doClientSideStuff() ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage1", CalcObjectiveProgress() );
}
}
float constructible_objective::CalcObjectiveProgress() {
return counter / constructionCount;
}
void constructible_objective::FinishObjective_Base() {
if ( !sys.isClient() ) {
disabled = true;
}
HideAndDisableClip();
}
void constructible_objective::StartObjective_Base() {
if ( !sys.isClient() ) {
disabled = false;
}
ShowAndEnableClip();
}
void constructible_objective::vMakePrimaryObjective( boolean value ) {
isPrimaryObjective = value;
OnIsPrimaryObjectiveChanged();
}
void constructible_objective::preinit() {
counter = 0;
objectiveIndex = getFloatKeyWithDefault( "objective_index", -1 );
forceShowProgress = getIntKey( "force_show_progress" );
useMeToolTip1 = GetToolTip( getKey( "tt_intro_use_me_1" ) );
useMeToolTip2 = GetToolTip( getKey( "tt_intro_use_me_2" ) );
constructionCount = gameRules.GetFloatKeyWithSuffix( self, "construct_count", 100.f );
totalCount = constructionCount;
fizzleTime = getFloatKeyWithDefault( "fizzle_time", 60.f );
progressMessage = sys.localizeString( getKeyWithDefault( "progress_message", "maps/generic/obj_construct" ) );
constructProficiency = GetProficiency( getKey( "prof_construct" ) );
objectName = sys.localizeString( getKey( "object_name" ) );
string temp = getKey( "constructed_message" );
if ( temp != "" ) {
constructedMessage = sys.localizeString( temp );
} else {
constructedMessage = invalid_handle;
}
nextProgressMessageTime = 0;
dmgIndex = GetDamage( getKey( "dmg_kill" ) );
}
void constructible_objective::destroy() {
if ( isPrimaryObjective ) {
ClearObjectiveIndicator();
}
vFreeMission();
}
boolean constructible_objective::CheckActionCode_Base( entity p, float actionCode ) {
if ( objManager.gameState != GS_GAMEON ) {
return false;
}
if ( getEntityAllegiance( p ) != TA_FRIEND ) {
return false;
}
if ( actionCode == AC_CONSTRUCT ) {
return true;
}
return false;
}
void constructible_objective::vConstruct( entity p ) {
float time = sys.getTime();
entity oldConstructor = constructor;
if ( constructor == $null_entity || lastConstructTime < time - 2 ) {
constructor = p;
if ( lastConstructTime < time - 10 ) {
oldConstructor = $null_entity;
}
}
if ( p == constructor && ( forceShowProgress || objectiveIndex >= 0 ) ) {
if ( sys.getTime() > nextProgressMessageTime ) {
objManager.PushCPrintString( p.getUserName() );
objManager.CPrintEvent( progressMessage, $null );
nextProgressMessageTime = sys.getTime() + 5.f;
}
if ( constructor != oldConstructor ) {
objManager.PlaySound( getKey( "snd_constructing_strogg" ), stroggTeam );
objManager.PlaySound( getKey( "snd_constructing_gdf" ), gdfTeam );
SetObjectiveReminderTime( sys.getTime() + ( OBJECTIVEMESSAGE_WAIT_TIME * 0.5f ) );
}
}
lastConstructTime = time;
team_base team = p.getGameTeam();
if ( counter >= constructionCount ) {
counter = 0;
}
if ( counter == 0 ) {
OnConstructionStarted();
}
float count = 1;
if ( team.HasConstructionBonus( p ) ) {
count = count * 1.25f;
}
counter = counter + count;
if ( !sys.isClient() ) {
if ( constructProficiency != -1 ) {
p.giveProficiency( constructProficiency, count / totalCount, missionTask, "construction" );
}
if ( counter >= constructionCount ) {
OnConstructionFinished( p );
} else {
CreateFizzleThread( fizzleTime );
}
}
OnConstructing();
}
void constructible_objective::KillFizzleThread() {
fizzling = false;
fizzleEndTime = 0;
sys.killThread( "FizzleThread_" + getName() );
fizzleThreadActive = false;
}
void constructible_objective::CreateFizzleThread( float delay ) {
KillFizzleThread();
fizzleEndTime = sys.getTime() + delay;
if ( !fizzleThreadActive ) {
thread FizzleThread( delay );
}
}
void constructible_objective::OnConstructionFizzled() {
counter = 0;
}
void constructible_objective::FizzleThread( float delay ) {
fizzling = false;
sys.threadName( "FizzleThread_" + getName() );
fizzleThreadActive = true;
while ( sys.getTime() < fizzleEndTime ) {
sys.wait( fizzleEndTime - sys.getTime() );
}
fizzleThreadActive = false;
if ( fizzleEndTime != 0 ) {
OnConstructionFizzled();
}
}
float constructible_objective::vGetPliersProgressBarValue( float action ) {
return counter / constructionCount;
}
float constructible_objective::OnUpdateCrosshairInfo( entity p ) {
if ( !sys.doClientSideStuff() ) {
return 1.f;
}
float allegiance = getEntityAllegiance( p );
float distance = chGetDistance();
float range = InchesToMetres( distance );
chSetNumLines( 0 );
vector color = GetAllegianceColor( allegiance );
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 ) ) {
float 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 );
if ( ( range <= 25.f ) && ( range >= 5.f ) ) {
index = chAddLine();
chSetLineText( index, G_BuildRangeStr( range ) );
chSetLineColor( index, color, 1.f );
chSetLineType( index, CI_TEXT );
chSetLineSize( index, 0, 0 );
}
return 1.f;
}
float constructible_objective::OnActivate( entity p, float distance ) {
float code = GetActivateCode( p, distance );
if ( code == AK_NONE ) {
return 0.f;
}
p.vSelectActionItem( code );
return 1.f;
}
float constructible_objective::GetActivateCode( entity p, float distance ) {
if ( objManager.gameState != GS_GAMEON ) {
return AK_INWARMUP;
}
if ( p.getViewingEntity() != p ) {
return AK_NONE;
}
if ( p.getHealth() <= 0 ) {
return AK_NONE;
}
if ( distance > DISTANCE_FOR_ACTION ) {
return AK_NONE;
}
float allegiance = getEntityAllegiance( p );
if ( allegiance == TA_FRIEND ) {
return AK_CONSTRUCT;
}
return AK_NONE;
}
boolean constructible_objective::HasConstructContext( entity other ) {
float allegiance = getEntityAllegiance( other );
if ( allegiance != TA_FRIEND ) {
return false;
}
return true;
}
void constructible_objective::vCreateMission() {
vFreeMission();
missionTask = taskManager.allocEntityTask( GetPlayerTask( getKey( "task_construct" ) ), self );
}
void constructible_objective::vFreeMission() {
if ( missionTask != $null ) {
missionTask.free();
missionTask = $null;
}
}
void constructible_objective::vCompleteMission() {
if ( missionTask != $null ) {
missionTask.complete();
missionTask.free();
missionTask = $null;
}
}
void constructible_objective::ShowAndEnableClip() {
show();
if ( hasForceDisableClip() ) {
forceEnableClip();
if ( !sys.isClient() ) {
// destroy touching entities
float count = self.entitiesInBounds( getAbsMins(), getAbsMaxs(), MASK_SHOT_RENDERMODEL | MASK_SHOT_BOUNDINGBOX, 1 );
float index;
for ( index = 0; index < count; index++ ) {
entity other = self.getBoundsCacheEntity( index );
if ( other == self ) {
continue;
}
if ( other != $null_entity ) {
float entTouch = other.touches( self, true );
if ( entTouch == 0.0f && inCollection( "bounds_check" ) ) {
if ( G_ContainsBounds( getAbsMins(), getAbsMaxs(), other.getAbsMins(), other.getAbsMaxs(), 2 ) ) {
entTouch = 1;
}
}
if ( entTouch ) {
projectile_landmine mine = other;
if ( mine != $null_entity ) {
mine.vSetOwner( $null_entity );
} else {
if ( dmgIndex != -1 ) {
other.applyDamage( $null_entity, self, vec3_down, dmgIndex, 1.0f, $null_entity );
}
}
}
}
}
}
}
}
void constructible_objective::HideAndDisableClip() {
hide();
if ( !hasForceDisableClip() ) {
forceDisableClip();
if ( !sys.isClient() ) {
entity next;
entity current;
for ( current = getNextTeamEntity(); current != $null_entity; current = next ) {
next = current.getNextTeamEntity();
current.vOnBindMasterDestroyed();
}
}
}
}
boolean constructible_objective::vIsPrimaryObjective() {
if ( objectiveIndex == -1 ) {
return false;
}
if ( !isPrimaryObjective ) {
return false;
}
return true;
}
boolean constructible_objective::IsPrimaryConstruction() {
if ( objectiveIndex >= 0 ) {
return true;
}
return false;
}
/*
===============================================================================
constructible_materials
the script object attached to the construct materials
===============================================================================
*/
#define CSTATE_BLANK 0
#define CSTATE_PROGRESS 1
#define CSTATE_COMPLETE 2
object constructible_materials : constructible_objective {
void preinit();
void init();
void syncFields();
void destroy();
boolean vCheckActionCode( entity p, float actionCode );
void OnConstructionStarted();
void OnConstructionFinished( entity p );
void OnConstructionFizzled();
void UpdateObjectiveProgress();
void SetupConstruction();
void OnStateChanged();
void SetConstructionState( float newState );
void AfterConstructed();
void vSetConstructionState( float newState ) { SetConstructionState( newState ); }
void vFinishObjective();
void vStartObjective();
void OnStartNewState();
void OnFinishCurrentState( entity other );
entity GetConstructionStage();
void OnConstructing();
string vGetQuickChatString( entity p );
void vOnContextConstruct( entity p );
void vOnContextDefend( entity p );
entity vGetSpectateEntity();
boolean vIsObjectiveComplete();
float startConstructed;
float state;
float oldState;
// todo nick; make a seperate multi-staged constructible
entity firstStage;
entity secondStage;
entity intermediateStage;
entity removeEnt;
entity constructedEnt;
boolean multipleStages;
float constructDelay;
flashpoint_obj flashpoint;
boolean firstCompletedVO;
}
void constructible_materials::syncFields() {
syncBroadcast( "removeEnt" );
syncBroadcast( "firstStage" );
syncBroadcast( "secondStage" );
syncBroadcast( "intermediateStage" );
syncBroadcast( "constructedEnt" );
syncBroadcast( "state" );
syncCallback( "state", "OnStateChanged" );
}
void constructible_materials::destroy() {
if ( flashpoint != $null ) {
delete flashpoint;
}
}
void constructible_materials::vFinishObjective() {
FinishObjective_Base();
HideAndDisableClip();
}
void constructible_materials::vStartObjective() {
StartObjective_Base();
SetConstructionState( state );
}
void constructible_materials::preinit() {
setGameTeam( sys.getTeam( getKey( "team" ) ) );
multipleStages = getIntKey( "multiple_stages" );
if ( multipleStages ) {
totalCount = totalCount * 2;
}
constructDelay = 0;
state = -1;
}
void constructible_materials::SetupConstruction() {
if ( sys.isClient() ) {
OnStateChanged();
return;
}
firstStage = getEntityKey( "construction" );
if ( firstStage == $null_entity ) {
sys.error( "No construction found on " + self.getName() );
}
firstStage.setGameTeam( getGameTeam() );
firstStage.vSetOwner( self );
removeEnt = getEntityKey( "construction_remove" );
if ( removeEnt != $null_entity ) {
removeEnt.setGameTeam( getGameTeam() );
}
if( multipleStages ) {
intermediateStage = getEntityKey( "construction_intermediate" );
intermediateStage.vSetOwner( self );
secondStage = getEntityKey( "construction_second" );
if( secondStage == $null_entity ) {
sys.error( "No construction_second found on " + self.getName());
}
secondStage.vSetOwner( self );
secondStage.setGameTeam( getGameTeam() );
}
constructedEnt = getEntityKey( "constructed" );
if ( constructedEnt != $null_entity ) {
constructedEnt.setGameTeam( getGameTeam() );
constructedEnt.vSetOwner( self );
}
float newState;
startConstructed = getFloatKey( "start_constructed" );
if( !startConstructed ) {
newState = CSTATE_NONE;
} else {
if( multipleStages ) {
newState = CSTATE_FIRST_SECOND;
} else {
newState = CSTATE_FIRST;
}
}
SetConstructionState( newState );
}
void constructible_materials::init() {
SetupConstruction();
}
boolean constructible_materials::vCheckActionCode( entity p, float actionCode ) {
if ( !CheckActionCode_Base( p, actionCode ) ) {
return false;
}
if ( sys.getTime() < constructDelay ) {
return false;
}
if( multipleStages ) {
return state != CSTATE_FIRST_SECOND;
}
return state != CSTATE_FIRST;
}
void constructible_materials::OnConstructionStarted() {
OnStartNewState();
if ( !sys.isClient() ) {
objManager.setBotActionStateForEvent( ACTION_STATE_START_BUILD, self ); //mal: let the bots know someone is building the obj!
}
}
void constructible_materials::OnConstructionFinished( entity p ) { //mal: the map script will handle this particular case.
OnFinishCurrentState( p );
counter = constructionCount;
}
void constructible_materials::OnConstructionFizzled() {
float fizzleDuration = g_objectiveDecayTime.getFloatValue();
// fizzle over time
while ( counter > 0 ) {
fizzling = true;
float fizzleAmount = constructionCount * ( sys.getFrameTime() / fizzleDuration );
counter = counter - fizzleAmount;
sys.waitFrame();
}
fizzling = false;
counter = 0;
float newState;
if ( state == CSTATE_FIRST_PROGRESS ) {
newState = CSTATE_NONE;
if ( !sys.isClient() ) {
objManager.setBotActionStateForEvent( ACTION_STATE_BUILD_FIZZLED, self ); //mal: its fizzled - update the bots.
}
} else if ( state == CSTATE_FIRST_SECOND_PROGRESS ) {
newState = CSTATE_FIRST;
} else {
sys.warning( "constructible_materials::FizzleThread Invalid State" );
return;
}
// we've fallen back a stage
SetConstructionState( newState );
}
void constructible_materials::OnStartNewState() {
float newState;
if ( state == CSTATE_NONE ) {
newState = CSTATE_FIRST_PROGRESS;
} else if ( state == CSTATE_FIRST ) {
newState = CSTATE_FIRST_SECOND_PROGRESS;
} else {
sys.warning( "constructible_materials::OnStartNewState Invalid State " + state );
return;
}
SetConstructionState( newState );
}
void constructible_materials::UpdateObjectiveProgress() {
if ( sys.doClientSideStuff() ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.multiStage", multipleStages );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.decaying", fizzling );
if( state == CSTATE_FIRST_SECOND_PROGRESS ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage1", 1 );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage2", CalcObjectiveProgress() );
return;
}
if ( state == CSTATE_FIRST ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage1", 1 );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "constructObjective.stage2", 0 );
return;
}
UpdateObjectiveProgress_Base();
}
}
void constructible_materials::OnFinishCurrentState( entity other ) {
boolean finished = true;
float newState;
if ( state == CSTATE_FIRST_PROGRESS ) {
newState = CSTATE_FIRST;
if ( multipleStages ) {
finished = false;
}
} else if ( state == CSTATE_FIRST_SECOND_PROGRESS ) {
newState = CSTATE_FIRST_SECOND;
} else {
sys.warning( "constructible_materials::OnFinishCurrentState Invalid State" );
return;
}
if ( finished ) {
player p = other;
if ( p != $null_entity ) {
team_base team = p.getGameTeam();
string statName = team.getName();
if ( IsPrimaryConstruction() ) {
statName = statName + "_primary";
} else {
statName = statName + "_secondary";
}
statName = statName + "_objective_constructed";
sys.increaseStatInt( sys.allocStatInt( statName ), p.getEntityNumber(), 1 );
sys.increaseStatInt( sys.allocStatInt( "total_objectives_completed" ), p.getEntityNumber(), 1 );
}
}
SetConstructionState( newState );
constructDelay = sys.getTime() + 0.5f;
KillFizzleThread();
}
void constructible_materials::OnStateChanged() {
SetConstructionState( state );
}
void constructible_materials::SetConstructionState( float newState ) {
if ( newState == CSTATE_DESTROY ) { // special notification state that is CSTATE_NONE, to distinguish between this and a fizzle
// Gordon: doing the extra check here, because constructions may be put directly into the none state when they spawn
if ( oldState != CSTATE_NONE ) {
objManager.OnDestructionComplete( self );
}
newState = CSTATE_NONE;
}
if ( newState == CSTATE_NONE ) {
firstStage.vSetState( CSTATE_NONE );
if ( !disabled ) {
ShowAndEnableClip();
}
if ( multipleStages ) {
secondStage.vSetState( CSTATE_NONE );
if ( intermediateStage != $null_entity ) {
intermediateStage.vSetState( CSTATE_NONE );
}
}
if ( constructedEnt != $null_entity ) {
constructedEnt.vSetState( CSTATE_NONE );
}
if ( removeEnt != $null_entity ) {
removeEnt.vSetState( CSTATE_COMPLETE );
}
} else if ( newState == CSTATE_FIRST_PROGRESS ) {
firstStage.vSetState( CSTATE_PROGRESS );
if ( !disabled ) {
ShowAndEnableClip();
}
if ( multipleStages ) {
secondStage.vSetState( CSTATE_NONE );
if ( intermediateStage != $null_entity ) {
intermediateStage.vSetState( CSTATE_PROGRESS );
}
}
if ( constructedEnt != $null_entity ) {
constructedEnt.vSetState( CSTATE_NONE );
}
if ( removeEnt != $null_entity ) {
removeEnt.vSetState( CSTATE_COMPLETE );
}
} else if ( newState == CSTATE_FIRST ) {
firstStage.vSetState( CSTATE_COMPLETE );
if ( multipleStages ) {
secondStage.vSetState( CSTATE_NONE );
if ( intermediateStage != $null_entity ) {
intermediateStage.vSetState( CSTATE_COMPLETE );
}
if ( !disabled ) {
ShowAndEnableClip();
}
if ( constructedEnt != $null_entity ) {
constructedEnt.vSetState( CSTATE_NONE );
}
if ( removeEnt != $null_entity ) {
removeEnt.vSetState( CSTATE_COMPLETE );
}
if ( !firstCompletedVO ) {
objManager.PlaySound( getKey( "snd_firststage_strogg" ), stroggTeam );
objManager.PlaySound( getKey( "snd_firststage_gdf" ), gdfTeam );
firstCompletedVO = true;
}
} else {
AfterConstructed();
}
} else if( newState == CSTATE_FIRST_SECOND_PROGRESS ) {
if( !multipleStages ) {
sys.warning( "constructible_materials::SetConstructionState Not Multistage!" );
return;
}
secondStage.vSetState( CSTATE_PROGRESS );
if ( !disabled ) {
ShowAndEnableClip();
}
if ( intermediateStage != $null_entity ) {
intermediateStage.vSetState( CSTATE_COMPLETE );
}
if ( constructedEnt != $null_entity ) {
constructedEnt.vSetState( CSTATE_NONE );
}
if ( removeEnt != $null_entity ) {
removeEnt.vSetState( CSTATE_COMPLETE );
}
} else if( newState == CSTATE_FIRST_SECOND ) {
if( !multipleStages ) {
sys.warning( "constructible_materials::SetConstructionState Not Multistage!" );
return;
}
if ( intermediateStage != $null_entity ) {
intermediateStage.vSetState( CSTATE_NONE );
}
firstStage.vSetState( CSTATE_NONE );
secondStage.vSetState( CSTATE_COMPLETE );
AfterConstructed();
}
state = newState;
oldState = newState;
}
void constructible_materials::AfterConstructed() {
if ( objectiveIndex >= 0 ) {
if ( getGameTeam() == stroggTeam ) {
G_PlayObjectiveCompletedRoll( GDF );
} else if ( getGameTeam() == gdfTeam ) {
G_PlayObjectiveCompletedRoll( STROGG );
}
objManager.CompleteObjective( objectiveIndex, constructor );
} else {
if ( constructedMessage != invalid_handle ) {
objManager.PushCPrintString( constructor.getUserName() );
objManager.CPrintEvent( constructedMessage, $null );
}
}
objManager.OnConstructionComplete( self );
if ( constructedEnt != $null_entity ) {
firstStage.vSetState( CSTATE_NONE );
if ( multipleStages ) {
secondStage.vSetState( CSTATE_NONE );
}
constructedEnt.vSetState( CSTATE_COMPLETE );
}
if( removeEnt != $null_entity ) {
removeEnt.vSetState( CSTATE_NONE );
}
HideAndDisableClip();
objManager.PlaySound( getKey( "snd_finished_strogg" ), stroggTeam );
objManager.PlaySound( getKey( "snd_finished_gdf" ), gdfTeam );
}
entity constructible_materials::GetConstructionStage() {
if ( state == CSTATE_FIRST_PROGRESS ) {
if ( multipleStages ) {
return intermediateStage;
}
return firstStage;
} else if ( state == CSTATE_FIRST_SECOND_PROGRESS ) {
return secondStage;
}
return $null_entity;
}
void constructible_materials::OnConstructing() {
entity stage = GetConstructionStage();
if ( stage == $null_entity ) {
return;
}
player p = sys.getLocalPlayer();
if ( p == $null_entity ) {
return;
}
if ( sys.getTime() - lastWarningUpdate < 1.0f ) {
return;
}
lastWarningUpdate = sys.getTime();
sys.assert( stage.hasForceDisableClip() );
stage.forceEnableClip();
if ( !p.touches( stage, 0.0f ) ) {
stage.forceDisableClip();
return;
}
float contents = p.getEntityContents();
stage.forceDisableClip();
if ( contents == 0.0f ) {
return;
}
if ( !p.isToolTipPlaying() ) {
p.sendToolTip( GetToolTip( getKey( "tt_warning" ) ) );
}
}
string constructible_materials::vGetQuickChatString( entity p ) {
if ( getEntityAllegiance( p ) == TA_FRIEND ) {
return getKey( "contextmenu_quickchat_friendly" );
}
return getKey( "contextmenu_quickchat_enemy" );
}
void constructible_materials::vOnContextConstruct( 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" ) );
}
void constructible_materials::vOnContextDefend( entity p ) {
player local = sys.getLocalViewPlayer();
if ( local == $null_entity || p == $null_entity ) {
return;
}
if ( objectiveIndex == -1 ) {
return;
}
if ( flashpoint != $null ) {
delete flashpoint;
}
flashpoint = new flashpoint_obj;
flashpoint.SetOwner( self );
flashpoint.SetMaterial( getKey( "mtr_icon_flash_destroy" ) );
}
entity constructible_materials::vGetSpectateEntity() {
float time = sys.getTime();
if ( lastConstructTime >= time - 0.5f ) {
return constructor;
}
return $null_entity;
}
boolean constructible_materials::vIsObjectiveComplete() {
if ( multipleStages ) {
if ( state == CSTATE_FIRST_SECOND ) {
return true;
}
} else {
if ( state == CSTATE_FIRST ) {
return true;
}
}
return false;
}
/*
================================================
constructible_base
This entity simply gets hidden, shown
and its skin changed
================================================
*/
object constructible_base {
float state;
string constructionSkin;
float maxHealth;
float dmgIndex;
void preinit() {
state = -1;
constructionSkin = getKeyWithDefault( "skin_construct", "deployEffect" );
}
void init() {
maxHealth = getMaxHealth();
dmgIndex = GetDamage( getKey( "dmg_kill" ) );
}
void SetState_Base( float newState );
void vSetState( float newState ) {
SetState_Base( newState );
}
void OnStateChanged() {
vSetState( state );
}
string vGetQuickChatString( entity p );
}
void constructible_base::SetState_Base( float newState ) {
if ( state == newState ) {
return;
}
setHealth( maxHealth );
if ( newState == CSTATE_NONE ) {
hide();
forceDisableClip();
if ( !sys.isClient() ) {
entity next;
entity current;
for ( current = getNextTeamEntity(); current != $null_entity; current = next ) {
next = current.getNextTeamEntity();
current.vOnBindMasterDestroyed();
}
}
} else if ( newState == CSTATE_PROGRESS ) {
show();
forceDisableClip();
setSkin( constructionSkin );
} else if ( newState == CSTATE_COMPLETE ) {
show();
setSkin( "" );
if ( hasForceDisableClip() ) {
forceEnableClip();
if ( !sys.isClient() ) {
// destroy touching entities
float count = self.entitiesInBounds( getAbsMins(), getAbsMaxs(), MASK_SHOT_RENDERMODEL | MASK_SHOT_BOUNDINGBOX, 1 );
float index;
for ( index = 0; index < count; index++ ) {
entity other = self.getBoundsCacheEntity( index );
if ( other == self ) {
continue;
}
if ( other != $null_entity ) {
float entTouch = other.touches( self, true );
if ( entTouch == 0.0f && inCollection( "bounds_check" ) ) {
if ( G_ContainsBounds( getAbsMins(), getAbsMaxs(), other.getAbsMins(), other.getAbsMaxs(), 2 ) ) {
entTouch = 1;
}
}
if ( entTouch ) {
projectile_landmine mine = other;
if ( mine != $null_entity ) {
mine.vSetOwner( $null_entity );
} else {
if ( dmgIndex != -1 ) {
other.applyDamage( $null_entity, self, vec3_down, dmgIndex, 1.0f, $null_entity );
}
}
}
}
}
}
}
}
state = newState;
}
string constructible_base::vGetQuickChatString( entity p ) {
if ( getEntityAllegiance( p ) == TA_FRIEND ) {
return getKey( "contextmenu_quickchat_friendly" );
}
return getKey( "contextmenu_quickchat_enemy" );
}
/*
================================================
constructible_tower
================================================
*/
object constructible_tower : constructible_base {
void preinit();
void init();
void destroy();
void vSetState( float newState );
void OnKilled( entity inflictor, entity attacker, float damage, vector dir, float location );
float OnUpdateCrosshairInfo( entity p );
float OnActivate( entity p, float distance );
float GetActivateCode( entity p, float distance );
void UpdateItemStates();
void vSetOwner( entity o );
void vCreateMission();
void vFreeMission();
void vCompleteMission();
void vOnContextDestroy( entity p );
entity gun;
entity ladder;
handle objectName;
constructible_materials materials;
task missionTask;
float dmgIndexDestroy;
flashpoint_obj flashpoint;
}
void constructible_tower::OnKilled( entity inflictor, entity attacker, float damage, vector dir, float location ) {
if ( !sys.isClient() ) {
// destroy touching entities
float count = self.entitiesInBounds( getAbsMins(), getAbsMaxs(), MASK_SHOT_RENDERMODEL | MASK_SHOT_BOUNDINGBOX, 1 );
float entityCache = saveCachedEntities();
float index;
for ( index = 0; index < count; index++ ) {
entity other = self.getSavedCacheEntity( entityCache, index );
if ( other == self ) {
continue;
}
if ( other != $null_entity ) {
if ( dmgIndexDestroy != -1 ) {
other.applyDamage( inflictor, attacker, vec3_down, dmgIndexDestroy, 1.0f, $null_entity );
}
}
}
freeSavedCache( entityCache );
}
materials.SetConstructionState( CSTATE_DESTROY );
}
void constructible_tower::preinit() {
objectName = sys.localizeString( getKey( "object_name" ) );
}
void constructible_tower::vCreateMission() {
vFreeMission();
missionTask = taskManager.allocEntityTask( GetPlayerTask( getKey( "task_destroy" ) ), self );
}
void constructible_tower::vFreeMission() {
if ( missionTask != $null ) {
missionTask.free();
missionTask = $null;
}
}
void constructible_tower::vCompleteMission() {
if ( missionTask != $null ) {
missionTask.complete();
missionTask.free();
missionTask = $null;
}
}
void constructible_tower::init() {
gun = getEntityKey( "gun_entity" );
ladder = getEntityKey( "ladder_entity" );
dmgIndex = GetDamage( getKey( "dmg_kill" ) );
dmgIndexDestroy = GetDamage( getKey( "dmg_kill_destroy" ) );
if ( state != -1 ) {
UpdateItemStates();
}
}
void constructible_tower::destroy() {
if ( flashpoint != $null ) {
delete flashpoint;
}
}
void constructible_tower::vSetState( float newState ) {
SetState_Base( newState );
UpdateItemStates();
}
void constructible_tower::UpdateItemStates() {
if ( gun != $null_entity ) {
if ( state == CSTATE_COMPLETE ) {
gun.vSetConstructed( true );
} else {
gun.vSetConstructed( false );
}
}
if ( ladder != $null_entity ) {
if ( state == CSTATE_COMPLETE ) {
ladder.forceEnableClip();
} else {
ladder.forceDisableClip();
}
}
if ( state == CSTATE_COMPLETE ) {
setTakesDamage( true );
} else {
setTakesDamage( false );
}
}
void constructible_tower::vSetOwner( entity o ) {
materials = o;
}
float constructible_tower::OnUpdateCrosshairInfo( entity p ) {
if ( !sys.doClientSideStuff() ) {
return 1.f;
}
float allegiance = getEntityAllegiance( p );
float distance = chGetDistance();
vector color = GetAllegianceColor( allegiance );
chSetNumLines( 0 );
if ( p != $null_entity ) {
// see if theres a valid action to perform
float code = GetActivateCode( p, distance );
if ( code != AK_NONE && p.vHasActionItem( code ) ) {
float index = chAddLine();
chSetLineMaterial( index, p.vGetActionIcon( code ) );
chSetLineType( index, CI_IMAGE );
chSetLineSize( index, 64, 64 );
chSetLineColor( index, g_colorWhite, 0.9f );
}
}
index = chAddLine();
chSetLineTextIndex( index, objectName );
chSetLineColor( index, color, 1.f );
chSetLineType( index, CI_TEXT );
chSetLineSize( index, 0, 0 );
return 1.f;
}
float constructible_tower::OnActivate( entity p, float distance ) {
float code = GetActivateCode( p, distance );
if ( code == AK_NONE ) {
return 0.f;
}
p.vSelectActionItem( code );
return 1.f;
}
float constructible_tower::GetActivateCode( entity p, float distance ) {
if ( p.getViewingEntity() != p ) {
return AK_NONE;
}
if ( p.getHealth() <= 0 ) {
return AK_NONE;
}
if ( distance > DISTANCE_FOR_ACTION ) {
return AK_NONE;
}
float allegiance = getEntityAllegiance( p );
if ( allegiance == TA_ENEMY ) {
if ( p.vHasActionItem( AK_PLANT ) ) {
return AK_PLANT;
}
}
return AK_NONE;
}
void constructible_tower::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_destroy" ) );
}