// Author: Slig
// maniaplanet nickname (game and forum): slig
//
// version 1.5, 27/07/2012
#RequireContext CSmMode
#Include "MathLib" as MathLib
#Include "TextLib" as TextLib
#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
#Include "Libs/Nadeo/Mode.Script.txt"
#Include "Libs/Nadeo/Victory.Script.txt" as Victory
#Include "Libs/Nadeo/ShootMania/Score.Script.txt" as Score
#Include "Libs/Nadeo/ShootMania/Airshot.Script.txt" as Airshot
#Include "Libs/Nadeo/ShootMania/BalancedWeapons.Script.txt" as BalancedWeapons
// Mostly compatible with Elite, Heroes, and TeamSurvival maps
// depending of the spawns and pole point(s), a map may be nice to play or not
#Const CompatibleMapTypes "EliteArena,HeroesArena,TeamSurvivalArena"
#Const Version "2012-07-27"
#Setting S_RoundsToWin 6 as _("Rounds to win") ///
#Setting S_RoundGapToWin 2 as _("Round gap to win") ///
#Setting S_RoundsLimit 8 as _("Rounds limit") ///
#Setting S_RoundTimeLimit 105 as _("Round time limit (s)") /// seconds, if briefcase not returned and still alive players in both teams
#Setting S_MapTimeLimit 0 as _("Map time limit (s)") /// seconds, if it comes before S_RoundsToWin and S_RoundsLimit
#Setting S_ArmorMax 200 as _("Armox max (100, 200, 300,...)") /// game default 200
#Setting S_BriefcaseHandlerStamina 0.6 as _("Reduced stamina for handler (0.1 to 1.0)") /// game default 1.0
#Setting S_FriendlyFire False as _("Is friendly fire effective ?") ///
#Setting S_AllowWeaponChange False as _("Can players change their weapon ?") ///
#Setting S_AutoBalance False as _("Auto balance ?") ///
#Setting S_TeamChangeTimeLimit 30 as _("Time limit to change team at beginning of round") /// seconds
#Setting S_RespawnTime 3001 as _("Respawn time (ms)") /// ms
#Const S_AmmoGain 1.0 // default 1.0 (tested: 1.42)
#Const S_RocketAmmoMax 4 // default 4
#Const S_LaserAmmoMax 1 // default 1
#Const ShowBriefcaseHandlerTimeout 3200 // ms, timeout to see briefcase handler position to enemies
#Const UITickPeriod 400
***UIPlayer***
***
UI.BigMessage = Airshot::Message(Player);
***
***EndTime***
***
EndTime = StartTime + S_RoundTimeLimit*1000;
***
***Locales***
***
locales["en"] = [ "language" => "English" ]; // needed to init locales["en"] array
locales["en"]["modename"] = "Infiltration";
locales["en"]["moderules"] = """Two teams game mode, inspired from SoF2 Infiltration mode :)
- The attackers must take the briefcase at the pole, then return it to the extract/start point.
- The defenders win the round if they prevent attackers to finish before the end of time.
- The attackers and the defenders win also if they eliminate all opponents.
- Once dead, you do not respawn until the end of the round.
- Score to win the map: {{{ S_RoundsToWin }}} (gap: {{{ S_RoundGapToWin }}} , max: {{{ S_RoundsLimit }}})
- You have to show players names (medium size or more) to see the briefcase and extract markers, sorry.
- The player who take the briefcase is (a little) highlighted, a marker is shown few seconds at the last position he shot or was hit.
- When spectator, the 0 key (num pad) allow to spec another player of own team.
""";
locales["en"]["keysrules"] = "Press F1 to show rules";
locales["en"]["keysweapons"] = "Press F3 / F4 to swap gun for next round";
locales["en"]["briefcase"] = "Briefcase";
locales["en"]["extract"] = "Extract";
locales["en"]["attacker"] = "Attacker";
locales["en"]["defender"] = "Defender";
locales["en"]["eliminate"] = "eliminate";
locales["en"]["help"] = "help";
locales["en"]["toextract"] = "return to extract point";
locales["en"]["winsround"] = "wins the round";
locales["en"]["drawround"] = "This round is a draw";
locales["en"]["winsmatch"] = "wins the match";
locales["en"]["defendit"] = "Defend the briefcase";
locales["en"]["attackit"] = "Take and return the briefcase";
locales["en"]["droppedit"] = "dropped the briefcase";
locales["en"]["droppedit2"] = "dropped the briefcase, take it";
locales["en"]["tookit"] = "took the briefcase";
locales["en"]["tookit2"] = "took the briefcase, help him";
locales["en"]["tookit0"] = "You took the briefcase, return to extract point now";
locales["en"]["eliminated1"] = "Defenders eliminated: attackers win";
locales["en"]["eliminated2"] = "Attackers eliminated: defenders win";
locales["en"]["successful"] = "Mission successful: attackers win";
locales["en"]["elapsed"] = "Time elapsed: defenders win";
locales["en"]["nextweapon"] = "Next weapon";
locales["en"]["Rocket"] = "Rocket";
locales["en"]["Laser"] = "Railgun";
locales["en"]["Nucleus"] = "Nucleus";
locales["fr"] = [ "language" => "French" ]; // needed to init locales["fr"] array
locales["fr"]["modename"] = "Infiltration";
locales["fr"]["moderules"] = """Mode jeu à 2 équipes, inspiré du mode Infiltration de SoF2 :)
- Les attaquants doivent prendre la mallette (briefcase) au poteau et la ramener au point de retour (extract).
- Les défenseurs gagnent le round s'ils empêchent les attaquants de finir avant la fin du temps.
- Les attaquants et les défenseurs peuvent aussi gagner en éliminant tous leurs adversaires.
- Une fois mort, vous ne revenez pas en jeu avant la fin du round.
- Score pour gagner la map : {{{ S_RoundsToWin }}} (écart : {{{ S_RoundGapToWin }}} , max : {{{ S_RoundsLimit }}})
- Vous devez afficher les noms (taille moyenne ou plus) pour voir les marqueurs de la mallette et du point de retour.
- Le joueur qui prend la mallette devient (un peu) plus lumineux, un marqueur est montré quelques secondes à la position où il a tiré ou bien a été touché.
- Lorsque spectateur, la touche 0 (pavé numérique) permet de changer de joueur dans son équipe.
""";
locales["fr"]["keysrules"] = "F1 pour lire les règles de jeu";
locales["fr"]["keysweapons"] = "F3 / F4 pour changer d'arme au round suivant";
locales["fr"]["briefcase"] = "Mallette";
locales["fr"]["extract"] = "Extraction";
locales["fr"]["attacker"] = "Attaquant";
locales["fr"]["defender"] = "Défenseur";
locales["fr"]["eliminate"] = "éliminez";
locales["fr"]["help"] = "aidez";
locales["fr"]["toextract"] = "retournez au point d'extraction";
locales["fr"]["winsround"] = "gagne le round";
locales["fr"]["drawround"] = "match nul sur ce round";
locales["fr"]["winsmatch"] = "gagne le match";
locales["fr"]["defendit"] = "Defendez la mallette";
locales["fr"]["attackit"] = "Prenez et ramenez la mallette";
locales["fr"]["droppedit"] = "a perdu la mallette";
locales["fr"]["droppedit2"] = "a perdu la mallette, récupérez la";
locales["fr"]["tookit"] = "a pris la mallette";
locales["fr"]["tookit2"] = "a pris la mallette, aidez le";
locales["fr"]["tookit0"] = "Ramenez la mallette au point d'extraction maintenant";
locales["fr"]["eliminated1"] = "Défenseurs éliminés";
locales["fr"]["eliminated2"] = "Attaquants éliminés";
locales["fr"]["finished"] = "Mission réussie";
locales["fr"]["eliminated1"] = "Défenseurs éliminés : les attaquants gagnent";
locales["fr"]["eliminated2"] = "Attaquants éliminés : les défenseurs gagnent";
locales["fr"]["successful"] = "Mission réussie : les attaquants gagnent";
locales["fr"]["elapsed"] = "Temps écoulé : les défenseurs gagnent";
locales["fr"]["nextweapon"] = "Prochaine arme ";
locales["fr"]["Rocket"] = "Rocket";
locales["fr"]["Laser"] = "Railgun";
locales["fr"]["Nucleus"] = "Nucleus";
locales["de"] = [ "language" => "German" ]; // needed to init locales["en"] array
locales["de"]["modename"] = "Infiltration";
locales["de"]["moderules"] = """Zwei Teams, inspiriert vom SoF2 Modus Infiltrations :)
- Die Angreifer müssen den Aktenkoffer (gegnerische Säule) abholen und zum Startpunkt zurückbringen.
- Die Verteidiger gewinnen wenn sie die Angreifer aufhalten bis die Zeit abgelaufen ist.
- Verteidiger und Angreifer gewinnen ebenfalls wenn sie das gegenerische Team eliminieren.
- Wird ein Spieler eliminiert muss er warten bis die aktuelle Runde beendet ist bevor er wieder in das Geschehen eingreifen kann.
- Punkt um die Map zu gewinnen: {{{ S_RoundsToWin }}} (Abstand: {{{ S_RoundGapToWin }}} , Max: {{{ S_RoundsLimit }}})
- Um den Aktenkoffer zu sehen müssen leider Spielernamen (mindestens medium) angezeigt werden.
- Der Spieler der den Aktenkoffer besitzt ist leicht erhellt dargestellt. Ein Marker zeigt die letzte bekannte Position an wo dieser geschossen hat oder getroffen wurde.
- Als Zuschauer kann mit Hilfe der Taste 0 (Ziffernblock) einem Spieler vom eigenen Team über die Schulter geschaut werden.""";
locales["de"]["keysrules"] = "Drücke F1 um die Spielregeln anzuzeigen";
locales["de"]["keysweapons"] = "Drücke F3 / F4 um in der nächsten Runde die Waffe zu wechseln";
locales["de"]["briefcase"] = "Aktenkoffer";
locales["de"]["extract"] = "Entnehmen";
locales["de"]["attacker"] = "Angreifer";
locales["de"]["defender"] = "Verteidiger";
locales["de"]["eliminate"] = "Eliminiere";
locales["de"]["help"] = "Hilf";
locales["de"]["toextract"] = "Zurück zum Startpunkt";
locales["de"]["winsround"] = "gewinnt die Runde";
locales["de"]["drawround"] = "Diese Runde endet unentschieden";
locales["de"]["winsmatch"] = "gewinnt das Spiel";
locales["de"]["defendit"] = "Beschützt den Aktenkoffer";
locales["de"]["attackit"] = "Findet den Aktenkoffer und bringt ihn zurück zu Basis";
locales["de"]["droppedit"] = "hast den Aktenkoffer fallen gelassen";
locales["de"]["droppedit2"] = "hat den Aktenkoffer verloren, hol ihn dir";
locales["de"]["tookit"] = "hat den Aktenkoffer genommen";
locales["de"]["tookit2"] = "hat den Aktenkoffer genommen, hilf ihn";
locales["de"]["eliminated1"] = "Alle Verteidiger eliminiert: Angreifer gewinnen";
locales["de"]["eliminated2"] = "Alle Angreifer eliminiert: Verteidiger gewinnen";
locales["de"]["successful"] = "Mission erfolgreich beendet: Angreifer gewinnen";
locales["de"]["elapsed"] = "Zeit abgelaufen: Verteidiger gewinnen";
locales["de"]["nextweapon"] = "Nächste Waffe";
locales["de"]["Rocket"] = "Rocket";
locales["de"]["Laser"] = "Railgun";
locales["de"]["Nucleus"] = "Nucleus";
***
///////////////////////////////////////////////////
// declare global array which will be filled by translation texts
declare Text[Text][Text] locales;
///////////////////////////////////////////////////
// fill translation texts in locales
Void setLocales() {
+++Locales+++
}
///////////////////////////////////////////////////
// Get the map name manialink string.
// @return The manialink string
Text UpdateLayerSpawnScreen() {
declare Text ML;
---Rules---
// create dico texts
declare Dico = "";
foreach(language => translations in locales) {
Dico = Dico ^ """""";
if(locales[language].existskey("modename"))
Dico = Dico ^ "$fff" ^ locales[language]["modename"] ^ "";
if(locales[language].existskey("moderules"))
Dico = Dico ^ "" ^ locales[language]["moderules"] ^ "";
if(locales[language].existskey("keysrules"))
Dico = Dico ^ "" ^ locales[language]["keysrules"] ^ "";
if(locales[language].existskey("keysweapons"))
Dico = Dico ^ "" ^ locales[language]["keysweapons"] ^ "";
Dico = Dico ^ "";
}
// keys messages depending on S_AllowWeaponChange or not
declare KeysMessage = """
""";
if(S_AllowWeaponChange){
KeysMessage = """
""";
}
ML = """
{{{ Dico }}}
{{{ KeysMessage }}}
""";
return ML;
}
///////////////////////////////////////////////////
// return the text for the tag, depending of locales arrays and player language
Text locale(CPlayer _Player, Text _Tag) {
declare language = _Player.User.Language;
if(_Tag == "")
return "";
// check if tag exists in player language dico
if(locales.existskey(language) && locales[language].existskey(_Tag))
return locales[language][_Tag];
// else test if tag exist in english dico (locales["en"] is supposed to exist !)
else if(locales["en"].existskey(_Tag))
return locales["en"][_Tag];
// else return "-*tag*-" for unknown tag
return "-*" ^ _Tag ^ "*-";
}
///////////////////////////////////////////////////
// Play a sound : _Sound: The sound to play , _Variant: The variant to play
Void PlaySound(CUIConfig::EUISound _Sound, Integer _Variant) {
UIManager.UIAll.SendNotice("", CUIConfig::ENoticeLevel::MatchInfo, Null, CUIConfig::EAvatarVariant::Default, _Sound, _Variant);
}
///////////////////////////////////////////////////
// return the clan/color num from the team number (1=defenders, 2=attackers)
Integer teamclan(Integer team, Integer round) {
if (round % 2 == 1) {
if (team == 1)
return 2;
return 1;
}
return team;
}
///////////////////////////////////////////////////
// clear all Markers to all
Void clearMarkers(){
foreach(Player2 in Players) {
declare UI <=> UIManager.GetUI(Player2);
if (UI==Null) continue;
declare BriefcaseMarker for Player2 = "";
declare ExtractMarker for Player2 = "";
BriefcaseMarker = "";
ExtractMarker = "";
UI.Hud3dMarkers = "";
}
}
///////////////////////////////////////////////////
// show a 'Briefcase' marker on a player for allies, not or at last know pos to enemies
Void showBriefcaseMarkerOnPlayer(Ident _PlayerId, Boolean _ShowToAllies, Boolean _ShowToEnemies, Vec3 _Pos, Boolean doSound){
if(!Players.existskey(_PlayerId)) {
// this case is not supposed to happen, btw erase markers to all
clearMarkers();
return;
}
declare Player <=> Players[_PlayerId];
// show the right Briefcase marker to each player (depending of clans)
foreach(Player2 in Players) {
declare UI <=> UIManager.GetUI(Player2);
if (UI==Null) continue;
declare BriefcaseMarker for Player2 = "";
declare ExtractMarker for Player2 = "";
BriefcaseMarker = "";
if(Player.CurrentClan != Player2.CurrentClan){
// enemy
if(_ShowToEnemies)
BriefcaseMarker = """""";
else
BriefcaseMarker = "";
} else {
// ally
if(_ShowToAllies && Player2.Id != _PlayerId)
BriefcaseMarker = """""";
else
BriefcaseMarker = "";
}
UI.Hud3dMarkers = BriefcaseMarker ^ ExtractMarker;
}
if(doSound)
PlaySound(CUIConfig::EUISound::TieBreakPoint, 0);
}
///////////////////////////////////////////////////
// show a 'Briefcase' marker at a plone/dropped position
Void showBriefcaseMarkerAtPos(Vec3 _Pos, Boolean doSound){
foreach(Player2 in Players) {
declare UI <=> UIManager.GetUI(Player2);
if (UI==Null) continue;
declare BriefcaseMarker for Player2 = "";
declare ExtractMarker for Player2 = "";
BriefcaseMarker = """""";
UI.Hud3dMarkers = BriefcaseMarker ^ ExtractMarker;
}
if(doSound)
PlaySound(CUIConfig::EUISound::TieBreakPoint, 0);
}
///////////////////////////////////////////////////
// show a 'Extract' marker at a spawn position
Void showExtractMarkerAtPos(Vec3 _Pos, Boolean doSound){
foreach(Player2 in Players) {
declare UI <=> UIManager.GetUI(Player2);
if (UI==Null) continue;
declare BriefcaseMarker for Player2 = "";
declare ExtractMarker for Player2 = "";
ExtractMarker = """""";
UI.Hud3dMarkers = BriefcaseMarker ^ ExtractMarker;
}
if(doSound)
PlaySound(CUIConfig::EUISound::TieBreakPoint, 0);
}
///////////////////////////////////////////////////
// show a localized BigMessage to teams
Void setBigMessageToTeams(Text[][] _BMs, Integer _Round, Ident _PlayerId, Boolean _SpecialPlayer){
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
declare Text BigMessage for Player = "";
if (Player.CurrentClan == teamclan(1, _Round)) {
BigMessage = _BMs[1][0] ^ locale(Player,_BMs[1][1]) ^ _BMs[1][2];
} else if (Player.CurrentClan == teamclan(2, _Round)) {
if(_SpecialPlayer && Player.Id == _PlayerId)
BigMessage = _BMs[0][0] ^ locale(Player,_BMs[0][1]) ^ _BMs[0][2];
else
BigMessage = _BMs[2][0] ^ locale(Player,_BMs[2][1]) ^ _BMs[2][2];
} else {
BigMessage = "";
}
//log("BigMessage,"^Player.Login^" : "^UI.BigMessage ^" , "^_BMs);
}
}
///////////////////////////////////////////////////
// show a localized BigMessage to all
Void setBigMessageToAll(Text[] _BM){
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
declare Text BigMessage for Player = "";
BigMessage = _BM[0] ^ locale(Player,_BM[1]) ^ _BM[2];
//log("BigMessage,"^Player.Login^" : "^UI.BigMessage);
}
}
///////////////////////////////////////////////////
// show again BigMessages (which else are transient)
Void showBigMessages(){
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
declare Text BigMessage for Player = "";
UI.BigMessage = BigMessage;
}
}
///////////////////////////////////////////////////
// try to force spec on a player of same team (set to next player in list if already spec on one)
Void forcePlayerSpec(CSmPlayer _Player){
declare UI <=> UIManager.GetUI(_Player);
declare Ident SpecTarget for _Player;
declare Ident SpecTargetOld = SpecTarget;
SpecTarget = NullId;
if(SpecTargetOld != NullId){
// had already on a target : skip the 1st ones until current target is found, then search a target in remaining ones
foreach(Player2 in Players) {
if(SpecTargetOld != NullId){
// If was on a player then skip/continue until he's found
if(SpecTargetOld == Player2.Id)
SpecTargetOld = NullId;
continue;
}
declare Boolean IsDead for Player2;
if(!IsDead && Player2.CurrentClan == _Player.CurrentClan){
SpecTarget = Player2.Id;
UI.SpectatorForcedTarget = Player2.Id;
//UI.SpectatorAutoTarget = Player2.Id;
//UI.SpectatorForceCameraType = 15;
log("Force spec "^_Player.Login^": " ^ _Player.CurrentClan ^ "," ^ Player2.CurrentClan ^ "," ^ Player2.Login ^ "," ^ UI.SpectatorForcedTarget ^ "," ^ UI.SpectatorAutoTarget ^ "," ^ UI.SpectatorForceCameraType);
return;
}
}
}
// search a target (a second time from start if had already a target)
foreach(Player2 in Players) {
declare Boolean IsDead for Player2;
if(!IsDead && Player2.CurrentClan == _Player.CurrentClan){
SpecTarget = Player2.Id;
UI.SpectatorForcedTarget = Player2.Id;
//UI.SpectatorAutoTarget = Player2.Id;
//UI.SpectatorForceCameraType = 15;
log("Force spec "^_Player.Login^": " ^ _Player.CurrentClan ^ "," ^ Player2.CurrentClan ^ "," ^ Player2.Login ^ "," ^ UI.SpectatorForcedTarget ^ "," ^ UI.SpectatorAutoTarget ^ "," ^ UI.SpectatorForceCameraType);
return;
}
}
}
///////////////////////////////////////////////////
// notice next player weapon
Void nextWeapon(CSmPlayer _Player, CUIConfig _UI, Text _Weapon){
_UI.SendNotice(locale(_Player,"nextweapon") ^ ": " ^ locale(_Player,_Weapon),
CUIConfig::ENoticeLevel::Default,
Null,
CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence,
0);
}
///////////////////////////////////////////////////
// set player weapon
Void setWeapon(CSmPlayer _Player){
declare WeaponRequired for _Player = CSmMode::EWeapon::Rocket;
log("set weapon " ^ WeaponRequired ^ "for " ^ _Player.Login);
_Player.ArmorMax = S_ArmorMax;
_Player.Armor = S_ArmorMax;
SetPlayerAmmoMax(_Player,CSmMode::EWeapon::Rocket,S_RocketAmmoMax);
SetPlayerAmmoMax(_Player,CSmMode::EWeapon::Laser,S_LaserAmmoMax);
SetPlayerWeapon(_Player, WeaponRequired, False);
}
///////////////////////////////////////////////////
// Handle keys press
Void handleKeyPress(Boolean _Init){
declare diffPress = 0;
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
// handle client 0n, F3 and F4 press
declare netread UIpressF3 for UI = 0;
declare netread UIpressF4 for UI = 0;
declare netread UIpress0n for UI = 0;
declare PressF3 for Player = 0;
declare PressF4 for Player = 0;
declare Press0n for Player = 0;
if(_Init){
PressF3 = UIpressF3;
PressF4 = UIpressF4;
Press0n = UIpress0n;
continue;
}
declare WeaponRequired for Player = CSmMode::EWeapon::Rocket;
if(S_AllowWeaponChange && UIpressF3 > PressF3){
// F3 pressed
declare diffPress = UIpressF3 - PressF3;
PressF3 = UIpressF3;
while(diffPress > 0){
if(WeaponRequired == CSmMode::EWeapon::Laser){
WeaponRequired = CSmMode::EWeapon::Rocket;
nextWeapon(Player, UI, "Rocket");
//log(Player.Login ^ " press F3: " ^ diffPress ^ " => Rocket required");
}
else if(WeaponRequired == CSmMode::EWeapon::Rocket){
WeaponRequired = CSmMode::EWeapon::Nucleus;
nextWeapon(Player, UI, "Nucleus");
//log(Player.Login ^ " press F3: " ^ diffPress ^ " => Nucleus required");
}
else if(WeaponRequired == CSmMode::EWeapon::Nucleus){
WeaponRequired = CSmMode::EWeapon::Laser;
nextWeapon(Player, UI, "Laser");
//log(Player.Login ^ " press F3: " ^ diffPress ^ " => Laser required");
}
diffPress = diffPress -1;
}
}
if(S_AllowWeaponChange && UIpressF4 > PressF4){
// F4 pressed
declare diffPress = UIpressF4 - PressF4;
PressF4 = UIpressF4;
while(diffPress > 0){
if(WeaponRequired == CSmMode::EWeapon::Laser){
WeaponRequired = CSmMode::EWeapon::Nucleus;
nextWeapon(Player, UI, "Nucleus");
//log(Player.Login ^ " press F4: " ^ diffPress ^ " => Nucleus required");
}
else if(WeaponRequired == CSmMode::EWeapon::Nucleus){
WeaponRequired = CSmMode::EWeapon::Rocket;
nextWeapon(Player, UI, "Rocket");
//log(Player.Login ^ " press F4: " ^ diffPress ^ " => Rocket required");
}
else if(WeaponRequired == CSmMode::EWeapon::Rocket){
WeaponRequired = CSmMode::EWeapon::Laser;
nextWeapon(Player, UI, "Laser");
//log(Player.Login ^ " press F4: " ^ diffPress ^ " => Laser required");
}
diffPress = diffPress -1;
}
}
if(UIpress0n > Press0n){
// 0 padnum pressed
declare diffPress = UIpress0n - Press0n;
//log(Player.Login ^ " press 0n: " ^ diffPress);
Press0n = UIpress0n;
declare Ident SpecTarget for Player;
if(SpecTarget != NullId){
while(diffPress > 0){
// Change target for spec player
//log("Try to change spec for " ^ Player.Login);
forcePlayerSpec(Player);
diffPress = diffPress -1;
}
}
}
}
}
///////////////////////////////////////////////////
// Main
main() {
setLocales();
declare MatchNumber = 0;
UseClans = True;
declare LayerTops <=> UIManager.UILayerCreate();
declare LayerRoundInfo <=> UIManager.UILayerCreate();
///////////////////////////////////////////////////
// Maps loop
while( !ServerShutdownRequested ) {
LoadMap();
Score::MatchBegin(False);
Airshot::MatchBegin();
BalancedWeapons::MatchBegin();
Victory::MatchBegin();
if(S_AutoBalance) AutoTeamBalance();
Ladder_OpenMatch_All();
+++MatchBegin+++
handleKeyPress(True);
//SetNbFakePlayers(1, 1);
declare Round = 0;
UIManager.ResetAll();
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Intro;
ClanScores[1] = 0;
ClanScores[2] = 0;
declare MapStartTime = Now + 2000 + S_RespawnTime;
declare MapRemainingtime = MapStartTime + S_MapTimeLimit*1000 - Now;
declare MapTimeInfo = "\n $z$n$999remaining map time: " ^ TextLib::TimeToText(MapRemainingtime);
//log("Map type: " ^ Map.MapType ^ "Map style: " ^ Map.MapStyle);
///////////////////////////////////////////////////
// Attackers = team 2 : teamclan(2, Round) => attackers clan number / color
// Defenders = team 1 : teamclan(1, Round) => defenders clan number / color
///////////////////////////////////////////////////
// choose spawns
// test EliteArena / HeroesArena style anchors tags
declare CSmBlockSpawn[Integer] ClanSpawnAnchors = [1=>SM::GetSpawn("SpawnDefense", 0), 2=>SM::GetSpawn("SpawnAttack", 0)];
// else test TeamSurvivalArena style anchors tags
if(ClanSpawnAnchors[1] == Null || ClanSpawnAnchors[2] == Null)
ClanSpawnAnchors = [1=>SM::GetSpawn("Spawn", 1), 2=>SM::GetSpawn("Spawn", 2)];
// else (should not happen) use the first two spawns
if(ClanSpawnAnchors[1] == Null || ClanSpawnAnchors[2] == Null)
ClanSpawnAnchors = [1=>BlockSpawns[0], 2=>BlockSpawns[1]];
declare Vec3 SpawnPos1 = ClanSpawnAnchors[1].Position;
declare Vec3 SpawnPos2 = ClanSpawnAnchors[2].Position;
foreach (Clan=>Spawn in ClanSpawnAnchors) {
Spawn.Base.Clan = Clan;
Spawn.Base.IsActive = True;
}
declare Vec3 AttackersStartPosition = SpawnPos2; // extraction point (where the briefcase should come back)
///////////////////////////////////////////////////
// try to choose a pole...
// pole gauge won't do anything, pole is just used to anchor the briefcase
declare CSmBlockPole BriefcasePole <=> Null; // Pole where the briefcase is at start
declare Ident BriefcasePoleId = NullId;
if(BlockPoles.count == 1){
// one single pole
BlockPoles[0].Gauge.Speed = 0;
BlockPoles[0].Gauge.Value = 0;
BlockPoles[0].Gauge.Max = 1000;
BriefcasePoleId = BlockPoles[0].Id;
} else {
// choose pole
declare dist12 = MathLib::Distance(SpawnPos1,SpawnPos2);
declare BPratiodiff = 1000000.;
declare BPexchange = False;
declare ratiodiff = 1000000.;
declare dist1 = 1.;
declare dist2 = 1.;
// find pole the closest to 0.6 ratio
foreach(index=>Pole in BlockPoles) {
Pole.Gauge.Speed = 0;
Pole.Gauge.Value = 0;
Pole.Gauge.Max = 1000;
dist1 = MathLib::Distance(SpawnPos1,Pole.Position);
dist2 = MathLib::Distance(SpawnPos2,Pole.Position);
ratiodiff = MathLib::Abs( (dist1 / dist2) - 0.6 );
//log("Pole: " ^ Pole.Tag ^ ", " ^ dist1 ^ ", " ^ dist2 ^ ", " ^ ratiodiff);
if(index == 0 || ratiodiff < BPratiodiff) {
// closer to a pole, keep it for now
BriefcasePoleId = Pole.Id;
BPratiodiff = ratiodiff;
//log("Pole: " ^ index ^ ", " ^ BPratiodiff);
}
}
}
///////////////////////////////////////////////////
// Rounds loop
while( Victory::NoMatchWinner() && !MatchEndRequested ) {
UIManager.ResetAll();
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
declare VictoryMessage = "";
Score::RoundBegin();
Airshot::RoundBegin();
BalancedWeapons::RoundBegin();
Victory::RoundBegin();
+++RoundBegin+++
SM::SetupDefaultVisibility();
declare LatestUITick = Now;
StartTime = Now + S_RespawnTime;
---EndTime---
BriefcasePole <=> BlockPoles[BriefcasePoleId];
///////////////////////////////////////////////////
declare Vec3 BriefcasePosition = BriefcasePole.Position; // store the current briefcase position
declare Vec3 BriefcaseSeenPosition = BriefcasePole.Position; // store the last briefcase position "seen" by enemies
declare Boolean BriefcaseSeenShow = False; // True while handled briefcase is shown to enemies
declare Integer BriefcaseSeenTime = Now; // time until handled briefcase is shown to enemies
declare IsBriefcaseAtPole = True; // set to False once the briefcase taken at pole
declare IsBriefcaseHandled = False; // set to True when a player handle the briefcase
declare Ident BriefcaseHandlerId = NullId; // Id of (last) player handling the briefcase
declare BriefcaseHandlerName = ""; // Name of (last) player handling the briefcase
declare Vec3 PPosition; // used to compute BDist for player against dropped briefcase
declare BDist = 1000.; // used to distance to briefcase or extraction point
declare TickPeriod = 1000; // 1s ticks for few computings...
declare LatestTick = Now;
MapRemainingtime = MapStartTime + S_MapTimeLimit*1000 - Now;
if(MapRemainingtime > 0)
MapTimeInfo = "\n $z$n$999remaining map time: " ^ TextLib::TimeToText(MapRemainingtime);
else
MapTimeInfo = "\n $z$n$999no map time left. Last round if no draw.";
log("Start round: " ^ Round);
///////////////////////////////////////////////////
// Swap spawns
if(Round > 0) {
declare CSmBlockSpawn spawntmp <=> ClanSpawnAnchors[2];
ClanSpawnAnchors[2] = ClanSpawnAnchors[1];
ClanSpawnAnchors[1] = spawntmp;
}
///////////////////////////////////////////////////
// Handle keys press
handleKeyPress(False);
///////////////////////////////////////////////////
// Spawning players
foreach(Player in Players) {
// back stamina to default
Player.StaminaMax = 1.0;
Player.StaminaPower = 1.0;
if (Player.SpawnStatus != CSmPlayer::ESpawnStatus::NotSpawned) continue;
BalancedWeapons::SetPlayerWeapon(Player, True);
//log(Player.Login ^ " Armor: " ^ Player.Armor ^ " / " ^ Player.ArmorMax);
setWeapon(Player);
SM::SpawnPlayer(Player, Player.RequestedClan, ClanSpawnAnchors[Player.RequestedClan], Now);
//log(Player.Login ^ " Armor: " ^ Player.Armor ^ " / " ^ Player.ArmorMax);
declare Ident SpecTarget for Player = NullId;
SpecTarget = NullId;
declare Boolean IsDead for Player = False;
IsDead = False;
}
declare Text[][] BigMessages = [["x","","x"],["$n","defendit"," !"],["$n","attackit"," !"]];
declare BigMessageTime = StartTime + 5000;
declare BigMessageShow = True;
setBigMessageToTeams(BigMessages,Round,NullId,False);
///////////////////////////////////////////////////
// Main play loop
while ( Victory::NoRoundWinner() && !MatchEndRequested ) {
yield;
///////////////////////////////////////////////////
// Handle events
foreach(Event, PendingEvents) {
if( Event.Type == CSmModeEvent::EType::OnHit ) {
if(IsBriefcaseHandled && BriefcaseHandlerId == Event.Victim.Id && Event.Shooter.CurrentClan != Event.Victim.CurrentClan){
// Briefcase Handler "seen", show his current pos for ShowBriefcaseHandlerTimeout
if(!BriefcaseSeenShow || Now > BriefcaseSeenTime - ShowBriefcaseHandlerTimeout + 1000){
// only if last "seen" is more than 1s old
BriefcaseSeenPosition = Event.Victim.Position;
BriefcaseSeenShow = ShowBriefcaseHandlerTimeout > 0;
BriefcaseSeenTime = Now + ShowBriefcaseHandlerTimeout;
showBriefcaseMarkerOnPlayer(BriefcaseHandlerId, True, BriefcaseSeenShow, BriefcaseSeenPosition, False);
}
}
if ( Event.Shooter == Null || Event.Victim == Null || Event.Shooter == Event.Victim ) {
Discard(Event);
} else if ( UseClans && Event.Shooter.CurrentClan == Event.Victim.CurrentClan ) {
if(S_FriendlyFire){
if(Event.Damage > 0) {
Airshot::OnHit(Event.Shooter, Event.Victim);
Score::AddPoints( Event.Shooter, -1);
}
PassOn(Event);
}else{
Discard(Event);
}
} else {
if(Event.Damage > 0) {
//log("Damage: " ^ Event.Damage);
Score::AddPoints( Event.Shooter, 1);
Airshot::OnHit(Event.Shooter, Event.Victim);
}
PassOn(Event);
}
} else if (Event.Type == CSmModeEvent::EType::OnShoot) {
if(IsBriefcaseHandled && BriefcaseHandlerId == Event.Shooter.Id){
// Briefcase Handler "seen", show his current pos for ShowBriefcaseHandlerTimeout
if(!BriefcaseSeenShow || Now > BriefcaseSeenTime - ShowBriefcaseHandlerTimeout + 1000){
// only if last "seen" is more than 1s old
BriefcaseSeenPosition = Event.Shooter.Position;
BriefcaseSeenShow = ShowBriefcaseHandlerTimeout > 0;
BriefcaseSeenTime = Now + ShowBriefcaseHandlerTimeout;
showBriefcaseMarkerOnPlayer(BriefcaseHandlerId, True, BriefcaseSeenShow, BriefcaseSeenPosition, False);
}
}
//log("AmmoGain: " ^ Event.Shooter.AmmoGain ^ " StaminaMax: " ^ Event.Shooter.StaminaMax ^ " StaminaGain: " ^ Event.Shooter.StaminaMax);
if(Event.Shooter.AmmoGain != S_AmmoGain)
Event.Shooter.AmmoGain = S_AmmoGain;
//SetPlayerAmmo(Event.Shooter,CSmMode::EWeapon::Rocket,4);
PassOn(Event);
} else if (Event.Type == CSmModeEvent::EType::OnArmorEmpty) {
BalancedWeapons::OnOut(Event.Shooter, Event.Victim);
declare Boolean IsDead for Event.Victim = True;
IsDead = True;
if(IsBriefcaseHandled && BriefcaseHandlerId == Event.Victim.Id){
// Briefcase handler is dead : briefcase dropped !
IsBriefcaseHandled = False;
BriefcaseSeenShow = False;
showBriefcaseMarkerAtPos(BriefcasePosition, True);
// back stamina to default
Event.Victim.StaminaMax = 1.0;
Event.Victim.StaminaPower = 1.0;
BigMessages = [["","",""],[Event.Victim.Name ^ " $z$n$s ", "droppedit", " !"],[Event.Victim.Name ^ " $z$n$s ", "droppedit2", " !"]];
BigMessageTime = Now + 2500;
BigMessageShow = True;
setBigMessageToTeams(BigMessages,Round,NullId,False);
}
// check specs to force on another player
foreach(Player2 in Players) {
declare Ident SpecTarget for Player2;
//log("UnForce spec? " ^ Player2.Login ^ "," ^ SpecTarget ^ "," ^ Event.Victim.Id);
if(SpecTarget == Event.Victim.Id) {
SpecTarget = NullId;
declare UI <=> UIManager.GetUI(Player2);
UI.SpectatorForcedTarget = NullId;
log("UnForce spec " ^ Player2.Login);
}
}
PassOn(Event);
} else{
PassOn(Event);
}
}
///////////////////////////////////////////////////
// count players
declare PlayersCount = [1=>0,2=>0];
declare PlayersAlive = [1=>0,2=>0];
declare TeamsArmor = [1=>0,2=>0];
foreach(Player in Players) {
if (Player.CurrentClan != 1 && Player.CurrentClan != 2)
continue;
PlayersCount[Player.CurrentClan] = PlayersCount[Player.CurrentClan] + 1;
if (Player.SpawnStatus != CSmPlayer::ESpawnStatus::NotSpawned) {
PlayersAlive[Player.CurrentClan] = PlayersAlive[Player.CurrentClan] + 1;
TeamsArmor[Player.CurrentClan] = TeamsArmor[Player.CurrentClan] + Player.Armor;
}
}
///////////////////////////////////////////////////
// In play spawns
if ((PlayersCount[1] == 0 && PlayersCount[2] > 0) || (PlayersCount[1] > 0 && PlayersCount[2] == 0)) {
foreach(Player in Players) {
if (Player.SpawnStatus != CSmPlayer::ESpawnStatus::NotSpawned) continue;
BalancedWeapons::SetPlayerWeapon(Player, True);
//log(Player.Login ^ " Armor: " ^ Player.Armor ^ " / " ^ Player.ArmorMax);
setWeapon(Player);
SM::SpawnPlayer(Player, Player.RequestedClan, ClanSpawnAnchors[Player.RequestedClan], Now + S_RespawnTime);
//log(Player.Login ^ " Armor: " ^ Player.Armor ^ " / " ^ Player.ArmorMax);
declare Ident SpecTarget for Player = NullId;
SpecTarget = NullId;
declare Boolean IsDead for Player = False;
IsDead = False;
}
}
foreach (Player in Players) {
// spawn new players
if (!Player.IsFakePlayer && Player.RequestedClan != 0 && Player.RequestedClan != Player.CurrentClan) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned)
UnspawnPlayer(Player);
if (Now - StartTime <= S_TeamChangeTimeLimit * 1000 || PlayersCount[1]+PlayersCount[2] < 2){
setWeapon(Player);
SM::SpawnPlayer(Player, Player.RequestedClan, ClanSpawnAnchors[Player.RequestedClan], Now + S_RespawnTime);
declare Ident SpecTarget for Player = NullId;
SpecTarget = NullId;
declare Boolean IsDead for Player = False;
IsDead = False;
}
}
// force spec to dead players
if(Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned && Player.CurrentClan > 0){
declare Ident SpecTarget for Player;
if(SpecTarget == NullId)
forcePlayerSpec(Player);
}
}
///////////////////////////////////////////////////
// Handle keys press
handleKeyPress(False);
+++Update+++
///////////////////////////////////////////////////
// Infiltrating
if(IsBriefcaseAtPole){
///////////////////////////////////////////////////
// briefcase is at pole : check if a player take it
foreach(PlayerId in BriefcasePole.Sector.PlayersIds) {
if (IsBriefcaseHandled) break;
declare Player <=> Players[PlayerId];
if(Player.SpawnStatus != CSmPlayer::ESpawnStatus::Spawned || Player.CurrentClan != teamclan(2, Round)) continue;
///////////////////////////////////////////////////
// Player grabbed the briefcase !
log("Player grab the briefcase on pole: " ^ Player.Login ^ " / " ^ Player.Name);
IsBriefcaseHandled = True;
IsBriefcaseAtPole = False;
BriefcaseHandlerId = Player.Id;
BriefcaseHandlerName = Player.Name;
Player.IsHighlighted = True;
showExtractMarkerAtPos(AttackersStartPosition, True);
// reduce briefcase handler stamina
Player.StaminaMax = S_BriefcaseHandlerStamina;
Player.StaminaPower = S_BriefcaseHandlerStamina;
// Briefcase Handler "seen", show his current pos for ShowBriefcaseHandlerTimeout
BriefcaseSeenPosition = Player.Position;
BriefcaseSeenShow = ShowBriefcaseHandlerTimeout > 0;
BriefcaseSeenTime = Now + ShowBriefcaseHandlerTimeout;
showBriefcaseMarkerOnPlayer(BriefcaseHandlerId, True, BriefcaseSeenShow, BriefcaseSeenPosition, False);
BigMessages = [["","tookit0",""],[Player.Name ^ " $z$n$s ", "tookit", " !"],[Player.Name ^ " $z$n$s ", "tookit2", " !"]];
BigMessageTime = Now + 2500;
BigMessageShow = True;
setBigMessageToTeams(BigMessages,Round,BriefcaseHandlerId,IsBriefcaseHandled);
}
} else if(!IsBriefcaseHandled){
///////////////////////////////////////////////////
// Briefcase is not handled nor at initial pole position, ie dropped somewhere
foreach(Player in Players){
// attention! the player who just died is still status spawn and still at its last live position !
if(IsBriefcaseHandled || Player.SpawnStatus != CSmPlayer::ESpawnStatus::Spawned || Player.CurrentClan != teamclan(2, Round) || Player.Id == BriefcaseHandlerId) continue;
PPosition = Player.Position;
BDist = MathLib::Distance(PPosition,BriefcasePosition);
if(BDist < 3){
///////////////////////////////////////////////////
// Player grabbed the briefcase !
log("Player grab the dropped briefcase: " ^ Player.Login ^ " / " ^ Player.Name);
IsBriefcaseHandled = True;
IsBriefcaseAtPole = False;
BriefcaseHandlerId = Player.Id;
BriefcaseHandlerName = Player.Name;
Player.IsHighlighted = True;
showExtractMarkerAtPos(AttackersStartPosition, True);
// reduce briefcase handler stamina
Player.StaminaMax = S_BriefcaseHandlerStamina;
Player.StaminaPower = S_BriefcaseHandlerStamina;
// Briefcase Handler "seen", show his current pos for ShowBriefcaseHandlerTimeout
BriefcaseSeenPosition = Player.Position;
BriefcaseSeenShow = ShowBriefcaseHandlerTimeout > 0;
BriefcaseSeenTime = Now + ShowBriefcaseHandlerTimeout;
showBriefcaseMarkerOnPlayer(BriefcaseHandlerId, True, BriefcaseSeenShow, BriefcaseSeenPosition, False);
BigMessages = [["","tookit0",""],[Player.Name ^ " $z$n$s ", "tookit", " !"],[Player.Name ^ " $z$n$s ", "tookit2", " !"]];
BigMessageTime = Now + 2500;
BigMessageShow = True;
setBigMessageToTeams(BigMessages,Round,BriefcaseHandlerId,IsBriefcaseHandled);
}
}
} else {
///////////////////////////////////////////////////
// briefcase is handled by a player : store position and check player return
if(Players.existskey(BriefcaseHandlerId)){
declare Player <=> Players[BriefcaseHandlerId];
if(Player.IsTouchingGround)
BriefcasePosition = Player.Position;
BDist = MathLib::Distance(AttackersStartPosition,BriefcasePosition);
//log("BDist " ^ Player.Login ^ ": " ^ BDist);
if(BDist < 5) {
////////////////////////////////////
// briefcase returned, attackers win !
log("Attackers win: " ^ Player.Login ^ " return briefcase ! BDist: " ^ BDist);
showExtractMarkerAtPos(AttackersStartPosition, True);
Score::AddPoints( Player, 1);
sleep(400);
Victory::SetRoundWinnerIfNoWinner(teamclan(2, Round));
VictoryMessage = "successful";
}
} else {
// should never happen !!! handler player has quit ?
IsBriefcaseHandled = False;
}
}
///////////////////////////////////////////////////
// check other victory cases
if(Victory::NoRoundWinner()){
if (PlayersCount[1] > 0 && PlayersCount[2] > 0) {
// Special victory ?
if (PlayersAlive[1] == 0 && PlayersAlive[2] == 0) {
////////////////////////////////////
// nobody alive : defenders win
log("Defenders win: no player alive ! PlayersCount: " ^ PlayersCount ^ " PlayersAlive: " ^ PlayersAlive);
sleep(1200);
Victory::SetRoundWinnerIfNoWinner(teamclan(1, Round));
VictoryMessage = "eliminated2";
} else if (PlayersAlive[teamclan(1, Round)] == 0) {
////////////////////////////////////
// no defender alive : attackers win
log("Attackers win: no defender alive ! PlayersCount: " ^ PlayersCount ^ " PlayersAlive: " ^ PlayersAlive);
sleep(1200);
Victory::SetRoundWinnerIfNoWinner(teamclan(2, Round));
VictoryMessage = "eliminated1";
} else if (PlayersAlive[teamclan(2, Round)] == 0) {
////////////////////////////////////
// no attacker alive : defenders win
log("Defenders win: no attacker alive ! PlayersCount: " ^ PlayersCount ^ " PlayersAlive: " ^ PlayersAlive);
sleep(1200);
Victory::SetRoundWinnerIfNoWinner(teamclan(1, Round));
VictoryMessage = "eliminated2";
}
}
if(Now >= EndTime) {
if (PlayersCount[1] == 0 || PlayersCount[2] == 0) {
////////////////////////////////////
// round timeout : nobody
log("Draw: timeout without player ! PlayersCount: " ^ PlayersCount ^ " PlayersAlive: " ^ PlayersAlive);
sleep(1200);
Victory::SetRoundDrawIfNoWinner();
VictoryMessage = "drawround";
} else {
////////////////////////////////////
// round timeout : defenders win (if any)
log("Defenders win: timeout ! PlayersCount: " ^ PlayersCount ^ " PlayersAlive: " ^ PlayersAlive);
sleep(1200);
Victory::SetRoundWinnerIfNoWinner(teamclan(1, Round));
VictoryMessage = "elapsed";
}
}
}
///////////////////////////////////////////////////
// show bigmessages or erase if timeout (they are transient if not reset)
if(BigMessageShow){
if(Now > BigMessageTime) {
BigMessageShow = False;
UIManager.UIAll.BigMessage = "";
//log("BigMessage,all : ---");
} else {
showBigMessages();
}
}
///////////////////////////////////////////////////
// Things computed every second...
if ( Now > LatestTick + TickPeriod){
LatestTick = Now;
// show briefcase at origin or dropped, to have it seen at beginning and for late comming players
if(IsBriefcaseAtPole || !IsBriefcaseHandled){
BriefcaseSeenShow = False;
showBriefcaseMarkerAtPos(BriefcasePosition, False);
}
//log("PlayersCount: " ^ PlayersCount ^ " PlayersAlive: " ^ PlayersAlive);
}
///////////////////////////////////////////////////
// Briefcase Handler was "seen" : check if ShowBriefcaseHandlerTimeout finished
if(BriefcaseSeenShow && Now > BriefcaseSeenTime){
BriefcaseSeenShow = False;
showBriefcaseMarkerOnPlayer(BriefcaseHandlerId, IsBriefcaseHandled, False, BriefcaseSeenPosition, False);
}
///////////////////////////////////////////////////
// UI stuff
if ( Now > LatestUITick + UITickPeriod){
LatestUITick = Now;
///////////////////////////////////////////////////
// show statusmessage
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
if (Player.CurrentClan == teamclan(1, Round)) {
if(IsBriefcaseHandled)
UI.StatusMessage = """$z$n$aaa{{{ locale(Player,"defender") }}}: $ddd$s{{{ locale(Player,"eliminate") }}} {{{ BriefcaseHandlerName }}} !""";
else
UI.StatusMessage = """$z$n$aaa{{{ locale(Player,"defender") }}}""";
} else if (Player.CurrentClan == teamclan(2, Round)) {
if(IsBriefcaseHandled) {
if(Player.Id == BriefcaseHandlerId)
UI.StatusMessage = """$z$n$aaa{{{ locale(Player,"attacker") }}}: $ddd$s{{{ locale(Player,"toextract") }}} !""";
else
UI.StatusMessage = """$z$n$aaa{{{ locale(Player,"attacker") }}}: $ddd$s{{{ locale(Player,"help") }}} {{{ BriefcaseHandlerName }}} !""";
} else
UI.StatusMessage = """$z$n$aaa{{{ locale(Player,"attacker") }}}""";
} else
UI.StatusMessage = "";
}
///////////////////////////////////////////////////
// Shields and names
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI == Null) continue;
if(IsBriefcaseHandled) {
Player.IsHighlighted = (Player.Id == BriefcaseHandlerId);
UI.AlliesLabelsVisibility = CUIConfig::ELabelsVisibility::WhenInMiddleOfScreen;
UI.AlliesLabelsShowGauges = CUIConfig::EVisibility::Normal;
UI.EnemiesLabelsVisibility = CUIConfig::ELabelsVisibility::WhenInMiddleOfScreen;
UI.EnemiesLabelsShowGauges = CUIConfig::EVisibility::None;
} else {
Player.IsHighlighted = False;
UI.AlliesLabelsVisibility = CUIConfig::ELabelsVisibility::WhenInMiddleOfScreen;
UI.AlliesLabelsShowGauges = CUIConfig::EVisibility::Normal;
UI.EnemiesLabelsVisibility = CUIConfig::ELabelsVisibility::Never;
UI.EnemiesLabelsShowGauges = CUIConfig::EVisibility::None;
}
}
// layers stuff
UIManager.UIAll.UILayers.clear();
UIManager.UIAll.UILayers.add(LayerRoundInfo);
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 && PlayerClan2Id != NullId) {
UIManager.UIAll.OverlayScoreSummary = True;
UIManager.UIAll.ScoreSummary_Player1 = PlayerClan1Id;
UIManager.UIAll.ScoreSummary_Points1 = ClanScores[1];
UIManager.UIAll.ScoreSummary_MatchPoints1 = -1;
//UIManager.UIAll.ScoreSummary_Gauge1 = ClanTotalRatios[1]/100.;
UIManager.UIAll.ScoreSummary_Player2 = PlayerClan2Id;
UIManager.UIAll.ScoreSummary_Points2 = ClanScores[2];
UIManager.UIAll.ScoreSummary_MatchPoints2 = -1;
//UIManager.UIAll.ScoreSummary_Gauge2 = ClanTotalRatios[2]/100.;
} else {
UIManager.UIAll.OverlayScoreSummary = False;
}
// handle layers
declare UsedLayers = Ident[];
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
declare CUILayer LayerSpawnScreen;
if (UI.UILayers.count != 1) {
LayerSpawnScreen <=> UIManager.UILayerCreate();
LayerSpawnScreen.Type = CUILayer::EUILayerType::ScreenIn3d;
UI.UILayers.add(LayerSpawnScreen);
} else {
LayerSpawnScreen <=> UI.UILayers[0];
}
UsedLayers.add(LayerSpawnScreen.Id);
LayerSpawnScreen.ManialinkPage = UpdateLayerSpawnScreen();
+++UIPlayer+++
}
+++UIAll+++
// Remove layers
declare LayersToRemove = Ident[];
UsedLayers.add(LayerTops.Id);UsedLayers.add(LayerRoundInfo.Id);
foreach (Layer in UIManager.UILayers) {
if (!UsedLayers.exists(Layer.Id)) {
LayersToRemove.add(Layer.Id);
}
}
foreach (LayerId in LayersToRemove) {
UIManager.UILayerDestroy(UIManager.UILayers[LayerId]);
}
}
// end of UI stuff
///////////////////////////////////////////////////
}
// end of main play loop
///////////////////////////////////////////////////
// end round sequence
StartTime = -1;
EndTime = -1;
clearMarkers();
UIManager.UIAll.UILayers.clear();
UIManager.UIAll.UILayers.add(LayerTops);
///////////////////////////////////////////////////
// show round victory statusmessage
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
UI.StatusMessage = """$z$n$s$eee{{{ locale(Player,VictoryMessage) }}} !""";
}
MapRemainingtime = MapStartTime + S_MapTimeLimit*1000 - Now;
if(MapRemainingtime > 0)
MapTimeInfo = "\n$z$n$999remaining map time: " ^ TextLib::TimeToText(MapRemainingtime);
else
MapTimeInfo = "\n $z$n$999no map time left.";
if ( Victory::IsRoundWinner(1) ) {
setBigMessageToAll([Teams[0].ColorizedName^" ","winsround"," !"]);
Clan1Score += 1;
} else if ( Victory::IsRoundWinner(2) ) {
setBigMessageToAll([Teams[1].ColorizedName^" ","winsround"," !"]);
Clan2Score += 1;
} else {
setBigMessageToAll(["","drawround"," !"]);
}
Victory::SetMatchWinnerFromScore(S_RoundsToWin, S_RoundGapToWin, S_RoundsLimit);
if(!Victory::NoMatchWinner() && S_MapTimeLimit > 0 && Now > MapStartTime + S_MapTimeLimit*1000) {
// Map timelimit victory (if not draw, else continue)
if(Clan1Score > Clan2Score){
Victory::SetMatchWinnerFromScore(Clan1Score, 1, Clan1Score);
UIManager.UIAll.BigMessage = "Map time limit !";
} else if(Clan1Score < Clan2Score){
Victory::SetMatchWinnerFromScore(Clan2Score, 1, Clan2Score);
UIManager.UIAll.BigMessage = "Map time limit !";
}
}
UIManager.UIAll.UISequence = CUIConfig::EUISequence::EndRound;
foreach(Player in Players) {
// back stamina to default
Player.StaminaMax = 1.0;
Player.StaminaPower = 1.0;
// unspawn player
UnspawnPlayer(Player);
}
sleep(2*1000);
UIManager.UIAll.UILayers.clear();
UIManager.UIAll.UILayers.add(LayerTops);
sleep(2*1000);
+++RoundEnd+++
Score::RoundEnd();
Airshot::RoundEnd();
BalancedWeapons::RoundEnd();
Victory::RoundEnd();
///////////////////////////////////////////////////
// Handle keys press
handleKeyPress(False);
Round += 1;
}
// end of Round loop
///////////////////////////////////////////////////
// end match sequence
UIManager.ResetAll();
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Outro;
declare WinnerClan = -1;
if ( Victory::IsMatchWinner(1) ) {
setBigMessageToAll([Teams[0].ColorizedName ^ " ", "winsmatch", " $z" ^ Clan1Score ^ " - " ^ Clan2Score]);
WinnerClan = 1;
} else if ( Victory::IsMatchWinner(2) ) {
setBigMessageToAll([Teams[1].ColorizedName ^ " ", "winsmatch", " $z" ^ Clan2Score ^ " - " ^ Clan1Score]);
WinnerClan = 2;
}
MatchNumber += 1;
sleep(2*1000);
if(WinnerClan != -1){
// Reset score clans
foreach (Score in Scores) { declare Integer Clan for Score; Clan = 0; }
foreach (Player in Players) {
if (Player.Score == Null) continue;
declare Integer Clan for Player.Score;
Clan = Player.CurrentClan;
}
// Sort scores by clan
declare ClanScoresSorted = [1=>CSmScore[], 2=>CSmScore[]];
foreach (Score in Scores) {
Score.LadderRankSortValue = 1000;
declare Integer Clan for Score;
if (Clan != 1 && Clan != 2) continue;
ClanScoresSorted[Clan].add(Score);
}
declare Shift = [1=>1, 2=>1];
Shift[3 - WinnerClan] = 2;
foreach(Index => Score in ClanScoresSorted[1]) {Score.LadderRankSortValue = Index * 2 + Shift[1];}
foreach(Index => Score in ClanScoresSorted[2]) {Score.LadderRankSortValue = Index * 2 + Shift[2];}
Ladder_CloseMatch();
}
else {
Ladder_CancelMatch();
}
+++MatchEnd+++
Score::MatchEnd();
Airshot::MatchEnd();
BalancedWeapons::MatchEnd();
Victory::MatchEnd();
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Podium;
sleep(12*1000);
UIManager.UIAll.BigMessage = "";
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
UIManager.UIAll.UILayers.clear();
sleep(1*1000);
MatchEndRequested = False;
UnloadMap();
}
// end of Map loop
///////////////////////////////////////////////////
UIManager.UILayerDestroy(LayerTops);
UIManager.UILayerDestroy(LayerRoundInfo);
}