1 /*
2 	network_games.c
3 
4 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 	and the "Aleph One" developers.
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 3 of the License, or
10 	(at your option) any later version.
11 
12 	This program is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU General Public License for more details.
16 
17 	This license is contained in the file "COPYING",
18 	which is included with this source code; it is available online at
19 	http://www.gnu.org/licenses/gpl.html
20 
21 	Wednesday, July 19, 1995 10:16:51 AM- rdm created.
22 
23 Jul 1, 2000 (Loren Petrich):
24 	Added Benad's changes
25 */
26 
27 #if !defined(DISABLE_NETWORKING)
28 
29 #include "cseries.h"
30 #include "map.h"
31 #include "items.h"
32 #include "lua_script.h"
33 #include "player.h"
34 #include "monsters.h"
35 #include "network.h"
36 #include "network_games.h"
37 #include "game_window.h" // for mark_player_network_stats_as_dirty
38 #include "SoundManager.h"
39 
40 int32 team_netgame_parameters[NUMBER_OF_TEAM_COLORS][2];
41 
42 // Benad
43 void destroy_players_ball(
44 	short player_index);
45 
46 #include <stdio.h>
47 #include <limits.h>
48 
49 /* ----------- #defines */
50 #define SINGLE_BALL_COLOR (1)
51 
52 /* ----------- enums */
53 
54 /* Net game parameters */
55 enum { // for king of the hill
56 	_king_of_hill_time= 0
57 };
58 
59 enum { // for kill the man with the ball
60 	_ball_carrier_time= 0
61 };
62 
63 enum { // for offense/defense
64 	_offender_time_in_base= 0, // for player->netgame_parameters
65 	_defending_team= 0, // for game_information->paramters
66 	_maximum_offender_time_in_base= 1 // for game_information->parameters
67 };
68 
69 enum { // for rugby
70 	_points_scored= 0
71 };
72 
73 enum { // for tag
74 	_time_spent_it= 0
75 };
76 
77 enum { // for capture the flag.
78 	_flag_pulls= 0, // for player->netgame_parameters
79 	_winning_team= 0 // for game_information->parameters[]
80 };
81 
82 
83 /* ----------------- private prototypes */
84 static bool player_has_ball(short player_index, short color);
85 extern void destroy_players_ball(short player_index);
86 
87 // for script controlled compass
88 extern bool use_lua_compass[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
89 extern world_point2d lua_compass_beacons[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
90 extern short lua_compass_states[MAXIMUM_NUMBER_OF_NETWORK_PLAYERS];
91 
92 /* ------------------ code */
get_player_net_ranking(short player_index,short * kills,short * deaths,bool game_is_over)93 long get_player_net_ranking(
94 	short player_index,
95 	short *kills,
96 	short *deaths,
97 	bool game_is_over)
98 {
99 	short index;
100 	long total_monster_damage, monster_damage;
101 	struct player_data *player= get_player_data(player_index);
102 	long ranking = 0;
103 
104 	*kills= 0;
105 	*deaths = player->monster_damage_taken.kills;
106 	monster_damage= player->monster_damage_given.damage;
107 
108 	total_monster_damage= monster_damage;
109 	for (index= 0; index<dynamic_world->player_count; ++index)
110 	{
111 		if (index!=player_index)
112 		{
113 			struct player_data *other_player= get_player_data(index);
114 
115 			(*kills)+= other_player->damage_taken[player_index].kills;
116 			total_monster_damage+= other_player->monster_damage_given.damage;
117 		}
118 
119 		(*deaths)+= player->damage_taken[index].kills;
120 	}
121 
122 	switch(GET_GAME_TYPE())
123 	{
124 		case _game_of_kill_monsters:
125 			ranking= (*kills)-(*deaths);
126 			break;
127 
128 		case _game_of_cooperative_play:
129 			ranking= total_monster_damage ? (100*monster_damage)/total_monster_damage : 0;
130 			break;
131 
132 	case _game_of_custom:
133 		switch(GetLuaScoringMode()) {
134 	  case _game_of_most_points:
135 	  case _game_of_most_time:
136 	    ranking = player->netgame_parameters[_points_scored];
137 	    break;
138 	  case _game_of_least_points:
139 	  case _game_of_least_time:
140 	    ranking = -player->netgame_parameters[_points_scored];
141 	    break;
142 	  }
143 	  break;
144 
145 		case _game_of_capture_the_flag:
146 			ranking= player->netgame_parameters[_flag_pulls];
147 			break;
148 
149 		case _game_of_king_of_the_hill:
150 			ranking= player->netgame_parameters[_king_of_hill_time];
151 			break;
152 
153 		case _game_of_kill_man_with_ball:
154 			ranking= player->netgame_parameters[_ball_carrier_time];
155 			break;
156 
157 		case _game_of_tag:
158 			ranking= -player->netgame_parameters[_time_spent_it];
159 			break;
160 
161 		// START Benad
162 		case _game_of_defense: {
163 			//ranking= (*kills)-(*deaths);
164 
165 			/* Bogus for now.. */
166 			/*if(game_is_over && GET_GAME_PARAMETER(_winning_team)==player->team)
167 			{
168 				ranking += 50;
169 			}
170 			break;*/
171 
172 			//short defending_team= GET_GAME_PARAMETER(_defending_team);
173 			short defending_team= 0;
174 			if(player->team != defending_team)
175 			{
176 				ranking= player->netgame_parameters[_offender_time_in_base];
177 			}
178 			else
179 			{
180 				long biggest = 0;
181 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
182 				{
183 					struct player_data *index_player= get_player_data(player_index);
184 					if ((index_player->team != defending_team) &&
185 						(index_player->netgame_parameters[_offender_time_in_base] > biggest))
186 					{
187 						biggest = index_player->netgame_parameters[_offender_time_in_base];
188 					}
189 				}
190 				ranking= (dynamic_world->game_information.kill_limit * TICKS_PER_SECOND) - biggest; // in ticks
191 			}
192 			break;
193 		// END Benad
194 		}
195 		case _game_of_rugby:
196 			// Benad
197 			ranking= player->netgame_parameters[_points_scored];
198 			break;
199 
200 		default:
201 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
202 			break;
203 	}
204 
205 	return ranking;
206 }
207 
get_team_net_ranking(short team,short * kills,short * deaths,bool game_is_over)208 long get_team_net_ranking(short team, short *kills, short *deaths,
209 			  bool game_is_over)
210 {
211   long total_monster_damage, monster_damage;
212   long ranking = NONE;
213   *kills = team_damage_given[team].kills;
214   *deaths = team_damage_taken[team].kills + team_monster_damage_taken[team].kills;
215 
216   total_monster_damage = 0;
217   for (int i = 0; i < NUMBER_OF_TEAM_COLORS; i++) {
218     total_monster_damage += team_monster_damage_given[i].damage;
219   }
220   monster_damage = team_monster_damage_given[team].damage;
221 
222   switch(GET_GAME_TYPE())
223     {
224     case _game_of_kill_monsters:
225       ranking = (*kills)-(*deaths);
226       break;
227     case _game_of_custom:
228 	    switch(GetLuaScoringMode()) {
229       case _game_of_most_points:
230       case _game_of_most_time:
231 	ranking = team_netgame_parameters[team][_points_scored];
232 	break;
233       case _game_of_least_points:
234       case _game_of_least_time:
235 	ranking = -team_netgame_parameters[team][_points_scored];
236 	break;
237       }
238       break;
239     case _game_of_cooperative_play:
240       ranking = total_monster_damage ? (100*monster_damage)/total_monster_damage : 0;
241       break;
242     case _game_of_capture_the_flag:
243       ranking = team_netgame_parameters[team][_flag_pulls];
244       break;
245     case _game_of_king_of_the_hill:
246       ranking = team_netgame_parameters[team][_king_of_hill_time];
247       break;
248     case _game_of_kill_man_with_ball:
249       ranking = team_netgame_parameters[team][_ball_carrier_time];
250       break;
251     case _game_of_tag:
252       ranking = -team_netgame_parameters[team][_time_spent_it];
253       break;
254     case _game_of_defense:
255       {
256       short defending_team = 0;
257       if (team != defending_team) {
258 	ranking = team_netgame_parameters[team][_offender_time_in_base];
259       } else {
260 	long biggest = 0;
261 	for (int i = 0; i < NUMBER_OF_TEAM_COLORS; i++) {
262 	  if ((i != defending_team) && (team_netgame_parameters[i][_offender_time_in_base] > biggest)) {
263 	    biggest = team_netgame_parameters[i][_offender_time_in_base];
264 	  }
265 	}
266 	ranking = (dynamic_world->game_information.kill_limit * TICKS_PER_SECOND) - biggest;
267       }
268       break;
269       }
270     case _game_of_rugby:
271       ranking = team_netgame_parameters[team][_points_scored];
272       break;
273     default:
274       vhalt(csprintf(temporary, "What is game type %d", GET_GAME_TYPE()));
275       break;
276     }
277 
278   return ranking;
279 }
280 
281 
282 
283 
284 
initialize_net_game(void)285 void initialize_net_game(
286 	void)
287 {
288   for (int i = 0; i < NUMBER_OF_TEAM_COLORS; i++) {
289     team_netgame_parameters[i][0] = 0;
290     team_netgame_parameters[i][1] = 0;
291   }
292 	switch (GET_GAME_TYPE())
293 	{
294 		case _game_of_king_of_the_hill:
295 		// Benad
296 		case _game_of_defense:
297 			// calculate the center of the hill
298 			{
299 				int32 x = 0, y = 0;
300 				int16 count = 0;
301 				struct polygon_data *polygon;
302 				short polygon_index;
303 
304 				for (polygon_index= 0, polygon= map_polygons; polygon_index<dynamic_world->polygon_count; ++polygon_index, ++polygon)
305 				{
306 					if (polygon->type==_polygon_is_hill)
307 					{
308 						count+= 1;
309 						x+= polygon->center.x, y+= polygon->center.y;
310 					}
311 				}
312 
313 				if (count > 0) {
314 				  dynamic_world->game_beacon.x= static_cast<world_distance>(x/count);
315 				  dynamic_world->game_beacon.y= static_cast<world_distance>(y/count);
316 				} else {
317 				  // KOTH map with no hill, nice
318 				  dynamic_world->game_beacon.x = 0;
319 				  dynamic_world->game_beacon.y = 0;
320 				}
321 			}
322 			break;
323 		// START Benad
324 		case _game_of_rugby:
325 			dynamic_world->game_player_index= NONE;
326 			break;
327 		// END Benad
328 		case _game_of_kill_man_with_ball:
329 			dynamic_world->game_player_index= NONE;
330 //			play_local_sound(_snd_got_ball);
331 			break;
332 
333 		case _game_of_tag:
334 			dynamic_world->game_player_index= NONE; // nobody is it, yet
335 			break;
336 	}
337 }
338 
339 #define NETWORK_COMPASS_SLOP SIXTEENTH_CIRCLE
340 
get_network_compass_state(short player_index)341 short get_network_compass_state(
342 	short player_index)
343 {
344 	short state= _network_compass_all_off;
345 	world_point2d *beacon= (world_point2d *) NULL;
346 
347         if (use_lua_compass [player_index])
348         {
349                 if (lua_compass_states [player_index] & _network_compass_use_beacon)
350                     beacon = lua_compass_beacons + player_index;
351                 else
352                     state = lua_compass_states [player_index];
353         }
354 	else
355 	{
356                 switch (GET_GAME_TYPE())
357                 {
358                         case _game_of_king_of_the_hill: // where�s the hill
359                         // Benad
360                         case _game_of_defense:
361                                 if (get_polygon_data(get_player_data(player_index)->supporting_polygon_index)->type==_polygon_is_hill)
362                                 {
363                                         state= _network_compass_all_on;
364                                 }
365                                 else
366                                 {
367                                         beacon= &dynamic_world->game_beacon;
368                                 }
369                                 break;
370 
371                         case _game_of_tag: // where�s it
372                                 if (dynamic_world->game_player_index==player_index)
373                                 {
374                                         state= _network_compass_all_on;
375                                 }
376                                 else
377                                 {
378                                         if (dynamic_world->game_player_index!=NONE)
379                                         {
380                                                 beacon= (world_point2d *) &get_player_data(dynamic_world->game_player_index)->location;
381                                         }
382                                 }
383                                 break;
384                         // START Benad
385                         case _game_of_rugby:
386                                 if (player_has_ball(player_index, SINGLE_BALL_COLOR))
387                                 {
388                                         state= _network_compass_all_on;
389                                 }
390                                 else
391                                 {
392                                         if (dynamic_world->game_player_index!=NONE)
393                                         {
394                                                 beacon= (world_point2d *) &get_player_data(dynamic_world->game_player_index)->location;
395                                         }
396                                 }
397                                 break;
398                         //END Benad
399                         case _game_of_kill_man_with_ball: // where�s the ball
400                                 if (player_has_ball(player_index, SINGLE_BALL_COLOR))
401                                 {
402                                         state= _network_compass_all_on;
403                                 }
404                                 else
405                                 {
406                                         if (dynamic_world->game_player_index!=NONE)
407                                         {
408                                                 beacon= (world_point2d *) &get_player_data(dynamic_world->game_player_index)->location;
409                                         }
410                                 }
411                                 break;
412                 }
413         }
414 
415 	if (beacon)
416 	{
417 		struct player_data *player= get_player_data(player_index);
418 		struct world_point2d *origin= (world_point2d *) &player->location;
419 		angle theta= NORMALIZE_ANGLE(get_object_data(player->object_index)->facing-arctangent(origin->x-beacon->x, origin->y-beacon->y));
420 
421 		if (theta>FULL_CIRCLE-NETWORK_COMPASS_SLOP || theta<QUARTER_CIRCLE+NETWORK_COMPASS_SLOP) state|= _network_compass_se;
422 		if (theta>QUARTER_CIRCLE-NETWORK_COMPASS_SLOP && theta<HALF_CIRCLE+NETWORK_COMPASS_SLOP) state|= _network_compass_ne;
423 		if (theta>HALF_CIRCLE-NETWORK_COMPASS_SLOP && theta<HALF_CIRCLE+QUARTER_CIRCLE+NETWORK_COMPASS_SLOP) state|= _network_compass_nw;
424 		if (theta>HALF_CIRCLE+QUARTER_CIRCLE-NETWORK_COMPASS_SLOP || theta<NETWORK_COMPASS_SLOP) state|= _network_compass_sw;
425 	}
426 
427 	return state;
428 }
429 
430 // if false is returned, don�t attribute kill
player_killed_player(short dead_player_index,short aggressor_player_index)431 bool player_killed_player(
432 	short dead_player_index,
433 	short aggressor_player_index)
434 {
435 	bool attribute_kill= true;
436 
437 	if (dynamic_world->player_count>1)
438 	{
439 		switch (GET_GAME_TYPE())
440 		{
441 			case _game_of_tag:
442 				if (aggressor_player_index==dynamic_world->game_player_index || // killed by it
443 					dead_player_index==aggressor_player_index || // killed themselves
444 					dynamic_world->game_player_index==NONE) // died without an it
445 				{
446 					if (dynamic_world->game_player_index!=dead_player_index)
447 					{
448 						// change of �it�
449 						player_data* player = get_player_data(dead_player_index);
450 						play_object_sound(player->object_index, _snd_you_are_it);
451 						dynamic_world->game_player_index= dead_player_index;
452 					}
453 				}
454 				break;
455 		}
456 
457 		if (attribute_kill)
458 		{
459 			switch (GET_GAME_TYPE())
460 			{
461 				case _game_of_kill_monsters:
462 					mark_player_network_stats_as_dirty(current_player_index);
463 					break;
464 			}
465 		}
466 	}
467 
468 	return attribute_kill;
469 }
470 
update_net_game(void)471 bool update_net_game(
472 	void)
473 {
474 	bool net_game_over= false;
475 	short player_index;
476 
477 	if (dynamic_world->player_count>1)
478 	{
479 		switch(GET_GAME_TYPE())
480 		{
481 			case _game_of_kill_monsters:
482 			case _game_of_cooperative_play:
483 		case _game_of_custom:
484 				/* These games have no housekeeping associated with them. */
485 				break;
486 
487 			case _game_of_capture_the_flag:
488 			// START Benad
489 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
490 				{
491 					struct player_data *player= get_player_data(player_index);
492 					struct polygon_data *polygon= get_polygon_data(player->supporting_polygon_index);
493 
494 					if ( (polygon->type==_polygon_is_base && polygon->permutation==player->team) ||
495 						((dynamic_world->game_information.kill_limit == 819) && (polygon->type==_polygon_is_hill)) )
496 					{
497 						short ball_color= find_player_ball_color(player_index);
498 
499 						if ((ball_color != NONE && ball_color != player->team) ||
500 							(ball_color != NONE && dynamic_world->game_information.kill_limit == 819))
501 						{
502 							player->netgame_parameters[_flag_pulls]++;
503 							team_netgame_parameters[player->team][_flag_pulls]++;
504 							destroy_players_ball(player_index);
505 						}
506 					}
507 				}
508 				break;
509 			// END Benad
510 
511 			case _game_of_king_of_the_hill:
512 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
513 				{
514 					struct player_data *player= get_player_data(player_index);
515 
516 					if(!PLAYER_IS_DEAD(player))
517 					{
518 						struct polygon_data *polygon= get_polygon_data(player->supporting_polygon_index);
519 
520 						if(polygon->type==_polygon_is_hill)
521 						{
522 							player->netgame_parameters[_king_of_hill_time]++;
523 							team_netgame_parameters[player->team][_king_of_hill_time]++;
524 						}
525 					}
526 				}
527 				break;
528 
529 			case _game_of_kill_man_with_ball:
530 				dynamic_world->game_player_index= NONE;
531 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
532 				{
533 					if (player_has_ball(player_index, SINGLE_BALL_COLOR))
534 					{
535 						struct player_data *player= get_player_data(player_index);
536 
537 						player->netgame_parameters[_ball_carrier_time]++;
538 						team_netgame_parameters[player->team][_ball_carrier_time]++;
539 						dynamic_world->game_player_index= player_index;
540 
541 						break;
542 					}
543 				}
544 				break;
545 
546 			case _game_of_tag:
547 				if (dynamic_world->game_player_index!=NONE)
548 				{
549 					struct player_data *player= get_player_data(dynamic_world->game_player_index);
550 
551 					if (!PLAYER_IS_DEAD(player) || PLAYER_IS_TOTALLY_DEAD(player))
552 					{
553 						player->netgame_parameters[_time_spent_it]+= 1;
554 						team_netgame_parameters[player->team][_time_spent_it]+= 1;
555 					}
556 				}
557 				break;
558 
559 			// START Benad
560 			case _game_of_defense:
561 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
562 				{
563 					struct player_data *player= get_player_data(player_index);
564 					//short defending_team= GET_GAME_PARAMETER(_defending_team);
565 					short defending_team= 0;
566 
567 					if((player->team != defending_team) && (!PLAYER_IS_DEAD(player)))
568 					{
569 						struct polygon_data *polygon= get_polygon_data(player->supporting_polygon_index);
570 
571 						/* They are in our base! */
572 						if(polygon->type==_polygon_is_hill/* && polygon->permutation==defending_team*/)
573 						{
574 							player->netgame_parameters[_offender_time_in_base]++;
575 							team_netgame_parameters[player->team][_offender_time_in_base]++;
576 							/*if(player->netgame_parameters[_offender_time_in_base]>GET_GAME_PARAMETER(_maximum_offender_time_in_base))
577 							{
578 								dprintf("Game is over. Offender won.");
579 								//��
580 								dynamic_world->game_information.parameters[_winning_team]= player->team;
581 								net_game_over= true;
582 							}*/
583 						}
584 						break;
585 					}
586 				}
587 				break;
588 
589 			case _game_of_rugby:
590 				dynamic_world->game_player_index= NONE;
591 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
592 				{
593 					struct player_data *player= get_player_data(player_index);
594 					struct polygon_data *polygon= get_polygon_data(player->supporting_polygon_index);
595 
596 					if (player_has_ball(player_index, SINGLE_BALL_COLOR))
597 					{
598 						// START Benad changed oct. 1st
599 						dynamic_world->game_player_index= player_index;
600 						//if(polygon->type==_polygon_is_base && polygon->permutation != player->team)
601 						if( ( (dynamic_world->game_information.kill_limit == 819) && (polygon->type==_polygon_is_hill)
602 							&& (!PLAYER_IS_DEAD(player)) ) ||
603 							( polygon->type==_polygon_is_base && polygon->permutation != player->team && (!PLAYER_IS_DEAD(player)) ) )
604 						{
605 							/* Goal! */
606 							player->netgame_parameters[_points_scored]++;
607 							team_netgame_parameters[player->team][_points_scored]++;
608 
609 							/* Ditch the ball.. (it will be recreated by the timer..) */
610 							destroy_players_ball(player_index);
611 							dynamic_world->game_player_index= NONE;
612 							break; // Break out of loop; assuming there's only one ball.
613 						}
614 						// Can't take the ball back to you own goal, otherwise weird bugs could happen
615 						// if an opponent touches the ball in your goal. Like real Rugby.
616 						else if ( polygon->type==_polygon_is_base && polygon->permutation == player->team && (!PLAYER_IS_DEAD(player)))
617 						{
618 							/* Ditch the ball.. (it will be recreated by the timer..) */
619 							destroy_players_ball(player_index);
620 							dynamic_world->game_player_index= NONE;
621 							break; // Break out of loop; assuming there's only one ball.
622 						}
623 						// END Benad changed oct. 1st
624 					}
625 				}
626 				break;
627 			// END Benad
628 			default:
629 				vhalt(csprintf(temporary, "What is game type: %d?", GET_GAME_TYPE()));
630 				break;
631 		}
632 
633 		if (--current_player->interface_decay<0 && GET_GAME_TYPE()!=_game_of_kill_monsters)
634 		{
635 			mark_player_network_stats_as_dirty(current_player_index);
636 		}
637 	}
638 	// Benad: Warning! This is actually ignored! Instead, change game_is_over().
639 	return net_game_over;
640 }
641 
calculate_player_rankings(struct player_ranking_data * rankings)642 void calculate_player_rankings(
643 	struct player_ranking_data *rankings)
644 {
645 	struct player_ranking_data temporary_copy[MAXIMUM_NUMBER_OF_PLAYERS];
646 	short player_index, count;
647 
648 	/* First get the stats. */
649 	for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
650 	{
651 		short kills, deaths;
652 
653 		temporary_copy[player_index].player_index= player_index;
654 		temporary_copy[player_index].ranking= get_player_net_ranking(player_index, &kills, &deaths,
655 			false);
656 	}
657 
658 	/* Now sort them.. */
659 	count= 0;
660 	while(count!=dynamic_world->player_count)
661 	{
662 		long highest_ranking= LONG_MIN;
663 		short highest_index= NONE;
664 
665 		for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
666 		{
667 			if(temporary_copy[player_index].ranking>highest_ranking)
668 			{
669 				highest_index= player_index;
670 				highest_ranking= temporary_copy[player_index].ranking;
671 			}
672 		}
673 
674 		assert(highest_index != NONE);
675 		rankings[count++]= temporary_copy[highest_index];
676 		temporary_copy[highest_index].ranking= LONG_MIN;
677 	}
678 }
679 
680 /* These aren't in resources for speed.... */
calculate_ranking_text(char * buffer,long ranking)681 void calculate_ranking_text(
682 	char *buffer,
683 	long ranking)
684 {
685 	long seconds;
686 
687 	switch(GET_GAME_TYPE())
688 	{
689 		case _game_of_kill_monsters:
690 		case _game_of_capture_the_flag:
691 		case _game_of_rugby:
692 			sprintf(buffer, "%ld", ranking);
693 			break;
694 
695 	case _game_of_custom:
696 		switch(GetLuaScoringMode()) {
697 	  case _game_of_most_points:
698 	    sprintf(buffer, "%ld", ranking);
699 	    break;
700 	  case _game_of_least_points:
701 	    sprintf(buffer, "%ld", -ranking);
702 	    break;
703 	  case _game_of_most_time:
704 	  case _game_of_least_time:
705 	    seconds= ABS(ranking)/TICKS_PER_SECOND;
706 	    sprintf(buffer, "%ld:%02ld", seconds/60, seconds%60);
707 	    break;
708 	  }
709 	  break;
710 
711 		case _game_of_cooperative_play:
712 			sprintf(buffer, "%ld%%", ranking);
713 			break;
714 		// START Benad
715 		case _game_of_king_of_the_hill:
716 		case _game_of_kill_man_with_ball:
717 		case _game_of_tag:
718 		case _game_of_defense:
719 			seconds= ABS(ranking)/TICKS_PER_SECOND;
720 			sprintf(buffer, "%ld:%02ld", seconds/60, seconds%60);
721 			break;
722 		// END Benad
723 		default:
724 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
725 			break;
726 	}
727 }
728 
729 enum {
730 	strNETWORK_GAME_STRINGS= 140,
731 	flagPullsFormatString= 0,
732 	minutesPossessedFormatString,
733 	pointsFormatString,
734 	teamString,
735 	timeWithBallString,
736 	flagsCapturedString,
737 	timeItString,
738 	goalsString,
739 	reignString,
740 	// Benad
741 	timeOnBaseString,
742 	// SB
743 	pointsString,
744 	timeString,
745 };
746 
calculate_ranking_text_for_post_game(char * buffer,long ranking)747 void calculate_ranking_text_for_post_game(
748 	char *buffer,
749 	long ranking)
750 {
751 	long seconds;
752 	char format[40];
753 
754 	switch(GET_GAME_TYPE())
755 	{
756 		case _game_of_kill_monsters:
757 		case _game_of_cooperative_play:
758 			break;
759 
760 	case _game_of_custom:
761 		switch(GetLuaScoringMode()) {
762 	  case _game_of_most_points:
763 	    getcstr(format, strNETWORK_GAME_STRINGS, pointsFormatString);
764 	    sprintf(buffer, format, ranking);
765 	    break;
766 	  case _game_of_least_points:
767 	    getcstr(format, strNETWORK_GAME_STRINGS, pointsFormatString);
768 	    sprintf(buffer, format, -ranking);
769 	    break;
770 	  case _game_of_most_time:
771 	  case _game_of_least_time:
772 	    seconds= ABS(ranking)/TICKS_PER_SECOND;
773 	    getcstr(format, strNETWORK_GAME_STRINGS, minutesPossessedFormatString);
774 	    sprintf(buffer, format, seconds/60, seconds%60);
775 	    break;
776 	  }
777 	  break;
778 
779 		case _game_of_capture_the_flag:
780 			getcstr(format, strNETWORK_GAME_STRINGS, flagPullsFormatString);
781 			sprintf(buffer, format, ranking);
782 			break;
783 
784 		case _game_of_rugby:
785 			getcstr(format, strNETWORK_GAME_STRINGS, pointsFormatString);
786 			sprintf(buffer, format, ranking);
787 			break;
788 		// START Benad
789 		case _game_of_king_of_the_hill:
790 		case _game_of_kill_man_with_ball:
791 		case _game_of_tag:
792 		case _game_of_defense:
793 			seconds= ABS(ranking)/TICKS_PER_SECOND;
794 			getcstr(format, strNETWORK_GAME_STRINGS, minutesPossessedFormatString);
795 			sprintf(buffer, format, seconds/60, seconds%60);
796 			break;
797 		// END Benad
798 		default:
799 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
800 			break;
801 	}
802 }
803 
get_network_score_text_for_postgame(char * buffer,bool team_mode)804 bool get_network_score_text_for_postgame(
805 	char *buffer,
806 	bool team_mode)
807 {
808 	short string_id= NONE;
809 
810 	switch(GET_GAME_TYPE())
811 	{
812 		case _game_of_kill_monsters:
813 		case _game_of_cooperative_play:
814 			string_id= NONE;
815 			break;
816 
817 	case _game_of_custom:
818 		switch(GetLuaScoringMode()) {
819 	  case _game_of_most_points:
820 	  case _game_of_least_points:
821 	    string_id= pointsString;
822 	    break;
823 	  case _game_of_most_time:
824 	  case _game_of_least_time:
825 	    string_id= timeString;
826 	    break;
827 	  }
828 	  break;
829 
830 		case _game_of_capture_the_flag:
831 			string_id= flagsCapturedString;
832 			break;
833 
834 		case _game_of_rugby:
835 			string_id= goalsString;
836 			break;
837 
838 		case _game_of_king_of_the_hill:
839 			string_id= reignString;
840 			break;
841 
842 		case _game_of_kill_man_with_ball:
843 			string_id= timeWithBallString;
844 			break;
845 		//START Benad
846 		case _game_of_defense:
847 			//dprintf("Not supported!");
848 			//string_id= timeWithBallString;
849 			string_id= timeOnBaseString;
850 			break;
851 		// END Benad
852 		case _game_of_tag:
853 			string_id= timeItString;
854 			break;
855 
856 		default:
857 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
858 			break;
859 	}
860 
861 	if(string_id != NONE)
862 	{
863 		char text[40];
864 		char team[20];
865 
866 		if(team_mode)
867 		{
868 			getcstr(team, strNETWORK_GAME_STRINGS, teamString);
869 			getcstr(text, strNETWORK_GAME_STRINGS, string_id);
870 			sprintf(buffer, "%s %s", team, text);
871 		} else {
872 			getcstr(text, strNETWORK_GAME_STRINGS, string_id);
873 			sprintf(buffer, "%s", text);
874 		}
875 	}
876 
877 	return (string_id!=NONE);
878 }
879 
current_net_game_has_scores(void)880 bool current_net_game_has_scores(
881 	void)
882 {
883 	bool has_scores;
884 
885 	switch(GET_GAME_TYPE())
886 	{
887 		case _game_of_kill_monsters:
888 		case _game_of_cooperative_play:
889 			has_scores= false;
890 			break;
891 
892 	case _game_of_custom:
893 		case _game_of_capture_the_flag:
894 		case _game_of_rugby:
895 		case _game_of_king_of_the_hill:
896 		case _game_of_kill_man_with_ball:
897 		case _game_of_defense:
898 		case _game_of_tag:
899 			has_scores= true;
900 			break;
901 
902 		default:
903 			has_scores= false;
904 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
905 			break;
906 	}
907 
908 	return has_scores;
909 }
910 
current_game_has_balls(void)911 bool current_game_has_balls(
912 	void)
913 {
914 	bool has_ball;
915 
916 	switch(GET_GAME_TYPE())
917 	{
918 		case _game_of_kill_monsters:
919 		case _game_of_cooperative_play:
920 		case _game_of_king_of_the_hill:
921 		case _game_of_defense:
922 		case _game_of_tag:
923 	case _game_of_custom:
924 			has_ball= false;
925 			break;
926 
927 		case _game_of_capture_the_flag:
928 		case _game_of_rugby:
929 		case _game_of_kill_man_with_ball:
930 			has_ball= true;
931 			break;
932 
933 		default:
934 			has_ball= false;
935 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
936 			break;
937 	}
938 
939 	return has_ball;
940 }
941 
942 /* Note that kill limit means different things.. */
943 /* if capture the flag- the number of flag pulls */
game_is_over(void)944 bool game_is_over(
945 	void)
946 {
947 	bool game_over= false;
948 
949 	if (dynamic_world->game_information.game_time_remaining<=0)
950 	{
951 		game_over= true;
952 	}
953 	else if(GetLuaGameEndCondition() == _game_end_now_condition)
954 	  {
955 	    game_over = true;
956 	  }
957 	else if(GetLuaGameEndCondition() == _game_no_end_condition)
958 	  {
959 	    game_over = false;
960 	  }
961 	else if(GET_GAME_OPTIONS() & _game_has_kill_limit)
962 	{
963 		short player_index;
964 
965 		switch(GET_GAME_TYPE())
966 		{
967 			case _game_of_kill_monsters:
968 			case _game_of_cooperative_play:
969 			case _game_of_king_of_the_hill:
970 			case _game_of_kill_man_with_ball:
971 			case _game_of_tag:
972 				/* Find out if the kill limit has been reached */
973 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
974 				{
975 					struct player_data *player= get_player_data(player_index);
976 
977 					// make sure we subtract our suicides.
978 					if (player->total_damage_given.kills-player->damage_taken[player_index].kills >= dynamic_world->game_information.kill_limit)
979 					{
980 						// we don't actually want the game to end right away, but give a second or
981 						// two to see the player die.
982 						dynamic_world->game_information.game_options &= ~_game_has_kill_limit;
983 						dynamic_world->game_information.game_time_remaining= 2*TICKS_PER_SECOND;
984 						break;
985 					}
986 				}
987 				break;
988 
989 		case _game_of_custom: // default scoring behavior is like CTF
990 			case _game_of_capture_the_flag:
991 				/* Kill limit is the number of flag pulls */
992 				for (int i = 0; i < NUMBER_OF_TEAM_COLORS; i++) {
993 					if (team_netgame_parameters[i][_flag_pulls] >= dynamic_world->game_information.kill_limit) {
994 						game_over = true;
995 						break;
996 					}
997 				}
998 				break;
999 
1000 			case _game_of_rugby:
1001 				/* Kill limit is the number of flag pulls */
1002 				for (int i = 0; i < NUMBER_OF_TEAM_COLORS; ++i)
1003 				{
1004 					if (team_netgame_parameters[i][_points_scored] >= dynamic_world->game_information.kill_limit)
1005 					{
1006 						game_over = true;
1007 						break;
1008 					}
1009 				}
1010 				break;
1011 			// START Benad
1012 			case _game_of_defense:
1013 				for(player_index= 0; player_index<dynamic_world->player_count; ++player_index)
1014 				{
1015 					struct player_data *player= get_player_data(player_index);
1016 					if(player->netgame_parameters[_offender_time_in_base] >
1017 						(dynamic_world->game_information.kill_limit * TICKS_PER_SECOND)) // kill_limit is in seconds
1018 					{
1019 						//dprintf("Game is over. Offender won.");
1020 						//dynamic_world->game_information.parameters[_winning_team]= player->team;
1021 						game_over= true;
1022 					}
1023 				}
1024 				break;
1025 			// END Benad
1026 			default:
1027 				vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
1028 				break;
1029 		}
1030 	}
1031 
1032 	return game_over;
1033 }
1034 
1035 enum {
1036 	joinNetworkStrings= 142,
1037 	_standard_format= 0,
1038 	_carnage_word,
1039 	_cooperative_string,
1040 	_capture_the_flag,
1041 	_king_of_the_hill,
1042 	_kill_the_man_with_the_ball,
1043 	_defender_offender,
1044 	_rugby,
1045 	_tag,
1046 	_custom_string
1047 };
1048 
get_network_joined_message(char * buffer,short game_type)1049 void get_network_joined_message(
1050 	char *buffer,
1051 	short game_type)
1052 {
1053 	short format_word= NONE; /* means cooperative */
1054 
1055 	switch(game_type)
1056 	{
1057 		case _game_of_kill_monsters: format_word= _carnage_word; break;
1058 	case _game_of_custom:
1059 		case _game_of_cooperative_play:	format_word= NONE; break;
1060 		case _game_of_capture_the_flag: format_word= _capture_the_flag; break;
1061 		case _game_of_rugby: format_word= _rugby; break;
1062 		case _game_of_king_of_the_hill: format_word= _king_of_the_hill; break;
1063 		case _game_of_kill_man_with_ball: format_word= _kill_the_man_with_the_ball; break;
1064 		case _game_of_defense: format_word= _defender_offender; break;
1065 		case _game_of_tag: format_word= _tag; break;
1066 		default:
1067 			vhalt(csprintf(temporary, "What is game type %d?", GET_GAME_TYPE()));
1068 			break;
1069 	}
1070 
1071 	if(format_word != NONE)
1072 	{
1073 		char format_string[128];
1074 		char game_type_word[50];
1075 
1076 		getcstr(format_string, joinNetworkStrings, _standard_format);
1077 		getcstr(game_type_word, joinNetworkStrings, format_word);
1078 		sprintf(buffer, format_string, game_type_word);
1079 	} else {
1080 	  if(game_type == _game_of_cooperative_play)
1081 	    getcstr(buffer, joinNetworkStrings, _cooperative_string);
1082 	  else
1083 	    getcstr(buffer, joinNetworkStrings, _custom_string);
1084 	}
1085 }
1086 
1087 /* This function is used only at network.. */
get_entry_point_flags_for_game_type(size_t game_type)1088 long get_entry_point_flags_for_game_type(
1089 	size_t game_type)
1090 {
1091 	long entry_flags = 0;
1092 
1093 	switch(game_type)
1094 	{
1095 		case _game_of_kill_man_with_ball:
1096 			entry_flags= _kill_the_man_with_the_ball_entry_point;
1097 			break;
1098 
1099 		case _game_of_kill_monsters:
1100 		case _game_of_tag:
1101 	case _game_of_custom:
1102 			entry_flags= _multiplayer_carnage_entry_point;
1103 			break;
1104 
1105 		case _game_of_cooperative_play:
1106 			entry_flags= _multiplayer_cooperative_entry_point;
1107 			break;
1108 
1109 		case _game_of_king_of_the_hill:
1110 			entry_flags= _king_of_hill_entry_point;
1111 			break;
1112 		// START Benad
1113 		case _game_of_rugby:
1114 			entry_flags= _rugby_entry_point;
1115 			break;
1116 		case _game_of_capture_the_flag:
1117 			entry_flags= _capture_the_flag_entry_point;
1118 			break;
1119 		case _game_of_defense:
1120 			entry_flags= _defense_entry_point;
1121 			break;
1122 		// END Benad
1123 		default:
1124 			vhalt(csprintf(temporary, "What is game type %zu?", game_type));
1125 			break;
1126 	}
1127 
1128 	return entry_flags;
1129 }
1130 
1131 /* ------------------ local code */
player_has_ball(short player_index,short color)1132 static bool player_has_ball(
1133 	short player_index,
1134 	short color)
1135 {
1136 	struct player_data *player= get_player_data(player_index);
1137 	bool has_ball= false;
1138 
1139 	if(player->items[BALL_ITEM_BASE+color]>0)
1140 	{
1141 		has_ball= true;
1142 	}
1143 
1144 	return has_ball;
1145 }
1146 
1147 // START Benad
1148 // This function moved to weapons.c
1149 /*
1150 static void destroy_players_ball(
1151 	short player_index)
1152 {
1153 	short color, item_type;
1154 	struct player_data *player= get_player_data(player_index);
1155 
1156 	color= find_player_ball_color(player_index);
1157 	assert(color != NONE);
1158 
1159 	*//* Get rid of it. *//*
1160 	item_type= BALL_ITEM_BASE+color;
1161 	player->items[item_type]= NONE;
1162 
1163 	*//* Destroy the object (placement will recreate it..) *//*
1164 	object_was_just_destroyed(_object_is_item, item_type);
1165 
1166 	*//* Mark the player inventory as dirty.. *//*
1167 	mark_player_inventory_as_dirty(player_index, _i_knife);
1168 }
1169 */
1170 // END Benad
1171 
1172 #endif // !defined(DISABLE_NETWORKING)
1173 
1174