1765 lines
43 KiB
Text
1765 lines
43 KiB
Text
|
|
||
|
#include <script/deployables/base_defines.include>
|
||
|
|
||
|
object deployable_base {
|
||
|
void syncFields();
|
||
|
void init();
|
||
|
void preinit();
|
||
|
void destroy();
|
||
|
|
||
|
void DoDeploy();
|
||
|
void vOnDeploy();
|
||
|
void vDoneDeploy();
|
||
|
|
||
|
void OnDeployedChanged();
|
||
|
void OnOwnerChanged();
|
||
|
void OnDisableEndTimeChanged();
|
||
|
|
||
|
void IncreaseUseCount();
|
||
|
|
||
|
void SetupStats();
|
||
|
|
||
|
void SetDisableEndTime( float t );
|
||
|
|
||
|
void Base_TargetSetTarget( vector targetPos, entity targetEnt );
|
||
|
|
||
|
void OnPostDamage( entity attacker, float oldHealth, float newHealth );
|
||
|
void UpdateDisabledStats( entity attacker, boolean oldDisabled );
|
||
|
void UpdateState( float health );
|
||
|
void UpdateGui();
|
||
|
void SetDeployableState( float newState );
|
||
|
|
||
|
void SetupRequestIcon( string key, string requirement );
|
||
|
void FreeRequestIcon();
|
||
|
void RequestIconThread( float timeout );
|
||
|
|
||
|
float OnActivate( entity p, float distance );
|
||
|
float GetActivateCode( entity p, float distance );
|
||
|
|
||
|
void OnStateDisabled();
|
||
|
void OnStateDamaged();
|
||
|
void OnStateNormal();
|
||
|
|
||
|
void DeployableBase_OnStateNormal();
|
||
|
void DeployableBase_OnStateDamaged();
|
||
|
void DeployableBase_OnStateDisabled();
|
||
|
|
||
|
void DeployableBase_OnKilled( entity attacker, entity inflictor );
|
||
|
void DeployableBase_Deploy();
|
||
|
|
||
|
void DoHack( entity hacker, float time );
|
||
|
|
||
|
float GetChargePerUse();
|
||
|
|
||
|
float OnUpdateCrosshairInfo( entity p );
|
||
|
|
||
|
float vGetPliersProgressBarValue( float action );
|
||
|
|
||
|
boolean vCheckActionCode( entity p, float actionCode );
|
||
|
void vRepair( float count, entity p );
|
||
|
vector vGetLastRepairOrigin();
|
||
|
|
||
|
void SelfDestruct();
|
||
|
|
||
|
boolean IsDeployed();
|
||
|
boolean IsDisabled();
|
||
|
|
||
|
float vGetFiringStatus( object traceObject );
|
||
|
void vUpdateFiringStatusObject( entity localPlayer );
|
||
|
float GetCoolDownFraction();
|
||
|
float vGetTimerState();
|
||
|
float vGetChargeTime();
|
||
|
float GetLockTime();
|
||
|
float GetLockGraceTime();
|
||
|
|
||
|
void SetupCommandMap();
|
||
|
void FreeCommandMap();
|
||
|
|
||
|
void vDismantle( entity p );
|
||
|
|
||
|
void vHack( entity p );
|
||
|
|
||
|
boolean vIsDeployed();
|
||
|
|
||
|
void SetDeployingFinished();
|
||
|
|
||
|
void vCheckProficiency();
|
||
|
|
||
|
void vApplyEmpDamage( entity attacker, float time, float weaponTime );
|
||
|
|
||
|
entity vGetDeployableOwner();
|
||
|
|
||
|
entity GetOwner();
|
||
|
void vSetDeployableOwner( entity other );
|
||
|
|
||
|
void DeployableBase_CheckProficiency();
|
||
|
|
||
|
void OnSpotted( entity spotter );
|
||
|
|
||
|
void OnSetTeam( object oldTeam, object newTeam );
|
||
|
void OnKilled( entity inflictor, entity attacker, float damage, vector direction, float location );
|
||
|
|
||
|
void InitDestroyTask( boolean highCommand );
|
||
|
void FreeDestroyTask();
|
||
|
void CompleteDestroyTask();
|
||
|
|
||
|
void InitDisableTask( boolean highCommand );
|
||
|
void FreeDisableTask();
|
||
|
void CompleteDisableTask();
|
||
|
|
||
|
void InitRepairTask( boolean highCommand );
|
||
|
void FreeRepairTask();
|
||
|
void CompleteRepairTask();
|
||
|
|
||
|
boolean NeedsRepair();
|
||
|
|
||
|
void vOnContextKill( entity p );
|
||
|
void vOnContextRepair( entity p );
|
||
|
|
||
|
void vOnRemovePlayersKillTask( player p );
|
||
|
|
||
|
void UpdateDisabled();
|
||
|
void CreateDisableThread();
|
||
|
void KillDisableThread();
|
||
|
void DisableThread();
|
||
|
boolean DeployableBase_CalculateDisabledState();
|
||
|
boolean CalculateDisabledState();
|
||
|
void SetDisabled( boolean newDisabledState );
|
||
|
|
||
|
void OnDisabled();
|
||
|
void OnReEnabled();
|
||
|
|
||
|
string vGetQuickChatString( entity p );
|
||
|
|
||
|
void FlashCMIcon( entity p, float requiredTeam, float flashTime );
|
||
|
|
||
|
void UpdateAnimThread();
|
||
|
|
||
|
float currentState;
|
||
|
|
||
|
boolean isDeploying;
|
||
|
handle objectTitle;
|
||
|
|
||
|
float hackCount;
|
||
|
float maxHackCount;
|
||
|
float damageHackCount;
|
||
|
float maxDamageHackCount;
|
||
|
float hackDisableTime;
|
||
|
|
||
|
task disableTask;
|
||
|
task destroyTask;
|
||
|
task repairTask;
|
||
|
|
||
|
player killTaskRequestee;
|
||
|
|
||
|
boolean manualDeploy;
|
||
|
|
||
|
float commandMapHandle;
|
||
|
|
||
|
float fireSupportState;
|
||
|
|
||
|
boolean finishedDeploying;
|
||
|
|
||
|
boolean playTracerFX;
|
||
|
|
||
|
string localFireSound;
|
||
|
|
||
|
float disableEndTime;
|
||
|
float repairMultiplier;
|
||
|
|
||
|
float disableProficiency;
|
||
|
float hackProficiency;
|
||
|
|
||
|
// variables for the repair drone
|
||
|
float orbitUnderneath;
|
||
|
float orbitRadius;
|
||
|
|
||
|
boolean vCustomOrbitRadius();
|
||
|
float vGetOrbitRadius();
|
||
|
boolean vOrbitUnderneath();
|
||
|
|
||
|
player owner;
|
||
|
|
||
|
boolean OverridePreventDeployment( entity p ) { return p == owner; }
|
||
|
|
||
|
float timerHandle; // Gordon: FIXME: These should not be a part of the base
|
||
|
float timerStartHandle;
|
||
|
float timerLength;
|
||
|
float gracePeriod;
|
||
|
|
||
|
float commandMapRequest;
|
||
|
|
||
|
void DestroyThread();
|
||
|
void CreateDestroyThread();
|
||
|
void DoBoundsDamageThread();
|
||
|
void KillBoundsDamageThread();
|
||
|
|
||
|
float useMeToolTip1_Hack;
|
||
|
float useMeToolTip2_Hack;
|
||
|
|
||
|
// Gordon: why on earth is this here?
|
||
|
string colorMaterial;
|
||
|
string desatMaterial;
|
||
|
|
||
|
boolean disabledState;
|
||
|
|
||
|
handle statTimeUsed;
|
||
|
handle statUseCount;
|
||
|
handle statNumDestroyed;
|
||
|
handle statNumDisabled;
|
||
|
float deployFinishedTime;
|
||
|
|
||
|
fireSupportStatus fsStatus;
|
||
|
|
||
|
float empJointHandle;
|
||
|
|
||
|
boolean IsDamageHackTime();
|
||
|
float GetCurrentMaxHackCount();
|
||
|
float GetCurrentHackCount();
|
||
|
void SetCurrentHackCount( float hack );
|
||
|
float disableHackHealth;
|
||
|
|
||
|
float disableHackedTime;
|
||
|
void OnDisableHackedTimeChanged();
|
||
|
}
|
||
|
|
||
|
void deployable_base::syncFields() {
|
||
|
syncBroadcast( "isDeploying" );
|
||
|
syncBroadcast( "finishedDeploying" );
|
||
|
syncBroadcast( "owner" );
|
||
|
syncBroadcast( "disableEndTime" );
|
||
|
syncCallback( "disableEndTime", "OnDisableEndTimeChanged" );
|
||
|
syncCallback( "isDeploying", "OnDeployedChanged" );
|
||
|
syncCallback( "owner", "OnOwnerChanged" );
|
||
|
|
||
|
sync( "hackCount" );
|
||
|
sync( "damageHackCount" );
|
||
|
sync( "disableHackedTime" );
|
||
|
syncCallback( "disableHackedTime", "OnDisableHackedTimeChanged" );
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnOwnerChanged() {
|
||
|
if ( owner != $null_entity ) {
|
||
|
owner.SetTargetingItem( self );
|
||
|
}
|
||
|
|
||
|
setXPShareInfo( owner, 0.5f );
|
||
|
|
||
|
vCheckProficiency();
|
||
|
|
||
|
if ( owner == sys.getLocalPlayer() ) {
|
||
|
sys.killThread( "UpdateGui_" + getName() );
|
||
|
thread UpdateGui();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::destroy() {
|
||
|
if ( owner != $null_entity ) {
|
||
|
if ( owner == sys.getLocalPlayer() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.state", DS_REMOVED );
|
||
|
}
|
||
|
|
||
|
owner.binRemove( self );
|
||
|
}
|
||
|
|
||
|
KillBoundsDamageThread();
|
||
|
|
||
|
FreeCommandMap();
|
||
|
FreeDestroyTask();
|
||
|
FreeDisableTask();
|
||
|
FreeRequestIcon();
|
||
|
FreeRepairTask();
|
||
|
|
||
|
if ( deployFinishedTime != -1 && owner != $null_entity ) {
|
||
|
sys.increaseStatInt( statTimeUsed, owner.getEntityNumber(), sys.getTime() - deployFinishedTime );
|
||
|
}
|
||
|
|
||
|
object team = getGameTeam();
|
||
|
if ( team != $null ) {
|
||
|
team.unRegisterDeployable( self );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::vSetDeployableOwner( entity other ) {
|
||
|
owner = other;
|
||
|
OnOwnerChanged();
|
||
|
}
|
||
|
|
||
|
entity deployable_base::vGetDeployableOwner() {
|
||
|
return owner;
|
||
|
}
|
||
|
|
||
|
entity deployable_base::GetOwner() {
|
||
|
return owner;
|
||
|
}
|
||
|
|
||
|
void deployable_base::vSetManualDeploy() {
|
||
|
manualDeploy = true;
|
||
|
}
|
||
|
|
||
|
void deployable_base::SetupCommandMap() {
|
||
|
commandMapHandle = sys.allocCMIcon( self, 10 );
|
||
|
|
||
|
sys.setCMIconShaderParm( commandMapHandle, 5, 1 );
|
||
|
|
||
|
float commandMapSize = getFloatKey( "icon_size_cm" );
|
||
|
|
||
|
sys.setCMIconSize( commandMapHandle, commandMapSize );
|
||
|
sys.setCMIconColorMode( commandMapHandle, CM_ALLEGIANCE );
|
||
|
|
||
|
sys.setCMIconMaterial( commandMapHandle, GetMaterial( getKey( "mtr_commandmap" ) ) );
|
||
|
sys.setCMIconUnknownMaterial( commandMapHandle, GetMaterial( getKey( "mtr_commandmap_unknown" ) ) );
|
||
|
sys.setCMIconUnknownSize( commandMapHandle, getFloatKeyWithDefault( "icon_unknown_size_cm", commandMapSize ) );
|
||
|
sys.setCMIconFlag( commandMapHandle, CMF_FOLLOWROTATION );
|
||
|
sys.setCMIconDrawMode( commandMapHandle, DM_ROTATED_MATERIAL );
|
||
|
}
|
||
|
|
||
|
void deployable_base::FreeCommandMap() {
|
||
|
if( commandMapHandle != -1 ) {
|
||
|
sys.freeCMIcon( self, commandMapHandle );
|
||
|
commandMapHandle = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnDeployedChanged() {
|
||
|
vOnDeploy();
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnDisableEndTimeChanged() {
|
||
|
SetDisableEndTime( disableEndTime );
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnSpotted( entity spotter ) {
|
||
|
if ( IsDeployed() ) {
|
||
|
killTaskRequestee = $null_entity;
|
||
|
InitDestroyTask( true );
|
||
|
InitDisableTask( true );
|
||
|
G_GiveSpottingProficiency( spotter );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::preinit() {
|
||
|
objectTitle = sys.localizeString( getKeyWithDefault( "ch_name", getKey( "task_name" ) ) );
|
||
|
playTracerFX = getFloatKey( "use_tracers" ) != 0;
|
||
|
repairMultiplier = getFloatKeyWithDefault( "repair_multiplier", 1.f );
|
||
|
|
||
|
maxHackCount = getFloatKeyWithDefault( "max_hack_count", 16 );
|
||
|
maxDamageHackCount = getFloatKeyWithDefault( "max_hack_count", 24 );
|
||
|
hackDisableTime = getFloatKeyWithDefault( "hack_disable_time", 60 );
|
||
|
|
||
|
localFireSound = getKey( "snd_fire_local" );
|
||
|
|
||
|
fireSupportState = MPS_NONE_ACTIVE;
|
||
|
|
||
|
orbitUnderneath = getFloatKey( "drone_orbit_underneath" );
|
||
|
orbitRadius = getFloatKey( "drone_orbit_radius" );
|
||
|
|
||
|
currentState = DS_NORMAL;
|
||
|
|
||
|
colorMaterial = getKey( "mtr_color" );
|
||
|
desatMaterial = getKey( "mtr_desat" );
|
||
|
|
||
|
timerHandle = sys.allocTargetTimer( FIRESUPPORT_TIMER_NAME );
|
||
|
timerStartHandle = sys.allocTargetTimer( FIRESUPPORT_TIMER_START_NAME );
|
||
|
timerLength = getFloatKey( "target_length" );
|
||
|
gracePeriod = getFloatKey( "target_lostgraceperiod" );
|
||
|
|
||
|
useMeToolTip1_Hack = GetToolTip( getKey( "tt_intro_use_me_1_hack" ) );
|
||
|
useMeToolTip2_Hack = GetToolTip( getKey( "tt_intro_use_me_2_hack" ) );
|
||
|
|
||
|
disableProficiency = GetProficiency( getKey( "prof_disable" ) );
|
||
|
hackProficiency = GetProficiency( getKey( "prof_hack" ) );
|
||
|
|
||
|
commandMapRequest = -1;
|
||
|
|
||
|
empJointHandle = getJointHandle( getKey( "emp_effect_joint" ) );
|
||
|
|
||
|
disableHackHealth = getMaxHealth() * 0.5f;
|
||
|
|
||
|
SetupStats();
|
||
|
|
||
|
SetupCommandMap();
|
||
|
|
||
|
if ( getFloatKey( "freeze_on_spawn" ) != 0.0f ) {
|
||
|
setComeToRest( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::IncreaseUseCount() {
|
||
|
if ( owner == $null_entity ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
sys.increaseStatInt( statUseCount, owner.getEntityNumber(), 1 );
|
||
|
}
|
||
|
|
||
|
void deployable_base::SetupStats() {
|
||
|
statTimeUsed = -1;
|
||
|
statNumDestroyed = -1;
|
||
|
statNumDisabled = -1;
|
||
|
statUseCount = -1;
|
||
|
deployFinishedTime = -1;
|
||
|
|
||
|
string statName = getKey( "stat_name" );
|
||
|
if ( statName == "" ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
statTimeUsed = sys.allocStatInt( statName + "_time_used" );
|
||
|
statNumDestroyed = sys.allocStatInt( statName + "_killed" );
|
||
|
statNumDisabled = sys.allocStatInt( statName + "_disabled" );
|
||
|
statUseCount = sys.allocStatInt( statName + "_uses" );
|
||
|
}
|
||
|
|
||
|
float deployable_base::OnActivate( entity p, float distance ) {
|
||
|
if ( distance > 128.f ) {
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
float code = GetActivateCode( p, distance );
|
||
|
if ( code == AK_HACK ) {
|
||
|
if ( p.isDisguised() ) {
|
||
|
p.disguise( $null_entity );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( p.vSelectActionItem( code ) ) {
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
void deployable_base::vOnContextRepair( entity p ) {
|
||
|
if ( currentState == DS_NORMAL ) {
|
||
|
SetupRequestIcon( "mtr_cm_icon_need_repair", "require_view_repair" );
|
||
|
thread RequestIconThread( 5.f );
|
||
|
}
|
||
|
InitRepairTask( false );
|
||
|
}
|
||
|
|
||
|
void deployable_base::vOnContextKill( entity p ) {
|
||
|
if ( IsDeployed() ) {
|
||
|
if ( destroyTask == $null && disableTask == $null ) {
|
||
|
killTaskRequestee = $null_entity;
|
||
|
InitDestroyTask( true );
|
||
|
InitDisableTask( true );
|
||
|
}
|
||
|
|
||
|
FlashCMIcon( p, TA_ENEMY, -1 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::vOnRemovePlayersKillTask( player p ) {
|
||
|
if ( p == killTaskRequestee ) {
|
||
|
FreeDestroyTask();
|
||
|
FreeDisableTask();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float deployable_base::GetActivateCode( entity p, float distance ) {
|
||
|
if ( p.getViewingEntity() != p ) {
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
if ( p.getHealth() <= 0 ) {
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
if ( p.getVehicle() != $null_entity ) {
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
float allegiance = getEntityAllegiance( p );
|
||
|
|
||
|
if ( distance < DISTANCE_FOR_ACTION ) {
|
||
|
if ( allegiance == TA_ENEMY ) {
|
||
|
if ( !disabledState || getHealth() > disableHackHealth ) {
|
||
|
if ( p.hasAbility( "hack" ) ) {
|
||
|
return AK_HACK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( p.vHasActionItem( AK_PLANT ) ) {
|
||
|
return AK_PLANT;
|
||
|
}
|
||
|
} else {
|
||
|
if ( p.vHasActionItem( AK_REPAIR ) ) {
|
||
|
float health = getHealth();
|
||
|
if ( ( health > 0 ) && ( health < getMaxHealth() ) ) {
|
||
|
return AK_REPAIR;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return AK_NONE;
|
||
|
}
|
||
|
|
||
|
void deployable_base::InitDestroyTask( boolean highCommand ) {
|
||
|
if ( sys.isClient() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( destroyTask != $null_entity ) {
|
||
|
if ( !highCommand ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( !destroyTask.isUserCreated() ) {
|
||
|
return;
|
||
|
}
|
||
|
destroyTask.free();
|
||
|
}
|
||
|
|
||
|
float taskHandle = GetPlayerTask( getKey( "task_destroy" ) );
|
||
|
if ( taskHandle != -1 ) {
|
||
|
|
||
|
destroyTask = taskManager.allocEntityTask( taskHandle, self );
|
||
|
if ( !highCommand ) {
|
||
|
destroyTask.setUserCreated();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::FreeDestroyTask() {
|
||
|
killTaskRequestee = $null_entity;
|
||
|
if ( destroyTask != $null_entity ) {
|
||
|
destroyTask.free();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::CompleteDestroyTask() {
|
||
|
if ( destroyTask != $null_entity ) {
|
||
|
destroyTask.complete();
|
||
|
destroyTask.setTimeout( 1.f );
|
||
|
destroyTask = $null_entity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::InitRepairTask( boolean highCommand ) {
|
||
|
if ( sys.isClient() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( getHealth() <= 0 ) {
|
||
|
FreeRepairTask();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( repairTask != $null_entity ) {
|
||
|
if ( !highCommand ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( !repairTask.isUserCreated() ) {
|
||
|
return;
|
||
|
}
|
||
|
repairTask.free();
|
||
|
}
|
||
|
|
||
|
float taskHandle = GetPlayerTask( getKey( "task_repair" ) );
|
||
|
if ( taskHandle != -1 ) {
|
||
|
repairTask = taskManager.allocEntityTask( taskHandle, self );
|
||
|
if ( !highCommand ) {
|
||
|
repairTask.setUserCreated();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::FreeRepairTask() {
|
||
|
if ( repairTask != $null ) {
|
||
|
repairTask.free();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::CompleteRepairTask() {
|
||
|
if ( repairTask != $null_entity ) {
|
||
|
repairTask.complete();
|
||
|
repairTask.setTimeout( 1.f );
|
||
|
repairTask = $null_entity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::InitDisableTask( boolean highCommand ) {
|
||
|
if ( sys.isClient() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( disableEndTime > sys.getTime() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( disableTask != $null_entity ) {
|
||
|
if ( !highCommand ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( !disableTask.isUserCreated() ) {
|
||
|
return;
|
||
|
}
|
||
|
disableTask.free();
|
||
|
}
|
||
|
|
||
|
float taskHandle = GetPlayerTask( getKey( "task_hack" ) );
|
||
|
if ( taskHandle != -1 ) {
|
||
|
disableTask = taskManager.allocEntityTask( taskHandle, self );
|
||
|
if ( !highCommand ) {
|
||
|
disableTask.setUserCreated();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::FreeDisableTask() {
|
||
|
killTaskRequestee = $null_entity;
|
||
|
if ( disableTask != $null_entity ) {
|
||
|
disableTask.free();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::CompleteDisableTask() {
|
||
|
if ( disableTask != $null_entity ) {
|
||
|
disableTask.complete();
|
||
|
disableTask.setTimeout( 1.f );
|
||
|
disableTask = $null_entity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::DeployableBase_OnKilled( entity attacker, entity inflictor ) {
|
||
|
FreeRepairTask();
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
CompleteDestroyTask();
|
||
|
|
||
|
// need to check for things like HE/Plasma charges still being on the deployable
|
||
|
float c = entitiesInBounds( getAbsMins(), getAbsMaxs(), MASK_ALL, 1 );
|
||
|
float i = 0;
|
||
|
for ( i = 0; i < c; i++ ) {
|
||
|
entity e = getBoundsCacheEntity( i );
|
||
|
if ( e.getMaster() == self ) {
|
||
|
e.vOnTargetDestroyed();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
player attackPlayer = attacker;
|
||
|
if ( attackPlayer != $null_entity ) {
|
||
|
if ( getEntityAllegiance( inflictor ) == TA_ENEMY ) {
|
||
|
sys.increaseStatInt( statNumDestroyed, attackPlayer.getEntityNumber(), 1 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CreateDestroyThread();
|
||
|
}
|
||
|
|
||
|
void deployable_base::init() {
|
||
|
string teamName = getKey( "team" );
|
||
|
if ( teamName != "" ) {
|
||
|
setGameTeam( sys.getTeam( teamName ) );
|
||
|
}
|
||
|
|
||
|
setTakesDamage( 0.f );
|
||
|
|
||
|
playAnim( ANIMCHANNEL_ALL, "undeployed" );
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
if ( !manualDeploy ) {
|
||
|
vOnDeploy();
|
||
|
} else {
|
||
|
thread DoBoundsDamageThread();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float deployable_base::OnUpdateCrosshairInfo( entity p ) {
|
||
|
if ( !sys.doClientSideStuff() ) {
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
float allegiance = getEntityAllegiance( p );
|
||
|
vector color = GetAllegianceColor( allegiance );
|
||
|
float distance = chGetDistance();
|
||
|
float range = InchesToMetres( distance );
|
||
|
float health = getHealth();
|
||
|
|
||
|
chSetNumLines( 0 );
|
||
|
float index;
|
||
|
|
||
|
// define length of health bar
|
||
|
float healthBarLength;
|
||
|
float maxHealth = getMaxHealth();
|
||
|
if ( maxHealth >= 2000.f ) {
|
||
|
healthBarLength = 150.f;
|
||
|
} else if ( maxHealth >= 1000.f ) {
|
||
|
healthBarLength = 100.f;
|
||
|
} else {
|
||
|
healthBarLength = 75.f;
|
||
|
}
|
||
|
|
||
|
team_base team;
|
||
|
|
||
|
if ( p != $null_entity ) {
|
||
|
// see if theres a valid action to perform
|
||
|
float code = GetActivateCode( p, distance );
|
||
|
if ( code != AK_NONE ) {
|
||
|
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 ) ) {
|
||
|
if ( code == AK_HACK ) {
|
||
|
p.sendToolTip( useMeToolTip1_Hack );
|
||
|
}
|
||
|
} else {
|
||
|
if ( code == AK_HACK ) {
|
||
|
p.sendToolTip( useMeToolTip2_Hack );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vector disabledColor;
|
||
|
if ( allegiance == TA_ENEMY || allegiance == TA_FRIEND ) {
|
||
|
disabledColor = g_colorYellow;
|
||
|
} else {
|
||
|
disabledColor = color;
|
||
|
}
|
||
|
|
||
|
index = chAddLine();
|
||
|
chSetLineTextIndex( index, objectTitle );
|
||
|
chSetLineColor( index, color, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
|
||
|
if ( owner != $null_entity ) {
|
||
|
if ( allegiance == TA_FRIEND ) {
|
||
|
index = chAddLine();
|
||
|
sys.pushLocString( sys.toWStr( owner.getCleanUserName() ) );
|
||
|
chSetLineText( index, sys.localizeStringArgs( "game/deployable_owner" ) );
|
||
|
chSetLineColor( index, color, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( health <= 0 ) {
|
||
|
if ( maxHealth != 0.f ) {
|
||
|
index = chAddLine();
|
||
|
chSetLineTextIndex( index, g_locStr_Destroyed );
|
||
|
chSetLineColor( index, color, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
}
|
||
|
} else {
|
||
|
if ( disabledState ) {
|
||
|
index = chAddLine();
|
||
|
|
||
|
float diff = disableEndTime - sys.getTime();
|
||
|
if ( diff > 0 ) {
|
||
|
sys.pushLocString( int( diff ) );
|
||
|
chSetLineText( index, sys.localizeStringArgs( "game/disabled_info" ) );
|
||
|
} else {
|
||
|
chSetLineTextIndex( index, g_locStr_Disabled );
|
||
|
}
|
||
|
|
||
|
chSetLineColor( index, disabledColor, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
}
|
||
|
|
||
|
index = chAddLine();
|
||
|
chSetLineColor( index, color, 0.5f );
|
||
|
chSetLineType( index, CI_BAR );
|
||
|
chSetLineFraction( index, getHealth() / getMaxHealth() );
|
||
|
chSetLineSize( index, healthBarLength, CROSSHAIR_INFO_BAR_HEIGHT );
|
||
|
|
||
|
if ( !disabledState ) {
|
||
|
G_StringForFireSupportState( fireSupportState );
|
||
|
|
||
|
index = chAddLine();
|
||
|
chSetLineTextIndex( index, g_fireSupportStateStr );
|
||
|
chSetLineColor( index, color, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
}
|
||
|
|
||
|
if ( range <= 100 ) {
|
||
|
index = chAddLine();
|
||
|
chSetLineText( index, G_BuildRangeStr( range ) );
|
||
|
chSetLineColor( index, color, 1.f );
|
||
|
chSetLineType( index, CI_TEXT );
|
||
|
chSetLineSize( index, 0, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
float deployable_base::vGetPliersProgressBarValue( float action ) {
|
||
|
if ( action == AC_HACK ) {
|
||
|
if ( !IsDamageHackTime() || damageHackCount == 0 ) {
|
||
|
return hackCount / maxHackCount;
|
||
|
} else {
|
||
|
return damageHackCount / maxDamageHackCount;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( action == AC_REPAIR ) {
|
||
|
return getHealth() / getMaxHealth();
|
||
|
}
|
||
|
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::vCheckActionCode( entity p, float actionCode ) {
|
||
|
if ( actionCode == AC_HACK ) {
|
||
|
if ( getEntityAllegiance( p ) != TA_ENEMY ) {
|
||
|
return false;
|
||
|
}
|
||
|
if ( !disabledState ) {
|
||
|
return true;
|
||
|
}
|
||
|
if ( getHealth() > disableHackHealth ) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ( actionCode == AC_REPAIR ) {
|
||
|
if ( getEntityAllegiance( p ) != TA_FRIEND ) {
|
||
|
return false;
|
||
|
}
|
||
|
float health = getHealth();
|
||
|
return ( health > 0 ) && ( health < getMaxHealth() );
|
||
|
}
|
||
|
|
||
|
if ( actionCode == AC_ENEMY_REPAIR ) {
|
||
|
if ( getEntityAllegiance( p ) != TA_FRIEND ) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( actionCode == AC_DISMANTLE ) {
|
||
|
if ( getEntityAllegiance( p ) != TA_FRIEND ) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::NeedsRepair() {
|
||
|
return getHealth() < getMaxHealth();
|
||
|
}
|
||
|
|
||
|
float deployable_base::GetCurrentMaxHackCount() {
|
||
|
if ( IsDamageHackTime() ) {
|
||
|
return maxDamageHackCount;
|
||
|
}
|
||
|
return maxHackCount;
|
||
|
}
|
||
|
float deployable_base::GetCurrentHackCount() {
|
||
|
if ( IsDamageHackTime() ) {
|
||
|
return damageHackCount;
|
||
|
}
|
||
|
return hackCount;
|
||
|
}
|
||
|
void deployable_base::SetCurrentHackCount( float hack ) {
|
||
|
if ( IsDamageHackTime() ) {
|
||
|
damageHackCount = hack;
|
||
|
} else {
|
||
|
hackCount = hack;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::IsDamageHackTime() {
|
||
|
return disabledState;
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnDisableHackedTimeChanged() {
|
||
|
if ( sys.getTime() - disableHackedTime < 2 ) {
|
||
|
playJointEffect( "fx_damage_hacked", empJointHandle, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::vHack( entity p ) {
|
||
|
float maxHack = GetCurrentMaxHackCount();
|
||
|
float hack = GetCurrentHackCount();
|
||
|
|
||
|
if ( hack >= maxHack ) {
|
||
|
hack = 0;
|
||
|
}
|
||
|
if ( !IsDamageHackTime() ) {
|
||
|
// make sure damage hack got reset
|
||
|
damageHackCount = 0;
|
||
|
}
|
||
|
|
||
|
float count = 1;
|
||
|
team_base team = p.getGameTeam();
|
||
|
if ( team.HasFastHackBonus( p ) ) {
|
||
|
count = count * 1.25f;
|
||
|
}
|
||
|
hack = hack + count;
|
||
|
SetCurrentHackCount( hack );
|
||
|
|
||
|
if ( hack >= maxHack && !sys.isClient() ) {
|
||
|
sys.increaseStatInt( sys.allocStatInt( team.getName() + "_hack_uses" ), p.getEntityNumber(), 1 );
|
||
|
if ( hackProficiency != -1 ) {
|
||
|
p.giveProficiency( hackProficiency, 1.f, disableTask, "hack success" );
|
||
|
}
|
||
|
|
||
|
if ( !IsDamageHackTime() ) {
|
||
|
boolean oldDisabled = disabledState;
|
||
|
DoHack( p, hackDisableTime );
|
||
|
|
||
|
UpdateDisabledStats( p, oldDisabled );
|
||
|
} else {
|
||
|
// cancel the hack
|
||
|
SetDisableEndTime( sys.getTime() );
|
||
|
|
||
|
// damage to the disable hack health
|
||
|
setTakesDamage( 1.f );
|
||
|
float neededScale = getHealth() - disableHackHealth;
|
||
|
applyDamage( $null_entity, $null_entity, vec3_up, GetDamage( "damage_deployable_disable" ), neededScale, $null_entity );
|
||
|
disableHackedTime = sys.getTime();
|
||
|
OnDisableHackedTimeChanged();
|
||
|
|
||
|
sys.increaseStatInt( statNumDisabled, p.getEntityNumber(), 1 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::SelfDestruct() {
|
||
|
// sys.wait( 4.f );
|
||
|
setTakesDamage( 1.f );
|
||
|
applyDamage( $null_entity, $null_entity, vec3_up, GetDamage( "damage_deployable_destruct" ), 1.f, $null_entity );
|
||
|
}
|
||
|
|
||
|
void deployable_base::vDismantle( entity p ) {
|
||
|
thread SelfDestruct();
|
||
|
}
|
||
|
|
||
|
void deployable_base::vRepair( float count, entity p ) {
|
||
|
count = count * repairMultiplier;
|
||
|
|
||
|
float maxHealth = getMaxHealth();
|
||
|
float health = getHealth();
|
||
|
float lost = maxHealth - health;
|
||
|
if ( count > lost ) {
|
||
|
count = lost;
|
||
|
}
|
||
|
|
||
|
float teamDamageCount = getTeamDamageDone();
|
||
|
|
||
|
float repairCount = count - teamDamageCount;
|
||
|
if ( repairCount > 0 ) {
|
||
|
team_base team = p.getGameTeam();
|
||
|
if ( team != $null_entity ) {
|
||
|
team.GiveRepairProficiency( p, repairTask, repairCount );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setTeamDamageDone( teamDamageCount - count );
|
||
|
|
||
|
float total = health + count;
|
||
|
setHealth( total );
|
||
|
if ( total >= getMaxHealth() ) {
|
||
|
CompleteRepairTask();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vector deployable_base::vGetLastRepairOrigin() {
|
||
|
vector mins = getAbsMins();
|
||
|
vector maxs = getAbsMaxs();
|
||
|
return (mins + maxs) * 0.5;
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::vOrbitUnderneath() {
|
||
|
return orbitUnderneath;
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::vCustomOrbitRadius() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
float deployable_base::vGetOrbitRadius() {
|
||
|
if ( orbitRadius == 0 ) {
|
||
|
vector size = getAbsMaxs() - getAbsMins();
|
||
|
orbitRadius = 0.7 * sys.sqrt( size_x * size_x + size_y * size_x );
|
||
|
}
|
||
|
|
||
|
return orbitRadius;
|
||
|
}
|
||
|
|
||
|
void deployable_base::DoHack( entity hacker, float time ) {
|
||
|
CompleteDisableTask();
|
||
|
|
||
|
float newEndTime = sys.getTime() + time;
|
||
|
if ( newEndTime > disableEndTime ) {
|
||
|
SetDisableEndTime( newEndTime );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::DeployableBase_Deploy() {
|
||
|
if ( !sys.isClient() ) {
|
||
|
if ( owner != $null_entity ) {
|
||
|
// add self to the bin
|
||
|
owner.binAdd( self );
|
||
|
|
||
|
G_GiveDeployBonus( owner, self );
|
||
|
}
|
||
|
|
||
|
if ( isSpotted() ) {
|
||
|
killTaskRequestee = $null_entity;
|
||
|
InitDisableTask( true );
|
||
|
InitDestroyTask( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vDoneDeploy();
|
||
|
}
|
||
|
|
||
|
void deployable_base::vDoneDeploy() {
|
||
|
SetDeployingFinished();
|
||
|
}
|
||
|
|
||
|
void deployable_base::vOnDeploy() {
|
||
|
thread DoDeploy();
|
||
|
}
|
||
|
|
||
|
void deployable_base::DoDeploy() {
|
||
|
// Gordon: only do this if we haven't been spawned from the console
|
||
|
if ( manualDeploy ) {
|
||
|
// if the territory has been captured since we were called in, shouldn't deploy
|
||
|
if ( sys.getTerritoryForPoint( getWorldOrigin(), getGameTeam(), 1.f, 0.f ) == $null_entity ) {
|
||
|
vDismantle( $null_entity );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !sys.isClient() ) {
|
||
|
isDeploying = true;
|
||
|
}
|
||
|
|
||
|
float hitGroundEffect = getFloatKey( "play_hitground_effect" );
|
||
|
if ( hitGroundEffect ) {
|
||
|
startSound( "snd_drop", SND_DEPLOYABLE_IDLE );
|
||
|
playEffect( "fx_hitground", "origin", false );
|
||
|
}
|
||
|
|
||
|
preventDeployment( 1.f );
|
||
|
|
||
|
KillBoundsDamageThread();
|
||
|
|
||
|
forceAnimUpdate( true );
|
||
|
|
||
|
float i;
|
||
|
float numHelpers = getFloatKeyWithDefault( "num_ik", 0.f );
|
||
|
|
||
|
if ( numHelpers > 0.f ) {
|
||
|
playAnim( ANIMCHANNEL_ALL, "pre_ik" );
|
||
|
|
||
|
while ( isAnimating() ) {
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
|
||
|
playAnim( ANIMCHANNEL_ALL, "post_ik" );
|
||
|
|
||
|
for( i = 0; i < numHelpers; i++ ) {
|
||
|
addHelper( GetStringMap( getKey( "str_ik" + i ) ) );
|
||
|
}
|
||
|
|
||
|
while ( isAnimating() ) {
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
} else {
|
||
|
playAnim( ANIMCHANNEL_ALL, "deploy" );
|
||
|
|
||
|
while ( isAnimating() ) {
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
forceAnimUpdate( false );
|
||
|
|
||
|
DeployableBase_Deploy();
|
||
|
}
|
||
|
|
||
|
void deployable_base::vApplyEmpDamage( entity attacker, float time, float weaponTime ) {
|
||
|
boolean oldDisabled = disabledState;
|
||
|
|
||
|
DoHack( attacker, time );
|
||
|
UpdateDisabledStats( attacker, oldDisabled );
|
||
|
if ( disableProficiency != -1 ) {
|
||
|
attacker.giveProficiency( disableProficiency, 1.f, disableTask, "emp on deployable" );
|
||
|
}
|
||
|
|
||
|
player playerAttacker = attacker;
|
||
|
if ( playerAttacker != $null_entity ) {
|
||
|
team_base team = attacker.getGameTeam();
|
||
|
if ( team != $null ) {
|
||
|
team.LogEmpUsage( playerAttacker );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnSetTeam( object oldTeam, object newTeam ) {
|
||
|
if ( oldTeam != $null ) {
|
||
|
oldTeam.unRegisterDeployable( self );
|
||
|
}
|
||
|
if ( newTeam != $null ) {
|
||
|
newTeam.registerDeployable( self );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::vIsDeployed() {
|
||
|
return IsDeployed();
|
||
|
}
|
||
|
|
||
|
boolean deployable_base::IsDeployed() {
|
||
|
return finishedDeploying;
|
||
|
}
|
||
|
|
||
|
void deployable_base::SetDeployingFinished() {
|
||
|
finishedDeploying = true;
|
||
|
deployFinishedTime = sys.getTime();
|
||
|
fireSupportState = MPS_READY;
|
||
|
|
||
|
if ( getHealth() > 0 ) {
|
||
|
setTakesDamage( 1.f );
|
||
|
|
||
|
// ao: only do this if we haven't been spawned from the console
|
||
|
if ( manualDeploy ) {
|
||
|
// if the territory has been captured since we were called in, shouldn't deploy
|
||
|
if ( sys.getTerritoryForPoint( getWorldOrigin(), getGameTeam(), 1.f, 0.f ) == $null_entity ) {
|
||
|
vDismantle( $null_entity );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( owner != $null_entity ) {
|
||
|
if ( owner.isLocalPlayer() ) {
|
||
|
owner.sendToolTip( GetToolTip( getKey( "tt_deploy_finished" ) ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::UpdateDisabledStats( entity attacker, boolean oldDisabled ) {
|
||
|
if ( !sys.isClient() ) {
|
||
|
if ( !oldDisabled && disabledState ) {
|
||
|
player attackerPlayer = attacker;
|
||
|
if ( attackerPlayer != $null_entity ) {
|
||
|
sys.increaseStatInt( statNumDisabled, attackerPlayer.getEntityNumber(), 1 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnPostDamage( entity attacker, float oldHealth, float newHealth ) {
|
||
|
boolean oldDisabled = disabledState;
|
||
|
UpdateState( newHealth );
|
||
|
UpdateDisabledStats( attacker, oldDisabled );
|
||
|
}
|
||
|
|
||
|
void deployable_base::UpdateState( float health ) {
|
||
|
float maxHealth = getMaxHealth();
|
||
|
if ( maxHealth == 0.f ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float frac = health / maxHealth;
|
||
|
|
||
|
float newState;
|
||
|
|
||
|
player p = sys.getLocalPlayer();
|
||
|
|
||
|
boolean showHealthStatus = false;
|
||
|
if ( p != $null_entity ) {
|
||
|
team_base team = p.getGameTeam();
|
||
|
float allegiance = getEntityAllegiance( p );
|
||
|
if ( allegiance == TA_FRIEND ) {
|
||
|
showHealthStatus = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float healthStatusParm = 0;
|
||
|
|
||
|
healthStatusParm = frac;
|
||
|
if ( frac < ( 1.f / 3.f ) ) {
|
||
|
newState = DS_DISABLED;
|
||
|
} else if ( frac < ( 2.f / 3.f ) ) {
|
||
|
newState = DS_DAMAGED;
|
||
|
} else {
|
||
|
newState = DS_NORMAL;
|
||
|
}
|
||
|
|
||
|
if ( showHealthStatus && !disabledState ) {
|
||
|
sys.setCMIconShaderParm( commandMapHandle, 5, healthStatusParm );
|
||
|
}
|
||
|
|
||
|
SetDeployableState( newState );
|
||
|
}
|
||
|
|
||
|
void deployable_base::SetDeployableState( float newState ) {
|
||
|
if ( currentState == newState ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( newState == DS_NORMAL ) {
|
||
|
OnStateNormal();
|
||
|
} else if ( newState == DS_DAMAGED ) {
|
||
|
OnStateDamaged();
|
||
|
InitRepairTask( true );
|
||
|
} else if ( newState == DS_DISABLED ) {
|
||
|
OnStateDisabled();
|
||
|
InitRepairTask( true );
|
||
|
}
|
||
|
|
||
|
currentState = newState;
|
||
|
|
||
|
UpdateDisabled();
|
||
|
}
|
||
|
|
||
|
void deployable_base::DeployableBase_OnStateNormal() {
|
||
|
playAnim( ANIMCHANNEL_ALL, "base" );
|
||
|
thread UpdateAnimThread();
|
||
|
stopEffect( "fx_damaged" );
|
||
|
|
||
|
FreeRequestIcon();
|
||
|
if ( owner == sys.getLocalPlayer() && disableEndTime <= sys.getTime() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.state", DS_NORMAL );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::DeployableBase_OnStateDamaged() {
|
||
|
float numDamageJoints;
|
||
|
string jointName;
|
||
|
|
||
|
playAnim( ANIMCHANNEL_ALL, "damaged" );
|
||
|
thread UpdateAnimThread();
|
||
|
|
||
|
// Is it being damage or being repaired?
|
||
|
if ( currentState == DS_NORMAL ) {
|
||
|
numDamageJoints = getFloatKeyWithDefault( "numDamageJoints", 0 );
|
||
|
if ( numDamageJoints ) {
|
||
|
jointName = getKey( "damageJoint" + int( sys.random( numDamageJoints ) ) );
|
||
|
playEffect( "fx_damaged", jointName, true );
|
||
|
}
|
||
|
} else {
|
||
|
stopEffect( "fx_damaged" );
|
||
|
}
|
||
|
|
||
|
SetupRequestIcon( "mtr_cm_icon_need_repair", "require_view_repair" );
|
||
|
thread RequestIconThread( 5.f );
|
||
|
if( owner == sys.getLocalPlayer() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.state", DS_DISABLED );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::DeployableBase_OnStateDisabled() {
|
||
|
float numDamageJoints;
|
||
|
string jointName;
|
||
|
|
||
|
playAnim( ANIMCHANNEL_ALL, "destroyed" );
|
||
|
thread UpdateAnimThread();
|
||
|
|
||
|
numDamageJoints = getFloatKeyWithDefault( "numDamageJoints", 0 );
|
||
|
if ( numDamageJoints ) {
|
||
|
jointName = getKey( "damageJoint" + int( sys.random( numDamageJoints ) ) );
|
||
|
playEffect( "fx_damaged", jointName, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnStateNormal() {
|
||
|
DeployableBase_OnStateNormal();
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnStateDamaged() {
|
||
|
DeployableBase_OnStateDamaged();
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnStateDisabled() {
|
||
|
DeployableBase_OnStateDisabled();
|
||
|
}
|
||
|
|
||
|
void deployable_base::OnKilled( entity inflictor, entity attacker, float damage, vector direction, float location ) {
|
||
|
DeployableBase_OnKilled( attacker, inflictor );
|
||
|
}
|
||
|
|
||
|
void deployable_base::CreateDestroyThread() {
|
||
|
thread DestroyThread();
|
||
|
}
|
||
|
|
||
|
void deployable_base::DestroyThread() {
|
||
|
playEffect( "fx_death", "" , 0 );
|
||
|
hide();
|
||
|
forceDisableClip();
|
||
|
|
||
|
sys.wait( 5.0f );
|
||
|
|
||
|
if( !sys.isClient() ) {
|
||
|
remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void deployable_base::UpdateGui() {
|
||
|
sys.setGUIString( GUI_GLOBALS_HANDLE, "deployables.statusMaterial", colorMaterial );
|
||
|
sys.setGUIString( GUI_GLOBALS_HANDLE, "deployables.statusDesatMaterial", desatMaterial );
|
||
|
sys.setGUIString( GUI_GLOBALS_HANDLE, "deployables.deployableName", getKey( "title" ) );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.maxHealth", getMaxHealth() );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.state", DS_NORMAL );
|
||
|
|
||
|
while( true ) {
|
||
|
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.health", getHealth() );
|
||
|
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float deployable_base::GetChargePerUse() {
|
||
|
if ( owner != $null_entity ) {
|
||
|
team_base team = owner.getGameTeam();
|
||
|
if ( team != $null ) {
|
||
|
if ( team.HasFastFireSupportRecharge( owner ) ) {
|
||
|
return 0.80f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 1.f;
|
||
|
}
|
||
|
|
||
|
void deployable_base::Base_TargetSetTarget( vector targetPos, entity targetEnt ) {
|
||
|
if( !sys.isClient() ) {
|
||
|
owner.EnergyBar_Remove( GetChargePerUse() );
|
||
|
G_DelayFireSupport( owner, self, timerLength );
|
||
|
}
|
||
|
|
||
|
IncreaseUseCount();
|
||
|
}
|
||
|
|
||
|
// Gordon: FIXME: This stuff doesn't even make sense
|
||
|
float deployable_base::vGetFiringStatus( object traceObject ) {
|
||
|
if ( disabledState ) {
|
||
|
return MPS_DISABLED;
|
||
|
}
|
||
|
|
||
|
float state = MPS_DISABLED;
|
||
|
float thisState = fireSupportState;
|
||
|
|
||
|
if ( thisState == MPS_FIRING_PREPARE || thisState == MPS_FIRING ) {
|
||
|
return MPS_FIRING;
|
||
|
}
|
||
|
|
||
|
if ( thisState == MPS_READY ) {
|
||
|
if( traceObject == $null ) {
|
||
|
state = MPS_READY;
|
||
|
} else if ( vTargetGetValid( traceObject.getTraceEndPos() ) ) {
|
||
|
state = MPS_READY;
|
||
|
} else {
|
||
|
thisState = MPS_OUT_OF_RANGE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( state != MPS_OUT_OF_RANGE && thisState > state ) {
|
||
|
state = thisState;
|
||
|
}
|
||
|
|
||
|
if ( GetCoolDownFraction() > 0.f ) {
|
||
|
return MPS_RELOADING;
|
||
|
}
|
||
|
|
||
|
if ( state == MPS_READY ) {
|
||
|
// explicitly look up firesupport timer value
|
||
|
|
||
|
// FIXME: hardcoded instead of looking up in weapon def
|
||
|
string energyKey = "energy_firesupport";
|
||
|
|
||
|
// find timer and recharge time
|
||
|
float chargeTimer = sys.allocTargetTimer( energyKey );
|
||
|
float energyChargeTime = GetGlobalFloat( energyKey + "_time" );
|
||
|
if ( energyChargeTime <= 0.f ) {
|
||
|
energyChargeTime = 1.f;
|
||
|
}
|
||
|
|
||
|
// find charge used
|
||
|
float chargeUsed = sys.getTargetTimerValue( chargeTimer, owner ) - sys.getTime();
|
||
|
if ( chargeUsed < 0 ) {
|
||
|
chargeUsed = 0;
|
||
|
} else {
|
||
|
chargeUsed = chargeUsed / energyChargeTime;
|
||
|
}
|
||
|
|
||
|
// change state if we can't remove charge
|
||
|
if( ( chargeUsed + GetChargePerUse() ) > 1.f ) {
|
||
|
state = MPS_WAITING;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
float deployable_base::GetCoolDownFraction() {
|
||
|
float coolDownTime = sys.getTargetTimerValue( timerHandle, owner );
|
||
|
float coolDownStartTime = sys.getTargetTimerValue( timerStartHandle, owner );
|
||
|
|
||
|
float temp = ( coolDownTime - sys.getTime() );
|
||
|
if ( temp > 0.f ) {
|
||
|
return temp / ( coolDownTime - coolDownStartTime );
|
||
|
}
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
float deployable_base::vGetTimerState() {
|
||
|
return GetCoolDownFraction();
|
||
|
}
|
||
|
|
||
|
float deployable_base::vGetChargeTime() {
|
||
|
float coolDownTime = sys.getTargetTimerValue( timerHandle, owner );
|
||
|
float coolDownStartTime = sys.getTargetTimerValue( timerStartHandle, owner );
|
||
|
|
||
|
float temp = ( coolDownTime - coolDownStartTime );
|
||
|
if ( temp > 0.f ) {
|
||
|
return temp;
|
||
|
}
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
float deployable_base::GetLockTime() {
|
||
|
float lockTime = getFloatKey( "target_locktime" );
|
||
|
team_base team = owner.getGameTeam();
|
||
|
if ( team.HasFastFireSupportLock( owner ) ) {
|
||
|
lockTime = lockTime * 0.8f;
|
||
|
}
|
||
|
return lockTime;
|
||
|
}
|
||
|
|
||
|
float deployable_base::GetLockGraceTime() {
|
||
|
return gracePeriod;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::SetupRequestIcon
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::SetupRequestIcon( string key, string requirement ) {
|
||
|
FreeRequestIcon();
|
||
|
|
||
|
commandMapRequest = sys.allocCMIcon( self, getFloatKey( "icon_sort_cm" ) );
|
||
|
|
||
|
sys.setCMIconMaterial( commandMapRequest, GetMaterial( getKey( key ) ) );
|
||
|
sys.setCMIconUnknownMaterial( commandMapRequest, GetMaterial( getKey( key ) ) );
|
||
|
sys.addCMIconRequirement( commandMapRequest, getKey( requirement ) );
|
||
|
sys.setCMIconColorMode( commandMapRequest, CM_NORMAL );
|
||
|
sys.setCMIconDrawMode( commandMapRequest, DM_ROTATED_MATERIAL );
|
||
|
sys.setCMIconSize( commandMapRequest, 24.0f );
|
||
|
sys.setCMIconUnknownSize( commandMapRequest, 16.0f );
|
||
|
sys.setCMIconColor( commandMapRequest, '1 1 1', 1.0f );
|
||
|
sys.flashCMIcon( commandMapRequest, -1, SPOTTED_FLASH_TIME, -1 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::FreeRequestIcon
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::FreeRequestIcon() {
|
||
|
if( commandMapRequest != -1 ) {
|
||
|
sys.freeCMIcon( self, commandMapRequest );
|
||
|
commandMapRequest = -1;
|
||
|
}
|
||
|
sys.killThread( "RequestIconThread_" + getName() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::RequestIconThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::RequestIconThread( float timeout ) {
|
||
|
sys.wait( timeout );
|
||
|
FreeRequestIcon();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::vCheckProficiency
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::vCheckProficiency() {
|
||
|
DeployableBase_CheckProficiency();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::DeployableBase_CheckProficiency
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::DeployableBase_CheckProficiency() {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::SetDisableEndTime
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::SetDisableEndTime( float t ) {
|
||
|
disableEndTime = t;
|
||
|
|
||
|
KillDisableThread();
|
||
|
if ( disableEndTime > sys.getTime() ) {
|
||
|
CreateDisableThread();
|
||
|
}
|
||
|
|
||
|
UpdateDisabled();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::DeployableBase_CalculateDisabledState
|
||
|
=====================
|
||
|
*/
|
||
|
boolean deployable_base::DeployableBase_CalculateDisabledState() {
|
||
|
boolean newDisabledState = false;
|
||
|
|
||
|
if ( currentState != DS_NORMAL ) {
|
||
|
newDisabledState = true;
|
||
|
} else if ( disableEndTime > sys.getTime() ) {
|
||
|
newDisabledState = true;
|
||
|
}
|
||
|
|
||
|
return newDisabledState;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::CalculateDisabledState
|
||
|
=====================
|
||
|
*/
|
||
|
boolean deployable_base::CalculateDisabledState() {
|
||
|
return DeployableBase_CalculateDisabledState();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::UpdateDisabled
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::UpdateDisabled() {
|
||
|
SetDisabled( CalculateDisabledState() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::IsDisabled
|
||
|
=====================
|
||
|
*/
|
||
|
boolean deployable_base::IsDisabled() {
|
||
|
return disabledState;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::SetDisabled
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::SetDisabled( boolean newDisabledState ) {
|
||
|
if ( disabledState == newDisabledState ) {
|
||
|
return;
|
||
|
}
|
||
|
disabledState = newDisabledState;
|
||
|
|
||
|
if ( disabledState ) {
|
||
|
OnDisabled();
|
||
|
FreeDisableTask();
|
||
|
} else {
|
||
|
OnReEnabled();
|
||
|
if ( isSpotted() ) {
|
||
|
killTaskRequestee = $null_entity;
|
||
|
InitDisableTask( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::OnDisabled
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::OnDisabled() {
|
||
|
sys.setCMIconShaderParm( commandMapHandle, 5, 0 );
|
||
|
if ( owner != $null_entity ) {
|
||
|
if ( owner.isLocalPlayer() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.state", DS_DISABLED );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::OnReEnabled
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::OnReEnabled() {
|
||
|
sys.setCMIconShaderParm( commandMapHandle, 5, 1 );
|
||
|
if ( owner != $null_entity ) {
|
||
|
if ( owner.isLocalPlayer() ) {
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.state", DS_NORMAL );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::KillDisableThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::KillDisableThread() {
|
||
|
sys.killThread( "DisableThread_" + getName() );
|
||
|
stopEffect( "fx_emped" );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::CreateDisableThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::CreateDisableThread() {
|
||
|
KillDisableThread();
|
||
|
thread DisableThread();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::DisableThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::DisableThread() {
|
||
|
if ( empJointHandle != -1 ) {
|
||
|
playJointEffect( "fx_emped", empJointHandle, 1 );
|
||
|
}
|
||
|
|
||
|
float delay = disableEndTime - sys.getTime();
|
||
|
if ( delay > 0.f ) {
|
||
|
sys.wait( delay );
|
||
|
}
|
||
|
|
||
|
stopEffect( "fx_emped" );
|
||
|
sys.waitFrame();
|
||
|
|
||
|
sys.threadName( "DisableThreadDead" );
|
||
|
|
||
|
UpdateDisabled();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::DoBoundsDamageThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::DoBoundsDamageThread() {
|
||
|
float dmgIndex = GetDamage( getKey( "dmg_falling" ) );
|
||
|
while ( 1 ) {
|
||
|
vector mins = self.getAbsMins();
|
||
|
vector maxs = self.getAbsMaxs();
|
||
|
mins_z = mins_z - 64;
|
||
|
|
||
|
//sys.debugBounds( g_colorRed, mins, maxs, 0 );
|
||
|
|
||
|
float count = self.entitiesInBounds( mins, maxs, 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 ) {
|
||
|
if ( self.touchesBounds( other ) ) {
|
||
|
other.applyDamage( $null_entity, self, vec3_down, dmgIndex, 1.f, $null_entity );
|
||
|
if ( other.inCollection( "mcp" ) ) {
|
||
|
SelfDestruct();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::KillBoundsDamageThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::KillBoundsDamageThread() {
|
||
|
sys.killThread( "DoBoundsDamageThread_" + getName() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::vGetQuickChatString
|
||
|
=====================
|
||
|
*/
|
||
|
string deployable_base::vGetQuickChatString( entity p ) {
|
||
|
if ( getEntityAllegiance( p ) == TA_FRIEND ) {
|
||
|
return getKey( "contextmenu_quickchat_friendly" );
|
||
|
}
|
||
|
return getKey( "contextmenu_quickchat_enemy" );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::vUpdateFiringStatusObject
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::vUpdateFiringStatusObject( entity localPlayer ) {
|
||
|
if( fsStatus != $null ) {
|
||
|
fsStatus.Update( localPlayer, $null, TARGET_LOCK_NOT_LOCKED, 0 );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.timerValue", fsStatus.timerStatus );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "deployables.guiState", fsStatus.guiStatus );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::FlashCMIcon
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::FlashCMIcon( entity p, float requiredTeam, float flashTime ) {
|
||
|
entity local = sys.getLocalViewPlayer();
|
||
|
if ( local == $null_entity ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( flashTime == -1 ) {
|
||
|
flashTime = SPOTTED_FLASH_TIME;
|
||
|
}
|
||
|
|
||
|
if ( getEntityAllegiance( local ) == requiredTeam ) {
|
||
|
float flags = sys.getCMIconFlags( commandMapHandle );
|
||
|
if ( requiredTeam == TA_ENEMY ) {
|
||
|
flags = flags | CMF_ENEMYALWAYSKNOWN;
|
||
|
}
|
||
|
sys.flashCMIcon( commandMapHandle, -1, flashTime, flags );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================
|
||
|
deployable_base::UpdateAnimThread
|
||
|
=====================
|
||
|
*/
|
||
|
void deployable_base::UpdateAnimThread() {
|
||
|
forceAnimUpdate( true );
|
||
|
waitUntil( !isAnimating() );
|
||
|
forceAnimUpdate( false );
|
||
|
}
|