1 #ifndef WIN32
2 #include "config.h"
3 #endif
4
5 #include <stdio.h>
6 #include <signal.h>
7 #include <math.h>
8
9 #ifdef HAVE_FLOAT_H
10 #include <float.h>
11 #endif
12
13 #ifdef HAVE_SIGINFO_H
14 #include <siginfo.h>
15 #endif
16
17 #ifdef HAVE_SYS_SELECT_H
18 #include <sys/select.h>
19 #endif
20
21 #include <ctype.h>
22
23 #if (!defined(WIN32))
24 #ifdef TIME_WITH_SYS_TIME
25 #include <sys/time.h>
26 #include <time.h>
27 #else
28 #ifdef TM_IN_SYS_TIME
29 #include <sys/time.h>
30 #else
31 #include <time.h>
32 #endif
33 #endif
34 #else
35 #include <time.h>
36 #endif
37
38 #include <errno.h>
39 #include <stdlib.h>
40 #ifndef WIN32
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netdb.h>
45 #ifndef __USE_GNU
46 #define __USE_GNU
47 #endif
48 #else
49 #include <winsock.h>
50 #endif
51
52 #include <string.h>
53
54 #include "sprite.h"
55 #include "data.h"
56 #include "cfg.h"
57 #include "net.h"
58 #include "hash.h"
59 #include "time.h"
60 #include "math.h"
61 #include "getopt.h"
62 #include "error.h"
63
64
65 #ifdef WIN32
66 int consoleApp=1;
67 #endif
68
69 #define N_NAMES 18
70 #define CAN_SEE_X 60
71 #define CAN_SEE_Y 10
72
73 /* some empty functions and variables */
c_shutdown(void)74 void c_shutdown(void){}
init_blit(void)75 void init_blit(void){}
shutdown_blit(void)76 void shutdown_blit(void){}
77 int SCREEN_X=1,SCREEN_Y=1;
78 unsigned char *screen,*screen_a;
79 #ifdef TRI_D
80 unsigned char *screen2,*screen2_a;
81 #endif
82
83
84 int in_signal_handler=0;
85 int level_sprites_start;
86 int level_number=-1;
87
88 /* my health, armor, frags, deaths, ammo, ... and ID */
89 unsigned char health,armor;
90 unsigned int frags,deaths;
91 unsigned short ammo[ARMS];
92 unsigned char current_weapon;
93 unsigned char weapons;
94 int my_id;
95
96 /* connection with server */
97 int connected=0;
98
99 int console_ok=1;
100
101 /* networking */
102 int fd; /* socket */
103 struct sockaddr_in server; /* server address */
104
105 /* objects */
106 struct object_list objects;
107 struct object_list *last_obj;
108 struct it* hero;
109
110 unsigned long_long game_start_offset; /* time difference between game start on this machine and on server */
111
112
113 struct /* keyboard status */
114 {
115 unsigned char right,left,jump,creep,speed,fire,weapon,down_ladder;
116 }keyboard_status;
117
118
119 unsigned char *names[N_NAMES]={
120 "Terminator",
121 "Jack The Ripper",
122 "Rambo",
123 "Exhumator",
124 "Assassin",
125 "Arnold",
126 "Necromancer",
127 "Predator",
128 "Rocky",
129 "Harvester",
130 "Lamer",
131 "Killme",
132 "Looser",
133 "Krueger",
134 "I'll kill you",
135 "Zombieman",
136 "Hellraiser",
137 "Eraser"
138 };
139
140 int direction=0; /* 0=stop, 1=left, 2=right */
141 int const1,const2,const3,const4;
142 unsigned short port=DEFAULT_PORT;
143 unsigned char *host;
144 int priority;
145 /* 0=nothing
146 * 1=kill player
147 * 2=find rifle
148 * 3=find shotgun
149 * 4=find UZI
150 * 5=find grenades
151 * 6=find gun ammo
152 * 7=find shotgun ammo
153 * 8=find rifle ammo
154 * 9=find uzi ammo
155 * 10=find medikit
156 */
157
158 /*-----------------------------------------------------------------------*/
159
160
161 #define can_see(a,b) (a<add_int(hero->x,CAN_SEE_X)&&a>sub_int(hero->x,CAN_SEE_X)&&b>sub_int(hero->y,CAN_SEE_Y)&&b<add_int(hero->y,CAN_SEE_Y))
162
163
odds(int p)164 int odds(int p)
165 {
166 return (random()%1000)<p;
167 }
168
169
170 /* free all before exit */
clear_memory(void)171 void clear_memory(void)
172 {
173 struct object_list *o;
174
175 for (o=&objects;o->next;)
176 delete_obj(o->next->member.id);
177 free_area();
178 shutdown_sprites();
179 free_sprites(0);
180 }
181
182
183 /* shut down the client */
shut_down(int a)184 void shut_down(int a)
185 {
186 if (a)
187 {
188 clear_memory();
189 check_memory_leaks();
190 EXIT(0);
191 }
192 }
193
194
195 /* find address of server and fill the server address structure */
find_server(char * name,unsigned short port)196 char * find_server(char *name,unsigned short port)
197 {
198 struct hostent *h;
199
200 h=gethostbyname(name);
201 if (!h)return "Error: Can't resolve server address.\n";
202
203 server.sin_family=AF_INET;
204 server.sin_port=htons(port);
205 server.sin_addr=*((struct in_addr*)(h->h_addr_list[0]));
206 return 0;
207 }
208
209
210 /* initialize socket */
init_socket(void)211 char * init_socket(void)
212 {
213 fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
214 if(fd<0)return "Can't get socket.\n";
215 return 0;
216 }
217
218
219 #define MAX_COUNT 32
220
221 /* send quit request to server */
send_quit(void)222 void send_quit(void)
223 {
224 unsigned char p;
225 fd_set rfds;
226 struct timeval tv;
227 int a=sizeof(server);
228 int count=0;
229
230 tv.tv_sec=2;
231 tv.tv_usec=0;
232 FD_ZERO(&rfds);
233 FD_SET(fd,&rfds);
234
235 send_again:
236 p=P_QUIT_REQUEST;
237 count ++;
238 send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
239 if (!select(fd+1,&rfds,0,0,&tv)&&count<=MAX_COUNT)goto send_again;
240 recv_packet(&p,1,(struct sockaddr*)(&server),&a,1,my_id,0);
241 if (p!=P_PLAYER_DELETED&&count<=MAX_COUNT)goto send_again;
242 }
243
244 #undef MAX_COUNT
245
246
247 /* initiate connection with server */
contact_server(int color,unsigned char * name)248 char * contact_server(int color,unsigned char *name)
249 {
250 static unsigned char packet[256];
251 int l=strlen(name)+1;
252 int a,r;
253 int min,maj;
254
255 fd_set fds;
256 struct timeval tv;
257 tv.tv_sec=4;
258 tv.tv_usec=0;
259 FD_ZERO(&fds);
260 FD_SET(fd,&fds);
261
262 packet[0]=P_NEW_PLAYER;
263 packet[1]=0;
264 packet[2]=VERSION_MAJOR;
265 packet[3]=VERSION_MINOR;
266 packet[4]=color;
267 memcpy(packet+5,name,l);
268
269 send_packet(packet,l+5,(struct sockaddr*)(&server),my_id,0);
270
271
272 if (!select(fd+1,&fds,NULL,NULL,&tv))return "No reply within 4 seconds.\n";
273
274 if ((r=recv_packet(packet,256,0,0,1,0,0))<0)
275 {
276 if (errno==EINTR)return "Server hung up.\n";
277 else return "Connection error.\n";
278 }
279
280 switch(*packet)
281 {
282 case P_PLAYER_REFUSED:
283 switch(packet[1])
284 {
285 case E_INCOMPATIBLE_VERSION:
286 return "Incompatible client version. Connection refused.\n";
287
288 default:
289 return "Connection refused.\n";
290 }
291
292 case P_PLAYER_ACCEPTED:
293 my_id=get_int(packet+33);
294 if (r<39){send_quit();return "Incompatible server version. Givin' up.\n";}
295 maj=packet[37];
296 min=packet[38];
297 if (maj!=VERSION_MAJOR||min<MIN_SERVER_VERSION_MINOR)
298 {send_quit();return "Incompatible server version. Givin' up.\n";}
299 game_start_offset=get_time();
300 game_start_offset-=get_long_long(packet+25);
301 health=100;
302 armor=0;
303 for(a=0;a<ARMS;a++)
304 ammo[a]=0;
305 ammo[0]=weapon[0].basic_ammo;
306 current_weapon=0;
307 weapons=17; /* gun and grenades */
308 hero=new_obj(
309 get_int(packet+1), /* ID */
310 T_PLAYER, /* type */
311 0, /* time to live */
312 get_int16(packet+5), /* sprite */
313 0, /* position */
314 get_int16(packet+23), /* status */
315 get_float(packet+7), /* X */
316 get_float(packet+11), /* Y */
317 get_float(packet+15), /* XSPEED */
318 get_float(packet+19), /* YSPEED */
319 0
320 );
321 break;
322
323 default:
324 return "Connection error.\n";
325 }
326 return 0;
327 }
328
329
330 /* I want to be born again */
send_reenter_game(void)331 void send_reenter_game(void)
332 {
333 unsigned char packet;
334 packet=P_REENTER_GAME;
335 send_packet(&packet,1,(struct sockaddr*)(&server),my_id,0);
336 }
337
338
339 /* send chat message */
send_message(char * msg)340 void send_message(char *msg)
341 {
342 static unsigned char packet[MAX_MESSAGE_LENGTH+2];
343 int a;
344
345 a=strlen(msg)+1;
346 packet[0]=P_MESSAGE;
347 memcpy(packet+1,msg,a);
348 send_packet(packet,a+1,(struct sockaddr *)(&server),my_id,0);
349 }
350
351
352 /* send end of game to server */
send_keyboard(void)353 void send_keyboard(void)
354 {
355 unsigned char packet[3];
356 packet[0]=P_KEYBOARD;
357 packet[1]= keyboard_status.right|
358 (keyboard_status.left<<1)|
359 (keyboard_status.jump<<2)|
360 (keyboard_status.creep<<3)|
361 (keyboard_status.speed<<4)|
362 (keyboard_status.fire<<5)|
363 (keyboard_status.down_ladder<<6);
364 packet[2]= keyboard_status.weapon;
365 send_packet(packet,3,(struct sockaddr*)(&server),my_id,0);
366 }
367
368
reset_keyboard(void)369 void reset_keyboard(void)
370 {
371 keyboard_status.left=0;
372 keyboard_status.right=0;
373 keyboard_status.speed=1;
374 keyboard_status.jump=0;
375 keyboard_status.creep=0;
376 keyboard_status.fire=0;
377 keyboard_status.weapon=0;
378 keyboard_status.down_ladder=0;
379 }
380
381
test_object(struct it * obj)382 void test_object(struct it *obj)
383 {
384 if (obj==hero)return;
385 if (!can_see(obj->x,obj->y))return;
386 switch(obj->type)
387 {
388 case T_PLAYER:
389 if (obj->status&64)break;
390 if (priority>1)break;
391 priority=1;
392 keyboard_status.fire=1;
393 if (obj->x>hero->x)direction=2;
394 else direction=1;
395 if (my_abs(obj->x-hero->x)<int2double(30))direction=0;
396 break;
397
398 case T_BULLET:
399 case T_SHRAPNEL:
400 if ((my_sgn(hero->x-obj->x)==my_sgn(obj->xspeed)||my_abs(hero->x-obj->x)<int2double(20))&&obj->y>=hero->y&&obj->y<hero->y+int2double(PLAYER_HEIGHT))
401 keyboard_status.creep=1;
402 break;
403
404 case T_RIFLE:
405 if (priority>2)break;
406 if ((weapons&(1<<WEAPON_RIFLE))&&ammo[WEAPON_RIFLE])break;
407 priority=2;
408 if (obj->x>hero->x)direction=2;
409 else direction=1;
410 break;
411
412 case T_SHOTGUN:
413 if (priority>3)break;
414 if ((weapons&(1<<WEAPON_SHOTGUN))&&ammo[WEAPON_SHOTGUN])break;
415 priority=3;
416 if (obj->x>hero->x)direction=2;
417 else direction=1;
418 break;
419
420 case T_UZI:
421 if (priority>4)break;
422 if ((weapons&(1<<WEAPON_UZI))&&ammo[WEAPON_UZI])break;
423 priority=4;
424 if (obj->x>hero->x)direction=2;
425 else direction=1;
426 break;
427
428 case T_AMMO_GRENADE:
429 if (priority>5)break;
430 if (!(weapons&(1<<WEAPON_GRENADE))||ammo[WEAPON_GRENADE])break;
431 priority=5;
432 if (obj->x>hero->x)direction=2;
433 else direction=1;
434 break;
435
436 case T_AMMO_GUN:
437 if (priority>6)break;
438 if (!(weapons&(1<<WEAPON_GUN))||ammo[WEAPON_GUN])break;
439 priority=6;
440 if (obj->x>hero->x)direction=2;
441 else direction=1;
442 break;
443
444 case T_AMMO_SHOTGUN:
445 if (priority>7)break;
446 if (!(weapons&(1<<WEAPON_SHOTGUN))||ammo[WEAPON_SHOTGUN])break;
447 priority=7;
448 if (obj->x>hero->x)direction=2;
449 else direction=1;
450 break;
451
452 case T_AMMO_RIFLE:
453 if (priority>8)break;
454 if (!(weapons&(1<<WEAPON_RIFLE))||ammo[WEAPON_RIFLE])break;
455 priority=8;
456 if (obj->x>hero->x)direction=2;
457 else direction=1;
458 break;
459
460 case T_AMMO_UZI:
461 if (priority>9)break;
462 if (!(weapons&(1<<WEAPON_UZI))||ammo[WEAPON_UZI])break;
463 priority=9;
464 if (obj->x>hero->x)direction=2;
465 else direction=1;
466 break;
467
468 case T_MEDIKIT:
469 if (priority>10)break;
470 if (health>70)break;
471 priority=10;
472 if (obj->x>hero->x)direction=2;
473 else direction=1;
474 break;
475
476 }
477 }
478
479
480 /* destroys all objects except hero (before level change) */
clean_memory(void)481 void clean_memory(void)
482 {
483 struct object_list *o;
484
485 /* delete all objects except hero */
486 for (o=&objects;o->next;)
487 if ((hero->id)!=(o->next->member.id))delete_obj(o->next->member.id);
488 else o=o->next;
489 }
490
491
change_level(void)492 void change_level(void)
493 {
494 unsigned char *LEVEL;
495 unsigned char txt[256];
496
497 clean_memory();
498 free_sprites(level_sprites_start);
499 reinit_area();
500
501 LEVEL=load_level(level_number);
502 snprintf(txt,256,"Loading level \"%s\".\n",LEVEL);
503 ERROR(txt);
504 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,LEVEL_SPRITES_SUFFIX);
505 load_sprites(txt);
506 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
507 load_data(txt);
508 mem_free(LEVEL);
509 }
510
511
512 /* recompute object positions */
update_game(void)513 void update_game(void)
514 {
515 struct object_list *p;
516 int w,h;
517 unsigned char stop_x,stop_y,sy;
518 unsigned long_long t;
519 my_double x,y,x1,y1,DELTA_TIME;
520
521 for(p=&objects;p->next;p=p->next)
522 {
523 if (p->next->member.type==T_NOTHING)continue;
524 if ((p->next->member.status)&1024)continue; /* dead player */
525 /* decrement time to live */
526 if (p->next->member.ttl>0)
527 {
528 p->next->member.ttl--;
529 if (!p->next->member.ttl)
530 {
531 if ((p->next->member.type)==T_PLAYER)p->next->member.status&=~16;
532 else
533 {
534 if (p->next->member.type!=T_GRENADE){ /* client's waiting for P_EXPLODE_GRENADE and doesn't delete the grenade yet */
535 p=p->prev;
536 delete_obj(p->next->next->member.id);
537 continue;}
538 }
539 }
540 }
541 test_object(&(p->next->member));
542 /* maintain only objects that you are allowed to maintain */
543 if (!(obj_attr[p->next->member.type].maintainer&1))continue;
544
545
546 /* if not falling slow down x motion */
547 if (!(p->next->member.status&8))p->next->member.xspeed=mul(p->next->member.xspeed,obj_attr[p->next->member.type].slow_down_x);
548
549 /* fall */
550 if (obj_attr[p->next->member.type].fall)
551 {
552 p->next->member.status|=8;
553 p->next->member.yspeed+=FALL_ACCEL;
554 /* but not too fast */
555 if (p->next->member.yspeed>MAX_Y_SPEED)p->next->member.yspeed=MAX_Y_SPEED;
556 }
557
558 get_dimensions(p->next->member.type,p->next->member.status,sprites[p->next->member.sprite].positions,&w,&h);
559 x=p->next->member.x;
560 y=p->next->member.y;
561 t=get_time();
562 DELTA_TIME=float2double(((double)(long_long)(t-p->next->member.last_updated))/MICROSECONDS);
563 update_position(
564 &(p->next->member),
565 p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
566 p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
567 w,h,&stop_x,&stop_y);
568 p->next->member.last_updated=t;
569
570 /* walk up the stairs */
571 if (stop_x&&p->next->member.type==T_PLAYER&&!(p->next->member.status&256))
572 {
573 x1=p->next->member.x;
574 y1=p->next->member.y;
575 p->next->member.x=x;
576 p->next->member.y=y-int2double(1);
577 update_position(
578 &(p->next->member),
579 p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
580 p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
581 w,h,0,&sy);
582 if ((p->next->member.xspeed>0&&p->next->member.x<=x1)||(p->next->member.xspeed<0&&p->next->member.x>=x1)) /* restore original values */
583 {
584 p->next->member.x=x1;
585 p->next->member.y=y1;
586 }
587 else
588 {
589 stop_y=sy;
590 stop_x=0;
591 }
592 }
593
594 if (stop_x)p->next->member.xspeed=-mul(p->next->member.xspeed,obj_attr[p->next->member.type].bounce_x);
595 if (my_abs(p->next->member.xspeed)<MIN_X_SPEED)
596 {
597 p->next->member.xspeed=0;
598 p->next->member.status&=~1;
599 }
600
601
602 if (stop_y)
603 {
604 p->next->member.yspeed=mul(p->next->member.yspeed,obj_attr[p->next->member.type].bounce_y);
605 p->next->member.yspeed=-p->next->member.yspeed;
606 if (my_abs(p->next->member.yspeed)<MIN_Y_SPEED)
607 {
608 p->next->member.yspeed=0;
609 if (stop_y==1)p->next->member.status&=~8;
610 }
611 }
612
613 if ((p->next->member.type==T_SHRAPNEL||p->next->member.type==T_BULLET)&&(stop_x||stop_y)) /* bullet and shrapnel die crashing into wall */
614 {
615 p=p->prev; /* deleting object makes a great mess in for cycle, so we must cheat the cycle */
616 delete_obj(p->next->next->member.id);
617 continue;
618 }
619
620 }
621 }
622
623
624 /* returns number of read bytes */
process_packet(unsigned char * packet,int l)625 int process_packet(unsigned char *packet,int l)
626 {
627 int a,n=l;
628
629 switch(*packet)
630 {
631 case P_CHUNK:
632 for (a=1;a<l&&a<MAX_PACKET_LENGTH;a+=n)
633 n=process_packet(packet+a,l-a);
634 break;
635
636 case P_NEW_OBJ:
637 if (l<28)break; /* invalid packet */
638 n=28;
639 new_obj(
640 get_int(packet+1), /* ID */
641 packet[25], /* type */
642 get_int16(packet+26), /* time to live */
643 get_int16(packet+5), /* sprite */
644 0, /* anim position */
645 get_int16(packet+23), /* status */
646 get_float(packet+7), /* x */
647 get_float(packet+11), /* y */
648 get_float(packet+15), /* xspeed */
649 get_float(packet+19), /* yspeed */
650 0 /* data */
651 );
652 break;
653
654 case P_PLAYER_DELETED:
655 n=1;
656 shut_down(1);
657 break;
658
659 case P_DELETE_OBJECT:
660 if (l<5)break; /* invalid packet */
661 delete_obj(get_int(packet+1));
662 n=5;
663 break;
664
665 case P_UPDATE_OBJECT:
666 if (l<26)break; /* invalid packet */
667 {
668 struct object_list *p;
669
670 n=26;
671 p=find_in_table(get_int(packet+1));
672 if (!p)break;
673 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
674 p->member.update_counter=packet[5];
675 p->member.x=get_float(packet+6);
676 p->member.y=get_float(packet+10);
677 p->member.xspeed=get_float(packet+14);
678 p->member.yspeed=get_float(packet+18);
679 p->member.status=get_int16(packet+22);
680 p->member.data=0;
681 p->member.ttl=get_int16(packet+24);
682 /* kdyz tasi, tak se nahodi ttl */
683 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
684 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
685 }
686 break;
687
688 case P_UPDATE_OBJECT_POS:
689 if (l<22)break; /* invalid packet */
690 {
691 struct object_list *p;
692
693 n=22;
694 p=find_in_table(get_int(packet+1));
695 if (!p)break;
696 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
697 p->member.update_counter=packet[5];
698 p->member.x=get_float(packet+6);
699 p->member.y=get_float(packet+10);
700 p->member.xspeed=get_float(packet+14);
701 p->member.yspeed=get_float(packet+18);
702 }
703 break;
704
705 case P_UPDATE_OBJECT_SPEED:
706 if (l<14)break; /* invalid packet */
707 {
708 struct object_list *p;
709
710 n=14;
711 p=find_in_table(get_int(packet+1));
712 if (!p)break;
713 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
714 p->member.update_counter=packet[5];
715 p->member.xspeed=get_float(packet+6);
716 p->member.yspeed=get_float(packet+10);
717 }
718 break;
719
720 case P_UPDATE_OBJECT_COORDS:
721 if (l<14)break; /* invalid packet */
722 {
723 struct object_list *p;
724
725 n=14;
726 p=find_in_table(get_int(packet+1));
727 if (!p)break;
728 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
729 p->member.update_counter=packet[5];
730 p->member.x=get_float(packet+6);
731 p->member.y=get_float(packet+10);
732 }
733 break;
734
735 case P_UPDATE_OBJECT_SPEED_STATUS:
736 if (l<16)break; /* invalid packet */
737 {
738 struct object_list *p;
739
740 n=16;
741 p=find_in_table(get_int(packet+1));
742 if (!p)break;
743 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
744 p->member.update_counter=packet[5];
745 p->member.xspeed=get_float(packet+6);
746 p->member.yspeed=get_float(packet+10);
747 p->member.status=get_int16(packet+14);
748 /* kdyz tasi, tak se nahodi ttl */
749 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
750 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
751 }
752 break;
753
754 case P_UPDATE_OBJECT_COORDS_STATUS:
755 if (l<16)break; /* invalid packet */
756 {
757 struct object_list *p;
758
759 n=16;
760 p=find_in_table(get_int(packet+1));
761 if (!p)break;
762 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
763 p->member.update_counter=packet[5];
764 p->member.x=get_float(packet+6);
765 p->member.y=get_float(packet+10);
766 p->member.status=get_int16(packet+14);
767 /* kdyz tasi, tak se nahodi ttl */
768 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
769 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
770 }
771 break;
772
773 case P_UPDATE_OBJECT_SPEED_STATUS_TTL:
774 if (l<18)break; /* invalid packet */
775 {
776 struct object_list *p;
777
778 n=18;
779 p=find_in_table(get_int(packet+1));
780 if (!p)break;
781 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
782 p->member.update_counter=packet[5];
783 p->member.xspeed=get_float(packet+6);
784 p->member.yspeed=get_float(packet+10);
785 p->member.status=get_int16(packet+14);
786 p->member.ttl=get_int16(packet+16);
787 /* kdyz tasi, tak se nahodi ttl */
788 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
789 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
790 }
791 break;
792
793 case P_UPDATE_OBJECT_COORDS_STATUS_TTL:
794 if (l<18)break; /* invalid packet */
795 {
796 struct object_list *p;
797
798 n=18;
799 p=find_in_table(get_int(packet+1));
800 if (!p)break;
801 if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
802 p->member.update_counter=packet[5];
803 p->member.x=get_float(packet+6);
804 p->member.y=get_float(packet+10);
805 p->member.status=get_int16(packet+14);
806 p->member.ttl=get_int16(packet+16);
807 /* kdyz tasi, tak se nahodi ttl */
808 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
809 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
810 }
811 break;
812
813 case P_UPDATE_STATUS:
814 if (l<7)break; /* invalid packet */
815 {
816 struct object_list *p;
817
818 n=7;
819 p=find_in_table(get_int(packet+1));
820 if (!p)break; /* ignore objects we don't have */
821 p->member.status=get_int16(packet+5);
822 /* kdyz tasi, tak se nahodi ttl */
823 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
824 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
825 }
826 break;
827
828 case P_HIT:
829 if (l<8)break; /* invalid packet */
830 {
831 struct object_list *p;
832
833 n=8;
834 p=find_in_table(get_int(packet+1));
835 if (!p)break; /* ignore objects we don't have */
836 p->member.status|=128;
837 p->member.data=(void*)((packet[5]<<16)+(packet[7]<<8)+(packet[6]));
838 /* kdyz tasi, tak se nahodi ttl */
839 if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
840 p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
841 }
842 break;
843
844 case P_UPDATE_PLAYER:
845 if (l<23)break; /* invalid packet */
846 health=packet[1];
847 armor=packet[2];
848 for (a=0;a<ARMS;a++)
849 ammo[a]=get_int16(packet+3+(a<<1));
850 frags=get_int(packet+3+ARMS*2);
851 deaths=get_int(packet+7+ARMS*2);
852 current_weapon=packet[11+2*ARMS];
853 weapons=packet[12+2*ARMS];
854 n=23;
855 break;
856
857 case P_MESSAGE:
858 if (l<2)break; /* invalid packet */
859 n=2+strlen(packet+1);
860 break;
861
862 case P_END:
863 if (l<2)printf("Game terminated.\n");
864 else printf("Game terminated by %s.\n",packet+1);
865 n=2+strlen(packet+1);
866 shut_down(1);
867
868 case P_INFO:
869 if (l<=5)break;
870 l=6;
871 for (a=0;a<packet[5]&&a<TOP_PLAYERS_N;a++)
872 {
873 int x;
874 x=strlen(packet+l+9)+1;
875 l+=x+9;
876 }
877 n=l;
878 break;
879
880 case P_EXPLODE_GRENADE:
881 {
882 unsigned int i,j;
883 struct object_list *p;
884 int b;
885
886 if (l<9)break;
887 n=9;
888 i=get_int(packet+1);
889 j=get_int(packet+5);
890 p=find_in_table(j);
891 if (!p)break;
892
893 for (b=0;b<N_SHRAPNELS_EXPLODE;b++)
894 {
895 double angle=(double)b*2*M_PI/N_SHRAPNELS_EXPLODE;
896 my_double spd=add_int(mul_int(my_and(mul_int(weapon[WEAPON_GRENADE].speed,b+1),15),16),100);
897
898 new_obj(
899 i,
900 T_SHRAPNEL,
901 SHRAPNEL_TTL,
902 0,
903 0,
904 WEAPON_GRENADE,
905 p->member.x,
906 p->member.y,
907 p->member.xspeed+mul(spd,float2double(cos(angle))),
908 p->member.yspeed+mul(spd,float2double(sin(angle))),
909 0);
910 i++;
911 }
912 delete_obj(j);
913
914 }
915 break;
916
917 case P_CHANGE_LEVEL:
918 {
919 unsigned char *md5;
920 int a;
921 char p;
922
923 if (l<38)break; /* invalid packet */
924 a=get_int(packet+1);
925 if (level_number==a)goto level_changed;
926 level_number=a;
927
928 md5=md5_level(level_number);
929 if (strcmp(md5,packet+5)) /* MD5s differ */
930 {
931 mem_free(md5);
932 ERROR("Invalid MD5 sum. Can't change level. Exiting...");
933 send_quit();
934 shut_down(1);
935 }
936 mem_free(md5);
937
938 /* OK we can change it */
939 change_level();
940 level_changed:
941
942 p=P_LEVEL_ACCEPTED;
943 send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
944 n=38;
945 }
946 break;
947
948 }
949 return n;
950 }
951
952
953 /* read packet from socket */
read_data(void)954 void read_data(void)
955 {
956 fd_set rfds;
957 struct timeval tv;
958 struct sockaddr_in client;
959 static unsigned char packet[MAX_PACKET_LENGTH];
960 int a=sizeof(client);
961 int l;
962
963 tv.tv_sec=0;
964 tv.tv_usec=0;
965 FD_ZERO(&rfds);
966 FD_SET(fd,&rfds);
967 while(select(fd+1,&rfds,0,0,&tv))
968 {
969 if ((l=recv_packet(packet,MAX_PACKET_LENGTH,(struct sockaddr*)(&client),&a,1,my_id,0))<0)
970 return; /* something's strange */
971 process_packet(packet,l);
972
973 }
974 }
975
976
977 /* handle fatal signal (sigabrt, sigsegv, ...) */
signal_handler(int signum)978 void signal_handler(int signum)
979 {
980
981 if (connected)send_quit();
982 shut_down(0);
983 clear_memory();
984 #ifdef HAVE_PSIGNAL
985 psignal(signum,"Exiting on signal");
986 #else
987 fprintf(stderr, "Exiting on signal: %d\n", signum);
988 #endif
989 if (!in_signal_handler){in_signal_handler=1;check_memory_leaks();}
990 EXIT(1);
991 }
992
993
994 /* print command line help */
print_help(void)995 void print_help(void)
996 {
997 printf(
998 "0verkill bot"
999 ".\n"
1000 "(c)2000 Brainsoft\n"
1001 "Usage: bot [-h] -a <server address> [-p <port>]"
1002 "\n"
1003 );
1004 }
1005
1006
parse_command_line(int argc,char ** argv)1007 void parse_command_line(int argc,char **argv)
1008 {
1009 int a;
1010 char *e;
1011
1012 while(1)
1013 {
1014 a=getopt(argc,argv,"hp:a:");
1015 switch(a)
1016 {
1017 case EOF:
1018 return;
1019
1020 case '?':
1021 case ':':
1022 EXIT(1);
1023
1024 case 'h':
1025 print_help();
1026 EXIT(0);
1027
1028 case 'a':
1029 host=optarg;
1030 break;
1031
1032 case 'p':
1033 port=strtoul(optarg,&e,10);
1034 if (*e){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1035 break;
1036 }
1037 }
1038 }
1039
1040
select_name(void)1041 unsigned char * select_name(void)
1042 {
1043 return names[(random())%N_NAMES];
1044 }
1045
1046
where2go(void)1047 void where2go(void)
1048 {
1049 if (!direction)
1050 {
1051 if (odds(20+const2))direction=2;
1052 if (odds(20+const2))direction=1;
1053 }
1054 if(direction==1)keyboard_status.left=1;
1055 if(direction==2)keyboard_status.right=1;
1056
1057 if (odds(40+const1))keyboard_status.jump=1;
1058 if (odds(100+const4))keyboard_status.down_ladder=1;
1059 if (odds(3)+const3)keyboard_status.fire=1;
1060
1061 }
1062
1063
action(void)1064 void action(void)
1065 {
1066 if ((hero->status)&1024)send_reenter_game(); /* respawn */
1067 where2go();
1068 }
1069
1070 /*----------------------------------------------------------------------------*/
main(int argc,char ** argv)1071 int main(int argc,char **argv)
1072 {
1073 int color;
1074 unsigned long_long last_time;
1075 unsigned char *m;
1076
1077
1078 #ifdef WIN32
1079 WSADATA wd;
1080
1081 WSAStartup(0x101, &wd);
1082 printf("Started WinSock version %X.%02X\n", wd.wVersion/0x100, wd.wVersion&0xFF);
1083 #endif
1084
1085
1086 ERROR("Initialization...\n");
1087
1088 last_obj=&objects;
1089 #ifndef WIN32
1090 srandom(get_time());
1091 #else
1092 srand(get_time());
1093 #endif
1094
1095 const1=random()%50;
1096 const2=random()%20;
1097 const3=random()%5;
1098 const4=random()%20;
1099
1100 host=NULL;
1101 parse_command_line(argc,argv);
1102 if (!host){ERROR("No server address specified.\n");EXIT(1);}
1103 hash_table_init();
1104 init_sprites();
1105 init_area();
1106 ERROR("Loading graphics...\n");
1107 load_sprites(DATA_PATH GAME_SPRITES_FILE);
1108 level_sprites_start=n_sprites;
1109
1110 signal(SIGINT,signal_handler);
1111 signal(SIGTERM,signal_handler);
1112 signal(SIGILL,signal_handler);
1113 signal(SIGABRT,signal_handler);
1114 signal(SIGFPE,signal_handler);
1115 signal(SIGSEGV,signal_handler);
1116 #ifndef WIN32
1117 signal(SIGQUIT,signal_handler);
1118 signal(SIGBUS,signal_handler);
1119 #endif
1120
1121 ERROR("Resolving server address ...\n");
1122 if ((m=find_server(host,port))){ERROR(m);EXIT(1);}
1123 ERROR("Initializing socket ...\n");
1124 if ((m=init_socket())){ERROR(m);EXIT(1);}
1125 ERROR("Contacting server ...\n");
1126 color=(random()%15)+1;
1127 if ((m=contact_server(color,select_name()))){ERROR(m);EXIT(1);}
1128
1129 connected=1;
1130 ERROR("OK, connected.\nPlaying...\n");
1131
1132 last_time=get_time();
1133 again:
1134 last_time+=CLIENT_PERIOD_USEC;
1135 if (get_time()-last_time>PERIOD_USEC*100)last_time=get_time();
1136 read_data();
1137 reset_keyboard();
1138 priority=0;
1139 update_game();
1140 action();
1141 send_keyboard();
1142 sleep_until(last_time+CLIENT_PERIOD_USEC);
1143 goto again;
1144 }
1145