1503 lines
36 KiB
Text
1503 lines
36 KiB
Text
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
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" ) );
|
||
|
}
|