Forum

> > CS2D > Scripts > Script to maintain a specific number of players?
ForenübersichtCS2D-Übersicht Scripts-ÜbersichtEinloggen, um zu antworten

Englisch Script to maintain a specific number of players?

11 Antworten
Zum Anfang Vorherige 1 Nächste Zum Anfang

alt Script to maintain a specific number of players?

RichNagel
User Off Offline

Zitieren
I know nothing about Lua scripting, but saw this script over in the file archive:

http://www.unrealsoftware.de/files_show.php?file=875

That gave me an idea... creating a simple script that would maintain "x" amount of players in the game. Bots would join or leave the game in order to maintain this preset amount of players in the game.

So... after a 'crash course' in Lua scripting <grin> (and browsing the above-linked script), I came up with this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
players = 10

addhook('ms100','botbalance_ms100')
function botbalance_ms100()
player_count = 0
	for i = 1,32, 1 do
		if (player(i,'exists')) then
			player_count = player_count + 1
		end
	end
	
	if (player_count < players) then
		for i = 1,players, 1 do
			parse('bot_add')
		end
	end
	
	if (player_count > players) then 
	parse('bot_remove')
	end
end

The above will maintain 10 players in the game. If a human joins the game, a bot leaves (and vice versa).


Now, that being said, I thought it would be handy if human spectators were NOT counted for the total amount of players. In other words:

I have 10 bots, five on each team. I join the game as a spectator, and the bots happily play their exisiting game.

If I join a team, one bot on that team is kicked... and if I join the spectators again, a bot will be added to that team.


So... I modified my script like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
players = 10

addhook('ms100','botbalance_ms100')
function botbalance_ms100()
player_count = 0
	for i = 1,32, 1 do
		if (player(i,'exists')) and (player(i,'team') ~= 0) then
			player_count = player_count + 1
		end
	end
	
	if (player_count < players) then
		for i = 1,players, 1 do
			parse('bot_add')
		end
	end
	
	if (player_count > players) then 
	parse('bot_remove')
	end
end

...which seems to work perfectly like I described above, but there is one little glitch that I don't care for:

If a human is in the game on a team, and then goes to spectator mode, ALL of the bots are kicked and a fresh new batch of bots are added (to equal out the teams)... thereby RESETTING the round (with the newly added bots).


Is there anything that I could modifiy in the second script so that if there is a human who is on one of the two teams, who then goes into spectator mode, the script will simply add another bot WITHOUT the round restarting?


Thanks in advance for any help

alt Re: Script to maintain a specific number of players?

sheeL
User Off Offline

Zitieren
is only one example of how you start your work

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
addhook("leave","_leave")
addhook("log","_log")

function _log(text)
     if string.sub(text,1,22)=="recv join attempt... (" then
          parse("bot_remove")
     end
end

function _leave(id)
     for i=1,game("sv_maxplayers")-#player(0,"table")+1 do
          timer(100,"parse","bot_add")
     end
end

for i=1,game("sv_maxplayers")-#player(0,"table") do
     parse("bot_add")
end
1× editiert, zuletzt 19.12.12 19:46:50

alt Re: Script to maintain a specific number of players?

RichNagel
User Off Offline

Zitieren
Thanks for the help, sheeL Although, that is WAY over my head and understanding <grin>.

That being said, I did come up with this that seems to work:

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
players = 10

addhook('ms100','botbalance_ms100')
function botbalance_ms100()
t_player_count = 0
ct_player_count = 0

	for i = 1,32, 1 do
		if (player(i,'exists')) and (player(i,'team') == 1) then
			t_player_count = t_player_count + 1
		end
	end
	
	for i = 1,32, 1 do
		if (player(i,'exists')) and (player(i,'team') == 2) then
			ct_player_count = ct_player_count + 1
		end
	end

	if (t_player_count < players / 2) then
	parse('bot_add_t')
	end

	if (ct_player_count < players / 2) then
	parse('bot_add_ct')
	end
	
	if (t_player_count > players / 2) then 
	parse('bot_remove_t')
	end

	if (ct_player_count > players / 2) then 
	parse('bot_remove_ct')
	end

end

Another question:

Is it possible via Lua to create new CVars that can be entered into the console that the script can proccess? In my script above, it would be really handy to be able to change the "players" variable 'on the fly' using the console (verses having to actually edit the script file).

alt Re: Script to maintain a specific number of players?

omg
User Off Offline

Zitieren
making a new console command would be harder than using a say hook to use lua stuff

basic idea:
1
2
3
4
5
6
7
addhook("say","bad_function")
function bad_function(id,txt)
	if string.sub(txt,1,7)=="players" then
		players=tonumber(string.sub(txt,9))
		return 1
	end
end
additionally, it may be smart to add a check to see if it's actually you who's using the command

alt Re: Script to maintain a specific number of players?

RichNagel
User Off Offline

Zitieren
(P[re].S. Scroll to the bottom of this message post)


Thanks for the code and info, omg! I'll try that out ASAP


(*EDIT*)

OK, I've pretty much got this beast working as I wished I ran into a small problem though.

user omg hat geschrieben
additionally, it may be smart to add a check to see if it's actually you who's using the command


Here is my current (and pretty much functioning) script:

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
bot_balance = 5

addhook('join','bot_team_balance_join_server_message')
function bot_team_balance_join_server_message()

	msg("©000255000This server is running Advanced Bot Team Balance v1.0!@C")

end

addhook('say','bot_team_balance_say_commands')
function bot_team_balance_say_commands(player_id,text)

	if (player(1,'exists')) and string.sub(text,1,20)=='bot_team_balance_off' then
		freehook('ms100','bot_team_balance_functions')
		msg("©000255000Bot Team Balance has been disabled.@C")
		msg("©000255000To enable Bot Team Balance, use the command 'bot_team_balance_on'.@C")
		return 1
	end

	if (player(player_id,'rcon') == true) and string.sub(text,1,20)=='bot_team_balance_off' then
		freehook('ms100','bot_team_balance_functions')
		msg("©000255000Bot Team Balance has been disabled.@C")
		msg("©000255000To enable Bot Team Balance, use the command 'bot_team_balance_on'.@C")
		return 1
	end

	if (player(1,'exists')) and string.sub(text,1,19)=='bot_team_balance_on' then
		addhook('ms100','bot_team_balance_functions')
		msg("©000255000Bot Team Balance has been enabled.@C")
		msg("©000255000To disable Bot Team Balance, use the command 'bot_team_balance_off'.@C")
		return 1
	end

	if (player(player_id,'rcon') == true) and string.sub(text,1,19)=='bot_team_balance_on' then
		addhook('ms100','bot_team_balance_functions')
		msg("©000255000Bot Team Balance has been enabled.@C")
		msg("©000255000To disable Bot Team Balance, use the command 'bot_team_balance_off'.@C")
		return 1
	end

	if (player(1,'exists')) and string.sub(text,1,11)=='bot_balance' then
		bot_balance_temp=tonumber(string.sub(text,13))
		bot_balance_temp_text=(string.sub(text,13))
			if (bot_balance_temp ~= nil) then
				msg("©000255000Bot Team Balance has been changed to "..bot_balance_temp_text.." players per team.@C")
				else
				msg("©255000000You have entered an invalid value for the 'bot_balance' command!@C")
				msg("©000255000Please include the desired number of players per team (e.g. 'bot_balance 5').@C")
			end
		return 1
	end

	if (player(player_id,'rcon') == true) and string.sub(text,1,11)=='bot_balance' then
		bot_balance_temp=tonumber(string.sub(text,13))
		bot_balance_temp_text=(string.sub(text,13))
			if (bot_balance_temp ~= nil) then
				msg("©000255000Bot Team Balance has been changed to "..bot_balance_temp_text.." players per team.@C")
				else
				msg("©255000000You have entered an invalid value for the 'bot_balance' command!@C")
				msg("©000255000Please include the desired number of players per team (e.g. 'bot_balance 5').@C")
			end
		return 1
	end

end

addhook('ms100','bot_team_balance_functions')
function bot_team_balance_functions()

t_player_count = 0
ct_player_count = 0

	if (bot_balance_temp ~= nil) then
		bot_balance = bot_balance_temp
		else
		bot_balance = bot_balance
	end

	for i = 1,32, 1 do
		if (player(i,'exists')) and (player(i,'team') == 1) then
			t_player_count = t_player_count + 1
		end
	end
	
	for i = 1,32, 1 do
		if (player(i,'exists')) and (player(i,'team') == 2) then
			ct_player_count = ct_player_count + 1
		end
	end

	for i = 1,32, 1 do
		if (player(i,'exists')) and (player(i,'team') == 3) then
			ct_player_count = ct_player_count + 1
		end
	end

	if (t_player_count < bot_balance) then
	parse('bot_add_t')
	end

	if (ct_player_count < bot_balance) then
	parse('bot_add_ct')
	end
	
	if (t_player_count > bot_balance) then
	parse('bot_remove_t')
	end

	if (ct_player_count > bot_balance) then
	parse('bot_remove_ct')
	end

end

In my script above I'm using the "(player(player_id,'rcon') == true)" to see if the player is connected to a dedicated server and is in RCon mode. But, I ALSO wanted this to work for an individual running the script locally on his PC (hosting a "listen" server).

So, I added the "(player(1,'exists'))" sections, as I couldn't RCon when I started a "listen" server. It seemed that every time that I started a "listen" server, I was always player ID "1"... hence the "(player(1,'exists'))" sections.

But, a small snag...

I discovered that when I started a dedicated server, and then started the game and joined the dedicated server (just like any ordinary player would join), occasionally my player ID was "1", even though there were already bots playing (?).

What would you suggest to check if the player is running the script during his own "listen" server game (short of him having to edit the script with something like his own player name or USGN ID)?


(*EDIT #2*)

Looks like it will work properly if I change all of the "say" commands to console commands

e.g.

1
2
3
4
5
6
7
8
9
10
addhook('parse','bot_team_balance_console_commands')
function bot_team_balance_console_commands(cmd)

	if (cmd=='bot_balance 1') then
		bot_balance = 1
		msg("©000255000Bot Team Balance has been changed to 1 players per team.@C")
		return 1
	end

end

etc...


(*AND YET ANOTHER EDIT*)

The fruit of my labor is here -> http://www.unrealsoftware.de/files_show.php?file=12891 .

Thanks to all of the posters in this thread for all of the help with my FIRST CS2D Lua scripting project!
9× editiert, zuletzt 21.12.12 15:22:49

alt Re: Script to maintain a specific number of players?

omg
User Off Offline

Zitieren
well, its one thing to be able to make something work. its more impressive if u can make it work more efficiently

using ms100 is awfully inefficient for something that doesnt need to be monitored precisely; it can easily be changed into a second hook without much difference and saves a lot more function calls

better yet, monitor whenever people leave and join and keep a counter of how many people are in the server that way and then change the ms100 function to a minute function to catch random disconnects. this would be just about the most efficient method possible for monitoring the same thing

alt Re: Script to maintain a specific number of players?

RichNagel
User Off Offline

Zitieren
user omg hat geschrieben
well, its one thing to be able to make something work. its more impressive if u can make it work more efficiently. using ms100 is awfully inefficient for something that doesnt need to be monitored precisely; it can easily be changed into a second hook without much difference and saves a lot more function calls.


Thanks for the heads-up, omg I was thinking the same thing... no real need to do a check 10 times a second.

BTW, here's something that I posted in the comments section of the file I uploaded ( http://www.unrealsoftware.de/files_show.php?file=12891 ), maybe you might be able to give me some ideas how to do this?

-=-=-=-=-=-=-=-=-=-

Folks,

One thing that I've recently discovered is that CS2D flushes all of the variables in a Lua script when the map cycles on a listen or dedicated server. This resets the main team balancing variable to 5 (the default "bot_balance = 5" line included in the Lua script).

Now, being that the 'bot team balance' can be configured via commands (listen server, as well as RCon for a dedicated server) in the console ("bot_balance 6" etc...), it would be SUPER if there was some way to save it to a config file, and then read the variable from the config file after the map cycles (and the Lua script is re-executed).

Anyhow, could anyone give any pointers on how to:

1 - Open a config file: e.g.

Open the filename "AdvancedBotTeamBalance.cfg" (which would be located in the same directory as the "AdvancedBotTeamBalance.lua" script).

2 - Read a line from the config file (in this case, there would be only one line to store the team balance number... BUT, POSSIBLY two lines; a second for if the team balancing routine is enabled or disabled): e.g.

bot_balance = 4
bot_balance_enabled = 1

3 - Read the "4" from the top line, and then pass it on to the Lua script's variable (as well as the "1" and also pass it on as another Lua script variable).

...and ALSO, WRITE to the config file if/when any of the settings have been changed in-game (listen server, or via RCon).

I've read a LOT from this site -> http://www.lua.org/manual/5.1/manual.html , and I THINK it probably would have something to do with using the "io.open", "io.read", "io.write" commands, etc... but it's WAY over my understanding of Lua coding (unless I could see a simple and an easy-to-understand code example).

-=-=-=-=-=-=-=-=-=-

alt Re: Script to maintain a specific number of players?

EngiN33R
Moderator Off Offline

Zitieren
Let's think this through.

You have a script that has to maintain a constant number of players. The number of players only changes if a player joins or leaves. Therefore, we can get rid of the ms100 hook in lieu of a more efficient method, which is join and leave hooks.

About the files - since you store such simple info in your file it really doesn't make much sense to use the I/O library. What you could do instead is simply execute your config file as if it were a Lua script.

Contents of sys/botbalance.cfg (you can change the path):

1
2
bot_balance = true
bot_balance_pl = 4

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
pcall(dofile,"sys/botbalance.cfg") -- we execute it as a Lua script, but we do it via pcall just in case that config file doesn't exist

if bot_balance == nil then bot_balance = false end --if no setting is specified default it to disabled

playern = 0

for _,id in pairs(player(0,"table")) do --you should prefer this method to the simple loop of 1 to 32
	playern = playern + 1
end

addhook("join","botbalance_jplayer")
function botbalance_jplayer(id)
	if bot_balance and not player(id,"bot") then
		playern = playern + 1
	end
end

addhook("leave","botbalance_lplayer")
function botbalance_lplayer(id)
	if bot_balance and not player(id,"bot") then
		playern = playern - 1
	end
end

function botbalance()
	if bot_balance then
		local botn=0 --this and the next block is to get the number of bots
		for _,id in pairs(player(0,"table")) do
			if player(id,"bot") then botn=botn+1 end
		end
		local diff = bot_balance_pl-playern-botn --difference that the bots will compensate for
		if diff>0 then
			for i=1,diff do
				parse("bot_add")
			end
		end
		if diff<=0 then --if there's an excess of players and there's still bots
			for i=1,math.abs(diff) do
				parse("bot_remove") --remove just the sheer number of bots
			end
		end
end

addhook("join","botbalance")
addhook("leave","botbalance") --add the pair of hooks to the function to make it work

function writeconf()
	local cfg=io.open("sys/botbalance.cfg","w") --open for overwriting
	cfg:write("bot_balance = "..tostring(bot_balance).."\n")
	cfg:write("bot_balance_pl = "..bot_balance_pl)
	cfg:close()
end

-- Now for the config writing part
addhook("parse","schange")
function schange(cmd)
	if cmd:sub(1,3)=="lua" then
		if cmd:find("bot_balance.-%s?=%s?") then --more below
			timer(1,"writeconf") --because this is executed before the command is, we have to wait for the command to take effect and then write the config.
		end
	end
end

To explain the cmd:find part in detail:
Mehr >


I haven't really tested this, but I have a hunch that it will work. Post the errors if they occur and we'll try to help. Also feel free to PM me if you have any questions on Lua scripting in general - I'm always glad to help.

alt Re: Script to maintain a specific number of players?

omg
User Off Offline

Zitieren
i think itd be simpler if bot_balance was saved as an integer

doesnt write have to use +a to keep previous lines? im pretty sure w overwrites previous text

you still need to run the ms100 function occasionally to catch disconnecters that dont "leave"

otherwise, i like the way engineer uses it as another script. saves some io work which (im pretty sure) is more expensive and harder to manage

alt Re: Script to maintain a specific number of players?

RichNagel
User Off Offline

Zitieren
Thanks a MILLION for all of the information, EngiN33R (you too, OMG)!

I have just successfully edited the script so that it reads from the config file, and then writes to it with any changes that were issued via the console

I've also added a routine to check if the config file actually exists; and if not, creates a new one with the default parameters (and subsequently executes those defaults).

I'm well on my way with these additions to my meager little LUA project

THANKS AGAIN!

alt Re: Script to maintain a specific number of players?

EngiN33R
Moderator Off Offline

Zitieren
user omg hat geschrieben
i think itd be simpler if bot_balance was saved as an integer

doesnt write have to use +a to keep previous lines? im pretty sure w overwrites previous text

you still need to run the ms100 function occasionally to catch disconnecters that dont "leave"

otherwise, i like the way engineer uses it as another script. saves some io work which (im pretty sure) is more expensive and harder to manage


Actually, boolean true/false is less expensive. Numbers in Lua take up 64 bits in memory while boolean values do 8. Basically, boolean values are 8 times as efficient. And you do use a to append, but I need the w mode to overwrite existing settings with the new ones - what's the point of having loads of lines declaring the same variables, but differently?

Yes, you're right about the disconnecters - sometimes players time out without being registered in the leave hook. You have to run the botbalance() function every now and then to compensate for that.

And it's no problem, user RichNagel. Always glad to help.
Zum Anfang Vorherige 1 Nächste Zum Anfang
Einloggen, um zu antworten Scripts-ÜbersichtCS2D-ÜbersichtForenübersicht