clean-up and make game interface gsc consistent

This commit is contained in:
RaidMax 2023-06-01 20:45:05 -05:00
parent ebdad2768d
commit 7323c6e3d7
8 changed files with 316 additions and 1036 deletions

View File

@ -19,11 +19,15 @@ Setup()
level.commonFunctions = spawnstruct(); level.commonFunctions = spawnstruct();
level.commonFunctions.setDvar = "SetDvarIfUninitialized"; level.commonFunctions.setDvar = "SetDvarIfUninitialized";
level.commonFunctions.isBot = "IsBot";
level.commonFunctions.getXuid = "GetXuid";
level.commonFunctions.getPlayerFromClientNum = "GetPlayerFromClientNum"; level.commonFunctions.getPlayerFromClientNum = "GetPlayerFromClientNum";
level.commonFunctions.waittillNotifyOrTimeout = "WaittillNotifyOrTimeout";
level.overrideMethods = [];
level.overrideMethods[level.commonFunctions.setDvar] = scripts\_integration_base::NotImplementedFunction;
level.overrideMethods[level.commonFunctions.getPlayerFromClientNum] = ::_GetPlayerFromClientNum;
level.commonKeys = spawnstruct(); level.commonKeys = spawnstruct();
level.commonKeys.enabled = "sv_iw4madmin_integration_enabled";
level.notifyTypes = spawnstruct(); level.notifyTypes = spawnstruct();
level.notifyTypes.gameFunctionsInitialized = "GameFunctionsInitialized"; level.notifyTypes.gameFunctionsInitialized = "GameFunctionsInitialized";
@ -51,12 +55,11 @@ Setup()
level.clientCommandCallbacks = []; level.clientCommandCallbacks = [];
level.clientCommandRusAsTarget = []; level.clientCommandRusAsTarget = [];
level.logger = spawnstruct(); level.logger = spawnstruct();
level.overrideMethods = [];
level.iw4madminIntegrationDebug = GetDvarInt( "sv_iw4madmin_integration_debug" ); level.iw4madminIntegrationDebug = GetDvarInt( "sv_iw4madmin_integration_debug" );
InitializeLogger(); InitializeLogger();
wait ( 0.05 ); // needed to give script engine time to propagate notifies wait ( 0.05 * 2 ); // needed to give script engine time to propagate notifies
level notify( level.notifyTypes.integrationBootstrapInitialized ); level notify( level.notifyTypes.integrationBootstrapInitialized );
level waittill( level.notifyTypes.gameFunctionsInitialized ); level waittill( level.notifyTypes.gameFunctionsInitialized );
@ -65,105 +68,26 @@ Setup()
_SetDvarIfUninitialized( level.eventBus.inVar, "" ); _SetDvarIfUninitialized( level.eventBus.inVar, "" );
_SetDvarIfUninitialized( level.eventBus.outVar, "" ); _SetDvarIfUninitialized( level.eventBus.outVar, "" );
_SetDvarIfUninitialized( "sv_iw4madmin_integration_enabled", 1 ); _SetDvarIfUninitialized( level.commonKeys.enabled, 1 );
_SetDvarIfUninitialized( "sv_iw4madmin_integration_debug", 0 ); _SetDvarIfUninitialized( "sv_iw4madmin_integration_debug", 0 );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 ) if ( GetDvarInt( level.commonKeys.enabled) != 1 )
{ {
return; return;
} }
// start long running tasks // start long running tasks
level thread MonitorClientEvents(); thread MonitorClientEvents();
level thread MonitorBus(); thread MonitorBus();
level thread OnPlayerConnect();
} }
////////////////////////////////// //////////////////////////////////
// Client Methods // Client Methods
////////////////////////////////// //////////////////////////////////
OnPlayerConnect()
{
level endon ( "game_ended" );
for ( ;; )
{
level waittill( "connected", player );
if ( _IsBot( player ) )
{
// we don't want to track bots
continue;
}
if ( !IsDefined( player.pers[level.clientDataKey] ) )
{
player.pers[level.clientDataKey] = spawnstruct();
}
player thread OnPlayerSpawned();
}
}
OnPlayerSpawned()
{
self endon( "disconnect" );
for ( ;; )
{
self waittill( "spawned_player" );
self PlayerSpawnEvents();
}
}
OnGameEnded()
{
for ( ;; )
{
level waittill( "game_ended" );
// note: you can run data code here but it's possible for
// data to get truncated, so we will try a timer based approach for now
}
}
DisplayWelcomeData()
{
self endon( "disconnect" );
clientData = self.pers[level.clientDataKey];
if ( clientData.permissionLevel == "User" || clientData.permissionLevel == "Flagged" )
{
return;
}
self IPrintLnBold( "Welcome, your level is ^5" + clientData.permissionLevel );
wait( 2.0 );
self IPrintLnBold( "You were last seen ^5" + clientData.lastConnection );
}
PlayerSpawnEvents()
{
self endon( "disconnect" );
clientData = self.pers[level.clientDataKey];
// this gives IW4MAdmin some time to register the player before making the request;
// although probably not necessary some users might have a slow database or poll rate
wait ( 2 );
if ( IsDefined( clientData.state ) && clientData.state == "complete" )
{
return;
}
self RequestClientBasicData();
}
MonitorClientEvents() MonitorClientEvents()
{ {
level endon( "game_ended" ); level endon( level.eventTypes.gameEnd );
for ( ;; ) for ( ;; )
{ {
@ -178,6 +102,7 @@ MonitorClientEvents()
client [[eventHandler]]( client.event ); client [[eventHandler]]( client.event );
LogDebug( "notify client for " + client.event.type ); LogDebug( "notify client for " + client.event.type );
client notify( level.eventTypes.localClientEvent, client.event ); client notify( level.eventTypes.localClientEvent, client.event );
client notify( client.event.type, client.event );
} }
client.eventData = []; client.eventData = [];
@ -188,11 +113,13 @@ MonitorClientEvents()
// Helper Methods // Helper Methods
////////////////////////////////// //////////////////////////////////
_IsBot( entity ) NotImplementedFunction( a, b, c, d, e, f )
{ {
// there already is a cgame function exists as "IsBot", for IW4, but unsure what all titles have it defined, LogWarning( "Function not implemented" );
// so we are defining it here if ( IsDefined ( a ) )
return IsDefined( entity.pers["isBot"] ) && entity.pers["isBot"]; {
LogWarning( a );
}
} }
_SetDvarIfUninitialized( dvarName, dvarValue ) _SetDvarIfUninitialized( dvarName, dvarValue )
@ -200,9 +127,22 @@ _SetDvarIfUninitialized( dvarName, dvarValue )
[[level.overrideMethods[level.commonFunctions.setDvar]]]( dvarName, dvarValue ); [[level.overrideMethods[level.commonFunctions.setDvar]]]( dvarName, dvarValue );
} }
NotImplementedFunction( a, b, c, d, e, f ) _GetPlayerFromClientNum( clientNum )
{ {
LogWarning( "Function not implemented" ); if ( clientNum < 0 )
{
return undefined;
}
for ( i = 0; i < level.players.size; i++ )
{
if ( level.players[i] getEntityNumber() == clientNum )
{
return level.players[i];
}
}
return undefined;
} }
// Not every game can output to console or even game log. // Not every game can output to console or even game log.
@ -285,13 +225,13 @@ RegisterLogger( logger )
RequestClientMeta( metaKey ) RequestClientMeta( metaKey )
{ {
getClientMetaEvent = BuildEventRequest( true, level.eventTypes.clientDataRequested, "Meta", self, metaKey ); getClientMetaEvent = BuildEventRequest( true, level.eventTypes.clientDataRequested, "Meta", self, metaKey );
level thread QueueEvent( getClientMetaEvent, level.eventTypes.clientDataRequested, self ); thread QueueEvent( getClientMetaEvent, level.eventTypes.clientDataRequested, self );
} }
RequestClientBasicData() RequestClientBasicData()
{ {
getClientDataEvent = BuildEventRequest( true, level.eventTypes.clientDataRequested, "None", self, "" ); getClientDataEvent = BuildEventRequest( true, level.eventTypes.clientDataRequested, "None", self, "" );
level thread QueueEvent( getClientDataEvent, level.eventTypes.clientDataRequested, self ); thread QueueEvent( getClientDataEvent, level.eventTypes.clientDataRequested, self );
} }
IncrementClientMeta( metaKey, incrementValue, clientId ) IncrementClientMeta( metaKey, incrementValue, clientId )
@ -326,7 +266,7 @@ SetClientMeta( metaKey, metaValue, clientId, direction )
} }
setClientMetaEvent = BuildEventRequest( true, level.eventTypes.setClientDataRequested, "Meta", clientNumber, data ); setClientMetaEvent = BuildEventRequest( true, level.eventTypes.setClientDataRequested, "Meta", clientNumber, data );
level thread QueueEvent( setClientMetaEvent, level.eventTypes.setClientDataRequested, self ); thread QueueEvent( setClientMetaEvent, level.eventTypes.setClientDataRequested, self );
} }
BuildEventRequest( responseExpected, eventType, eventSubtype, entOrId, data ) BuildEventRequest( responseExpected, eventType, eventSubtype, entOrId, data )
@ -359,7 +299,7 @@ BuildEventRequest( responseExpected, eventType, eventSubtype, entOrId, data )
MonitorBus() MonitorBus()
{ {
level endon( "game_ended" ); level endon( level.eventTypes.gameEnd );
for( ;; ) for( ;; )
{ {
@ -387,7 +327,7 @@ MonitorBus()
QueueEvent( request, eventType, notifyEntity ) QueueEvent( request, eventType, notifyEntity )
{ {
level endon( "game_ended" ); level endon( level.eventTypes.gameEnd );
start = GetTime(); start = GetTime();
maxWait = level.eventBus.timeout * 1000; // 30 seconds maxWait = level.eventBus.timeout * 1000; // 30 seconds
@ -395,7 +335,7 @@ QueueEvent( request, eventType, notifyEntity )
while ( GetDvar( level.eventBus.inVar ) != "" && ( GetTime() - start ) < maxWait ) while ( GetDvar( level.eventBus.inVar ) != "" && ( GetTime() - start ) < maxWait )
{ {
level [[level.overrideMethods["waittill_notify_or_timeout"]]]( "bus_ready", 1 ); level [[level.overrideMethods[level.commonFunctions.waittillNotifyOrTimeout]]]( "bus_ready", 1 );
if ( GetDvar( level.eventBus.inVar ) != "" ) if ( GetDvar( level.eventBus.inVar ) != "" )
{ {
@ -541,7 +481,7 @@ OnClientDataReceived( event )
metaKey = event.data[0]; metaKey = event.data[0];
clientData.meta[metaKey] = event.data[metaKey]; clientData.meta[metaKey] = event.data[metaKey];
LogDebug( "Meta Key=" + metaKey + ", Meta Value=" + event.data[metaKey] ); LogDebug( "Meta Key=" + CoerceUndefined( metaKey ) + ", Meta Value=" + CoerceUndefined( event.data[metaKey] ) );
return; return;
} }
@ -553,8 +493,6 @@ OnClientDataReceived( event )
clientData.performance = event.data["performance"]; clientData.performance = event.data["performance"];
clientData.state = "complete"; clientData.state = "complete";
self.persistentClientId = event.data["clientId"]; self.persistentClientId = event.data["clientId"];
self thread DisplayWelcomeData();
} }
OnExecuteCommand( event ) OnExecuteCommand( event )
@ -590,5 +528,15 @@ OnExecuteCommand( event )
OnSetClientDataCompleted( event ) OnSetClientDataCompleted( event )
{ {
// IW4MAdmin let us know it persisted (success or fail) // IW4MAdmin let us know it persisted (success or fail)
LogDebug( "Set Client Data -> subtype = " + event.subType + " status = " + event.data["status"] ); LogDebug( "Set Client Data -> subtype = " + CoerceUndefined( event.subType ) + ", status = " + CoerceUndefined( event.data["status"] ) );
}
CoerceUndefined( object )
{
if ( !IsDefined( object ) )
{
return "undefined";
}
return object;
} }

View File

@ -8,18 +8,17 @@ Init()
Setup() Setup()
{ {
level endon( "game_ended" ); level endon( "game_ended" );
waittillframeend;
// it's possible that the notify type has not been defined yet so we have to hard code it level waittill( level.notifyTypes.sharedFunctionsInitialized );
level waittill( "SharedFunctionsInitialized" );
level.eventBus.gamename = "IW4"; level.eventBus.gamename = "IW4";
scripts\_integration_base::RegisterLogger( ::Log2Console ); scripts\_integration_base::RegisterLogger( ::Log2Console );
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired; level.overrideMethods[level.commonFunctions.getTotalShotsFired] = ::GetTotalShotsFired;
level.overrideMethods[level.commonFunctions.setDvar] = ::_SetDvarIfUninitialized; level.overrideMethods[level.commonFunctions.setDvar] = ::SetDvarIfUninitializedWrapper;
level.overrideMethods[level.commonFunctions.isBot] = ::IsTestClient; level.overrideMethods[level.commonFunctions.isBot] = ::IsBotWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID; level.overrideMethods[level.commonFunctions.getXuid] = ::GetXuidWrapper;
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout;
level.overrideMethods[level.commonFunctions.changeTeam] = ::ChangeTeam; level.overrideMethods[level.commonFunctions.changeTeam] = ::ChangeTeam;
level.overrideMethods[level.commonFunctions.getTeamCounts] = ::CountPlayers; level.overrideMethods[level.commonFunctions.getTeamCounts] = ::CountPlayers;
level.overrideMethods[level.commonFunctions.getMaxClients] = ::GetMaxClients; level.overrideMethods[level.commonFunctions.getMaxClients] = ::GetMaxClients;
@ -28,19 +27,18 @@ Setup()
level.overrideMethods[level.commonFunctions.getClientKillStreak] = ::GetClientKillStreak; level.overrideMethods[level.commonFunctions.getClientKillStreak] = ::GetClientKillStreak;
level.overrideMethods[level.commonFunctions.backupRestoreClientKillStreakData] = ::BackupRestoreClientKillStreakData; level.overrideMethods[level.commonFunctions.backupRestoreClientKillStreakData] = ::BackupRestoreClientKillStreakData;
level.overrideMethods[level.commonFunctions.waitTillAnyTimeout] = ::WaitTillAnyTimeout; level.overrideMethods[level.commonFunctions.waitTillAnyTimeout] = ::WaitTillAnyTimeout;
level.overrideMethods[level.commonFunctions.waittillNotifyOrTimeout] = ::WaitillNotifyOrTimeoutWrapper;
RegisterClientCommands(); RegisterClientCommands();
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
level notify( level.notifyTypes.gameFunctionsInitialized ); level notify( level.notifyTypes.gameFunctionsInitialized );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 ) if ( GetDvarInt( level.commonKeys.enabled ) != 1 )
{ {
return; return;
} }
level thread OnPlayerConnect(); thread OnPlayerConnect();
} }
OnPlayerConnect() OnPlayerConnect()
@ -51,7 +49,7 @@ OnPlayerConnect()
{ {
level waittill( "connected", player ); level waittill( "connected", player );
if ( player call [[ level.overrideMethods[ level.commonFunctions.isBot ] ]]() ) if ( player IsTestClient() )
{ {
// we don't want to track bots // we don't want to track bots
continue; continue;
@ -186,12 +184,7 @@ GetTotalShotsFired()
return maps\mp\_utility::getPlayerStat( "mostshotsfired" ); return maps\mp\_utility::getPlayerStat( "mostshotsfired" );
} }
_SetDvarIfUninitialized( dvar, value ) WaitillNotifyOrTimeoutWrapper( _notify, timeout )
{
SetDvarIfUninitialized( dvar, value );
}
_waittill_notify_or_timeout( _notify, timeout )
{ {
common_scripts\utility::waittill_notify_or_timeout( _notify, timeout ); common_scripts\utility::waittill_notify_or_timeout( _notify, timeout );
} }
@ -201,11 +194,21 @@ Log2Console( logLevel, message )
PrintConsole( "[" + logLevel + "] " + message + "\n" ); PrintConsole( "[" + logLevel + "] " + message + "\n" );
} }
_GetXUID() SetDvarIfUninitializedWrapper( dvar, value )
{
SetDvarIfUninitialized( dvar, value );
}
GetXuidWrapper()
{ {
return self GetXUID(); return self GetXUID();
} }
IsBotWrapper( client )
{
return client IsTestClient();
}
////////////////////////////////// //////////////////////////////////
// GUID helpers // GUID helpers
///////////////////////////////// /////////////////////////////////
@ -519,11 +522,7 @@ HideImpl()
AlertImpl( event, data ) AlertImpl( event, data )
{ {
if ( level.eventBus.gamename == "IW4" ) self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], "compass_waypoint_target", ( 1, 0, 0 ), "ui_mp_nukebomb_timer", 7.5 );
{
self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], "compass_waypoint_target", ( 1, 0, 0 ), "ui_mp_nukebomb_timer", 7.5 );
}
return "Sent alert to " + self.name; return "Sent alert to " + self.name;
} }

View File

@ -8,50 +8,22 @@ Init()
Setup() Setup()
{ {
level endon( "game_ended" ); level endon( "game_ended" );
waittillframeend;
// it's possible that the notify type has not been defined yet so we have to hard code it level waittill( level.notifyTypes.sharedFunctionsInitialized );
level waittill( "SharedFunctionsInitialized" );
level.eventBus.gamename = "IW5"; level.eventBus.gamename = "IW5";
scripts\_integration_base::RegisterLogger( ::Log2Console ); scripts\_integration_base::RegisterLogger( ::Log2Console );
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired; level.overrideMethods[level.commonFunctions.getTotalShotsFired] = ::GetTotalShotsFired;
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized; level.overrideMethods[level.commonFunctions.setDvar] = ::SetDvarIfUninitializedWrapper;
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout; level.overrideMethods[level.commonFunctions.waittillNotifyOrTimeout] = ::WaitillNotifyOrTimeoutWrapper;
level.overrideMethods[level.commonFunctions.isBot] = ::IsTestClient; level.overrideMethods[level.commonFunctions.isBot] = ::IsBotWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID; level.overrideMethods[level.commonFunctions.getXuid] = ::GetXuidWrapper;
RegisterClientCommands(); RegisterClientCommands();
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
level notify( level.notifyTypes.gameFunctionsInitialized ); level notify( level.notifyTypes.gameFunctionsInitialized );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
{
return;
}
level thread OnPlayerConnect();
}
OnPlayerConnect()
{
level endon ( "game_ended" );
for ( ;; )
{
level waittill( "connected", player );
if ( player call [[ level.overrideMethods[ level.commonFunctions.isBot ] ]]() )
{
// we don't want to track bots
continue;
}
player thread SetPersistentData();
player thread WaitForClientEvents();
}
} }
RegisterClientCommands() RegisterClientCommands()
@ -69,39 +41,17 @@ RegisterClientCommands()
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl ); scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
} }
WaitForClientEvents()
{
self endon( "disconnect" );
// example of requesting a meta value
lastServerMetaKey = "LastServerPlayed";
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
for ( ;; )
{
self waittill( level.eventTypes.localClientEvent, event );
scripts\_integration_base::LogDebug( "Received client event " + event.type );
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
{
clientData = self.pers[level.clientDataKey];
lastServerPlayed = clientData.meta[lastServerMetaKey];
}
}
}
GetTotalShotsFired() GetTotalShotsFired()
{ {
return maps\mp\_utility::getPlayerStat( "mostshotsfired" ); return maps\mp\_utility::getPlayerStat( "mostshotsfired" );
} }
_SetDvarIfUninitialized( dvar, value ) SetDvarIfUninitializedWrapper( dvar, value )
{ {
SetDvarIfUninitialized( dvar, value ); SetDvarIfUninitialized( dvar, value );
} }
_waittill_notify_or_timeout( _notify, timeout ) WaitillNotifyOrTimeoutWrapper( _notify, timeout )
{ {
common_scripts\utility::waittill_notify_or_timeout( _notify, timeout ); common_scripts\utility::waittill_notify_or_timeout( _notify, timeout );
} }
@ -111,142 +61,16 @@ Log2Console( logLevel, message )
Print( "[" + logLevel + "] " + message + "\n" ); Print( "[" + logLevel + "] " + message + "\n" );
} }
_GetXUID() IsBotWrapper( client )
{
return client IsTestClient();
}
GetXuidWrapper()
{ {
return self GetXUID(); return self GetXUID();
} }
//////////////////////////////////
// GUID helpers
/////////////////////////////////
SetPersistentData()
{
self endon( "disconnect" );
guidHigh = self GetPlayerData( "bests", "none" );
guidLow = self GetPlayerData( "awards", "none" );
persistentGuid = guidHigh + "," + guidLow;
guidIsStored = guidHigh != 0 && guidLow != 0;
if ( guidIsStored )
{
// give IW4MAdmin time to collect IP
wait( 15 );
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
return;
}
guid = self SplitGuid();
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
self SetPlayerData( "bests", "none", guid["high"] );
self SetPlayerData( "awards", "none", guid["low"] );
}
SplitGuid()
{
guid = self GetGuid();
if ( isDefined( self.guid ) )
{
guid = self.guid;
}
firstPart = 0;
secondPart = 0;
stringLength = 17;
firstPartExp = 0;
secondPartExp = 0;
for ( i = stringLength - 1; i > 0; i-- )
{
char = GetSubStr( guid, i - 1, i );
if ( char == "" )
{
char = "0";
}
if ( i > stringLength / 2 )
{
value = GetIntForHexChar( char );
power = Pow( 16, secondPartExp );
secondPart = secondPart + ( value * power );
secondPartExp++;
}
else
{
value = GetIntForHexChar( char );
power = Pow( 16, firstPartExp );
firstPart = firstPart + ( value * power );
firstPartExp++;
}
}
split = [];
split["low"] = int( secondPart );
split["high"] = int( firstPart );
return split;
}
Pow( num, exponent )
{
result = 1;
while( exponent != 0 )
{
result = result * num;
exponent--;
}
return result;
}
GetIntForHexChar( char )
{
char = ToLower( char );
// generated by co-pilot because I can't be bothered to make it more "elegant"
switch( char )
{
case "0":
return 0;
case "1":
return 1;
case "2":
return 2;
case "3":
return 3;
case "4":
return 4;
case "5":
return 5;
case "6":
return 6;
case "7":
return 7;
case "8":
return 8;
case "9":
return 9;
case "a":
return 10;
case "b":
return 11;
case "c":
return 12;
case "d":
return 13;
case "e":
return 14;
case "f":
return 15;
default:
return 0;
}
}
////////////////////////////////// //////////////////////////////////
// Command Implementations // Command Implementations
///////////////////////////////// /////////////////////////////////
@ -427,10 +251,7 @@ HideImpl()
AlertImpl( event, data ) AlertImpl( event, data )
{ {
if ( level.eventBus.gamename == "IW5" ) { self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "ui_mp_nukebomb_timer", 7.5 );
self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "ui_mp_nukebomb_timer", 7.5 );
}
return "Sent alert to " + self.name; return "Sent alert to " + self.name;
} }

View File

@ -1,4 +1,3 @@
Init() Init()
{ {
thread Setup(); thread Setup();
@ -6,10 +5,10 @@ Init()
Setup() Setup()
{ {
wait ( 0.05 );
level endon( "game_ended" ); level endon( "game_ended" );
// it's possible that the notify type has not been defined yet so we have to hard code it level waittill( level.notifyTypes.integrationBootstrapInitialized );
level waittill( "IntegrationBootstrapInitialized" );
level.commonFunctions.changeTeam = "ChangeTeam"; level.commonFunctions.changeTeam = "ChangeTeam";
level.commonFunctions.getTeamCounts = "GetTeamCounts"; level.commonFunctions.getTeamCounts = "GetTeamCounts";
@ -18,7 +17,10 @@ Setup()
level.commonFunctions.getClientTeam = "GetClientTeam"; level.commonFunctions.getClientTeam = "GetClientTeam";
level.commonFunctions.getClientKillStreak = "GetClientKillStreak"; level.commonFunctions.getClientKillStreak = "GetClientKillStreak";
level.commonFunctions.backupRestoreClientKillStreakData = "BackupRestoreClientKillStreakData"; level.commonFunctions.backupRestoreClientKillStreakData = "BackupRestoreClientKillStreakData";
level.commonFunctions.getTotalShotsFired = "GetTotalShotsFired";
level.commonFunctions.waitTillAnyTimeout = "WaitTillAnyTimeout"; level.commonFunctions.waitTillAnyTimeout = "WaitTillAnyTimeout";
level.commonFunctions.isBot = "IsBot";
level.commonFunctions.getXuid = "GetXuid";
level.overrideMethods[level.commonFunctions.changeTeam] = scripts\_integration_base::NotImplementedFunction; level.overrideMethods[level.commonFunctions.changeTeam] = scripts\_integration_base::NotImplementedFunction;
level.overrideMethods[level.commonFunctions.getTeamCounts] = scripts\_integration_base::NotImplementedFunction; level.overrideMethods[level.commonFunctions.getTeamCounts] = scripts\_integration_base::NotImplementedFunction;
@ -28,16 +30,19 @@ Setup()
level.overrideMethods[level.commonFunctions.getClientKillStreak] = scripts\_integration_base::NotImplementedFunction; level.overrideMethods[level.commonFunctions.getClientKillStreak] = scripts\_integration_base::NotImplementedFunction;
level.overrideMethods[level.commonFunctions.backupRestoreClientKillStreakData] = scripts\_integration_base::NotImplementedFunction; level.overrideMethods[level.commonFunctions.backupRestoreClientKillStreakData] = scripts\_integration_base::NotImplementedFunction;
level.overrideMethods[level.commonFunctions.waitTillAnyTimeout] = scripts\_integration_base::NotImplementedFunction; level.overrideMethods[level.commonFunctions.waitTillAnyTimeout] = scripts\_integration_base::NotImplementedFunction;
level.overrideMethods["GetPlayerFromClientNum"] = ::GetPlayerFromClientNum; level.overrideMethods[level.commonFunctions.getXuid] = scripts\_integration_base::NotImplementedFunction;
level.overrideMethods[level.commonFunctions.isBot] = scripts\_integration_base::NotImplementedFunction;
// these can be overridden per game if needed // these can be overridden per game if needed
level.commonKeys.team1 = "allies"; level.commonKeys.team1 = "allies";
level.commonKeys.team2 = "axis"; level.commonKeys.team2 = "axis";
level.commonKeys.teamSpectator = "spectator"; level.commonKeys.teamSpectator = "spectator";
level.commonKeys.autoBalance = "sv_iw4madmin_autobalance";
level.eventTypes.connect = "connected"; level.eventTypes.connect = "connected";
level.eventTypes.disconnect = "disconnect"; level.eventTypes.disconnect = "disconnect";
level.eventTypes.joinTeam = "joined_team"; level.eventTypes.joinTeam = "joined_team";
level.eventTypes.joinSpec = "joined_spectators";
level.eventTypes.spawned = "spawned_player"; level.eventTypes.spawned = "spawned_player";
level.eventTypes.gameEnd = "game_ended"; level.eventTypes.gameEnd = "game_ended";
@ -45,13 +50,20 @@ Setup()
level notify( level.notifyTypes.sharedFunctionsInitialized ); level notify( level.notifyTypes.sharedFunctionsInitialized );
level waittill( level.notifyTypes.gameFunctionsInitialized ); level waittill( level.notifyTypes.gameFunctionsInitialized );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 ) scripts\_integration_base::_SetDvarIfUninitialized( level.commonKeys.autoBalance, 0 );
if ( GetDvarInt( level.commonKeys.enabled ) != 1 )
{ {
return; return;
} }
level thread OnPlayerConnect(); thread OnPlayerConnect();
}
_IsBot( player )
{
return [[level.overrideMethods[level.commonFunctions.isBot]]]( player );
} }
OnPlayerConnect() OnPlayerConnect()
@ -62,17 +74,23 @@ OnPlayerConnect()
{ {
level waittill( level.eventTypes.connect, player ); level waittill( level.eventTypes.connect, player );
if ( scripts\_integration_base::_IsBot( player ) ) if ( _IsBot( player ) )
{ {
// we don't want to track bots // we don't want to track bots
continue; continue;
} }
if ( !IsDefined( player.pers[level.clientDataKey] ) )
{
player.pers[level.clientDataKey] = spawnstruct();
}
player thread OnPlayerSpawned();
player thread OnPlayerJoinedTeam(); player thread OnPlayerJoinedTeam();
player thread OnPlayerJoinedSpectators(); player thread OnPlayerJoinedSpectators();
player thread PlayerTrackingOnInterval(); player thread PlayerTrackingOnInterval();
if ( GetDvarInt( "sv_iw4madmin_autobalance" ) != 1 || !IsDefined( [[level.overrideMethods[level.commonFunctions.getTeamBased]]]() ) ) if ( GetDvarInt( level.commonKeys.autoBalance ) != 1 || !IsDefined( [[level.overrideMethods[level.commonFunctions.getTeamBased]]]() ) )
{ {
continue; continue;
} }
@ -85,13 +103,91 @@ OnPlayerConnect()
teamToJoin = player GetTeamToJoin(); teamToJoin = player GetTeamToJoin();
player [[level.overrideMethods[level.commonFunctions.changeTeam]]]( teamToJoin ); player [[level.overrideMethods[level.commonFunctions.changeTeam]]]( teamToJoin );
player thread OnClientFirstSpawn(); player thread OnPlayerFirstSpawn();
player thread OnClientJoinedTeam(); player thread OnPlayerDisconnect();
player thread OnClientDisconnect();
} }
} }
OnClientDisconnect() PlayerSpawnEvents()
{
self endon( level.eventTypes.disconnect );
clientData = self.pers[level.clientDataKey];
// this gives IW4MAdmin some time to register the player before making the request;
// although probably not necessary some users might have a slow database or poll rate
wait ( 2 );
if ( IsDefined( clientData.state ) && clientData.state == "complete" )
{
return;
}
self scripts\_integration_base::RequestClientBasicData();
self waittill( level.eventTypes.clientDataReceived, clientEvent );
if ( clientData.permissionLevel == "User" || clientData.permissionLevel == "Flagged" )
{
return;
}
self IPrintLnBold( "Welcome, your level is ^5" + clientData.permissionLevel );
wait( 2.0 );
self IPrintLnBold( "You were last seen ^5" + clientData.lastConnection );
}
PlayerTrackingOnInterval()
{
self endon( level.eventTypes.disconnect );
for ( ;; )
{
wait ( 120 );
if ( IsAlive( self ) )
{
self SaveTrackingMetrics();
}
}
}
SaveTrackingMetrics()
{
if ( !IsDefined( self.persistentClientId ) )
{
return;
}
scripts\_integration_base::LogDebug( "Saving tracking metrics for " + self.persistentClientId );
if ( !IsDefined( self.lastShotCount ) )
{
self.lastShotCount = 0;
}
currentShotCount = self [[level.overrideMethods["GetTotalShotsFired"]]]();
change = currentShotCount - self.lastShotCount;
self.lastShotCount = currentShotCount;
scripts\_integration_base::LogDebug( "Total Shots Fired increased by " + change );
if ( !IsDefined( change ) )
{
change = 0;
}
if ( change == 0 )
{
return;
}
scripts\_integration_base::IncrementClientMeta( "TotalShotsFired", change, self.persistentClientId );
}
// #region team balance
OnPlayerDisconnect()
{ {
level endon( level.eventTypes.gameEnd ); level endon( level.eventTypes.gameEnd );
self endon( "disconnect_logic_end" ); self endon( "disconnect_logic_end" );
@ -106,7 +202,7 @@ OnClientDisconnect()
} }
} }
OnClientJoinedTeam() OnPlayerJoinedTeam()
{ {
self endon( level.eventTypes.disconnect ); self endon( level.eventTypes.disconnect );
@ -114,6 +210,14 @@ OnClientJoinedTeam()
{ {
self waittill( level.eventTypes.joinTeam ); self waittill( level.eventTypes.joinTeam );
wait( 0.25 );
LogPrint( GenerateJoinTeamString( false ) );
if ( GetDvarInt( level.commonKeys.autoBalance ) != 1 )
{
continue;
}
if ( IsDefined( self.wasAutoBalanced ) && self.wasAutoBalanced ) if ( IsDefined( self.wasAutoBalanced ) && self.wasAutoBalanced )
{ {
self.wasAutoBalanced = false; self.wasAutoBalanced = false;
@ -141,12 +245,34 @@ OnClientJoinedTeam()
} }
} }
OnClientFirstSpawn() OnPlayerSpawned()
{
self endon( level.eventTypes.disconnect );
for ( ;; )
{
self waittill( level.eventTypes.spawned );
self thread PlayerSpawnEvents();
}
}
OnPlayerJoinedSpectators()
{
self endon( level.eventTypes.disconnect );
for( ;; )
{
self waittill( level.eventTypes.joinSpec );
LogPrint( GenerateJoinTeamString( true ) );
}
}
OnPlayerFirstSpawn()
{ {
self endon( level.eventTypes.disconnect ); self endon( level.eventTypes.disconnect );
timeoutResult = self [[level.overrideMethods[level.commonFunctions.waitTillAnyTimeout]]]( 30, level.eventTypes.spawned ); timeoutResult = self [[level.overrideMethods[level.commonFunctions.waitTillAnyTimeout]]]( 30, level.eventTypes.spawned );
if ( timeoutResult != "timeout" ) if ( timeoutResult != level.eventBus.timeoutKey )
{ {
return; return;
} }
@ -467,48 +593,6 @@ GetClientPerformanceOrDefault()
return performance; return performance;
} }
GetPlayerFromClientNum( clientNum )
{
if ( clientNum < 0 )
{
return undefined;
}
for ( i = 0; i < level.players.size; i++ )
{
if ( level.players[i] getEntityNumber() == clientNum )
{
return level.players[i];
}
}
return undefined;
}
OnPlayerJoinedTeam()
{
self endon( "disconnect" );
for( ;; )
{
self waittill( "joined_team" );
// join spec and join team occur at the same moment - out of order logging would be problematic
wait( 0.25 );
LogPrint( GenerateJoinTeamString( false ) );
}
}
OnPlayerJoinedSpectators()
{
self endon( "disconnect" );
for( ;; )
{
self waittill( "joined_spectators" );
LogPrint( GenerateJoinTeamString( true ) );
}
}
GenerateJoinTeamString( isSpectator ) GenerateJoinTeamString( isSpectator )
{ {
team = self.team; team = self.team;
@ -540,49 +624,4 @@ GenerateJoinTeamString( isSpectator )
return "JT;" + guid + ";" + self getEntityNumber() + ";" + team + ";" + self.name + "\n"; return "JT;" + guid + ";" + self getEntityNumber() + ";" + team + ";" + self.name + "\n";
} }
PlayerTrackingOnInterval() // #end region
{
self endon( "disconnect" );
for ( ;; )
{
wait ( 120 );
if ( IsAlive( self ) )
{
self SaveTrackingMetrics();
}
}
}
SaveTrackingMetrics()
{
if ( !IsDefined( self.persistentClientId ) )
{
return;
}
scripts\_integration_base::LogDebug( "Saving tracking metrics for " + self.persistentClientId );
if ( !IsDefined( self.lastShotCount ) )
{
self.lastShotCount = 0;
}
currentShotCount = self [[level.overrideMethods["GetTotalShotsFired"]]]();
change = currentShotCount - self.lastShotCount;
self.lastShotCount = currentShotCount;
scripts\_integration_base::LogDebug( "Total Shots Fired increased by " + change );
if ( !IsDefined( change ) )
{
change = 0;
}
if ( change == 0 )
{
return;
}
scripts\_integration_base::IncrementClientMeta( "TotalShotsFired", change, self.persistentClientId );
}

View File

@ -8,49 +8,22 @@ Init()
Setup() Setup()
{ {
level endon( "game_ended" ); level endon( "game_ended" );
waittillframeend;
// it's possible that the notify type has not been defined yet so we have to hard code it level waittill( level.notifyTypes.sharedFunctionsInitialized );
level waittill( "SharedFunctionsInitialized" );
level.eventBus.gamename = "T5"; level.eventBus.gamename = "T5";
scripts\_integration_base::RegisterLogger( ::Log2Console ); scripts\_integration_base::RegisterLogger( ::Log2Console );
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired; level.overrideMethods[level.commonFunctions.getTotalShotsFired] = ::GetTotalShotsFired;
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized; level.overrideMethods[level.commonFunctions.setDvar] = ::SetDvarIfUninitializedWrapper;
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout; level.overrideMethods[level.commonFunctions.waittillNotifyOrTimeout] = ::WaitillNotifyOrTimeoutWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID; level.overrideMethods[level.commonFunctions.isBot] = ::IsBotWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::GetXuidWrapper;
RegisterClientCommands(); RegisterClientCommands();
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
level notify( level.notifyTypes.gameFunctionsInitialized ); level notify( level.notifyTypes.gameFunctionsInitialized );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
{
return;
}
level thread OnPlayerConnect();
}
OnPlayerConnect()
{
level endon ( "game_ended" );
for ( ;; )
{
level waittill( "connected", player );
if ( scripts\_integration_base::_IsBot( player ) )
{
// we don't want to track bots
continue;
}
//player thread SetPersistentData();
player thread WaitForClientEvents();
}
} }
RegisterClientCommands() RegisterClientCommands()
@ -68,39 +41,17 @@ RegisterClientCommands()
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl ); scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
} }
WaitForClientEvents()
{
self endon( "disconnect" );
// example of requesting a meta value
lastServerMetaKey = "LastServerPlayed";
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
for ( ;; )
{
self waittill( level.eventTypes.localClientEvent, event );
scripts\_integration_base::LogDebug( "Received client event " + event.type );
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
{
clientData = self.pers[level.clientDataKey];
lastServerPlayed = clientData.meta[lastServerMetaKey];
}
}
}
GetTotalShotsFired() GetTotalShotsFired()
{ {
return maps\mp\gametypes\_persistence::statGet( "total_shots" ); return maps\mp\gametypes\_persistence::statGet( "total_shots" );
} }
_SetDvarIfUninitialized(dvar, value) SetDvarIfUninitializedWrapper( dvar, value )
{ {
maps\mp\_utility::set_dvar_if_unset(dvar, value); maps\mp\_utility::set_dvar_if_unset( dvar, value );
} }
_waittill_notify_or_timeout( msg, timer ) WaitillNotifyOrTimeoutWrapper( msg, timer )
{ {
self endon( msg ); self endon( msg );
wait( timer ); wait( timer );
@ -113,7 +64,6 @@ Log2Console( logLevel, message )
God() God()
{ {
if ( !IsDefined( self.godmode ) ) if ( !IsDefined( self.godmode ) )
{ {
self.godmode = false; self.godmode = false;
@ -131,142 +81,16 @@ God()
} }
} }
_GetXUID() IsBotWrapper( client )
{
return client maps\mp\_utility::is_bot();
}
GetXuidWrapper()
{ {
return self GetXUID(); return self GetXUID();
} }
//////////////////////////////////
// GUID helpers
/////////////////////////////////
/*SetPersistentData()
{
self endon( "disconnect" );
guidHigh = self GetPlayerData( "bests", "none" );
guidLow = self GetPlayerData( "awards", "none" );
persistentGuid = guidHigh + "," + guidLow;
guidIsStored = guidHigh != 0 && guidLow != 0;
if ( guidIsStored )
{
// give IW4MAdmin time to collect IP
wait( 15 );
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
return;
}
guid = self SplitGuid();
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
self SetPlayerData( "bests", "none", guid["high"] );
self SetPlayerData( "awards", "none", guid["low"] );
}
SplitGuid()
{
guid = self GetGuid();
if ( isDefined( self.guid ) )
{
guid = self.guid;
}
firstPart = 0;
secondPart = 0;
stringLength = 17;
firstPartExp = 0;
secondPartExp = 0;
for ( i = stringLength - 1; i > 0; i-- )
{
char = GetSubStr( guid, i - 1, i );
if ( char == "" )
{
char = "0";
}
if ( i > stringLength / 2 )
{
value = GetIntForHexChar( char );
power = Pow( 16, secondPartExp );
secondPart = secondPart + ( value * power );
secondPartExp++;
}
else
{
value = GetIntForHexChar( char );
power = Pow( 16, firstPartExp );
firstPart = firstPart + ( value * power );
firstPartExp++;
}
}
split = [];
split["low"] = int( secondPart );
split["high"] = int( firstPart );
return split;
}
Pow( num, exponent )
{
result = 1;
while( exponent != 0 )
{
result = result * num;
exponent--;
}
return result;
}
GetIntForHexChar( char )
{
char = ToLower( char );
// generated by co-pilot because I can't be bothered to make it more "elegant"
switch( char )
{
case "0":
return 0;
case "1":
return 1;
case "2":
return 2;
case "3":
return 3;
case "4":
return 4;
case "5":
return 5;
case "6":
return 6;
case "7":
return 7;
case "8":
return 8;
case "9":
return 9;
case "a":
return 10;
case "b":
return 11;
case "c":
return 12;
case "d":
return 13;
case "e":
return 14;
case "f":
return 15;
default:
return 0;
}
}*/
////////////////////////////////// //////////////////////////////////
// Command Implementations // Command Implementations
///////////////////////////////// /////////////////////////////////

View File

@ -9,48 +9,21 @@ Setup()
{ {
level endon( "game_ended" ); level endon( "game_ended" );
// it's possible that the notify type has not been defined yet so we have to hard code it level waittill( level.notifyTypes.sharedFunctionsInitialized );
level waittill( "SharedFunctionsInitialized" );
level.eventBus.gamename = "T5"; level.eventBus.gamename = "T5";
scripts\_integration_base::RegisterLogger( ::Log2Console ); scripts\_integration_base::RegisterLogger( ::Log2Console );
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired; level.overrideMethods[level.commonFunctions.getTotalShotsFired] = ::GetTotalShotsFired;
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized; level.overrideMethods[level.commonFunctions.setDvar] = ::SetDvarIfUninitializedWrapper;
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout; level.overrideMethods[level.commonFunctions.waittillNotifyOrTimeout] = ::WaitillNotifyOrTimeoutWrapper;
level.overrideMethods["GetPlayerFromClientNum"] = ::_GetPlayerFromClientNum; level.overrideMethods[level.commonFunctions.isBot] = ::IsBotWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::GetXuidWrapper;
level.overrideMethods[level.commonFunction.getPlayerFromClientNum] = ::_GetPlayerFromClientNum;
RegisterClientCommands(); RegisterClientCommands();
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
level notify( level.notifyTypes.gameFunctionsInitialized ); level notify( level.notifyTypes.gameFunctionsInitialized );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
{
return;
}
level thread OnPlayerConnect();
}
OnPlayerConnect()
{
level endon ( "game_ended" );
for ( ;; )
{
level waittill( "connected", player );
if ( scripts\_integration_base::_IsBot( player ) )
{
// we don't want to track bots
continue;
}
//player thread SetPersistentData();
player thread WaitForClientEvents();
}
} }
RegisterClientCommands() RegisterClientCommands()
@ -68,45 +41,23 @@ RegisterClientCommands()
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl ); scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
} }
WaitForClientEvents()
{
self endon( "disconnect" );
// example of requesting a meta value
lastServerMetaKey = "LastServerPlayed";
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
for ( ;; )
{
self waittill( level.eventTypes.localClientEvent, event );
scripts\_integration_base::LogDebug( "Received client event " + event.type );
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
{
clientData = self.pers[level.clientDataKey];
lastServerPlayed = clientData.meta[lastServerMetaKey];
}
}
}
GetTotalShotsFired() GetTotalShotsFired()
{ {
return 0; //ZM has no shot tracking. TODO: add tracking function for event weapon_fired return 0; //ZM has no shot tracking. TODO: add tracking function for event weapon_fired
} }
_SetDvarIfUninitialized(dvar, value) SetDvarIfUninitializedWrapper( dvar, value )
{ {
if (GetDvar(dvar)=="" ) if ( GetDvar( dvar ) == "" )
{ {
SetDvar(dvar, value); SetDvar( dvar, value );
return value; return value;
} }
return GetDvar(dvar); return GetDvar( dvar );
} }
_waittill_notify_or_timeout( msg, timer ) WaitillNotifyOrTimeoutWrapper( msg, timer )
{ {
self endon( msg ); self endon( msg );
wait( timer ); wait( timer );
@ -119,7 +70,6 @@ Log2Console( logLevel, message )
God() God()
{ {
if ( !IsDefined( self.godmode ) ) if ( !IsDefined( self.godmode ) )
{ {
self.godmode = false; self.godmode = false;
@ -137,6 +87,16 @@ God()
} }
} }
IsBotWrapper( client )
{
return ( IsDefined ( client.pers["isBot"] ) && client.pers["isBot"] != 0 );
}
GetXuidWrapper()
{
return self GetXUID();
}
_GetPlayerFromClientNum( clientNum ) _GetPlayerFromClientNum( clientNum )
{ {
if ( clientNum < 0 ) if ( clientNum < 0 )
@ -148,7 +108,8 @@ _GetPlayerFromClientNum( clientNum )
for ( i = 0; i < players.size; i++ ) for ( i = 0; i < players.size; i++ )
{ {
scripts\_integration_base::LogDebug(i+"/"+players.size+ "=" + players[i].name); scripts\_integration_base::LogDebug( i+"/"+players.size+ "=" + players[i].name );
if ( players[i] getEntityNumber() == clientNum ) if ( players[i] getEntityNumber() == clientNum )
{ {
return players[i]; return players[i];
@ -158,137 +119,6 @@ _GetPlayerFromClientNum( clientNum )
return undefined; return undefined;
} }
//////////////////////////////////
// GUID helpers
/////////////////////////////////
/*SetPersistentData()
{
self endon( "disconnect" );
guidHigh = self GetPlayerData( "bests", "none" );
guidLow = self GetPlayerData( "awards", "none" );
persistentGuid = guidHigh + "," + guidLow;
guidIsStored = guidHigh != 0 && guidLow != 0;
if ( guidIsStored )
{
// give IW4MAdmin time to collect IP
wait( 15 );
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
return;
}
guid = self SplitGuid();
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
self SetPlayerData( "bests", "none", guid["high"] );
self SetPlayerData( "awards", "none", guid["low"] );
}
SplitGuid()
{
guid = self GetGuid();
if ( isDefined( self.guid ) )
{
guid = self.guid;
}
firstPart = 0;
secondPart = 0;
stringLength = 17;
firstPartExp = 0;
secondPartExp = 0;
for ( i = stringLength - 1; i > 0; i-- )
{
char = GetSubStr( guid, i - 1, i );
if ( char == "" )
{
char = "0";
}
if ( i > stringLength / 2 )
{
value = GetIntForHexChar( char );
power = Pow( 16, secondPartExp );
secondPart = secondPart + ( value * power );
secondPartExp++;
}
else
{
value = GetIntForHexChar( char );
power = Pow( 16, firstPartExp );
firstPart = firstPart + ( value * power );
firstPartExp++;
}
}
split = [];
split["low"] = int( secondPart );
split["high"] = int( firstPart );
return split;
}
Pow( num, exponent )
{
result = 1;
while( exponent != 0 )
{
result = result * num;
exponent--;
}
return result;
}
GetIntForHexChar( char )
{
char = ToLower( char );
// generated by co-pilot because I can't be bothered to make it more "elegant"
switch( char )
{
case "0":
return 0;
case "1":
return 1;
case "2":
return 2;
case "3":
return 3;
case "4":
return 4;
case "5":
return 5;
case "6":
return 6;
case "7":
return 7;
case "8":
return 8;
case "9":
return 9;
case "a":
return 10;
case "b":
return 11;
case "c":
return 12;
case "d":
return 13;
case "e":
return 14;
case "f":
return 15;
default:
return 0;
}
}*/
////////////////////////////////// //////////////////////////////////
// Command Implementations // Command Implementations
///////////////////////////////// /////////////////////////////////
@ -472,7 +302,7 @@ HideImpl( event, data )
AlertImpl( event, data ) AlertImpl( event, data )
{ {
//self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "mpl_sab_ui_suitcasebomb_timer", 7.5 ); //self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "mpl_sab_ui_suitcasebomb_timer", 7.5 );
self IPrintLnBold(data["message"]); self IPrintLnBold( data["message"] );
return "Sent alert to " + self.name; return "Sent alert to " + self.name;
} }

View File

@ -9,49 +9,22 @@ Init()
Setup() Setup()
{ {
level endon( "game_ended" ); level endon( "game_ended" );
waittillframeend;
// it's possible that the notify type has not been defined yet so we have to hard code it level waittill( level.notifyTypes.sharedFunctionsInitialized );
level waittill( "SharedFunctionsInitialized" );
level.eventBus.gamename = "T6"; level.eventBus.gamename = "T6";
scripts\_integration_base::RegisterLogger( ::Log2Console ); scripts\_integration_base::RegisterLogger( ::Log2Console );
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired; level.overrideMethods[level.commonFunctions.getTotalShotsFired] = ::GetTotalShotsFired;
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized; level.overrideMethods[level.commonFunctions.setDvar] = ::SetDvarIfUninitializedWrapper;
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout; level.overrideMethods[level.commonFunctions.waittillNotifyOrTimeout] = ::WaitillNotifyOrTimeoutWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID; level.overrideMethods[level.commonFunctions.isBot] = ::IsBotWrapper;
level.overrideMethods[level.commonFunctions.getXuid] = ::GetXuidWrapper;
RegisterClientCommands(); RegisterClientCommands();
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
level notify( level.notifyTypes.gameFunctionsInitialized ); level notify( level.notifyTypes.gameFunctionsInitialized );
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
{
return;
}
level thread OnPlayerConnect();
}
OnPlayerConnect()
{
level endon ( "game_ended" );
for ( ;; )
{
level waittill( "connected", player );
if ( scripts\_integration_base::_IsBot( player ) )
{
// we don't want to track bots
continue;
}
//player thread SetPersistentData();
player thread WaitForClientEvents();
}
} }
RegisterClientCommands() RegisterClientCommands()
@ -69,39 +42,17 @@ RegisterClientCommands()
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl ); scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
} }
WaitForClientEvents()
{
self endon( "disconnect" );
// example of requesting a meta value
lastServerMetaKey = "LastServerPlayed";
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
for ( ;; )
{
self waittill( level.eventTypes.localClientEvent, event );
scripts\_integration_base::LogDebug( "Received client event " + event.type );
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
{
clientData = self.pers[level.clientDataKey];
lastServerPlayed = clientData.meta[lastServerMetaKey];
}
}
}
GetTotalShotsFired() GetTotalShotsFired()
{ {
return self.pers[ "total_shots" ]; return self.pers["total_shots"];
} }
_SetDvarIfUninitialized(dvar, value) SetDvarIfUninitializedWrapper( dvar, value )
{ {
maps\mp\_utility::set_dvar_if_unset(dvar, value); maps\mp\_utility::set_dvar_if_unset( dvar, value );
} }
_waittill_notify_or_timeout( msg, timer ) WaitillNotifyOrTimeoutWrapper( msg, timer )
{ {
self endon( msg ); self endon( msg );
wait( timer ); wait( timer );
@ -114,7 +65,6 @@ Log2Console( logLevel, message )
God() God()
{ {
if ( !IsDefined( self.godmode ) ) if ( !IsDefined( self.godmode ) )
{ {
self.godmode = false; self.godmode = false;
@ -132,142 +82,16 @@ God()
} }
} }
_GetXUID() IsBotWrapper( client )
{
return client maps\mp\_utility::is_bot();
}
GetXuidWrapper()
{ {
return self GetXUID(); return self GetXUID();
} }
//////////////////////////////////
// GUID helpers
/////////////////////////////////
/*SetPersistentData()
{
self endon( "disconnect" );
guidHigh = self GetPlayerData( "bests", "none" );
guidLow = self GetPlayerData( "awards", "none" );
persistentGuid = guidHigh + "," + guidLow;
guidIsStored = guidHigh != 0 && guidLow != 0;
if ( guidIsStored )
{
// give IW4MAdmin time to collect IP
wait( 15 );
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
return;
}
guid = self SplitGuid();
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
self SetPlayerData( "bests", "none", guid["high"] );
self SetPlayerData( "awards", "none", guid["low"] );
}
SplitGuid()
{
guid = self GetGuid();
if ( isDefined( self.guid ) )
{
guid = self.guid;
}
firstPart = 0;
secondPart = 0;
stringLength = 17;
firstPartExp = 0;
secondPartExp = 0;
for ( i = stringLength - 1; i > 0; i-- )
{
char = GetSubStr( guid, i - 1, i );
if ( char == "" )
{
char = "0";
}
if ( i > stringLength / 2 )
{
value = GetIntForHexChar( char );
power = Pow( 16, secondPartExp );
secondPart = secondPart + ( value * power );
secondPartExp++;
}
else
{
value = GetIntForHexChar( char );
power = Pow( 16, firstPartExp );
firstPart = firstPart + ( value * power );
firstPartExp++;
}
}
split = [];
split["low"] = int( secondPart );
split["high"] = int( firstPart );
return split;
}
Pow( num, exponent )
{
result = 1;
while( exponent != 0 )
{
result = result * num;
exponent--;
}
return result;
}
GetIntForHexChar( char )
{
char = ToLower( char );
// generated by co-pilot because I can't be bothered to make it more "elegant"
switch( char )
{
case "0":
return 0;
case "1":
return 1;
case "2":
return 2;
case "3":
return 3;
case "4":
return 4;
case "5":
return 5;
case "6":
return 6;
case "7":
return 7;
case "8":
return 8;
case "9":
return 9;
case "a":
return 10;
case "b":
return 11;
case "c":
return 12;
case "d":
return 13;
case "e":
return 14;
case "f":
return 15;
default:
return 0;
}
}*/
////////////////////////////////// //////////////////////////////////
// Command Implementations // Command Implementations
///////////////////////////////// /////////////////////////////////
@ -456,17 +280,7 @@ HideImpl( event, data )
AlertImpl( event, data ) AlertImpl( event, data )
{ {
/*if ( !sessionmodeiszombiesgame() ) self thread oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "mpl_sab_ui_suitcasebomb_timer", 7.5 );
{*/
self thread oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "mpl_sab_ui_suitcasebomb_timer", 7.5 );
/*}
else
{
self IPrintLnBold( data["alertType"] );
self IPrintLnBold( data["message"] );
}*/
return "Sent alert to " + self.name; return "Sent alert to " + self.name;
} }
@ -550,7 +364,7 @@ SetSpectatorImpl( event, data )
///////////////////////////////// /////////////////////////////////
/* /*
1:1 the same on MP and ZM but in different includes. Since we probably want to be able to send Alerts on non teambased wagermatechs use our own copy. 1:1 the same on MP and ZM but in different includes. Since we probably want to be able to send Alerts on non teambased wagermatches use our own copy.
*/ */
oldnotifymessage( titletext, notifytext, iconname, glowcolor, sound, duration ) oldnotifymessage( titletext, notifytext, iconname, glowcolor, sound, duration )
{ {
@ -567,5 +381,3 @@ oldnotifymessage( titletext, notifytext, iconname, glowcolor, sound, duration )
self.startmessagenotifyqueue[ self.startmessagenotifyqueue.size ] = notifydata; self.startmessagenotifyqueue[ self.startmessagenotifyqueue.size ] = notifydata;
self notify( "received award" ); self notify( "received award" );
} }

View File

@ -1,45 +1,48 @@
init() Init()
{ {
level.startmessagedefaultduration = 2; level.startmessagedefaultduration = 2;
level.regulargamemessages = spawnstruct(); level.regulargamemessages = spawnstruct();
level.regulargamemessages.waittime = 6; level.regulargamemessages.waittime = 6;
thread OnPlayerConnect();
level thread onplayerconnect();
} }
onplayerconnect() OnPlayerConnect()
{ {
for ( ;; ) for ( ;; )
{ {
level waittill( "connecting", player ); level waittill( "connecting", player );
player thread displaypopupswaiter(); player thread DisplaypopupsWaiter()();
} }
} }
displaypopupswaiter() DisplaypopupsWaiter()
{ {
self endon( "disconnect" ); self endon( "disconnect" );
self.ranknotifyqueue = []; self.ranknotifyqueue = [];
if ( !isDefined( self.pers[ "challengeNotifyQueue" ] ) )
if ( !IsDefined( self.pers[ "challengeNotifyQueue" ] ) )
{ {
self.pers[ "challengeNotifyQueue" ] = []; self.pers[ "challengeNotifyQueue" ] = [];
} }
if ( !isDefined( self.pers[ "contractNotifyQueue" ] ) ) if ( !IsDefined( self.pers[ "contractNotifyQueue" ] ) )
{ {
self.pers[ "contractNotifyQueue" ] = []; self.pers[ "contractNotifyQueue" ] = [];
} }
self.messagenotifyqueue = []; self.messagenotifyqueue = [];
self.startmessagenotifyqueue = []; self.startmessagenotifyqueue = [];
self.wagernotifyqueue = []; self.wagernotifyqueue = [];
while ( !level.gameended ) while ( !level.gameended )
{ {
if ( self.startmessagenotifyqueue.size == 0 && self.messagenotifyqueue.size == 0 ) if ( self.startmessagenotifyqueue.size == 0 && self.messagenotifyqueue.size == 0 )
{ {
self waittill( "received award" ); self waittill( "received award" );
} }
waittillframeend; waittillframeend;
if ( level.gameended ) if ( level.gameended )
{ {
return; return;
@ -50,7 +53,7 @@ displaypopupswaiter()
{ {
nextnotifydata = self.startmessagenotifyqueue[ 0 ]; nextnotifydata = self.startmessagenotifyqueue[ 0 ];
arrayremoveindex( self.startmessagenotifyqueue, 0, 0 ); arrayremoveindex( self.startmessagenotifyqueue, 0, 0 );
if ( isDefined( nextnotifydata.duration ) ) if ( IsDefined( nextnotifydata.duration ) )
{ {
duration = nextnotifydata.duration; duration = nextnotifydata.duration;
} }
@ -58,15 +61,18 @@ displaypopupswaiter()
{ {
duration = level.startmessagedefaultduration; duration = level.startmessagedefaultduration;
} }
self maps\mp\gametypes_zm\_hud_message::shownotifymessage( nextnotifydata, duration ); self maps\mp\gametypes_zm\_hud_message::shownotifymessage( nextnotifydata, duration );
wait duration; wait ( duration );
continue; continue;
} }
else if ( self.messagenotifyqueue.size > 0 ) else if ( self.messagenotifyqueue.size > 0 )
{ {
nextnotifydata = self.messagenotifyqueue[ 0 ]; nextnotifydata = self.messagenotifyqueue[ 0 ];
arrayremoveindex( self.messagenotifyqueue, 0, 0 ); arrayremoveindex( self.messagenotifyqueue, 0, 0 );
if ( isDefined( nextnotifydata.duration ) )
if ( IsDefined( nextnotifydata.duration ) )
{ {
duration = nextnotifydata.duration; duration = nextnotifydata.duration;
} }
@ -74,13 +80,14 @@ displaypopupswaiter()
{ {
duration = level.regulargamemessages.waittime; duration = level.regulargamemessages.waittime;
} }
self maps\mp\gametypes_zm\_hud_message::shownotifymessage( nextnotifydata, duration ); self maps\mp\gametypes_zm\_hud_message::shownotifymessage( nextnotifydata, duration );
continue; continue;
} }
else else
{ {
wait 1; wait ( 1 );
} }
} }
} }
} }