View difference between Paste ID: kJuLwPiD and U4SkNqqs
SHOW: | | - or go back to the newest paste.
1-
-- Module [football] by Matiasgim and Sincabellera
1+
2
3-
--tfm.exec.setRoomMaxPlayers(14)
3+
4
local MAX_SCORE = 20;
5
local WELCOME_MESSAGE = "<J>Welcome! This is a football game for testing modules. Write <N>!help<J> for more information. Please report any issues to Makinit.";
6
local keys = {space = 32, left = 37, right = 39, a = 65, d = 68, q = 81, x = 88};
7
local team1 = {id = 1, score = 1, colour = "0x0000FF", colour2 = "0x8888FF", tag = "<BV>", name = "the blue team", players = {}};
8
local team2 = {id = 2, score = 1, colour = "0xFF0000", colour2 = "0xFF8888", tag = "<R>", name = "the red team", players = {}};
9
local ball = {player = nil, object = 0, t = 0, x = 0, y = 0, vx = 0, vy = 0, ax = 0, ay = 0, takeTime = 0, shootTime = 0};
10
local tasks = {};
11
12
local addShamanObject = function(...)
13
	local object, x, y, r, vx, vy = ...
14
	print(object .. "," .. x .. "," .. y .. "," .. r .. "," .. vx .. "," .. vy)
15
	return tfm.exec.addShamanObject(...)
16
end
17
18
local players = {};
19
local spectators = {Matiasgim};
20
21
function table.copy(t)
22
  local t2 = {}
23
  for k,v in pairs(t) do
24
    t2[k] = v
25
  end
26
  return t2
27
end
28
29
function printInfo(name, value, tabs)
30
	tabs = tabs or "";
31
	local t = type(value);
32
	print(tabs .. t .. " " .. tostring(name) .. " = " .. tostring(value));
33
	if t == "table" then
34
		for n, v in pairs(value) do
35
			if v == value then
36
				print(tabs .. "\tself " .. n);
37
			else
38
				printInfo(n, v, tabs .. "\t");
39
			end
40
		end
41
	end
42
end
43
44
-------------------------
45
-- Fonction principale --
46
-------------------------
47
48
function main()
49
	command.addHandler("debug", doDebug);
50
	command.addHandler("cheese", doCheese);
51
	command.addHandler("help", doHelp);
52
	command.addHandler("arrow", doArrow);
53
	--command.addHandler("t", doTeamChat);
54
	
55
	debug.disableEventLog(debugOff);
56
	tfm.exec.disableAutoScore(true);
57
	tfm.exec.disableAutoNewGame(true);
58
	tfm.exec.setGameTime(0, true);
59
	--tfm.exec.chatMessage(WELCOME_MESSAGE);
60
	tfm.exec.newGame(MAP);
61
end
62
63
------------------------
64
-- Fonction newGame ----
65
------------------------
66
67
function eventNewGame()
68
	team1.players = {};
69
	team2.players = {};
70
	team1.score = 1;
71
	team2.score = 1;
72
	gameOver = false;
73
	arrows = false;
74
	clearTextArea = false;
75
	for name, player in pairs(tfm.get.room.playerList) do
76
		if player.isShaman then
77
			tfm.exec.killPlayer(name);
78
			tfm.exec.respawnPlayer(name);
79
			shaman = name;
80
		end
81
		initPlayer(name);
82
	end
83
	
84
	for name, player in pairs(tfm.get.room.playerList) do
85
		if player.isShaman then
86
			tfm.exec.killPlayer(name);
87
			tfm.exec.respawnPlayer(name);
88
			shaman = name;
89
		end
90
		returnPlayer(name);
91
	end
92
	ball.object = nil;
93
	if #team1.players > 0 and math.random() > 0.5 then
94
		tasks[os.time() + 5000] = function() giveBall(team1.players[math.random(#team1.players)]) tp123 == true; end;
95
	elseif #team2.players > 0 then
96
		tasks[os.time() + 5000] = function() giveBall(team2.players[math.random(#team2.players)]) tp123 == true; end;
97
	end
98
end
99
100
------------------------------
101
-- Fonction PlayerGetCheese --
102
------------------------------
103
function eventPlayerGetCheese(player)
104
	ball.player = player;
105
        tp123 == true;
106
end
107
108
------------------------
109
-- Fonction eventLoop --
110
------------------------
111
112
function doArrow(player)
113
	if arrows then
114
	arrows = false
115
	else
116
	arrows = true
117
	end
118
end
119
120
function eventLoop()
121
	--[[if clearTextArea then
122
	ui.removeTextArea(0, player)
123
	clearTextArea = false
124
	end]]
125
	--local done = {}
126
	local now = os.time();
127
	
128
	-- task handler
129
	for when, task in pairs(table.copy(tasks)) do
130
		if when <= now then
131
			tasks[when] = nil;
132
			task();
133
		end
134
	end
135
	if not gameOver then
136
		tfm.exec.setGameTime(60 * team1.score + team2.score + 1, true);
137
	if arrows then
138
		local object = ball.object;
139
		local player = ball.player;
140
		if object then
141
			local x, y = getBallLocation();
142
			addShamanObject(0, x, y - 25, 0, 0, 0, true);
143
		elseif player then
144
			local ballPlayer = players[player];
145
			if false or ballPlayer then
146
				addShamanObject(0, ballPlayer.x, ballPlayer.y - 50, 0, 0, 0, true);
147
			end
148
			local tfmPlayer = tfm.get.room.playerList[player];
149
			if tfmPlayer then
150
				addShamanObject(0, tfmPlayer.x, tfmPlayer.y - 50, 0, 0, 0, true);
151
				end
152
				end
153
				end
154
	-- Flèches
155
		
156
		--[[local object = ball.object;
157
		local player = ball.player;
158
		if object then
159
			local x, y = getBallLocation();
160
			addShamanObject(0, x, y - 25, 0, 0, 0, true);
161
		elseif player then
162
			local ballPlayer = players[player];
163
			if false or ballPlayer then
164
				addShamanObject(0, ballPlayer.x, ballPlayer.y - 50, 0, 0, 0, true);
165
			end
166
			local tfmPlayer = tfm.get.room.playerList[player];
167
			if tfmPlayer then
168
				addShamanObject(0, tfmPlayer.x, tfmPlayer.y - 50, 0, 0, 0, true);
169
			end
170
		end]]
171
	else
172
		local left =50;
173
		local right = 1550;
174
		if team1.score > team2.score then
175
			right = 800;
176
		elseif team2.score > team1.score then
177
			left = 800;
178
		end
179
		addShamanObject(28, math.random(left, right), 350, 0, 0, 0, false);
180
	end
181
end
182
183
-----------------------
184
-- Fonction keyboard --
185
-----------------------
186
187
function eventKeyboard(player, key, down, x, y)
188
	if down and players[player] then
189
		if key == keys.left or key == keys.a or key == keys.q then
190
			players[player].direction = -1;
191
		elseif key == keys.right or key == keys.d then
192
			players[player].direction = 1;
193
		end
194
	end
195
	if key == keys.space then
196
		local now = os.time();
197
		local x2, y2 = getBallLocation(now);
198
		if player == ball.player then
199
			if down then
200
				ball.space = now;
201
			elseif ball.space then
202
				local force = (now - ball.space) / 100;
203
				if force > 8 then
204
					force = 8;
205
				end
206
				ball.space = nil;
207
				shootBall(x, y, 5, -6 - force);
208
				players[player].shootTime = now;
209
				ball.takeTime = 0;
210
				ball.shooter = player;
211
			end
212
		elseif ball.object then
213
			local shootTime = players[player].shootTime or 0;
214
			if now > shootTime + 1000 and isClose(x, y - 25, getBallLocation(now)) then
215
				removeBall();
216
				ball.takeTime = now;
217
				giveBall(player);
218
				ball.space = nil;
219
				ball.passer = ball.shooter;
220
			end
221
		elseif ball.player and players[ball.player] and players[ball.player].team.id ~= players[player].team.id and now > ball.takeTime + 1000 then
222
			local ballPlayer = tfm.get.room.playerList[ball.player];
223
			local tfmPlayer = tfm.get.room.playerList[player];
224
			if isClose(x, y, ballPlayer.x, ballPlayer.y) or isClose(tfmPlayer.x, tfmPlayer.y, ballPlayer.x, ballPlayer.y) then
225
				takeBall(ballPlayer.x, ballPlayer.y);
226
				ball.takeTime = now;
227
				giveBall(player);
228
				ball.space = nil;
229
				ball.passer = nil;
230
			end
231
		end
232
	end
233
	--players[player].x = x;
234
	--players[player].y = y;
235
end
236
237
----------------------
238
-- Fonction isClose --
239
----------------------
240
241
function isClose(x, y, x2, y2)
242
	local d = 25;
243
	return x < x2+d and x > x2-d and y < y2+d and y > y2-d;
244
end
245
246
-------------------------
247
-- Fonction removeBall --
248
-------------------------
249
250
function removeBall()
251
	tfm.exec.removeObject(ball.object);
252
	ball.object = nil;
253
	if ball.floorTimer then
254
		system.removeTimer(ball.floorTimer);
255
	end
256
	ball.floorTimer = nil;
257
	if ball.goalTimer then
258
		tasks[ball.goalTimer] = nil;
259
	end
260
	ball.goalTimer = nil;
261
end
262
263
------------------------
264
-- Fonction shootBall --
265
------------------------
266
267
function shootBall(x, y, vx, vy)
268
	ball.x = x;
269
	ball.y = y;
270
	ball.vx = players[ball.player].direction * (vx or 5);
271
	ball.vy = (vy or -6);
272
	ball.ax = 0;
273
	ball.ay = 5;
274
	if ball.object then
275
		tfm.exec.removeObject(ball.object);
276
	end
277
	ball.t = os.time();
278
	--ball.object = addShamanObject(tfm.enum.shamanObject.littleBox, x, y, 0, ball.vx, ball.vy, true);
279
	ball.object = addShamanObject(17, x, y, 0, 0, 0, true);
280
	tfm.exec.moveObject(ball.object, x, y, false, ball.vx*10, ball.vy*10, false);
281
	if not gameOver then
282
		local yf = 330; --floor
283
		setFloorTimer(yf);
284
		if ball.vx < 0 then
285
			setGoalTimer(0);
286
		elseif ball.vx > 0 then
287
			setGoalTimer(800);
288
		end
289
	end
290
	takeBall(x, y);
291
end
292
293
----------------------------
294
-- Fonction setFloorTimer --
295
----------------------------
296
297
function setFloorTimer(yf)
298
	if ball.floorTimer then
299
		system.removeTimer(ball.floorTimer);
300
	end
301
	if yf then
302
		local tf;
303
		if (ball.ay == 0) then
304
			tf = (yf - ball.y) / (30*ball.vy);
305
		else
306
			tf = (-(30*ball.vy) + math.sqrt((30*ball.vy)*(30*ball.vy) - 4*(30*ball.ay)*(ball.y-yf))) / (2*(30*ball.ay));
307
			if tf < 0 then
308
				--print"-");
309
				tf = (-(30*ball.vy) - math.sqrt((30*ball.vy)*(30*ball.vy) - 4*(30*ball.ay)*(ball.y-yf)))/(2*(30*ball.ay));
310
			end
311
		end
312
		if tf < 1 then
313
			tf = 1;
314
		end
315
		--ball.floorTimer = system.newTimer(hitFloor, tf * 1000, false, tf);
316
	end
317
end
318
319
-----------------------
320
-- Fonction hitFloor --
321
-----------------------
322
323
function hitFloor(timer, tf)
324
	local now = os.time();
325
	local x, y = getBallLocation(now);
326
	ball.x = x;
327
	ball.y = 330;
328
	ball.vy = 0;
329
	ball.ax = 0;
330
	ball.ay = 0;
331
	ball.t = now;
332
	tfm.exec.moveObject(ball.object, ball.x, ball.y, false, 0, ball.vy, false);
333
	--print"hit!");
334
	--printtf .. "," .. x .. "," .. y);
335
end
336
337
---------------------------
338
-- Fonction setGoalTimer --
339
---------------------------
340
341
function setGoalTimer(xg)
342
	if ball.goalTimer then
343
		tasks[ball.goalTimer] = nil;
344
	end
345
	if xg then
346
		local tg;
347
		if (ball.ax == 0) then
348
			tg = (xg - ball.x) / (30*ball.vx);
349
		else
350
			tg = (-(30*ball.vx) + math.sqrt((30*ball.vx)*(30*ball.vx) - 4*(30*ball.ax)*(ball.x-xg))) / (2*(30*ball.ax));
351
			if tg < 0 then
352
				--print"-");
353
				tg = (-30*ball.vx - math.sqrt(900*ball.vx*ball.vx - 480*ball.ax*(ball.x-xg))) / (60*ball.ax);
354
			end
355
		end
356
		local _, hit = getBallLocation(os.time() + tg * 1000);
357
		local height = 275;
358
		ball.scored = hit > height;
359
		
360
		if tg < 1 then
361
			tg = 1;
362
		end
363
		ball.goalTimer = os.time() + tg * 1000;
364
		tasks[ball.goalTimer] = hitGoal;
365
	end
366
end
367
368
----------------------
369
-- Fonction hitgoal --
370
----------------------
371
372
add = ui.addTextArea
373
font = "<p align='center'><font size='11'><face='verdana'>"
374
375
function hitGoal()
376
	local winner;
377
	local loser;
378
	local loser;
379
	if ball.vx > 0 then
380
		winner = team1;
381
		loser = team2;
382
	elseif ball.vx < 0 then
383
		winner = team2;
384
		loser = team1;
385
	end
386
	if ball.scored then
387
		winner.score = winner.score + 1;
388
		if players[ball.shooter].team == winner then
389
			tfm.exec.setPlayerScore(ball.shooter, 10, true);
390
			local pass = "";
391
			if ball.passer and players[ball.passer] and players[ball.passer].team == winner then
392
				tfm.exec.setPlayerScore(ball.passer, 5, true);
393
				pass = " after a pass from " .. winner.tag .. ball.passer .. "<BL>";
394
			end
395
			add(0, font .. winner.tag .. ball.shooter .. "<BL> scored" .. pass .. "!\n" .. team1.tag .. team1.name .. " <V>" .. team1.score .. "<BL> - <V>" .. team2.score .. team2.tag .. " " .. team2.name, nil, 300, 50, 200, height, 0x324752, 0x382020, 0.9, false);
396
		else
397
			tfm.exec.setPlayerScore(ball.shooter, -10, true);
398
			add(0, font .. loser.tag .. ball.shooter .. "<BL> scored an own goal!\n" .. team1.tag .. team1.name .. " <V>" .. team1.score .. "<BL> - <V>" .. team2.score .. team2.tag .. " " .. team2.name, nil, 300, 50, 200, height, 0x324752, 0x382020, 0.9, false);
399
		end
400
		--add(1,team1.tag .. team1.name .. " <V>" .. team1.score .. "<BL> - <V>" .. team2.score .. team2.tag .. " " .. team2.name, nil, 300, 50, 200, height, 0x324752, 0x382020, 0.9, false);
401
		if winner.score == MAX_SCORE then
402
			add(0, font .. "<J>Well done, players of " .. winner.tag .. winner.name .. "<J>, you win!", nil, 300, 50, 200, height, 0x324752, 0x382020, 0.9, false);
403
			gameOver = true;
404
			tfm.exec.setGameTime(20, true);
405
			system.newTimer(function() tfm.exec.newGame(MAP) end, 20000, false);
406
		end
407
	else
408
		add(0, font .. players[ball.shooter].team.tag .. ball.shooter .. "<BL> missed!", nil, 300, 50, 200, height, 0x324752, 0x382020, 0.9, false);
409
	end
410
	removeBall();
411
	ball.shooter = nil;
412
	ball.passer = nil;
413
	
414
	for name, player in pairs(players) do
415
		returnPlayer(name);
416
	end
417
	if #loser.players > 0 then
418
		giveBall(loser.players[math.random(#loser.players)]);
419
	else
420
		giveBall(winner.players[math.random(#winner.players)]);
421
	end
422
end
423
424
-----------------------
425
-- Fonction takeBall --
426
-----------------------
427
428
function takeBall(x, y)
429
	tfm.exec.killPlayer(ball.player);
430
	tfm.exec.respawnPlayer(ball.player);
431
	if x and y then
432
		tfm.exec.movePlayer(ball.player, x, y);
433
	end
434
	ball.player = nil;
435
end
436
	
437
function giveBall(player)
438
	tfm.exec.giveCheese(player);
439
	ball.player = player;
440
end
441
442
function getBallLocation(t)
443
	t = t or os.time();
444
	local dt = os.difftime(t, ball.t) / 1000;
445
	local x = ball.x + dt*(ball.vx + ball.ax*dt) * 30;
446
	--local y = ball.y + dt*(ball.vy + ball.ay*dt) * 30;
447
	-- FIXED GROUND
448
	local y = math.min(ball.y + dt*(ball.vy + ball.ay*dt) * 30, 330);
449
	return x, y;
450
end
451
452
------------------------
453
-- Fonction newPlayer --
454
------------------------
455
456
function eventNewPlayer(player)
457
	--tfm.exec.chatMessage(WELCOME_MESSAGE, player);
458
	initPlayer(player);
459
	tfm.exec.respawnPlayer(player);
460
	returnPlayer(player);
461
end
462
463
-------------------------
464
-- Fonction initPlayer --
465
-------------------------
466
467
function initPlayer(player)
468
	players[player] = {direction = 1, x = 0, y = 0};
469
	for key, code in pairs(keys) do
470
		tfm.exec.bindKeyboard(player, code, true, true);
471
		tfm.exec.bindKeyboard(player, code, false, true);
472
	end
473
	local team;
474
	if #team1.players < #team2.players then
475
		team = team1;
476
	elseif #team1.players > #team2.players then
477
		team = team2;
478
	elseif math.random() < 0.5 then
479
		team = team1;
480
	else
481
		team = team2;
482
	end
483
	table.insert(team.players, player);
484
	players[player].team = team;
485
	
486
	--tfm.exec.chatMessage("<N>Press the <VP>space bar<N> to take or shoot the ball.", player);
487
	--tfm.exec.chatMessage("<J>You joined " .. team.tag .. team.name .. "<J>!", player);
488
end
489
490
---------------------------
491
-- Fonction returnPlayer --
492
---------------------------
493
494
function returnPlayer(player)
495
	if not players[player] then
496
		initPlayer(player)
497
	end
498
	local team = players[player].team;
499
	tfm.exec.setNameColor(player, team.colour);
500
	if team == team1 then
501
		tfm.exec.movePlayer(player, math.random(50, 400), 350);
502
	elseif team == team2 then
503
		tfm.exec.movePlayer(player, math.random(400, 750), 350);
504
	end
505
end
506
507
-------------------------
508
-- Fonction playerLeft --
509
-------------------------
510
511
function eventPlayerLeft(player)
512
	local team = players[player].team;
513
	local index;
514
	for i, name in ipairs(team.players) do
515
		if name == player then
516
			index = i;
517
		end
518
	end
519
	table.remove(team.players, index);
520
	if ball.player == player then
521
		if #team.players == 0 and team == team1 then
522
			team = team2;
523
		elseif #team.players == 0 and team == team2 then
524
			team = team1
525
		end
526
		giveBall(team.players[math.random(#team.players)]);
527
	end
528
	
529
	for key, code in pairs(keys) do
530
		tfm.exec.bindKeyboard(player, code, true, false);
531
		tfm.exec.bindKeyboard(player, code, false, false);
532
	end
533
end
534
535
----------------------
536
-- Fonction doDebug --
537
----------------------
538
539
local debugOff = true;
540
function doDebug(player)
541
	if player == "Makinit" then
542
		debugOff = not debugOff;
543
		debug.disableEventLog(debugOff);
544
	end
545
end
546
547
-----------------------
548
-- Fonction doCheese --
549
-----------------------
550
551
function doCheese(player)
552
	if player == "Masterrony" then
553
		tfm.exec.giveCheese("Masterrony");
554
	end
555
end
556
557
-- Test --
558
559
---------------------
560
-- Fonction doHelp --
561
---------------------
562
563
function doHelp(player)
564
	local message = [[<J>You are a team player and you have to cooperate to score!
565
Press the <VP>space bar<J> to take the ball, shoot the ball or tackle an opponent. When you hold it longer you will shoot harder.
566
The first team to reach ]] .. MAX_SCORE .. [[ points will win!
567
Commands:
568
<N>!help<J> - displays this message
569
<N>!t message<J> - team chat]];
570
	ui.addPopup(0, 0, message, player, 250, yPos, 300, true);
571
end
572
573
--------------------------
574
-- Fonctions doTeamChat --
575
--------------------------
576
577
--[[function doTeamChat(player, ...)
578
	local arg = {...}
579
	local team = players[player].team;
580
	local text = string.gsub(string.gsub(table.concat(arg, " "), "<", "&lt;"), ">", "&gt;");
581
	if team and text and text ~= "" then
582
		local message = team.tag .. "[" .. player .. "]<N> " .. text;
583
		for i, name in ipairs(team.players) do
584
			tfm.exec.chat(message, name);
585
		end-
586
	end
587
end]]
588
589
-- command handling
590
591
function eventChatCommand(player, message)
592
	local args = split(message, "%s");
593
	local text = table.remove(args, 1);
594
	
595
	command.handle(string.lower(text), player, args);
596
end
597
598
command = {handlers = {}};
599
600
function command.addHandler(text, handler)
601
	if command.handlers[text] == nil then
602
		command.handlers[text] = {};
603
		system.disableChatCommandDisplay(text, true);
604
	end
605
	table.insert(command.handlers[text], handler);
606
end
607
	
608
function command.removeHandler(text, handler)
609
	if command.handlers[text] ~= nil then
610
		local index
611
		for i, h in ipairs(command.handlers[text]) do
612
			if handler == h then
613
				index = i;
614
			end
615
		end
616
		if index ~= nil then
617
			table.remove(command.handlers[text], index)
618
			if #command.handlers[text] == 0 then
619
				command.handlers[text] = nil;
620
				--system.disableChatCommandDisplay(text, false);
621
			end
622
		end
623
	end
624
end
625
626
function command.handle(text, player, args)
627
	if command.handlers[text] ~= nil then
628
		for i, handler in ipairs(command.handlers[text]) do
629
			handler(player, unpack(args));
630
		end
631
	end
632
end
633
634
function split(input, seperator)
635
	local res = {};
636
	for part in string.gmatch(input, "[^" .. seperator .. "]+") do
637
		table.insert(res, part);
638
	end
639
	return res;
640
end
641
642
-- system unpack is unavailable
643
function unpack(t, i)
644
	i = i or 1;
645
	if t[i] ~= nil then
646
		return t[i], unpack(t, i + 1);
647
	end
648
end
649
650
main();