aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/gamemodes/_frontline.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/gamemodes/_frontline.gnut')
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_frontline.gnut159
1 files changed, 159 insertions, 0 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_frontline.gnut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_frontline.gnut
new file mode 100644
index 00000000..7ece7dc1
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_frontline.gnut
@@ -0,0 +1,159 @@
+untyped
+
+
+global function GetFrontline
+global function SetFrontline
+global function AddCalculateFrontlineCallback
+
+const DEBUG_FRONTLINE = false
+
+global struct Frontline
+{
+ vector origin = Vector( 0.0, 0.0, 0.0 )
+ vector combatDir = Vector( 0.0, 0.0, 0.0 )
+ vector line = Vector( 0.0, 0.0, 0.0 )
+ vector friendlyCenter = Vector( 0.0, 0.0, 0.0 )
+ vector enemyCenter = Vector( 0.0, 0.0, 0.0 )
+ float lastCalcTime = -1.0
+}
+
+struct
+{
+ Frontline frontline
+ array<void functionref()> calculateFrontlineCallbacks
+} file
+
+Frontline function GetFrontline( team )
+{
+ if ( file.frontline.lastCalcTime < Time() )
+ {
+ CalculateFrontline()
+ file.frontline.lastCalcTime = Time()
+ }
+
+ Frontline fl
+ fl = clone file.frontline
+
+ if ( team == TEAM_MILITIA )
+ {
+ fl.combatDir *= -1.0
+ vector temp = fl.friendlyCenter
+ fl.friendlyCenter = fl.enemyCenter
+ fl.enemyCenter = temp
+ }
+
+ return fl
+}
+
+void function AddCalculateFrontlineCallback( void functionref() callbackFunc )
+{
+ // Check if this function has already been added
+ #if DEV
+ foreach ( func in file.calculateFrontlineCallbacks )
+ {
+ Assert( func != callbackFunc )
+ }
+ #endif
+
+ file.calculateFrontlineCallbacks.append( callbackFunc )
+}
+
+void function CalculateFrontline()
+{
+ #if DEV
+ float debugTime = 0.2
+ #endif
+
+ if ( file.calculateFrontlineCallbacks.len() > 0 )
+ {
+ foreach ( callbackFunc in file.calculateFrontlineCallbacks )
+ {
+ callbackFunc()
+ }
+ }
+ else
+ {
+ vector militiaCenter = CalculateWeightedTeamCenter( TEAM_MILITIA )
+ vector imcCenter = CalculateWeightedTeamCenter( TEAM_IMC )
+
+ file.frontline.friendlyCenter = imcCenter // friendlyCenter is for TEAM_IMC by default
+ file.frontline.enemyCenter = militiaCenter
+
+ file.frontline.origin = ( militiaCenter + imcCenter ) * 0.5
+ file.frontline.combatDir = Normalize( militiaCenter - imcCenter ) // combatDir is for TEAM_IMC by default
+ file.frontline.line = CrossProduct( file.frontline.combatDir, Vector( 0.0, 0.0, 1.0 ) )
+
+ #if DEV
+ if ( DEBUG_FRONTLINE )
+ {
+ DrawBox( militiaCenter, Vector( -8.0, -8.0, -8.0 ), Vector( 8.0, 8.0, 8.0 ), 255, 102, 0, true, debugTime )
+ DrawBox( imcCenter, Vector( -8.0, -8.0, -8.0 ), Vector( 8.0, 8.0, 8.0 ), 0, 0, 255, true, debugTime )
+ DebugDrawLine( militiaCenter, imcCenter, 0, 255, 0, true, debugTime )
+ }
+ #endif
+ }
+
+ #if DEV
+ if ( DEBUG_FRONTLINE )
+ {
+ DrawBox( file.frontline.origin, Vector( -32.0, -32.0, -32.0 ), Vector( 32.0, 32.0, 32.0 ), 255, 0, 0, true, debugTime )
+ DebugDrawLine( file.frontline.origin - file.frontline.line * 500.0, file.frontline.origin + file.frontline.line * 500.0, 255, 0, 0, true, debugTime )
+ }
+ #endif
+}
+
+void function SetFrontline( vector origin, vector combatDir )
+{
+ file.frontline.origin = origin
+ file.frontline.combatDir = combatDir
+ file.frontline.line = CrossProduct( file.frontline.combatDir, Vector( 0.0, 0.0, 1.0 ) )
+}
+
+vector function CalculateWeightedTeamCenter( int team )
+{
+ array<entity> teamPlayers = GetPlayerArrayOfTeam_Alive( team )
+ int teamPlayersCount = teamPlayers.len()
+
+ if ( teamPlayersCount == 0 )
+ return Vector( 0.0, 0.0, 0.0 )
+
+ // find minimum distances between teammates
+ array<float> minTeammateDistances// = arrayofsize( teamPlayersCount, 99999.0 )
+ minTeammateDistances.resize( teamPlayersCount, 99999.0 )
+
+ for ( int i = 0; i < teamPlayersCount; i++ )
+ {
+ entity playerI = teamPlayers[ i ]
+
+ for ( int j = i + 1; j < teamPlayersCount; j++ )
+ {
+ entity playerJ = teamPlayers[ j ]
+ float distanceBetweenPlayers = Distance( playerI.GetOrigin(), playerJ.GetOrigin() )
+
+ if ( distanceBetweenPlayers < minTeammateDistances[ i ] )
+ minTeammateDistances[ i ] = distanceBetweenPlayers
+
+ if ( distanceBetweenPlayers < minTeammateDistances[ j ] )
+ minTeammateDistances[ j ] = distanceBetweenPlayers
+ }
+ }
+
+ vector weightedOrgSum = Vector( 0.0, 0.0, 0.0 )
+ float weightSum = 0.0
+ float weight = 0.0
+ float halfPi = 1.57 // passing a fraction of this value into sin which gives us the first part of a sin wave from 0 - 1
+ float maxPossibleDistance = MAX_WORLD_RANGE
+ float magicNumber = 14.0 // magic number gives the desired falloff
+
+ // calculate a weighted origin based on how close players are to teammates
+ foreach ( index, player in teamPlayers )
+ {
+ float radians = halfPi * ( minTeammateDistances[ index ] / maxPossibleDistance ) // radians will be a value between 0 - halfPi
+ weight = pow( ( 1.0 - sin( radians ) ), magicNumber ) // pow squashes the result so the curve has the falloff that's desired
+
+ weightedOrgSum += player.GetOrigin() * weight
+ weightSum += weight
+ }
+
+ return weightedOrgSum / weightSum
+} \ No newline at end of file