Script:Files:script/vehicles/base.script
From Mod Wiki
#define VWS_SHUTDOWN 0 #define VWS_POWERED 1 #define VPT_PART 1 #define VPT_SIMPLE_PART 2 #define VPT_WHEEL 4 #define VPT_ROTOR 8 #define VPT_HOVER 16 #define VPT_MASS 32 #define VPT_TRACK 64 #define VPT_THRUSTER 128 #define VPT_SUSPENSION 256 #define VPT_VTOL 512 #define FASTER_DECOY_SCALE 0.66 object vehicle_base { void preinit(); void init(); void destroy(); void syncFields(); void OnKilled( entity inflictor, entity attacker, float damage, vector dir, float location ); void OnKilledRemove( entity inflictor, entity attacker, float damage, vector dir, float location ); void OnDecayed(); float OnUpdateCrosshairInfo( entity p ); void OnUsed( entity user ); float OnActivate( entity p, float distance ); void OnRouteKickPlayer(); float GetActivateCode( entity p, float distance ); float VehicleBase_OnActivate( entity p, float distance ); void vSetDeployer( entity other ); void OnSpotted( entity spotter ); void OnCollision_Base( object traceObject, float velocity, vector mins, vector maxs ); void NotifyBoundEntitiesOfDestruction(); void vTargetLockAlarm( entity other ); void vStopTargetLockAlarm( entity other ); float vGetTargetLockCount(); void vCheckProficiency(); boolean vSkipDeployDrop(); void vOnContextRepair( entity p ); void vOnContextKill( entity p ); void vOnContextNeedPassenger( entity p ); void vOnRemovePlayersKillTask( player p ); void vOnEndGame(); void CheckArmor(); void FireDecoy( entity p ); void OnPostDamage( entity attacker, float oldHealth, float newHealth ); void ShowDamageEffects( float oldHealth, float newHealth ); void OnSetTeam( object oldTeam, object newTeam ); void InitRadarValues() { ; } float vGetPliersProgressBarValue( float action ); boolean vCheckActionCode( entity p, float actionCode ); void UpdateHealth( float oldHealth, float newHealth ); void VehicleBase_UpdateHealth( float oldHealth, float newHealth ); void SetupCommandMap(); void SetupRequestIcon( string key, string requirement ); void FreeRequestIcon(); void RequestIconThread( float timeout ); void InitDestroyTask( boolean highCommand ); void FreeDestroyTask(); void CompleteDestroyTask(); void InitRepairTask( boolean highCommand ); void FreeRepairTask(); void CompleteRepairTask(); void InitNeedPassengerTask( entity p ); void FreeRequestTask(); void vRepair( float count, entity other ); vector vGetLastRepairOrigin(); boolean vBlockVehicleSpawn() { return true; } void ApplyEmpDamage_Base( entity attacker, float time, float weaponTime ); void vApplyEmpDamage( entity attacker, float time, float weaponTime ); void OnPlayerEntered( entity p, float position ); void OnPlayerEntered_Base( entity p, float position ); void OnPlayerExited( entity p, float position ); void OnPlayerExited_Base( entity p, float position ); void OnDecoyChargeTimeChanged(); void OnDecoyLaunched(); void DestroyThread(); void DecayThread(); void DamageEffectThread(); void OnTeleportEntityChanged( entity other ); void CheckFireTeamInfo( boolean localExiting ); void DecoyUseCharge(); boolean DecoyHasCharge(); float CalcDecoyChargeUsed(); void StartDecoyChargeThread(); void StopDecoyChargeThread(); void DecoyChargeThread(); boolean NeedGunner(); string vGetQuickChatString( entity p ); void FlashCMIcon( entity p, float requiredTeam ); float nextDecoyTime; float decoyChargeMax; float baseDecoyChargePerUse; float decoyChargeTime; float decoyFireRate; float decoyJointHandle; vector decoyLaunchVelocity; float decoyProjectileIndex; boolean decoyChargeThreadActive; float decoyChargePerUse; float commandMapRequest; task destroyTask; task requestTask; task repairTask; player killTaskRequestee; string jointEffectSmoke; string jointEffectFire; float damageLevelSmoke; float damageLevel1; float damageLevel2; float damageLevel3; float destroyDelay; float repairThreshold; float commandMapHandle; float commandMapFireTeamInfo; handle crosshairName; float targetLockCount; float damageEffectLevel; handle damageEffectHandle; handle damageSmokeEffectHandle; float disableProficiency; // variables for the repair drone boolean orbitUnderneath; float orbitRadius; float repairMultiplier; boolean vCustomOrbitRadius(); float vGetOrbitRadius(); boolean vOrbitUnderneath(); void SetArmorBonus( boolean value ); entity deployer; boolean hasArmorBonus; float healthBarLength; float toolTipVehicle_enter; float lastTooltipTime; float toolTipCannotRepair; float toolTipNoEntry; boolean playingKlaxon; float klaxonThreshold; float drownHeight; float maxEnterDistance; float nextCollisionEffectTime; float spiralHealthFrac; boolean EnemyHasLockedOnPlayer() { return ( targetLockCount > 0 ); } } void vehicle_base::syncFields() { syncBroadcast( "decoyChargeTime" ); syncCallback( "decoyChargeTime", "OnDecoyChargeTimeChanged" ); } void vehicle_base::preinit() { decoyFireRate = getFloatKey( "projectile_decoy_rate" ); decoyJointHandle = getJointHandle( getKey( "projectile_decoy_joint" ) ); decoyLaunchVelocity = getVectorKey( "projectile_decoy_velocity" ); decoyProjectileIndex = GetEntityDef( getKey( "def_projectile_decoy" ) ); crosshairName = sys.localizeString( getKey( "info_name" ) ); damageLevelSmoke = getFloatKey( "damage_smoke" ) / 100; damageLevel1 = getFloatKey( "damage_level1" ) / 100; damageLevel2 = getFloatKey( "damage_level2" ) / 100; damageLevel3 = getFloatKey( "damage_level3" ) / 100; disableProficiency = GetProficiency( getKey( "prof_disable" ) ); toolTipCannotRepair = GetToolTip( getKey( "tt_cannot_repair" ) ); toolTipNoEntry = GetToolTip( getKey( "tt_noentry" ) ); repairMultiplier = getFloatKeyWithDefault( "repair_multiplier", 1.f ); jointEffectSmoke = getKey( "joint_damage_smoke" ); jointEffectFire = getKey( "joint_damage_fire" ); destroyDelay = getFloatKey( "destroy_delay" ); repairThreshold = getFloatKey( "repair_threshold" ) / 100; commandMapRequest = -1; damageEffectLevel = 0; damageEffectHandle = 0; damageSmokeEffectHandle = 0; commandMapHandle = -1; commandMapFireTeamInfo = -1; SetupCommandMap(); if ( commandMapFireTeamInfo != -1 ) { sys.hideCMIcon( commandMapFireTeamInfo ); } orbitUnderneath = getFloatKey( "drone_orbit_underneath" ); orbitRadius = getFloatKey( "drone_orbit_radius" ); decoyChargeMax = getFloatKey( "projectile_decoy_max" ); baseDecoyChargePerUse = getFloatKey( "projectile_decoy_charge" ); baseDecoyChargePerUse = ( baseDecoyChargePerUse / 100 ) * decoyChargeMax; toolTipVehicle_enter = GetToolTip( getKey( "tt_use_vehicle" ) ); klaxonThreshold = getFloatKey( "klaxon_threshold" ); drownHeight = getFloatKeyWithDefault( "drown_height", 0.5 ); maxEnterDistance = getFloatKeyWithDefault( "max_enter_distance", 128 ); float maxHealth = getMaxHealth(); if ( maxHealth >= 3000.f ) { healthBarLength = 150.f; } else if ( maxHealth >= 2000.f ) { healthBarLength = 125.f; } else if ( maxHealth >= 500.f ) { healthBarLength = 100.f; } else { healthBarLength = 75.f; } } void vehicle_base::OnDecoyChargeTimeChanged() { OnDecoyLaunched(); } void vehicle_base::OnDecoyLaunched() { entity driver = getDriver(); if ( driver != $null_entity ) { if ( driver == sys.getLocalViewPlayer() ) { sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.decoyLaunchedTime", sys.getTime() ); StartDecoyChargeThread(); } } } void vehicle_base::SetupCommandMap() { commandMapHandle = sys.allocCMIcon( self, getFloatKey( "icon_sort_cm" ) ); float commandMapSize = 14;// getFloatKeyWithDefault( "icon_size_cm", 16.f ); sys.setCMIconDrawMode( commandMapHandle, DM_ROTATED_MATERIAL ); 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 / 2.0f ) ); sys.setCMIconFlag( commandMapHandle, CMF_FOLLOWROTATION ); sys.setCMIconFlag( commandMapHandle, CMF_FIRETEAMCOLORING ); // fire team ring /* commandMapFireTeamInfo = sys.allocCMIcon( self, getFloatKey( "icon_sort_cm_ft_ring" ) ); sys.setCMIconDrawMode( commandMapFireTeamInfo, DM_ROTATED_MATERIAL ); sys.setCMIconMaterial( commandMapFireTeamInfo, GetMaterial( getKey( "mtr_icon_team_ring" ) ) ); sys.setCMIconSize( commandMapFireTeamInfo, commandMapSize * getFloatKey( "team_ring_size" ) ); sys.setCMIconFlag( commandMapFireTeamInfo, CMF_TEAMONLY ); sys.setCMIconFlag( commandMapFireTeamInfo, CMF_FOLLOWROTATION ); sys.setCMIconFlag( commandMapFireTeamInfo, CMF_ALWAYSKNOWN ); sys.setCMIconColorMode( commandMapFireTeamInfo, CM_NORMAL ); sys.setCMIconColor( commandMapFireTeamInfo, g_colorWhite, 1.0f ); */ } void vehicle_base::NotifyBoundEntitiesOfDestruction() { entity next; entity current; for ( current = getNextTeamEntity(); current != $null_entity; current = next ) { next = current.getNextTeamEntity(); current.vOnBindMasterDestroyed(); } } void vehicle_base::destroy() { sys.freeCMIcon( self, commandMapHandle ); if ( commandMapFireTeamInfo != -1 ) { sys.freeCMIcon( self, commandMapFireTeamInfo ); } FreeRequestIcon(); NotifyBoundEntitiesOfDestruction(); if ( deployer != $null_entity ) { deployer.vOnVehicleDestroyed(); } if ( playingKlaxon ) { sys.startSoundDirect( "", SND_VEHICLE_INTERIOR_LOWHEALTH ); playingKlaxon = false; } FreeDestroyTask(); FreeRequestTask(); FreeRepairTask(); } void vehicle_base::SetupRequestIcon( string key, string requirement ) { FreeRequestIcon(); commandMapRequest = sys.allocCMIcon( self, getFloatKey( "icon_sort_cm_request" ) ); 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 ); } void vehicle_base::FreeRequestIcon() { if( commandMapRequest != -1 ) { sys.freeCMIcon( self, commandMapRequest ); commandMapRequest = -1; } sys.killThread( "RequestIconThread_" + getName() ); } void vehicle_base::RequestIconThread( float timeout ) { sys.wait( timeout ); FreeRequestIcon(); } void vehicle_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 vehicle_base::FreeDestroyTask() { if ( destroyTask != $null_entity ) { destroyTask.free(); } } void vehicle_base::CompleteRepairTask() { if ( repairTask != $null_entity ) { repairTask.complete(); repairTask.free(); } } void vehicle_base::CompleteDestroyTask() { if ( destroyTask != $null_entity ) { destroyTask.complete(); destroyTask.free(); } } void vehicle_base::InitRepairTask( boolean highCommand ) { if ( sys.isClient() ) { return; } if ( repairTask != $null ) { if ( !highCommand ) { return; } if ( !repairTask.isUserCreated() ) { return; } FreeRepairTask(); } float taskHandle = GetPlayerTask( getKey( "task_repair" ) ); if ( taskHandle != -1 ) { repairTask = taskManager.allocEntityTask( taskHandle, self ); if ( !highCommand ) { repairTask.setUserCreated(); } } } void vehicle_base::FreeRepairTask() { if ( repairTask != $null_entity ) { repairTask.free(); repairTask = $null_entity; } } void vehicle_base::InitNeedPassengerTask( entity p ) { if ( sys.isClient() ) { return; } if ( p == $null_entity ) { return; } float spots = getNumPositions(); float usedSpots = getNumOccupiedPositions(); if ( spots - usedSpots <= 0 ) { return; } if ( requestTask != $null ) { if ( !requestTask.isUserCreated() ) { return; } FreeRequestTask(); } float pickupTaskInfo; if ( getDriver() == $null_entity ) { pickupTaskInfo = GetPlayerTask( getKey( "task_need_pilot" ) ); } else if ( NeedGunner() ) { pickupTaskInfo = GetPlayerTask( getKey( "task_need_gunner" ) ); } else { pickupTaskInfo = GetPlayerTask( getKey( "task_need_passenger" ) ); } if ( pickupTaskInfo != -1 ) { requestTask = taskManager.allocEntityTask( pickupTaskInfo, self ); } } void vehicle_base::FreeRequestTask() { if ( requestTask != $null ) { requestTask.free(); requestTask = $null; } } void vehicle_base::OnSpotted( entity spotter ) { InitDestroyTask( false ); G_GiveSpottingProficiency( spotter ); } float vehicle_base::OnUpdateCrosshairInfo( entity p ) { if ( sys.getLocalPlayer() == $null_entity ) { return 1.f; } float allegiance = getEntityAllegiance( p ); vector color = GetAllegianceColor( allegiance ); float distance = chGetDistance(); float range = InchesToMetres( distance ); float minHealth = getMinDisplayHealth(); float maxHealth = getMaxHealth() - minHealth; float health = getHealth() - minHealth; chSetNumLines( 0 ); float index; // see if theres a valid action to perform float code = GetActivateCode( p, distance ); if ( code != AK_NONE && p.vHasActionItem( code ) ) { if ( code == AK_USEVEHICLE ) { if ( distance > maxEnterDistance ) { return 0.f; } } 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, crosshairName ); chSetLineColor( index, color, 1.f ); chSetLineType( index, CI_TEXT ); chSetLineSize( index, 0, 0 ); if( health <= 0 ) { index = chAddLine(); chSetLineTextIndex( index, g_locStr_Destroyed ); chSetLineColor( index, color, 1.f ); chSetLineType( index, CI_TEXT ); chSetLineSize( index, 0, 0 ); } else { if( isEMPed() ) { index = chAddLine(); sys.pushLocString( int( getRemainingEMP() ) ); chSetLineText( index, sys.localizeStringArgs( "game/disabled_info" ) ); chSetLineColor( index, color, 1.f ); chSetLineType( index, CI_TEXT ); chSetLineSize( index, 0, 0 ); } index = chAddLine(); chSetLineColor( index, color, 0.5f ); chSetLineType( index, CI_BAR ); chSetLineFraction( index, health / maxHealth ); chSetLineSize( index, healthBarLength, CROSSHAIR_INFO_BAR_HEIGHT ); if( range <= 100 ) { if( getNumOccupiedPositions() > 0 ) { index = chAddLine(); chSetLineText( index, getPassengerNames() ); chSetLineColor( index, color, 1.f ); chSetLineType( index, CI_TEXT ); chSetLineSize( index, 0, 0 ); } index = chAddLine(); chSetLineText( index, G_BuildRangeStr( range ) ); chSetLineColor( index, color, 1.f ); chSetLineType( index, CI_TEXT ); chSetLineSize( index, 0, 0 ); } } // show enter vehicle tooltip if ( p.isLocalPlayer()) { if ( distance <= 128.f ) { if ( allegiance == TA_FRIEND ) { if ( !p.isToolTipPlaying() ) { if ( sys.getTime() - lastTooltipTime > 5.f ) { if ( sys.getTime() - p.getCrosshairStartTime() > 1.f ) { p.sendToolTip( toolTipVehicle_enter ); lastTooltipTime = sys.getTime(); } } } } } } return 1.f; } void vehicle_base::OnUsed( entity user ) { entity team = user.getGameTeam(); if ( team == $null_entity ) { return; } if ( getHealth() <= 0 ) { if ( user == sys.getLocalViewPlayer() ) { user.sendToolTip( toolTipNoEntry ); } return; } if ( getEntityAllegiance( user ) != TA_ENEMY && user.getHealth() > 0 ) { if ( isPlayerBanned( user ) ) { float toolTipIndex = GetToolTip( getKey( "tt_player_banned" ) ); sys.broadcastToolTip( toolTipIndex, user, wstr_empty, wstr_empty, wstr_empty, wstr_empty ); return; } user.enter( self ); return; } } void vehicle_base::init() { thread DamageEffectThread(); } void vehicle_base::OnKilled( entity inflictor, entity attacker, float damage, vector dir, float location ) { NotifyBoundEntitiesOfDestruction(); OnKilledRemove( inflictor, attacker, damage, dir, location ); } void vehicle_base::OnKilledRemove( entity inflictor, entity attacker, float damage, vector dir, float location ) { CompleteDestroyTask(); kickPlayer( -1, EF_KILL_PLAYERS ); stopEffectHandle( damageEffectHandle ); stopEffectHandle( damageSmokeEffectHandle ); damageEffectHandle = 0; damageSmokeEffectHandle = 0; float water = isInWater(); if( water == 1.0f ) { playOriginEffect( "fx_destroy_submerged", "", getWorldOrigin() , '0 0 1', 0 ); } else if( water > 0.5f ) { playOriginEffect( "fx_destroy_water", "", getWorldOrigin() , '0 0 1', 0 ); } else { playOriginEffect( "fx_destroy", "", getWorldOrigin() , '0 0 1', 0 ); } destroyParts( 0 ); // the body would start falling here, so disable the model disableModel( 1 ); thread DestroyThread(); } void vehicle_base::OnPostDamage( entity attacker, float oldHealth, float newHealth ) { float maxHealth = getMaxHealth(); UpdateHealth( oldHealth / maxHealth, newHealth / maxHealth ); resetDecayTime(); } void vehicle_base::ShowDamageEffects( float oldHealth, float newHealth ) { float newDamageEffectLevel; // Figure out damage level if ( isInWater() < 0.5f && newHealth > 0.f ) { if ( newHealth > damageLevelSmoke ) { newDamageEffectLevel = 0; } else if( newHealth > damageLevel1 ) { newDamageEffectLevel = 1; } else if( newHealth > damageLevel2 ) { newDamageEffectLevel = 2; } else if( newHealth > damageLevel3 ) { newDamageEffectLevel = 3; } else { newDamageEffectLevel = 4; } } else { newDamageEffectLevel = 0; } // Apply if it changed if ( damageEffectLevel != newDamageEffectLevel ) { stopEffectHandle( damageEffectHandle ); damageEffectHandle = 0; if ( newDamageEffectLevel != 0 ) { if ( !damageSmokeEffectHandle ) { damageSmokeEffectHandle = playEffect( "fx_damage_level_smoke", jointEffectFire, 1 ); } } else { stopEffectHandle( damageSmokeEffectHandle ); damageSmokeEffectHandle = 0; } if ( newDamageEffectLevel == 2 ) { damageEffectHandle = playEffect( "fx_damage_level1", jointEffectFire, 1 ); } else if ( newDamageEffectLevel == 3 ) { damageEffectHandle = playEffect( "fx_damage_level2", jointEffectFire, 1 ); } else if ( newDamageEffectLevel == 4 ) { damageEffectHandle = playEffect( "fx_damage_level3", jointEffectFire, 1 ); } damageEffectLevel = newDamageEffectLevel; } // issue a repair task if damage was inflicted & we're below 30% if ( newHealth < oldHealth ) { if ( newHealth <= spiralHealthFrac ) { FreeRepairTask(); } else if ( newHealth <= repairThreshold ) { SetupRequestIcon( "mtr_cm_icon_need_repair", "require_view_repair" ); thread RequestIconThread( 5.f ); InitRepairTask( true ); } } if ( newHealth > oldHealth && newHealth >= 1.f ) { if ( repairTask != $null_entity ) { FreeRequestIcon(); CompleteRepairTask(); } } } void vehicle_base::DamageEffectThread( ) { float oldWaterLevel; while ( true ) { vector vel = getLinearVelocity(); float speed = sys.vecLength( vel ); if ( speed > 400 ) { speed = 400; } float attenuation = speed / 400; if ( damageEffectHandle ) { setEffectAttenuation( damageEffectHandle, attenuation ); } if ( damageSmokeEffectHandle ) { setEffectAttenuation( damageSmokeEffectHandle, attenuation ); } float newWaterLevel = isInWater(); if ( newWaterLevel != oldWaterLevel ) { float health = getHealth() / getMaxHealth(); ShowDamageEffects( health, health ); oldWaterLevel = newWaterLevel; } sys.wait( 0.25f ); } } float vehicle_base::vGetPliersProgressBarValue( float action ) { if ( action == AC_REPAIR ) { float minHealth = getMinDisplayHealth(); return ( getHealth() - minHealth ) / ( getMaxHealth() - minHealth ); } return 0.f; } void vehicle_base::vTargetLockAlarm( entity other ) { targetLockCount++; setLockAlarmActive( true ); } void vehicle_base::vStopTargetLockAlarm( entity other ) { targetLockCount--; if( targetLockCount <= 0 ) { targetLockCount = 0; setLockAlarmActive( false ); } } boolean vehicle_base::vCheckActionCode( entity p, float actionCode ) { if ( getEntityAllegiance( p ) == TA_ENEMY ) { if ( actionCode == AC_ENEMY_REPAIR ) { return true; } return false; } if ( actionCode == AC_REPAIR ) { if ( isInWater() < drownHeight ) { float health = getHealth(); return ( health >= getMinDisplayHealth() ) && ( ( health < getMaxHealth() ) || hasHiddenParts() ); } } return false; } void vehicle_base::vRepair( float count, entity other ) { count = count * repairMultiplier; player p = other; team_base team; if ( p != $null_entity ) { team = p.getGameTeam(); } if ( team != $null_entity ) { if ( team.HasConstructionBonus( p ) ) { count = count * 1.25f; } } float oldHealth = getHealth(); if ( repair( count ) < 0 ) { if ( other == sys.getLocalPlayer() ) { other.sendToolTip( toolTipCannotRepair ); } } float maxHealth = getMaxHealth(); float newHealth = getHealth(); float teamDamageCount = getTeamDamageDone(); float diff = newHealth - oldHealth; float repairCount = diff - teamDamageCount; if ( repairCount > 0 ) { if ( team != $null_entity ) { task_repair_vehicle t = requestTask; team.GiveRepairProficiency( p, t, repairCount ); } } setTeamDamageDone( teamDamageCount - diff ); UpdateHealth( oldHealth / maxHealth, newHealth / maxHealth ); resetDecayTime(); } vector vehicle_base::vGetLastRepairOrigin() { return getLastRepairOrigin(); } boolean vehicle_base::vCustomOrbitRadius() { return true; } float vehicle_base::vGetOrbitRadius() { if ( orbitRadius == 0 ) { vector size = getAbsMaxs() - getAbsMins(); orbitRadius = 0.7 * sys.sqrt( size_x * size_x + size_y * size_x ); } return orbitRadius; } boolean vehicle_base::vOrbitUnderneath() { return orbitUnderneath; } void vehicle_base::ApplyEmpDamage_Base( entity attacker, float time, float weaponTime ) { if ( applyEMPDamage( time, weaponTime ) ) { if ( disableProficiency != -1 ) { attacker.giveProficiency( disableProficiency, getDamageScale(), $null, "emp on vehicle" ); } } } void vehicle_base::vApplyEmpDamage( entity attacker, float time, float weaponTime ) { ApplyEmpDamage_Base( attacker, time, weaponTime ); } void vehicle_base::OnPlayerEntered( entity p, float position ) { OnPlayerEntered_Base( p, position ); } object vehicle_weapon_base; void vehicle_base::OnPlayerEntered_Base( entity p, float position ) { if ( p.isDisguised() ) { p.disguise( $null_entity ); } if ( p == sys.getLocalViewPlayer() ) { p.cancelToolTips(); sys.setGUIString( GUI_GLOBALS_HANDLE, "gameHud.weaponCrosshair", "none" ); sys.setGUIFloat( GUI_GLOBALS_HANDLE, "weapons.energySegments", 1 ); sys.setGUIHandle( GUI_GLOBALS_HANDLE, "vehicles.siegeMode", -1 ); sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.weaponReloadTime", 0 ); if ( position == 0 ) { if ( CalcDecoyChargeUsed() > 0 ) { StartDecoyChargeThread(); } else { sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.decoyChargeFraction", 1 ); } } float healthFrac = getHealth() / getMaxHealth(); if ( healthFrac < klaxonThreshold ) { sys.startSoundDirect( getKey( "snd_health_warn" ), SND_VEHICLE_INTERIOR_LOWHEALTH ); playingKlaxon = true; } } vCheckProficiency(); CheckFireTeamInfo( false ); } void vehicle_base::OnPlayerExited( entity p, float position ) { OnPlayerExited_Base( p, position ); } void vehicle_base::OnPlayerExited_Base( entity p, float position ) { if ( p == sys.getLocalViewPlayer() ) { p.cancelToolTips(); StopDecoyChargeThread(); sys.setGUIFloat( GUI_GLOBALS_HANDLE, "weapons.cooling", 0 ); sys.setGUIFloat( GUI_GLOBALS_HANDLE, "weapons.energySegments", 1 ); sys.startSoundDirect( "", SND_VEHICLE_INTERIOR_LOWHEALTH ); playingKlaxon = false; } vCheckProficiency(); if ( p == sys.getLocalPlayer() ) { CheckFireTeamInfo( true ); } else { CheckFireTeamInfo( false ); } } float vehicle_base::vGetTargetLockCount() { return targetLockCount; } void vehicle_base::DestroyThread() { sys.wait( destroyDelay ); // totally submerged vehicles don't explode float water = isInWater(); if( water < 1.0f ) { vector middle = ( getMins() + getMaxs() ) * 0.5f; middle = sys.toWorldSpace( middle, self ); sys.applyRadiusDamage( middle, self, self, $null_entity, self, GetDamage( "damage_vehicle_explode" ), 1.f, 1.f ); } if( !sys.isClient() ) { remove(); } } void vehicle_base::OnDecayed() { CompleteDestroyTask(); thread DecayThread(); } void vehicle_base::DecayThread() { stopEffectHandle( damageEffectHandle ); stopEffectHandle( damageSmokeEffectHandle ); damageEffectHandle = 0; damageSmokeEffectHandle = 0; float decayRandom = sys.random( 2 ); if( decayRandom >= 1 ) { decayLeftWheels(); } else { decayRightWheels(); } playEffect( "fx_decay", "", 0 ); sys.wait( 0.6 ); if( decayRandom >= 1 ) { decayRightWheels(); } else { decayLeftWheels(); } sys.wait( 0.6 ); decayNonWheels(); // the body would start falling here, so disable the model disableModel( 1 ); sys.wait( destroyDelay ); if( !sys.isClient() ) { remove(); } } void vehicle_base::UpdateHealth( float oldHealth, float newHealth ) { VehicleBase_UpdateHealth( oldHealth, newHealth ); } void vehicle_base::VehicleBase_UpdateHealth( float oldHealth, float newHealth ) { ShowDamageEffects( oldHealth, newHealth ); if ( newHealth < klaxonThreshold ) { if ( !playingKlaxon ) { player p = sys.getLocalPlayer(); if ( p != $null_entity ) { if ( p.getVehicle() == self ) { sys.startSoundDirect( getKey( "snd_health_warn" ), SND_VEHICLE_INTERIOR_LOWHEALTH ); playingKlaxon = true; } } } } else { if ( playingKlaxon ) { sys.startSoundDirect( "", SND_VEHICLE_INTERIOR_LOWHEALTH ); playingKlaxon = false; } } } void vehicle_base::FireDecoy( entity p ) { if ( getPositionPlayer( 0 ) != p ) { return; } vector xAxis = getWorldAxis( 0 ); vector yAxis = getWorldAxis( 1 ); vector zAxis = getWorldAxis( 2 ); vector localAxis; localAxis = decoyLaunchVelocity_x * xAxis; localAxis += decoyLaunchVelocity_y * yAxis; localAxis += decoyLaunchVelocity_z * zAxis; if ( sys.getTime() > nextDecoyTime ) { if ( DecoyHasCharge() ) { vector origin = getJointPos( decoyJointHandle ); entity projectileEntity = launchMissileSimple( p, self, $null_entity, decoyProjectileIndex, -1, 0, origin, localAxis ); if ( projectileEntity != $null_entity ) { projectileEntity.vSetOwner( self ); DecoyUseCharge(); } team_base team = p.getGameTeam(); if ( team != $null && team.HasEfficientDecoys( p ) ) { nextDecoyTime = sys.getTime() + decoyFireRate * FASTER_DECOY_SCALE; } else { nextDecoyTime = sys.getTime() + decoyFireRate; } OnDecoyLaunched(); } } } void vehicle_base::DecoyUseCharge() { decoyChargeTime = CalcDecoyChargeUsed() + sys.getTime() + decoyChargePerUse; } boolean vehicle_base::DecoyHasCharge() { return ( CalcDecoyChargeUsed() + decoyChargePerUse ) <= decoyChargeMax; } float vehicle_base::CalcDecoyChargeUsed() { float used = decoyChargeTime - sys.getTime(); if ( used < 0 ) { return 0; } return used; } void vehicle_base::StartDecoyChargeThread() { if ( decoyChargeThreadActive ) { return; } decoyChargeThreadActive = true; thread DecoyChargeThread(); } void vehicle_base::StopDecoyChargeThread() { if ( !decoyChargeThreadActive ) { return; } decoyChargeThreadActive = false; sys.killThread( "DecoyChargeThread_" + getName() ); } void vehicle_base::DecoyChargeThread() { while ( true ) { float used = CalcDecoyChargeUsed(); float frac = ( decoyChargeMax - used ) / decoyChargeMax; sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.decoyChargeFraction", frac ); if ( used == 0 ) { break; } sys.waitFrame(); } decoyChargeThreadActive = false; } boolean vehicle_base::NeedGunner() { float numWeapons = getNumVehicleWeapons(); float index = 0; for ( index = 0; index < numWeapons; index++ ) { vehicle_weapon_base weapon = getVehicleWeapon( index ); player user = weapon.getPlayer(); if ( user == $null_entity ) { return true; } } return false; } float vehicle_base::GetActivateCode( entity p, float distance ) { if ( p.getViewingEntity() != p ) { return AK_NONE; } if ( p.getHealth() <= 0 ) { return AK_NONE; } if ( p.getProxyEntity() != $null_entity ) { return AK_NONE; } float allegiance = getEntityAllegiance( p ); if ( allegiance == TA_FRIEND ) { if ( distance < DISTANCE_FOR_ACTION ) { if ( isInWater() < drownHeight ) { float health = getHealth(); if ( health >= getMinDisplayHealth() && ( ( health < getMaxHealth() ) || hasHiddenParts() ) ) { if ( p.vHasActionItem( AK_REPAIR ) ) { return AK_REPAIR; } } } } if ( distance < maxEnterDistance ) { float spots = getNumPositions(); float usedSpots = getNumOccupiedPositions(); if ( spots - usedSpots > 0 ) { return AK_USEVEHICLE; } } } return AK_NONE; } float vehicle_base::VehicleBase_OnActivate( entity p, float distance ) { if ( p.getVehicle() == self ) { swapPosition( p ); return 1.f; } if ( distance < DISTANCE_FOR_ACTION ) { if ( p.vSelectActionItem( GetActivateCode( p, distance ) ) ) { return 1.f; } } return 0.f; } float vehicle_base::OnActivate( entity p, float distance ) { return VehicleBase_OnActivate( p, distance ); } void vehicle_base::OnSetTeam( object oldTeam, object newTeam ) { InitRadarValues(); } void vehicle_base::vSetDeployer( entity other ) { deployer = other; } void vehicle_base::CheckArmor() { team_base team = getGameTeam(); float index; for ( index = 0; index < getNumPositions(); index++ ) { entity p = getPositionPlayer( index ); if ( p == $null_entity ) { continue; } if ( team.HasVehicleArmorBonus( p ) ) { SetArmorBonus( true ); return; } } SetArmorBonus( false ); } void vehicle_base::vCheckProficiency() { CheckArmor(); decoyChargePerUse = baseDecoyChargePerUse; entity driver = getDriver(); if ( driver != $null_entity ) { team_base team = driver.getGameTeam(); if ( team != $null ) { if ( team.HasEfficientDecoys( driver ) ) { decoyChargePerUse = decoyChargePerUse * FASTER_DECOY_SCALE; } } } float count = getNumVehicleWeapons(); float index; for ( index = 0; index < count; index++ ) { object weapon = getVehicleWeapon( index ); weapon.vCheckProficiency(); } } void vehicle_base::SetArmorBonus( boolean value ) { if ( hasArmorBonus == value ) { return; } hasArmorBonus = value; if ( hasArmorBonus ) { setArmor( getArmor() + 0.1f ); } else { setArmor( getArmor() - 0.1f ); } } boolean vehicle_base::vSkipDeployDrop() { return true; } void vehicle_base::OnTeleportEntityChanged( entity other ) { if ( !sys.isClient() ) { entitiesOfCollection( "decoy_target" ); float count = getBoundsCacheCount(); entity target; float i; for( i = 0; i < count; i++ ) { target = getBoundsCacheEntity( i ); if ( target.vGetCurrentTarget() != self ) { continue; } target.vSetNewTarget( $null_entity ); } } // force a physics update so player origin is correct while teleporting if ( other != $null_entity ) { forceRunPhysics(); } player p = sys.getLocalPlayer(); if ( p != $null_entity ) { if ( p.getProxyEntity() == self ) { float flags; if ( other != $null_entity ) { flags = sys.getGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.activeCrosshairInfoFlags" ); flags = flags & ~( CF_TASKS | CF_OBJ_MIS ); sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.activeCrosshairInfoFlags", flags ); } else { flags = sys.getGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.activeCrosshairInfoFlags" ); flags = flags | CF_TASKS | CF_OBJ_MIS; sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.activeCrosshairInfoFlags", flags ); } } } } void vehicle_base::vOnContextRepair( entity p ) { SetupRequestIcon( "mtr_cm_icon_need_repair", "require_view_repair" ); thread RequestIconThread( 5.f ); InitRepairTask( false ); } void vehicle_base::vOnContextKill( entity p ) { if ( destroyTask == $null ) { InitDestroyTask( false ); killTaskRequestee = p; } FlashCMIcon( p, TA_ENEMY ); } void vehicle_base::vOnContextNeedPassenger( entity p ) { InitNeedPassengerTask( p ); FlashCMIcon( p, TA_FRIEND ); } void vehicle_base::vOnRemovePlayersKillTask( player p ) { if ( p == killTaskRequestee ) { FreeDestroyTask(); } } void vehicle_base::OnRouteKickPlayer() { entity driver = getDriver(); if ( driver != $null_entity ) { float toolTipIndex = GetToolTip( getKey( "tt_player_kicked" ) ); sys.broadcastToolTip( toolTipIndex, driver, wstr_empty, wstr_empty, wstr_empty, wstr_empty ); kickPlayer( 0, 0 ); banPlayer( driver, 30.f ); } } void vehicle_base::CheckFireTeamInfo( boolean localExiting ) { player localPlayer = sys.getLocalPlayer(); if ( localPlayer == $null_entity ) { return; } boolean showMapFireTeamInfo = false; float index; for ( index = 0; index < getNumPositions(); index++ ) { player other = getPositionPlayer( index ); if ( other == $null_entity ) { continue; } if ( other == localPlayer ) { continue; } if ( other.sameFireTeam( localPlayer ) ) { showMapFireTeamInfo = true; break; } } if ( localExiting || localPlayer.getVehicle() != self ) { if ( showMapFireTeamInfo ) { if ( commandMapFireTeamInfo != -1 ) { sys.showCMIcon( commandMapFireTeamInfo ); return; } } } if ( commandMapFireTeamInfo != -1 ) { sys.hideCMIcon( commandMapFireTeamInfo ); } } string vehicle_base::vGetQuickChatString( entity p ) { if ( getEntityAllegiance( p ) == TA_ENEMY ) { return getKey( "qc_spotted" ); } return ""; } void vehicle_base::FlashCMIcon( entity p, float requiredTeam ) { entity local = sys.getLocalViewPlayer(); if ( local == $null_entity ) { return; } if ( getEntityAllegiance( local ) == requiredTeam ) { if ( requiredTeam == TA_ENEMY ) { float flags = sys.getCMIconFlags( commandMapHandle ); flags = flags | CMF_ENEMYALWAYSKNOWN; sys.flashCMIcon( commandMapHandle, -1, SPOTTED_FLASH_TIME, flags ); } else { sys.flashCMIcon( commandMapHandle, -1, SPOTTED_FLASH_TIME, -1 ); } } } void vehicle_base::OnCollision_Base( object traceObject, float velocity, vector mins, vector maxs ) { if( sys.getTime() < nextCollisionEffectTime ) { return; } velocity = UPStoKPH( velocity ); string surfaceType = traceObject.getTraceSurfaceType(); if ( surfaceType == "" ) { entity other = traceObject.getTraceEntity(); if ( other != $null_entity ) { surfaceType = other.getDefaultSurfaceType(); } } string severity; if( velocity < 15 ) { return; } else if( velocity < 30 ) { severity = "light"; } else if( velocity < 60 ) { severity = "medium"; } else { severity = "heavy"; } vector point = traceObject.getTracePoint(); playOriginEffect( "fx_crash_" + severity, surfaceType, point, '0 0 1', 0 ); nextCollisionEffectTime = sys.getTime() + 2.f; } void vehicle_base::vOnEndGame() { if ( !sys.isClient() ) { remove(); } }