aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaya <11448698+RoyalBlue1@users.noreply.github.com>2023-01-13 17:20:12 +0100
committerGitHub <noreply@github.com>2023-01-13 17:20:12 +0100
commit9bbe6832460aaabd96fef18d6e4ebb05779bb71d (patch)
tree196b38f2f90e1b004776977155413f885d8c1586
parent3b2049a933b0831e65283b89c0ecca865ebe985c (diff)
downloadNorthstarMods-9bbe6832460aaabd96fef18d6e4ebb05779bb71d.tar.gz
NorthstarMods-9bbe6832460aaabd96fef18d6e4ebb05779bb71d.zip
Fortwar fixes from #564 with my requested changes (#571)v1.12.1-rc1v1.12.1v1.12.0-rc5v1.12.0
* Initial commit * add playlistvar "fw_harvester_regen_time" * adding friendly highlights * Scale Damage before shield Health but let other damage callbacks run * Make Gamemode 8v8 again * Fix NotifyEnterEnemyArea Callback Co-authored-by: DBmaoha <56738369+DBmaoha@users.noreply.github.com>
-rw-r--r--Northstar.Custom/mod.json12
-rw-r--r--Northstar.Custom/mod/resource/northstar_custom_english.txtbin5110 -> 6318 bytes
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fw.nut301
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fw_custom.nut13
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut10
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut15
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut27
7 files changed, 239 insertions, 139 deletions
diff --git a/Northstar.Custom/mod.json b/Northstar.Custom/mod.json
index 1952f72ac..e81b197f2 100644
--- a/Northstar.Custom/mod.json
+++ b/Northstar.Custom/mod.json
@@ -96,6 +96,10 @@
"RunOn": "SERVER && MP"
},
{
+ "Path": "gamemodes/_gamemode_fw.nut",
+ "RunOn": "SERVER && MP"
+ },
+ {
"Path": "gamemodes/sh_gamemode_fw_custom.nut",
"RunOn": "( CLIENT || SERVER ) && MP",
"ClientCallback": {
@@ -110,6 +114,10 @@
"RunOn": "( CLIENT || SERVER ) && MP"
},
{
+ "Path": "gamemodes/cl_gamemode_fw_custom.nut",
+ "RunOn": "CLIENT && MP"
+ },
+ {
"Path": "gamemodes/cl_gamemode_fw.nut",
"RunOn": "CLIENT && MP"
},
@@ -419,10 +427,6 @@
}
},
{
- "Path": "gamemodes/_gamemode_fw.nut",
- "RunOn": "SERVER && MP"
- },
- {
"Path": "sh_northstar_http_requests.gnut",
"RunOn": "CLIENT || SERVER || UI"
}
diff --git a/Northstar.Custom/mod/resource/northstar_custom_english.txt b/Northstar.Custom/mod/resource/northstar_custom_english.txt
index 794aa6649..04a8d0097 100644
--- a/Northstar.Custom/mod/resource/northstar_custom_english.txt
+++ b/Northstar.Custom/mod/resource/northstar_custom_english.txt
Binary files differ
diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fw.nut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fw.nut
index 89ca06360..7a5b0ee5f 100644
--- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fw.nut
+++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fw.nut
@@ -1,6 +1,10 @@
untyped
global function GamemodeFW_Init
-global function RateSpawnpoints_FW
+
+// spawn points
+global function RateSpawnpointsPilot_FW
+global function RateSpawnpointsTitan_FW
+//global function RateSpawnpoints_FW
// for battery_port.gnut to work
global function FW_ReplaceMegaTurret
@@ -96,7 +100,8 @@ struct
// this is for saving territory's connecting time, try not to make faction dialogues play together
table< int, float > teamTerrLastConnectTime // team, time
-
+
+ // unused
array<entity> etitaninmlt
array<entity> etitaninimc
@@ -120,17 +125,18 @@ void function GamemodeFW_Init()
AddCallback_GameStateEnter( eGameState.Playing, OnFWGamePlaying )
AddSpawnCallback( "item_powerup", FWAddPowerUpIcon )
- // check spawn point, WIP
- AddSpawnCallback( "npc_titan", FWForcedTitanSpawnPoint )
+ AddSpawnCallback( "npc_turret_mega", FWTurretHighlight )
AddCallback_OnClientConnected( OnFWPlayerConnected )
+ AddCallback_PlayerClassChanged( OnFWPlayerClassChanged )
AddCallback_OnPlayerKilled( OnFWPlayerKilled )
AddCallback_OnPilotBecomesTitan( OnFWPilotBecomesTitan )
AddCallback_OnTitanBecomesPilot( OnFWTitanBecomesPilot )
ScoreEvent_SetupEarnMeterValuesForMixedModes()
- SetRecalculateTitanReplacementPointCallback(FW_ReCalculateTitanReplacementPoint)
- SetRequestTitanAllowedCallback(FW_RequestTitanAllowed)
+ SetRecalculateRespawnAsTitanStartPointCallback( FW_ForcedTitanStartPoint )
+ SetRecalculateTitanReplacementPointCallback( FW_ReCalculateTitanReplacementPoint )
+ SetRequestTitanAllowedCallback( FW_RequestTitanAllowed )
}
@@ -222,16 +228,25 @@ void function HACK_ForceDestroyNPCs_Threaded()
///// SPAWNPOINT FUNCTIONS /////
////////////////////////////////
-void function RateSpawnpoints_FW( int checkClass, array<entity> spawnpoints, int team, entity player )
+void function RateSpawnpointsPilot_FW( int checkClass, array<entity> spawnpoints, int team, entity player )
+{
+ array<entity> startSpawns = SpawnPoints_GetPilotStart( team )
+ RateSpawnpoints_FW( startSpawns, checkClass, spawnpoints, team, player )
+}
+
+void function RateSpawnpointsTitan_FW( int checkClass, array<entity> spawnpoints, int team, entity player )
+{
+ array<entity> startSpawns = SpawnPoints_GetTitanStart( team )
+ RateSpawnpoints_FW( startSpawns, checkClass, spawnpoints, team, player )
+}
+
+void function RateSpawnpoints_FW( array<entity> startSpawns, int checkClass, array<entity> spawnpoints, int team, entity player )
{
if ( HasSwitchedSides() )
team = GetOtherTeam( team )
- // check hardpoints, determine which ones we own
- array<entity> startSpawns = SpawnPoints_GetPilotStart( team )
- vector averageFriendlySpawns
-
// average out startspawn positions
+ vector averageFriendlySpawns
foreach ( entity spawnpoint in startSpawns )
averageFriendlySpawns += spawnpoint.GetOrigin()
@@ -295,6 +310,12 @@ void function OnFWPlayerConnected( entity player )
InitFWPlayers( player )
}
+void function OnFWPlayerClassChanged( entity player )
+{
+ // give player a friendly highlight
+ Highlight_SetFriendlyHighlight( player, "fw_friendly" )
+}
+
void function OnFWPlayerKilled( entity victim, entity attacker, var damageInfo )
{
HandleFWPlayerKilledScoreEvent( victim, attacker )
@@ -562,6 +583,7 @@ void function LoadEntities()
entity turret = CreateNPC( "npc_turret_mega", TEAM_UNASSIGNED, info_target.GetOrigin(), info_target.GetAngles() )
SetSpawnOption_AISettings( turret, "npc_turret_mega_fortwar" )
SetDefaultMPEnemyHighlight( turret ) // for sonar highlights to work
+ Highlight_SetFriendlyHighlight( turret, "fw_friendly" )
AddEntityCallback_OnDamaged( turret, OnMegaTurretDamaged )
DispatchSpawn( turret )
@@ -1144,16 +1166,19 @@ bool function FW_IsPlayerInEnemyTerritory( entity player )
////////////////////////////////
// territory trigger don't have a kv.radius, let's use a const
-// 1800 will pretty much get harvester's near titan startpoints
-const float FW_SPAWNPOINT_SEARCH_RADIUS = 1800.0
+// 2800 will pretty much get harvester's near titan startpoints
+const float FW_SPAWNPOINT_SEARCH_RADIUS = 2800.0
-Point function FW_ReCalculateTitanReplacementPoint( Point basePoint, entity player)
+Point function FW_ReCalculateTitanReplacementPoint( Point basePoint, entity player )
{
int team = player.GetTeam()
// find team's harvester
entity teamHarvester = FW_GetTeamHarvesterProp( team )
+ if ( !IsValid( teamHarvester ) ) // team's havester has been destroyed!
+ return basePoint // return given value
+
if( Distance2D( basePoint.origin, teamHarvester.GetOrigin() ) <= FW_SPAWNPOINT_SEARCH_RADIUS ) // close enough!
return basePoint // this origin is good enough
@@ -1171,13 +1196,26 @@ bool function FW_RequestTitanAllowed( entity player, array< string > args )
PlayFactionDialogueToPlayer( "tw_territoryNag", player ) // notify player
TryPlayTitanfallNegativeSoundToPlayer( player )
int objectiveID = 101 // which means "#FW_OBJECTIVE_TITANFALL"
- //CreateCustomMessageForRefusingTitanfall( player )
Remote_CallFunction_NonReplay( player, "ServerCallback_FW_SetObjective", objectiveID )
return false
}
return true
}
+bool function TryPlayTitanfallNegativeSoundToPlayer( entity player )
+{
+ if( !( "lastNegativeSound" in player.s ) )
+ player.s.lastNegativeSound <- 0.0 // float
+ if( player.s.lastNegativeSound + 1.0 > Time() ) // in sound cooldown
+ return false
+
+ // use a sound to notify player they can't titanfall here
+ EmitSoundOnEntityOnlyToPlayer( player, player, "titan_dryfire" )
+ player.s.lastNegativeSound = Time()
+
+ return true
+}
+
array<entity> function FW_GetTitanSpawnPointsForTeam( int team )
{
array<entity> validSpawnPoints
@@ -1200,10 +1238,13 @@ array<entity> function FW_GetTitanSpawnPointsForTeam( int team )
return validSpawnPoints
}
-// WORKING IN PROGRESS
-void function FWForcedTitanSpawnPoint( entity titan )
+// "Respawn as Titan" don't follow the rateSpawnPoints, fix it manually
+entity function FW_ForcedTitanStartPoint( entity player, entity basePoint )
{
-
+ int team = player.GetTeam()
+ array<entity> startPoints = SpawnPoints_GetTitanStart( team )
+ entity validPoint = startPoints[ RandomInt( startPoints.len() ) ] // choose a random( maybe not safe ) start point
+ return validPoint
}
////////////////////////////////////
@@ -1343,6 +1384,21 @@ void function FWAreaThreatLevelThink_Threaded()
///// TURRET FUNCTIONS /////
////////////////////////////
+void function FWTurretHighlight( entity turret )
+{
+ thread FWTurretHighlightThink( turret )
+}
+
+// this will clear turret's highlight upon their death, for notifying players to fix them
+void function FWTurretHighlightThink( entity turret )
+{
+ turret.EndSignal( "OnDestroy" )
+ Highlight_SetFriendlyHighlight( turret, "fw_friendly" )
+
+ turret.WaitSignal( "OnDeath" )
+ Highlight_ClearFriendlyHighlight( turret )
+}
+
// for battery_port, replace the turret with new one
entity function FW_ReplaceMegaTurret( entity perviousTurret )
{
@@ -1673,7 +1729,7 @@ entity function FW_GetTeamHarvesterProp( int team )
void function FW_createHarvester()
{
- // mlt havester spawn
+ // imc havester spawn
fw_harvesterImc = SpawnHarvester( file.harvesterImc_info.GetOrigin(), file.harvesterImc_info.GetAngles(), GetCurrentPlaylistVarInt( "fw_harvester_health", FW_DEFAULT_HARVESTER_HEALTH ), GetCurrentPlaylistVarInt( "fw_harvester_shield", FW_DEFAULT_HARVESTER_SHIELD ), TEAM_IMC )
fw_harvesterImc.harvester.Minimap_SetAlignUpright( true )
fw_harvesterImc.harvester.Minimap_AlwaysShow( TEAM_IMC, null )
@@ -1683,6 +1739,7 @@ void function FW_createHarvester()
fw_harvesterImc.harvester.Minimap_SetCustomState( eMinimapObject_prop_script.FD_HARVESTER )
AddEntityCallback_OnDamaged( fw_harvesterImc.harvester, OnHarvesterDamaged )
AddEntityCallback_OnPostDamaged( fw_harvesterImc.harvester, OnHarvesterPostDamaged )
+
// imc havester settings
// don't set this, or sonar pulse will try to find it and failed to set highlight
//fw_harvesterMlt.harvester.SetScriptName("fw_team_tower")
@@ -1721,6 +1778,8 @@ void function FW_createHarvester()
GameRules_SetTeamScore( TEAM_IMC , 100 )
GameRules_SetTeamScore2( TEAM_IMC , 100 )
}
+
+// this function can't handle specific damageSourceID, such as plasma railgun, but is the best to scale both shield and health damage
void function OnHarvesterDamaged( entity harvester, var damageInfo )
{
if ( !IsValid( harvester ) )
@@ -1728,7 +1787,8 @@ void function OnHarvesterDamaged( entity harvester, var damageInfo )
int friendlyTeam = harvester.GetTeam()
int enemyTeam = GetOtherTeam( friendlyTeam )
-
+ int damageSourceID = DamageInfo_GetDamageSourceIdentifier( damageInfo )
+
HarvesterStruct harvesterstruct // current harveter's struct
if( friendlyTeam == TEAM_MILITIA )
harvesterstruct = fw_harvesterMlt
@@ -1748,53 +1808,45 @@ void function OnHarvesterDamaged( entity harvester, var damageInfo )
// always reset harvester's recharge delay
harvesterstruct.lastDamage = Time()
-}
-void function OnHarvesterPostDamaged( entity harvester, var damageInfo )
-{
- if ( !IsValid( harvester ) )
- return
-
- int friendlyTeam = harvester.GetTeam()
- int enemyTeam = GetOtherTeam( friendlyTeam )
-
- GameRules_SetTeamScore( friendlyTeam , 1.0 * GetHealthFrac( harvester ) * 100 )
-
- int damageSourceID = DamageInfo_GetDamageSourceIdentifier( damageInfo )
- entity attacker = DamageInfo_GetAttacker( damageInfo )
- float damageAmount = DamageInfo_GetDamage( damageInfo )
- if(damageAmount == 0)
- return
- printt("Harvester damage", damageAmount,attacker, damageSourceID)
- if ( !damageSourceID && !damageAmount && !attacker ) // actually not dealing any damage?
- return
+
// done damage adjustments here, since harvester prop's health is setting manually through damageAmount
if ( damageSourceID == eDamageSourceId.mp_titancore_laser_cannon )
DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 50 ) // laser core shreds super well for some reason
- // plasma railgun can always do no-charge shots and deal same damage
- if ( damageSourceID == eDamageSourceId.mp_titanweapon_sniper ) // nerf northstar
+ // plasma railgun can always do no-charge shots and deal same damage
+ if ( damageSourceID == eDamageSourceId.mp_titanweapon_sniper ) // nerf northstar
+ {
DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 3 )
+ entity inflictor = DamageInfo_GetInflictor( damageInfo )
+ if( IsValid( inflictor ) && inflictor.IsProjectile() )
+ {
+ inflictor.s.extraDamagePerBullet = expect int( inflictor.s.extraDamagePerBullet ) / 3
+ }
+ }
- // leadwall have high pilot damage so works really well aginst harvester
- if ( damageSourceID == eDamageSourceId.mp_titanweapon_leadwall ) // nerf ronin
- DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 2 )
+ // leadwall have high pilot damage so works really well aginst harvester
+ if ( damageSourceID == eDamageSourceId.mp_titanweapon_leadwall ) // nerf ronin
+ DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 2 )
- // missiles mostly have high pilot damage so works really well aginst harvester
+ // missiles mostly have high pilot damage so works really well aginst harvester
if ( damageSourceID == eDamageSourceId.mp_titanweapon_salvo_rockets ||
damageSourceID == eDamageSourceId.mp_titanweapon_shoulder_rockets ||
- damageSourceID == eDamageSourceId.mp_titancore_salvo_core
+ damageSourceID == eDamageSourceId.mp_titancore_salvo_core
) // titan missiles
DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 3 )
- if ( damageSourceID == eDamageSourceId.mp_titanweapon_flightcore_rockets ) // flight core shreds well
- DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 5 )
+ if ( damageSourceID == eDamageSourceId.mp_titanweapon_sticky_40mm ) // 40mm trakcer cannon
+ DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 2 )
+
+ if ( damageSourceID == eDamageSourceId.mp_titanweapon_flightcore_rockets ) // flight core shreds well
+ DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 5 )
- // cluster missle is very effective against non-moving targets
- if ( damageSourceID == eDamageSourceId.mp_titanweapon_dumbfire_rockets ) // cluster missile shreds super well
- DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 10 )
+ // cluster missle is very effective against non-moving targets
+ if ( damageSourceID == eDamageSourceId.mp_titanweapon_dumbfire_rockets ) // cluster missile shreds super well
+ DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 10 )
- // scorch's thermites is very effective against non-moving targets
+ // scorch's thermites is very effective against non-moving targets
if ( damageSourceID == eDamageSourceId.mp_titanweapon_heat_shield ||
damageSourceID == eDamageSourceId.mp_titanweapon_meteor_thermite ||
damageSourceID == eDamageSourceId.mp_titanweapon_flame_wall ||
@@ -1803,12 +1855,44 @@ void function OnHarvesterPostDamaged( entity harvester, var damageInfo )
) // scorch's thermite damages, nerf scorch
DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 5 )
+}
+void function OnHarvesterPostDamaged( entity harvester, var damageInfo )
+{
+ if ( !IsValid( harvester ) )
+ return
+
+ int friendlyTeam = harvester.GetTeam()
+ int enemyTeam = GetOtherTeam( friendlyTeam )
+
+ GameRules_SetTeamScore( friendlyTeam , 1.0 * GetHealthFrac( harvester ) * 100 )
+
+ int damageSourceID = DamageInfo_GetDamageSourceIdentifier( damageInfo )
+ entity attacker = DamageInfo_GetAttacker( damageInfo )
+ int scriptType = DamageInfo_GetCustomDamageType( damageInfo )
+ float damageAmount = DamageInfo_GetDamage( damageInfo )
+
+ if(damageAmount == 0)
+ return
+
+ if ( !damageSourceID && !damageAmount && !attacker ) // actually not dealing any damage?
+ return
+
+ // prevent player from sniping the harvester cross-map
+ if ( attacker.IsPlayer() && !FW_IsPlayerInEnemyTerritory( attacker ) )
+ {
+ Remote_CallFunction_NonReplay( attacker , "ServerCallback_FW_NotifyNeedsEnterEnemyArea" )
+ DamageInfo_SetDamage( damageInfo, 0 )
+ DamageInfo_SetCustomDamageType( damageInfo, scriptType | DF_NO_INDICATOR ) // hide the hitmarker
+ return // these damage won't do anything to the harvester
+ }
+
HarvesterStruct harvesterstruct // current harveter's struct
if( friendlyTeam == TEAM_MILITIA )
harvesterstruct = fw_harvesterMlt
if( friendlyTeam == TEAM_IMC )
harvesterstruct = fw_harvesterImc
+
damageAmount = DamageInfo_GetDamage( damageInfo ) // get damageAmount again after all damage adjustments
if ( !attacker.IsTitan() )
@@ -1819,12 +1903,18 @@ void function OnHarvesterPostDamaged( entity harvester, var damageInfo )
damageAmount = 0 // never damage haveter's prop
}
+ if( !harvesterstruct.harvesterShieldDown )
+ {
+ PlayFactionDialogueToTeam( "fortwar_baseShieldDownFriendly", friendlyTeam )
+ PlayFactionDialogueToTeam( "fortwar_baseShieldDownEnemy", enemyTeam )
+ harvesterstruct.harvesterShieldDown = true // prevent shield dialogues from repeating
+ }
+
harvesterstruct.harvesterDamageTaken = harvesterstruct.harvesterDamageTaken + damageAmount // track damage for wave recaps
float newHealth = harvester.GetHealth() - damageAmount
float oldhealthpercent = ( ( harvester.GetHealth().tofloat() / harvester.GetMaxHealth() ) * 100 )
-
float healthpercent = ( ( newHealth / harvester.GetMaxHealth() ) * 100 )
-
+
if (healthpercent <= 75 && oldhealthpercent > 75) // we don't want the dialogue to keep saying "Harvester is below 75% health" everytime they take additional damage
{
PlayFactionDialogueToTeam( "fortwar_baseDmgFriendly75", friendlyTeam )
@@ -1854,48 +1944,48 @@ void function OnHarvesterPostDamaged( entity harvester, var damageInfo )
harvester.SetHealth( newHealth )
harvesterstruct.havesterWasDamaged = true
-
if ( attacker.IsPlayer() )
{
- // dialogue for enemy attackers
- if( !harvesterstruct.harvesterShieldDown )
- PlayFactionDialogueToTeam( "fortwar_baseEnemyAllyAttacking", enemyTeam )
+ // dialogue for enemy attackers
+ if( !harvesterstruct.harvesterShieldDown )
+ PlayFactionDialogueToTeam( "fortwar_baseEnemyAllyAttacking", enemyTeam )
attacker.NotifyDidDamage( harvester, DamageInfo_GetHitBox( damageInfo ), DamageInfo_GetDamagePosition( damageInfo ), DamageInfo_GetCustomDamageType( damageInfo ), DamageInfo_GetDamage( damageInfo ), DamageInfo_GetDamageFlags( damageInfo ), DamageInfo_GetHitGroup( damageInfo ), DamageInfo_GetWeapon( damageInfo ), DamageInfo_GetDistFromAttackOrigin( damageInfo ) )
- // get newest damage for adding score!
- int scoreDamage = int( DamageInfo_GetDamage( damageInfo ) )
- // score events
- attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, scoreDamage )
-
- // add to player structs
- file.playerDamageHarvester[ attacker ].recentDamageTime = Time()
- file.playerDamageHarvester[ attacker ].storedDamage += scoreDamage
-
- // enough to earn score?
- if( file.playerDamageHarvester[ attacker ].storedDamage >= FW_HARVESTER_DAMAGE_SEGMENT )
- {
- AddPlayerScore( attacker, "FortWarTowerDamage", attacker )
- attacker.AddToPlayerGameStat( PGS_DEFENSE_SCORE, POINTVALUE_FW_TOWER_DAMAGE )
- file.playerDamageHarvester[ attacker ].storedDamage -= FW_HARVESTER_DAMAGE_SEGMENT // reset stored damage
- }
+ // get newest damage for adding score!
+ int scoreDamage = int( DamageInfo_GetDamage( damageInfo ) )
+ // score events
+ attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, scoreDamage )
+
+ // add to player structs
+ file.playerDamageHarvester[ attacker ].recentDamageTime = Time()
+ file.playerDamageHarvester[ attacker ].storedDamage += scoreDamage
+
+ // enough to earn score?
+ if( file.playerDamageHarvester[ attacker ].storedDamage >= FW_HARVESTER_DAMAGE_SEGMENT )
+ {
+ AddPlayerScore( attacker, "FortWarTowerDamage", attacker )
+ attacker.AddToPlayerGameStat( PGS_DEFENSE_SCORE, POINTVALUE_FW_TOWER_DAMAGE )
+ file.playerDamageHarvester[ attacker ].storedDamage -= FW_HARVESTER_DAMAGE_SEGMENT // reset stored damage
+ }
}
-
- if ( harvester.GetHealth() == 0 )
- {
- SetWinner( enemyTeam )
- //PlayFactionDialogueToTeam( "scoring_wonMercy", enemyTeam )
- //PlayFactionDialogueToTeam( "fortwar_matchLoss", friendlyTeam )
- GameRules_SetTeamScore2( friendlyTeam, 0 ) // force set score2 to 0( shield bar will empty )
- GameRules_SetTeamScore( friendlyTeam, 0 ) // force set score to 0( health 0% )
- }
+ // harvester down!
+ if ( harvester.GetHealth() == 0 )
+ {
+ // force deciding winner
+ SetWinner( enemyTeam )
+ //PlayFactionDialogueToTeam( "scoring_wonMercy", enemyTeam )
+ //PlayFactionDialogueToTeam( "fortwar_matchLoss", friendlyTeam )
+ GameRules_SetTeamScore2( friendlyTeam, 0 ) // force set score2 to 0( shield bar will empty )
+ GameRules_SetTeamScore( friendlyTeam, 0 ) // force set score to 0( health 0% )
+ }
}
-void function HarvesterThink( HarvesterStruct fd_harvester )
+void function HarvesterThink( HarvesterStruct fw_harvester )
{
- entity harvester = fd_harvester.harvester
+ entity harvester = fw_harvester.harvester
EmitSoundOnEntity( harvester, "coop_generator_startup" )
@@ -1903,8 +1993,8 @@ void function HarvesterThink( HarvesterStruct fd_harvester )
float lastTime = Time()
wait 4
int lastShieldHealth = harvester.GetShieldHealth()
- generateBeamFX( fd_harvester )
- generateShieldFX( fd_harvester )
+ generateBeamFX( fw_harvester )
+ generateShieldFX( fw_harvester )
EmitSoundOnEntity( harvester, "coop_generator_ambient_healthy" )
@@ -1915,26 +2005,26 @@ void function HarvesterThink( HarvesterStruct fd_harvester )
float currentTime = Time()
float deltaTime = currentTime -lastTime
- if ( IsValid( fd_harvester.particleShield ) )
+ if ( IsValid( fw_harvester.particleShield ) )
{
vector shieldColor = GetShieldTriLerpColor( 1.0 - ( harvester.GetShieldHealth().tofloat() / harvester.GetShieldHealthMax().tofloat() ) )
- EffectSetControlPointVector( fd_harvester.particleShield, 1, shieldColor )
+ EffectSetControlPointVector( fw_harvester.particleShield, 1, shieldColor )
}
- if( IsValid( fd_harvester.particleBeam ) )
+ if( IsValid( fw_harvester.particleBeam ) )
{
vector beamColor = GetShieldTriLerpColor( 1.0 - ( harvester.GetHealth().tofloat() / harvester.GetMaxHealth().tofloat() ) )
- EffectSetControlPointVector( fd_harvester.particleBeam, 1, beamColor )
+ EffectSetControlPointVector( fw_harvester.particleBeam, 1, beamColor )
}
- if ( fd_harvester.harvester.GetShieldHealth() == 0 )
- if( IsValid( fd_harvester.particleShield ) )
- fd_harvester.particleShield.Destroy()
+ if ( fw_harvester.harvester.GetShieldHealth() == 0 )
+ if( IsValid( fw_harvester.particleShield ) )
+ fw_harvester.particleShield.Destroy()
- if ( ( ( currentTime-fd_harvester.lastDamage ) >= GENERATOR_SHIELD_REGEN_DELAY ) && ( harvester.GetShieldHealth() < harvester.GetShieldHealthMax() ) )
+ if ( ( ( currentTime-fw_harvester.lastDamage ) >= GetCurrentPlaylistVarFloat( "fw_harvester_regen_delay", FW_DEFAULT_HARVESTER_REGEN_DELAY ) ) && ( harvester.GetShieldHealth() < harvester.GetShieldHealthMax() ) )
{
- if( !IsValid( fd_harvester.particleShield ) )
- generateShieldFX( fd_harvester )
+ if( !IsValid( fw_harvester.particleShield ) )
+ generateShieldFX( fw_harvester )
if( harvester.GetShieldHealth() == 0 )
EmitSoundOnEntity( harvester, "coop_generator_shieldrecharge_start" )
@@ -1942,15 +2032,16 @@ void function HarvesterThink( HarvesterStruct fd_harvester )
if (!isRegening)
{
EmitSoundOnEntity( harvester, "coop_generator_shieldrecharge_resume" )
- fd_harvester.harvesterShieldDown = false
+ fw_harvester.harvesterShieldDown = false
isRegening = true
}
- float newShieldHealth = ( harvester.GetShieldHealthMax() / GENERATOR_SHIELD_REGEN_TIME * deltaTime ) + harvester.GetShieldHealth()
+ float newShieldHealth = ( harvester.GetShieldHealthMax() / GetCurrentPlaylistVarFloat( "fw_harvester_regen_time", FW_DEFAULT_HARVESTER_REGEN_TIME ) * deltaTime ) + harvester.GetShieldHealth()
+ // shield full
if ( newShieldHealth >= harvester.GetShieldHealthMax() )
{
- StopSoundOnEntity( harvester, "coop_generator_shieldrecharge_resume" )
+ StopSoundOnEntity( harvester, "coop_generator_shieldrecharge_resume" )
harvester.SetShieldHealth( harvester.GetShieldHealthMax() )
EmitSoundOnEntity( harvester, "coop_generator_shieldrecharge_end" )
PlayFactionDialogueToTeam( "fortwar_baseShieldUpFriendly", harvester.GetTeam() )
@@ -1961,7 +2052,7 @@ void function HarvesterThink( HarvesterStruct fd_harvester )
harvester.SetShieldHealth( newShieldHealth )
}
}
- else if ( ( ( currentTime-fd_harvester.lastDamage ) < GENERATOR_SHIELD_REGEN_DELAY ) && ( harvester.GetShieldHealth() < harvester.GetShieldHealthMax() ) )
+ else if ( ( ( currentTime-fw_harvester.lastDamage ) < GENERATOR_SHIELD_REGEN_DELAY ) && ( harvester.GetShieldHealth() < harvester.GetShieldHealthMax() ) )
{
isRegening = false
}
@@ -1978,13 +2069,13 @@ void function HarvesterThink( HarvesterStruct fd_harvester )
}
}
-void function HarvesterAlarm( HarvesterStruct fd_harvester )
+void function HarvesterAlarm( HarvesterStruct fw_harvester )
{
- while( IsAlive( fd_harvester.harvester ) )
+ while( IsAlive( fw_harvester.harvester ) )
{
- if( fd_harvester.harvester.GetShieldHealth() == 0 )
+ if( fw_harvester.harvester.GetShieldHealth() == 0 )
{
- wait EmitSoundOnEntity( fd_harvester.harvester, "coop_generator_underattack_alarm" )
+ wait EmitSoundOnEntity( fw_harvester.harvester, "coop_generator_underattack_alarm" )
}
else
{
diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fw_custom.nut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fw_custom.nut
new file mode 100644
index 000000000..68a710e8f
--- /dev/null
+++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fw_custom.nut
@@ -0,0 +1,13 @@
+// cl_gamemode_fw already exists in vanilla game file
+// this file is to register more network vars or remote functions
+global function ServerCallback_FW_NotifyNeedsEnterEnemyArea
+
+void function ServerCallback_FW_NotifyNeedsEnterEnemyArea()
+{
+ AnnouncementData announcement = Announcement_Create( "#FW_ENTER_ENEMY_AREA" )
+ Announcement_SetSoundAlias( announcement, "UI_InGame_LevelUp" )
+ Announcement_SetSubText( announcement, "#FW_TITAN_REQUIRED_SUB" )
+ Announcement_SetPurge( announcement, true )
+ Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc
+ AnnouncementFromClass( GetLocalViewPlayer(), announcement )
+}
diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut
index 0cd2fd624..d999bb4c5 100644
--- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut
+++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut
@@ -9,6 +9,8 @@ global function SHCreateGamemodeFW_Init
// default havester settings
global const int FW_DEFAULT_HARVESTER_HEALTH = 25000
global const int FW_DEFAULT_HARVESTER_SHIELD = 5000
+global const float FW_DEFAULT_HARVESTER_REGEN_DELAY = 12.0
+global const float FW_DEFAULT_HARVESTER_REGEN_TIME = 10.0
// default turret settings
global const int FW_DEFAULT_TURRET_HEALTH = 12500
global const int FW_DEFAULT_TURRET_SHIELD = 4000
@@ -25,6 +27,8 @@ void function SHCreateGamemodeFW_Init()
// harvester playlistvar
AddPrivateMatchModeSettingArbitrary( "#PL_fw", "fw_harvester_health", FW_DEFAULT_HARVESTER_HEALTH.tostring() )
AddPrivateMatchModeSettingArbitrary( "#PL_fw", "fw_harvester_shield", FW_DEFAULT_HARVESTER_SHIELD.tostring() )
+ AddPrivateMatchModeSettingArbitrary( "#PL_fw", "fw_harvester_regen_delay", FW_DEFAULT_HARVESTER_REGEN_DELAY.tostring() )
+ AddPrivateMatchModeSettingArbitrary( "#PL_fw", "fw_harvester_regen_time", FW_DEFAULT_HARVESTER_REGEN_TIME.tostring() )
// turret playlistvar
AddPrivateMatchModeSettingArbitrary( "#PL_fw", "fw_turret_health", FW_DEFAULT_TURRET_HEALTH.tostring() )
AddPrivateMatchModeSettingArbitrary( "#PL_fw", "fw_turret_shield", FW_DEFAULT_TURRET_SHIELD.tostring() )
@@ -59,8 +63,8 @@ void function CreateGamemodeFW()
#if SERVER
GameMode_AddServerInit( FORT_WAR, GamemodeFW_Init )
- GameMode_SetPilotSpawnpointsRatingFunc( FORT_WAR, RateSpawnpoints_FW )
- GameMode_SetTitanSpawnpointsRatingFunc( FORT_WAR, RateSpawnpoints_FW )
+ GameMode_SetPilotSpawnpointsRatingFunc( FORT_WAR, RateSpawnpointsPilot_FW )
+ GameMode_SetTitanSpawnpointsRatingFunc( FORT_WAR, RateSpawnpointsTitan_FW )
#elseif CLIENT
GameMode_AddClientInit( FORT_WAR, CLGamemodeFW_Init )
#endif
@@ -74,6 +78,8 @@ void function FWOnRegisteringNetworkVars()
if ( GAMETYPE != FORT_WAR )
return
+ Remote_RegisterFunction( "ServerCallback_FW_NotifyNeedsEnterEnemyArea" )
+
RegisterNetworkedVariable( "turretSite1", SNDC_GLOBAL, SNVT_ENTITY )
RegisterNetworkedVariable( "turretSite2", SNDC_GLOBAL, SNVT_ENTITY )
RegisterNetworkedVariable( "turretSite3", SNDC_GLOBAL, SNVT_ENTITY )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
index ca8dc5f13..ec4267545 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
@@ -19,6 +19,8 @@ global function ShouldEntTakeDamage_SPMP
global function GetTitanBuildTime
global function TitanPlayerHotDropsIntoLevel
+global function SetRecalculateRespawnAsTitanStartPointCallback
+
struct {
bool killcamsEnabled = true
bool playerDeathsHidden = false
@@ -26,6 +28,8 @@ struct {
entity intermissionCamera
array<entity> specCams
+
+ entity functionref( entity player, entity basePoint ) recalculateRespawnAsTitanStartPointCallback
} file
void function BaseGametype_Init_MPSP()
@@ -443,6 +447,9 @@ void function RespawnAsTitan( entity player, bool manualPosition = false )
player.isSpawning = true
entity spawnpoint = FindSpawnPoint( player, true, ( ShouldStartSpawn( player ) || Flag( "ForceStartSpawn" ) ) && !IsFFAGame() )
+ if ( file.recalculateRespawnAsTitanStartPointCallback != null )
+ spawnpoint = file.recalculateRespawnAsTitanStartPointCallback( player, spawnpoint )
+
TitanLoadoutDef titanLoadout = GetTitanLoadoutForPlayer( player )
asset model = GetPlayerSettingsAssetForClassName( titanLoadout.setFile, "bodymodel" )
@@ -500,7 +507,7 @@ void function RespawnAsTitan( entity player, bool manualPosition = false )
titan.Destroy() // pilotbecomestitan leaves an npc titan that we need to delete
else
RespawnAsPilot( player ) // this is 100% an edgecase, just avoid softlocking if we ever hit it in playable gamestates
-
+
camera.Fire( "Disable", "!activator", 0, player )
camera.Destroy()
})
@@ -509,6 +516,7 @@ void function RespawnAsTitan( entity player, bool manualPosition = false )
player.RespawnPlayer( null ) // spawn player as pilot so they get their pilot loadout on embark
player.SetOrigin( titan.GetOrigin() )
+ ClearTitanAvailable( player ) // titanfall succeed, clear titan availability
// don't make player titan when entity batteryContainer is not valid.
// This will prevent a servercrash that sometimes occur when evac is disabled and somebody is calling a titan in the defeat screen.
@@ -577,6 +585,11 @@ void function CheckForAutoTitanDeath( entity victim, entity attacker, var damage
}
}
+void function SetRecalculateRespawnAsTitanStartPointCallback( entity functionref( entity player, entity basePoint ) callbackFunc )
+{
+ file.recalculateRespawnAsTitanStartPointCallback = callbackFunc
+}
+
// stuff to change later
bool function ShouldEntTakeDamage_SPMP( entity ent, var damageInfo )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut
index 349f9131f..57361362b 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut
@@ -20,7 +20,6 @@ global function req
global function ReplacementTitan
global function TryAnnounceTitanfallWarningToEnemyTeam
global function GetTitanForPlayer
-global function TryPlayTitanfallNegativeSoundToPlayer
global function ShouldSetTitanRespawnTimer
@@ -539,32 +538,6 @@ bool function ClientCommand_RequestTitan( entity player, array<string> args )
return true
}
-bool function TryPlayTitanfallNegativeSoundToPlayer( entity player )
-{
- if( !( "lastNegativeSound" in player.s ) )
- player.s.lastNegativeSound <- 0.0 // float
- if( player.s.lastNegativeSound + 3.0 > Time() ) // in sound cooldown
- return false
-
- EmitSoundOnEntityOnlyToPlayer( player, player, "titan_dryfire" )
- player.s.lastNegativeSound = Time()
-
- return true
-}
-
-/* // serverSideRUI can't handle localized strings
-void function CreateCustomMessageForRefusingTitanfall( entity player )
-{
- if( !( "lastMessageSend" in player.s ) )
- player.s.lastMessageSend <- 0.0 // float
- if( player.s.lastMessageSend + 10 > Time() ) // in message cooldown
- return
-
- NSSendInfoMessageToPlayer( player, "#FW_OBJECTIVE_TITANFALL" )
- player.s.lastMessageSend = Time()
-}
-*/
-
// This a baseline titan request function; the only things that prevent this from happening are
// common cases; wrong gamestate, already has a titan, is currently dead, etc...
bool function RequestTitan( entity player )