1 /* When compiling with X support don't forget to define XWINDOW symbol */
2 
3 #ifndef WIN32
4 #include "config.h"
5 #endif
6 
7 #include <stdio.h>
8 #include <signal.h>
9 #include <math.h>
10 
11 #ifdef HAVE_FLOAT_H
12 	#include <float.h>
13 #endif
14 
15 #ifdef HAVE_SIGINFO_H
16 	#include <siginfo.h>
17 #endif
18 
19 #ifdef HAVE_SYS_SELECT_H
20 #include <sys/select.h>
21 #endif
22 
23 #include <ctype.h>
24 
25 #if (!defined(WIN32))
26 	#ifdef TIME_WITH_SYS_TIME
27 		#include <sys/time.h>
28 		#include <time.h>
29 	#else
30 		#ifdef TM_IN_SYS_TIME
31 			#include <sys/time.h>
32 		#else
33 			#include <time.h>
34 		#endif
35 	#endif
36 #else
37 	#include <time.h>
38 #endif
39 
40 #include <errno.h>
41 #include <stdlib.h>
42 #ifndef WIN32
43 	#include <sys/types.h>
44 	#include <sys/socket.h>
45 	#include <netinet/in.h>
46 	#include <netdb.h>
47 	#ifndef __USE_GNU
48 		#define __USE_GNU
49 	#endif
50 #else
51 	#include <winsock.h>
52 #endif
53 
54 #include <string.h>
55 
56 #include "blit.h"
57 #include "sprite.h"
58 #include "data.h"
59 #include "cfg.h"
60 #include "net.h"
61 #include "hash.h"
62 #include "console.h"
63 #include "time.h"
64 #include "math.h"
65 #include "help.h"
66 #include "getopt.h"
67 #include "error.h"
68 
69 #ifdef XWINDOW
70 	#include "x.h"
71 #endif
72 
73 #undef PAUSE
74 
75 #ifdef WIN32
76 	int consoleApp=1;
77 #endif
78 
79 /* my health, armor, frags, deaths, ammo, ... and ID */
80 unsigned char health,armor;
81 unsigned int frags,deaths;
82 unsigned short ammo[ARMS];
83 unsigned char current_weapon;
84 unsigned char weapons;
85 unsigned char creep;
86 unsigned char autorun,autocreep;
87 int my_id;
88 
89 /* connection with server */
90 int connected;
91 
92 int level_number=-1;
93 
94 /* networking */
95 int fd;  /* socket */
96 struct sockaddr_in server;  /* server address */
97 
98 /* objects */
99 struct object_list objects;
100 struct object_list *last_obj;
101 struct it* hero;
102 
103 /* important sprites */
104 int hit_sprite;
105 int title_sprite;
106 int bulge_sprite;
107 int shrapnel_sprite[N_SHRAPNELS];
108 
109 int level_sprites_start;  /* number of first sprite in the level (all other level sprites follow) */
110 
111 unsigned long_long game_start_offset; /* time difference between game start on this machine and on server */
112 
113 
114 /* top players table */
115 struct
116 {
117 	char name[MAX_NAME_LEN+1];
118 	int frags,deaths;
119 	unsigned char color;
120 }top_players[TOP_PLAYERS_N];
121 
122 /* # of active players in the game */
123 int active_players;
124 
125 
126 struct  /* keyboard status */
127 {
128 	unsigned char right,left,jump,creep,speed,fire,weapon,down_ladder;
129 }keyboard_status;
130 
131 /* message */
132 struct msgline_type
133 {
134 	unsigned long_long time;
135 	char *msg;
136 }msg_line[N_MESSAGES];
137 
138 int last_message;
139 unsigned char error_message[1024];
140 
141 unsigned char set_size;  /* -s option was on the command line */
142 
143 /* convert key to key with shift */
my_toupper(int c)144 int my_toupper(int c)
145 {
146         switch(c)
147         {
148                 case '1': return '!';
149                 case '2': return '@';
150                 case '3': return '#';
151                 case '4': return '$';
152                 case '5': return '%';
153                 case '6': return '^';
154                 case '7': return '&';
155                 case '8': return '*';
156                 case '9': return '(';
157                 case '0': return ')';
158                 case '-': return '_';
159                 case '=': return '+';
160                 case '\\': return '|';
161                 case '[': return '{';
162                 case ']': return '}';
163                 case ';': return ':';
164                 case '\'': return '"';
165                 case ',': return '<';
166                 case '.': return '>';
167                 case '/': return '?';
168                 case '`': return '~';
169                 default: return toupper(c);
170         }
171 }
172 
173 
174 
wait_for_enter(void)175 void wait_for_enter(void)
176 {
177 	c_update_kbd();
178 	while (!c_was_pressed(K_ENTER))
179 	{
180 		c_wait_for_key();
181 		c_update_kbd();
182 	}
183 }
184 
185 
186 /* load configure file from player's home directory */
load_cfg(char * host,char * name,int * color)187 void load_cfg(char *host,char *name,int *color)
188 {
189 	FILE *stream;
190 	int a;
191 	unsigned char txt[256];
192 
193 #ifndef WIN32
194 	snprintf(txt,sizeof(txt),"%s/%s",getenv("HOME"),CFG_FILE);
195 #else
196 	snprintf(txt,sizeof(txt),"./%s",CFG_FILE);
197 #endif
198 	stream=fopen(txt,"r");
199 	if (!stream)return;
200 
201 	if (!fgets(txt,MAX_HOST_LEN+2,stream))
202 		return;
203 	a=strlen(txt);
204 	if (txt[a-1]==10)txt[a-1]=0;
205 	memcpy(host,txt,strlen(txt)+1);
206 
207 	if (!fgets(txt,MAX_NAME_LEN+2,stream))
208 		return;
209 	a=strlen(txt);
210 	if (txt[a-1]==10)txt[a-1]=0;
211 	memcpy(name,txt,strlen(txt)+1);
212 	if (!fgets(txt,256,stream))
213 		return;
214 	*color=strtol(txt,0,10);
215 	fclose(stream);
216 }
217 
218 
219 /* save configure file to player's home */
save_cfg(char * host,char * name,int color)220 void save_cfg(char *host,char *name,int color)
221 {
222 	FILE *stream;
223 	unsigned char txt[256];
224 
225 #ifndef WIN32
226 	snprintf(txt,sizeof(txt),"%s/%s",getenv("HOME"),CFG_FILE);
227 #else
228 	snprintf(txt,sizeof(txt),"./%s",CFG_FILE);
229 #endif
230 	stream=fopen(txt,"w");
231 	if (!stream)return;
232 	fprintf(stream,"%s\n%s\n%d\n",host,name,color);
233 	fclose(stream);
234 }
235 
236 
scroll_messages(void)237 void scroll_messages(void)
238 {
239 	int a;
240 
241 	if (last_message<0)return;
242 	for (a=0;a<=last_message-1;a++)
243 	{
244 		msg_line[a].time=msg_line[a+1].time;
245 		msg_line[a].msg=mem_realloc(msg_line[a].msg,strlen(msg_line[a+1].msg)+1);
246 		memcpy(msg_line[a].msg,msg_line[a+1].msg,strlen(msg_line[a+1].msg)+1);
247 	}
248 	mem_free(msg_line[last_message].msg);
249 	msg_line[last_message].msg=0;
250 	last_message--;
251 }
252 
253 
add_message(char * message)254 void add_message(char *message)
255 {
256 	if (last_message==N_MESSAGES-1)scroll_messages();
257 	msg_line[last_message+1].time=get_time()+MESSAGE_TTL;
258 	msg_line[last_message+1].msg=mem_alloc(strlen(message)+1);
259 	if (!msg_line[last_message+1].msg)return;	/* not such a fatal errror */
260 	memcpy(msg_line[last_message+1].msg,message,strlen(message)+1);
261 	last_message++;
262 }
263 
264 
print_messages(void)265 void print_messages(void)
266 {
267 	int a;
268 
269 	for (a=0;a<=last_message;a++)
270 		print2screen(0,a,MESSAGE_COLOR,msg_line[a].msg);
271 }
272 
273 
274 /* throw out old messages */
update_messages(unsigned long_long time)275 void update_messages(unsigned long_long time)
276 {
277 	int a,b;
278 
279 	for(a=0,b=0;a<=last_message;a++)
280 		if (msg_line[b].time<=time)scroll_messages();
281 		else b++;
282 }
283 
284 
285 /* destroys all objects and messages */
clean_memory(void)286 void clean_memory(void)
287 {
288 	int a;
289 	struct object_list *o;
290 
291 	/* delete all objects except hero */
292 	for (o=&objects;o->next;)
293 		if ((hero->id)!=(o->next->member.id))delete_obj(o->next->member.id);
294 		else o=o->next;
295 
296 	/* delete messages */
297 	for (a=0;a<=last_message;a++)
298 		mem_free(msg_line[a].msg);
299 	msg_line[last_message].msg=0;
300 	last_message=-1;
301 }
302 
303 
304 /* shut down the client */
shut_down(int x)305 void shut_down(int x)
306 {
307 	struct object_list *o;
308 	int a;
309 
310 	c_shutdown();
311 	free_sprites(0);
312 	free_area();
313 	if (hero)delete_obj(hero->id);
314 
315 
316 	/* delete all objects except hero */
317 	for (o=&objects;o->next;)
318 		delete_obj(o->next->member.id);
319 
320 	/* delete messages */
321 	for (a=0;a<=last_message;a++)
322 		mem_free(msg_line[a].msg);
323 	msg_line[last_message].msg=0;
324 
325 	shutdown_sprites();
326 	check_memory_leaks();
327 	if (x)EXIT(0);
328 }
329 
330 
331 /* find address of server and fill the server address structure */
find_server(char * name,unsigned short port)332 char * find_server(char *name,unsigned short port)
333 {
334 	struct hostent *h;
335 
336 	h=gethostbyname(name);
337 	if (!h)return "Error: Can't resolve server address.";
338 
339 	server.sin_family=AF_INET;
340 	server.sin_port=htons(port);
341 	server.sin_addr=*((struct in_addr*)(h->h_addr_list[0]));
342 	return 0;
343 }
344 
345 
346 /* initialize socket */
init_socket(void)347 char * init_socket(void)
348 {
349 	fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
350 	if(fd<0)return "Can't get socket.\n";
351 	return 0;
352 }
353 
354 
355 #define MAX_COUNT 32
356 
357 /* send quit request to server */
send_quit(void)358 void send_quit(void)
359 {
360 	unsigned char p;
361 	fd_set rfds;
362 	struct timeval tv;
363 	int a=sizeof(server);
364 	int count=0;
365 
366 	tv.tv_sec=2;
367 	tv.tv_usec=0;
368 	FD_ZERO(&rfds);
369 	FD_SET(fd,&rfds);
370 
371 send_again:
372 	p=P_QUIT_REQUEST;
373 	count ++;
374 	send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
375 	if (!select(fd+1,&rfds,0,0,&tv)&&count<=MAX_COUNT)goto send_again;
376 	recv_packet(&p,1,(struct sockaddr*)(&server),&a,1,my_id,0);
377 	if (p!=P_PLAYER_DELETED&&count<=MAX_COUNT)goto send_again;
378 }
379 
380 #undef MAX_COUNT
381 
382 
383 /* initiate connection with server */
contact_server(int color,unsigned char * name)384 char * contact_server(int color,unsigned char *name)
385 {
386 	static unsigned char packet[256];
387 	int l=strlen(name)+1;
388 	int a,r;
389 	int min,maj;
390 
391         fd_set fds;
392         struct timeval tv;
393         tv.tv_sec=4;
394         tv.tv_usec=0;
395         FD_ZERO(&fds);
396         FD_SET(fd,&fds);
397 
398 	packet[0]=P_NEW_PLAYER;
399 	packet[1]=0;
400 	packet[2]=VERSION_MAJOR;
401 	packet[3]=VERSION_MINOR;
402 	packet[4]=color;
403 	memcpy(packet+5,name,l);
404 
405 	send_packet(packet,l+5,(struct sockaddr*)(&server),my_id,0);
406 
407 
408         if (!select(fd+1,&fds,NULL,NULL,&tv))return "No reply within 4 seconds. Press ENTER.";
409 
410 	if ((r=recv_packet(packet,256,0,0,1,0,0))<0)
411 	{
412 		if (errno==EINTR)return "Server hung up. Press ENTER.";
413 		else return "Connection error. Press ENTER.";
414 	}
415 
416 	switch(*packet)
417 	{
418 		case P_PLAYER_REFUSED:
419 		switch(packet[1])
420 		{
421 			case E_INCOMPATIBLE_VERSION:
422 			return "Incompatible client version. Connection refused. Press Enter.";
423 
424 			default:
425 			return "Connection refused. Press ENTER.";
426 		}
427 
428 		case P_PLAYER_ACCEPTED:
429 		my_id=get_int(packet+33);
430 		if (r<39){send_quit();return "Incompatible server version. Givin' up. Press Enter.";}
431 		maj=packet[37];
432 		min=packet[38];
433 		if (maj!=VERSION_MAJOR||min<MIN_SERVER_VERSION_MINOR)
434 		{send_quit();return "Incompatible server version. Givin' up. Press Enter.";}
435 		game_start_offset=get_time();
436 		game_start_offset-=get_long_long(packet+25);
437 		health=100;
438 		armor=0;
439 		for(a=0;a<ARMS;a++)
440 			ammo[a]=0;
441 		ammo[0]=weapon[0].basic_ammo;
442 		current_weapon=0;
443 		weapons=17;  /* gun and grenades */
444 		hero=new_obj(
445 			get_int(packet+1),   /* ID */
446 			T_PLAYER,   /* type */
447 			0,  /* time to live */
448 			get_int16(packet+5),   /* sprite */
449 			0,        /* position */
450 			get_int16(packet+23),        /* status */
451 			get_float(packet+7),     /* X */
452 			get_float(packet+11),    /* Y */
453 			get_float(packet+15),    /* XSPEED */
454 			get_float(packet+19),    /* YSPEED */
455 			0
456 			);
457 		break;
458 
459 		default:
460 		return "Connection error. Press ENTER.";
461 	}
462 	return 0;
463 }
464 
465 
466 /* send me top X players */
send_info_request(void)467 void send_info_request(void)
468 {
469 	unsigned char packet;
470 	packet=P_INFO;
471 	send_packet(&packet,1,(struct sockaddr*)(&server),my_id,0);
472 }
473 
474 
475 /* I want to be born again */
send_reenter_game(void)476 void send_reenter_game(void)
477 {
478 	unsigned char packet;
479 	packet=P_REENTER_GAME;
480 	send_packet(&packet,1,(struct sockaddr*)(&server),my_id,0);
481 }
482 
483 
484 /* send end of game to server */
end_game(void)485 void end_game(void)
486 {
487 	unsigned char packet;
488 	packet=P_END;
489 	send_packet(&packet,1,(struct sockaddr*)(&server),my_id,0);
490 }
491 
492 
493 /* send chat message */
send_message(char * msg)494 void send_message(char *msg)
495 {
496 	static unsigned char packet[MAX_MESSAGE_LENGTH+2];
497 	int a;
498 
499 	a=strlen(msg)+1;
500 	packet[0]=P_MESSAGE;
501 	memcpy(packet+1,msg,a);
502 	send_packet(packet,a+1,(struct sockaddr *)(&server),my_id,0);
503 }
504 
505 
506 /* send end of game to server */
send_keyboard(void)507 void send_keyboard(void)
508 {
509 	unsigned char packet[3];
510 	packet[0]=P_KEYBOARD;
511 	packet[1]=	keyboard_status.right|
512 			(keyboard_status.left<<1)|
513 			(keyboard_status.jump<<2)|
514 			(keyboard_status.creep<<3)|
515 			(keyboard_status.speed<<4)|
516 			(keyboard_status.fire<<5)|
517 			(keyboard_status.down_ladder<<6);
518 	packet[2]=	keyboard_status.weapon;
519 	send_packet(packet,3,(struct sockaddr*)(&server),my_id,0);
520 }
521 
522 
reset_keyboard(void)523 void reset_keyboard(void)
524 {
525 	keyboard_status.left=0;
526 	keyboard_status.right=0;
527 	keyboard_status.speed=0;
528 	keyboard_status.jump=0;
529 	keyboard_status.creep=0;
530 	keyboard_status.fire=0;
531 	keyboard_status.weapon=0;
532 	keyboard_status.down_ladder=0;
533 }
534 
535 /* recompute object positions */
update_game(void)536 void update_game(void)
537 {
538 	struct object_list *p;
539 	int w,h;
540 	unsigned char stop_x,stop_y,sy;
541 	unsigned long_long t;
542 	my_double x,y,x1,y1,DELTA_TIME;
543 
544 	for(p=&objects;p->next;p=p->next)
545 	{
546 		if (p->next->member.type==T_NOTHING)continue;
547 		if ((p->next->member.status)&1024)continue;   /* dead player */
548 		/* decrement time to live */
549 		if (p->next->member.ttl>0)
550 		{
551 			p->next->member.ttl--;
552 			if (!p->next->member.ttl)
553 			{
554 				if ((p->next->member.type)==T_PLAYER)p->next->member.status&=~16;
555 				else
556 				{
557 					if (p->next->member.type!=T_GRENADE){  /* client's waiting for P_EXPLODE_GRENADE and doesn't delete the grenade yet */
558 		                        p=p->prev;
559 					delete_obj(p->next->next->member.id);
560 					continue;}
561 				}
562 			}
563 		}
564 		/* maintain only objects that you are allowed to maintain */
565 		if (!(obj_attr[p->next->member.type].maintainer&1))continue;
566 
567 
568 		/* if not falling slow down x motion */
569 		if (!(p->next->member.status&8))p->next->member.xspeed=mul(p->next->member.xspeed,obj_attr[p->next->member.type].slow_down_x);
570 
571 		/* fall */
572 		if (obj_attr[p->next->member.type].fall)
573 		{
574 			p->next->member.status|=8;
575 			p->next->member.yspeed+=FALL_ACCEL;
576 			/* but not too fast */
577 			if (p->next->member.yspeed>MAX_Y_SPEED)p->next->member.yspeed=MAX_Y_SPEED;
578 		}
579 
580                 get_dimensions(p->next->member.type,p->next->member.status,sprites[p->next->member.sprite].positions,&w,&h);
581                 x=p->next->member.x;
582                 y=p->next->member.y;
583 		t=get_time();
584 		DELTA_TIME=float2double(((double)(long_long)(t-p->next->member.last_updated))/MICROSECONDS);
585                 update_position(
586                         &(p->next->member),
587                         p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
588                         p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
589                         w,h,&stop_x,&stop_y);
590 		p->next->member.last_updated=t;
591 
592 		/* walk up the stairs */
593 		if (stop_x&&p->next->member.type==T_PLAYER&&!(p->next->member.status&256))
594 		{
595 			x1=p->next->member.x;
596 			y1=p->next->member.y;
597 			p->next->member.x=x;
598 			p->next->member.y=y-int2double(1);
599 	                update_position(
600         	                &(p->next->member),
601                 	        p->next->member.x+mul(p->next->member.xspeed,DELTA_TIME),
602                         	p->next->member.y+mul(p->next->member.yspeed,DELTA_TIME),
603 	                        w,h,0,&sy);
604 			if ((p->next->member.xspeed>0&&p->next->member.x<=x1)||(p->next->member.xspeed<0&&p->next->member.x>=x1)) /* restore original values */
605 			{
606 				p->next->member.x=x1;
607 				p->next->member.y=y1;
608 			}
609 			else
610 			{
611 				stop_y=sy;
612 				stop_x=0;
613 			}
614 		}
615 
616 		if (stop_x)p->next->member.xspeed=-mul(p->next->member.xspeed,obj_attr[p->next->member.type].bounce_x);
617 		if (my_abs(p->next->member.xspeed)<MIN_X_SPEED)
618 		{
619 			p->next->member.xspeed=0;
620 			p->next->member.status&=~1;
621 		}
622 
623 
624 		if (stop_y)
625 		{
626 			p->next->member.yspeed=mul(p->next->member.yspeed,obj_attr[p->next->member.type].bounce_y);
627 			p->next->member.yspeed=-p->next->member.yspeed;
628 			if (my_abs(p->next->member.yspeed)<MIN_Y_SPEED)
629 			{
630 				p->next->member.yspeed=0;
631 				if (stop_y==1)p->next->member.status&=~8;
632 			}
633 		}
634 
635 		if ((p->next->member.type==T_SHRAPNEL||p->next->member.type==T_BULLET)&&(stop_x||stop_y))  /* bullet and shrapnel die crashing into wall */
636 		{
637 			p=p->prev;  /* deleting object makes a great mess in for cycle, so we must cheat the cycle */
638 			delete_obj(p->next->next->member.id);
639 			continue;
640 		}
641 
642 	}
643 }
644 
645 #define FIRE_SHOOTING weapon[current_weapon].cadence-4+HOLD_GUN_AFTER_SHOOT
646 
647 /* hero's next anim position when walking to the right */
_next_anim_right(int pos,int status,int ttl)648 int _next_anim_right(int pos,int status, int ttl)
649 {
650 	int start,offset;
651 
652 	if (pos<=18)start=10;  /* normal */
653 	else
654 	{
655 		if (pos<=46)start=38; /* holding gun */
656 		else
657 		{
658 			if (pos<=55)start=47; /* shooting */
659 			else start=64;  /* creeping */
660 		}
661 	}
662 	offset=pos-start;
663 
664 	if (status&256)start=64;  /* creeping */
665 	else
666 	{
667 		if (status&16)
668 		{
669 			if (ttl>=FIRE_SHOOTING) start=47;  /* shooting */
670 			else start=38; /* holding a gun */
671 		}
672 		else start=10; /* normal */
673 	}
674 
675 	return (status&256)?((offset+1)&7)+start:start+(offset&7)+1;
676 }
677 
678 
679 /* hero's next anim position when walking to the left */
_next_anim_left(int pos,int status,int ttl)680 int _next_anim_left(int pos,int status, int ttl)
681 {
682 	int start,offset;
683 
684 	if (pos<=8)start=0;  /* normal */
685 	else
686 	{
687 		if (pos<=28)start=20; /* holding gun */
688 		else
689 		{
690 			if (pos<=37)start=29; /* shooting */
691 			else start=56; /* creeping */
692 		}
693 	}
694 	offset=pos-start;
695 
696 	if (status&256)start=56; /* creeping */
697 	else
698 	{
699 		if (status&16)
700 		{
701 			if (ttl>=FIRE_SHOOTING) start=29;  /* shooting */
702 			else start=20; /* holding a gun */
703 		}
704 		else start=0; /* normal */
705 	}
706 
707 	return (status&256)?((offset+1)&7)+start:start+(offset&7)+1;
708 }
709 
710 
711 /* update hero animating position */
update_anim(struct it * obj)712 void update_anim(struct it* obj)
713 {
714 	if (!(obj->status&1))  /* not walking */
715 		switch((obj->status&6)>>1)
716 		{
717 			case 0:  /* look at me */
718 			obj->anim_pos=(obj->status&256)?72:9;
719 			break;
720 			case 1:   /* look left */
721 			if (obj->status&16)
722 			{
723 				if (obj->status&512)
724 				{
725 					if (obj->ttl>=((weapon[WEAPON_GRENADE].cadence>>1)+HOLD_GUN_AFTER_SHOOT))obj->anim_pos=73;
726 					else
727 					{
728 						if (obj->ttl>=((weapon[WEAPON_GRENADE].cadence>>2)+HOLD_GUN_AFTER_SHOOT))obj->anim_pos=74;
729 						else
730 						{
731 							if (obj->ttl>=HOLD_GUN_AFTER_SHOOT)obj->anim_pos=75;
732 							else obj->anim_pos=0;
733 						}
734 					}
735 				}
736 				else
737 				{
738 					if (obj->ttl>=FIRE_SHOOTING)obj->anim_pos=29;
739 					else obj->anim_pos=20;
740 				}
741 			}
742 			else obj->anim_pos=0;
743 			if (obj->status&256)obj->anim_pos=56;
744 			break;
745 			case 2:   /* look right */
746 			if (obj->status&16)
747 			{
748 				if (obj->status&512)
749 				{
750 					if (obj->ttl>=((weapon[WEAPON_GRENADE].cadence>>1)+HOLD_GUN_AFTER_SHOOT))obj->anim_pos=76;
751 					else
752 					{
753 						if (obj->ttl>=((weapon[WEAPON_GRENADE].cadence>>2)+HOLD_GUN_AFTER_SHOOT))obj->anim_pos=77;
754 						else
755 						{
756 							if (obj->ttl>=HOLD_GUN_AFTER_SHOOT)obj->anim_pos=78;
757 							else obj->anim_pos=10;
758 						}
759 					}
760 				}
761 				else
762 				{
763 					if (obj->ttl>=FIRE_SHOOTING)obj->anim_pos=47;
764 					else obj->anim_pos=38;
765 				}
766 			}
767 			else obj->anim_pos=10;
768 			if (obj->status&256)obj->anim_pos=64;
769 			break;
770 		}
771 	else  /* walking */
772 	{
773 		switch((obj->status&6)>>1)
774 		{
775 			case 1:  /* walk left */
776 			obj->anim_pos=_next_anim_left(obj->anim_pos,obj->status,obj->ttl);
777 			break;
778 
779 			case 2:   /* walk right */
780 			obj->anim_pos=_next_anim_right(obj->anim_pos,obj->status,obj->ttl);
781 			break;
782 		}
783 	}
784 }
785 
786 
787 /* draw scene into screenbuffer*/
draw_scene(void)788 void draw_scene(void)
789 {
790 	struct object_list *p;
791 	unsigned char fore;
792 
793 #ifdef TRI_D
794 	if (TRI_D_ON)
795 	{
796 		tri_d=1;
797 		show_window(double2int(hero->x)-SCREEN_XOFFSET,double2int(hero->y)-SCREEN_YOFFSET);
798 		tri_d=0;
799 	}
800 #endif
801 
802 	show_window(double2int(hero->x)-SCREEN_XOFFSET,double2int(hero->y)-SCREEN_YOFFSET);
803 	for (fore=0;fore<=1;fore++)
804 	{
805 		for(p=&objects;p->next;p=p->next)
806 		{
807 			if ((obj_attr[p->next->member.type].foreground)!=fore)continue;
808 			if (&(p->next->member)==hero)continue;
809 			if (p->next->member.type==T_PLAYER)update_anim(&(p->next->member));
810 			else {p->next->member.anim_pos++;p->next->member.anim_pos%=sprites[p->next->member.sprite].n_steps;}
811 			if (!(p->next->member.status&1024)&&!(p->next->member.status&64))   /* don't draw hidden objects and dead players */
812 			{
813 #ifdef TRI_D
814 				if(TRI_D_ON)
815 				{
816 					tri_d=1;
817 					put_sprite(
818 						double2int(p->next->member.x-hero->x)+fore+SCREEN_XOFFSET,
819 						double2int(p->next->member.y-hero->y)+SCREEN_YOFFSET,
820 						sprites[p->next->member.sprite].positions+sprites[p->next->member.sprite].steps[p->next->member.anim_pos],
821 						1
822 						);
823 					tri_d=0;
824 				}
825 #endif
826 
827 				put_sprite(
828 					double2int(p->next->member.x-hero->x)+SCREEN_XOFFSET,
829 					double2int(p->next->member.y-hero->y)+SCREEN_YOFFSET,
830 					sprites[p->next->member.sprite].positions+sprites[p->next->member.sprite].steps[p->next->member.anim_pos],
831 					1
832 					);
833 			}
834 			if (p->next->member.type==T_PLAYER&&p->next->member.status&128) /* hit */
835 			{
836 				p->next->member.status&=~128;
837 				if (!(p->next->member.status&1024))   /* don't draw blood splash to dead players */
838 				{
839 #ifdef TRI_D
840 					if (TRI_D_ON)
841 					{
842 						tri_d=1;
843 						put_sprite(
844 							double2int(p->next->member.x-hero->x)+SCREEN_XOFFSET+fore+((int)(p->next->member.data)&255),
845 							double2int(p->next->member.y-hero->y)+SCREEN_YOFFSET+(((int)(p->next->member.data)>>8)&255),
846 							sprites[hit_sprite].positions+sprites[hit_sprite].steps[((int)p->next->member.data)>>16],
847 							1
848 							);
849 						tri_d=0;
850 					}
851 #endif
852 
853 					put_sprite(
854 						double2int(p->next->member.x-hero->x)+SCREEN_XOFFSET+((int)(p->next->member.data)&255),
855 						double2int(p->next->member.y-hero->y)+SCREEN_YOFFSET+(((int)(p->next->member.data)>>8)&255),
856 						sprites[hit_sprite].positions+sprites[hit_sprite].steps[((int)p->next->member.data)>>16],
857 						1
858 						);
859 				}
860 			}
861 		}
862 		if (obj_attr[T_PLAYER].foreground!=fore)continue;
863 		update_anim(hero);
864 		if ((hero->status)&1024)continue;   /* don't draw dead hero */
865 #ifdef TRI_D
866 		if (TRI_D_ON)
867 		{
868 			tri_d=1;
869 			put_sprite(
870 				SCREEN_XOFFSET,
871 				SCREEN_YOFFSET,
872 				sprites[hero->sprite].positions+sprites[hero->sprite].steps[hero->anim_pos],
873 				1
874 				);
875 			tri_d=0;
876 		}
877 #endif
878 		put_sprite(
879 			SCREEN_XOFFSET,
880 			SCREEN_YOFFSET,
881 			sprites[hero->sprite].positions+sprites[hero->sprite].steps[hero->anim_pos],
882 			1
883 			);
884 		if (hero->status&128) /* hit */
885 		{
886 			hero->status&=~128;
887 #ifdef TRI_D
888 			if (TRI_D_ON)
889 			{
890 				tri_d=1;
891 				put_sprite(
892 					SCREEN_XOFFSET+((int)(hero->data)&255),
893 					SCREEN_YOFFSET+(((int)(hero->data)>>8)&255),
894 					sprites[hit_sprite].positions+sprites[hit_sprite].steps[((int)hero->data)>>16],
895 					1
896 					);
897 				tri_d=0;
898 			}
899 #endif
900 			put_sprite(
901 				SCREEN_XOFFSET+((int)(hero->data)&255),
902 				SCREEN_YOFFSET+(((int)(hero->data)>>8)&255),
903 				sprites[hit_sprite].positions+sprites[hit_sprite].steps[((int)hero->data)>>16],
904 				1
905 				);
906 		}
907 	}
908 }
909 
910 
change_level(void)911 void change_level(void)
912 {
913 	unsigned char *LEVEL;
914 	unsigned char txt[256];
915 
916 	clean_memory();
917 	free_sprites(level_sprites_start);
918 	reinit_area();
919 
920 	LEVEL=load_level(level_number);
921 	snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,LEVEL_SPRITES_SUFFIX);
922 	load_sprites(txt);
923 	snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
924 	load_data(txt);
925 	mem_free(LEVEL);
926 }
927 
928 
929 /* returns number of read bytes */
process_packet(unsigned char * packet,int l)930 int process_packet(unsigned char *packet,int l)
931 {
932 	int a,n=l;
933 
934 	switch(*packet)
935 	{
936 		case P_CHUNK:
937 		for (a=1;a<l&&a<MAX_PACKET_LENGTH;a+=n)
938 			n=process_packet(packet+a,l-a);
939 		break;
940 
941 		case P_NEW_OBJ:
942 		if (l<28)break;  /* invalid packet */
943 		n=28;
944 		new_obj(
945 			get_int(packet+1), /* ID */
946 			packet[25],  /* type */
947 			get_int16(packet+26), /* time to live */
948 			get_int16(packet+5),  /* sprite */
949 			0, /* anim position */
950 			get_int16(packet+23),  /* status */
951 			get_float(packet+7),  /* x */
952 			get_float(packet+11),  /* y */
953 			get_float(packet+15),  /* xspeed */
954 			get_float(packet+19),  /* yspeed */
955 			0  /* data */
956 		);
957 		break;
958 
959 		case P_PLAYER_DELETED:
960 		n=1;
961 		*error_message=0;
962 		return -1;
963 
964 		case P_DELETE_OBJECT:
965 		if (l<5)break;  /* invalid packet */
966 		delete_obj(get_int(packet+1));
967 		n=5;
968 		break;
969 
970 		case P_UPDATE_OBJECT:
971 		if (l<26)break;   /* invalid packet */
972 		{
973 			struct object_list *p;
974 
975 			n=26;
976 			p=find_in_table(get_int(packet+1));
977 			if (!p)break;
978 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
979 			p->member.update_counter=packet[5];
980 			p->member.x=get_float(packet+6);
981 			p->member.y=get_float(packet+10);
982 			p->member.xspeed=get_float(packet+14);
983 			p->member.yspeed=get_float(packet+18);
984 			p->member.status=get_int16(packet+22);
985 			p->member.data=0;
986 			p->member.ttl=get_int16(packet+24);
987 			/* kdyz tasi, tak se nahodi ttl */
988 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
989 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
990 		}
991 		break;
992 
993 		case P_UPDATE_OBJECT_POS:
994 		if (l<22)break;   /* invalid packet */
995 		{
996 			struct object_list *p;
997 
998 			n=22;
999 			p=find_in_table(get_int(packet+1));
1000 			if (!p)break;
1001 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1002 			p->member.update_counter=packet[5];
1003 			p->member.x=get_float(packet+6);
1004 			p->member.y=get_float(packet+10);
1005 			p->member.xspeed=get_float(packet+14);
1006 			p->member.yspeed=get_float(packet+18);
1007 		}
1008 		break;
1009 
1010 		case P_UPDATE_OBJECT_SPEED:
1011 		if (l<14)break;   /* invalid packet */
1012 		{
1013 			struct object_list *p;
1014 
1015 			n=14;
1016 			p=find_in_table(get_int(packet+1));
1017 			if (!p)break;
1018 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1019 			p->member.update_counter=packet[5];
1020 			p->member.xspeed=get_float(packet+6);
1021 			p->member.yspeed=get_float(packet+10);
1022 		}
1023 		break;
1024 
1025 		case P_UPDATE_OBJECT_COORDS:
1026 		if (l<14)break;   /* invalid packet */
1027 		{
1028 			struct object_list *p;
1029 
1030 			n=14;
1031 			p=find_in_table(get_int(packet+1));
1032 			if (!p)break;
1033 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1034 			p->member.update_counter=packet[5];
1035 			p->member.x=get_float(packet+6);
1036 			p->member.y=get_float(packet+10);
1037 		}
1038 		break;
1039 
1040 		case P_UPDATE_OBJECT_SPEED_STATUS:
1041 		if (l<16)break;   /* invalid packet */
1042 		{
1043 			struct object_list *p;
1044 
1045 			n=16;
1046 			p=find_in_table(get_int(packet+1));
1047 			if (!p)break;
1048 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1049 			p->member.update_counter=packet[5];
1050 			p->member.xspeed=get_float(packet+6);
1051 			p->member.yspeed=get_float(packet+10);
1052 			p->member.status=get_int16(packet+14);
1053 			/* kdyz tasi, tak se nahodi ttl */
1054 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
1055 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
1056 		}
1057 		break;
1058 
1059 		case P_UPDATE_OBJECT_COORDS_STATUS:
1060 		if (l<16)break;   /* invalid packet */
1061 		{
1062 			struct object_list *p;
1063 
1064 			n=16;
1065 			p=find_in_table(get_int(packet+1));
1066 			if (!p)break;
1067 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1068 			p->member.update_counter=packet[5];
1069 			p->member.x=get_float(packet+6);
1070 			p->member.y=get_float(packet+10);
1071 			p->member.status=get_int16(packet+14);
1072 			/* kdyz tasi, tak se nahodi ttl */
1073 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
1074 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
1075 		}
1076 		break;
1077 
1078 		case P_UPDATE_OBJECT_SPEED_STATUS_TTL:
1079 		if (l<18)break;   /* invalid packet */
1080 		{
1081 			struct object_list *p;
1082 
1083 			n=18;
1084 			p=find_in_table(get_int(packet+1));
1085 			if (!p)break;
1086 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1087 			p->member.update_counter=packet[5];
1088 			p->member.xspeed=get_float(packet+6);
1089 			p->member.yspeed=get_float(packet+10);
1090 			p->member.status=get_int16(packet+14);
1091 			p->member.ttl=get_int16(packet+16);
1092 			/* kdyz tasi, tak se nahodi ttl */
1093 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
1094 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
1095 		}
1096 		break;
1097 
1098 		case P_UPDATE_OBJECT_COORDS_STATUS_TTL:
1099 		if (l<18)break;   /* invalid packet */
1100 		{
1101 			struct object_list *p;
1102 
1103 			n=18;
1104 			p=find_in_table(get_int(packet+1));
1105 			if (!p)break;
1106 			if(packet[5]-(p->member.update_counter)>127)break; /* throw out old updates */
1107 			p->member.update_counter=packet[5];
1108 			p->member.x=get_float(packet+6);
1109 			p->member.y=get_float(packet+10);
1110 			p->member.status=get_int16(packet+14);
1111 			p->member.ttl=get_int16(packet+16);
1112 			/* kdyz tasi, tak se nahodi ttl */
1113 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
1114 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
1115 		}
1116 		break;
1117 
1118 		case P_UPDATE_STATUS:
1119 		if (l<7)break;   /* invalid packet */
1120 		{
1121 			struct object_list *p;
1122 
1123 			n=7;
1124 			p=find_in_table(get_int(packet+1));
1125 			if (!p)break;  /* ignore objects we don't have */
1126 			p->member.status=get_int16(packet+5);
1127 			/* kdyz tasi, tak se nahodi ttl */
1128 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
1129 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
1130 		}
1131 		break;
1132 
1133 		case P_HIT:
1134 		if (l<8)break;    /* invalid packet */
1135 		{
1136 			struct object_list *p;
1137 
1138 			n=8;
1139 			p=find_in_table(get_int(packet+1));
1140 			if (!p)break;  /* ignore objects we don't have */
1141 			p->member.status|=128;
1142 			p->member.data=(void*)((packet[5]<<16)+(packet[7]<<8)+(packet[6]));
1143 			/* kdyz tasi, tak se nahodi ttl */
1144 			if (p->member.type==T_PLAYER&&(p->member.status&32)&&(p->member.status&16))
1145 				p->member.ttl=weapon[current_weapon].cadence+HOLD_GUN_AFTER_SHOOT;
1146 		}
1147 		break;
1148 
1149 		case P_UPDATE_PLAYER:
1150 		if (l<23)break;  /* invalid packet */
1151 		health=packet[1];
1152 		armor=packet[2];
1153 		for (a=0;a<ARMS;a++)
1154 			ammo[a]=get_int16(packet+3+(a<<1));
1155 		frags=get_int(packet+3+ARMS*2);
1156 		deaths=get_int(packet+7+ARMS*2);
1157 		current_weapon=packet[11+2*ARMS];
1158 		weapons=packet[12+2*ARMS];
1159 		n=23;
1160 		break;
1161 
1162 		case P_MESSAGE:
1163 		if (l<2)break;   /* invalid packet */
1164 		add_message(packet+1);
1165 		n=2+strlen(packet+1);
1166 		break;
1167 
1168 		case P_CHANGE_LEVEL:
1169 		{
1170 			unsigned char txt[256];
1171 			unsigned char *name;
1172 			unsigned char *md5;
1173 			int a;
1174 			char p;
1175 
1176 			if (l<38)break;   /* invalid packet */
1177 			a=get_int(packet+1);
1178 			if (level_number==a)goto level_changed;
1179 			level_number=a;
1180 			snprintf(txt,256, "Trying to change level to number %d",level_number);
1181 			add_message(txt);
1182 			name=load_level(level_number);
1183 			if (!name){snprintf(error_message,1024,"Cannot find level number %d. Game terminated. Press ENTER.", level_number);send_quit();return -1;}
1184 			snprintf(txt,256,"Changing level to \"%s\"",name);
1185 			mem_free(name);
1186 			add_message(txt);
1187 
1188 			md5=md5_level(level_number);
1189 			if (strcmp(md5,packet+5))   /* MD5s differ */
1190 			{
1191 				mem_free(md5);
1192 				snprintf(error_message,1024,"Invalid MD5 sum. Can't change level. Game terminated. Press ENTER.");
1193 				add_message("Invalid MD5 sum. Can't change level. Exiting...");
1194 				send_quit();
1195 				return -1;
1196 			}
1197 			mem_free(md5);
1198 
1199 			/* OK we can change it */
1200 			change_level();
1201 level_changed:
1202 
1203 			p=P_LEVEL_ACCEPTED;
1204 			send_packet(&p,1,(struct sockaddr *)(&server),my_id,0);
1205 			n=38;
1206 		}
1207 		break;
1208 
1209 		case P_END:
1210 		if (l<2)snprintf(error_message,1024,"Game terminated. Press ENTER.");
1211 		else snprintf(error_message,1024,"Game terminated by %s. Press ENTER.",packet+1);
1212 		return -1;
1213 
1214 		case P_BELL:
1215 		n=1;
1216 		c_bell();
1217 		break;
1218 
1219 		case P_INFO:
1220 		if (l<=5)break;
1221 		active_players=get_int(packet+1);
1222 		l=6;
1223 		for (a=0;a<packet[5]&&a<TOP_PLAYERS_N;a++)
1224 		{
1225 			int x;
1226 			top_players[a].frags=get_int(packet+l);
1227 			top_players[a].deaths=get_int(packet+l+4);
1228 			top_players[a].color=packet[l+8];
1229 			x=strlen(packet+l+9)+1;
1230 			memcpy(top_players[a].name,packet+l+9,x);
1231 			l+=x+9;
1232 		}
1233 		n=l;
1234 		break;
1235 
1236 		case P_EXPLODE_GRENADE:
1237 		{
1238 			unsigned int i,j;
1239 			struct object_list *p;
1240 			int b;
1241 
1242 			if (l<9)break;
1243 			n=9;
1244 			i=get_int(packet+1);
1245 			j=get_int(packet+5);
1246 			p=find_in_table(j);
1247 			if (!p)break;
1248 
1249 			for (b=0;b<N_SHRAPNELS_EXPLODE;b++)
1250 			{
1251 				double angle=(double)b*2*M_PI/N_SHRAPNELS_EXPLODE;
1252 				my_double spd=add_int(mul_int(my_and(mul_int(weapon[WEAPON_GRENADE].speed,b+1),15),16),100);
1253 
1254 				new_obj(
1255 					i,
1256 					T_SHRAPNEL,
1257 					SHRAPNEL_TTL,
1258 					shrapnel_sprite[random()%N_SHRAPNELS],
1259 					0,
1260 					WEAPON_GRENADE,
1261 					p->member.x,
1262 					p->member.y,
1263 					p->member.xspeed+mul(spd,float2double(cos(angle))),
1264 					p->member.yspeed+mul(spd,float2double(sin(angle))),
1265 					0);
1266 				i++;
1267 			}
1268 			delete_obj(j);
1269 
1270 		}
1271 		break;
1272 	}
1273 	return n;
1274 }
1275 
1276 
1277 /* read packet from socket */
read_data(void)1278 int read_data(void)
1279 {
1280         fd_set rfds;
1281         struct timeval tv;
1282         struct sockaddr_in client;
1283         static unsigned char packet[MAX_PACKET_LENGTH];
1284         int a=sizeof(client);
1285 	int l;
1286 
1287         tv.tv_sec=0;
1288         tv.tv_usec=0;
1289         FD_ZERO(&rfds);
1290         FD_SET(fd,&rfds);
1291 	while(select(fd+1,&rfds,0,0,&tv))
1292 	{
1293 	        if ((l=recv_packet(packet,MAX_PACKET_LENGTH,(struct sockaddr*)(&client),&a,1,my_id,0))<0)
1294 			return 0;   /* something's strange */
1295 		if (process_packet(packet,l)<0)return 1;
1296 
1297 	}
1298 	return 0;
1299 }
1300 
1301 
1302 /* select color for numeric value (red=lack, yellow=edium, green=fill) */
select_color(int value,int max)1303 int select_color(int value,int max)
1304 {
1305 	return value>=(max>>1)?10:(value>=(max>>2)?11:9);
1306 }
1307 
1308 
1309 /* draw board at the bottom of the screen */
draw_board(void)1310 void draw_board(void)
1311 {
1312 	int offs=SCREEN_X*(SCREEN_Y-2);
1313 	int space=(SCREEN_X-60)/5;
1314 	char txt[16];
1315 
1316 	memset(screen_a+offs,4,SCREEN_X);
1317 	memset(screen+offs,'-',SCREEN_X);
1318 	memset(screen+offs+SCREEN_X,0,SCREEN_X);
1319 	print2screen(0,SCREEN_Y-1,7,"HEALTH");
1320 	sprintf(txt,"% 3d%%",health);
1321 	print2screen(6,SCREEN_Y-1,select_color(health,100),txt);
1322 
1323 	print2screen(11+(space>>1),SCREEN_Y-2,4,",");
1324 	print2screen(11+(space>>1),SCREEN_Y-1,4,"|");
1325 	print2screen(11+space,SCREEN_Y-1,7,"FRAGS");
1326 	sprintf(txt,"% 4d",frags);
1327 	print2screen(11+space+6,SCREEN_Y-1,11,txt);
1328 
1329 	print2screen(21+space+(space>>1),SCREEN_Y-2,4,",");
1330 	print2screen(21+space+(space>>1),SCREEN_Y-1,4,"|");
1331 	print2screen(21+(space<<1),SCREEN_Y-1,7,"DEATHS");
1332 	sprintf(txt,"% 4d",deaths);
1333 	print2screen(21+(space<<1)+7,SCREEN_Y-1,11,txt);
1334 
1335 	print2screen(31+(space<<1)+(space>>1),SCREEN_Y-2,4,",");
1336 	print2screen(31+(space<<1)+(space>>1),SCREEN_Y-1,4,"|");
1337 	sprintf(txt,"%10s",weapon[current_weapon].name);
1338 	print2screen(31+3*space,SCREEN_Y-1,11,txt);
1339 
1340 	print2screen(41+(3*space)+(space>>1),SCREEN_Y-2,4,",");
1341 	print2screen(41+(3*space)+(space>>1),SCREEN_Y-1,4,"|");
1342 	print2screen(41+(space<<2),SCREEN_Y-1,7,"AMMO");
1343 	sprintf(txt,"% 4d",ammo[current_weapon]);
1344 	print2screen(41+5+(space<<2),SCREEN_Y-1,select_color(ammo[current_weapon],weapon[current_weapon].max_ammo),txt);
1345 
1346 	print2screen(49+(space<<2)+(space>>1),SCREEN_Y-2,4,",");
1347 	print2screen(49+(space<<2)+(space>>1),SCREEN_Y-1,4,"|");
1348 	print2screen(49+5*space,SCREEN_Y-1,7,"ARMOR");
1349 	sprintf(txt,"% 4d%%",armor);
1350 	print2screen(49+5+5*space,SCREEN_Y-1,select_color(armor,100),txt);
1351 	if ((hero->status)&64)print2screen(SCREEN_X-14,SCREEN_Y-2,11,"INVISIBILITY");
1352 	if (autorun)print2screen(2,SCREEN_Y-2,15,"AUTORUN");
1353 	if (autocreep)print2screen(10,SCREEN_Y-2,15,"AUTOCREEP");
1354 }
1355 
1356 
1357 /* read string from input, returns everytime, not when string's read */
read_str_online(int y,char * pointer,char * message,int max_len)1358 int read_str_online(int y,char *pointer,char *message, int max_len)
1359 {
1360 	int a,b,c,shift=0;
1361 
1362 	a=strlen(message);
1363 	b=strlen(pointer);
1364 	c=SCREEN_X*y;
1365 
1366 #ifdef TRI_D
1367 	if (TRI_D_ON)
1368 	{
1369 		memcpy(screen2+c,message,a);
1370 		memcpy(screen2+c+a,pointer,b);
1371 		memset(screen2_a+c,15,a);
1372 		memset(screen2_a+c+a,7,b);
1373 		memset(screen2_a+c+a+b,0,SCREEN_X-b-a);
1374 	}
1375 #endif
1376 
1377 	memcpy(screen+c,message,a);
1378 	memcpy(screen+c+a,pointer,b);
1379 	memset(screen_a+c,15,a);
1380 	memset(screen_a+c+a,7,b);
1381 	memset(screen_a+c+a+b,0,SCREEN_X-b-a);
1382 
1383 	c_update_kbd();
1384 
1385 	if (c_was_pressed(K_ESCAPE))
1386 	{
1387 		pointer[0]=0;
1388 		return 2;
1389 	}
1390 	if (c_was_pressed(K_ENTER))
1391 	{
1392 		return 1;
1393 	}
1394 	if (c_pressed(K_BACKSPACE)&&b)
1395 	{
1396 		b--;
1397 		pointer[b]=0;
1398 	}
1399 	shift=c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT);
1400 	for (c=' ';c<128&&b<max_len;c++)
1401 		if (c_was_pressed(c))
1402 		{
1403 			pointer[b]=shift?my_toupper(c):c;
1404 			b++;
1405 			pointer[b]=0;
1406 		}
1407 	return 0;
1408 }
1409 
1410 
1411 /* read number from input, returns everytime, not when number's read */
read_num_online(int y,char * pointer,char * message,int max_len)1412 int read_num_online(int y,char *pointer,char *message, int max_len)
1413 {
1414 	int a,b,c;
1415 
1416 	a=strlen(message);
1417 	b=strlen(pointer);
1418 	c=SCREEN_X*y;
1419 
1420 #ifdef TRI_D
1421 	if (TRI_D_ON)
1422 	{
1423 		memcpy(screen2+c,message,a);
1424 		memcpy(screen2+c+a,pointer,b);
1425 		memset(screen2_a+c,15,a);
1426 		memset(screen2_a+c+a,7,b);
1427 		memset(screen2_a+c+a+b,0,SCREEN_X-b-a);
1428 	}
1429 #endif
1430 
1431 	memcpy(screen+c,message,a);
1432 	memcpy(screen+c+a,pointer,b);
1433 	memset(screen_a+c,15,a);
1434 	memset(screen_a+c+a,7,b);
1435 	memset(screen_a+c+a+b,0,SCREEN_X-b-a);
1436 
1437 	c_update_kbd();
1438 
1439 	if (c_was_pressed(K_ESCAPE))
1440 	{
1441 		pointer[0]=0;
1442 		return 2;
1443 	}
1444 	if (c_was_pressed(K_ENTER))
1445 	{
1446 		return 1;
1447 	}
1448 	if (c_pressed(K_BACKSPACE)&&b)
1449 	{
1450 		b--;
1451 		pointer[b]=0;
1452 	}
1453 	for (c='0';c<='9'&&b<max_len;c++)
1454 		if (c_was_pressed(c))
1455 		{
1456 			pointer[b]=c;
1457 			b++;
1458 			pointer[b]=0;
1459 		}
1460 	return 0;
1461 }
1462 
1463 
1464 /* load banner.dat */
load_banner(char ** banner)1465 void load_banner(char **banner)
1466 {
1467 	FILE *s;
1468 	char line[1025];
1469 	int a,b;
1470 
1471 	s=fopen(DATA_PATH BANNER_FILE,"r");
1472 	if (!s){shut_down(0);ERROR("Error: Can't load file \""DATA_PATH BANNER_FILE"\".\n");EXIT(1);}
1473 	*banner=mem_alloc(1);
1474 	**banner=0;
1475 	if (!(*banner)){shut_down(0);ERROR("Error: Not enough memory.\n");EXIT(1);}
1476 	while (fgets(line,1024,s))
1477 	{
1478 		if (line[strlen(line)-1]==10)line[strlen(line)-1]=0;
1479 		if (line[strlen(line)-1]==13)line[strlen(line)-1]=0;  /* crlf shit */
1480 		a=strlen(*banner);
1481 		b=strlen(line);
1482 		*banner=mem_realloc((*banner),a+b+SCREEN_X+1);
1483 		memcpy((*banner)+a,line,b);
1484 		memset((*banner)+a+b,' ',SCREEN_X);
1485 		(*banner)[a+b+SCREEN_X]=0;
1486 	}
1487 	fclose(s);
1488 }
1489 
1490 
1491 /* draw initial screen */
menu_screen(char * host,char * name,unsigned short * p,int * color)1492 void menu_screen(char *host,char *name,unsigned short *p,int *color)
1493 {
1494 	char txt[8];
1495 	int sprite,anim=0,title_anim=0,bulge_anim=0;
1496 	unsigned long_long t;
1497 	char port[MAX_PORT_LEN+1];
1498 	int a=0;
1499 	char *m;
1500 	char *color_name[15]={"red","green","brown","blue","violet","cyan","gray","black","light red","light green","yellow","light blue","magenta","light cyan","white"};
1501 	char *banner;
1502 	int l,banner_pos=0;
1503 	int help=0;
1504 
1505 	load_banner(&banner);
1506 	l=strlen(banner);
1507 	sprintf(port,"%d",*p);
1508 	sprintf(txt,"hero%d",*color);
1509 	if (find_sprite(txt,&sprite))
1510 	{
1511 		unsigned char msg[256];
1512 		mem_free(banner);
1513 		shut_down(0);
1514 		snprintf(msg,256,"Error: Can't find sprite \"%s\".\n",txt);
1515 		ERROR(msg);
1516 		EXIT(1);
1517 	}
1518 
1519 cycle:
1520 	t=get_time();
1521 	clear_screen();
1522 #ifdef TRI_D
1523 	if (TRI_D_ON)
1524 	{
1525 		tri_d=1;
1526 		put_sprite((SCREEN_X+1-TITLE_WIDTH)>>1,0,sprites[title_sprite].positions+sprites[title_sprite].steps[title_anim],0);
1527 		put_sprite(SCREEN_XOFFSET+1+PLAYER_WIDTH+((SCREEN_X-SCREEN_XOFFSET-PLAYER_WIDTH-BULGE_WIDTH)>>1),TITLE_HEIGHT+((SCREEN_Y-3-BULGE_HEIGHT-TITLE_HEIGHT)>>1),sprites[bulge_sprite].positions+sprites[bulge_sprite].steps[bulge_anim],0);
1528 		put_sprite(SCREEN_XOFFSET+1,TITLE_HEIGHT+((SCREEN_Y-3-PLAYER_HEIGHT-TITLE_HEIGHT)>>1),sprites[sprite].positions+sprites[sprite].steps[(anim<2?48:39)+(anim&7)],0);
1529 		tri_d=0;
1530 	}
1531 #endif
1532 	put_sprite((SCREEN_X-TITLE_WIDTH)>>1,0,sprites[title_sprite].positions+sprites[title_sprite].steps[title_anim],0);
1533 	put_sprite(SCREEN_XOFFSET+PLAYER_WIDTH+((SCREEN_X-SCREEN_XOFFSET-PLAYER_WIDTH-BULGE_WIDTH)>>1),TITLE_HEIGHT+((SCREEN_Y-3-BULGE_HEIGHT-TITLE_HEIGHT)>>1),sprites[bulge_sprite].positions+sprites[bulge_sprite].steps[bulge_anim],0);
1534 	put_sprite(SCREEN_XOFFSET,TITLE_HEIGHT+((SCREEN_Y-3-PLAYER_HEIGHT-TITLE_HEIGHT)>>1),sprites[sprite].positions+sprites[sprite].steps[(anim<2?48:39)+(anim&7)],0);
1535 	print2screen(0,TITLE_HEIGHT+4,11,"N:");
1536 	print2screen(1,TITLE_HEIGHT+4,2,"AME:");
1537 	print2screen(6,TITLE_HEIGHT+4,7,name);
1538 	print2screen(0,TITLE_HEIGHT+6,2,"COLOR:");
1539 	print2screen(7,TITLE_HEIGHT+6,7,color_name[(*color-1)%15]);
1540 	print2screen(0,TITLE_HEIGHT+0,11,"S");
1541 	print2screen(1,TITLE_HEIGHT+0,2,"ERVER ADDRESS:");
1542 	print2screen(16,TITLE_HEIGHT+0,7,host);
1543 	print2screen(0,TITLE_HEIGHT+2,11,"P");
1544 	print2screen(1,TITLE_HEIGHT+2,2,"ORT:");
1545 	print2screen(6,TITLE_HEIGHT+2,7,port);
1546 	print2screen((SCREEN_X-26)>>1,SCREEN_Y-3,7,"Use arrows to change color");
1547 	print2screen((SCREEN_X-52)>>1,SCREEN_Y-2,7,"Press ENTER to connect, H for help, ESC or Q to quit");
1548 	print2screen(0,SCREEN_Y-1,15,banner+(banner_pos>>1));
1549 	banner_pos++;
1550 	banner_pos%=l<<1;
1551 	anim++;
1552 	anim&=15;
1553 	title_anim++;
1554 	title_anim%=sprites[title_sprite].n_steps;
1555 	bulge_anim++;
1556 	bulge_anim%=sprites[bulge_sprite].n_steps;
1557 	if (*error_message)
1558 	{
1559 		print2screen((SCREEN_X-strlen(error_message)>>1),SCREEN_Y-1,9,error_message);
1560 
1561 #ifdef TRI_D
1562 		if (TRI_D_ON)
1563 		{
1564 			tri_d=1;
1565 			blit_screen(1);
1566 			tri_d=0;
1567 		}
1568 
1569 #endif
1570 		blit_screen(1);
1571 		wait_for_enter();
1572 		*error_message=0;
1573 		goto cc1;
1574 	}
1575 	if (help)print_help_window();
1576 	switch(a)
1577 	{
1578 		case 1:
1579 		if (read_str_online(SCREEN_Y-1,name,"Enter your name: ",MAX_NAME_LEN))
1580 			a=0;
1581 		break;
1582 
1583 		case 3:
1584 		if (read_str_online(SCREEN_Y-1,host,"Enter address: ",MAX_HOST_LEN))
1585 			a=0;
1586 		break;
1587 
1588 		case 2:
1589 		if (read_num_online(SCREEN_Y-1,port,"Enter port: ",MAX_PORT_LEN))
1590 			a=0;
1591 		break;
1592 	}
1593 	c_update_kbd();
1594 
1595 #ifdef TRI_D
1596 	if (TRI_D_ON)
1597 	{
1598 		tri_d=1;
1599 		blit_screen(1);
1600 		tri_d=0;
1601 	}
1602 #endif
1603 
1604 	blit_screen(1);
1605 	if (!a)
1606 	{
1607 		if (c_was_pressed('+')||c_was_pressed('=')||c_was_pressed(K_UP)||c_was_pressed(K_RIGHT)||c_was_pressed(K_NUM_PLUS))
1608 		{
1609 			(*color)++;
1610 			if (*color>30)(*color)=1;
1611 			sprintf(txt,"hero%d",*color);
1612 			if (find_sprite(txt,&sprite))
1613 				{shut_down(0);mem_free(banner);fprintf(stderr,"Error: Can't find sprite \"%s\".\n",txt);}
1614 		}
1615 
1616 		if (c_was_pressed('-')||c_was_pressed(K_NUM_MINUS)||c_was_pressed(K_DOWN)||c_was_pressed(K_LEFT))
1617 		{
1618 			(*color)--;
1619 			if (*color<1)(*color)=30;
1620 			sprintf(txt,"hero%d",*color);
1621 			if (find_sprite(txt,&sprite))
1622 				{shut_down(0);mem_free(banner);fprintf(stderr,"Error: Can't find sprite \"%s\".\n",txt);}
1623 		}
1624 
1625 		if (c_was_pressed('h'))help^=1;
1626 		if (c_was_pressed(K_ENTER))
1627 		{
1628 			save_cfg(host,name,*color);
1629 			*p=strtol(port,0,10);
1630 			if ((m=find_server(host,*p)))
1631 			{
1632 				print2screen((SCREEN_X-strlen(m)>>1),SCREEN_Y-1,9,m);
1633 #ifdef TRI_D
1634 				if (TRI_D_ON)
1635 				{
1636 					tri_d=1;
1637 					blit_screen(1);
1638 					tri_d=0;
1639 				}
1640 #endif
1641 				blit_screen(1);
1642 				wait_for_enter();
1643 				goto cc1;
1644 			}
1645 			if ((m=init_socket()))
1646 			{
1647 				print2screen((SCREEN_X-strlen(m)>>1),SCREEN_Y-1,9,m);
1648 #ifdef TRI_D
1649 				if (TRI_D_ON)
1650 				{
1651 					tri_d=1;
1652 					blit_screen(1);
1653 					tri_d=0;
1654 				}
1655 #endif
1656 				blit_screen(1);
1657 				wait_for_enter();
1658 				goto cc1;
1659 			}
1660 			if ((m=contact_server(*color,name)))
1661 			{
1662 				print2screen((SCREEN_X-strlen(m)>>1),SCREEN_Y-1,9,m);
1663 #ifdef TRI_D
1664 				if (TRI_D_ON)
1665 				{
1666 					tri_d=1;
1667 					blit_screen(1);
1668 					tri_d=0;
1669 				}
1670 #endif
1671 				blit_screen(1);
1672 				wait_for_enter();
1673 				goto cc1;
1674 			}
1675 			mem_free(banner);
1676 			return;
1677 		}
1678 cc1:
1679 		if (c_was_pressed('q')||c_was_pressed(K_ESCAPE))
1680 		{
1681 			save_cfg(host,name,*color);
1682 			mem_free(banner);
1683 			shut_down(1);
1684 		}
1685 
1686 		if (c_was_pressed('n'))
1687 			a=1;
1688 
1689 		if (c_was_pressed('a')||c_was_pressed('s'))
1690 			a=3;
1691 
1692 		if (c_was_pressed('p'))
1693 			a=2;
1694 	}
1695 	sleep_until(t+MENU_PERIOD_USEC);
1696 	goto cycle;
1697 }
1698 
1699 
1700 /* handle fatal signal (sigabrt, sigsegv, ...) */
signal_handler(int signum)1701 void signal_handler(int signum)
1702 {
1703 
1704 	if (connected)send_quit();
1705 	shut_down(0);
1706 #ifdef HAVE_PSIGNAL
1707 	psignal(signum,"Exiting on signal");
1708 #else
1709 	fprintf(stderr, "Exiting on signal: %d\n", signum);
1710 #endif
1711 	EXIT(1);
1712 }
1713 
1714 
1715 /* change size of the screen */
sigwinch_handler(int signum)1716 void sigwinch_handler(int signum)
1717 {
1718 	signum=signum;
1719 	resize_screen();
1720 #ifdef WIN32
1721 	c_shutdown();
1722 	c_init(SCREEN_X,SCREEN_Y);
1723 #endif
1724 	c_cls();
1725 	c_refresh();
1726 #ifndef WIN32
1727 #ifdef SIGWINCH
1728 	signal(SIGWINCH,sigwinch_handler);
1729 #endif
1730 #endif
1731 }
1732 
1733 
1734 /* print command line help */
print_help(void)1735 void print_help(void)
1736 {
1737         printf(
1738 		"0verkill client"
1739 #ifdef XWINDOW
1740 		" for X windows"
1741 #endif
1742 		".\n"
1743                 "(c)2000 Brainsoft\n"
1744                 "Usage: 0verkill [-h] [-3] [-s <width>x<height>]"
1745 #ifdef XWINDOW
1746 		" [-d <display>] [-f <font name>]"
1747 #endif
1748 		"\n"
1749 	);
1750 }
1751 
1752 
parse_dimensions(char * txt)1753 void parse_dimensions(char *txt)
1754 {
1755 	char *p;
1756 	char *e;
1757 	p=txt;
1758 	for (p=txt;(*p)&&(*p)!='x';p++);
1759 	if (!(*p)){ERROR("Error: Expected dimensions in form WIDTHxHEIGHT.\n");EXIT(1);}
1760 	(*p)=0;
1761 	p++;
1762 	if (!strlen(txt)||!strlen(p)){fprintf(stderr,"Error: Decimal number expected.\n");EXIT(1);}
1763 	SCREEN_X=strtoul(txt,&e,10);
1764 	if (*e){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1765 	SCREEN_Y=strtoul(p,&e,10);
1766 	if (*e){ERROR("Error: Decimal number expected.\n");EXIT(1);}
1767 	set_size=1;
1768 }
1769 
1770 
parse_command_line(int argc,char ** argv)1771 void parse_command_line(int argc,char **argv)
1772 {
1773         int a;
1774 
1775         while(1)
1776         {
1777 #ifdef TRI_D
1778 
1779 	#ifdef XWINDOW
1780 		a=getopt(argc,argv,"3hl:f:d:s:");
1781 	#endif
1782 	#ifndef XWINDOW
1783 		a=getopt(argc,argv,"3hl:s:");
1784 	#endif
1785 #else
1786 	#ifdef XWINDOW
1787 		a=getopt(argc,argv,"hf:d:s:");
1788 	#endif
1789 	#ifndef XWINDOW
1790 		a=getopt(argc,argv,"hs:");
1791 	#endif
1792 #endif
1793                 switch(a)
1794                 {
1795                         case EOF:
1796                         return;
1797 
1798                         case '?':
1799                         case ':':
1800                         EXIT(1);
1801 
1802                         case 'h':
1803                         print_help();
1804                         EXIT(0);
1805 
1806 #ifdef TRI_D
1807 			case '3':
1808 			TRI_D_ON=1;
1809 			break;
1810 #endif
1811 
1812                         case 's':
1813 			parse_dimensions(optarg);
1814                         break;
1815 #ifdef XWINDOW
1816 			case 'd':
1817 			x_display_name=optarg;
1818 			break;
1819 
1820 			case 'f':
1821 			x_font_name=optarg;
1822 			break;
1823 #endif
1824                 }
1825         }
1826 }
1827 
1828 
1829 #define HALL_FAME_WIDTH (MAX_NAME_LEN+17)
1830 #define HALL_FAME_HEIGHT ((active_players>TOP_PLAYERS_N?TOP_PLAYERS_N:active_players)+5)
1831 #define HALL_FAME_X ((SCREEN_X-2-HALL_FAME_WIDTH)>>1)
1832 #define HALL_FAME_Y ((SCREEN_Y-2-HALL_FAME_HEIGHT)>>1)
1833 
1834 /* draw window with top players */
print_hall_of_fame(void)1835 void print_hall_of_fame(void)
1836 {
1837 	int a;
1838 	char txt[32];
1839 	unsigned char color;
1840 
1841 	if (!active_players)return;
1842 	sprintf(txt,"TOP %d PLAYERS",TOP_PLAYERS_N);
1843 	draw_frame(HALL_FAME_X,HALL_FAME_Y,HALL_FAME_WIDTH,HALL_FAME_HEIGHT,15);
1844 	print2screen(HALL_FAME_X+1+((HALL_FAME_WIDTH-strlen(txt))>>1),HALL_FAME_Y+1,11,txt);
1845 	print2screen(HALL_FAME_X+2,HALL_FAME_Y+3,15,"NAME");
1846 	print2screen(HALL_FAME_X+2+MAX_NAME_LEN+2,HALL_FAME_Y+3,15,"FRAGS");
1847 	print2screen(HALL_FAME_X+2+MAX_NAME_LEN+9,HALL_FAME_Y+3,15,"DEATHS");
1848 	for (a=0;a<active_players&&a<TOP_PLAYERS_N;a++)
1849 	{
1850 		color=((top_players[a].color-1)%15)+1;
1851 		print2screen(HALL_FAME_X+2,HALL_FAME_Y+4+a,color,top_players[a].name);
1852 		sprintf(txt,"% 5d",top_players[a].frags);
1853 		print2screen(HALL_FAME_X+2+MAX_NAME_LEN+2,HALL_FAME_Y+4+a,color,txt);
1854 		sprintf(txt,"% 5d",top_players[a].deaths);
1855 		print2screen(HALL_FAME_X+2+MAX_NAME_LEN+9,HALL_FAME_Y+4+a,color,txt);
1856 	}
1857 	sprintf(txt,"%d",active_players);
1858 	print2screen(HALL_FAME_X+2,HALL_FAME_Y+HALL_FAME_HEIGHT,11,"Players in the game:");
1859 	print2screen(HALL_FAME_X+23,HALL_FAME_Y+HALL_FAME_HEIGHT,7,txt);
1860 }
1861 
1862 
play(void)1863 void play(void)
1864 {
1865 #ifdef PAUSE
1866 	int p=0;
1867 #endif
1868 	char string[80];
1869 	unsigned char chat=0;
1870 	unsigned char help=0;
1871 	unsigned char hall_fame=0;
1872 	unsigned long_long last_time;
1873 
1874 	last_time=get_time();
1875 	while(1)
1876 	{
1877 		last_time+=CLIENT_PERIOD_USEC;
1878 		if (get_time()-last_time>PERIOD_USEC*100)last_time=get_time();
1879 		if (read_data())return;  /* game terminated */
1880 #ifdef PAUSE
1881 		if(!p)clear_screen();
1882 #else
1883 		clear_screen();
1884 #endif
1885 		update_game();
1886 #ifdef PAUSE
1887 		if (!p)draw_scene();
1888 #else
1889 		draw_scene();
1890 #endif
1891 		update_messages(last_time);
1892 		print_messages();
1893 		if (chat)
1894 		{
1895 			switch (read_str_online(SCREEN_Y-3,string,"> ",78))
1896 			{
1897 				case 2:
1898 				chat=0;
1899 				break;
1900 
1901 				case 1:
1902 				chat=0;
1903 				send_message(string);
1904 				break;
1905 			}
1906 		}
1907 		if (help)print_help_window();
1908 		if (hall_fame)print_hall_of_fame();
1909 		draw_board();
1910 
1911 #ifdef TRI_D
1912 		if (TRI_D_ON)
1913 		{
1914 			tri_d=1;
1915 			blit_screen(1);
1916 			tri_d=0;
1917 		}
1918 #endif
1919 
1920 		blit_screen(1);
1921 
1922 		creep=0;
1923 		if (!chat)c_update_kbd();
1924 
1925 #ifdef PAUSE
1926 		if (c_was_pressed('p'))p^=1;
1927 #endif
1928 		if (!chat&&c_was_pressed('r'))
1929 		{
1930 			c_cls();
1931 			redraw_screen();
1932 		}
1933 		if (!chat&&c_was_pressed('h'))help^=1;
1934 		if (!chat&&c_was_pressed(K_TAB))
1935 		{
1936 			hall_fame^=1;
1937 			if (hall_fame)send_info_request();
1938 		}
1939 		if (c_was_pressed(K_CAPS_LOCK)||(!chat&&c_was_pressed('a')))autorun^=1;
1940 		if (c_was_pressed(K_F10)||(!chat&&c_was_pressed('q')))
1941 		{
1942 			send_quit();
1943 			*error_message=0;
1944 			return;
1945 		}
1946 		if (c_pressed(K_F12))
1947 			end_game();
1948 
1949 		if (!chat && c_was_pressed(K_ENTER))
1950 		{
1951 			memset(string,0,80);
1952 #ifdef WIN32
1953 			c_update_kbd();
1954 			c_was_pressed('d');
1955 #endif
1956 			chat=1;
1957 		}
1958 		reset_keyboard();
1959 		if (!chat&&c_was_pressed(' '))send_reenter_game();
1960 		if (!chat&&c_was_pressed('c'))
1961 			autocreep^=1;
1962 		if (c_pressed(K_DOWN)||autocreep)
1963 			keyboard_status.creep=1;
1964 		if (c_pressed(K_UP))
1965 			keyboard_status.jump=1;
1966 		if (c_pressed(K_LEFT_CTRL)||c_pressed(K_RIGHT_CTRL)||(!chat&&c_pressed('z')))
1967 			keyboard_status.fire=1;
1968 		if (!chat && c_pressed('d'))
1969 				keyboard_status.down_ladder=1;
1970 		if (!chat && c_was_pressed('1'))
1971 			keyboard_status.weapon=1;
1972 		if (!chat && c_was_pressed('2'))
1973 			keyboard_status.weapon=2;
1974 		if (!chat && c_was_pressed('3'))
1975 			keyboard_status.weapon=3;
1976 		if (!chat && c_was_pressed('4'))
1977 			keyboard_status.weapon=4;
1978 		if (!chat && c_was_pressed('5'))
1979 			keyboard_status.weapon=5;
1980 		if (c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT)||autorun)
1981 		keyboard_status.speed=1;
1982 		if (c_pressed(K_LEFT))
1983 			keyboard_status.left=1;
1984 		if (c_pressed(K_RIGHT))
1985 			keyboard_status.right=1;
1986 
1987 		send_keyboard();
1988 		sleep_until(last_time+CLIENT_PERIOD_USEC);
1989 	}
1990 }
1991 
1992 /*----------------------------------------------------------------------------*/
main(int argc,char ** argv)1993 int main(int argc,char **argv)
1994 {
1995 	unsigned short port=DEFAULT_PORT;
1996 	int color=1;
1997 	char host[MAX_HOST_LEN+1];
1998 	char name[MAX_NAME_LEN+1];
1999 	int a;
2000 	unsigned char txt[256];
2001 
2002 
2003 #ifdef WIN32
2004 	WSADATA wd;
2005 
2006 	WSAStartup(0x101, &wd);
2007 	printf("Started WinSock version %X.%02X\n", wd.wVersion/0x100, wd.wVersion&0xFF);
2008 #endif
2009 
2010 
2011 #ifdef XWINDOW
2012 	x_display_name=0;
2013 	x_font_name=0;
2014 #endif
2015 
2016 	last_message=-1;
2017 	autorun=0;
2018 	autocreep=0;
2019 	memset(host,0,MAX_HOST_LEN+1);
2020 	memset(name,0,MAX_NAME_LEN+1);
2021 	load_cfg(host,name,&color);
2022 	last_obj=&objects;
2023 	*error_message=0;
2024 
2025 	parse_command_line(argc,argv);
2026 	hash_table_init();
2027 	if (!set_size)c_get_size(&SCREEN_X,&SCREEN_Y);
2028 	init_sprites();
2029 	init_area();
2030 	load_sprites(DATA_PATH GAME_SPRITES_FILE);
2031 	/* sprites are stored in memory in this order: game sprites (players,
2032 	 * bullets, corpses, blood, meat...) followed by level sprites
2033 	 */
2034 
2035 	level_sprites_start=n_sprites;
2036 	if (find_sprite("hit",&hit_sprite)){ERROR("Error: Can't find sprite \"hit\".\n");EXIT(1);}
2037 	if (find_sprite("title",&title_sprite)){ERROR("Error: Can't find sprite \"title\".\n");EXIT(1);}
2038 	if (find_sprite("bulge",&bulge_sprite)){ERROR("Error: Can't find sprite \"bulge\".\n");EXIT(1);}
2039 	for (a=0;a<N_SHRAPNELS;a++)
2040 	{
2041 		sprintf(txt,"shrapnel%d",a+1);
2042 		if (find_sprite(txt,&shrapnel_sprite[a])){fprintf(stderr,"Can't find sprite \"%s\".\n",txt);EXIT(1);}
2043 	}
2044 
2045 	signal(SIGINT,signal_handler);
2046 	signal(SIGTERM,signal_handler);
2047 	signal(SIGILL,signal_handler);
2048 	signal(SIGABRT,signal_handler);
2049 	signal(SIGFPE,signal_handler);
2050 	signal(SIGSEGV,signal_handler);
2051 #ifndef WIN32
2052 	signal(SIGQUIT,signal_handler);
2053 	signal(SIGBUS,signal_handler);
2054 #ifdef SIGWINCH
2055 	signal(SIGWINCH,sigwinch_handler);
2056 #endif
2057 #endif
2058 	c_init(SCREEN_X,SCREEN_Y);
2059 	c_cls();
2060 	c_cursor(C_HIDE);
2061 	c_refresh();
2062 	while(1)
2063 	{
2064 		level_number=-1;
2065 		connected=0;
2066 		menu_screen(host,name,&port,&color);
2067 		connected=1;
2068 		play();
2069 		clean_memory();
2070 		delete_obj(hero->id);
2071 	}
2072 }
2073