Skip to content

Instantly share code, notes, and snippets.

@rsepierre
Last active August 29, 2015 14:02
Show Gist options
  • Save rsepierre/43e8151b80f3ead4b777 to your computer and use it in GitHub Desktop.
Save rsepierre/43e8151b80f3ead4b777 to your computer and use it in GitHub Desktop.
Team Arena Master mode for Shootmania
/**
* Mode Team Arena Master
*/
#Extends "Modes/ShootMania/ModeMatchmaking.Script.txt"
#Const CompatibleMapTypes "ComboArena"
#Const Version "2014-06-01"
#Const ScriptName "Combo.Script.txt"
#Include "Libs/Nadeo/Markers.Script.txt" as Markers
#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
#Include "Libs/Nadeo/ShootMania/Map.Script.txt" as Map
#Include "Libs/Nadeo/ShootMania/Score.Script.txt" as Score
#Include "Libs/Nadeo/ShootMania/WarmUp2.Script.txt" as WarmUp2
// ---------------------------------- //
// Settings
// ---------------------------------- //
#Setting S_NbPlayersPerTeam 5 as _("Number of players per team (Max. 5)")
#Setting S_PointsLimit 10 as _("Points limit (0: No points limit)")
#Setting S_RoundTimeLimit 240 as _("Round time limit (0: No time limit)")
#Setting S_WarmUpDuration 45 as _("Warmup duration (0: disabled)")
#Setting S_AllowUnbalancedTeams True as _("Allow a game to begin without the same number of players in each team")
#Setting S_UseArmorReduction False as _("Reduce the armor of players above two armor points")
// Clublinks settings
#Setting S_UsePlayerClublinks False as _("Use players Clublinks") default teams
#Setting S_ForceClublinkTeam1 "" as "<hidden>"
#Setting S_ForceClublinkTeam2 "" as "<hidden>"
// ---------------------------------- //
// Constants
// ---------------------------------- //
#Const C_ActionEvent_SwitchWeapon "SwitchWeapon"
#Const C_Object [
"Armor" => "Armor",
"Arrow" => "Arrow",
"Laser" => "Laser",
"Nucleus" => "Nucleus",
"Rocket" => "Rocket"
]
#Const C_AmmoGain [
"Rocket" => 0.5,
"Laser" => 0.6,
"Nucleus" => 0.5,
"Arrow" => 0.3
]
#Const C_AmmoMax [
"Laser" => 1,
"Nucleus" => 2,
"Arrow" => 1,
"Rocket" => 4
]
#Const C_ArmorReductionPeriod 30000
#Const C_ArmorReductionStart 0
#Const C_RoundStartInvicibilityDuration 10000
#Const C_Default_ComboTime 30000
#Const C_Default_Armor 700
#Const C_Default_ArmorMax 700
#Const C_Object_Delay 30000
#Const C_Object_ArmorValue 100
#Const C_NbPlayersPerTeamMax 5
#Const C_ComboTimeStep 2000
#Const C_OffZoneRadiusMax 300.
#Const C_OffZoneRadiusMin 16.
#Const C_OffZoneDuration 60
#Const C_MaxDamage 100
#Const C_ImgBaseDir "file://Media/Manialinks/Shootmania/Common/"
#Const C_WaitConnectionTimeLimit 60000
#Const C_SleepEndMap 10000
#Const C_LayerTimersPosition 151.5
#Const Description _("TYPE: Team DeathMatch\nOBJECTIVE:\n- Eliminate all the enemy team.\n- Use '1', '2', '3' and '4' on your keyboard to switch weapon. You start with all your weapons.")
#Const C_BlueBots 0
#Const C_RedBots 0
// ---------------------------------- //
// Globales variables
// ---------------------------------- //
declare Ident[Text] G_ObjectId;
// Ids of the objects
declare Boolean G_OffZoneIsActivated;
// OffZone status
declare Integer G_ComboTime;
// Timer of the current combo
declare Integer G_ComboClan;
// Clan doing the combo
declare Integer G_ComboNextTick;
// Combo time
declare Integer[Integer] G_ClanComboTimeLimit;
// Timer max of the combo for each clan
declare Ident[][Integer] G_ClansPlayers;
// List of players allowed to play
declare Integer S_Script_RoundTimeLimit;
declare Integer S_Script_PointsLimit;
declare Integer S_Script_NbPlayersPerTeam;
declare CSmMode::EWeapon[Integer] C_Default_Weapons;
declare CSmMode::EWeapon C_Default_Weapon;
// ---------------------------------- //
// Extend
// ---------------------------------- //
***LogVersion***
***
MB_LogVersion(ScriptName, Version);
MB_LogVersion(SM::GetScriptName(), SM::GetScriptVersion());
MB_LogVersion(Score::GetScriptName(), Score::GetScriptVersion());
MB_LogVersion(Layers::GetScriptName(), Layers::GetScriptVersion());
MB_LogVersion(WarmUp2::GetScriptName(), WarmUp2::GetScriptVersion());
MB_LogVersion(Message::GetScriptName(), Message::GetScriptVersion());
MB_LogVersion(SpawnScreen::GetScriptName(), SpawnScreen::GetScriptVersion());
***
***LobbyStartServer***
***
MM_SetFormat([S_NbPlayersPerTeam, S_NbPlayersPerTeam]);
***
***Rules***
***
declare ModeName = "Team Arena Master";
declare ModeObjectives = TL::Compose(_("$<%11. $>Eliminate all the enemy team."), "$"^SpawnScreen::GetModeColor());
declare ModeConditions = TL::Compose(_("$<%11. $>Use '1', '2', '3' and '4' on your keyboard to switch weapon. You start with all your weapons."), "$"^SpawnScreen::GetModeColor());
SpawnScreen::AddSubsection(_("Type"), _("Team versus Team"), 0.);
SpawnScreen::AddSubsection(
_("Objectives"),
ModeObjectives,
25.
);
SpawnScreen::AddSubsection(
_("Conditions"),
ModeConditions,
65.
);
SpawnScreen::CreatePrettyRules(ModeName);
***
***InitServer***
***
MB_UsePlayerClublinks = S_UsePlayerClublinks;
***
***StartServer***
***
// ---------------------------------- //
// Matchmaking mode
if (S_MatchmakingMode == 2) {
MM_Init([S_NbPlayersPerTeam, S_NbPlayersPerTeam]);
}
// ---------------------------------- //
// Set mode options
UseClans = True;
MB_UseSectionRound = True;
C_Default_Weapons = [GetWeaponOrder(CSmMode::EWeapon::Rocket) => CSmMode::EWeapon::Rocket];
C_Default_Weapon = CSmMode::EWeapon::Rocket;
// ---------------------------------- //
// Create the rules
---Rules---
// ---------------------------------- //
// Create the warm up
WarmUp2::Load();
WarmUp2::CreateGroup("Clan1", S_NbPlayersPerTeam);
WarmUp2::CreateGroup("Clan2", S_NbPlayersPerTeam);
WarmUp2::DisplayClanSelection(True);
// ---------------------------------- //
// Create the scores table
ST2::SetStyle("LibST_SMBaseTeams");
ST2::SetStyle("LibST_SMBasePoints");
ST2::SetStyle("LibST_SMWithLegends");
ST2::SetFormat(2, 6);
ST2::SetTextScale(1.1);
ST2::CreateCol("HitsPerWeapon", _("Hits per weapon"), "0/0/0/0", 8., 50.);
ST2::SetColTextAlign("HitsPerWeapon", CMlControl::AlignHorizontal::Right);
ST2::SetColLegend("LibST_SMRoundPoints", _("Hits"));
ST2::SetColLegend("LibST_SMPoints", _("Score"));
ST2::SetColWidth("LibST_Name", 15.);
MM_SetScoresTableStyleFromXml(S_ScoresTableStylePath);
ST2::Build("SM");
// ---------------------------------- //
// Load items
//ItemList_Begin();
//G_ObjectId[C_Object["Armor"]] = ItemList_Add("Storm\\MeleeUltimate\\Armor.Item.gbx");
//G_ObjectId[C_Object["Rocket"]] = ItemList_Add("Storm\\MeleeUltimate\\Rocket.Item.gbx");
//G_ObjectId[C_Object["Laser"]] = ItemList_Add("Storm\\MeleeUltimate\\Laser.Item.gbx");
//G_ObjectId[C_Object["Nucleus"]] = ItemList_Add("Storm\\MeleeUltimate\\Nucleus.Item.gbx");
//G_ObjectId[C_Object["Arrow"]] = ItemList_Add("Storm\\MeleeUltimate\\Arrow.Item.gbx");
//ItemList_End();
// ---------------------------------- //
// Create layer
Layers::Create("Info");
// ---------------------------------- //
// Initialize Markers
Markers::Load();
***
***InitMap***
***
declare Integer MapWinnerClan;
declare CSmMapPlayerSpawn[Integer] Spawns;
if (S_MatchmakingMode == 2) MB_UseIntro = False;
else MB_UseIntro = True;
***
***StartMap***
***
// ---------------------------------- //
// Misc initialization
Users_SetNbFakeUsers(C_BlueBots, C_RedBots);
Score::MatchBegin();
SM::SetupDefaultVisibility();
//UIManager.UIAll.TeamLabelsVisibility = CUIConfig::ELabelsVisibility::Always;
MapWinnerClan = 0;
G_ClansPlayers = [1 => Ident[], 2 => Ident[]];
Spawns = [1 => Null, 2 => Null];
foreach (MapLandmark in MapLandmarks_PlayerSpawn) {
if (MapLandmark.Order == 1) Spawns[1] <=> MapLandmark.PlayerSpawn;
else if (MapLandmark.Order == 2) Spawns[2] <=> MapLandmark.PlayerSpawn;
}
assert(Spawns[1] != Null && Spawns[2] != Null);
UpdateModeStatusMessage();
UpdateBasesColors();
// ---------------------------------- //
// Initialize players
foreach (Player in AllPlayers) {
SetPlayerClan(Player, MM_GetRequestedClan(Player));
declare UI <=> UIManager.GetUI(Player);
if (UI != Null) {
UI.SpectatorForceCameraType = -1;
UI.SpectatorForcedClan = -1;
}
}
// ---------------------------------- //
// Initialize scores
foreach (Score in Scores) {
declare HitLaser for Score = 0;
declare HitNucleus for Score = 0;
declare HitArrow for Score = 0;
declare HitRocket for Score = 0;
HitLaser = 0;
HitNucleus = 0;
HitArrow = 0;
HitRocket = 0;
}
// ---------------------------------- //
// Set storm center
foreach (Pole in MapLandmarks_Gauge) {
if (Pole.Tag == "Checkpoint") {
OffZoneCenterLandmarkId = Pole.Id;
break;
}
}
// ---------------------------------- //
// Update the scores table
ST2::ClearScores();
ST2::SetFooterText(TL::Compose("%1 "^S_PointsLimit, _("Points limit : ")));
UpdateScoresHeader();
// ---------------------------------- //
// Initialize markers
Markers::Clear();
CreateMarkers();
// ---------------------------------- //
// Initalize settings
S_Script_RoundTimeLimit = S_RoundTimeLimit;
S_Script_PointsLimit = S_PointsLimit;
S_Script_NbPlayersPerTeam = S_NbPlayersPerTeam;
if (S_Script_NbPlayersPerTeam > C_NbPlayersPerTeamMax) {
S_Script_NbPlayersPerTeam = C_NbPlayersPerTeamMax;
}
// ---------------------------------- //
// Wait players when using matchmaking
if (S_MatchmakingMode == 2) {
MM_MatchWait();
PrepareMatch();
}
// ---------------------------------- //
// Do warm up
else WarmUp();
declare ClansOrder = [1 => WarmUp2::GetGroup("Clan1"), 2 => WarmUp2::GetGroup("Clan2")];
foreach (Clan => ClanOrder in ClansOrder) {
if (!G_ClansPlayers.existskey(Clan)) continue;
foreach (Slot => PlayerId in ClanOrder) {
G_ClansPlayers[Clan].add(PlayerId);
}
}
// ---------------------------------- //
// Update the players clublinks
if (S_ForceClublinkTeam1 == "" && S_ForceClublinkTeam2 == "") {
Clublink::DefineTeamAuto();
Clublink::SyncUpdate(); ///< Try to force the load of the clublink
} else {
Clublink::DefineTeamFromUrl(S_ForceClublinkTeam1, S_ForceClublinkTeam2);
}
// ---------------------------------- //
// Initialize UI
UpdateScoresHeader();
UIManager.UIAll.SendNotice("", CUIConfig::ENoticeLevel::MatchInfo, Null, CUIConfig::EAvatarVariant::Default, CUIConfig::EUISound::StartRound, 0);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
Layers::Attach("Info");
Layers::Update("Info", UpdateLayerInfo());
// ---------------------------------- //
// Matchmaking : allow substitutes
MM_AllowSubstitutes(True);
***
***InitRound***
***
declare Integer RoundWinnerClan;
declare Integer SpawnClan1;
declare Integer SpawnClan2;
declare Integer InvincibilityEndTime;
***
***StartRound***
***
// ---------------------------------- //
// Combo initialization
RoundWinnerClan = 0;
G_ComboClan = 0;
G_ComboTime = 0;
G_ComboNextTick = 0;
G_ClanComboTimeLimit = [1 => C_Default_ComboTime, 2 => C_Default_ComboTime];
OffZoneRadius = -1.;
OffZoneRadiusSpeed = 0.;
G_OffZoneIsActivated = False;
Score::RoundBegin();
UpdateModeStatusMessage();
// ---------------------------------- //
// Initalize game
S_Script_RoundTimeLimit = S_RoundTimeLimit;
S_Script_PointsLimit = S_PointsLimit;
S_Script_NbPlayersPerTeam = S_NbPlayersPerTeam;
if (S_Script_NbPlayersPerTeam > C_NbPlayersPerTeamMax) {
S_Script_NbPlayersPerTeam = C_NbPlayersPerTeamMax;
}
StartTime = Now;
if (S_Script_RoundTimeLimit <= 0) {
UIManager.UIAll.CountdownEndTime = -1;
} else {
UIManager.UIAll.CountdownEndTime = StartTime + (S_Script_RoundTimeLimit * 1000);
}
// ---------------------------------- //
// Initialize players
foreach (Player in AllPlayers) {
InitializePlayer(Player);
}
UpdateClansPlayers();
// ---------------------------------- //
// Initialize objects
ObjectDestroyAll();
foreach (MapLandmark in MapLandmarks_ObjectAnchor) {
declare ObjectSpawned for MapLandmark = False;
declare ObjectNextSpawn for MapLandmark = Now;
ObjectSpawned = False;
ObjectNextSpawn = Now + C_Object_Delay;
declare netwrite Integer[Text] Net_Combo_ItemsRespawn for Teams[0];
Net_Combo_ItemsRespawn["Marker_Object"^MapLandmark.Id] = ObjectNextSpawn;
}
// ---------------------------------- //
// Spawn players
SpawnClan1 = 1;
SpawnClan2 = 1;
if (MB_SectionRoundNb % 2 == 0) {
SpawnClan1 = 2;
SpawnClan2 = 2;
}
foreach (Player in Players) {
if (!G_ClansPlayers.existskey(Player.CurrentClan)) continue;
if (!G_ClansPlayers[Player.CurrentClan].exists(Player.Id)) continue;
declare CSmMapPlayerSpawn MapLandmark_PlayerSpawn;
if (Player.CurrentClan == 1) {
MapLandmark_PlayerSpawn <=> Spawns[SpawnClan1];
SpawnClan1 = 3 - SpawnClan1;
} else if (Player.CurrentClan == 2) {
MapLandmark_PlayerSpawn <=> Spawns[SpawnClan2];
SpawnClan2 = 3 - SpawnClan2;
}
declare SpawnTime = Now + 2000;
if (SpawnTime < StartTime) SpawnTime = StartTime;
if (MapLandmark_PlayerSpawn != Null) SM::SpawnPlayer(Player, Player.CurrentClan, C_Default_Armor, MapLandmark_PlayerSpawn, SpawnTime);
}
// ---------------------------------- //
// Initialize UI
Net_Combo_ComboClan1 = G_ClanComboTimeLimit[1];
Net_Combo_ComboClan2 = G_ClanComboTimeLimit[2];
// ---------------------------------- //
// Update the players clublinks
if (S_ForceClublinkTeam1 == "" && S_ForceClublinkTeam2 == "") {
Clublink::DefineTeamAuto();
Clublink::SyncUpdate(); ///< Try to force the load of the clublink
} else {
Clublink::DefineTeamFromUrl(S_ForceClublinkTeam1, S_ForceClublinkTeam2);
}
// ---------------------------------- //
// Round start invincibility
InvincibilityEndTime = StartTime + C_RoundStartInvicibilityDuration;
UsePvPCollisions = False;
UsePvPWeapons = False;
Message::SendStatusMessage(_("Players are invincible"), InvincibilityEndTime - Now, 1);
***
***OnNewPlayer***
***
InitializePlayer(Player);
declare UI <=> UIManager.GetUI(Player);
if (UI != Null) {
UI.SpectatorForceCameraType = 1;
UI.SpectatorForcedClan = Player.CurrentClan;
}
***
***OnNewSpectator***
***
declare UI <=> UIManager.GetUI(Spectator);
if (UI != Null) {
UI.SpectatorForceCameraType = -1;
UI.SpectatorForcedClan = -1;
}
***
***Yield***
***
foreach (Event in XmlRpc.PendingEvents) {
if (Event.Type == CXmlRpcEvent::EType::CallbackArray) {
switch (Event.ParamArray1) {
case "Combo_SetTimersLayerPosition": {
declare netwrite Net_Combo_TimersLayerPosition for Teams[0] = C_LayerTimersPosition;
if (Event.ParamArray2.existskey(0)) {
Net_Combo_TimersLayerPosition.X = TL::ToReal(Event.ParamArray2[0]);
}
if (Event.ParamArray2.existskey(1)) {
Net_Combo_TimersLayerPosition.Y = TL::ToReal(Event.ParamArray2[1]);
}
if (Event.ParamArray2.existskey(2)) {
Net_Combo_TimersLayerPosition.Z = TL::ToReal(Event.ParamArray2[2]);
}
}
}
}
}
***
***PlayLoop***
***
// ---------------------------------- //
// Libraries
Message::Loop();
// ---------------------------------- //
// Check Action events
foreach (Event in PendingEvents) {
// ---------------------------------- //
// On armor empty
if (Event.Type == CSmModeEvent::EType::OnArmorEmpty) {
if (Event.Victim != Null) {
declare NewComboClan = 3 - Event.Victim.CurrentClan;
UpdateCombo(NewComboClan);
}
XmlRpc::OnArmorEmpty(Event);
PassOn(Event);
}
// ---------------------------------- //
// On hit
else if (Event.Type == CSmModeEvent::EType::OnHit) {
if (Event.Victim == Null || Event.Shooter == Event.Victim) {
Discard(Event);
} else if (Event.Shooter != Null && Event.Victim != Null && Event.Shooter.CurrentClan == Event.Victim.CurrentClan) {
Discard(Event);
} else {
if (Event.Damage > C_MaxDamage) Event.Damage = C_MaxDamage;
Score::AddPoints(Event.Shooter, 1);
XmlRpc::OnHit(Event);
if (Event.Shooter != Null) {
declare HitLaser for Event.Shooter.Score = 0;
declare HitNucleus for Event.Shooter.Score = 0;
declare HitArrow for Event.Shooter.Score = 0;
declare HitRocket for Event.Shooter.Score = 0;
switch (Event.WeaponNum) {
case 1: HitLaser += 1;
case 3: HitNucleus += 1;
case 5: HitArrow += 1;
case 2: HitRocket += 1;
}
ST2::SetColValue("HitsPerWeapon", Event.Shooter.Score, HitLaser^"/"^HitNucleus^"/"^HitArrow^"/"^HitRocket);
}
PassOn(Event);
}
}
// ---------------------------------- //
// On player request respawn
else if (Event.Type == CSmModeEvent::EType::OnPlayerRequestRespawn) {
if (Event.Player != Null) {
declare NewComboClan = 3 - Event.Player.CurrentClan;
UpdateCombo(NewComboClan);
}
XmlRpc::OnPlayerRequestRespawn(Event);
PassOn(Event);
}
// ---------------------------------- //
// On player touches object
else if (Event.Type == CSmModeEvent::EType::OnPlayerTouchesObject) {
if (Event.Player == Null) {
Discard(Event);
} else if (Event.Player != Null && Event.Player.SpawnStatus != CSmPlayer::ESpawnStatus::Spawned) {
Discard(Event);
} else {
PickUpObject(Event.Player, Event.Object);
PassOn(Event);
}
}
// ---------------------------------- //
// On action event
else if (Event.Type == CSmModeEvent::EType::OnActionEvent) {
if (Event.Player == Null) {
Discard(Event);
} else {
SwitchWeapon(Event.Player, Event.ActionInput);
PassOn(Event);
}
}
// ---------------------------------- //
// On player request action change
else if (Event.Type == CSmModeEvent::EType::OnPlayerRequestActionChange) {
if (Event.Player == Null) {
Discard(Event);
} else {
CycleWeapon(Event.Player, Event.ActionChange);
PassOn(Event);
}
}
// ---------------------------------- //
// Others
else {
PassOn(Event);
}
}
// ---------------------------------- //
// Round start invincibility
if (InvincibilityEndTime > 0 && InvincibilityEndTime <= Now) {
InvincibilityEndTime = -1;
UsePvPCollisions = True;
UsePvPWeapons = True;
UIManager.UIAll.SendNotice("", CUIConfig::ENoticeLevel::MatchInfo, Null, CUIConfig::EAvatarVariant::Default, CUIConfig::EUISound::PhaseChange, 0);
}
// ---------------------------------- //
// Start the storm
if (UIManager.UIAll.CountdownEndTime > 0 && UIManager.UIAll.CountdownEndTime <= Now) {
UIManager.UIAll.CountdownEndTime = -1;
OffZoneRadius = C_OffZoneRadiusMax;
OffZoneRadiusSpeed = (C_OffZoneRadiusMax - C_OffZoneRadiusMin) / ML::ToReal(C_OffZoneDuration);
G_OffZoneIsActivated = True;
UIManager.UIAll.StatusMessage = _("Direct elimination");
}
// ---------------------------------- //
// Stop the storm
if (OffZoneRadiusSpeed > 0. && OffZoneRadius <= C_OffZoneRadiusMin) {
OffZoneRadiusSpeed = 0.;
OffZoneRadius = C_OffZoneRadiusMin;
}
// ---------------------------------- //
// Spawn objects
Combo_SpawnObjects();
// ---------------------------------- //
// Update combo timer
if (G_ComboTime > 0) {
if (G_ComboNextTick <= Now) {
G_ComboNextTick = Now + 1000;
if (G_ComboTime > 0) {
Message::SendBigMessage(Teams[G_ComboClan-1].ColorText^(G_ComboTime / 1000), 1000, 1);
}
}
G_ComboTime -= Period;
if (G_ComboTime <= 0) {
G_ComboClan = 0;
G_ComboTime = 0;
}
}
// ---------------------------------- //
// Spawn players
foreach (Player in Players) {
if (G_ComboTime <= 0 && !G_OffZoneIsActivated) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned && !Player.RequestsSpectate) {
SetPlayerClan(Player, MM_GetRequestedClan(Player));
if (!G_ClansPlayers.existskey(Player.CurrentClan)) continue;
if (!G_ClansPlayers[Player.CurrentClan].exists(Player.Id)) continue;
Player.ArmorMax = C_Default_ArmorMax;
declare CSmMapPlayerSpawn MapLandmark_PlayerSpawn;
if (Player.CurrentClan == 1) {
MapLandmark_PlayerSpawn <=> Spawns[SpawnClan1];
SpawnClan1 = 3 - SpawnClan1;
} else if (Player.CurrentClan == 2) {
MapLandmark_PlayerSpawn <=> Spawns[SpawnClan2];
SpawnClan2 = 3 - SpawnClan2;
}
if (MapLandmark_PlayerSpawn != Null) SM::SpawnPlayer(Player, Player.CurrentClan, C_Default_Armor, MapLandmark_PlayerSpawn, Now);
declare netwrite Net_Combo_AmmoMax for Player = C_AmmoMax;
SetPlayerAmmo(Player, CSmMode::EWeapon::Rocket, Net_Combo_AmmoMax["Rocket"]/2);
SetPlayerAmmo(Player, CSmMode::EWeapon::Laser, Net_Combo_AmmoMax["Laser"]/2);
SetPlayerAmmo(Player, CSmMode::EWeapon::Nucleus, Net_Combo_AmmoMax["Nucleus"]/2);
SetPlayerAmmo(Player, CSmMode::EWeapon::Arrow, Net_Combo_AmmoMax["Arrow"]/2);
if (Player.Armor > C_ArmorReductionStart) {
declare NextArmorReduction for Player = -1;
NextArmorReduction = Now + C_ArmorReductionPeriod;
}
declare UI <=> UIManager.GetUI(Player);
if (UI != Null) {
UI.SpectatorForceCameraType = 1;
UI.SpectatorForcedClan = Player.CurrentClan;
}
}
}
if (S_UseArmorReduction) {
if (Player.Armor > C_ArmorReductionStart) {
declare NextArmorReduction for Player = -1;
if (NextArmorReduction > 0 && NextArmorReduction < Now) {
Player.Armor -= 100;
if (Player.Armor > C_ArmorReductionStart) {
NextArmorReduction = Now + C_ArmorReductionPeriod;
}
}
}
}
}
// ---------------------------------- //
// Check if we need more players
UpdateClansPlayers();
// ---------------------------------- //
// Update settings
if (S_Script_RoundTimeLimit != S_RoundTimeLimit) {
S_Script_RoundTimeLimit = S_RoundTimeLimit;
if (S_Script_RoundTimeLimit <= 0) {
UIManager.UIAll.CountdownEndTime = -1;
} else {
UIManager.UIAll.CountdownEndTime = StartTime + (S_Script_RoundTimeLimit * 1000);
}
}
if (S_Script_PointsLimit != S_PointsLimit) {
S_Script_PointsLimit = S_PointsLimit;
ST2::SetFooterText(TL::Compose("%1 "^S_PointsLimit, _("Points limit : ")));
}
if (S_Script_NbPlayersPerTeam != S_NbPlayersPerTeam) {
S_Script_NbPlayersPerTeam = S_NbPlayersPerTeam;
Layers::Update("Info", UpdateLayerInfo());
}
// ---------------------------------- //
// victory conditions
declare EndRound = False;
declare EndMap = False;
if (ClansNbPlayers[1] == 0) {
EndMap = True;
RoundWinnerClan = 2;
MapWinnerClan = 2;
} else if (ClansNbPlayers[2] == 0) {
EndMap = True;
RoundWinnerClan = 1;
MapWinnerClan = 1;
} else if (ClansNbPlayersAlive[1] == 0) {
EndRound = True;
RoundWinnerClan = 2;
} else if (ClansNbPlayersAlive[2] == 0) {
EndRound = True;
RoundWinnerClan = 1;
}
if (G_ComboTime > 0) {
if (G_ComboClan == 1 && ClansNbPlayersAlive[2] == 0) {
EndRound = True;
RoundWinnerClan = 1;
} else if (G_ComboClan == 2 && ClansNbPlayersAlive[1] == 0) {
EndRound = True;
RoundWinnerClan = 2;
}
}
if (EndMap || EndRound) MB_StopRound = True;
if (EndMap) MB_StopMap = True;
***
***EndRound***
***
UIManager.UIAll.StatusMessage = "";
Message::CleanAllMessages();
Score::RoundEnd();
UIManager.UIAll.CountdownEndTime = -1;
OffZoneRadius = -1.;
OffZoneRadiusSpeed = 0.;
G_OffZoneIsActivated = False;
// ---------------------------------- //
// Update scores
if (ClanScores.existskey(RoundWinnerClan)) {
ClanScores[RoundWinnerClan] += 1;
if (RoundWinnerClan == 1 || RoundWinnerClan == 2) {
Message::SendBigMessage(TL::Compose(_("$<%1$> wins the round"), Teams[RoundWinnerClan - 1].ColorizedName), 3000, 1);
}
}
UpdateScoresHeader();
UpdateModeStatusMessage();
// ---------------------------------- //
// Save the current player clan for ladder ranking
foreach (Player in Players) {
if (Player.Score == Null) continue;
Player.Score.LadderClan = Player.CurrentClan;
}
// ---------------------------------- //
// Check if the points limit is reached
declare EndMap = False;
if (S_Script_PointsLimit > 0) {
if (ClanScores[1] >= S_Script_PointsLimit && ClanScores[1] > ClanScores[2]) {
EndMap = True;
MapWinnerClan = 1;
} else if (ClanScores[2] >= S_Script_PointsLimit && ClanScores[2] > ClanScores[1]) {
EndMap = True;
MapWinnerClan = 2;
}
}
if (EndMap) {
MB_StopMap = True;
} else {
MM_Sleep(500);
SM::UnspawnAllPlayers();
StartTime = -1;
MM_Sleep(2500);
}
***
***EndMap***
***
MM_Sleep(500);
StartTime = -1;
EndTime = -1;
ObjectDestroyAll();
Markers::Clear();
// ---------------------------------- //
// Update UI
UIManager.UIAll.CountdownEndTime = -1;
Message::CleanAllMessages();
Layers::Detach("Info");
declare MasterLogin = "";
declare MasterPoints = 0;
foreach (Score in Scores) {
Score.LadderMatchScoreValue = ML::ToReal(Score.Points);
declare PrevPoints for Score = 0;
PrevPoints = Score.Points;
if (Score.Points > MasterPoints) {
MasterPoints = Score.Points;
MasterLogin = Score.User.Login;
}
if (Score.LadderClan == MapWinnerClan) {
Score.Points = 3;
Score.LadderMatchScoreValue *= 2.;
} else if (Score.LadderClan == 3 - MapWinnerClan) {
Score.Points = 2;
Score.LadderMatchScoreValue *= 1.;
} else {
Score.Points = 1;
Score.LadderMatchScoreValue *= 0.5;
}
}
Ladder_SetResultsVersion(1);
Score::MatchEnd(True);
foreach (Score in Scores) {
declare PrevPoints for Score = 0;
Score.Points = PrevPoints;
}
// ---------------------------------- //
// Send match result
if (S_MatchmakingMode == 2) {
MM_MatchEnd(MasterLogin);
}
// ---------------------------------- //
// Winning sequence
UIManager.UIAll.UISequence = CUIConfig::EUISequence::EndRound;
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::EndMatch;
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
if (MapWinnerClan == 1 || MapWinnerClan == 2) {
UIManager.UIAll.BigMessage = TL::Compose(_("$<%1$> wins the map"), Teams[MapWinnerClan - 1].ColorizedName);
} else {
UIManager.UIAll.BigMessage = _("|Match|Draw");
}
MM_Sleep(C_SleepEndMap/2);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Podium;
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
MM_Sleep(C_SleepEndMap/2);
UIManager.UIAll.BigMessage = "";
// ---------------------------------- //
// Transfert players back to the lobby
if (S_MatchmakingMode == 2) {
MM_MatchToLobby();
}
***
***EndServer***
***
WarmUp2::Unload();
SpawnScreen::DestroyRules();
Markers::Unload();
// ---------------------------------- //
// Destroy layer
Layers::Destroy("Info");
***
// ---------------------------------- //
/// Update the ModeStatusMessage
Void UpdateModeStatusMessage() {
declare Text BaseRules = _("Eliminate all the enemy team.");
declare Text RoundsToWinSetting = ""^S_PointsLimit;
declare Text MatchScore = ClanScores[1] ^ " - " ^ ClanScores[2];
ModeStatusMessage = TL::Compose("%1\nRounds to win: %2 \\ Current Score: %3", BaseRules, RoundsToWinSetting, MatchScore);
}
Void InitializePlayer(CSmPlayer _Player) {
SetPlayerClan(_Player, MM_GetRequestedClan(_Player));
declare NextArmorReduction for _Player = -1;
NextArmorReduction = -1;
declare netwrite Net_Combo_AmmoUpdate for _Player = _Player.Login^"_"^Now;
declare netwrite Net_Combo_AmmoMax for _Player = C_AmmoMax;
declare netwrite Net_Combo_Weapon for _Player = "Rocket";
Net_Combo_AmmoUpdate = _Player.Login^"_"^Now;
Net_Combo_AmmoMax = C_AmmoMax;
Net_Combo_Weapon = "Rocket";
declare CurrentWeapon for _Player = C_Default_Weapon;
declare Weapons for _Player = C_Default_Weapons;
CurrentWeapon = C_Default_Weapon;
Weapons = C_Default_Weapons;
_Player.ArmorMax = C_Default_ArmorMax;
_Player.AmmoGain = C_AmmoGain["Rocket"];
SetPlayerWeapon(_Player, C_Default_Weapon, False);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Rocket, Net_Combo_AmmoMax["Rocket"]);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Laser, Net_Combo_AmmoMax["Laser"]);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Nucleus, Net_Combo_AmmoMax["Nucleus"]);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Arrow, Net_Combo_AmmoMax["Arrow"]);
SetPlayerReloadAllWeapons(_Player, True);
}
// ---------------------------------- //
/// Update the base colors
Void UpdateBasesColors() {
foreach (MapBase in MapBases) {
MapBase.Clan = 0;
MapBase.IsActive = True;
}
}
// ---------------------------------- //
/** Update the combo
*
* @param _NewComboClan The clan who updated the combo
*/
Void UpdateCombo(Integer _NewComboClan) {
// Start combo
if (G_ComboClan == 0 || G_ComboClan == _NewComboClan) {
if (!G_OffZoneIsActivated) {
G_ComboClan = _NewComboClan;
G_ComboNextTick = Now;
if (G_ClanComboTimeLimit.existskey(G_ComboClan)) {
G_ComboTime = G_ClanComboTimeLimit[G_ComboClan];
G_ClanComboTimeLimit[G_ComboClan] += C_ComboTimeStep;
Message::SendBigMessage(Teams[G_ComboClan-1].ColorText^(G_ComboTime / 1000), 1000, 1, CUIConfig::EUISound::TieBreakPoint, 0);
if (_NewComboClan == 1) {
Net_Combo_ComboClan1 = G_ClanComboTimeLimit[G_ComboClan];
} else if (_NewComboClan == 2) {
Net_Combo_ComboClan2 = G_ClanComboTimeLimit[G_ComboClan];
}
}
}
}
// Combo breaker
else {
G_ComboClan = 0;
G_ComboTime = 0;
if (Teams.existskey(_NewComboClan-1)) {
declare Message = TL::Compose("%1%2", Teams[_NewComboClan-1].ColorText, _("Combo breaker"));
Message::SendBigMessage(Message, 3000, 1, CUIConfig::EUISound::TiePoint, 0);
}
}
}
// ---------------------------------- //
/// Update the scores header
Void UpdateScoresHeader() {
UIManager.UIAll.OverlayScoreSummary = True;
declare PlayerClan1Id = NullId;
declare PlayerClan2Id = NullId;
foreach (Player in Players) {
if ((PlayerClan1Id == NullId) && (Player.CurrentClan == 1)) PlayerClan1Id = Player.Id;
if ((PlayerClan2Id == NullId) && (Player.CurrentClan == 2)) PlayerClan2Id = Player.Id;
if (PlayerClan1Id != NullId && PlayerClan2Id != NullId) break;
}
if (PlayerClan1Id != NullId) UIManager.UIAll.ScoreSummary_Player1 = PlayerClan1Id;
else UIManager.UIAll.ScoreSummary_Player1 = NullId;
if (PlayerClan2Id != NullId) UIManager.UIAll.ScoreSummary_Player2 = PlayerClan2Id;
else UIManager.UIAll.ScoreSummary_Player2 = NullId;
UIManager.UIAll.ScoreSummary_Points1 = ClanScores[1];
UIManager.UIAll.ScoreSummary_Points2 = ClanScores[2];
UIManager.UIAll.ScoreSummary_MatchPoints1 = -1;
UIManager.UIAll.ScoreSummary_MatchPoints2 = -1;
}
// ---------------------------------- //
/** Create the script for the layer Markers
*
* @return The script of the layer Markers
*/
Text GetMLMarkersScript() {
return """
declare CMlLabel[Integer] Labels_Timer;
declare CMlQuad[Integer] Quads_Timer;
Void UpdateTimers() {
declare netread Integer[Text] Net_Combo_ItemsRespawn for Teams[0];
foreach (Key => Label_Timer in Labels_Timer) {
declare Text ObjectId for Label_Timer;
declare Quad_Timer = Quads_Timer[Key];
if (ObjectId == "" || !Net_Combo_ItemsRespawn.existskey(ObjectId)) {
if (Label_Timer.Value != "-") {
Label_Timer.Value = "-";
Quad_Timer.ModulateColor = <0., 1., 0.>;
}
} else {
declare TimeRemaining = (Net_Combo_ItemsRespawn[ObjectId] - ArenaNow) / 1000;
if (TimeRemaining > 0) {
Label_Timer.Value = ""^TimeRemaining;
if (Quads_Timer[Key].ModulateColor != <1., 0., 0.>) Quads_Timer[Key].ModulateColor = <1., 0., 0.>;
} else if (Label_Timer.Value != "-") {
Label_Timer.Value = "-";
Quad_Timer.ModulateColor = <0., 1., 0.>;
}
}
}
}
main() {
declare Frame_Global <=> (Page.GetFirstChild("Frame_Global") as CMlFrame);
Page.GetClassChildren("MarkerObject", Frame_Global, False);
declare Key = 0;
foreach (Marker_Object in Page.GetClassChildren_Result) {
declare Label_Timer <=> ((Marker_Object as CMlFrame).GetFirstChild("Label_Timer") as CMlLabel);
declare Text ObjectId for Label_Timer;
ObjectId = Marker_Object.ControlId;
Labels_Timer[Key] = Label_Timer;
declare Quad_Timer <=> ((Marker_Object as CMlFrame).GetFirstChild("Quad_Timer") as CMlQuad);
Quads_Timer[Key] = Quad_Timer;
Key += 1;
}
Frame_Global.Visible = False;
declare MarkersVisible for UI = False;
declare NextUpdate = Now;
declare PrevIsSpectatorMode = False;
declare PrevMarkersVisible = False;
while (True) {
yield;
if (!PageIsVisible || InputPlayer == Null) continue;
if (PrevIsSpectatorMode != IsSpectatorMode || PrevMarkersVisible != MarkersVisible) {
PrevIsSpectatorMode = IsSpectatorMode;
PrevMarkersVisible = MarkersVisible;
if (IsSpectatorMode && MarkersVisible) {
Frame_Global.Visible = True;
} else {
Frame_Global.Visible = False;
}
}
if (Now >= NextUpdate) {
NextUpdate = Now + 1000;
UpdateTimers();
}
}
}""";
}
// ---------------------------------- //
/// Create the markers manialinks
Void CreateMarkers() {
declare TypeCount = Integer[Text];
declare ImagePath = "";
declare ImageSize = "";
foreach (MapLandmark in MapLandmarks_ObjectAnchor) {
if (!C_Object.exists(MapLandmark.Tag)) continue;
declare Pos = MapLandmark.Position.X^" "^(MapLandmark.Position.Y+1.)^" "^MapLandmark.Position.Z;
declare ManialinkFrameId = "Marker_Object"^MapLandmark.Id;
if (!TypeCount.existskey(MapLandmark.Tag)) TypeCount[MapLandmark.Tag] = 0;
TypeCount[MapLandmark.Tag] += 1;
if (MapLandmark.Tag == "Armor") {
ImagePath = C_ImgBaseDir^"ShieldWhite.dds";
ImageSize = "4 6";
} else {
ImagePath = C_ImgBaseDir^MapLandmark.Tag^"White.dds";
ImageSize = "5 6";
}
declare Marker = """<marker pos="{{{Pos}}}" manialinkframeid="{{{ManialinkFrameId}}}" />""";
declare Manialink = """
<frame scale="0.75" class="MarkerObject" id="{{{ManialinkFrameId}}}">
<quad posn="0 0 -1" sizen="12 10" halign="center" valign="bottom" style="Bgs1InRace" substyle="BgList" modulatecolor="f00" id="Quad_Timer" />
<frame posn="0 5 0">
<format textemboss="1" />
<!--<label posn="-3.5 0" sizen="5 5" textsize="2" halign="right" valign="center2" text="#{{{TypeCount[MapLandmark.Tag]}}}" />-->
<quad posn="-1 0" sizen="{{{ImageSize}}}" halign="right" valign="center" image="{{{ImagePath}}}" />
<label posn="2.5 0" sizen="5 5" textsize="3" halign="center" valign="center2" id="Label_Timer" />
</frame>
</frame>""";
Markers::Add(Marker, Manialink);
}
Markers::SetManialinkScript(GetMLMarkersScript());
}
// ---------------------------------- //
/// Update the players lists on the side of the screen
Text UpdateLayerInfo() {
declare LoginsTeam = [1 => "", 2 => ""];
for (Clan, 1, 2) {
if (!G_ClansPlayers.existskey(Clan)) continue;
foreach (PlayerId in G_ClansPlayers[Clan]) {
if (!Players.existskey(PlayerId)) continue;
if (LoginsTeam[Clan] == "") LoginsTeam[Clan] ^= Players[PlayerId].Login;
else LoginsTeam[Clan] ^= ","^Players[PlayerId].Login;
}
}
declare TimersHeight = 0.;
declare TypeCount = Integer[Text];
declare ImagePath = "";
declare ImageSize = "";
declare Timers = "";
foreach (MapLandmark in MapLandmarks_ObjectAnchor) {
if (!C_Object.exists(MapLandmark.Tag)) continue;
if (TimersHeight >= 120.) break;
declare Pos = "0 "^TimersHeight;
declare ManialinkFrameId = "Marker_Object"^MapLandmark.Id;
if (!TypeCount.existskey(MapLandmark.Tag)) TypeCount[MapLandmark.Tag] = 0;
TypeCount[MapLandmark.Tag] += 1;
if (MapLandmark.Tag == "Armor") {
ImagePath = C_ImgBaseDir^"ShieldWhite.dds";
ImageSize = "4 6";
} else {
ImagePath = C_ImgBaseDir^MapLandmark.Tag^"White.dds";
ImageSize = "5 6";
}
TimersHeight += 10.;
Timers ^= """
<frame posn="{{{Pos}}}" class="FrameTimer" id="{{{ManialinkFrameId}}}">
<quad posn="0 0 -1" sizen="21 10" halign="center" valign="bottom" style="Bgs1InRace" substyle="BgList" modulatecolor="f00" id="Quad_Timer" />
<frame posn="-1 5 0">
<format textemboss="1" />
<label posn="-3.5 0" sizen="5 5" textsize="2" halign="right" valign="center2" text="#{{{TypeCount[MapLandmark.Tag]}}}" />
<quad posn="2 0" sizen="{{{ImageSize}}}" halign="right" valign="center" image="{{{ImagePath}}}" />
<label posn="5.5 0" sizen="5 5" textsize="3" halign="center" valign="center2" id="Label_Timer" />
</frame>
</frame>""";
}
return """
<frame posn="-160 68">
<quad sizen="41 4" halign="left" bgcolor="0007" />
<quad posn="1 5 1" sizen="10 10" halign="left" style="Emblems" substyle="#1" />
<label id="team1name" posn="11 0 1" sizen="40 4" halign="left" textprefix="$s" text="Blue" />
<playerlist posn="0 -5" scale="0.75" halign="left" substyle="Medium" lines="{{{S_Script_NbPlayersPerTeam}}}" columns="1" team="1" status="Playing" logins="{{{LoginsTeam[1]}}}" />
</frame>
<frame posn="160 68">
<quad sizen="41 4" halign="right" bgcolor="0007" />
<quad posn="-1 5 1" sizen="10 10" halign="right" style="Emblems" substyle="#2" />
<label id="team2name" posn="-11 0 1" sizen="40 4" halign="right" textprefix="$s" text="Red" />
<playerlist posn="0 -5" scale="0.75" halign="right" substyle="Medium" lines="{{{S_Script_NbPlayersPerTeam}}}" columns="1" team="2" status="Playing" logins="{{{LoginsTeam[2]}}}"/>
</frame>
<frame posn="0 71 5" id="Frame_ScoreInfo">
<label posn="-25 0.5 6" sizen="15 5" textsize="4" halign="right" valign="center" textemboss="1" text="0" id="Label_ComboClan1" />
<quad posn="-22 0 6" sizen="5 5" halign="center" valign="center" style="Icons64x64_1" substyle="GenericButton" />
<quad posn=" 22 0 6" sizen="5 5" halign="center" valign="center" style="Icons64x64_1" substyle="GenericButton" />
<label posn="25 0.5 6" sizen="15 5" textsize="4" halign="left" valign="center" textemboss="1" text="0" id="Label_ComboClan2" />
</frame>
<frame posn="-68 -76" id="Frame_WeaponInfo">
<quad posn="0 0" sizen="6 6" halign="right" valign="center" image="{{{C_ImgBaseDir}}}LaserWhite.dds" id="Quad_IconLaser" />
<quad posn="12 0" sizen="6 6" halign="right" valign="center" image="{{{C_ImgBaseDir}}}NucleusWhite.dds" id="Quad_IconNucleus" />
<quad posn="24 0" sizen="6 6" halign="right" valign="center" image="{{{C_ImgBaseDir}}}ArrowWhite.dds" id="Quad_IconArrow" />
<quad posn="36 0" sizen="6 6" halign="right" valign="center" image="{{{C_ImgBaseDir}}}RocketWhite.dds" id="Quad_IconRocket" />
<frame posn="0 0.3">
<label posn="0 0" sizen="6 6" halign="left" valign="center" textemboss="1" text="0" id="Label_AmmoLaser" />
<label posn="12 0" sizen="6 6" halign="left" valign="center" textemboss="1" text="0" id="Label_AmmoNucleus" />
<label posn="24 0" sizen="6 6" halign="left" valign="center" textemboss="1" text="0" id="Label_AmmoArrow" />
<label posn="36 0" sizen="6 6" halign="left" valign="center" textemboss="1" text="0" id="Label_AmmoRocket" />
</frame>
</frame>
<frame id="Frame_Spec">
<frame posn="{{{C_LayerTimersPosition.X}}} {{{C_LayerTimersPosition.Y}}} {{{C_LayerTimersPosition.Z}}}" id="Frame_Timers">
{{{Timers}}}
</frame>
<frame posn="159 -83">
<label halign="right" style="CardButtonSmallS" text="Show markers" scriptevents="1" id="Button_DisplayMarkers" />
<label posn="0 6" halign="right" style="CardButtonSmallS" text="Show list" scriptevents="1" id="Button_DisplayList" />
</frame>
</frame>
<script><!--
#Include "TextLib" as TL
declare CMlQuad Quad_IconLaser;
declare CMlQuad Quad_IconNucleus;
declare CMlQuad Quad_IconArrow;
declare CMlQuad Quad_IconRocket;
declare CMlLabel Label_AmmoLaser;
declare CMlLabel Label_AmmoNucleus;
declare CMlLabel Label_AmmoArrow;
declare CMlLabel Label_AmmoRocket;
declare CMlLabel[Integer] Labels_Timer;
declare CMlQuad[Integer] Quads_Timer;
Void UpdateTimers() {
declare netread Integer[Text] Net_Combo_ItemsRespawn for Teams[0];
foreach (Key => Label_Timer in Labels_Timer) {
declare Text ObjectId for Label_Timer;
declare Quad_Timer = Quads_Timer[Key];
if (ObjectId == "" || !Net_Combo_ItemsRespawn.existskey(ObjectId)) {
if (Label_Timer.Value != "-") {
Label_Timer.Value = "-";
Quad_Timer.ModulateColor = <0., 1., 0.>;
}
} else {
declare TimeRemaining = (Net_Combo_ItemsRespawn[ObjectId] - ArenaNow) / 1000;
if (TimeRemaining > 0) {
Label_Timer.Value = ""^TimeRemaining;
if (Quads_Timer[Key].ModulateColor != <1., 0., 0.>) Quads_Timer[Key].ModulateColor = <1., 0., 0.>;
} else if (Label_Timer.Value != "-") {
Label_Timer.Value = "-";
Quad_Timer.ModulateColor = <0., 1., 0.>;
}
}
}
}
Void UpdateAmmoMax(Integer[Text] _AmmoMax) {
foreach (Weapon => AmmoMax in _AmmoMax) {
declare WeaponText = "$aaa"^AmmoMax;
declare WeaponIcon = "{{{C_ImgBaseDir}}}"^Weapon^".dds";
if (AmmoMax > 0) {
WeaponText = "$fff"^AmmoMax;
WeaponIcon = "{{{C_ImgBaseDir}}}"^Weapon^"White.dds";
}
switch (Weapon) {
case "Laser" : {
Label_AmmoLaser.SetText(WeaponText);
if (Http.IsValidUrl(WeaponIcon)) Quad_IconLaser.ChangeImageUrl(WeaponIcon);
}
case "Nucleus" : {
Label_AmmoNucleus.SetText(WeaponText);
if (Http.IsValidUrl(WeaponIcon)) Quad_IconNucleus.ChangeImageUrl(WeaponIcon);
}
case "Arrow" : {
Label_AmmoArrow.SetText(WeaponText);
if (Http.IsValidUrl(WeaponIcon)) Quad_IconArrow.ChangeImageUrl(WeaponIcon);
}
case "Rocket" : {
Label_AmmoRocket.SetText(WeaponText);
if (Http.IsValidUrl(WeaponIcon)) Quad_IconRocket.ChangeImageUrl(WeaponIcon);
}
}
}
}
Void UpdateWeapon(Text _PrevWeapon, Text _NewWeapon) {
switch (_PrevWeapon) {
case "Laser" : Quad_IconLaser.RelativeScale = 1.;
case "Nucleus" : Quad_IconNucleus.RelativeScale = 1.;
case "Arrow" : Quad_IconArrow.RelativeScale = 1.;
case "Rocket" : Quad_IconRocket.RelativeScale = 1.;
}
switch (_NewWeapon) {
case "Laser" : Quad_IconLaser.RelativeScale = 1.3;
case "Nucleus" : Quad_IconNucleus.RelativeScale = 1.3;
case "Arrow" : Quad_IconArrow.RelativeScale = 1.3;
case "Rocket" : Quad_IconRocket.RelativeScale = 1.3;
}
}
main() {
declare Frame_WeaponInfo <=> (Page.GetFirstChild("Frame_WeaponInfo") as CMlFrame);
declare Label_Team1Name <=> (Page.GetFirstChild("team1name") as CMlLabel);
declare Label_Team2Name <=> (Page.GetFirstChild("team2name") as CMlLabel);
declare Label_ComboClan1 <=> (Page.GetFirstChild("Label_ComboClan1") as CMlLabel);
declare Label_ComboClan2 <=> (Page.GetFirstChild("Label_ComboClan2") as CMlLabel);
Label_AmmoLaser <=> (Page.GetFirstChild("Label_AmmoLaser") as CMlLabel);
Label_AmmoNucleus <=> (Page.GetFirstChild("Label_AmmoNucleus") as CMlLabel);
Label_AmmoArrow <=> (Page.GetFirstChild("Label_AmmoArrow") as CMlLabel);
Label_AmmoRocket <=> (Page.GetFirstChild("Label_AmmoRocket") as CMlLabel);
Quad_IconLaser <=> (Page.GetFirstChild("Quad_IconLaser") as CMlQuad);
Quad_IconNucleus <=> (Page.GetFirstChild("Quad_IconNucleus") as CMlQuad);
Quad_IconArrow <=> (Page.GetFirstChild("Quad_IconArrow") as CMlQuad);
Quad_IconRocket <=> (Page.GetFirstChild("Quad_IconRocket") as CMlQuad);
declare Frame_Timers <=> (Page.GetFirstChild("Frame_Timers") as CMlFrame);
declare Frame_Spec <=> (Page.GetFirstChild("Frame_Spec") as CMlFrame);
declare Button_DisplayList <=> (Page.GetFirstChild("Button_DisplayList") as CMlLabel);
declare Button_DisplayMarkers <=> (Page.GetFirstChild("Button_DisplayMarkers") as CMlLabel);
Page.GetClassChildren("FrameTimer", Frame_Timers, False);
declare Key = 0;
foreach (Marker_Object in Page.GetClassChildren_Result) {
declare Label_Timer <=> ((Marker_Object as CMlFrame).GetFirstChild("Label_Timer") as CMlLabel);
declare Text ObjectId for Label_Timer;
ObjectId = Marker_Object.ControlId;
Labels_Timer[Key] = Label_Timer;
declare Quad_Timer <=> ((Marker_Object as CMlFrame).GetFirstChild("Quad_Timer") as CMlQuad);
Quads_Timer[Key] = Quad_Timer;
Key += 1;
}
declare MarkersVisible for UI = False;
declare ListVisible = True;
if (MarkersVisible) Button_DisplayMarkers.Value = "{{{_("Hide markers")}}}";
else Button_DisplayMarkers.Value = "{{{_("Show markers")}}}";
if (ListVisible) Button_DisplayList.Value = "{{{_("Hide list")}}}";
else Button_DisplayList.Value = "{{{_("Show list")}}}";
declare netread Vec3 Net_Combo_TimersLayerPosition for Teams[0];
declare Vec3 PrevTimersLayerPosition;
declare PrevTeam1Name = "";
declare PrevTeam2Name = "";
declare PrevComboClan1 = 0;
declare PrevComboClan2 = 0;
declare PrevAmmoUpdate = "";
declare PrevWeapon = "";
declare NextUpdateTimers = Now;
declare NextUpdate = Now;
while (True) {
yield;
foreach (Event in PendingEvents) {
if (Event.Type == CMlEvent::Type::MouseClick) {
if (Event.ControlId == "Button_DisplayMarkers") {
MarkersVisible = !MarkersVisible;
if (MarkersVisible) Button_DisplayMarkers.Value = "{{{_("Hide markers")}}}";
else Button_DisplayMarkers.Value = "{{{_("Show markers")}}}";
} else if (Event.ControlId == "Button_DisplayList") {
ListVisible = !ListVisible;
if (ListVisible) {
Frame_Timers.Visible = True;
Button_DisplayList.Value = "{{{_("Hide list")}}}";
} else {
Frame_Timers.Visible = False;
Button_DisplayList.Value = "{{{_("Show list")}}}";
}
}
}
}
if (!PageIsVisible || InputPlayer == Null) continue;
if (Now < NextUpdate) continue;
NextUpdate = Now + 250;
if (PrevTeam1Name != Teams[0].ColorizedName) {
PrevTeam1Name = Teams[0].ColorizedName;
Label_Team1Name.SetText(Teams[0].ColorizedName);
}
if (PrevTeam2Name != Teams[1].ColorizedName) {
PrevTeam2Name = Teams[1].ColorizedName;
Label_Team2Name.SetText(Teams[1].ColorizedName);
}
if (PrevComboClan1 != Net_Combo_ComboClan1) {
PrevComboClan1 = Net_Combo_ComboClan1;
Label_ComboClan1.SetText(TL::ToText(PrevComboClan1/1000));
}
if (PrevComboClan2 != Net_Combo_ComboClan2) {
PrevComboClan2 = Net_Combo_ComboClan2;
Label_ComboClan2.SetText(TL::ToText(PrevComboClan2/1000));
}
if (PrevTimersLayerPosition != Net_Combo_TimersLayerPosition) {
PrevTimersLayerPosition = Net_Combo_TimersLayerPosition;
Frame_Timers.RelativePosition = Net_Combo_TimersLayerPosition;
}
if (Now >= NextUpdateTimers) {
NextUpdateTimers = Now + 1000;
UpdateTimers();
}
if (IsSpectatorMode && GUIPlayer != Null) {
declare netread Text Net_Combo_AmmoUpdate for GUIPlayer;
declare netread Integer[Text] Net_Combo_AmmoMax for GUIPlayer;
declare netread Text Net_Combo_Weapon for GUIPlayer;
if (PrevAmmoUpdate != Net_Combo_AmmoUpdate) {
PrevAmmoUpdate = Net_Combo_AmmoUpdate;
UpdateAmmoMax(Net_Combo_AmmoMax);
}
if (PrevWeapon != Net_Combo_Weapon) {
UpdateWeapon(PrevWeapon, Net_Combo_Weapon);
PrevWeapon = Net_Combo_Weapon;
}
if (!Frame_WeaponInfo.Visible) Frame_WeaponInfo.Visible = True;
if (!Frame_Spec.Visible) {
Frame_Spec.Visible = True;
}
} else if (IsSpectatorMode) {
if (Frame_WeaponInfo.Visible) Frame_WeaponInfo.Visible = False;
if (!Frame_Spec.Visible) {
Frame_Spec.Visible = True;
}
} else {
declare netread Text Net_Combo_AmmoUpdate for InputPlayer;
declare netread Integer[Text] Net_Combo_AmmoMax for InputPlayer;
declare netread Text Net_Combo_Weapon for InputPlayer;
if (PrevAmmoUpdate != Net_Combo_AmmoUpdate) {
PrevAmmoUpdate = Net_Combo_AmmoUpdate;
UpdateAmmoMax(Net_Combo_AmmoMax);
}
if (PrevWeapon != Net_Combo_Weapon) {
UpdateWeapon(PrevWeapon, Net_Combo_Weapon);
PrevWeapon = Net_Combo_Weapon;
}
if (!Frame_WeaponInfo.Visible) Frame_WeaponInfo.Visible = True;
if (Frame_Spec.Visible) {
Frame_Spec.Visible = False;
}
}
}
}
--></script>""";
}
// ---------------------------------- //
/// Update the players allowed to play
Void UpdateClansPlayers() {
declare ToRemove = [1 => Ident[], 2 => Ident[]];
declare AllowedPlayers = Ident[];
declare PlayersListNeedUpdate = False;
foreach (Clan => ClanPlayers in G_ClansPlayers) {
foreach (PlayerId in ClanPlayers) {
if (!Players.existskey(PlayerId)) {
ToRemove[Clan].add(PlayerId);
if (!S_AllowUnbalancedTeams || PlayerId != NullId) UpdateCombo(3 - Clan);
} else {
AllowedPlayers.add(PlayerId);
}
}
}
foreach (Clan => ClanPlayers in ToRemove) {
foreach (PlayerId in ClanPlayers) {
declare Removed = G_ClansPlayers[Clan].remove(PlayerId);
PlayersListNeedUpdate = True;
}
}
for (Clan, 1, 2) {
if (G_ClansPlayers[Clan].count < S_Script_NbPlayersPerTeam) {
if (ClansNbPlayers[Clan] > ClansNbPlayersAlive[Clan]) {
foreach (Player in Players) {
if (AllowedPlayers.exists(Player.Id)) continue;
SetPlayerClan(Player, MM_GetRequestedClan(Player));
if (Player.CurrentClan == Clan) {
G_ClansPlayers[Clan].add(Player.Id);
PlayersListNeedUpdate = True;
}
}
}
}
}
if (PlayersListNeedUpdate) {
Layers::Update("Info", UpdateLayerInfo());
}
}
Integer GetWeaponOrder(CSmMode::EWeapon _Weapon) {
switch (_Weapon) {
case CSmMode::EWeapon::Laser : return 1;
case CSmMode::EWeapon::Nucleus : return 2;
case CSmMode::EWeapon::Arrow : return 3;
case CSmMode::EWeapon::Rocket : return 4;
default: return 0;
}
return 0;
}
// ---------------------------------- //
/** Switch the weapon of a player
*
* @param _Player The player who will switch weapon
* @param _Weapon The number of the new weapon
*/
Void SwitchWeapon(CSmPlayer _Player, CSmModeEvent::EActionInput _Weapon) {
declare Weapons for _Player = C_Default_Weapons;
declare CurrentWeapon for _Player = C_Default_Weapon;
switch (_Weapon) {
// Rocket
case CSmModeEvent::EActionInput::Activable4: {
if (!Weapons.exists(CSmMode::EWeapon::Rocket)) return;
SetPlayerWeapon(_Player, CSmMode::EWeapon::Rocket, False);
CurrentWeapon = CSmMode::EWeapon::Rocket;
_Player.AmmoGain = C_AmmoGain["Rocket"];
declare netwrite Text Net_Combo_Weapon for _Player;
Net_Combo_Weapon = "Rocket";
}
// Laser
case CSmModeEvent::EActionInput::Activable1: {
if (!Weapons.exists(CSmMode::EWeapon::Laser)) return;
SetPlayerWeapon(_Player, CSmMode::EWeapon::Laser, False);
CurrentWeapon = CSmMode::EWeapon::Laser;
_Player.AmmoGain = C_AmmoGain["Laser"];
declare netwrite Text Net_Combo_Weapon for _Player;
Net_Combo_Weapon = "Laser";
}
// Nucleus
case CSmModeEvent::EActionInput::Activable2: {
if (!Weapons.exists(CSmMode::EWeapon::Nucleus)) return;
SetPlayerWeapon(_Player, CSmMode::EWeapon::Nucleus, False);
CurrentWeapon = CSmMode::EWeapon::Nucleus;
_Player.AmmoGain = C_AmmoGain["Nucleus"];
declare netwrite Text Net_Combo_Weapon for _Player;
Net_Combo_Weapon = "Nucleus";
}
// Arrow
case CSmModeEvent::EActionInput::Activable3: {
if (!Weapons.exists(CSmMode::EWeapon::Arrow)) return;
SetPlayerWeapon(_Player, CSmMode::EWeapon::Arrow, False);
CurrentWeapon = CSmMode::EWeapon::Arrow;
_Player.AmmoGain = C_AmmoGain["Arrow"];
declare netwrite Text Net_Combo_Weapon for _Player;
Net_Combo_Weapon = "Arrow";
}
}
}
// ---------------------------------- //
/** Cycle through the available weapons
*
* @param _Player The player who will cycle through his weapons
* @param _Step The number of step to go forward or backward in the weapons list
*/
Void CycleWeapon(CSmPlayer _Player, Integer _Step) {
declare Weapons for _Player = C_Default_Weapons;
if (Weapons.count <= 1) return;
declare Step = 0;
if (_Step < 0) Step = -1;
else if (_Step > 0) Step = 1;
declare CurrentWeapon for _Player = C_Default_Weapon;
if (!Weapons.exists(CurrentWeapon)) return;
declare Key = Weapons.keyof(CurrentWeapon) + Step;
while (!Weapons.existskey(Key)) {
Key += Step;
if (Key > 4) Key = 1;
else if (Key < 1) Key = 4;
}
CurrentWeapon = Weapons[Key];
declare netwrite Text Net_Combo_Weapon for _Player;
switch (CurrentWeapon) {
case CSmMode::EWeapon::Laser : SwitchWeapon(_Player, CSmModeEvent::EActionInput::Activable1);
case CSmMode::EWeapon::Nucleus : SwitchWeapon(_Player, CSmModeEvent::EActionInput::Activable2);
case CSmMode::EWeapon::Arrow : SwitchWeapon(_Player, CSmModeEvent::EActionInput::Activable3);
case CSmMode::EWeapon::Rocket : SwitchWeapon(_Player, CSmModeEvent::EActionInput::Activable4);
}
}
// ---------------------------------- //
/// Prepare match for matchmaking
Void PrepareMatch() {
foreach (Player in AllPlayers) {
SetPlayerClan(Player, MM_GetRequestedClan(Player));
if (Player.CurrentClan == 1) WarmUp2::SetPlayerGroup(Player, "Clan1");
else if (Player.CurrentClan == 2) WarmUp2::SetPlayerGroup(Player, "Clan2");
}
WarmUp2::Clean();
WarmUp2::Fill();
}
// ---------------------------------- //
// Manage the warm up sequence
Void WarmUp() {
XmlRpc::BeginWarmUp();
// Init warm up
declare PrevSequence = UIManager.UIAll.UISequence;
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::PhaseChange;
UIManager.UIAll.BigMessage = _("Warm-up");
UIManager.UIAll.StatusMessage = _("Press F6 once you're ready.");
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
UsePvPCollisions = True;
UsePvPWeapons = True;
WarmUp2::Begin();
// ---------------------------------- //
// Init players
foreach (Player in Players) {
SetPlayerClan(Player, MM_GetRequestedClan(Player));
if (Player.CurrentClan == 1) WarmUp2::SetPlayerGroup(Player, "Clan1");
else if (Player.CurrentClan == 2) WarmUp2::SetPlayerGroup(Player, "Clan2");
}
WarmUp2::Clean();
WarmUp2::Fill();
declare PrevWarmUpDuration = S_WarmUpDuration-1;
declare PrevAllowUnbalancedTeams = !S_AllowUnbalancedTeams;
while (!WarmUp2::Stop()) {
MM_Yield();
// Let the server sleep if there's no players on it
if (PlayersNbTotal <= 0) continue;
// Manage players
foreach (Player in Players) {
if (Player.CurrentClan != MM_GetRequestedClan(Player)) {
UnspawnPlayer(Player);
SetPlayerClan(Player, MM_GetRequestedClan(Player));
if (Player.CurrentClan == 1) WarmUp2::SetPlayerGroup(Player, "Clan1");
else if (Player.CurrentClan == 2) WarmUp2::SetPlayerGroup(Player, "Clan2");
}
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) {
SetPlayerWeapon(Player, CSmMode::EWeapon::Rocket, False);
declare PlayerSpawn <=> Map::GetPlayerSpawn("Spawn", Player.CurrentClan);
if (PlayerSpawn != Null) SM::SpawnPlayer(Player, Player.CurrentClan, 200, PlayerSpawn, Now);
}
}
WarmUp2::Loop();
WarmUp2::ManageEvents();
if (PrevWarmUpDuration != S_WarmUpDuration || PrevAllowUnbalancedTeams != S_AllowUnbalancedTeams) {
PrevWarmUpDuration = S_WarmUpDuration;
PrevAllowUnbalancedTeams = S_AllowUnbalancedTeams;
declare LongTimer = S_WarmUpDuration*1000;
declare ShortTimer = 5000;
if (LongTimer <= 0) { LongTimer = 0; ShortTimer = 0; }
if (S_AllowUnbalancedTeams) {
WarmUp2::SetGroupTimers("Clan1", [ShortTimer => [-1, 1], LongTimer => [1, 1]]);
WarmUp2::SetGroupTimers("Clan2", [ShortTimer => [-1, 1], LongTimer => [1, 1]]);
} else {
WarmUp2::SetGroupTimers("Clan1", [ShortTimer => [-1, S_Script_NbPlayersPerTeam], LongTimer => [1, S_Script_NbPlayersPerTeam]]);
WarmUp2::SetGroupTimers("Clan2", [ShortTimer => [-1, S_Script_NbPlayersPerTeam], LongTimer => [1, S_Script_NbPlayersPerTeam]]);
}
}
}
WarmUp2::End();
WarmUp2::Clean();
WarmUp2::Fill();
declare PlayersOrder = [1 => WarmUp2::GetGroup("Clan1"), 2 => WarmUp2::GetGroup("Clan2")];
declare AllowedPlayers = Ident[];
for (I, 1, 2) {
foreach (Slot => PlayerId in PlayersOrder[I]) {
AllowedPlayers.add(PlayerId);
}
}
// Init players
foreach (Player in Players) {
if (AllowedPlayers.exists(Player.Id)) {
declare ValidPlayer for Player = False;
ValidPlayer = True;
} else {
declare ValidPlayer for Player = False;
ValidPlayer = False;
}
}
SM::UnspawnAllPlayers();
MM_Sleep(3000);
ObjectDestroyAll();
UIManager.UIAll.BigMessage = "";
UIManager.UIAll.StatusMessage = "";
UIManager.UIAll.UISequence = PrevSequence;
XmlRpc::EndWarmUp();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment