3 * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
5 * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
7 * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
9 * This file is part of Jump'n'Bump.
11 * Jump'n'Bump is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * Jump'n'Bump is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 #define M_PI 3.14159265358979323846
48 gob_t rabbit_gobs = { 0 };
49 gob_t font_gobs = { 0 };
50 gob_t object_gobs = { 0 };
51 gob_t number_gobs = { 0 };
53 main_info_t main_info;
54 player_t player[JNB_MAX_PLAYERS];
55 player_anim_t player_anims[7];
56 object_t objects[NUM_OBJECTS];
60 char datfile_name[2048];
68 unsigned int ban_map[17][22] = {
69 {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
70 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},
71 {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
72 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
73 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
74 {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
75 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
76 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
77 {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
78 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1},
79 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
80 {1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1},
81 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
82 {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
83 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 1, 1},
84 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
85 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
88 #define GET_BAN_MAP_XY(x,y) ban_map[(y) >> 4][(x) >> 4]
213 int flies_enabled = 1;
218 int old_draw_x, old_draw_y;
230 } pobs[NUM_LEFTOVERS];
234 int pogostick, bunnies_in_space, jetpack, lord_of_the_flies, blood_is_thicker_than_water;
238 int filelength(int handle)
242 if (fstat(handle, &buf) == -1) {
243 perror("filelength");
252 /* networking shite. */
254 int client_player_num = -1;
259 TCPsocket sock = NULL;
260 SDLNet_SocketSet socketset = NULL;
266 SDLNet_SocketSet socketset;
269 NetInfo net_info[JNB_MAX_PLAYERS];
281 #define NETPKTBUFSIZE (4 + 4 + 4 + 4 + 4)
283 #define NETCMD_NACK (0xF00DF00D + 0)
284 #define NETCMD_ACK (0xF00DF00D + 1)
285 #define NETCMD_HELLO (0xF00DF00D + 2)
286 #define NETCMD_GREENLIGHT (0xF00DF00D + 3)
287 #define NETCMD_MOVE (0xF00DF00D + 4)
288 #define NETCMD_BYE (0xF00DF00D + 5)
289 #define NETCMD_POSITION (0xF00DF00D + 6)
290 #define NETCMD_ALIVE (0xF00DF00D + 7)
291 #define NETCMD_KILL (0xF00DF00D + 8)
295 void bufToPacket(const char *buf, NetPacket *pkt)
297 SDLNet_Write32(*((Uint32*) (buf + 0)), &pkt->cmd);
298 SDLNet_Write32(*((Uint32*) (buf + 4)), &pkt->arg);
299 SDLNet_Write32(*((Uint32*) (buf + 8)), &pkt->arg2);
300 SDLNet_Write32(*((Uint32*) (buf + 12)), &pkt->arg3);
301 SDLNet_Write32(*((Uint32*) (buf + 16)), &pkt->arg4);
303 pkt->cmd = ntohl(*((unsigned long *) (buf + 0)));
304 pkt->arg = (long) ntohl(*((unsigned long *) (buf + 4)));
305 pkt->arg2 = (long) ntohl(*((unsigned long *) (buf + 8)));
306 pkt->arg3 = (long) ntohl(*((unsigned long *) (buf + 12)));
307 pkt->arg4 = (long) ntohl(*((unsigned long *) (buf + 16)));
312 void packetToBuf(const NetPacket *pkt, char *buf)
314 *((Uint32*) (buf + 0)) = SDLNet_Read32(&pkt->cmd);
315 *((Uint32*) (buf + 4)) = SDLNet_Read32(&pkt->arg);
316 *((Uint32*) (buf + 8)) = SDLNet_Read32(&pkt->arg2);
317 *((Uint32*) (buf + 12)) = SDLNet_Read32(&pkt->arg3);
318 *((Uint32*) (buf + 16)) = SDLNet_Read32(&pkt->arg4);
320 *((unsigned long *) (buf + 0)) = htonl(pkt->cmd);
321 *((unsigned long *) (buf + 4)) = htonl((unsigned long) pkt->arg);
322 *((unsigned long *) (buf + 8)) = htonl((unsigned long) pkt->arg2);
323 *((unsigned long *) (buf + 12)) = htonl((unsigned long) pkt->arg3);
324 *((unsigned long *) (buf + 16)) = htonl((unsigned long) pkt->arg4);
329 void sendPacketToSock(TCPsocket s, NetPacket *pkt)
331 int bytes_left = NETPKTBUFSIZE;
333 char buf[NETPKTBUFSIZE];
336 packetToBuf(pkt, buf);
337 while (bytes_left > 0) {
338 bw = SDLNet_TCP_Send(s, ptr, bytes_left);
340 fprintf(stderr, "SERVER: SDLNet_TCP_Send(): %s\n", SDLNet_GetError());
343 } else if (bw == 0) {
353 void sendPacket(int playerid, NetPacket *pkt)
355 if ( (playerid < JNB_MAX_PLAYERS) && (playerid >= 0)) {
356 if ((player[playerid].enabled) && (playerid != client_player_num)) {
357 sendPacketToSock(net_info[playerid].sock, pkt);
363 void sendPacketToAll(NetPacket *pkt)
367 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
372 /** read a packet from the given TCPsocket
373 Returns -1 if some error occured, 0 if there was no data available and 1 if a
374 packet was successfully read.
375 Note: the socket has to be in the supplied socketset.
376 TODO: this function will bomb if a packet arrives in pieces, there is no
377 inherent guarantee that the next call will be made on the same socket. */
378 int grabPacket(TCPsocket s, SDLNet_SocketSet ss, NetPacket *pkt)
380 static char buf[NETPKTBUFSIZE];
381 static int buf_count = 0;
384 if (SDLNet_CheckSockets(ss, 0) <= 0)
387 if(!SDLNet_SocketReady(s))
390 rc = SDLNet_TCP_Recv(s, &buf[buf_count], NETPKTBUFSIZE - buf_count);
392 /* closed connection? */
394 } else if (rc != NETPKTBUFSIZE) {
395 /* we got a partial packet. Store what we got in the static buffer and
396 return so that the next call can read the rest. Hopefully. */
401 bufToPacket(buf, pkt);
407 int serverRecvPacket(NetPacket *pkt)
414 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
415 TCPsocket s = net_info[i].sock;
417 if ((i == client_player_num) || (!player[i].enabled))
420 rc = grabPacket(s, net_info[i].socketset, pkt);
424 player[i].enabled = 0;
426 pkt.cmd = NETCMD_BYE;
431 sendPacketToAll(&pkt);
433 return(i); /* it's all good. */
437 return(-1); /* no packets available currently. */
441 void wait_for_greenlight(void)
446 printf("CLIENT: Waiting for greenlight...\n");
450 while ((rc = grabPacket(sock, socketset, &pkt)) == 0) {
451 SDL_Delay(100); /* nap and then try again. */
455 printf("CLIENT: Lost connection.\n");
456 SDLNet_TCP_Close(sock);
459 } while (pkt.cmd != NETCMD_GREENLIGHT);
461 printf("CLIENT: Got greenlight.\n");
463 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
464 if (pkt.arg & (1 << i)) {
465 printf("CLIENT: There is a player #%d.\n", i);
466 player[i].enabled = 1;
472 static int buggered_off = 0;
475 void tellServerGoodbye(void)
481 pkt.cmd = NETCMD_BYE;
482 pkt.arg = client_player_num;
486 sendPacketToSock(sock, &pkt);
492 void processMovePacket(NetPacket *pkt)
494 int playerid = pkt->arg;
495 int movetype = ((pkt->arg2 >> 16) & 0xFF);
496 int newval = ((pkt->arg2 >> 0) & 0xFF);
498 if (movetype == MOVEMENT_LEFT) {
499 player[playerid].action_left = newval;
500 } else if (movetype == MOVEMENT_RIGHT) {
501 player[playerid].action_right = newval;
502 } else if (movetype == MOVEMENT_UP) {
503 player[playerid].action_up = newval;
505 printf("bogus MOVE packet!\n");
508 player[playerid].x = pkt->arg3;
509 player[playerid].y = pkt->arg4;
513 void tellServerPlayerMoved(int playerid, int movement_type, int newval)
517 pkt.cmd = NETCMD_MOVE;
519 pkt.arg2 = ( ((movement_type & 0xFF) << 16) | ((newval & 0xFF) << 0) );
520 pkt.arg3 = player[playerid].x;
521 pkt.arg4 = player[playerid].y;
524 processMovePacket(&pkt);
527 sendPacketToAll(&pkt);
529 sendPacketToSock(sock, &pkt);
536 void tellServerNewPosition(void)
539 pkt.cmd = NETCMD_POSITION;
540 pkt.arg = client_player_num;
541 pkt.arg2 = player[client_player_num].x;
542 pkt.arg3 = player[client_player_num].y;
545 sendPacketToAll(&pkt);
547 sendPacketToSock(sock, &pkt);
553 void processKillPacket(NetPacket *pkt)
562 player[c1].y_add = -player[c1].y_add;
563 if (player[c1].y_add > -262144L)
564 player[c1].y_add = -262144L;
565 player[c1].jump_abort = 1;
566 player[c2].dead_flag = 1;
567 if (player[c2].anim != 6) {
569 player[c2].frame = 0;
570 player[c2].frame_tick = 0;
571 player[c2].image = player_anims[player[c2].anim].frame[player[c2].frame].image + player[c2].direction * 9;
572 if (main_info.no_gore == 0) {
573 for (c4 = 0; c4 < 6; c4++)
574 add_object(OBJ_FUR, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 44 + c2 * 8);
575 for (c4 = 0; c4 < 6; c4++)
576 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 76);
577 for (c4 = 0; c4 < 6; c4++)
578 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 77);
579 for (c4 = 0; c4 < 8; c4++)
580 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 78);
581 for (c4 = 0; c4 < 10; c4++)
582 add_object(OBJ_FLESH, (x >> 16) + 6 + rnd(5), (y >> 16) + 6 + rnd(5), (rnd(65535) - 32768) * 3, (rnd(65535) - 32768) * 3, 0, 79);
584 dj_play_sfx(SFX_DEATH, (unsigned short)(SFX_DEATH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
586 player[c1].bumped[c2]++;
587 s1 = player[c1].bumps % 100;
588 add_leftovers(0, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
589 add_leftovers(1, 360, 34 + c1 * 64, s1 / 10, &number_gobs);
590 add_leftovers(0, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
591 add_leftovers(1, 376, 34 + c1 * 64, s1 - (s1 / 10) * 10, &number_gobs);
597 void processPositionPacket(NetPacket *pkt)
599 int playerid = pkt->arg;
601 player[playerid].x = pkt->arg2;
602 player[playerid].y = pkt->arg3;
606 void processAlivePacket(NetPacket *pkt)
608 int playerid = pkt->arg;
610 player[playerid].dead_flag = 0;
611 player[playerid].x = pkt->arg2;
612 player[playerid].y = pkt->arg3;
616 void serverTellEveryoneGoodbye(void)
622 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
623 if (player[i].enabled) {
626 pkt.cmd = NETCMD_BYE;
631 sendPacketToAll(&pkt);
638 int server_said_bye = 0;
641 int update_players_from_server(void)
648 while ((rc = grabPacket(sock, socketset, &pkt)) != 0) {
650 printf("CLIENT: Lost connection.\n");
651 pkt.cmd = NETCMD_BYE;
652 pkt.arg = client_player_num;
655 if (pkt.cmd == NETCMD_BYE) {
656 if (pkt.arg == client_player_num) {
657 SDLNet_FreeSocketSet(socketset);
658 SDLNet_TCP_Close(sock);
663 player[pkt.arg].enabled = 0;
665 } else if (pkt.cmd == NETCMD_MOVE) {
666 processMovePacket(&pkt);
667 } else if (pkt.cmd == NETCMD_ALIVE) {
668 processAlivePacket(&pkt);
669 } else if (pkt.cmd == NETCMD_POSITION) {
670 processPositionPacket(&pkt);
671 } else if (pkt.cmd == NETCMD_KILL) {
672 processKillPacket(&pkt);
674 printf("CLIENT: Got an unknown packet: 0x%lX.\n", pkt.cmd);
682 void serverSendAlive(int playerid)
687 pkt.cmd = NETCMD_ALIVE;
689 pkt.arg2 = player[playerid].x;
690 pkt.arg3 = player[playerid].y;
691 sendPacketToAll(&pkt);
696 void serverSendKillPacket(int killer, int victim)
701 pkt.cmd = NETCMD_KILL;
704 pkt.arg3 = player[victim].x;
705 pkt.arg4 = player[victim].y;
706 processKillPacket(&pkt);
709 sendPacketToAll(&pkt);
715 void update_players_from_clients(void)
723 while ((playerid = serverRecvPacket(&pkt)) >= 0) {
724 if (pkt.cmd == NETCMD_BYE) {
725 pkt.arg = playerid; /* just in case. */
726 sendPacketToAll(&pkt);
727 player[playerid].enabled = 0;
728 SDLNet_FreeSocketSet(net_info[playerid].socketset);
729 SDLNet_TCP_Close(net_info[playerid].sock);
730 } else if (pkt.cmd == NETCMD_POSITION) {
731 pkt.arg = playerid; /* just in case. */
732 processPositionPacket(&pkt);
733 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
738 } else if (pkt.cmd == NETCMD_MOVE) {
739 pkt.arg = playerid; /* just in case. */
741 pkt.arg3 = player[playerid].x;
742 pkt.arg4 = player[playerid].y;
744 processMovePacket(&pkt);
745 sendPacketToAll(&pkt);
747 printf("SERVER: Got unknown packet (0x%lX).\n", pkt.cmd);
753 void init_server(const char *netarg)
758 int wait_for_clients = ((netarg == NULL) ? 0 : atoi(netarg));
761 /** assign player number zero as default for the server */
762 if(-1 == client_player_num)
763 client_player_num = 0;
765 if ((wait_for_clients >= JNB_MAX_PLAYERS) || (wait_for_clients < 0)) {
766 printf("SERVER: Waiting for bogus client count (%d).\n", wait_for_clients);
770 if (SDLNet_Init() < 0) {
775 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
776 ipstr = SDLNet_ResolveIP(&addr);
777 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
778 printf("SERVER: we are %s (%i.%i.%i.%i:%i).\n", ipstr, (addr.host >> 0) & 0xff, (addr.host >> 8) & 0xff, (addr.host >> 16) & 0xff, (addr.host >> 24) & 0xff, addr.port);
779 net_info[client_player_num].addr = addr;
781 addr.host = INADDR_ANY;
782 sock = SDLNet_TCP_Open(&addr);
784 fprintf(stderr, "SERVER: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
788 player[client_player_num].enabled = 1;
790 printf("SERVER: waiting for (%d) clients...\n", wait_for_clients);
792 socketset = SDLNet_AllocSocketSet(JNB_MAX_PLAYERS + 1);
793 SDLNet_TCP_AddSocket(socketset, sock);
795 while (wait_for_clients > 0)
797 char buf[NETPKTBUFSIZE];
803 /* Wait for events */
804 SDLNet_CheckSockets(socketset, ~0);
805 if ( SDLNet_SocketReady(sock) ) {
806 s = SDLNet_TCP_Accept(sock);
810 fprintf(stderr, "SERVER: SDLNet_TCP_Accept(): %s", SDLNet_GetError());
811 SDLNet_TCP_Close(sock);
817 br = SDLNet_TCP_Recv(s, buf, NETPKTBUFSIZE);
819 fprintf(stderr, "SERVER: SDLNet_TCP_Recv(): %s\n", SDLNet_GetError());
821 SDLNet_TCP_Close(sock);
825 from = SDLNet_TCP_GetPeerAddress(s);
826 ipstr = SDLNet_ResolveIP(from);
827 printf("SERVER: Got data from %s (%i.%i.%i.%i:%i).\n", ipstr, (from->host >> 0) & 0xff, (from->host >> 8) & 0xff, (from->host >> 16) & 0xff, (from->host >> 24) & 0xff, from->port);
829 if (br != NETPKTBUFSIZE) {
830 printf("SERVER: Bogus packet.\n");
834 bufToPacket(buf, &pkt);
835 if (pkt.cmd != NETCMD_HELLO) {
836 printf("SERVER: Bogus packet.\n");
840 printf("SERVER: Client claims to be player #%ld.\n", pkt.arg);
844 for(i=0; i!=JNB_MAX_PLAYERS; ++i) {
845 if(!player[i].enabled) {
846 printf("SERVER: assigning %d as player number\n", i);
853 if ((pkt.arg>=JNB_MAX_PLAYERS)||(pkt.arg<0)) {
854 printf("SERVER: (that's an invalid player number.)\n");
855 } else if (player[pkt.arg].enabled) {
856 printf("SERVER: (that player number is already taken.)\n");
862 printf("SERVER: Forbidding connection.\n");
863 pkt.cmd = NETCMD_NACK;
864 sendPacketToSock(s, &pkt);
867 player[pkt.arg].enabled = 1;
868 net_info[pkt.arg].sock = s;
869 net_info[pkt.arg].addr = *from;
870 net_info[pkt.arg].socketset = SDLNet_AllocSocketSet(1);
871 SDLNet_TCP_AddSocket(net_info[pkt.arg].socketset, net_info[pkt.arg].sock);
873 printf("SERVER: Granting connection. (%d) to go.\n", wait_for_clients);
874 pkt.cmd = NETCMD_ACK;
875 sendPacket(pkt.arg, &pkt);
879 SDLNet_TCP_Close(sock); /* done with the listen socket. */
880 SDLNet_FreeSocketSet(socketset);
884 printf("SERVER: Got all our connections. Greenlighting clients...\n");
886 pkt.cmd = NETCMD_GREENLIGHT;
888 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
889 if (player[i].enabled) {
893 sendPacketToAll(&pkt);
897 void connect_to_server(char *netarg)
900 char buf[NETPKTBUFSIZE];
906 if (netarg == NULL) {
907 printf("CLIENT: Need to specify host to connect to.\n");
911 if (SDLNet_Init() < 0) {
916 SDLNet_ResolveHost(&addr, NULL, JNB_INETPORT);
917 ipstr = SDLNet_ResolveIP(&addr);
918 SDLNet_ResolveHost(&addr, ipstr, JNB_INETPORT);
919 printf("CLIENT: we are %s (%i.%i.%i.%i:%i).\n", ipstr, (addr.host >> 0) & 0xff, (addr.host >> 8) & 0xff, (addr.host >> 16) & 0xff, (addr.host >> 24) & 0xff, addr.port);
921 if (SDLNet_ResolveHost(&hent, netarg, JNB_INETPORT) < 0) {
922 fprintf(stderr, "CLIENT: couldn't find host: %s\n", SDLNet_GetError());
926 sock = SDLNet_TCP_Open(&hent);
928 fprintf(stderr, "CLIENT: SDLNet_TCP_Open(): %s\n", SDLNet_GetError());
932 socketset = SDLNet_AllocSocketSet(1);
933 SDLNet_TCP_AddSocket(socketset, sock);
935 printf("CLIENT: connected to %s...\n", SDLNet_ResolveIP(&hent));
937 printf("CLIENT: Sending HELLO packet...\n");
938 pkt.cmd = NETCMD_HELLO;
939 pkt.arg = client_player_num;
940 sendPacketToSock(sock, &pkt);
942 printf("CLIENT: Waiting for ACK from server...\n");
944 br = SDLNet_TCP_Recv(sock, buf, NETPKTBUFSIZE);
946 fprintf(stderr, "CLIENT: recv(): %s\n", SDLNet_GetError());
947 SDLNet_FreeSocketSet(socketset);
948 SDLNet_TCP_Close(sock);
952 if (br != NETPKTBUFSIZE) {
953 printf("CLIENT: Bogus packet size (%d of %d). FIXME.\n", br, NETPKTBUFSIZE);
954 SDLNet_FreeSocketSet(socketset);
955 SDLNet_TCP_Close(sock);
959 bufToPacket(buf, &pkt);
961 if (pkt.cmd == NETCMD_NACK) {
962 printf("CLIENT: Server forbid us from playing.\n");
963 SDLNet_FreeSocketSet(socketset);
964 SDLNet_TCP_Close(sock);
968 if (pkt.cmd != NETCMD_ACK) {
969 printf("CLIENT: Unexpected packet (cmd=0x%lX).\n", pkt.cmd);
970 SDLNet_FreeSocketSet(socketset);
971 SDLNet_TCP_Close(sock);
975 client_player_num = pkt.arg;
976 player[client_player_num].enabled = 1;
977 net_info[client_player_num].addr = addr;
978 printf("CLIENT: Server accepted our connection.\n");
980 wait_for_greenlight();
985 static void flip_pixels(unsigned char *pixels)
991 for (y = 0; y < JNB_HEIGHT; y++) {
992 for (x = 0; x < (352/2); x++) {
993 temp = pixels[y*JNB_WIDTH+x];
994 pixels[y*JNB_WIDTH+x] = pixels[y*JNB_WIDTH+(352-x)-1];
995 pixels[y*JNB_WIDTH+(352-x)-1] = temp;
1001 void get_closest_player_to_point(int x,int y,int *dist,int *closest_player)
1007 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1008 if (player[c1].enabled == 1) {
1009 cur_dist = (int)sqrt((x - ((player[c1].x >> 16) + 8)) * (x - ((player[c1].x >> 16) + 8)) + (y - ((player[c1].y >> 16) + 8)) * (y - ((player[c1].y >> 16) + 8)));
1010 if (cur_dist < *dist) {
1011 *closest_player = c1;
1019 static void update_flies(int update_count)
1022 int closest_player = 0, dist;
1025 /* get center of fly swarm */
1027 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1034 if (update_count == 1) {
1035 /* get closest player to fly swarm */
1036 get_closest_player_to_point(s1, s2, &dist, &closest_player);
1037 /* update fly swarm sound */
1041 dj_set_sfx_channel_volume(4, (char)(s3));
1044 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1045 /* get closest player to fly */
1046 get_closest_player_to_point(flies[c1].x, flies[c1].y, &dist, &closest_player);
1047 flies[c1].old_x = flies[c1].x;
1048 flies[c1].old_y = flies[c1].y;
1050 if ((s1 - flies[c1].x) > 30)
1052 else if ((s1 - flies[c1].x) < -30)
1055 if (((player[closest_player].x >> 16) + 8) > flies[c1].x) {
1056 if (lord_of_the_flies == 0)
1061 if (lord_of_the_flies == 0)
1067 s4 = rnd(3) - 1 + s3;
1068 if ((flies[c1].x + s4) < 16)
1070 if ((flies[c1].x + s4) > 351)
1072 if (GET_BAN_MAP_XY(flies[c1].x + s4, flies[c1].y) != BAN_VOID)
1076 if ((s2 - flies[c1].y) > 30)
1078 else if ((s2 - flies[c1].y) < -30)
1081 if (((player[closest_player].y >> 16) + 8) > flies[c1].y) {
1082 if (lord_of_the_flies == 0)
1087 if (lord_of_the_flies == 0)
1093 s4 = rnd(3) - 1 + s3;
1094 if ((flies[c1].y + s4) < 0)
1096 if ((flies[c1].y + s4) > 239)
1098 if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y + s4) != BAN_VOID)
1105 static void player_kill(int c1, int c2)
1107 if (player[c1].y_add >= 0) {
1109 serverSendKillPacket(c1, c2);
1111 if (player[c2].y_add < 0)
1112 player[c2].y_add = 0;
1117 static void check_cheats(void)
1119 if (strncmp(last_keys, "kcitsogop", strlen("kcitsogop")) == 0) {
1123 if (strncmp(last_keys, "ecapsniseinnub", strlen("ecapsniseinnub")) == 0) {
1124 bunnies_in_space ^= 1;
1127 if (strncmp(last_keys, "kcaptej", strlen("kcaptej")) == 0) {
1131 if (strncmp(last_keys, "seilfehtfodrol", strlen("seilfehtfodrol")) == 0) {
1132 lord_of_the_flies ^= 1;
1135 if (strncmp(last_keys, "retawnahtrekcihtsidoolb", strlen("retawnahtrekcihtsidoolb")) == 0) {
1137 63,32,32,53,17,17,42, 7,
1138 7,28, 0, 0,24, 0, 0,19,
1139 0, 0,12, 0, 0, 7, 0, 0
1142 63,63,63,40,53,62,19,42,
1143 60, 0,33,60, 3,32,46, 3,
1144 26,33, 3,19,21, 1, 8, 8
1148 blood_is_thicker_than_water ^= 1;
1149 if (blood_is_thicker_than_water == 1) {
1150 for (i=0; i<32; i++)
1151 pal[432+i] = blood[i];
1153 for (i=0; i<32; i++)
1154 pal[432+i] = water[i];
1156 register_background(background_pic, pal);
1157 recalculate_gob(&object_gobs, pal);
1163 static void collision_check(void)
1165 int c1 = 0, c2 = 0, c3 = 0;
1168 /* collision check */
1169 for (c3 = 0; c3 < 6; c3++) {
1173 } else if (c3 == 1) {
1176 } else if (c3 == 2) {
1179 } else if (c3 == 3) {
1182 } else if (c3 == 4) {
1185 } else if (c3 == 5) {
1189 if (player[c1].enabled == 1 && player[c2].enabled == 1) {
1190 if (labs(player[c1].x - player[c2].x) < (12L << 16) && labs(player[c1].y - player[c2].y) < (12L << 16)) {
1191 if ((labs(player[c1].y - player[c2].y) >> 16) > 5) {
1192 if (player[c1].y < player[c2].y) {
1198 if (player[c1].x < player[c2].x) {
1199 if (player[c1].x_add > 0)
1200 player[c1].x = player[c2].x - (12L << 16);
1201 else if (player[c2].x_add < 0)
1202 player[c2].x = player[c1].x + (12L << 16);
1204 player[c1].x -= player[c1].x_add;
1205 player[c2].x -= player[c2].x_add;
1207 l1 = player[c2].x_add;
1208 player[c2].x_add = player[c1].x_add;
1209 player[c1].x_add = l1;
1210 if (player[c1].x_add > 0)
1211 player[c1].x_add = -player[c1].x_add;
1212 if (player[c2].x_add < 0)
1213 player[c2].x_add = -player[c2].x_add;
1215 if (player[c1].x_add > 0)
1216 player[c2].x = player[c1].x - (12L << 16);
1217 else if (player[c2].x_add < 0)
1218 player[c1].x = player[c2].x + (12L << 16);
1220 player[c1].x -= player[c1].x_add;
1221 player[c2].x -= player[c2].x_add;
1223 l1 = player[c2].x_add;
1224 player[c2].x_add = player[c1].x_add;
1225 player[c1].x_add = l1;
1226 if (player[c1].x_add < 0)
1227 player[c1].x_add = -player[c1].x_add;
1228 if (player[c2].x_add > 0)
1229 player[c2].x_add = -player[c2].x_add;
1237 static void game_loop(void) {
1238 int mod_vol, sfx_vol;
1239 int update_count = 1;
1240 int end_loop_flag = 0;
1242 int update_palette = 0;
1243 int mod_fade_direction;
1246 mod_vol = sfx_vol = 0;
1247 mod_fade_direction = 1;
1248 dj_ready_mod(MOD_GAME);
1249 dj_set_mod_volume((char)mod_vol);
1250 dj_set_sfx_volume((char)mod_vol);
1256 while (update_count) {
1258 if (key_pressed(1) == 1) {
1262 serverTellEveryoneGoodbye();
1264 tellServerGoodbye();
1269 memset(pal, 0, 768);
1270 mod_fade_direction = 0;
1278 update_players_from_clients();
1280 if (!update_players_from_server()) {
1281 break; /* got a BYE packet */
1295 main_info.page_info[main_info.draw_page].num_pobs = 0;
1296 for (i = 0; i < JNB_MAX_PLAYERS; i++) {
1297 if (player[i].enabled == 1)
1298 main_info.page_info[main_info.draw_page].num_pobs++;
1305 if (flies_enabled) {
1306 update_flies(update_count);
1311 if (update_count == 1) {
1314 for (i = 0, c2 = 0; i < JNB_MAX_PLAYERS; i++) {
1315 if (player[i].enabled == 1) {
1316 main_info.page_info[main_info.draw_page].pobs[c2].x = player[i].x >> 16;
1317 main_info.page_info[main_info.draw_page].pobs[c2].y = player[i].y >> 16;
1318 main_info.page_info[main_info.draw_page].pobs[c2].image = player[i].image + i * 18;
1319 main_info.page_info[main_info.draw_page].pobs[c2].pob_data = &rabbit_gobs;
1326 draw_pobs(main_info.draw_page);
1331 draw_flies(main_info.draw_page);
1336 if (mod_fade_direction == 1) {
1339 dj_set_mod_volume((char)mod_vol);
1343 dj_set_sfx_volume((char)sfx_vol);
1348 dj_set_mod_volume((char)mod_vol);
1352 dj_set_sfx_volume((char)sfx_vol);
1357 for (i = 0; i < 768; i++) {
1358 if (cur_pal[i] < pal[i]) {
1361 } else if (cur_pal[i] > pal[i]) {
1368 if (fade_flag == 0 && end_loop_flag == 1)
1371 if (update_count == 1) {
1372 if (update_palette == 1) {
1373 setpalette(0, 256, cur_pal);
1377 main_info.draw_page ^= 1;
1378 main_info.view_page ^= 1;
1380 flippage(main_info.view_page);
1387 redraw_flies_background(main_info.draw_page);
1389 redraw_pob_backgrounds(main_info.draw_page);
1391 draw_leftovers(main_info.draw_page);
1401 if ( (player[client_player_num].dead_flag == 0) &&
1403 (player[client_player_num].action_left) ||
1404 (player[client_player_num].action_right) ||
1405 (player[client_player_num].action_up) ||
1406 (player[client_player_num].jump_ready == 0)
1409 tellServerNewPosition();
1414 update_count = intr_sysupdate();
1418 if ((server_said_bye) || ((fade_flag == 0) && (end_loop_flag == 1)))
1422 if ((fade_flag == 0) && (end_loop_flag == 1))
1428 static int menu_loop(void)
1430 unsigned char *handle;
1441 if (key_pressed(1) == 1) {
1444 if (init_level(0, pal) != 0) {
1449 memset(cur_pal, 0, 768);
1450 setpalette(0, 256, cur_pal);
1452 recalculate_gob(&rabbit_gobs, pal);
1453 recalculate_gob(&object_gobs, pal);
1454 recalculate_gob(&number_gobs, pal);
1457 register_background(background_pic, pal);
1460 if (flies_enabled) {
1464 for (c1 = 0; c1 < NUM_FLIES; c1++) {
1466 flies[c1].x = s1 + rnd(101) - 50;
1467 flies[c1].y = s2 + rnd(101) - 50;
1468 if (GET_BAN_MAP_XY(flies[c1].x, flies[c1].y) == BAN_VOID)
1471 flies[c1].back_defined[0] = 0;
1472 flies[c1].back_defined[1] = 0;
1477 dj_play_sfx(SFX_FLY, SFX_FLY_FREQ, 0, 0, 0, 4);
1481 lord_of_the_flies = bunnies_in_space = jetpack = pogostick = blood_is_thicker_than_water = 0;
1482 main_info.page_info[0].num_pobs = 0;
1483 main_info.page_info[1].num_pobs = 0;
1484 main_info.view_page = 0;
1485 main_info.draw_page = 1;
1492 serverTellEveryoneGoodbye();
1493 SDLNet_TCP_Close(sock);
1496 if (!server_said_bye) {
1497 tellServerGoodbye();
1500 SDLNet_TCP_Close(sock);
1506 main_info.view_page = 0;
1507 main_info.draw_page = 1;
1509 dj_stop_sfx_channel(4);
1513 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
1514 register_mask(mask_pic);
1516 register_background(NULL, NULL);
1520 put_text(main_info.view_page, 100, 50, "DOTT", 2);
1521 put_text(main_info.view_page, 160, 50, "JIFFY", 2);
1522 put_text(main_info.view_page, 220, 50, "FIZZ", 2);
1523 put_text(main_info.view_page, 280, 50, "MIJJI", 2);
1524 put_text(main_info.view_page, 40, 80, "DOTT", 2);
1525 put_text(main_info.view_page, 40, 110, "JIFFY", 2);
1526 put_text(main_info.view_page, 40, 140, "FIZZ", 2);
1527 put_text(main_info.view_page, 40, 170, "MIJJI", 2);
1529 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1532 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++) {
1534 sprintf(str1, "%d", player[c1].bumped[c2]);
1535 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, str1, 2);
1537 put_text(main_info.view_page, 100 + c2 * 60, 80 + c1 * 30, "-", 2);
1539 sprintf(str1, "%d", player[c1].bumps);
1540 put_text(main_info.view_page, 350, 80 + c1 * 30, str1, 2);
1543 put_text(main_info.view_page, 200, 230, "Press ESC to continue", 2);
1547 flippage(main_info.view_page);
1549 if ((handle = dat_open("menu.pcx")) == 0) {
1550 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1553 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
1554 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
1559 for (c1 = 0; c1 < 16; c1++) {
1560 pal[(240 + c1) * 3 + 0] = c1 << 2;
1561 pal[(240 + c1) * 3 + 1] = c1 << 2;
1562 pal[(240 + c1) * 3 + 2] = c1 << 2;
1565 memset(cur_pal, 0, 768);
1567 setpalette(0, 256, cur_pal);
1570 dj_ready_mod(MOD_SCORES);
1571 dj_set_mod_volume((char)mod_vol);
1575 while (key_pressed(1) == 0) {
1578 dj_set_mod_volume((char)mod_vol);
1579 for (c1 = 0; c1 < 768; c1++) {
1580 if (cur_pal[c1] < pal[c1])
1586 setpalette(0, 256, cur_pal);
1587 flippage(main_info.view_page);
1589 while (key_pressed(1) == 1) {
1594 memset(pal, 0, 768);
1596 while (mod_vol > 0) {
1598 dj_set_mod_volume((char)mod_vol);
1599 for (c1 = 0; c1 < 768; c1++) {
1600 if (cur_pal[c1] > pal[c1])
1605 setpalette(0, 256, cur_pal);
1606 flippage(main_info.view_page);
1609 fillpalette(0, 0, 0);
1615 return 0; /* don't go back to menu if in net game. */
1620 int main(int argc, char *argv[])
1624 if (init_program(argc, argv, pal) != 0)
1627 if (main_info.fireworks == 1) {
1632 result = menu_loop();
1640 static void player_action_left(int c1)
1643 int below_left, below, below_right;
1645 s1 = (player[c1].x >> 16);
1646 s2 = (player[c1].y >> 16);
1647 below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1648 below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1649 below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1651 if (below == BAN_ICE) {
1652 if (player[c1].x_add > 0)
1653 player[c1].x_add -= 1024;
1655 player[c1].x_add -= 768;
1656 } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1657 if (player[c1].x_add > 0)
1658 player[c1].x_add -= 1024;
1660 player[c1].x_add -= 768;
1662 if (player[c1].x_add > 0) {
1663 player[c1].x_add -= 16384;
1664 if (player[c1].x_add > -98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1665 add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0);
1667 player[c1].x_add -= 12288;
1669 if (player[c1].x_add < -98304L)
1670 player[c1].x_add = -98304L;
1671 player[c1].direction = 1;
1672 if (player[c1].anim == 0) {
1673 player[c1].anim = 1;
1674 player[c1].frame = 0;
1675 player[c1].frame_tick = 0;
1676 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1681 static void player_action_right(int c1)
1684 int below_left, below, below_right;
1686 s1 = (player[c1].x >> 16);
1687 s2 = (player[c1].y >> 16);
1688 below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1689 below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1690 below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1692 if (below == BAN_ICE) {
1693 if (player[c1].x_add < 0)
1694 player[c1].x_add += 1024;
1696 player[c1].x_add += 768;
1697 } else if ((below_left != BAN_SOLID && below_right == BAN_ICE) || (below_left == BAN_ICE && below_right != BAN_SOLID)) {
1698 if (player[c1].x_add > 0)
1699 player[c1].x_add += 1024;
1701 player[c1].x_add += 768;
1703 if (player[c1].x_add < 0) {
1704 player[c1].x_add += 16384;
1705 if (player[c1].x_add < 98304L && player[c1].in_water == 0 && below == BAN_SOLID)
1706 add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0);
1708 player[c1].x_add += 12288;
1710 if (player[c1].x_add > 98304L)
1711 player[c1].x_add = 98304L;
1712 player[c1].direction = 0;
1713 if (player[c1].anim == 0) {
1714 player[c1].anim = 1;
1715 player[c1].frame = 0;
1716 player[c1].frame_tick = 0;
1717 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1722 #define GET_BAN_MAP_IN_WATER(s1, s2) (GET_BAN_MAP_XY((s1), ((s2) + 7)) == BAN_VOID || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 7)) == BAN_VOID) && (GET_BAN_MAP_XY((s1), ((s2) + 8)) == BAN_WATER || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 8)) == BAN_WATER)
1725 void steer_players(void)
1730 update_player_actions();
1732 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
1734 if (player[c1].enabled == 1) {
1736 if (player[c1].dead_flag == 0) {
1738 if (player[c1].action_left && player[c1].action_right) {
1739 if (player[c1].direction == 0) {
1740 if (player[c1].action_right) {
1741 player_action_right(c1);
1744 if (player[c1].action_left) {
1745 player_action_left(c1);
1748 } else if (player[c1].action_left) {
1749 player_action_left(c1);
1750 } else if (player[c1].action_right) {
1751 player_action_right(c1);
1752 } else if ((!player[c1].action_left) && (!player[c1].action_right)) {
1753 int below_left, below, below_right;
1755 s1 = (player[c1].x >> 16);
1756 s2 = (player[c1].y >> 16);
1757 below_left = GET_BAN_MAP_XY(s1, s2 + 16);
1758 below = GET_BAN_MAP_XY(s1 + 8, s2 + 16);
1759 below_right = GET_BAN_MAP_XY(s1 + 15, s2 + 16);
1760 if (below == BAN_SOLID || below == BAN_SPRING || (((below_left == BAN_SOLID || below_left == BAN_SPRING) && below_right != BAN_ICE) || (below_left != BAN_ICE && (below_right == BAN_SOLID || below_right == BAN_SPRING)))) {
1761 if (player[c1].x_add < 0) {
1762 player[c1].x_add += 16384;
1763 if (player[c1].x_add > 0)
1764 player[c1].x_add = 0;
1766 player[c1].x_add -= 16384;
1767 if (player[c1].x_add < 0)
1768 player[c1].x_add = 0;
1770 if (player[c1].x_add != 0 && GET_BAN_MAP_XY((s1 + 8), (s2 + 16)) == BAN_SOLID)
1771 add_object(OBJ_SMOKE, (player[c1].x >> 16) + 2 + rnd(9), (player[c1].y >> 16) + 13 + rnd(5), 0, -16384 - rnd(8192), OBJ_ANIM_SMOKE, 0);
1773 if (player[c1].anim == 1) {
1774 player[c1].anim = 0;
1775 player[c1].frame = 0;
1776 player[c1].frame_tick = 0;
1777 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1782 if (pogostick == 1 || (player[c1].jump_ready == 1 && player[c1].action_up)) {
1783 s1 = (player[c1].x >> 16);
1784 s2 = (player[c1].y >> 16);
1788 if (GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 16)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 16)) == BAN_ICE) {
1789 player[c1].y_add = -280000L;
1790 player[c1].anim = 2;
1791 player[c1].frame = 0;
1792 player[c1].frame_tick = 0;
1793 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1794 player[c1].jump_ready = 0;
1795 player[c1].jump_abort = 1;
1797 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1799 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1801 /* jump out of water */
1802 if (GET_BAN_MAP_IN_WATER(s1, s2)) {
1803 player[c1].y_add = -196608L;
1804 player[c1].in_water = 0;
1805 player[c1].anim = 2;
1806 player[c1].frame = 0;
1807 player[c1].frame_tick = 0;
1808 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1809 player[c1].jump_ready = 0;
1810 player[c1].jump_abort = 1;
1812 dj_play_sfx(SFX_JUMP, (unsigned short)(SFX_JUMP_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1814 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1817 /* fall down by gravity */
1818 if (pogostick == 0 && (!player[c1].action_up)) {
1819 player[c1].jump_ready = 1;
1820 if (player[c1].in_water == 0 && player[c1].y_add < 0 && player[c1].jump_abort == 1) {
1821 if (bunnies_in_space == 0)
1822 /* normal gravity */
1823 player[c1].y_add += 32768;
1826 player[c1].y_add += 16384;
1827 if (player[c1].y_add > 0)
1828 player[c1].y_add = 0;
1833 if (player[c1].action_up) {
1834 player[c1].y_add -= 16384;
1835 if (player[c1].y_add < -400000L)
1836 player[c1].y_add = -400000L;
1837 if (GET_BAN_MAP_IN_WATER(s1, s2))
1838 player[c1].in_water = 0;
1840 add_object(OBJ_SMOKE, (player[c1].x >> 16) + 6 + rnd(5), (player[c1].y >> 16) + 10 + rnd(5), 0, 16384 + rnd(8192), OBJ_ANIM_SMOKE, 0);
1844 player[c1].x += player[c1].x_add;
1845 if ((player[c1].x >> 16) < 0) {
1847 player[c1].x_add = 0;
1849 if ((player[c1].x >> 16) + 15 > 351) {
1850 player[c1].x = 336L << 16;
1851 player[c1].x_add = 0;
1854 if (player[c1].y > 0) {
1855 s2 = (player[c1].y >> 16);
1857 /* check top line only */
1861 s1 = (player[c1].x >> 16);
1862 if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
1863 player[c1].x = (((s1 + 16) & 0xfff0)) << 16;
1864 player[c1].x_add = 0;
1867 s1 = (player[c1].x >> 16);
1868 if (GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
1869 player[c1].x = (((s1 + 16) & 0xfff0) - 16) << 16;
1870 player[c1].x_add = 0;
1874 player[c1].y += player[c1].y_add;
1876 s1 = (player[c1].x >> 16);
1877 s2 = (player[c1].y >> 16);
1878 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING || ((GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) != BAN_SOLID) || (GET_BAN_MAP_XY(s1, (s2 + 15)) != BAN_SOLID && GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING))) {
1879 player[c1].y = ((player[c1].y >> 16) & 0xfff0) << 16;
1880 player[c1].y_add = -400000L;
1881 player[c1].anim = 2;
1882 player[c1].frame = 0;
1883 player[c1].frame_tick = 0;
1884 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1885 player[c1].jump_ready = 0;
1886 player[c1].jump_abort = 0;
1887 for (c2 = 0; c2 < NUM_OBJECTS; c2++) {
1888 if (objects[c2].used == 1 && objects[c2].type == OBJ_SPRING) {
1889 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 15)) == BAN_SPRING) {
1890 if ((objects[c2].x >> 20) == ((s1 + 8) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1891 objects[c2].frame = 0;
1892 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1893 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1897 if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING) {
1898 if ((objects[c2].x >> 20) == (s1 >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1899 objects[c2].frame = 0;
1900 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1901 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1904 } else if (GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
1905 if ((objects[c2].x >> 20) == ((s1 + 15) >> 4) && (objects[c2].y >> 20) == ((s2 + 15) >> 4)) {
1906 objects[c2].frame = 0;
1907 objects[c2].ticks = object_anims[objects[c2].anim].frame[objects[c2].frame].ticks;
1908 objects[c2].image = object_anims[objects[c2].anim].frame[objects[c2].frame].image;
1915 dj_play_sfx(SFX_SPRING, (unsigned short)(SFX_SPRING_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1917 s1 = (player[c1].x >> 16);
1918 s2 = (player[c1].y >> 16);
1921 if (GET_BAN_MAP_XY(s1, s2) == BAN_SOLID || GET_BAN_MAP_XY(s1, s2) == BAN_ICE || GET_BAN_MAP_XY(s1, s2) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), s2) == BAN_SPRING) {
1922 player[c1].y = (((s2 + 16) & 0xfff0)) << 16;
1923 player[c1].y_add = 0;
1924 player[c1].anim = 0;
1925 player[c1].frame = 0;
1926 player[c1].frame_tick = 0;
1927 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1929 s1 = (player[c1].x >> 16);
1930 s2 = (player[c1].y >> 16);
1933 if (GET_BAN_MAP_XY((s1 + 8), (s2 + 8)) == BAN_WATER) {
1934 if (player[c1].in_water == 0) {
1935 /* falling into water */
1936 player[c1].in_water = 1;
1937 player[c1].anim = 4;
1938 player[c1].frame = 0;
1939 player[c1].frame_tick = 0;
1940 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1941 if (player[c1].y_add >= 32768) {
1942 add_object(OBJ_SPLASH, (player[c1].x >> 16) + 8, ((player[c1].y >> 16) & 0xfff0) + 15, 0, 0, OBJ_ANIM_SPLASH, 0);
1943 if (blood_is_thicker_than_water == 0)
1944 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 1000), 64, 0, 0, -1);
1946 dj_play_sfx(SFX_SPLASH, (unsigned short)(SFX_SPLASH_FREQ + rnd(2000) - 5000), 64, 0, 0, -1);
1949 /* slowly move up to water surface */
1950 player[c1].y_add -= 1536;
1951 if (player[c1].y_add < 0 && player[c1].anim != 5) {
1952 player[c1].anim = 5;
1953 player[c1].frame = 0;
1954 player[c1].frame_tick = 0;
1955 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1957 if (player[c1].y_add < -65536L)
1958 player[c1].y_add = -65536L;
1959 if (player[c1].y_add > 65535L)
1960 player[c1].y_add = 65535L;
1961 if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE) {
1962 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
1963 player[c1].y_add = 0;
1965 } else if (GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY(s1, (s2 + 15)) == BAN_SPRING || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SOLID || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_ICE || GET_BAN_MAP_XY((s1 + 15), (s2 + 15)) == BAN_SPRING) {
1966 player[c1].in_water = 0;
1967 player[c1].y = (((s2 + 16) & 0xfff0) - 16) << 16;
1968 player[c1].y_add = 0;
1969 if (player[c1].anim != 0 && player[c1].anim != 1) {
1970 player[c1].anim = 0;
1971 player[c1].frame = 0;
1972 player[c1].frame_tick = 0;
1973 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1976 if (player[c1].in_water == 0) {
1977 if (bunnies_in_space == 0)
1978 player[c1].y_add += 12288;
1980 player[c1].y_add += 6144;
1981 if (player[c1].y_add > 327680L)
1982 player[c1].y_add = 327680L;
1984 player[c1].y = (player[c1].y & 0xffff0000) + 0x10000;
1985 player[c1].y_add = 0;
1987 player[c1].in_water = 0;
1989 if (player[c1].y_add > 36864 && player[c1].anim != 3 && player[c1].in_water == 0) {
1990 player[c1].anim = 3;
1991 player[c1].frame = 0;
1992 player[c1].frame_tick = 0;
1993 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
1998 player[c1].frame_tick++;
1999 if (player[c1].frame_tick >= player_anims[player[c1].anim].frame[player[c1].frame].ticks) {
2001 if (player[c1].frame >= player_anims[player[c1].anim].num_frames) {
2002 if (player[c1].anim != 6)
2003 player[c1].frame = player_anims[player[c1].anim].restart_frame;
2005 position_player(c1);
2007 player[c1].frame_tick = 0;
2009 player[c1].image = player_anims[player[c1].anim].frame[player[c1].frame].image + player[c1].direction * 9;
2018 void position_player(int player_num)
2027 if (ban_map[s2][s1] == BAN_VOID && (ban_map[s2 + 1][s1] == BAN_SOLID || ban_map[s2 + 1][s1] == BAN_ICE))
2030 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2031 if (c1 != player_num && player[c1].enabled == 1) {
2032 if (abs((s1 << 4) - (player[c1].x >> 16)) < 32 && abs((s2 << 4) - (player[c1].y >> 16)) < 32)
2036 if (c1 == JNB_MAX_PLAYERS) {
2037 player[player_num].x = (long) s1 << 20;
2038 player[player_num].y = (long) s2 << 20;
2039 player[player_num].x_add = player[player_num].y_add = 0;
2040 player[player_num].direction = 0;
2041 player[player_num].jump_ready = 1;
2042 player[player_num].in_water = 0;
2043 player[player_num].anim = 0;
2044 player[player_num].frame = 0;
2045 player[player_num].frame_tick = 0;
2046 player[player_num].image = player_anims[player[player_num].anim].frame[player[player_num].frame].image;
2051 serverSendAlive(player_num);
2053 player[player_num].dead_flag = 0;
2063 void add_object(int type, int x, int y, int x_add, int y_add, int anim, int frame)
2067 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2068 if (objects[c1].used == 0) {
2069 objects[c1].used = 1;
2070 objects[c1].type = type;
2071 objects[c1].x = (long) x << 16;
2072 objects[c1].y = (long) y << 16;
2073 objects[c1].x_add = x_add;
2074 objects[c1].y_add = y_add;
2075 objects[c1].x_acc = 0;
2076 objects[c1].y_acc = 0;
2077 objects[c1].anim = anim;
2078 objects[c1].frame = frame;
2079 objects[c1].ticks = object_anims[anim].frame[frame].ticks;
2080 objects[c1].image = object_anims[anim].frame[frame].image;
2088 void update_objects(void)
2093 for (c1 = 0; c1 < NUM_OBJECTS; c1++) {
2094 if (objects[c1].used == 1) {
2095 switch (objects[c1].type) {
2097 objects[c1].ticks--;
2098 if (objects[c1].ticks <= 0) {
2099 objects[c1].frame++;
2100 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames) {
2101 objects[c1].frame--;
2102 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2104 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2105 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2108 if (objects[c1].used == 1)
2109 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2112 objects[c1].ticks--;
2113 if (objects[c1].ticks <= 0) {
2114 objects[c1].frame++;
2115 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2116 objects[c1].used = 0;
2118 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2119 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2122 if (objects[c1].used == 1)
2123 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2126 objects[c1].x += objects[c1].x_add;
2127 objects[c1].y += objects[c1].y_add;
2128 objects[c1].ticks--;
2129 if (objects[c1].ticks <= 0) {
2130 objects[c1].frame++;
2131 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2132 objects[c1].used = 0;
2134 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2135 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2138 if (objects[c1].used == 1)
2139 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2141 case OBJ_YEL_BUTFLY:
2142 case OBJ_PINK_BUTFLY:
2143 objects[c1].x_acc += rnd(128) - 64;
2144 if (objects[c1].x_acc < -1024)
2145 objects[c1].x_acc = -1024;
2146 if (objects[c1].x_acc > 1024)
2147 objects[c1].x_acc = 1024;
2148 objects[c1].x_add += objects[c1].x_acc;
2149 if (objects[c1].x_add < -32768)
2150 objects[c1].x_add = -32768;
2151 if (objects[c1].x_add > 32768)
2152 objects[c1].x_add = 32768;
2153 objects[c1].x += objects[c1].x_add;
2154 if ((objects[c1].x >> 16) < 16) {
2155 objects[c1].x = 16 << 16;
2156 objects[c1].x_add = -objects[c1].x_add >> 2;
2157 objects[c1].x_acc = 0;
2158 } else if ((objects[c1].x >> 16) > 350) {
2159 objects[c1].x = 350 << 16;
2160 objects[c1].x_add = -objects[c1].x_add >> 2;
2161 objects[c1].x_acc = 0;
2163 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2164 if (objects[c1].x_add < 0) {
2165 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2167 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2169 objects[c1].x_add = -objects[c1].x_add >> 2;
2170 objects[c1].x_acc = 0;
2172 objects[c1].y_acc += rnd(64) - 32;
2173 if (objects[c1].y_acc < -1024)
2174 objects[c1].y_acc = -1024;
2175 if (objects[c1].y_acc > 1024)
2176 objects[c1].y_acc = 1024;
2177 objects[c1].y_add += objects[c1].y_acc;
2178 if (objects[c1].y_add < -32768)
2179 objects[c1].y_add = -32768;
2180 if (objects[c1].y_add > 32768)
2181 objects[c1].y_add = 32768;
2182 objects[c1].y += objects[c1].y_add;
2183 if ((objects[c1].y >> 16) < 0) {
2185 objects[c1].y_add = -objects[c1].y_add >> 2;
2186 objects[c1].y_acc = 0;
2187 } else if ((objects[c1].y >> 16) > 255) {
2188 objects[c1].y = 255 << 16;
2189 objects[c1].y_add = -objects[c1].y_add >> 2;
2190 objects[c1].y_acc = 0;
2192 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0) {
2193 if (objects[c1].y_add < 0) {
2194 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2196 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2198 objects[c1].y_add = -objects[c1].y_add >> 2;
2199 objects[c1].y_acc = 0;
2201 if (objects[c1].type == OBJ_YEL_BUTFLY) {
2202 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_LEFT) {
2203 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_LEFT;
2204 objects[c1].frame = 0;
2205 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2206 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2207 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_YEL_BUTFLY_RIGHT) {
2208 objects[c1].anim = OBJ_ANIM_YEL_BUTFLY_RIGHT;
2209 objects[c1].frame = 0;
2210 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2211 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2214 if (objects[c1].x_add < 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_LEFT) {
2215 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_LEFT;
2216 objects[c1].frame = 0;
2217 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2218 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2219 } else if (objects[c1].x_add > 0 && objects[c1].anim != OBJ_ANIM_PINK_BUTFLY_RIGHT) {
2220 objects[c1].anim = OBJ_ANIM_PINK_BUTFLY_RIGHT;
2221 objects[c1].frame = 0;
2222 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2223 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2226 objects[c1].ticks--;
2227 if (objects[c1].ticks <= 0) {
2228 objects[c1].frame++;
2229 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2230 objects[c1].frame = object_anims[objects[c1].anim].restart_frame;
2232 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2233 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2236 if (objects[c1].used == 1)
2237 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2241 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 0);
2242 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2243 objects[c1].y_add += 3072;
2244 if (objects[c1].y_add > 196608L)
2245 objects[c1].y_add = 196608L;
2246 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2247 if (objects[c1].x_add < 0) {
2248 if (objects[c1].x_add < -65536L)
2249 objects[c1].x_add = -65536L;
2250 objects[c1].x_add += 1024;
2251 if (objects[c1].x_add > 0)
2252 objects[c1].x_add = 0;
2254 if (objects[c1].x_add > 65536L)
2255 objects[c1].x_add = 65536L;
2256 objects[c1].x_add -= 1024;
2257 if (objects[c1].x_add < 0)
2258 objects[c1].x_add = 0;
2260 objects[c1].y_add += 1024;
2261 if (objects[c1].y_add < -65536L)
2262 objects[c1].y_add = -65536L;
2263 if (objects[c1].y_add > 65536L)
2264 objects[c1].y_add = 65536L;
2266 objects[c1].x += objects[c1].x_add;
2267 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1 || ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3)) {
2268 if (objects[c1].x_add < 0) {
2269 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2270 objects[c1].x_add = -objects[c1].x_add >> 2;
2272 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2273 objects[c1].x_add = -objects[c1].x_add >> 2;
2276 objects[c1].y += objects[c1].y_add;
2277 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2278 objects[c1].used = 0;
2279 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2280 if (objects[c1].y_add < 0) {
2281 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2282 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2283 objects[c1].x_add >>= 2;
2284 objects[c1].y_add = -objects[c1].y_add >> 2;
2287 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2288 if (objects[c1].y_add > 131072L) {
2289 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2290 objects[c1].x_add >>= 2;
2291 objects[c1].y_add = -objects[c1].y_add >> 2;
2293 objects[c1].used = 0;
2294 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2295 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2296 if (objects[c1].y_add > 131072L)
2297 objects[c1].y_add = -objects[c1].y_add >> 2;
2299 objects[c1].y_add = 0;
2303 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2304 objects[c1].x_add = -16384;
2305 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2306 objects[c1].x_add = 16384;
2307 if (objects[c1].used == 1) {
2308 s1 = (int)(atan2(objects[c1].y_add, objects[c1].x_add) * 4 / M_PI);
2315 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame + s1, &object_gobs);
2319 if (rnd(100) < 30) {
2320 if (objects[c1].frame == 76)
2321 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 1);
2322 else if (objects[c1].frame == 77)
2323 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 2);
2324 else if (objects[c1].frame == 78)
2325 add_object(OBJ_FLESH_TRACE, objects[c1].x >> 16, objects[c1].y >> 16, 0, 0, OBJ_ANIM_FLESH_TRACE, 3);
2327 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 0) {
2328 objects[c1].y_add += 3072;
2329 if (objects[c1].y_add > 196608L)
2330 objects[c1].y_add = 196608L;
2331 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 2) {
2332 if (objects[c1].x_add < 0) {
2333 if (objects[c1].x_add < -65536L)
2334 objects[c1].x_add = -65536L;
2335 objects[c1].x_add += 1024;
2336 if (objects[c1].x_add > 0)
2337 objects[c1].x_add = 0;
2339 if (objects[c1].x_add > 65536L)
2340 objects[c1].x_add = 65536L;
2341 objects[c1].x_add -= 1024;
2342 if (objects[c1].x_add < 0)
2343 objects[c1].x_add = 0;
2345 objects[c1].y_add += 1024;
2346 if (objects[c1].y_add < -65536L)
2347 objects[c1].y_add = -65536L;
2348 if (objects[c1].y_add > 65536L)
2349 objects[c1].y_add = 65536L;
2351 objects[c1].x += objects[c1].x_add;
2352 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1 || ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3)) {
2353 if (objects[c1].x_add < 0) {
2354 objects[c1].x = (((objects[c1].x >> 16) + 16) & 0xfff0) << 16;
2355 objects[c1].x_add = -objects[c1].x_add >> 2;
2357 objects[c1].x = ((((objects[c1].x >> 16) - 16) & 0xfff0) + 15) << 16;
2358 objects[c1].x_add = -objects[c1].x_add >> 2;
2361 objects[c1].y += objects[c1].y_add;
2362 if ((objects[c1].x >> 16) < -5 || (objects[c1].x >> 16) > 405 || (objects[c1].y >> 16) > 260)
2363 objects[c1].used = 0;
2364 if ((objects[c1].y >> 16) > 0 && (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 0)) {
2365 if (objects[c1].y_add < 0) {
2366 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] != 2) {
2367 objects[c1].y = (((objects[c1].y >> 16) + 16) & 0xfff0) << 16;
2368 objects[c1].x_add >>= 2;
2369 objects[c1].y_add = -objects[c1].y_add >> 2;
2372 if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 1) {
2373 if (objects[c1].y_add > 131072L) {
2374 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2375 objects[c1].x_add >>= 2;
2376 objects[c1].y_add = -objects[c1].y_add >> 2;
2378 if (rnd(100) < 10) {
2380 add_leftovers(0, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2381 add_leftovers(1, objects[c1].x >> 16, (objects[c1].y >> 16) + s1, objects[c1].frame, &object_gobs);
2383 objects[c1].used = 0;
2385 } else if (ban_map[objects[c1].y >> 20][objects[c1].x >> 20] == 3) {
2386 objects[c1].y = ((((objects[c1].y >> 16) - 16) & 0xfff0) + 15) << 16;
2387 if (objects[c1].y_add > 131072L)
2388 objects[c1].y_add = -objects[c1].y_add >> 2;
2390 objects[c1].y_add = 0;
2394 if (objects[c1].x_add < 0 && objects[c1].x_add > -16384)
2395 objects[c1].x_add = -16384;
2396 if (objects[c1].x_add > 0 && objects[c1].x_add < 16384)
2397 objects[c1].x_add = 16384;
2398 if (objects[c1].used == 1)
2399 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].frame, &object_gobs);
2401 case OBJ_FLESH_TRACE:
2402 objects[c1].ticks--;
2403 if (objects[c1].ticks <= 0) {
2404 objects[c1].frame++;
2405 if (objects[c1].frame >= object_anims[objects[c1].anim].num_frames)
2406 objects[c1].used = 0;
2408 objects[c1].ticks = object_anims[objects[c1].anim].frame[objects[c1].frame].ticks;
2409 objects[c1].image = object_anims[objects[c1].anim].frame[objects[c1].frame].image;
2412 if (objects[c1].used == 1)
2413 add_pob(main_info.draw_page, objects[c1].x >> 16, objects[c1].y >> 16, objects[c1].image, &object_gobs);
2422 int add_pob(int page, int x, int y, int image, gob_t *pob_data)
2425 if (main_info.page_info[page].num_pobs >= NUM_POBS)
2428 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].x = x;
2429 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].y = y;
2430 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].image = image;
2431 main_info.page_info[page].pobs[main_info.page_info[page].num_pobs].pob_data = pob_data;
2432 main_info.page_info[page].num_pobs++;
2439 void draw_flies(int page)
2443 for (c2 = 0; c2 < NUM_FLIES; c2++) {
2444 flies[c2].back[main_info.draw_page] = get_pixel(main_info.draw_page, flies[c2].x, flies[c2].y);
2445 flies[c2].back_defined[main_info.draw_page] = 1;
2446 if (mask_pic[(flies[c2].y * JNB_WIDTH) + flies[c2].x] == 0)
2447 set_pixel(main_info.draw_page, flies[c2].x, flies[c2].y, 0);
2451 void draw_pobs(int page)
2458 for (c1 = main_info.page_info[page].num_pobs - 1; c1 >= 0; c1--) {
2459 main_info.page_info[page].pobs[c1].back_buf_ofs = back_buf_ofs;
2460 get_block(page, main_info.page_info[page].pobs[c1].x - pob_hs_x(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), main_info.page_info[page].pobs[c1].y - pob_hs_y(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), (unsigned char *)main_info.pob_backbuf[page] + back_buf_ofs);
2462 back_buf_ofs += pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * 4;
2464 back_buf_ofs += pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data) * pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data);
2465 put_pob(page, main_info.page_info[page].pobs[c1].x, main_info.page_info[page].pobs[c1].y, main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data, 1, mask_pic);
2471 void redraw_flies_background(int page)
2475 for (c2 = NUM_FLIES - 1; c2 >= 0; c2--) {
2476 if (flies[c2].back_defined[page] == 1)
2477 set_pixel(page, flies[c2].old_draw_x, flies[c2].old_draw_y, flies[c2].back[page]);
2478 flies[c2].old_draw_x = flies[c2].x;
2479 flies[c2].old_draw_y = flies[c2].y;
2484 void redraw_pob_backgrounds(int page)
2488 for (c1 = 0; c1 < main_info.page_info[page].num_pobs; c1++)
2489 put_block(page, main_info.page_info[page].pobs[c1].x - pob_hs_x(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), main_info.page_info[page].pobs[c1].y - pob_hs_y(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_width(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), pob_height(main_info.page_info[page].pobs[c1].image, main_info.page_info[page].pobs[c1].pob_data), (unsigned char *)main_info.pob_backbuf[page] + main_info.page_info[page].pobs[c1].back_buf_ofs);
2494 int add_leftovers(int page, int x, int y, int image, gob_t *pob_data)
2497 if (leftovers.page[page].num_pobs >= NUM_LEFTOVERS)
2500 leftovers.page[page].pobs[leftovers.page[page].num_pobs].x = x;
2501 leftovers.page[page].pobs[leftovers.page[page].num_pobs].y = y;
2502 leftovers.page[page].pobs[leftovers.page[page].num_pobs].image = image;
2503 leftovers.page[page].pobs[leftovers.page[page].num_pobs].pob_data = pob_data;
2504 leftovers.page[page].num_pobs++;
2511 void draw_leftovers(int page)
2515 for (c1 = leftovers.page[page].num_pobs - 1; c1 >= 0; c1--)
2516 put_pob(page, leftovers.page[page].pobs[c1].x, leftovers.page[page].pobs[c1].y, leftovers.page[page].pobs[c1].image, leftovers.page[page].pobs[c1].pob_data, 1, mask_pic);
2518 leftovers.page[page].num_pobs = 0;
2523 int init_level(int level, char *pal)
2525 unsigned char *handle;
2529 if ((handle = dat_open("level.pcx")) == 0) {
2530 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2533 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2534 strcpy(main_info.error_str, "Error loading 'level.pcx', aborting...\n");
2538 flip_pixels(background_pic);
2539 if ((handle = dat_open("mask.pcx")) == 0) {
2540 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2543 if (read_pcx(handle, mask_pic, JNB_WIDTH*JNB_HEIGHT, 0) != 0) {
2544 strcpy(main_info.error_str, "Error loading 'mask.pcx', aborting...\n");
2548 flip_pixels(mask_pic);
2549 register_mask(mask_pic);
2551 for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) {
2552 if (player[c1].enabled == 1) {
2553 player[c1].bumps = 0;
2554 for (c2 = 0; c2 < JNB_MAX_PLAYERS; c2++)
2555 player[c1].bumped[c2] = 0;
2556 position_player(c1);
2560 for (c1 = 0; c1 < NUM_OBJECTS; c1++)
2561 objects[c1].used = 0;
2563 for (c1 = 0; c1 < 16; c1++) {
2564 for (c2 = 0; c2 < 22; c2++) {
2565 if (ban_map[c1][c2] == BAN_SPRING)
2566 add_object(OBJ_SPRING, c2 << 4, c1 << 4, 0, 0, OBJ_ANIM_SPRING, 5);
2573 if (ban_map[s2][s1] == BAN_VOID) {
2574 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2581 if (ban_map[s2][s1] == BAN_VOID) {
2582 add_object(OBJ_YEL_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2589 if (ban_map[s2][s1] == BAN_VOID) {
2590 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2597 if (ban_map[s2][s1] == BAN_VOID) {
2598 add_object(OBJ_PINK_BUTFLY, (s1 << 4) + 8, (s2 << 4) + 8, (rnd(65535) - 32768) * 2, (rnd(65535) - 32768) * 2, 0, 0);
2608 void deinit_level(void)
2616 #define PATH_MAX 1024
2622 unsigned char *datafile_buffer = NULL;
2624 static void preread_datafile(const char *fname)
2634 #ifdef BZLIB_SUPPORT
2639 #ifdef BZLIB_SUPPORT
2640 bzfilename = malloc(strlen(fname) + 5);
2641 strcpy(bzfilename, fname);
2642 strcat(bzfilename, ".bz2");
2643 bzf = BZ2_bzopen(bzfilename, "rb");
2653 if (bufpos >= bufsize) {
2654 bufsize += 1024 * 1024;
2655 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2656 if (datafile_buffer == NULL) {
2657 perror("realloc()");
2662 br = BZ2_bzread(bzf, datafile_buffer + bufpos, bufsize - bufpos);
2664 fprintf(stderr, "gzread failed.\n");
2671 /* try to shrink buffer... */
2672 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2674 datafile_buffer = ptr;
2680 /* drop through and try for an gzip compressed or uncompressed datafile... */
2684 gzfilename = malloc(strlen(fname) + 4);
2685 strcpy(gzfilename, fname);
2686 strcat(gzfilename, ".gz");
2687 gzf = gzopen(gzfilename, "rb");
2697 if (bufpos >= bufsize) {
2698 bufsize += 1024 * 1024;
2699 datafile_buffer = (unsigned char *) realloc(datafile_buffer, bufsize);
2700 if (datafile_buffer == NULL) {
2701 perror("realloc()");
2706 br = gzread(gzf, datafile_buffer + bufpos, bufsize - bufpos);
2708 fprintf(stderr, "gzread failed.\n");
2713 } while (!gzeof(gzf));
2715 /* try to shrink buffer... */
2716 ptr = (unsigned char *) realloc(datafile_buffer, bufpos);
2718 datafile_buffer = ptr;
2724 /* drop through and try for an uncompressed datafile... */
2727 fd = open(fname, O_RDONLY | O_BINARY);
2729 fprintf(stderr, "can't open %s:", fname);
2734 len = filelength(fd);
2735 datafile_buffer = (unsigned char *) malloc(len);
2736 if (datafile_buffer == NULL) {
2742 if (read(fd, datafile_buffer, len) != len) {
2752 int init_program(int argc, char *argv[], char *pal)
2754 char *netarg = NULL;
2755 unsigned char *handle = (unsigned char *) NULL;
2760 int player_anim_data[] = {
2761 1, 0, 0, 0x7fff, 0, 0, 0, 0, 0, 0,
2762 4, 0, 0, 4, 1, 4, 2, 4, 3, 4,
2763 1, 0, 4, 0x7fff, 0, 0, 0, 0, 0, 0,
2764 4, 2, 5, 8, 6, 10, 7, 3, 6, 3,
2765 1, 0, 6, 0x7fff, 0, 0, 0, 0, 0, 0,
2766 2, 1, 5, 8, 4, 0x7fff, 0, 0, 0, 0,
2767 1, 0, 8, 5, 0, 0, 0, 0, 0, 0
2771 memset(&net_info, 0, sizeof(net_info));
2775 if (__djgpp_nearptr_enable() == 0)
2781 if (hook_keyb_handler() != 0)
2784 memset(&main_info, 0, sizeof(main_info));
2786 strcpy(datfile_name, DATA_PATH);
2788 force2 = force3 = 0;
2791 for (c1 = 1; c1 < argc; c1++) {
2792 if (stricmp(argv[c1], "-nosound") == 0)
2793 main_info.no_sound = 1;
2794 else if (stricmp(argv[c1], "-musicnosound") == 0)
2795 main_info.music_no_sound = 1;
2796 else if (stricmp(argv[c1], "-nogore") == 0)
2797 main_info.no_gore = 1;
2798 else if (stricmp(argv[c1], "-noflies") == 0)
2800 else if (stricmp(argv[c1], "-nojoy") == 0)
2801 main_info.joy_enabled = 0;
2802 else if (stricmp(argv[c1], "-fireworks") == 0)
2803 main_info.fireworks = 1;
2805 else if (stricmp(argv[c1], "-fullscreen") == 0)
2808 else if (stricmp(argv[c1], "-scaleup") == 0)
2810 else if (stricmp(argv[c1], "-mirror") == 0)
2812 else if (stricmp(argv[c1], "-dat") == 0) {
2813 if (c1 < (argc - 1)) {
2816 if ((f = fopen(argv[c1 + 1], "rb")) != NULL) {
2818 strcpy(datfile_name, argv[c1 + 1]);
2821 } else if (stricmp(argv[c1], "-player") == 0) {
2822 if (c1 < (argc - 1)) {
2823 if (client_player_num < 0)
2824 client_player_num = atoi(argv[c1 + 1]);
2827 } else if (stricmp(argv[c1], "-server") == 0) {
2828 if (c1 < (argc - 1)) {
2831 netarg = argv[c1 + 1];
2833 } else if (stricmp(argv[c1], "-connect") == 0) {
2834 if (c1 < (argc - 1)) {
2837 netarg = argv[c1 + 1];
2840 } else if (stricmp(argv[c1], "-mouse") == 0) {
2841 if (c1 < (argc - 1)) {
2842 if (stricmp(argv[c1 + 1], "2") == 0)
2844 if (stricmp(argv[c1 + 1], "3") == 0)
2848 else if (strstr(argv[1],"-v")) {
2849 printf("jumpnbump %s compiled %s at %s with",JNB_VERSION,__DATE__,__TIME__);
2853 printf(" network support.\n");
2856 else if (strstr(argv[1],"-h")) {
2857 printf("Usage: jumpnbump [OPTION]...\n");
2859 printf(" -h this help\n");
2860 printf(" -v print version\n");
2861 printf(" -dat level.dat play a different level\n");
2863 printf(" -server playercount start as server waiting for players\n");
2864 printf(" -connect host connect to server\n");
2866 printf(" -player num set main player to num (0-3). Needed for networking\n");
2867 printf(" -fireworks screensaver mode\n");
2868 printf(" -fullscreen run in fullscreen mode\n");
2869 printf(" -nosound play without sound\n");
2870 printf(" -nogore play without blood\n");
2871 printf(" -noflies disable flies\n");
2872 printf(" -mirror play with mirrored level\n");
2873 printf(" -scaleup play with doubled resolution (800x512)\n");
2874 printf(" -musicnosound play with music but without sound\n");
2881 preread_datafile(datfile_name);
2884 /** It should not be necessary to assign a default player number here. The
2885 server assigns one in init_server, the client gets one assigned by the server,
2886 all provided the user didn't choose one on the commandline. */
2888 if (client_player_num < 0)
2889 client_player_num = 0;
2890 player[client_player_num].enabled = 1;
2894 main_info.pob_backbuf[0] = malloc(screen_pitch*screen_height);
2895 main_info.pob_backbuf[1] = malloc(screen_pitch*screen_height);
2897 for (c1 = 0; c1 < 7; c1++) {
2898 player_anims[c1].num_frames = player_anim_data[c1 * 10];
2899 player_anims[c1].restart_frame = player_anim_data[c1 * 10 + 1];
2900 for (c2 = 0; c2 < 4; c2++) {
2901 player_anims[c1].frame[c2].image = player_anim_data[c1 * 10 + c2 * 2 + 2];
2902 player_anims[c1].frame[c2].ticks = player_anim_data[c1 * 10 + c2 * 2 + 3];
2906 if ((handle = dat_open("menu.pcx")) == 0) {
2907 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2910 if (read_pcx(handle, background_pic, JNB_WIDTH*JNB_HEIGHT, pal) != 0) {
2911 strcpy(main_info.error_str, "Error loading 'menu.pcx', aborting...\n");
2915 if ((handle = dat_open("rabbit.gob")) == 0) {
2916 strcpy(main_info.error_str, "Error loading 'rabbit.gob', aborting...\n");
2919 if (register_gob(handle, &rabbit_gobs, dat_filelen("rabbit.gob"))) {
2924 if ((handle = dat_open("objects.gob")) == 0) {
2925 strcpy(main_info.error_str, "Error loading 'objects.gob', aborting...\n");
2928 if (register_gob(handle, &object_gobs, dat_filelen("objects.gob"))) {
2933 if ((handle = dat_open("font.gob")) == 0) {
2934 strcpy(main_info.error_str, "Error loading 'font.gob', aborting...\n");
2937 if (register_gob(handle, &font_gobs, dat_filelen("font.gob"))) {
2942 if ((handle = dat_open("numbers.gob")) == 0) {
2943 strcpy(main_info.error_str, "Error loading 'numbers.gob', aborting...\n");
2946 if (register_gob(handle, &number_gobs, dat_filelen("numbers.gob"))) {
2951 if (read_level() != 0) {
2952 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
2958 if (main_info.no_sound == 0) {
2960 dj_set_mixing_freq(20000);
2964 dj_set_num_sfx_channels(5);
2965 dj_set_sfx_volume(64);
2969 if ((handle = dat_open("jump.mod")) == 0) {
2970 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2973 if (dj_load_mod(handle, 0, MOD_MENU) != 0) {
2974 strcpy(main_info.error_str, "Error loading 'jump.mod', aborting...\n");
2978 if ((handle = dat_open("bump.mod")) == 0) {
2979 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2982 if (dj_load_mod(handle, 0, MOD_GAME) != 0) {
2983 strcpy(main_info.error_str, "Error loading 'bump.mod', aborting...\n");
2987 if ((handle = dat_open("scores.mod")) == 0) {
2988 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2991 if (dj_load_mod(handle, 0, MOD_SCORES) != 0) {
2992 strcpy(main_info.error_str, "Error loading 'scores.mod', aborting...\n");
2996 if ((handle = dat_open("jump.smp")) == 0) {
2997 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3000 if (dj_load_sfx(handle, 0, dat_filelen("jump.smp"), DJ_SFX_TYPE_SMP, SFX_JUMP) != 0) {
3001 strcpy(main_info.error_str, "Error loading 'jump.smp', aborting...\n");
3005 if ((handle = dat_open("death.smp")) == 0) {
3006 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3009 if (dj_load_sfx(handle, 0, dat_filelen("death.smp"), DJ_SFX_TYPE_SMP, SFX_DEATH) != 0) {
3010 strcpy(main_info.error_str, "Error loading 'death.smp', aborting...\n");
3014 if ((handle = dat_open("spring.smp")) == 0) {
3015 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3018 if (dj_load_sfx(handle, 0, dat_filelen("spring.smp"), DJ_SFX_TYPE_SMP, SFX_SPRING) != 0) {
3019 strcpy(main_info.error_str, "Error loading 'spring.smp', aborting...\n");
3023 if ((handle = dat_open("splash.smp")) == 0) {
3024 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3027 if (dj_load_sfx(handle, 0, dat_filelen("splash.smp"), DJ_SFX_TYPE_SMP, SFX_SPLASH) != 0) {
3028 strcpy(main_info.error_str, "Error loading 'splash.smp', aborting...\n");
3032 if ((handle = dat_open("fly.smp")) == 0) {
3033 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3036 if (dj_load_sfx(handle, 0, dat_filelen("fly.smp"), DJ_SFX_TYPE_SMP, SFX_FLY) != 0) {
3037 strcpy(main_info.error_str, "Error loading 'fly.smp', aborting...\n");
3041 dj_get_sfx_settings(SFX_FLY, &fly);
3043 fly.default_freq = SFX_FLY_FREQ;
3046 fly.loop_length = fly.length;
3047 dj_set_sfx_settings(SFX_FLY, &fly);
3050 if ((background_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3052 if ((mask_pic = malloc(JNB_WIDTH*JNB_HEIGHT)) == NULL)
3054 memset(mask_pic, 0, JNB_WIDTH*JNB_HEIGHT);
3055 register_mask(mask_pic);
3058 for (c1 = 0; c1 < 16; c1++) {
3059 pal[(240 + c1) * 3 + 0] = c1 << 2;
3060 pal[(240 + c1) * 3 + 1] = c1 << 2;
3061 pal[(240 + c1) * 3 + 2] = c1 << 2;
3064 setpalette(0, 256, pal);
3068 recalculate_gob(&font_gobs, pal);
3070 if (main_info.joy_enabled == 1 && main_info.fireworks == 0) {
3072 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3073 put_text(0, 200, 100, "Move the joystick to the", 2);
3074 put_text(0, 200, 115, "UPPER LEFT", 2);
3075 put_text(0, 200, 130, "and press button A", 2);
3076 put_text(0, 200, 200, "Or press ESC to use", 2);
3077 put_text(0, 200, 215, "previous settings", 2);
3078 if (calib_joy(0) != 0)
3081 register_background(NULL, NULL);
3083 main_info.view_page = 1;
3088 put_text(1, 200, 40, "JOYSTICK CALIBRATION", 2);
3089 put_text(1, 200, 100, "Move the joystick to the", 2);
3090 put_text(1, 200, 115, "LOWER RIGHT", 2);
3091 put_text(1, 200, 130, "and press button A", 2);
3092 put_text(1, 200, 200, "Or press ESC to use", 2);
3093 put_text(1, 200, 215, "previous settings", 2);
3094 if (calib_joy(1) != 0)
3097 register_background(NULL, NULL);
3102 put_text(0, 200, 40, "JOYSTICK CALIBRATION", 2);
3103 put_text(0, 200, 100, "Move the joystick to the", 2);
3104 put_text(0, 200, 115, "CENTER", 2);
3105 put_text(0, 200, 130, "and press button A", 2);
3106 put_text(0, 200, 200, "Or press ESC to use", 2);
3107 put_text(0, 200, 215, "previous settings", 2);
3108 if (calib_joy(2) != 0)
3111 if (joy.calib_data.x1 == joy.calib_data.x2)
3112 joy.calib_data.x1 -= 10;
3113 if (joy.calib_data.x3 == joy.calib_data.x2)
3114 joy.calib_data.x3 += 10;
3115 if (joy.calib_data.y1 == joy.calib_data.y2)
3116 joy.calib_data.y1 -= 10;
3117 if (joy.calib_data.y3 == joy.calib_data.y2)
3118 joy.calib_data.y3 += 10;
3123 if (load_flag == 1) {
3124 if ((handle = dat_open("calib.dat")) == 0) {
3125 strcpy(main_info.error_str, "Error loading 'calib.dat', aborting...\n");
3128 joy.calib_data.x1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3129 joy.calib_data.x2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3130 joy.calib_data.x3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3131 joy.calib_data.y1 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3132 joy.calib_data.y2 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3133 joy.calib_data.y3 = (handle[0]) + (handle[1] << 8) + (handle[2] << 16) + (handle[3] << 24); handle += 4;
3140 init_server(netarg);
3142 connect_to_server(netarg);
3151 void deinit_program(void)
3158 dj_free_mod(MOD_MENU);
3159 dj_free_mod(MOD_GAME);
3160 dj_free_sfx(SFX_DEATH);
3161 dj_free_sfx(SFX_SPRING);
3162 dj_free_sfx(SFX_SPLASH);
3165 if (background_pic != 0)
3166 free(background_pic);
3170 remove_keyb_handler();
3174 __dpmi_int(0x10, ®s);
3177 if (main_info.error_str[0] != 0) {
3178 printf(main_info.error_str);
3180 MessageBox(0, main_info.error_str, "Jump'n'Bump", 0);
3189 unsigned short rnd(unsigned short max)
3191 #if (RAND_MAX < 0x7fff)
3192 #error "rand returns too small values"
3193 #elif (RAND_MAX == 0x7fff)
3194 return (unsigned short)((rand()*2) % (int)max);
3196 return (unsigned short)(rand() % (int)max);
3201 int read_level(void)
3203 unsigned char *handle;
3207 if ((handle = dat_open("levelmap.txt")) == 0) {
3208 strcpy(main_info.error_str, "Error loading 'levelmap.txt', aborting...\n");
3212 for (c1 = 0; c1 < 16; c1++) {
3213 for (c2 = 0; c2 < 22; c2++) {
3215 chr = (int) *(handle++);
3216 if (chr >= '0' && chr <= '4')
3220 ban_map[c1][21-c2] = chr - '0';
3222 ban_map[c1][c2] = chr - '0';
3226 for (c2 = 0; c2 < 22; c2++)
3227 ban_map[16][c2] = BAN_SOLID;
3234 unsigned char *dat_open(char *file_name)
3242 if (datafile_buffer == NULL)
3245 memset(name, 0, sizeof(name));
3247 num = ( (datafile_buffer[0] << 0) +
3248 (datafile_buffer[1] << 8) +
3249 (datafile_buffer[2] << 16) +
3250 (datafile_buffer[3] << 24) );
3252 ptr = datafile_buffer + 4;
3254 for (c1 = 0; c1 < num; c1++) {
3256 memcpy(name, ptr, 12);
3259 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3260 ofs = ( (ptr[0] << 0) +
3265 return (datafile_buffer + ofs);
3274 int dat_filelen(char *file_name)
3282 memset(name, 0, sizeof(name));
3284 num = ( (datafile_buffer[0] << 0) +
3285 (datafile_buffer[1] << 8) +
3286 (datafile_buffer[2] << 16) +
3287 (datafile_buffer[3] << 24) );
3289 ptr = datafile_buffer + 4;
3291 for (c1 = 0; c1 < num; c1++) {
3293 memcpy(name, ptr, 12);
3296 if (strnicmp(name, file_name, strlen(file_name)) == 0) {
3299 len = ( (ptr[0] << 0) +
3313 void write_calib_data(void)
3321 if ((handle = fopen(datfile_name, "rb")) == NULL)
3323 len = filelength(fileno(handle));
3324 if ((mem = malloc(len)) == NULL)
3326 fread(mem, 1, len, handle);
3330 num = *(int *) (&mem[0]);
3331 for (c1 = 0; c1 < num; c1++) {
3332 if (strnicmp(&mem[ofs], "calib.dat", strlen("calib.dat")) == 0) {
3333 ofs = *(int *) (&mem[ofs + 12]);
3339 mem[ofs] = joy.calib_data.x1 & 0xff;
3340 mem[ofs + 1] = (joy.calib_data.x1 >> 8) & 0xff;
3341 mem[ofs + 2] = (joy.calib_data.x1 >> 16) & 0xff;
3342 mem[ofs + 3] = (joy.calib_data.x1 >> 24) & 0xff;
3343 mem[ofs + 4] = joy.calib_data.x2 & 0xff;
3344 mem[ofs + 5] = (joy.calib_data.x2 >> 8) & 0xff;
3345 mem[ofs + 6] = (joy.calib_data.x2 >> 16) & 0xff;
3346 mem[ofs + 7] = (joy.calib_data.x2 >> 24) & 0xff;
3347 mem[ofs + 8] = joy.calib_data.x3 & 0xff;
3348 mem[ofs + 9] = (joy.calib_data.x3 >> 8) & 0xff;
3349 mem[ofs + 10] = (joy.calib_data.x3 >> 16) & 0xff;
3350 mem[ofs + 11] = (joy.calib_data.x3 >> 24) & 0xff;
3351 mem[ofs + 12] = joy.calib_data.y1 & 0xff;
3352 mem[ofs + 13] = (joy.calib_data.y1 >> 8) & 0xff;
3353 mem[ofs + 14] = (joy.calib_data.y1 >> 16) & 0xff;
3354 mem[ofs + 15] = (joy.calib_data.y1 >> 24) & 0xff;
3355 mem[ofs + 16] = joy.calib_data.y2 & 0xff;
3356 mem[ofs + 17] = (joy.calib_data.y2 >> 8) & 0xff;
3357 mem[ofs + 18] = (joy.calib_data.y2 >> 16) & 0xff;
3358 mem[ofs + 19] = (joy.calib_data.y2 >> 24) & 0xff;
3359 mem[ofs + 20] = joy.calib_data.y3 & 0xff;
3360 mem[ofs + 21] = (joy.calib_data.y3 >> 8) & 0xff;
3361 mem[ofs + 22] = (joy.calib_data.y3 >> 16) & 0xff;
3362 mem[ofs + 23] = (joy.calib_data.y3 >> 24) & 0xff;
3364 if ((handle = fopen(datfile_name, "wb")) == NULL)
3366 fwrite(mem, 1, len, handle);