// #RequireContext CSmMode #Extends "Modes/TrackMania/TM_TimeAttack_Online.Script.txt" #Const C_MLID_WaitingMessage "WaitYourMate_WaitingMessage" #Setting S_ForceRespawnWhenAhead False as "" #Setting S_TeamsConfig "" as "json of the Team attribution" // {"56f8dd9f-8581-444e-a2ad-1e8e89eed1a4":1,"752c4db6-26f9-44a3-9c80-08264d1665dc":1} ***Match_Yield*** *** foreach (Event in PendingEvents) { if (Event.Type == CSmModeEvent::EType::OnPlayerAdded) { if (S_TeamsConfig == "") continue; if (Event.Player == Null || Event.Player.User == Null || Event.Player.Score == Null) continue; if (Event.Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) continue; declare Integer[Text] TeamsConfig; TeamsConfig.fromjson(S_TeamsConfig); declare Integer ClanId = TeamsConfig.get(Event.Player.User.WebServicesUserId, 0); Event.Player.Score.LadderClan = ClanId; SetPlayerClan(Event.Player, ClanId); log("Attributing Player "^ Event.Player.User.Name ^"to the clan " ^ ClanId); } } *** ***Match_AfterLoadHud*** *** UIModules::UnloadModules(["UIModule_Race_TimeGap"]); LoadManialinks(); *** ***Match_StartMatch*** *** Clans::SetClansNb(30); *** ***Match_InitMap*** *** foreach (Player in AllPlayers) { declare netwrite Boolean Net_WaitYourMate_IsWaiting for Player = False; Net_WaitYourMate_IsWaiting = False; Player.TrustClientSimu = S_TrustClientSimu; } declare Text[] Map_LoginsToRespawn; *** ***Match_StartMap*** *** if (S_TeamsConfig != "") { declare Integer[Text] TeamsConfig ; TeamsConfig.fromjson(S_TeamsConfig); foreach (Player in AllPlayers) { if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) continue; declare Integer ClanId = TeamsConfig.get(Player.User.WebServicesUserId, 0); Player.Score.LadderClan = ClanId; SetPlayerClan(Player, ClanId); log("Attributing Player "^ Player.User.Name ^"to the clan " ^ ClanId); declare CUIConfig UI <=> UIManager.GetUI(Player); if (UI == Null) continue; UI.SendChat("$ff3You play for the team $fff"^ ClanId); } } Race::SetRespawnBehaviour(Race::C_RespawnBehaviour_NeverGiveUp); *** ***Match_PlayLoop*** *** foreach (Event in Race::GetPendingEvents()) { if (Event.Player == Null) continue; switch (Event.Type) { case Events::C_Type_Waypoint: { if (Event.IsEndRace) continue; UpdateClanStates(Event.Player.Score.LadderClan); if (S_ForceRespawnWhenAhead) { Map_LoginsToRespawn.add(Event.Player.User.Login); } } case Events::C_Type_StartLine: { if (S_TeamsConfig != "") { declare Integer[Text] TeamsConfig ; TeamsConfig.fromjson(S_TeamsConfig); declare Integer ClanId = TeamsConfig.get(Event.Player.User.WebServicesUserId, 0); Event.Player.Score.LadderClan = ClanId; if (Event.Player.Score.LadderClan != Event.Player.CurrentClan) { log("Player spawned on the wrong team, but should not cause any issue"); } } UpdateClanStates(Event.Player.Score.LadderClan); } case Events::C_Type_GiveUp: { UpdateClanStates(Event.Player.Score.LadderClan); } case Events::C_Type_Respawn: { UpdateClanStates(Event.Player.Score.LadderClan); Map_LoginsToRespawn.remove(Event.Player.User.Login); } } } foreach (LoginToRespawn in Map_LoginsToRespawn) { declare CSmPlayer Player <=> GetPlayer(LoginToRespawn) ; if (Player == Null) { Map_LoginsToRespawn.remove(LoginToRespawn); } else { RespawnPlayer(Player); } } *** Void ApplyModeToPlayer(CSmPlayer _Player, Boolean _Lock) { if (_Player == Null) return; if (_Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) return; if (_Lock) { _Player.TrustClientSimu = False; } else { _Player.TrustClientSimu = S_TrustClientSimu; } SetPlayerVehicle_ControlledByMode(_Player, _Lock); declare netwrite Boolean Net_WaitYourMate_IsWaiting for _Player = False; Net_WaitYourMate_IsWaiting = _Lock; } Void LockPlayer(CSmPlayer _Player) { ApplyModeToPlayer(_Player, True); } Void UnlockPlayer(CSmPlayer _Player) { ApplyModeToPlayer(_Player, False); } Void UpdateClanStates(Integer _ClanId) { log("UpdateClanStates _ClanId: " ^ _ClanId); declare CSmPlayer[][Integer] TeammatesPerCheckpoint; foreach (Player in Players) { if (Player.Score == Null) continue; if (Player.Score.BestRaceTimes.count > 0) continue; if (Player.Score.LadderClan != _ClanId) continue; if (!TeammatesPerCheckpoint.existskey(Player.RaceWaypointTimes.count)) TeammatesPerCheckpoint[Player.RaceWaypointTimes.count] = []; TeammatesPerCheckpoint[Player.RaceWaypointTimes.count].add(Player); } if (TeammatesPerCheckpoint.count == 1) { foreach (TeamMates in TeammatesPerCheckpoint) { foreach (Player in TeamMates) { UnlockPlayer(Player); } } } else { TeammatesPerCheckpoint = TeammatesPerCheckpoint.sortkey(); declare Integer MinCheckpointNumber = -1; foreach (Checkpoint => TeamMates in TeammatesPerCheckpoint) { if (MinCheckpointNumber == -1) MinCheckpointNumber = Checkpoint; foreach (Player in TeamMates) { ApplyModeToPlayer(Player, (Checkpoint != MinCheckpointNumber)); } } } } Void LoadManialinks() { declare Text MLText = """ """; Layers::Create(C_MLID_WaitingMessage, MLText); Layers::SetType(C_MLID_WaitingMessage, CUILayer::EUILayerType::Normal); Layers::Attach(C_MLID_WaitingMessage); }