diff --git a/PhysicsDiscovery.Script.txt b/PhysicsDiscovery.Script.txt new file mode 100644 index 0000000..0a754d0 --- /dev/null +++ b/PhysicsDiscovery.Script.txt @@ -0,0 +1,629 @@ +#Extends "Modes/TrackMania/TM_TimeAttack_Online.Script.txt" + +#Setting S_TrustClientSimu False +#Setting S_UseCrudeExtrapolation False +#Setting S_AdminPlayers "" as "Comma separated admin to manage all players physics" +#Setting S_ForcePlayersToBeControledBySpectators False as "Force Players to be controlled by Spectators" +#Setting S_AllowPlayersToBeControledBySpectators True as "Allow Players to be controlled by Spectators" + +#Struct K_PlayerPhysics { + Real AccelCoef; + Real AdherenceCoef; + Boolean Boost2Down; + Boolean Boost2Up; + Boolean BoostDown; + Boolean BoostUp; + Real ControlCoef; + Real Cruise; + Boolean ForceEngine; + Boolean Fragile; + Real GravityCoef; + Boolean NoBrakes; + Boolean NoEngine; + Boolean NoSteer; + Boolean SlowMotion; +} + + +***Match_StartServer*** +*** +UsePvPCollisions = True; +UIModules_Record::Reset(); +UIModules_Record::SetSpecialVisibility(False); +*** + +***Match_AfterLoadHud*** +*** +SetML(); +*** + +***Match_InitMap*** +*** +declare K_PlayerPhysics AllPlayersPhysics = InitPlayerPhysicsVariable(); +declare Text Last_AdminPlayers; + +declare netwrite Boolean Net_ServerForcePlayersToBeControledBySpectators for Teams[0] = S_ForcePlayersToBeControledBySpectators; +declare netwrite Boolean Net_ServerAllowPlayersToBeControledBySpectators for Teams[0] = S_AllowPlayersToBeControledBySpectators; +*** + +***Match_PlayLoop*** +*** + +foreach (Event in PendingEvents) { + Log::Log("[PendingEvents] Event.Type: " ^ Event.Type); + if (Event.Type == CSmModeEvent::EType::OnPlayerAdded) { + if (Event.Player != Null) { + declare netwrite Boolean Net_PlayerIsAdmin for Event.Player = False; + Net_PlayerIsAdmin = TL::Split(",", S_AdminPlayers).exists(Event.Player.User.Login); + declare netwrite K_PlayerPhysics Net_PlayerPhysics for Event.Player = InitPlayerPhysicsVariable(); + Net_PlayerPhysics = AllPlayersPhysics; + } + } +} + +// Manage Custom UI Events +foreach (Event in UIManager.PendingEvents) { // TODO: Add Secure token to admins + Log::Log("[UIManager] Event.Type: " ^ Event.Type); + if (TL::StartsWith("Request.PlayerPhysics.", Event.CustomEventType)) { + + declare Text EventName = TL::Split(".", Event.CustomEventType)[2]; + declare Text Target = Event.CustomEventData[0]; + declare Text Value = Event.CustomEventData[1]; + if (Target == "all") { + AllPlayersPhysics = GetUpdatedPlayerPhysicsVariable(EventName, Value, AllPlayersPhysics); + foreach (Player in Players) { + SetPhysicsChange(EventName, Value, Player); + declare netwrite K_PlayerPhysics Net_PlayerPhysics for Player = InitPlayerPhysicsVariable(); + Net_PlayerPhysics = AllPlayersPhysics; + } + } else { + declare CSmPlayer Player = GetPlayer(Target); + if (Player != Null && Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) { + SetPhysicsChange(EventName, Value, Player); + declare netwrite K_PlayerPhysics Net_PlayerPhysics for Player = InitPlayerPhysicsVariable(); + Net_PlayerPhysics = GetUpdatedPlayerPhysicsVariable(EventName, Value, Net_PlayerPhysics); + } + } + } else if (Event.CustomEventType == "Request.ControlBySpectators") { + declare Text Target = Event.CustomEventData[0]; + declare Text Value = Event.CustomEventData[1]; + declare Boolean Allowed = (Value == "1"); + declare CSmPlayer Player = GetPlayer(Target); + if (Player != Null) { + declare netwrite Boolean Net_PlayerAllowToBeControledBySpectators for Player = True; + Net_PlayerAllowToBeControledBySpectators = Allowed; + } + } else if (Event.CustomEventType == "Request.AdminLock") { + declare Boolean Locked = (Event.CustomEventData[1] == "1"); + declare netwrite Boolean Net_ControledByAdmins for Teams[0]; + Net_ControledByAdmins = Locked; + AllPlayersPhysics = InitPlayerPhysicsVariable(); + if (Locked) { + foreach (Player in Players) { + SetPhysicsChange("Reset", "", Player); + declare netwrite K_PlayerPhysics Net_PlayerPhysics for Player = InitPlayerPhysicsVariable(); + Net_PlayerPhysics = AllPlayersPhysics; + } + } + } +} + +foreach (Event in RacePendingEvents) { + Log::Log("[RacePendingEvents] Event.Type: " ^ Event.Type); + if (Event.Type == Events::C_Type_StartLine || Event.Type == Events::C_Type_GiveUp || (Event.Type == Events::C_Type_Waypoint && Event.IsEndRace)) { + declare netwrite K_PlayerPhysics Net_PlayerPhysics for Event.Player = InitPlayerPhysicsVariable(); + ApplyPhysicsAtRespawn(Event.Player, Net_PlayerPhysics); + } +} + +if (Last_AdminPlayers != S_AdminPlayers) { + Last_AdminPlayers = S_AdminPlayers; + declare Text[] Admin = TL::Split(",", S_AdminPlayers); + foreach (Player in Players) { + declare netwrite Boolean Net_PlayerIsAdmin for Player = False; + Net_PlayerIsAdmin = Admin.exists(Player.User.Login); + } +} + +if (Net_ServerForcePlayersToBeControledBySpectators != S_ForcePlayersToBeControledBySpectators) { + Net_ServerForcePlayersToBeControledBySpectators = S_ForcePlayersToBeControledBySpectators; +} + +if (Net_ServerAllowPlayersToBeControledBySpectators != S_AllowPlayersToBeControledBySpectators) { + Net_ServerAllowPlayersToBeControledBySpectators = S_AllowPlayersToBeControledBySpectators; +} +*** + +K_PlayerPhysics InitPlayerPhysicsVariable() { + return K_PlayerPhysics { + AccelCoef = 1., + AdherenceCoef = 1., + ControlCoef = 1., + Cruise = 0., + GravityCoef = 1. + }; +} + +Boolean SetPhysicsChange(Text _EventName, Text _EventValue, CSmPlayer _Player) { + if (_Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) { + while (SetPlayer_DelayedIsFull(_Player)) MB_Yield(); + switch (_EventName) { + case "AccelCoef": SetPlayer_Delayed_AccelCoef(_Player, TL::ToReal(_EventValue)); + case "AdherenceCoef": SetPlayer_Delayed_AdherenceCoef(_Player, TL::ToReal(_EventValue)); + case "Boost2Down": SetPlayer_Delayed_Boost2Down(_Player, (_EventValue == "1")); + case "Boost2Up": SetPlayer_Delayed_Boost2Up(_Player, (_EventValue == "1")); + case "BoostDown": SetPlayer_Delayed_BoostDown(_Player, (_EventValue == "1")); + case "BoostUp": SetPlayer_Delayed_BoostUp(_Player, (_EventValue == "1")); + case "ControlCoef": SetPlayer_Delayed_ControlCoef(_Player, TL::ToReal(_EventValue)); + case "Cruise": SetPlayer_Delayed_Cruise(_Player, (_EventValue != "0"), TL::ToReal(_EventValue)); + case "ForceEngine": SetPlayer_Delayed_ForceEngine(_Player, (_EventValue == "1")); + case "Fragile": SetPlayer_Delayed_Fragile(_Player, (_EventValue == "1")); + case "GravityCoef": SetPlayer_Delayed_GravityCoef(_Player, TL::ToReal(_EventValue)); + case "NoBrakes": SetPlayer_Delayed_NoBrakes(_Player, (_EventValue == "1")); + case "NoEngine": SetPlayer_Delayed_NoEngine(_Player, (_EventValue == "1")); + case "NoSteer": SetPlayer_Delayed_NoSteer(_Player, (_EventValue == "1")); + case "Reset": SetPlayer_Delayed_Reset(_Player); + case "SlowMotion": SetPlayer_Delayed_SlowMotion(_Player, (_EventValue == "1")); + } + return True; + } + return False; +} + +K_PlayerPhysics GetUpdatedPlayerPhysicsVariable(Text _EventName, Text _EventValue, K_PlayerPhysics _PlayerPhysics) { + declare K_PlayerPhysics NewPlayerPhysics = _PlayerPhysics; + switch (_EventName) { + case "AccelCoef": NewPlayerPhysics.AccelCoef = TL::ToReal(_EventValue); + case "AdherenceCoef": NewPlayerPhysics.AdherenceCoef = TL::ToReal(_EventValue); + case "Boost2Down": { + NewPlayerPhysics.Boost2Down = (_EventValue == "1"); + NewPlayerPhysics.Boost2Up = False; + NewPlayerPhysics.BoostDown = False; + NewPlayerPhysics.BoostUp = False; + } + case "Boost2Up": { + NewPlayerPhysics.Boost2Down = False; + NewPlayerPhysics.Boost2Up = (_EventValue == "1"); + NewPlayerPhysics.BoostDown = False; + NewPlayerPhysics.BoostUp = False; + } + case "BoostDown": { + NewPlayerPhysics.Boost2Down = False; + NewPlayerPhysics.Boost2Up = False; + NewPlayerPhysics.BoostDown = (_EventValue == "1"); + NewPlayerPhysics.BoostUp = False; + } + case "BoostUp": { + NewPlayerPhysics.Boost2Down = False; + NewPlayerPhysics.Boost2Up = False; + NewPlayerPhysics.BoostDown = False; + NewPlayerPhysics.BoostUp = (_EventValue == "1"); + } + case "ControlCoef": NewPlayerPhysics.ControlCoef = TL::ToReal(_EventValue); + case "Cruise": NewPlayerPhysics.Cruise = TL::ToReal(_EventValue); + case "ForceEngine": { + NewPlayerPhysics.NoEngine = False; + NewPlayerPhysics.ForceEngine = (_EventValue == "1"); + } + case "Fragile": NewPlayerPhysics.Fragile = (_EventValue == "1"); + case "GravityCoef": NewPlayerPhysics.GravityCoef = TL::ToReal(_EventValue); + case "NoBrakes": NewPlayerPhysics.NoBrakes = (_EventValue == "1"); + case "NoEngine": { + NewPlayerPhysics.NoEngine = (_EventValue == "1"); + NewPlayerPhysics.ForceEngine = False; + } + case "NoSteer": NewPlayerPhysics.NoSteer = (_EventValue == "1"); + case "Reset": NewPlayerPhysics = InitPlayerPhysicsVariable(); + case "SlowMotion": NewPlayerPhysics.SlowMotion = (_EventValue == "1"); + } + + return NewPlayerPhysics; +} + +Void ApplyPhysicsAtRespawn(CSmPlayer _Player, K_PlayerPhysics _PlayerPhysics) { + declare K_PlayerPhysics DefaultPlayerPhysics = InitPlayerPhysicsVariable(); + while (_Player.SpawnStatus != CSmPlayer::ESpawnStatus::Spawned) MB_Yield(); + + if (DefaultPlayerPhysics.AccelCoef != _PlayerPhysics.AccelCoef) SetPhysicsChange("AccelCoef", TL::ToText(_PlayerPhysics.AccelCoef), _Player); + if (DefaultPlayerPhysics.AdherenceCoef != _PlayerPhysics.AdherenceCoef) SetPhysicsChange("AdherenceCoef", TL::ToText(_PlayerPhysics.AdherenceCoef), _Player); + if (DefaultPlayerPhysics.Boost2Down != _PlayerPhysics.Boost2Down) SetPhysicsChange("Boost2Down", "1", _Player); + if (DefaultPlayerPhysics.Boost2Up != _PlayerPhysics.Boost2Up) SetPhysicsChange("Boost2Up", "1", _Player); + if (DefaultPlayerPhysics.BoostDown != _PlayerPhysics.BoostDown) SetPhysicsChange("BoostDown", "1", _Player); + if (DefaultPlayerPhysics.BoostUp != _PlayerPhysics.BoostUp) SetPhysicsChange("BoostUp", "1", _Player); + if (DefaultPlayerPhysics.ControlCoef != _PlayerPhysics.ControlCoef) SetPhysicsChange("ControlCoef", TL::ToText(_PlayerPhysics.ControlCoef), _Player); + if (DefaultPlayerPhysics.Cruise != _PlayerPhysics.Cruise) SetPhysicsChange("Cruise", TL::ToText(_PlayerPhysics.Cruise), _Player); + if (DefaultPlayerPhysics.ForceEngine != _PlayerPhysics.ForceEngine) SetPhysicsChange("ForceEngine", "1", _Player); + if (DefaultPlayerPhysics.Fragile != _PlayerPhysics.Fragile) SetPhysicsChange("Fragile", "1", _Player); + if (DefaultPlayerPhysics.GravityCoef != _PlayerPhysics.GravityCoef) SetPhysicsChange("GravityCoef", TL::ToText(_PlayerPhysics.GravityCoef), _Player); + if (DefaultPlayerPhysics.NoBrakes != _PlayerPhysics.NoBrakes) SetPhysicsChange("NoBrakes", "1", _Player); + if (DefaultPlayerPhysics.NoEngine != _PlayerPhysics.NoEngine) SetPhysicsChange("NoEngine", "1", _Player); + if (DefaultPlayerPhysics.NoSteer != _PlayerPhysics.NoSteer) SetPhysicsChange("NoSteer", "1", _Player); + if (DefaultPlayerPhysics.SlowMotion != _PlayerPhysics.SlowMotion) SetPhysicsChange("SlowMotion", "1", _Player); +} + +Void SetML() { + declare Text MLText = """ + + + +