×

Langue

Fermer
Atelier 801
  • Forums
  • Dev Tracker
  • Connexion
    • English Français
      Português do Brasil Español
      Türkçe Polski
      Magyar Română
      العربية Skandinavisk
      Nederlands Deutsch
      Bahasa Indonesia Русский
      中文 Filipino
      Lietuvių kalba 日本語
      Suomi עברית
      Italiano Česky
      Hrvatski Slovensky
      Български Latviešu
      Estonian
  • Langue
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Adding teams to your games
[Tutorial] Adding teams to your games
Onkei
« Citoyen »
1495639500000
    • Onkei#0000
    • Profil
    • Derniers messages
    • Tribu
#1
  2
Welcome to this short tutorial on adding Teams to your mini-game! For this, I'll be taking the finished version of Shamousey's Free for All tutorial and we'll work from this script to add teams.

This is the script we have initially;


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
tfm.exec.disableAutoNewGame(true)
tfm.exec.disableAutoShaman(true)

players = {}
toDespawn = {}
maps = {521833, 401421, 541917, 541928, 541936, 541943, 527935, 559634, 559644, 888052, 878047, 885641, 770600, 770656, 772172, 891472, 589736, 589800, 589708, 900012, 901062, 754380, 901337, 901411, 907870, 910078, 1190467, 1252043, 1124380, 1016258, 1252299, 1255902, 1256808, 986790, 1285380, 1271249, 1255944, 1255983, 1085344, 1273114, 1276664, 1279258, 1286824, 1280135, 1280342, 1284861, 1287556, 1057753, 1196679, 1288489, 1292983, 1298164, 1298521, 1293189, 1296949, 1308378, 1311136, 1314419, 1314982, 1318248, 1312411, 1312589, 1312845, 1312933, 1313969, 1338762, 1339474, 1349878, 1297154, 644588, 1351237, 1354040, 1354375, 1362386, 1283234, 1370578, 1306592, 1360889, 1362753, 1408124, 1407949, 1407849, 1343986, 1408028, 1441370, 1443416, 1389255, 1427349, 1450527, 1424739, 869836, 1459902, 1392993, 1426457, 1542824, 1533474, 1561467, 1563534, 1566991, 1587241, 1416119, 1596270, 1601580, 1525751, 1582146, 1558167, 1420943, 1466487, 1642575, 1648013, 1646094, 1393097, 1643446, 1545219, 1583484, 1613092, 1627981, 1633374, 1633277, 1633251, 1585138, 1624034, 1616785, 1625916, 1667582, 1666996, 1675013, 1675316, 1531316, 1665413, 1681719, 1699880, 1688696, 623770, 1727243, 1531329, 1683915, 1689533, 1738601, 3756146, 912118, 3326933, 3722005, 3566478, 1456622, 1357994, 1985670, 1884075, 1708065, 1700322, 2124484, 3699046, 2965313, 4057963, 4019126, 3335202, 2050466}

function eventNewPlayer(name)
for i, key in ipairs({32, 40, 83}) do
tfm.exec.bindKeyboard(name, key, true, true)
end

players[name] = {
timestamp = os.time(),
offsets = {x = 2, y = 10}
}
end

function eventKeyboard(name, key, down, x, y)
if (key == 32 or key == 40 or key == 83) and not tfm.get.room.playerList[name].isDead and started then
if players[name].timestamp < os.time() - 1000 then
local id = tfm.exec.addShamanObject(17, x + (tfm.get.room.playerList[name].isFacingRight and players[name].offsets.x or -players[name].offsets.x), y + players[name].offsets.y, tfm.get.room.playerList[name].isFacingRight and 90 or 270)
players[name].timestamp = os.time()
table.insert(toDespawn, {os.time(), id})
end
end
end

function eventChatCommand(name, command)
local arg = {}
for argument in command:gmatch("[^%s]+") do
table.insert(arg,argument)
end
if arg[1] == "off" then
if tonumber(arg[2]) and tonumber(arg[3]) then
players[name].offsets.x = tonumber(arg[2])
players[name].offsets.y = tonumber(arg[3])
else
players[name].offsets.x = 2
players[name].offsets.y = 10
end
-- tfm.exec.chatMessage("Offsets changed to X:"..players[name].offsets.x.." Y:"..players[name].offsets.y,name)
end
end

function eventNewGame()
started = false
end

function eventLoop(time, remaining)
if time >= 3000 and not started then
started = true
end
if remaining <= 0 then
tfm.exec.newGame(maps[math.random(#maps)])
end
for i, cannon in ipairs(toDespawn) do
if cannon[1] <= os.time() - 3000 then
tfm.exec.removeObject(cannon[2])
table.remove(toDespawn, i)
end
end
end

function eventPlayerDied(name)
local i = 0
local n
for pname, player in pairs(tfm.get.room.playerList) do
if not player.isDead then
i = i + 1
n = pname
end
end
if i == 0 then
tfm.exec.newGame(maps[math.random(#maps)])
elseif i == 1 then
tfm.exec.giveCheese(n)
tfm.exec.playerVictory(n)
tfm.exec.setGameTime(5)
end
end

for name, player in pairs(tfm.get.room.playerList) do
eventNewPlayer(name)
end

tfm.exec.newGame(maps[math.random(#maps)])


To start off, we need to determine a way to store the players and other team-related data into the different teams. In this example, we'll have only two teams Blue and Red, but we'll make it so it'll easy to expand the script to add more teams. A simple way to store players / data into different teams would be to make a table for each team (Blue and Red). Additionally, we'll put these into another "teams" table to allow for easier access later on.

Inside the Blue and Red tables, we'll have another table called "playerList" to store the players in that team, and a "color" variable to store the team's respective color. The color variable will store a 0xhex code, which will allow us to determine whether a player is in Team Red or Team Blue in-game later when we use it to set each player's nametag.


Code Lua

1
2
3
4
5
6
7
8
9
10
11
local teams = {
Blue = {
playerList = {},
color = "0x2323bf"
},

Red = {
playerList = {},
color = "0xbf2323"
},
}


Now, let's actually start putting the players into different teams by randomising them. To do this, let's actually put the code to implement this into its' own seperate function, since we might want to call this in different places. We'll call this function "seperatePlayers" since we'll be seperating the players into different teams.

To implement the actual seperation of the players, we need to put conveniently put all the players into a local table (a table that we can't access outside of the function) so we can check who hasn't been selected into a team when we seperate the players. Let's do this first by looping through tfm.get.room.playerList and putting them into a "playersLeft" table.


Code Lua

1
2
3
4
5
6
7
8
function seperatePlayers()
local playersLeft = {}

for n in pairs(tfm.get.room.playerList) do
-- Adding each player's name into the playersLeft table.
table.insert(playersLeft, n)
end
end


Okay, this next bit is slightly harder since we're going to have to do actually seperate the players now. There's plenty of ways to do this, it just requires some thinking. The algorithm I'll be implementing will involve putting the players left in the playersLeft table to the team with the least amount of members. Let's see how we can do this..

First, we have to find the team with the least amount of players. We'll do this by looping through each team's table and compare their playerList with the playerList of the current team with the least amount of players. The current team with the least amount of players can be stored into a local table called "smallestTeam".


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function seperatePlayers()
local playersLeft = {}

for n in pairs(tfm.get.room.playerList) do
table.insert(playersLeft, n)
end

--[[
Finding the team with the least amount of members.

We initialise the smallestTeam with some players
in the playerList table so it won't get selected
as the actual smallest team at the end.
]]
local smallestTeam = {playerList = {"Onkei", "Random Guy", "Another Guy", "More Guys", "Johnny Cash"}}
for team, data in pairs(teams) do
-- #table gives the length of a table (number of things inside it).
if #data.playerList < #smallestTeam.playerList then
--[[
Since the teams table is an associative array (accessed by strings
like "Blue" or "Red"), we can access the data for the team with
the least amount of players by doing like so;
]]
smallestTeam = teams[team]
end
end
--[[
Now, the team with the least amount of players will be contained in
smallestTeam.
]]

end


Now that we've got the team with the least amount of players, what do we need to do? We have to put a random player from the playersLeft table to the team!

However, note that we'll have to do this process again and again until there's nobody left in the playersLeft table, so we need to put all of the code we written into a while loop. This while loop should end whenever the playersLeft is empty, indicating that all players have been randomized into a team.


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function seperatePlayers()
local playersLeft = {}

for n in pairs(tfm.get.room.playerList) do
table.insert(playersLeft, n)
end

--[[
We keep executing the code enclosed in the while loop
when the length of playersLeft is greater than 0 (not empty).
]]
while (#playersLeft > 0) do
local smallestTeam = {playerList = {"Onkei", "Random Guy", "Another Guy", "More Guys", "Johnny Cash"}}
for team, data in pairs(teams) do
if #data.playerList < #smallestTeam.playerList then
smallestTeam = teams[team]
end
end

--[[
Selecting a random index (key / location) from the playersLeft table
and storing it into a variable called randomIndex, and the player
(value / data) associated with the index to another variable called
randomPlayer.

This player is then added to the team with the least amount of players
and removed from the playersLeft table.
]]
local randomIndex = math.random(#playersLeft)
local randomPlayer = playersLeft[randomIndex]
table.insert(smallestTeam.playerList, randomPlayer)
table.remove(playersLeft, randomIndex)
end
end


We can consider this function pretty much done now, since whenever we call the function, it'll put all the players in the room into a random team from the teams table. However, we should reset the playerList for each team whenever this function is called, so players don't end up being in the two teams at the same time. Let's quickly do this.


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function seperatePlayers()
--[[
For each team in the teams table, empty their playerList
by replacing it with a new table.
]]
for team, data in pairs(teams) do
data.playerList = {}
end

local playersLeft = {}

for n in pairs(tfm.get.room.playerList) do
table.insert(playersLeft, n)
end

while (#playersLeft > 0) do
local smallestTeam = {playerList = {"Onkei", "Random Guy", "Another Guy", "More Guys", "Johnny Cash"}}
for team, data in pairs(teams) do
if #data.playerList < #smallestTeam.playerList then
smallestTeam = teams[team]
end
end

local randomIndex = math.random(#playersLeft)
local randomPlayer = playersLeft[randomIndex]
table.insert(smallestTeam.playerList, randomPlayer)
table.remove(playersLeft, randomIndex)
end
end


It's time to actually call the function. If we want to have the teams be chosen only once at the start of the script, we can just call it before we load a new map for the first time. However, if we want to have different teams every round (which is how the Team mode works in official FFA), we put it inside the eventNewGame function, which gets called whenever a new round begins.


Code Lua

1
2
3
4
5
function eventNewGame()
started = false

seperatePlayers()
end


Teams are finally implemented into the game! Buuut.. we don't really know who's in what team. Well actually, we have a corresponding color variable which contains a 0xhex value for each team. Let's actually use this to distinguish between players! We can loop through each team's playerList and then give every player in that playerList the color of that respective team.

We'll enclose the code to implement this into another seperate function "manageTeams" so we can easily add more features to it if we want to in the future. But to be honest I just want to keep eventNewGame clean.


Code Lua

1
2
3
4
5
6
function eventNewGame()
started = false

seperatePlayers()
manageTeams()
end



Code Lua

1
2
3
4
5
6
7
function manageTeams()
for team, data in pairs(teams) do
for i, n in pairs(data.playerList) do
tfm.exec.setNameColor(n, data.color)
end
end
end


Woot! We're getting close to done. The only thing we've really got to do is to determine when to end a round. What we have currently is from Shamo's FFA tutorial, which lowers the time down to 5s (since a new map will load when 0s is left, done in eventLoop) and gives a win to the player alive when there's only one person left.


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function eventPlayerDied(name)
local i = 0
local n
for pname, player in pairs(tfm.get.room.playerList) do
if not player.isDead then
i = i + 1
n = pname
end
end
if i == 0 then
tfm.exec.newGame(maps[math.random(#maps)])
elseif i == 1 then
tfm.exec.giveCheese(n)
tfm.exec.playerVictory(n)
tfm.exec.setGameTime(5)
end
end


We want to change this so all of the players in a team wins if the other team(s) are dead. We can achieve this by creating an empty table called "aliveTeams" that'll contain a list of teams that are alive, so we can check if there's only one team alive left later. Now, to fill the table we loop through the teams table, and through each team's playerList and try to find if someone is alive from that team.

To check if someone is alive, we use the tfm.get.room.playerList table which contains data about the player - and access the isDead value which returns either true or false (true if the player is dead). In-case a player from the team has left the room, we'll also check if the data about the player exists.


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function eventPlayerDied(name)
local aliveTeams = {}

for team, data in pairs(teams) do
for i, n in pairs(data.playerList) do
if tfm.get.room.playerList[n] and not tfm.get.room.playerList[n].isDead then
table.insert(aliveTeams, team)
--[[
If a person isn't dead from a certain team, we can just break
the for loop to check if the team's alive since we only need
one player in the team alive, for that team to be alive.
]]
break
end
end
end
--[[
Now we can check if there's only one team alive.
]]

end


Last thing to do is to give victory to all the players in the only team alive. We can easily do this since we can access the only team alive by doing "teams[aliveTeams[1]]". To give victory to everyone in that team, we can just do the for looping method again.


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function eventPlayerDied(name)
local aliveTeams = {}

for team, data in pairs(teams) do
for i, n in pairs(data.playerList) do
if tfm.get.room.playerList[n] and not tfm.get.room.playerList[n].isDead then
table.insert(aliveTeams, team)
break
end
end
end

--[[
If the number of teams in aliveTeams is equal
to 1 (only one team is alive).
]]
if #aliveTeams == 1 then
local aliveTeam = teams[aliveTeams[1]]
for i, n in pairs(aliveTeam.playerList) do
if tfm.get.room.playerList[n] and not tfm.get.room.playerList[n].isDead then
tfm.exec.giveCheese(n)
tfm.exec.playerVictory(n)
end
end

tfm.exec.setGameTime(5)
elseif #aliveTeams == 0 then
tfm.exec.newGame(maps[math.random(#maps)])
end
end


And that concludes this tutorial! We've implemented a Teams system into FFA, simillar to that from the actual Team Mode from the official Deathmatch module!

Obviously, you should improve this script so you can add scores and more things to it, but hopefully you've learned how to implement a Teams system into all your mini-games. The manageTeams and seperatePlayers functions we made should be mostly applicable to any mini-game you want to implement teams in! If you want to add more teams, you can simply follow the template I used to make the Blue or the Red team.

Here's the full code we now have;


Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
--[[
[Tutorial] Adding teams to your games by Onkei.
]]

local teams = {
Blue = {
playerList = {},
color = "0x2323bf"
},

Red = {
playerList = {},
color = "0xbf2323"
},
}

function eventPlayerDied(name)
local aliveTeams = {}

for team, data in pairs(teams) do
for i, n in pairs(data.playerList) do
if tfm.get.room.playerList[n] and not tfm.get.room.playerList[n].isDead then
table.insert(aliveTeams, team)
break
end
end
end

if #aliveTeams == 1 then
local aliveTeam = teams[aliveTeams[1]]
for i, n in pairs(aliveTeam.playerList) do
if tfm.get.room.playerList[n] and not tfm.get.room.playerList[n].isDead then
tfm.exec.giveCheese(n)
tfm.exec.playerVictory(n)
end
end

tfm.exec.setGameTime(5)
elseif #aliveTeams == 0 then
tfm.exec.newGame(maps[math.random(#maps)])
end
end

function manageTeams()
for team, data in pairs(teams) do
for i, n in pairs(data.playerList) do
tfm.exec.setNameColor(n, data.color)
end
end
end

function seperatePlayers()
for team, data in pairs(teams) do
data.playerList = {}
end

local playersLeft = {}

for n in pairs(tfm.get.room.playerList) do
table.insert(playersLeft, n)
end

while (#playersLeft > 0) do
local smallestTeam = {playerList = {"Onkei", "Random Guy", "Another Guy", "More Guys", "Johnny Cash"}}
for team, data in pairs(teams) do
if #data.playerList < #smallestTeam.playerList then
smallestTeam = teams[team]
end
end

local randomIndex = math.random(#playersLeft)
local randomPlayer = playersLeft[randomIndex]
table.insert(smallestTeam.playerList, randomPlayer)
table.remove(playersLeft, randomIndex)
end
end

--[[
[Tutorial] Free for All script by Shamousey.
]]

tfm.exec.disableAutoNewGame(true)
tfm.exec.disableAutoShaman(true)

players = {}
toDespawn = {}
maps = {521833, 401421, 541917, 541928, 541936, 541943, 527935, 559634, 559644, 888052, 878047, 885641, 770600, 770656, 772172, 891472, 589736, 589800, 589708, 900012, 901062, 754380, 901337, 901411, 907870, 910078, 1190467, 1252043, 1124380, 1016258, 1252299, 1255902, 1256808, 986790, 1285380, 1271249, 1255944, 1255983, 1085344, 1273114, 1276664, 1279258, 1286824, 1280135, 1280342, 1284861, 1287556, 1057753, 1196679, 1288489, 1292983, 1298164, 1298521, 1293189, 1296949, 1308378, 1311136, 1314419, 1314982, 1318248, 1312411, 1312589, 1312845, 1312933, 1313969, 1338762, 1339474, 1349878, 1297154, 644588, 1351237, 1354040, 1354375, 1362386, 1283234, 1370578, 1306592, 1360889, 1362753, 1408124, 1407949, 1407849, 1343986, 1408028, 1441370, 1443416, 1389255, 1427349, 1450527, 1424739, 869836, 1459902, 1392993, 1426457, 1542824, 1533474, 1561467, 1563534, 1566991, 1587241, 1416119, 1596270, 1601580, 1525751, 1582146, 1558167, 1420943, 1466487, 1642575, 1648013, 1646094, 1393097, 1643446, 1545219, 1583484, 1613092, 1627981, 1633374, 1633277, 1633251, 1585138, 1624034, 1616785, 1625916, 1667582, 1666996, 1675013, 1675316, 1531316, 1665413, 1681719, 1699880, 1688696, 623770, 1727243, 1531329, 1683915, 1689533, 1738601, 3756146, 912118, 3326933, 3722005, 3566478, 1456622, 1357994, 1985670, 1884075, 1708065, 1700322, 2124484, 3699046, 2965313, 4057963, 4019126, 3335202, 2050466}

function eventNewPlayer(name)
for i, key in ipairs({32, 40, 83}) do
tfm.exec.bindKeyboard(name, key, true, true)
end

players[name] = {
timestamp = os.time(),
offsets = {x = 2, y = 10}
}
end

function eventKeyboard(name, key, down, x, y)
if (key == 32 or key == 40 or key == 83) and not tfm.get.room.playerList[name].isDead and started then
if players[name].timestamp < os.time() - 1000 then
local id = tfm.exec.addShamanObject(17, x + (tfm.get.room.playerList[name].isFacingRight and players[name].offsets.x or -players[name].offsets.x), y + players[name].offsets.y, tfm.get.room.playerList[name].isFacingRight and 90 or 270)
players[name].timestamp = os.time()
table.insert(toDespawn, {os.time(), id})
end
end
end

function eventChatCommand(name, command)
local arg = {}
for argument in command:gmatch("[^%s]+") do
table.insert(arg,argument)
end
if arg[1] == "off" then
if tonumber(arg[2]) and tonumber(arg[3]) then
players[name].offsets.x = tonumber(arg[2])
players[name].offsets.y = tonumber(arg[3])
else
players[name].offsets.x = 2
players[name].offsets.y = 10
end
-- tfm.exec.chatMessage("Offsets changed to X:"..players[name].offsets.x.." Y:"..players[name].offsets.y,name)
end
end

function eventNewGame()
started = false

seperatePlayers()
manageTeams()
end

function eventLoop(time, remaining)
if time >= 3000 and not started then
started = true
end
if remaining <= 0 then
tfm.exec.newGame(maps[math.random(#maps)])
end
for i, cannon in ipairs(toDespawn) do
if cannon[1] <= os.time() - 3000 then
tfm.exec.removeObject(cannon[2])
table.remove(toDespawn, i)
end
end
end

for name, player in pairs(tfm.get.room.playerList) do
eventNewPlayer(name)
end

tfm.exec.newGame(maps[math.random(#maps)])

Dernière modification le 1496663460000
Honorabilis
« Consul »
1495641840000
    • Honorabilis#0000
    • Profil
    • Derniers messages
    • Tribu
#2
  1
Good job^^ Thanks.
Soulzone5257
« Citoyen »
1495643520000
    • Soulzone5257#0000
    • Profil
    • Derniers messages
    • Tribu
#3
  0
Good tutorial
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Adding teams to your games
© Atelier801 2018

Equipe Conditions Générales d'Utilisation Politique de Confidentialité Contact

Version 1.27