1 #include "button.h"
2 #include "files.h"
3 #include "satellite.h"
4 #include "update.h"
5 #include "network.h"
6 #include "client.h"
7 #include "beam.h"
8 #include "explosion.h"
9 #include "missile.h"
10 #include "teleport.h"
11 #include "floattext.h"
12 #include "player.h"
13 #include "tank.h"
14
15 #include "sky.h"
16
17 // Note: Don't guard everything. Empty compilation units are invalid.
18 #ifdef NETWORK
19
20 // From gameloop.cpp:
21 void draw_top_bar();
22
23 // Here we try to match the buffer with an action. We then attempt to
24 // perform the action. Remember, this is a command from the server, so
25 // it is either giving us some info or telling us to create something.
Parse_Client_Data(char * buffer)26 int Parse_Client_Data(char *buffer)
27 {
28 char args[CLIENT_ARGS][BUFFER_SIZE];
29 char letter;
30 int dest_string;
31 int line_length = strlen(buffer);
32 int sourceindex = 0, destindex = 0;
33
34 // clear buffers
35 for (dest_string = 0; dest_string < CLIENT_ARGS; dest_string++)
36 memset(args[dest_string], '\0', BUFFER_SIZE);
37
38 dest_string = 0;
39 // copy buffer into cmd and argument variables
40 while ( ( sourceindex < line_length ) && (dest_string < CLIENT_ARGS) )
41 {
42 letter = buffer[sourceindex];
43 if ( letter == ' ' )
44 {
45 letter = '\0';
46 args[dest_string][destindex] = letter;
47 destindex = 0;
48 dest_string++;
49 }
50 else
51 {
52 args[dest_string][destindex] = letter;
53 destindex++;
54 }
55 sourceindex++;
56 }
57
58 // let us see what we have
59 if (! strcmp(args[0], "SERVERVERSION") )
60 {
61 if (! strcmp(args[1], VERSION) )
62 printf("Server version matchs us. OK.\n");
63 else
64 printf("Server version is %s, we are %s. This is likely to cause problems.\n",
65 args[1], VERSION);
66 return TRUE;
67 }
68 else if (! strcmp(args[0], "CURRENTPOSITION") )
69 {
70 if ( (global.client_player) && (global.client_player->tank) )
71 {
72 sscanf(args[1], "%lf", &(global.client_player->tank->x));
73 sscanf(args[2], "%lf", &(global.client_player->tank->y));
74 }
75 }
76 else if (! strcmp(args[0], "BEAM") )
77 {
78 double my_x, my_y;
79 int my_angle, my_type;
80 sscanf(args[1], "%lf", &my_x);
81 sscanf(args[2], "%lf", &my_y);
82 sscanf(args[3], "%d", &my_angle);
83 sscanf(args[4], "%d", &my_type);
84 new BEAM(nullptr, my_x, my_y, my_angle, my_type, BT_WEAPON);
85 }
86 else if (! strcmp(args[0], "BOXED"))
87 {
88 int got_box;
89 sscanf(args[1], "%d", &got_box);
90 if (got_box)
91 env.isBoxed = true;
92 else
93 env.isBoxed = false;
94 return TRUE;
95 }
96 else if (! strcmp(args[0], "EXPLOSION") )
97 {
98 double my_x, my_y;
99 int my_type;
100 sscanf(args[1], "%lf", &my_x);
101 sscanf(args[2], "%lf", &my_y);
102 sscanf(args[3], "%d", &my_type);
103 new EXPLOSION(nullptr, my_x, my_y, 0., 0., my_type, true);
104 return FALSE;
105 }
106 else if (! strcmp(args[0], "ITEM"))
107 {
108 int itemindex, amount;
109 sscanf(args[1], "%d", &itemindex);
110 sscanf(args[2], "%d", &amount);
111 if ( (itemindex >= 0) && (itemindex < ITEMS) &&
112 (amount >= 0) && (amount <= 99) )
113 {
114 global.client_player->ni[itemindex] = amount;
115 }
116 if (itemindex == (ITEMS - 1) )
117 return TRUE;
118 }
119 else if (! strcmp(args[0], "HEALTH") )
120 {
121 int tankindex;
122 int health, shield, shield_type;
123 char some_text[32];
124
125 sscanf(args[1], "%d", &tankindex);
126 if (tankindex >= 0)
127 {
128 sscanf(args[2], "%d", &health );
129 sscanf(args[3], "%d", &shield );
130 sscanf(args[4], "%d", &shield_type);
131 env.players[tankindex]->tank->l = health;
132 env.players[tankindex]->tank->sh = shield;
133 env.players[tankindex]->tank->sht = shield_type;
134 // set the text over the tank
135 sprintf(some_text, "%d", health);
136 env.players[tankindex]->tank->healthText.set_text(some_text);
137 env.players[tankindex]->tank->healthText.set_color(env.players[tankindex]->color);
138 sprintf(some_text, "%d", shield);
139 env.players[tankindex]->tank->shieldText.set_text(some_text);
140 env.players[tankindex]->tank->healthText.set_color(env.players[tankindex]->color);
141 }
142 if (tankindex == (env.numGamePlayers - 1) )
143 return TRUE;
144 else
145 return FALSE;
146 }
147 else if (! strcmp(args[0], "WIND") )
148 {
149 sscanf(args[1], "%lf", & (global.wind) );
150 return TRUE;
151 }
152 else if (! strcmp(args[0], "MISSILE") )
153 {
154 int my_type;
155 double my_x, my_y, delta_x, delta_y;
156 MISSILE *missile;
157 sscanf(args[1], "%lf", &my_x);
158 sscanf(args[2], "%lf", &my_y);
159 sscanf(args[3], "%lf", &delta_x);
160 sscanf(args[4], "%lf", &delta_y);
161 sscanf(args[5], "%d", &my_type);
162 missile = new MISSILE(nullptr, my_x, my_y, delta_x, delta_y, my_type,
163 MT_WEAPON, 1);
164 if (! missile)
165 printf("Attempted to create missile failed in client code.\n");
166 return FALSE;
167 }
168 else if (! strcmp(args[0], "NUMPLAYERS") )
169 {
170 int counter;
171 sscanf(args[1], "%d", & (env.numGamePlayers) );
172 // create the players in question
173 for (counter = 0; counter < env.numGamePlayers; counter++)
174 {
175 env.players[counter] = new PLAYER();
176 env.players[counter]->tank = new TANK();
177 env.players[counter]->tank->player = env.players[counter];
178 env.players[counter]->tank->nameText.set_text(nullptr);
179 }
180 return TRUE;
181 }
182 // ping is a special case where we do not do anything it is just
183 // making sure we are still here because we are not talking
184 else if (! strcmp(args[0], "PING"))
185 {
186 return FALSE;
187 }
188 else if (! strcmp(args[0], "PLAYERNAME") )
189 {
190 int number;
191 sscanf(args[1], "%d", &number);
192 if ( (number < env.numGamePlayers) && (number >= 0) )
193 env.players[number]->setName(args[2]);
194 if (number == (env.numGamePlayers - 1) )
195 return TRUE;
196 }
197 else if (! strcmp(args[0], "REMOVETANK") )
198 {
199 int index;
200 sscanf(args[1], "%d", &index);
201 if ( (index >= 0) && (index < env.numGamePlayers) )
202 {
203 // make sure this tank exists before we get rid of it
204 if ( env.players[index]->tank )
205 {
206 delete env.players[index]->tank;
207 env.players[index]->tank = NULL;
208 }
209 }
210 }
211 else if (! strcmp(args[0], "ROUNDS") )
212 {
213 sscanf(args[1], "%u", &env.rounds);
214 sscanf(args[2], "%u", &global.currentround);
215 return TRUE;
216 }
217 else if (! strcmp(args[0], "SURFACE") )
218 {
219 int x, y;
220 int index;
221 int colour_change = 0;
222 int green = 150;
223 int my_height;
224
225 sscanf(args[1], "%d", &x);
226 sscanf(args[2], "%d", &y);
227 global.surface[x].store(y);
228 my_height = env.screenHeight - y;
229 my_height = my_height / 50; // ratio of change
230 // fill in terrain...
231 for (index = y; index < env.screenHeight; index++)
232 {
233 putpixel(global.terrain, x, index, makecol(0, green, 0));
234 colour_change++;
235 if (colour_change >= my_height)
236 {
237 colour_change = 0;
238 green--;
239 }
240 }
241 if (x >= (env.screenWidth - 1) )
242 return TRUE;
243 }
244 else if (! strcmp(args[0], "SCREEN") )
245 {
246 int width, height;
247
248 sscanf(args[1], "%d", &width);
249 sscanf(args[2], "%d", &height);
250 if ( (width == env.screenWidth) &&
251 (height == env.screenHeight) )
252 printf("Host's screen resolution matches ours.\n");
253 else
254 {
255 printf("Host's screen resolution is %d by %d.\n", width, height);
256 printf("Ours is %d by %d. This is going to cause problems!\n",
257 env.screenWidth, env.screenHeight);
258 }
259 return TRUE;
260 }
261 else if (! strcmp(args[0], "TANKPOSITION") )
262 {
263 int player_number, x, y;
264 PLAYER *my_player;
265
266 sscanf(args[1], "%d", &player_number);
267 my_player = env.players[player_number];
268 if ( (my_player) && (my_player->tank) )
269 {
270 sscanf(args[2], "%d", &x);
271 sscanf(args[3], "%d", &y);
272 my_player->tank->x = x;
273 my_player->tank->y = y;
274 }
275 if (player_number == (env.numGamePlayers - 1))
276 return TRUE;
277 }
278 else if (! strcmp(args[0], "TEAM") )
279 {
280 int32_t player_number = 0;
281 int32_t colour = BLACK;
282 int the_team;
283 sscanf(args[1], "%d", &player_number);
284 sscanf(args[2], "%d", & the_team);
285 if ( (the_team < env.numGamePlayers) && (the_team >= 0) )
286 {
287 env.players[player_number]->team =
288 static_cast<eTeamTypes>(the_team);
289 if (the_team == TEAM_JEDI)
290 colour = makecol(0, 255, 0);
291 else if (the_team == TEAM_SITH)
292 colour = makecol(255, 0, 255);
293 else if (the_team == TEAM_NEUTRAL)
294 colour = makecol(0, 0, 255);
295 if (env.players[player_number] == global.client_player)
296 colour = makecol(255, 0, 0);
297 env.players[player_number]->color = colour;
298 }
299 if (player_number == (env.numGamePlayers - 1) )
300 return TRUE;
301 }
302 else if (! strcmp(args[0], "TELEPORT") )
303 {
304 int player_num;
305 int new_x, new_y;
306
307 sscanf(args[1], "%d", &player_num);
308 sscanf(args[2], "%d", &new_x);
309 sscanf(args[3], "%d", &new_y);
310 if ( (player_num >= 0) && (player_num < env.numGamePlayers) &&
311 (env.players[player_num]->tank) )
312 {
313 TANK* lt = env.players[player_num]->tank;
314 new TELEPORT(lt, new_x, new_y, lt->getDiameter(), 120, ITEM_TELEPORT);
315 }
316
317 }
318 else if (! strcmp(args[0], "WALLTYPE"))
319 {
320 sscanf(args[1], "%d", &(env.current_wallType));
321 switch (env.current_wallType)
322 {
323 case WALL_RUBBER:
324 env.wallColour = makecol(0, 255, 0); // GREEN;
325 break;
326 case WALL_STEEL:
327 env.wallColour = makecol(255, 0, 0); // RED;
328 break;
329 case WALL_SPRING:
330 env.wallColour = makecol(0, 0, 255); //BLUE;
331 break;
332 case WALL_WRAP:
333 env.wallColour = makecol(255, 255, 0); // YELLOW;
334 break;
335 }
336 return TRUE;
337 }
338 else if (! strcmp(args[0], "WEAPON") )
339 {
340 int weaponindex, amount;
341 sscanf(args[1], "%d", &weaponindex);
342 sscanf(args[2], "%d", &amount);
343 if ( (weaponindex >= 0) && (weaponindex < WEAPONS) &&
344 (amount >= 0) && (amount <= 99) )
345 {
346 global.client_player->nm[weaponindex] = amount;
347 }
348 if (weaponindex == (WEAPONS - 1))
349 return TRUE;
350 }
351 else if (! strcmp(args[0], "YOUARE") )
352 {
353 int index;
354 sscanf(args[1], "%d", &index );
355 if ( (index >= 0) && (index < env.numGamePlayers) )
356 {
357 global.client_player = env.players[index];
358 global.set_curr_tank(global.client_player->tank);
359 }
360 return TRUE;
361 }
362
363 return FALSE;
364 }
365
366
367
Create_Sky()368 void Create_Sky()
369 {
370 if (env.custom_background && env.bitmap_filenames) {
371 if (env.sky)
372 destroy_bitmap(env.sky);
373 env.sky = load_bitmap(
374 env.bitmap_filenames[ rand() % env.number_of_bitmaps ], nullptr);
375 }
376
377 if (!env.custom_background || !env.sky) {
378 if (env.sky
379 && ( (env.sky->w != env.screenWidth)
380 || (env.sky->h != (env.screenHeight - MENUHEIGHT) ) ) ) {
381 destroy_bitmap(env.sky);
382 env.sky = nullptr;
383 }
384
385 if (!env.sky)
386 env.sky = create_bitmap(env.screenWidth,
387 env.screenHeight - MENUHEIGHT);
388 generate_sky (nullptr, sky_gradients[global.cursky],
389 (env.ditherGradients ? GENSKY_DITHERGRAD : 0 )
390 | (env.detailedSky ? GENSKY_DETAILED : 0 ) );
391 }
392 } // end of create sky function
393
394
395
396 // Send a shot command to the server
Client_Fire(PLAYER * my_player,int my_socket)397 int Client_Fire(PLAYER *my_player, int my_socket)
398 {
399 char buffer[256];
400
401 if (!my_player) return FALSE;
402 if (! my_player->tank) return FALSE;
403
404 int32_t towrite, written;
405
406 SAFE_WRITE(my_socket, "FIRE %d %d %d", my_player->tank->cw,
407 my_player->tank->a, my_player->tank->p)
408
409 return TRUE;
410 }
411
412
413 // Adjust our power on the client side
Client_Power(PLAYER * my_player,int more_or_less)414 int Client_Power(PLAYER *my_player, int more_or_less)
415 {
416 if ( (my_player) && (my_player->tank) )
417 {
418 if ( (more_or_less == CLIENT_UP) && (my_player->tank->p < 1996) )
419 my_player->tank->p += 5;
420 else if ( (more_or_less == CLIENT_DOWN) && (my_player->tank->p > 5) )
421 my_player->tank->p -= 5;
422 return TRUE;
423 }
424 return FALSE;
425 }
426
427
428
Client_Angle(PLAYER * my_player,int left_or_right)429 int Client_Angle(PLAYER *my_player, int left_or_right)
430 {
431 if (! my_player) return FALSE;
432 if (! my_player->tank) return FALSE;
433
434 if ( (left_or_right == CLIENT_LEFT) && (my_player->tank->a < 270) )
435 my_player->tank->a++;
436 else if ( (left_or_right == CLIENT_RIGHT) && (my_player->tank->a > 90) )
437 my_player->tank->a--;
438 return TRUE;
439 }
440
441
Client_Cycle_Weapon(PLAYER * my_player,int forward_or_back)442 int Client_Cycle_Weapon(PLAYER *my_player, int forward_or_back)
443 {
444 bool found = false;
445
446 if (! my_player->tank)
447 return FALSE;
448
449 while (! found)
450 {
451 if (forward_or_back == CYCLE_FORWARD)
452 my_player->tank->cw++;
453 else
454 my_player->tank->cw--;
455
456 if (my_player->tank->cw >= THINGS)
457 my_player->tank->cw = 0;
458 else if (my_player->tank->cw < 0)
459 my_player->tank->cw = THINGS - 1;
460
461 // check if we have found a weapon
462 if (my_player->tank->cw < WEAPONS)
463 {
464 if (my_player->nm[my_player->tank->cw])
465 found = true;
466 }
467 else // an item
468 {
469 if ( (item[my_player->tank->cw - WEAPONS].selectable) &&
470 (my_player->ni[my_player->tank->cw - WEAPONS]) )
471 found = true;
472 }
473 }
474 return TRUE;
475 }
476
477
478
479 // This function takes an error number and returns a string
480 // which contains useful information about that error.
481 // On success, a pointer to char is returned.
482 // On failure, a NULL is returned.
483 // The returned pointer does NOT need to be freed.
Explain_Error(int32_t error_code)484 const char* Explain_Error(int32_t error_code)
485 {
486 switch (error_code) {
487 case CLIENT_ERROR_VERSION:
488 return env.ingame->Get_Line(77);
489 break;
490 case CLIENT_ERROR_SCREENSIZE:
491 return env.ingame->Get_Line(78);
492 break;
493 case CLIENT_ERROR_DISCONNECT:
494 return env.ingame->Get_Line(79);
495 break;
496 }
497
498 return nullptr;
499 }
500
501
502 // Client version of the game
503 // Really, this loop should do some basic things.
504 // 1. Find out what the landscape should look like from the server.
505 // 2. Place tanks on the battle field
506 // 3. Create missiles, beam weapons and such when the server asks us to
507 // 4. Get input from the player and forward it to the server.
508 // 5. Clean up at the end of the round.
509 //
510 // Function return TRUE if everything went well or FALSE
511 // if an error occured.
Game_Client(int socket_number)512 int Game_Client(int socket_number)
513 {
514 int surface_x = 1, tank_position = 1, team_number = 1, name_number = 1;
515 int weapon_number = 1, item_number = 1, tank_health = 1;
516 int end_of_round = FALSE, keep_playing = FALSE;
517 int game_stage = CLIENT_VERSION;
518 char buffer[BUFFER_SIZE];
519 int incoming;
520 int my_key;
521 int time_clock = 0;
522 bool screen_update = false;
523 int count; // generic counter
524 int stuff_going_down = FALSE; // explosions, missiles etc on the screen
525 VIRTUAL_OBJECT *my_object, *next_obj;
526 int32_t class_ = 0;
527 bool fired = false;
528 int32_t towrite, written;
529
530
531 clear_to_color (global.terrain, PINK); // get terrain ready
532 clear_to_color(global.canvas, BLACK);
533
534 // clean up old text
535 global.getHeadOfClass(CLASS_FLOATTEXT, &my_object);
536 while (my_object) {
537 my_object->getNext(&next_obj);
538 static_cast<FLOATTEXT*>(my_object)->newRound();
539 delete my_object;
540 }
541
542 Create_Sky(); // so we have a background
543 SAFE_WRITE(socket_number, "%s", "VERSION")
544
545 while (! end_of_round)
546 {
547 // check for waiting input from the server
548 incoming = Check_For_Incoming_Data(socket_number);
549 if (incoming)
550 {
551 int bytes_read;
552
553 memset(buffer, '\0', BUFFER_SIZE);
554 bytes_read = read(socket_number, buffer, BUFFER_SIZE);
555 if (bytes_read > 0)
556 {
557 // do something with this input
558 if (! strncmp(buffer, "CLOSE", 5) )
559 {
560 end_of_round = TRUE;
561 keep_playing = FALSE;
562 printf("Got close message.\n");
563 global.client_message = strdup(env.ingame->Get_Line(81));
564 }
565 else if (! strncmp(buffer, "NOROOM", 6) )
566 {
567 end_of_round = TRUE;
568 keep_playing = FALSE;
569 printf("The server is full or the game has not started. Please try again later.\n");
570 global.client_message = strdup(env.ingame->Get_Line(80));
571 }
572 else if (! strncmp(buffer, "GAMEEND", 7) )
573 {
574 end_of_round = TRUE;
575 keep_playing = FALSE;
576 printf("The game is over.\n");
577 if ( strlen(buffer) > 7)
578 global.client_message = strdup(& (buffer[8])) ;
579 else
580 global.client_message = strdup(env.ingame->Get_Line(82));
581 }
582 else if (! strncmp(buffer, "ROUNDEND", 8) )
583 {
584 end_of_round = TRUE;
585 keep_playing = TRUE;
586 printf("Round is over.\n");
587 }
588
589 else // not a special command, parse it
590 {
591 if ( Parse_Client_Data(buffer) )
592 {
593 if (game_stage < CLIENT_PLAYING)
594 game_stage++;
595
596 // Request more information
597 if (game_stage < CLIENT_PLAYING)
598 {
599 switch (game_stage)
600 {
601 case CLIENT_SCREEN: strcpy(buffer, "SCREEN"); break;
602 case CLIENT_WIND: strcpy(buffer, "WIND"); break;
603 case CLIENT_NUMPLAYERS: strcpy(buffer, "NUMPLAYERS"); break;
604 case CLIENT_TANK_POSITION: strcpy(buffer, "TANKPOSITION 0"); break;
605 case CLIENT_SURFACE: strcpy(buffer, "SURFACE 0"); break;
606 case CLIENT_WHOAMI: strcpy(buffer, "WHOAMI"); break;
607 case CLIENT_WEAPONS: strcpy(buffer, "WEAPON 0"); break;
608 case CLIENT_ITEMS: strcpy(buffer, "ITEM 0"); break;
609 case CLIENT_ROUNDS: strcpy(buffer, "ROUNDS"); break;
610 case CLIENT_TEAMS: strcpy(buffer, "TEAMS 0");
611 global.updateMenu = TRUE; break;
612 case CLIENT_WALL_TYPE: strcpy(buffer, "WALLTYPE"); break;
613 case CLIENT_BOXED: strcpy(buffer, "BOXED"); break;
614 case CLIENT_NAME: strcpy(buffer, "PLAYERNAME 0"); break;
615 case CLIENT_TANK_HEALTH: strcpy(buffer, "HEALTH 0"); break;
616 default: buffer[0] = '\0';
617 }
618 towrite = strlen(buffer);
619 written = write(socket_number, buffer, strlen(buffer));
620 if (written < towrite)
621 fprintf(stderr,
622 "%s:%d: Warning: Only %d/%d bytes sent to server\n",
623 __FILE__, __LINE__, written, towrite);
624 } // end of getting more info
625 } // our game stage went up
626 else // we got data, but our game stage did not go up
627 {
628 if (fired)
629 {
630 if ( (global.client_player) && (global.client_player->tank) )
631 {
632 fired = false;
633 if (global.client_player->tank->cw < WEAPONS)
634 SAFE_WRITE(socket_number, "WEAPON %d",
635 global.client_player->tank->cw)
636 else
637 SAFE_WRITE(socket_number, "ITEM %d",
638 global.client_player->tank->cw - WEAPONS)
639 }
640 }
641 else if (game_stage == CLIENT_SURFACE)
642 {
643 SAFE_WRITE(socket_number, "SURFACE %d", surface_x)
644 surface_x++;
645 }
646 else if (game_stage == CLIENT_ITEMS)
647 {
648 SAFE_WRITE(socket_number, "ITEM %d", item_number)
649 item_number++;
650 }
651 else if (game_stage == CLIENT_TANK_POSITION)
652 {
653 SAFE_WRITE(socket_number, "TANKPOSITION %d", tank_position)
654 tank_position++;
655 if (tank_position >= env.numGamePlayers)
656 tank_position = 0;
657 }
658 else if (game_stage == CLIENT_TANK_HEALTH)
659 {
660 SAFE_WRITE(socket_number, "HEALTH %d", tank_health)
661 tank_health++;
662 if (tank_health >= env.numGamePlayers)
663 tank_health = 0;
664 }
665 else if (game_stage == CLIENT_TEAMS)
666 {
667 SAFE_WRITE(socket_number, "TEAMS %d", team_number)
668 team_number++;
669 }
670 else if (game_stage == CLIENT_NAME)
671 {
672 SAFE_WRITE(socket_number, "PLAYERNAME %d", name_number)
673 name_number++;
674 }
675 else if (game_stage == CLIENT_WEAPONS)
676 {
677 SAFE_WRITE(socket_number, "WEAPON %d", weapon_number)
678 weapon_number++;
679 }
680 else if (game_stage == CLIENT_PLAYING)
681 {
682 time_clock++;
683 if (time_clock > 1) // check positions every few inputs
684 {
685 time_clock = 0;
686 if (surface_x < env.screenWidth)
687 {
688 game_stage = CLIENT_SURFACE;
689 SAFE_WRITE(socket_number, "SURFACE %d", surface_x)
690 surface_x++;
691 }
692 else
693 {
694 game_stage = CLIENT_TANK_POSITION;
695 tank_position = 1;
696 SAFE_WRITE(socket_number, "TANKPOSITION %d", 0)
697 } // game stage stuff
698 }
699 } // end of playing commands
700 }
701
702 } // end of we got something besides the close command
703
704 }
705 else // connection was broken
706 {
707 close(socket_number);
708 printf("Server closed connection.\n");
709 end_of_round = TRUE;
710 }
711 }
712
713 class_ = 0;
714 while (class_ < CLASS_COUNT) {
715 if (CLASS_TANK == class_) {
716 ++class_;
717 continue;
718 }
719
720 global.getHeadOfClass(static_cast<eClasses>(class_), &my_object);
721 while(my_object) {
722 my_object->getNext(&next_obj);
723
724 if (CLASS_EXPLOSION == class_)
725 static_cast<EXPLOSION*>(my_object)->explode();
726
727 my_object->applyPhysics();
728
729 if (my_object->destroy) {
730 my_object->requireUpdate();
731 my_object->update();
732 delete my_object;
733 if (CLASS_TELEPORT == class_)
734 time_clock = 2;
735 }
736
737 if ( (CLASS_BEAM == class_)
738 || (CLASS_MISSILE == class_)
739 || (CLASS_EXPLOSION == class_)
740 || (CLASS_TELEPORT == class_) )
741 stuff_going_down = TRUE;
742
743 my_object = next_obj;
744 }
745 ++class_;
746 }
747
748 global.slideLand();
749
750 // update everything on the screen
751 if (global.updateMenu)
752 draw_top_bar ();
753
754 if (screen_update) {
755 screen_update = false;
756 global.make_fullUpdate();
757 }
758 global.replace_canvas ();
759
760 screen_update = true;
761
762 class_ = 0;
763 while (class_ < CLASS_COUNT) {
764 global.getHeadOfClass(static_cast<eClasses>(class_), &my_object);
765 while(my_object) {
766 my_object->draw();
767 if (CLASS_FLOATTEXT == class_)
768 my_object->requireUpdate();
769 my_object->update();
770 my_object->getNext(&my_object);
771 }
772 ++class_;
773 }
774
775 global.do_updates();
776
777
778 // check for input from the user
779 if ( keypressed() )
780 {
781 my_key = readkey();
782 my_key = my_key >> 8;
783 if (my_key == KEY_SPACE)
784 {
785 Client_Fire(global.client_player, socket_number);
786 fired = true;
787 }
788 else if (my_key == KEY_ESC)
789 {
790 end_of_round = TRUE;
791 close(socket_number);
792 }
793 else if (my_key == KEY_UP)
794 {
795 Client_Power(global.client_player, CLIENT_UP);
796 }
797 else if (my_key == KEY_DOWN)
798 {
799 Client_Power(global.client_player, CLIENT_DOWN);
800 }
801 else if (my_key == KEY_LEFT)
802 {
803 Client_Angle(global.client_player, CLIENT_LEFT);
804 }
805 else if (my_key == KEY_RIGHT)
806 {
807 Client_Angle(global.client_player, CLIENT_RIGHT);
808 }
809 else if ( (my_key == KEY_Z) || (my_key == KEY_BACKSPACE) )
810 {
811 Client_Cycle_Weapon(global.client_player, CYCLE_BACK);
812 }
813 else if ( (my_key == KEY_C) || (my_key == KEY_TAB) )
814 {
815 Client_Cycle_Weapon(global.client_player, CYCLE_FORWARD);
816 global.updateMenu = TRUE;
817 }
818
819 screen_update = false;
820 global.updateMenu = TRUE;
821 }
822
823 // pause for a moment
824 // if (game_stage < CLIENT_PLAYING)
825 if (stuff_going_down)
826 {
827 LINUX_SLEEP;
828 stuff_going_down = FALSE;
829 }
830 }
831
832 // we should clean up here
833 for (count = 0; count < env.numGamePlayers; count++)
834 {
835 if (env.players[count]->tank)
836 {
837 delete env.players[count]->tank;
838 env.players[count]->tank = NULL;
839 }
840 }
841
842 return keep_playing;
843 }
844
845
846 #endif // NETWORK
847
848