/** @context CSmMode */
#Extends "Modes/TM2020-Gamemodes/PhysicsController.Script.txt"
#Setting S_CoolDownBeforeReset 4
#Setting S_CoolDownForEffects 180
#Setting S_FloorsInfo "136,256,384,512,648,768,904,1040,1168,1296,1432" as "comma separated floor height" // Default is floors of the map "Bennett Foddy ate my CPs"
#Struct K_PlayerInfo {
Text Login;
Text Name;
Integer PrevRank;
Integer CurRank;
Integer Altitude;
Integer RaceTime;
Integer RoundPoints;
Boolean Eliminated;
Boolean isSpectator;
}
***Match_InitMap***
***
declare Integer[Text] ApplyResetAtRespawn_Queue for This;
ApplyResetAtRespawn_Queue = [];
if (Map.MapInfo.MapUid == "3tMeImoOvcb0hnryDZ9nbw9YVY6") { // Only upload record on the right map
Race::SetupRecord(
MenuConsts::C_ScopeType_Season,
MenuConsts::C_ScopeType_PersonalBest,
MenuConsts::C_GameMode_TimeAttack,
"",
True, //C_UploadRecord
False, //C_DisplayRecordGhost
False, //C_DisplayRecordMedal
False, //C_CelebrateRecordGhost
False //C_CelebrateRecordMedal
);
} else {
Race::SetupRecord(
MenuConsts::C_ScopeType_Season,
MenuConsts::C_ScopeType_PersonalBest,
MenuConsts::C_GameMode_TimeAttack,
"",
False, //C_UploadRecord
False, //C_DisplayRecordGhost
False, //C_DisplayRecordMedal
False, //C_CelebrateRecordGhost
False //C_CelebrateRecordMedal
);
}
***
// force a reset at respawn to prevent abuse
***PhysicsController_PhysicsAtRespawn***
***
foreach (Event in RacePendingEvents) {
Log::Log("[RacePendingEvents][MainLoop] Event.Type: " ^ Event.Type);
if (Event.Type == Events::C_Type_StartLine || Event.Type == Events::C_Type_GiveUp || Event.Type == Events::C_Type_SkipOutro || Event.Type == Events::C_Type_Respawn) {
if (Event.Player != Null) {
if (Event.Type != Events::C_Type_Respawn) {
declare netwrite Integer Net_CoolDownForEffects for Event.Player;
declare netwrite Integer Net_CoolDownBeforeReset for Event.Player;
Net_CoolDownForEffects = 0;
Net_CoolDownBeforeReset = 0;
}
declare netwrite Net_PlayerPhysics for Event.Player = InitPlayerPhysicsVariable();
Net_PlayerPhysics = InitPlayerPhysicsVariable();
if (!ApplyPhysics_Queue.existskey(Event.Player.User.WebServicesUserId)) ApplyPhysics_Queue[Event.Player.User.WebServicesUserId] = [];
ApplyPhysics_Queue[Event.Player.User.WebServicesUserId] = GetDiffPhysics(Event.Player, True);
}
}
}
***
***PhysicsController_UI***
***
SetHolidayShowdownControlML();
SetHolidayShowdownLiveRaceML();
UIModules::UnloadModules(["UIModule_Rounds_SmallScoresTable","UIModule_Knockout_KnockoutInfo"]);
***
***PhysicsController_SetPhysicsChange***
***
declare netwrite Integer Net_CoolDownForEffects for _Player = 0;
declare netwrite Integer Net_CoolDownBeforeReset for _Player = 0;
if (_EventName == "Reset") {
Net_CoolDownBeforeReset = 0;
if (_Player != Null && !SetPlayer_DelayedIsFull(_Player) && (_Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned || _Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawning)) {
declare netwrite Net_PlayerPhysics for _Player = InitPlayerPhysicsVariable();
Net_PlayerPhysics = InitPlayerPhysicsVariable();
}
} else {
Net_CoolDownBeforeReset = Now + (S_CoolDownBeforeReset * 1000);
Net_CoolDownForEffects = Now + (S_CoolDownForEffects * 1000);
}
***
***PhysicsController_BeforeAddApplyPhysicsEffect***
***
ApplyPhysics_Queue[Player.User.WebServicesUserId] = [];
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics("Reset", "", Now + (S_CoolDownBeforeReset * 1000) - 50));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics("Reset", "", Now + (S_CoolDownBeforeReset * 1000) + 50));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics("Reset", "", Now + (S_CoolDownBeforeReset * 1000) + 100));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics("Reset", "", Now + (S_CoolDownBeforeReset * 1000) + 200));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics("Reset", "", Now + (S_CoolDownBeforeReset * 1000) + 500));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics("Reset", "", Now + (S_CoolDownBeforeReset * 1000) + 1000));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics(EventName, Value, Now + 50));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics(EventName, Value, Now + 100));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics(EventName, Value, Now + 200));
ApplyPhysics_Queue[Player.User.WebServicesUserId].add(GetPhysics(EventName, Value, Now + 500));
***
***Match_InitMap***
***
declare Integer WaitNextUpdate = 0;
declare netwrite Text Net_FloorsInfo for Teams[0] = S_FloorsInfo;
declare netwrite K_PlayerInfo[] Net_HolidayShowdown_Ranking for Teams[0];
declare netwrite Integer Net_HolidayShowdown_RankingSerial for Teams[0];
***
***Match_InitPlayLoop***
***
WaitNextUpdate = 0;
Net_HolidayShowdown_RankingSerial = 0;
***
***Match_PlayLoop***
***
if (Now > WaitNextUpdate) {
WaitNextUpdate = Now + 500;
declare Integer[Text] SortedPlayersByRaceTime;
declare Integer[Text] SortedPlayersByAltitude;
declare Text[] SortedPlayersEliminated;
foreach (Player in AllPlayers) {
if (!Player.RequestsSpectate || Scores::GetPlayerMatchPoints(Player.Score) > 0) {
if (Player.Score.PrevRaceTimes.count > 0 && Player.RaceWaypointTimes.count == Player.Score.PrevRaceTimes.count && Player.RaceWaypointTimes[Player.RaceWaypointTimes.count - 1] == Player.Score.PrevRaceTimes[Player.Score.PrevRaceTimes.count - 1]) {
SortedPlayersByRaceTime[Player.User.WebServicesUserId] = Player.Score.PrevRaceTimes[Player.Score.PrevRaceTimes.count - 1];
} else if (UIManager.UIAll.UISequence == CUIConfig::EUISequence::Playing && Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) {
declare netwrite Integer Net_Knockout_KnockoutInfo_PlayersNb for Teams[0] = 0;
declare netwrite Boolean Net_Knockout_PlayerIsAlive for Player.Score = False;
if (Net_Knockout_KnockoutInfo_PlayersNb == 0 || Net_Knockout_PlayerIsAlive) {
SortedPlayersEliminated.add(Player.User.WebServicesUserId);
}
} else {
SortedPlayersByAltitude[Player.User.WebServicesUserId] = ML::FloorInteger(Player.Position.Y);
}
}
}
SortedPlayersByRaceTime = SortedPlayersByRaceTime.sort();
SortedPlayersByAltitude = SortedPlayersByAltitude.sortreverse();
declare K_PlayerInfo[] Ranking;
declare Integer Rank = 1;
foreach (AccountId => RaceTime in SortedPlayersByRaceTime) {
if (Rank > 16) break;
declare CSmPlayer Player <=> ModeUtils::GetPlayerFromAccountId(AccountId);
if (Player != Null) {
declare Integer HolidayShowdown_PrevRank for Player = 0;
Ranking.add(K_PlayerInfo {
Login = Player.User.Login,
Name = Player.User.Name,
PrevRank = HolidayShowdown_PrevRank,
CurRank = Rank,
Altitude = -1,
RaceTime = RaceTime,
RoundPoints = Player.Score.RoundPoints,
Eliminated = False,
isSpectator = Player.RequestsSpectate
});
if (Rank != HolidayShowdown_PrevRank) CarRank::SetRank(Player, Rank);
HolidayShowdown_PrevRank = Rank;
Rank = Rank + 1;
}
}
foreach (AccountId => PlayerAltitude in SortedPlayersByAltitude) {
if (Rank > 16) break;
declare CSmPlayer Player <=> ModeUtils::GetPlayerFromAccountId(AccountId);
if (Player != Null ) {
declare Integer HolidayShowdown_PrevRank for Player = 0;
// Add the player to the ranking
Ranking.add(K_PlayerInfo {
Login = Player.User.Login,
Name = Player.User.Name,
PrevRank = HolidayShowdown_PrevRank,
CurRank = Rank,
Altitude = PlayerAltitude,
RaceTime = -1,
RoundPoints = -1,
Eliminated = False,
isSpectator = Player.RequestsSpectate
});
if (Rank != HolidayShowdown_PrevRank) CarRank::SetRank(Player, Rank);
HolidayShowdown_PrevRank = Rank;
Rank = Rank + 1;
}
}
foreach (AccountId in SortedPlayersEliminated) {
if (Rank > 16) break;
declare CSmPlayer Player <=> ModeUtils::GetPlayerFromAccountId(AccountId);
if (Player != Null) {
declare Integer HolidayShowdown_PrevRank for Player = 0;
// Add the player to the ranking
Ranking.add(K_PlayerInfo {
Login = Player.User.Login,
Name = Player.User.Name,
PrevRank = HolidayShowdown_PrevRank,
CurRank = Rank,
Altitude = -1,
RaceTime = -1,
RoundPoints = -1,
Eliminated = True,
isSpectator = Player.RequestsSpectate
});
if (Rank != HolidayShowdown_PrevRank) CarRank::SetRank(Player, Rank);
HolidayShowdown_PrevRank = Rank;
Rank = Rank + 1;
}
}
Net_HolidayShowdown_Ranking = Ranking;
Net_HolidayShowdown_RankingSerial = Net_HolidayShowdown_RankingSerial + 1;
}
if (Net_FloorsInfo != S_FloorsInfo) {
Net_FloorsInfo = S_FloorsInfo;
}
***
***PhysicsController_NewCustomEvents***
***
if (Event.CustomEventType == "Request.ResetCD") {
declare Text Target = Event.CustomEventData[0];
Log::Log("[UIManager] Admin send reset CD to : " ^ Target);
declare CSmPlayer Player = GetPlayer(Target);
if (Player != Null) {
declare netwrite Integer Net_CoolDownForEffects for Player = 0;
declare netwrite Integer Net_CoolDownBeforeReset for Player = 0;
Net_CoolDownForEffects=0;
Net_CoolDownBeforeReset=0;
}
}
***
Void SetHolidayShowdownControlML() {
declare Text MLText = """
""";
Layers::Create("PhysicsDiscovery_ControlUI", MLText);
Layers::SetType("PhysicsDiscovery_ControlUI", CUILayer::EUILayerType::Normal);
Layers::Attach("PhysicsDiscovery_ControlUI");
}
Void SetHolidayShowdownLiveRaceML() {
declare Text MLText = """
""";
Layers::Create("PhysicsDiscovery_LiveRaceUI", MLText);
Layers::SetType("PhysicsDiscovery_LiveRaceUI", CUILayer::EUILayerType::Normal);
Layers::Attach("PhysicsDiscovery_LiveRaceUI");
}