Dear forum users! In compliance with the new European GDPR regulations, we'd just like to inform you that if you have an account, your email address is stored in our database. We do not share your information with third parties, and your email address and password are encrypted for security reasons.

New to the forum? Say hello in this topic! Also make sure to read the rules.

#Tourney - A (very) simple Tournament Script

Custom scripts
Forum rules
By using the forum you agree to the following rules.
Post Reply
User avatar
Mighty Spirit the 2
Superfighter
Superfighter
Posts: 187
Joined: Mon Jun 25, 2018 5:02 pm
Title: Wasted potential
SFD Account: ake004
SFD Alias: Retired SFD player
Started SFD: When melee was good
Location: SFD Veteran trauma hospital
Gender:
Age: 22

#Tourney - A (very) simple Tournament Script

Post by Mighty Spirit the 2 » Thu Feb 09, 2023 1:48 am


Last year I replied to a topic made from @DaxOttsel about a Tournament Script. Upon further thought I realised that wasn't actually a Tournament Script, it was more like a competitive Battle Royale. Anyway I decided to give it a shot at trying to make something simple. Since "Tournament" would purely assume 1v1 solo or 2 Teams fighting, I realised it didn't actually matter if the game couldn't track who killed who, it just mattered that at the end of the round there is only one Team left standing. Kinda like Battle of Teams which has existed for ages, minus the respawn.

So what's special about this Script? Well, I decided that since it was going to be geared towards players who would challenge each other to serious matches, they can select which maps they want to play through. So basically you would contact each other on Discord, and then each player (or team) will suggest some maps. This is just like in other fighting games where the players do counter-picks and such. These are the maps that will populate the Array which will represent how many wins you will need to be crowned the Victor of the Tournament. The script will automatically register who won and switch over to the next map of the winning team.
I would suggest typing in all the submitted maps into a randomizer like this one - https://www.random.org/lists/

Took me about 2 months of work, but I learned a great deal so I'm satisfied with that. But right now I'm progress is slowing down, and I finished this last revision more than 1 week ago, so I figured that if I don't release it now it won't matter. It's not really in the finished state I was looking for, but it's totally usable. I tested it once with Hiwor, so it should work.

This script works for Beta 1.0.2c, so it won't have any Command writing functionality available. Instead, I decided the host should be able to start the Tournament from in-game, and not have to tweak with the txt file during the middle of gameplay.

It's very easy to use:
1. Assign a Team 1 and Team 2 to the contestants. Anyone else will be removed on Startup if the Tournament is ongoing. Just like Spectators.
2. The host must start a Tournament within 10 Seconds, or else need to wait for next round. Start #Tourney by pressing: Crouch+Walk+Block.
3. The Tournament can be cancelled by the host within 4 seconds by pressing: Crouch+Walk+Attack. Then script can then be stopped.
4. Tournament will register the Teams wins and change map accordingly to the array selected.
5. First Team to complete their maps list wins, with a nice Congratulation message.


I hope whoever tries this can have some fun, report back any errors you find. This script would really have been great around 2017-2018 when clan wars and game balance were still a thing of Pride.



Code: Select all

//==================================================================//
//=======*******< Tournament Mode 1v1 or 2 Teams >*******=======//
//==================================================================//
	//Write each Teams maps below, The Length of the Array decides how many wins you need.
	//I suggest to have even teams and equal size of Maps for fair play.
//--------------------<		Team Map Arrays		>--------------------//
String[] Team1_Maps = new string[]{"Police Station", "Steamship", "Alley", "Canals", "Heavy Equipment" };
String[] Team2_Maps = new string[]{ "Rooftops II",  "Hotel", "Tower", "High Moon", "The Church (MK)"  };
//"Chemical Plant", "Trainyard", "Teahouse",  "Subway",

//==================================================================//
//=========< Tribute to #Chelog {#OCTOHORP} Scripts >==========//
//=============================================================//

/*Changelog:
This script has gone through at least 8 versions, each one adding some new variables and methods that i hadn't thought off beforehand...
It's been maybe 2 months since i started work on the earliest draft at 2 am.
[v.8.0](19.01.23) - The first functioning, more or less "complete" version of the script, cut from a very time-consuming Debug script.
[v.8.3](26.01.23) --> "Save Score in Game.Data which will fix TournamentCancelled() from displaying "...Score=0" for the contestant who left."
		This is Done. I had to read that in Pre-Alpha 1.7.2 -> "Game.Data no longer shared between Scripts".
[v.8.4](09.02.23) - Finally finished setting up RevoluteJoint, using same method as in "Ultimate Battle Mod" (Zoke), but i needed to include "convert" type. Also tested with an additional Timer.

Planned features:
  - Randomised GameOver texts for variation.
  - Have a CPU be the "Host" for Tournament with multiple Dialog sequence options based on who wins. Be able to customize "Host" profile.
	- Problem with this making Host impossible to gib or kill, and setting SpawnPoint. 	--> Very unlikely that i will ever do this as it's unnecessary.

*/

//############<		Don't Edit Anything Below	>###############//
Boolean ScriptActive=false;
private List <IUser>  Team1 = new List<IUser>();
private List <IUser>  Team2 = new List<IUser>();
private List <IUser>  AlreadyTakenCareOf = new List<IUser>();
private int Current_Connected_Team1 = 0;
private int Current_Connected_Team2 = 0;
private int Team1_lastWin = 0;
private int Team2_lastWin= 0;
Random rnd = new Random();

private String TournamentWinner = null;
private String EndOfRound = "";

private int GameOverTimeElapsed = 0;
private string VarGO=null;

private int Connected_Users = 0;

private int TW_Wins = 0;
private int EoR_Wins = 0;

IObjectRevoluteJoint TourneyStarted;

//*******************************//

public void OnStartup(){

	if(Game.GetMapType() !=MapType.Versus) { CloseTournament(); MSG("Wrong Map Type - #Tourney Disabled"); return; }

	if(Game.Data.Contains("1v1Mode")) {
		ScriptActive=true;
		CheckPlayers();
		//Game.RunCommand("/msg TournamentAlreadyOn")
		CreateRevoluteJoint();

		foreach(IUser u in Game.GetActiveUsers()){
			var pT= u.GetPlayer().GetTeam().ToString();
			//Find out if Tournament finished last round and reset the score!
			if(pT=="Team1") { if(u.TotalWins>Team1_Maps.Length) { MSG("#Tourney - Tournament Finished Last Round"); CloseTournament(); return; }} //MSG("G.D= "+Game.Data);
			if(pT=="Team2") { if(u.TotalWins>Team2_Maps.Length) { MSG("#Tourney - Tournament Finished Last Round"); CloseTournament(); return; }}	
		}
	}
	


    IObjectTimerTrigger TournamentTimer = (IObjectTimerTrigger)Game.CreateObject("TimerTrigger");
    TournamentTimer.SetIntervalTime(0);
    TournamentTimer.SetRepeatCount (0);
    TournamentTimer.CustomID="TournamentTimer";
    TournamentTimer.SetScriptMethod("Check_World");
    TournamentTimer.Trigger();

		Connected_Users = Game.GetActiveUsers().Length;
		//MSG("CurrentUsers= "+Connected_Users );

}


public void CheckPlayers(){
	foreach(IUser u in Game.GetActiveUsers()){
		var pTeam = u.GetPlayer().GetTeam().ToString();
		switch(pTeam){ 
		case "Team1": Team1.Add(u); Team1_lastWin=u.TotalWins;  Current_Connected_Team1++; break; //
		case "Team2": Team2.Add(u); Team2_lastWin=u.TotalWins; Current_Connected_Team2++; break; //
		default: u.GetPlayer().Remove(); break; }
	}
		//Check possible states when Tournament can't continue
		if(Current_Connected_Team1 ==0 || Current_Connected_Team2 ==0) {
			if(!ScriptActive) { ErrorTournament(); return; }
			else { 			
			TournamentCancelled();
//			Remove1v1Timer();
			return; }
		}
	//Tournament is good to go.
	if(!ScriptActive){
		Game.Data += "1v1ModeScore=0-0";
		ScriptActive=true;
		CreateRevoluteJoint();

		MSG("#Tourney - Tournament Started");
	}
Connected_Users = Game.GetActiveUsers().Length;

}


public void Check_World(TriggerArgs args){
//Blah blah blah

if(!ScriptActive) {
	foreach(IUser u in Game.GetActiveUsers()){
	if(u.IsHost){
	var ply = u.GetPlayer();

		if(ply!=null) {
		//Host starts Tournament
			if(Game.TotalElapsedGameTime<=10000) {
				if(ply.IsCrouching && ply.IsWalking && ply.IsBlocking) { //ply.GetUser().IsHost should be!
					Game.ResetScore(); CheckPlayers(); } //Reset Score to start fresh tournament if it works
							}
			else { Remove1v1Timer(); return; }
					}
				}
			}
		}
if(ScriptActive){
	//Host cancels the ongoing Tournament
	foreach(IUser u in Game.GetActiveUsers()){
	if(u.IsHost){
	var ply = u.GetPlayer();
		if(ply!=null) {
			if(Game.TotalElapsedGameTime<=4000) {
				if(ply.IsCrouching && ply.IsWalking && ply.IsMeleeAttacking) { //ply.GetUser().IsHost should be!
					TournamentStopped(); }
							}
					}
			}
	}
	


	//Loop each User list and see if they are still here withinn 5 Seconds of Start. Else Remove. "5020" because it works once with loop interval of 0.
	if(!Game.IsGameOver && Game.TotalElapsedGameTime>=5000 && Game.TotalElapsedGameTime<=5020) {
		RecheckUsers(); MSG("RevoluteJOinexist");
		}
	//Checks if a contestant left during the match, just to see if all members of a team left.
	if(!Game.IsGameOver && Connected_Users != Game.GetActiveUsers().Length){
		RecheckUsers();
		}
}
	//Use VariableGameOver for when GameOver is called from somewhere else in the Script
	if(VarGO==null){
		if(Game.IsGameOver) {
			if(ScriptActive) {
				Game.PlayEffect("Electric", new Vector2(0,0));
				GameOverTimeElapsed++;

/*
				
					if(GameOverTimeElapsed<100) { Game.SetGameOver("Checking Winner"); }
					if(GameOverTimeElapsed==100) { MSG("First EoR= "+EndOfRound); Game.SetGameOver("Updating Score"); } // Events.UpdateCallback.Start(Gay,3000,1);
*/
				CheckGameOver();
			}
			else {  Game.SetGameOver("<<<<<<!!!Game Over!!!>>>>>>"); }
			}
		}
	else { GameOverTimeElapsed++; GameOver(VarGO); if(GameOverTimeElapsed==100) GameDataScore(); } //MSG(GameOverTimeElapsed.ToString());
	
}

public void Remove1v1Timer() {
	if(TourneyStarted!=null) TourneyStarted.Remove();
	foreach(IObjectTimerTrigger tim in Game.GetObjectsByCustomId("TournamentTimer")) { tim.Remove();  } 
}

public void CheckGameOver(){

	RecheckUsers();

	//Cancels rest of code if GameOver already runned somewhere else.
	if(VarGO!=null) { return; }

	foreach(IPlayer ply in Game.GetPlayers()){
		var pTeam = ply.GetTeam().ToString();
		if(ply.GetUser()!=null) {
			if(!ply.IsDead && ply!=null){
				if(pTeam=="Team1" && !EndOfRound.Contains("1")) { EndOfRound += "1"; }
				if(pTeam=="Team2" && !EndOfRound.Contains("T2")) { EndOfRound += "T2"; }
			}
		}
	}


	//Team 2 Won the round
	if(EndOfRound.Length==2) {
		//Check if The person won the tournament
		Team2_lastWin++;
		if(Team2_lastWin>Team2_Maps.Length) { TournamentWinner = "Team 2"; TournamentOver(); return; }
		else { Game.SetGameOver("Red Team Wins"); VarGO="Red Team Wins"; NextMap(Team2_Maps[Team2_lastWin-1]); } //Game.RunCommand("/changemap " + Team2_Maps[Team2_lastWin-1]);
	}

	//Team 1 Won the round
	if(EndOfRound.Length==1) {
		Team1_lastWin++;
		if(Team1_lastWin>Team1_Maps.Length) { TournamentWinner = "Team 1"; TournamentOver(); return; }
		else { Game.SetGameOver("Blue Team Wins"); VarGO="Blue Team Wins"; NextMap(Team1_Maps[Team1_lastWin-1]); }
	}


	//Nobody Won the round
	if(EndOfRound.Length>=3 || EndOfRound.Length==0) {
		Game.SetGameOver("No One Wins, losers"); VarGO="No One Wins, losers";
//MSG("T2win= "+Team2_lastWin); MSG("T1win= "+Team1_lastWin);
		//Change to opponents next map if Contestant failed to win.
		if(Team1_Maps.Contains(Game.MapName)) { PickTeam2_Map(); return; }
		if(Team2_Maps.Contains(Game.MapName)) { PickTeam1_Map(); return; } 
		
		//If it's a map that's not part of the array.... Picks one of the arrays. Same chance for both.
		int Pickrnd = rnd.Next(2);
		//MSG(""+Pickrnd);
		if(Pickrnd==0) { PickTeam1_Map(); }
		else { PickTeam2_Map(); }
	}

//if(GameOverTimeElapsed>=500) { Game.SetGameOver("Preparing Next Round"); }

}

public void PickTeam2_Map(){
if(Team2_lastWin>0) { NextMap(Team2_Maps[Team2_lastWin-1]); }
else{ NextMap(Team2_Maps[0]); }
}

public void PickTeam1_Map(){
if(Team1_lastWin>0) { NextMap(Team1_Maps[Team1_lastWin-1]); }
else{ NextMap(Team1_Maps[0]); }
}

public void CheckContestant_Names(){
//MSG("This works");
String T1 = null;
String T2 = null;
	if(Team1.Count==1) { T1=Team1[0].Name; }
	else { T1="Team 1";
	}
	if(Team2.Count==1) { T2=Team2[0].Name; }
	else { T2="Team 2";
		}
	if(Current_Connected_Team1==0) { TournamentWinner="Team 2"; }
	if(Current_Connected_Team2==0) { TournamentWinner="Team 1"; }
	
	if(TournamentWinner=="Team 1") {
		TournamentWinner=T1; EndOfRound=T2;
		TW_Wins = Team1_lastWin; EoR_Wins=Team2_lastWin;
		}
	else { TournamentWinner=T2; EndOfRound=T1;
		TW_Wins = Team2_lastWin; EoR_Wins=Team1_lastWin;
	}
}

public void PasteScore() {
String T1=null;
String T2 = null;
	if(Team1.Count>1){ T1="Team 1 size = "+Team1.Count+" "; }
	if(Team2.Count>1){ T2="Team 2 size = "+Team2.Count; }

	MSG(TournamentWinner+" Score = "+TW_Wins);
	MSG(EndOfRound+" Score = "+EoR_Wins);
	MSG(T1+T2);

}

		
public void RecheckUsers() {
for (int i = Team1.Count - 1; i >= 0; i--){
	IUser u = Team1[i];
	if(!AlreadyTakenCareOf.Contains(u)) {
		if(!UserStillHere(u)) {
			Current_Connected_Team1--;
			if(!Game.IsGameOver){
				if(Game.TotalElapsedGameTime<=6000){ Team1.Remove(u); }
				else { AlreadyTakenCareOf.Add(u); }
				}
			}
		}
	}

for (int i = Team2.Count - 1; i >= 0; i--){
	IUser u = Team2[i];
	if(!AlreadyTakenCareOf.Contains(u)) {
		if(!UserStillHere(u)) {
			Current_Connected_Team2--;
			if(!Game.IsGameOver){
				if(Game.TotalElapsedGameTime<=6000){ Team2.Remove(u); }
				else { AlreadyTakenCareOf.Add(u); }
				}
			}
		}
	}

if(VarGO==null) {
	if(Current_Connected_Team1==0 || Current_Connected_Team2==0) { TournamentCancelled(); return; }
	}

	Connected_Users = Game.GetActiveUsers().Length;
}


public void CloseTournament(){
	ScriptActive=false;
	Game.ResetScore();
	Game.Data = String.Empty;
	if(TourneyStarted!=null) { TourneyStarted.Remove(); }
}


public void TournamentOver(){
	Game.SetGameOver("Tournament Over");
	VarGO="Tournament Over";
	CheckContestant_Names();

	MSG("####< #Tourney >####");
	//MSG("TOURNAMENT OVER");
	MSG("Congratulations "+TournamentWinner);
	MSG("Final Score:");
	PasteScore();
	MSG("Thanks for Playing!!! :)");
	MSG("######< End >#######");

//CloseTournament(); --> Clear Score on start of next round.

}

public void TournamentCancelled(){
//If Player left last round
if(Game.TotalElapsedGameTime<100) { GameDataScore(); }
	Game.SetGameOver("Tournament Interrupted");
	VarGO="Tournament Interrupted";
	CheckContestant_Names();

	MSG("####< #Tourney >####");
	MSG("TOURNAMENT was abandoned");
	MSG(EndOfRound+" Forfeited the match");
	MSG("Current Score was:");
	PasteScore();
//	MSG("Predicted Winner?");
	MSG("######< End >#######");

CloseTournament();
}

public void GameDataScore(){
	if(!Game.IsGameOver){
		string CurrentScore=Game.Data.Replace("1v1ModeScore=", String.Empty);
			String[] CS = CurrentScore.Split('-');
				if(Team1_lastWin==0) { Team1_lastWin=int.Parse(CS[0]); }
				if(Team2_lastWin==0) { Team2_lastWin=int.Parse(CS[1]); }
	}
	else{
		if(ScriptActive) Game.Data= string.Format("1v1ModeScore={0}-{1}", Team1_lastWin, Team2_lastWin); //MSG("GD= "+Game.Data);
	}
}

public void ErrorTournament(){
Remove1v1Timer();
	MSG("#######< #Tourney >########");
MSG("Unable To Start Tournament");
MSG("-> Assign Team 1 and Team 2");
	MSG("#######< End >########");
}

public void TournamentStopped(){
Remove1v1Timer();
	MSG("#######< #Tourney >########");
MSG("Host has Stopped the Tournament!");
MSG("You can now stop the Script.");
	MSG("#######< End >########");
CloseTournament();
}


// =====< helpers >===== //

private bool UserStillHere(IUser user){
	foreach (IUser usr in Game.GetActiveUsers())
		if (usr.UserId == user.UserId) return true;
	return false;
}

public void MSG(string text) { Game.RunCommand("/MSG " + text); }

public void GameOver(string text) { Game.SetGameOver(text); }

public void NextMap(string map) { Game.RunCommand("/changemap " + map); }

public void CFTXT(Vector2 pos, string text) { Game.PlayEffect("CFTXT", pos, text); }

public void CreateRevoluteJoint()
{
	TourneyStarted = (IObjectRevoluteJoint)Game.CreateObject("RevoluteJoint", new Vector2(10,10));
	TourneyStarted.CustomID="#Tourney_Running";

}

// ==================== //
1 x
🎶I will tell your story if you die
I will tell your story and keep you alive the best i can
...
But I've always had the feeling we would die young
Some die young
🎵
https://i.imgur.com/D479VLi.png

Post Reply