aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts
diff options
context:
space:
mode:
authorGeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>2023-12-31 18:58:50 +0100
committerGitHub <noreply@github.com>2023-12-31 18:58:50 +0100
commita1502e9ad3ed44b2a0a8ab5f17d4d2bf5238d9cf (patch)
tree0f171ab768fa6f8dd8d68fc4f0675baffbfd5e5d /Northstar.CustomServers/mod/scripts
parentad70253601a77844347d8aa1989ae5ab4fb4217c (diff)
parent00a4bb6fb5e107788ea77cad51c8c8004a9537f1 (diff)
downloadNorthstarMods-a1502e9ad3ed44b2a0a8ab5f17d4d2bf5238d9cf.tar.gz
NorthstarMods-a1502e9ad3ed44b2a0a8ab5f17d4d2bf5238d9cf.zip
Merge pull request #777 from R2Northstar/main
Update FD branch
Diffstat (limited to 'Northstar.CustomServers/mod/scripts')
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_items.nut4
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut4
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut14
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut34
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut75
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_spectator.gnut10
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut10
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut27
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut24
9 files changed, 176 insertions, 26 deletions
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_items.nut b/Northstar.CustomServers/mod/scripts/vscripts/_items.nut
index a5c3e270..a23a68b0 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_items.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_items.nut
@@ -10231,6 +10231,10 @@ void function StatUnlock_Unlocked( entity player, string itemRef, string parentR
if ( IsItemNew( player, itemRef, parentRef ) )
return
+ // early out if the player has progression disabled
+ if ( !ProgressionEnabledForPlayer( player ) )
+ return
+
int refGuid = file.itemRefToGuid[itemRef]
int parentRefGuid = parentRef == "" ? 0 : file.itemRefToGuid[parentRef]
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
index 24dbb62d..103efe6f 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
@@ -201,6 +201,10 @@ bool function ClientCommandCallback_SwapSecondaryAndWeapon3PersistentLoadoutData
// get loadout
int index = args[0].tointeger()
+
+ if ( !IsValidPilotLoadoutIndex(index) )
+ return false
+
PilotLoadoutDef loadout = GetPilotLoadoutFromPersistentData( player, index )
// swap loadouts
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 bab7eaed..9288f75e 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
@@ -295,6 +295,10 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
})
entity attacker = DamageInfo_GetAttacker( damageInfo )
+ entity inflictor = DamageInfo_GetInflictor( damageInfo )
+ int eHandle = attacker.GetEncodedEHandle()
+ if ( inflictor && ShouldTryUseProjectileReplay( player, attacker, damageInfo, false ) )
+ eHandle = inflictor.GetEncodedEHandle()
int methodOfDeath = DamageInfo_GetDamageSourceIdentifier( damageInfo )
table<int, bool> alreadyAssisted
@@ -374,7 +378,7 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
if ( "respawnTime" in attacker.s )
respawnTime = Time() - expect float ( attacker.s.respawnTime )
- thread PlayerWatchesKillReplayWrapper( player, attacker, respawnTime, timeOfDeath, beforeTime, replayTracker )
+ thread PlayerWatchesKillReplayWrapper( player, attacker, eHandle, respawnTime, timeOfDeath, beforeTime, replayTracker )
}
player.SetPlayerSettings( "spectator" ) // prevent a crash with going from titan => pilot on respawn
@@ -432,7 +436,7 @@ void function ForceRespawnMeSignalAfterDelay( entity player, int delay = 5 )
player.Signal( "RespawnMe" )
}
-void function PlayerWatchesKillReplayWrapper( entity player, entity attacker, float timeSinceAttackerSpawned, float timeOfDeath, float beforeTime, table replayTracker )
+void function PlayerWatchesKillReplayWrapper( entity player, entity attacker, int eHandle, float timeSinceAttackerSpawned, float timeOfDeath, float beforeTime, table replayTracker )
{
player.EndSignal( "RespawnMe" )
player.EndSignal( "OnRespawned" )
@@ -455,7 +459,7 @@ void function PlayerWatchesKillReplayWrapper( entity player, entity attacker, fl
})
player.SetPredictionEnabled( false )
- PlayerWatchesKillReplay( player, attacker.GetEncodedEHandle(), attacker.GetIndexForEntity(), timeSinceAttackerSpawned, timeOfDeath, beforeTime, replayTracker )
+ PlayerWatchesKillReplay( player, eHandle, attacker.GetIndexForEntity(), timeSinceAttackerSpawned, timeOfDeath, beforeTime, replayTracker )
}
void function DecideRespawnPlayer( entity player )
@@ -628,6 +632,10 @@ void function SetRecalculateRespawnAsTitanStartPointCallback( entity functionref
bool function ShouldEntTakeDamage_SPMP( entity ent, var damageInfo )
{
+ // dropships are immune to being crushed
+ if ( ( IsDropship( ent ) || IsEvacDropship( ent ) ) && IsTitanCrushDamage( damageInfo ) )
+ return false
+
return true
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
index 3426cec5..4c52a9bf 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
@@ -13,6 +13,8 @@ global function SetTimerBased
global function SetShouldUseRoundWinningKillReplay
global function SetRoundWinningKillReplayKillClasses
global function SetRoundWinningKillReplayAttacker
+global function SetCallback_TryUseProjectileReplay
+global function ShouldTryUseProjectileReplay
global function SetWinner
global function SetTimeoutWinnerDecisionFunc
global function AddTeamScore
@@ -48,13 +50,28 @@ struct {
float roundWinningKillReplayTime
entity roundWinningKillReplayVictim
entity roundWinningKillReplayAttacker
+ int roundWinningKillReplayInflictorEHandle // this is either the inflictor or the attacker
int roundWinningKillReplayMethodOfDeath
float roundWinningKillReplayTimeOfDeath
float roundWinningKillReplayHealthFrac
array<void functionref()> roundEndCleanupCallbacks
+ bool functionref( entity victim, entity attacker, var damageInfo, bool isRoundEnd ) shouldTryUseProjectileReplayCallback
} file
+void function SetCallback_TryUseProjectileReplay( bool functionref( entity victim, entity attacker, var damageInfo, bool isRoundEnd ) callback )
+{
+ file.shouldTryUseProjectileReplayCallback = callback
+}
+
+bool function ShouldTryUseProjectileReplay( entity victim, entity attacker, var damageInfo, bool isRoundEnd )
+{
+ if ( file.shouldTryUseProjectileReplayCallback != null )
+ return file.shouldTryUseProjectileReplayCallback( victim, attacker, damageInfo, isRoundEnd )
+ // default to true (vanilla behaviour)
+ return true
+}
+
void function PIN_GameStart()
{
// todo: using the pin telemetry function here, weird and was done veeery early on before i knew how this all worked, should use a different one
@@ -319,6 +336,7 @@ void function GameStateEnter_WinnerDetermined_Threaded()
WaitFrame() // prevent a race condition with PlayerWatchesRoundWinningKillReplay
file.roundWinningKillReplayAttacker = null // clear this
+ file.roundWinningKillReplayInflictorEHandle = -1
if ( killcamsWereEnabled )
SetKillcamsEnabled( true )
@@ -394,7 +412,7 @@ void function PlayerWatchesRoundWinningKillReplay( entity player, float replayLe
if ( IsValid( attacker ) )
{
player.SetKillReplayDelay( Time() - replayLength, THIRD_PERSON_KILL_REPLAY_ALWAYS )
- player.SetKillReplayInflictorEHandle( attacker.GetEncodedEHandle() )
+ player.SetKillReplayInflictorEHandle( file.roundWinningKillReplayInflictorEHandle )
player.SetKillReplayVictim( file.roundWinningKillReplayVictim )
player.SetViewIndex( attacker.GetIndexForEntity() )
player.SetIsReplayRoundWinning( true )
@@ -460,6 +478,7 @@ void function GameStateEnter_SwitchingSides_Threaded()
svGlobal.levelEnt.Signal( "RoundEnd" ) // might be good to get a new signal for this? not 100% necessary tho i think
SetServerVar( "switchedSides", 1 )
file.roundWinningKillReplayAttacker = null // reset this after replay
+ file.roundWinningKillReplayInflictorEHandle = -1
if ( file.usePickLoadoutScreen )
SetGameState( eGameState.PickLoadout )
@@ -483,7 +502,7 @@ void function PlayerWatchesSwitchingSidesKillReplay( entity player, bool doRepla
entity attacker = file.roundWinningKillReplayAttacker
player.SetKillReplayDelay( Time() - replayLength, THIRD_PERSON_KILL_REPLAY_ALWAYS )
- player.SetKillReplayInflictorEHandle( attacker.GetEncodedEHandle() )
+ player.SetKillReplayInflictorEHandle( file.roundWinningKillReplayInflictorEHandle )
player.SetKillReplayVictim( file.roundWinningKillReplayVictim )
player.SetViewIndex( attacker.GetIndexForEntity() )
player.SetIsReplayRoundWinning( true )
@@ -578,6 +597,9 @@ void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
return
}
+ entity inflictor = DamageInfo_GetInflictor( damageInfo )
+ bool shouldUseInflictor = IsValid( inflictor ) && ShouldTryUseProjectileReplay( victim, attacker, damageInfo, true )
+
// set round winning killreplay info here if we're tracking pilot kills
// todo: make this not count environmental deaths like falls, unsure how to prevent this
if ( file.roundWinningKillReplayTrackPilotKills && victim != attacker && attacker != svGlobal.worldspawn && IsValid( attacker ) )
@@ -587,6 +609,7 @@ void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
file.roundWinningKillReplayTime = Time()
file.roundWinningKillReplayVictim = victim
file.roundWinningKillReplayAttacker = attacker
+ file.roundWinningKillReplayInflictorEHandle = ( shouldUseInflictor ? inflictor : attacker ).GetEncodedEHandle()
file.roundWinningKillReplayMethodOfDeath = DamageInfo_GetDamageSourceIdentifier( damageInfo )
file.roundWinningKillReplayTimeOfDeath = Time()
file.roundWinningKillReplayHealthFrac = GetHealthFrac( attacker )
@@ -637,6 +660,9 @@ void function OnTitanKilled( entity victim, var damageInfo )
return
}
+ entity inflictor = DamageInfo_GetInflictor( damageInfo )
+ bool shouldUseInflictor = IsValid( inflictor ) && ShouldTryUseProjectileReplay( victim, DamageInfo_GetAttacker( damageInfo ), damageInfo, true )
+
// set round winning killreplay info here if we're tracking titan kills
// todo: make this not count environmental deaths like falls, unsure how to prevent this
entity attacker = DamageInfo_GetAttacker( damageInfo )
@@ -647,6 +673,7 @@ void function OnTitanKilled( entity victim, var damageInfo )
file.roundWinningKillReplayTime = Time()
file.roundWinningKillReplayVictim = victim
file.roundWinningKillReplayAttacker = attacker
+ file.roundWinningKillReplayInflictorEHandle = ( shouldUseInflictor ? inflictor : attacker ).GetEncodedEHandle()
file.roundWinningKillReplayMethodOfDeath = DamageInfo_GetDamageSourceIdentifier( damageInfo )
file.roundWinningKillReplayTimeOfDeath = Time()
file.roundWinningKillReplayHealthFrac = GetHealthFrac( attacker )
@@ -761,11 +788,12 @@ void function SetRoundWinningKillReplayKillClasses( bool pilot, bool titan )
file.roundWinningKillReplayTrackTitanKills = titan // player kills in titans should get tracked anyway, might be worth renaming this
}
-void function SetRoundWinningKillReplayAttacker( entity attacker )
+void function SetRoundWinningKillReplayAttacker( entity attacker, int inflictorEHandle = -1 )
{
file.roundWinningKillReplayTime = Time()
file.roundWinningKillReplayHealthFrac = GetHealthFrac( attacker )
file.roundWinningKillReplayAttacker = attacker
+ file.roundWinningKillReplayInflictorEHandle = inflictorEHandle == -1 ? attacker.GetEncodedEHandle() : inflictorEHandle
file.roundWinningKillReplayTimeOfDeath = Time()
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut
index 0b55e9ff..be20982d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut
@@ -28,6 +28,10 @@ void function InitPlayerForScoreEvents( entity player )
player.s.currentKillstreak <- 0
player.s.lastKillTime <- 0.0
player.s.currentTimedKillstreak <- 0
+ player.s.lastKillTime_Mayhem <- 0.0
+ player.s.currentTimedKillstreak_Mayhem <- 0
+ player.s.lastKillTime_Onslaught <- 0.0
+ player.s.currentTimedKillstreak_Onslaught <- 0
}
void function AddPlayerScore( entity targetPlayer, string scoreEventName, entity associatedEnt = null, string noideawhatthisis = "", int pointValueOverride = -1 )
@@ -93,6 +97,7 @@ void function ScoreEvent_PlayerKilled( entity victim, entity attacker, var damag
victim.s.currentTimedKillstreak = 0
victim.p.numberOfDeathsSinceLastKill++ // this is reset on kill
+ victim.p.lastKiller = attacker
// have to do this early before we reset victim's player killstreaks
// nemesis when you kill a player that is dominating you
@@ -131,12 +136,20 @@ void function ScoreEvent_PlayerKilled( entity victim, entity attacker, var damag
attacker.p.numberOfDeathsSinceLastKill = 0
}
+ // revenge + quick revenge
+ if ( attacker.p.lastKiller == victim )
+ {
+ if ( Time() - GetPlayerLastRespawnTime( attacker ) < QUICK_REVENGE_TIME_LIMIT )
+ AddPlayerScore( attacker, "QuickRevenge" )
+ else
+ AddPlayerScore( attacker, "Revenge" )
+ }
// untimed killstreaks
attacker.s.currentKillstreak++
- if ( attacker.s.currentKillstreak == 3 )
+ if ( attacker.s.currentKillstreak == KILLINGSPREE_KILL_REQUIREMENT )
AddPlayerScore( attacker, "KillingSpree" )
- else if ( attacker.s.currentKillstreak == 5 )
+ else if ( attacker.s.currentKillstreak == RAMPAGE_KILL_REQUIREMENT )
AddPlayerScore( attacker, "Rampage" )
// increment untimed killstreaks against specific players
@@ -202,18 +215,23 @@ void function ScoreEvent_TitanKilled( entity victim, entity attacker, var damage
AddPlayerScore( attacker, "KillTitan" )
}
- table<int, bool> alreadyAssisted
- foreach( DamageHistoryStruct attackerInfo in victim.e.recentDamageHistory )
+ entity soul = victim.GetTitanSoul()
+ if ( IsValid( soul ) )
{
- if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == victim )
- continue
-
- bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false
- if( attackerInfo.attacker != attacker && !exists )
+ table<int, bool> alreadyAssisted
+
+ foreach( DamageHistoryStruct attackerInfo in soul.e.recentDamageHistory )
{
- alreadyAssisted[attackerInfo.attacker.GetEncodedEHandle()] <- true
- AddPlayerScore(attackerInfo.attacker, "TitanAssist" )
- Remote_CallFunction_NonReplay( attackerInfo.attacker, "ServerCallback_SetAssistInformation", attackerInfo.damageSourceId, attacker.GetEncodedEHandle(), victim.GetEncodedEHandle(), attackerInfo.time )
+ if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == soul )
+ continue
+
+ bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false
+ if( attackerInfo.attacker != attacker && !exists )
+ {
+ alreadyAssisted[attackerInfo.attacker.GetEncodedEHandle()] <- true
+ AddPlayerScore(attackerInfo.attacker, "TitanAssist" )
+ Remote_CallFunction_NonReplay( attackerInfo.attacker, "ServerCallback_SetAssistInformation", attackerInfo.damageSourceId, attacker.GetEncodedEHandle(), soul.GetEncodedEHandle(), attackerInfo.time )
+ }
}
}
@@ -229,6 +247,39 @@ void function ScoreEvent_NPCKilled( entity victim, entity attacker, var damageIn
AddPlayerScore( attacker, ScoreEventForNPCKilled( victim, damageInfo ), victim )
}
catch ( ex ) {}
+
+ if ( !attacker.IsPlayer() )
+ return
+
+ // mayhem/onslaught (timed killstreaks vs AI)
+
+ // reset before checking
+ if ( Time() - attacker.s.lastKillTime_Mayhem > MAYHEM_REQUIREMENT_TIME )
+ {
+ attacker.s.currentTimedKillstreak_Mayhem = 0
+ attacker.s.lastKillTime_Mayhem = Time()
+ }
+ if ( Time() - attacker.s.lastKillTime_Mayhem <= MAYHEM_REQUIREMENT_TIME )
+ {
+ attacker.s.currentTimedKillstreak_Mayhem++
+
+ if ( attacker.s.currentTimedKillstreak_Mayhem == MAYHEM_REQUIREMENT_KILLS )
+ AddPlayerScore( attacker, "Mayhem" )
+ }
+
+ // reset before checking
+ if ( Time() - attacker.s.lastKillTime_Onslaught > ONSLAUGHT_REQUIREMENT_TIME )
+ {
+ attacker.s.currentTimedKillstreak_Onslaught = 0
+ attacker.s.lastKillTime_Onslaught = Time()
+ }
+ if ( Time() - attacker.s.lastKillTime_Onslaught <= ONSLAUGHT_REQUIREMENT_TIME )
+ {
+ attacker.s.currentTimedKillstreak_Onslaught++
+
+ if ( attacker.s.currentTimedKillstreak_Onslaught == ONSLAUGHT_REQUIREMENT_KILLS )
+ AddPlayerScore( attacker, "Onslaught" )
+ }
}
void function ScoreEvent_MatchComplete( int winningTeam )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_spectator.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_spectator.gnut
index aa2fc108..510a9b7e 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_spectator.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_spectator.gnut
@@ -170,6 +170,9 @@ void function SpectatorFunc_Default( entity player )
{
player.SetObserverTarget( target )
player.StartObserverMode( OBS_MODE_CHASE )
+ // the delay of 0.1 seems to fix the spec_mode command not working
+ // when using the keybind
+ player.SetSpecReplayDelay( 0.1 )
}
catch ( ex ) { }
}
@@ -215,9 +218,12 @@ bool function ClientCommandCallback_spec_mode( entity player, array<string> args
else if ( player.GetObserverMode() == OBS_MODE_IN_EYE )
{
// set to third person spectate
- player.SetSpecReplayDelay( 0.0 )
+
+ // the delay of 0.1 seems to fix the spec_mode command not working
+ // when using the keybind
+ player.SetSpecReplayDelay( 0.1 )
player.StartObserverMode( OBS_MODE_CHASE )
}
return true
-} \ No newline at end of file
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut
index 208e6da1..bd64e4ca 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut
@@ -264,7 +264,7 @@ void function Stats_IncrementStat( entity player, string statCategory, string st
// persistence string, we can't save the persistence so we have to just return
if ( str != saveVar )
{
- printt( ex )
+ //printt( ex, str, GetMapName(), mode ) // Commented out due to spamming logs on invalid modes (e.g. Gun Game, Infection, ...)
return
}
}
@@ -571,9 +571,11 @@ void function HandleKillStats( entity victim, entity attacker, var damageInfo )
// assistsTotal ( weapon_kill_stats )
// note: eww
table<int, bool> alreadyAssisted
- foreach( DamageHistoryStruct attackerInfo in victim.e.recentDamageHistory )
+ // titans store their recentDamageHistory in the soul
+ entity assistVictim = ( victim.IsTitan() && IsValid( victim.GetTitanSoul() ) ) ? victim.GetTitanSoul() : victim
+ foreach( DamageHistoryStruct attackerInfo in assistVictim.e.recentDamageHistory )
{
- if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == victim )
+ if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == assistVictim )
continue
bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false
@@ -585,7 +587,7 @@ void function HandleKillStats( entity victim, entity attacker, var damageInfo )
string source = DamageSourceIDToString( attackerInfo.damageSourceId )
if ( IsValidStatItemString( source ) )
- Stats_IncrementStat( attacker, "weapon_kill_stats", "assistsTotal", source, 1.0 )
+ Stats_IncrementStat( attackerInfo.attacker, "weapon_kill_stats", "assistsTotal", source, 1.0 )
}
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut b/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut
index ceb5e837..2dc88d0d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut
@@ -38,6 +38,7 @@ void function Progression_Init()
#if SERVER
AddCallback_OnClientDisconnected( OnClientDisconnected )
AddClientCommandCallback( "ns_progression", ClientCommand_SetProgression )
+ AddClientCommandCallback( "ns_resettitanaegis", ClientCommand_ResetTitanAegis )
AddCallback_GameStateEnter( eGameState.Playing, OnPlaying )
#elseif CLIENT
AddCallback_OnClientScriptInit( OnClientScriptInit )
@@ -84,6 +85,28 @@ bool function ClientCommand_SetProgression( entity player, array<string> args )
return true
}
+
+/// Resets a specific Titan's Aegis rank back to `0`
+/// * `player` - The player entity to perform the action on
+/// * `args` - The arguments passed from the client command. `args[0]` should be an integer corresponding to the index of the Titan to reset.
+///
+/// Returns `true` on success and `false` on missing args.
+bool function ClientCommand_ResetTitanAegis( entity player, array<string> args )
+{
+ if ( !args.len() )
+ return false
+
+ int suitIndex = args[0].tointeger()
+ player.SetPersistentVar( "titanFDUnlockPoints[" + suitIndex + "]", 0 )
+ player.SetPersistentVar( "previousFDUnlockPoints[" + suitIndex + "]", 0 )
+ player.SetPersistentVar( "fdTitanXP[" + suitIndex + "]", 0 )
+ player.SetPersistentVar( "fdPreviousTitanXP[" + suitIndex + "]", 0 )
+
+ // Refresh Highest Aegis Titan since we might get all of them back to 1 if players wants
+ RecalculateHighestTitanFDLevel( player )
+
+ return true
+}
#endif
#if CLIENT
@@ -268,7 +291,7 @@ void function ValidateEquippedItems( entity player )
// camoIndex
if ( loadout.skinIndex == TITAN_SKIN_INDEX_CAMO )
{
- array<ItemData> camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN )
+ array<ItemData> camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN_TITAN )
if ( loadout.camoIndex >= camoSkins.len() || loadout.camoIndex < 0 )
{
printt( " - INVALID TITAN CAMO/SKIN, RESETTING" )
@@ -363,7 +386,7 @@ void function ValidateEquippedItems( entity player )
// primeCamoIndex
if ( loadout.primeSkinIndex == TITAN_SKIN_INDEX_CAMO )
{
- array<ItemData> camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN )
+ array<ItemData> camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN_TITAN )
if ( loadout.primeCamoIndex >= camoSkins.len() || loadout.primeCamoIndex < 0 )
{
printt( " - INVALID TITAN CAMO/SKIN, RESETTING" )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut b/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut
index 9e762985..2ca051cf 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut
@@ -348,6 +348,14 @@ string function GetMapDisplayDesc( string mapname )
return "#" + mapname + "_CLASSIC_DESC"
}
+/// Sends a string message to player
+/// * `baseString` - The input string to search through
+/// * `searchString` - Find this substring...
+/// * `replaceString` - ...and replace with this substring
+/// * `replaceAll` - Whether to replace all occurences or just the first
+/// * `caseInsensitive` - Whether to consider casing (upper/lower)
+///
+/// Returns the updated string
string function StringReplace( string baseString, string searchString, string replaceString, bool replaceAll = false, bool caseInsensitive = false )
{
bool loopedOnce = false
@@ -1532,7 +1540,23 @@ array<string> function GetAvailableTitanRefs( entity player )
return availableTitanRefs
}
+/// Gets the highest Titan FD level and stores it in the corresponding persistent var.
+/// * `player` - The player entity to perform the action on
#if MP
+void function RecalculateHighestTitanFDLevel( entity player )
+{
+ int enumCount = PersistenceGetEnumCount( "titanClasses" )
+ int highestAegis = 0
+ for ( int i = 0; i < enumCount; i++ )
+ {
+ string enumName = PersistenceGetEnumItemNameForIndex( "titanClasses", i )
+ int aegisLevel = FD_TitanGetLevelForXP( enumName, FD_TitanGetXP( player, enumName ) )
+ if ( highestAegis < aegisLevel )
+ highestAegis = aegisLevel
+ }
+ player.SetPersistentVar( "fdStats.highestTitanFDLevel", highestAegis )
+}
+
string function GetTitanRefForLoadoutIndex( entity player, int loadoutIndex )
{
TitanLoadoutDef loadout = GetTitanLoadoutFromPersistentData( player, loadoutIndex )