| //------------------------------------------------------------------------- |
| /* |
| Copyright (C) 1996, 2003 - 3D Realms Entertainment |
| |
| This file is part of Duke Nukem 3D version 1.5 - Atomic Edition |
| |
| Duke Nukem 3D is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| |
| See the GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| aint32_t with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| Original Source: 1996 - Todd Replogle |
| Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms |
| */ |
| //------------------------------------------------------------------------- |
| |
| #include "duke3d.h" |
| |
| |
| extern short otherp; |
| |
| static short total_lines,line_number; |
| static uint8_t checking_ifelse,parsing_state; |
| char *last_used_text; |
| static short num_squigilly_brackets; |
| static int32_t last_used_size; |
| |
| static short g_i,g_p; |
| static int32_t g_x; |
| static int32_t *g_t; |
| static spritetype *g_sp; |
| |
| #define NUMKEYWORDS 112 |
| |
| //From global.c |
| void FixFilePath(char *filename); |
| |
| //From actors.c |
| void lotsofmail(spritetype *s, short n); |
| void lotsofpaper(spritetype *s, short n); |
| |
| char *keyw[NUMKEYWORDS] = |
| { |
| "definelevelname", // 0 |
| "actor", // 1 [#] |
| "addammo", // 2 [#] |
| "ifrnd", // 3 [C] |
| "enda", // 4 [:] |
| "ifcansee", // 5 [C] |
| "ifhitweapon", // 6 [#] |
| "action", // 7 [#] |
| "ifpdistl", // 8 [#] |
| "ifpdistg", // 9 [#] |
| "else", // 10 [#] |
| "strength", // 11 [#] |
| "break", // 12 [#] |
| "shoot", // 13 [#] |
| "palfrom", // 14 [#] |
| "sound", // 15 [filename.voc] |
| "fall", // 16 [] |
| "state", // 17 |
| "ends", // 18 |
| "define", // 19 |
| "//", // 20 |
| "ifai", // 21 |
| "killit", // 22 |
| "addweapon", // 23 |
| "ai", // 24 |
| "addphealth", // 25 |
| "ifdead", // 26 |
| "ifsquished", // 27 |
| "sizeto", // 28 |
| "{", // 29 |
| "}", // 30 |
| "spawn", // 31 |
| "move", // 32 |
| "ifwasweapon", // 33 |
| "ifaction", // 34 |
| "ifactioncount", // 35 |
| "resetactioncount", // 36 |
| "debris", // 37 |
| "pstomp", // 38 |
| "/*", // 39 |
| "cstat", // 40 |
| "ifmove", // 41 |
| "resetplayer", // 42 |
| "ifonwater", // 43 |
| "ifinwater", // 44 |
| "ifcanshoottarget", // 45 |
| "ifcount", // 46 |
| "resetcount", // 47 |
| "addinventory", // 48 |
| "ifactornotstayput",// 49 |
| "hitradius", // 50 |
| "ifp", // 51 |
| "count", // 52 |
| "ifactor", // 53 |
| "music", // 54 |
| "include", // 55 |
| "ifstrength", // 56 |
| "definesound", // 57 |
| "guts", // 58 |
| "ifspawnedby", // 59 |
| "gamestartup", // 60 |
| "wackplayer", // 61 |
| "ifgapzl", // 62 |
| "ifhitspace", // 63 |
| "ifoutside", // 64 |
| "ifmultiplayer", // 65 |
| "operate", // 66 |
| "ifinspace", // 67 |
| "debug", // 68 |
| "endofgame", // 69 |
| "ifbulletnear", // 70 |
| "ifrespawn", // 71 |
| "iffloordistl", // 72 |
| "ifceilingdistl", // 73 |
| "spritepal", // 74 |
| "ifpinventory", // 75 |
| "betaname", // 76 |
| "cactor", // 77 |
| "ifphealthl", // 78 |
| "definequote", // 79 |
| "quote", // 80 |
| "ifinouterspace", // 81 |
| "ifnotmoving", // 82 |
| "respawnhitag", // 83 |
| "tip", // 84 |
| "ifspritepal", // 85 |
| "money", // 86 |
| "soundonce", // 87 |
| "addkills", // 88 |
| "stopsound", // 89 |
| "ifawayfromwall", // 90 |
| "ifcanseetarget", // 91 |
| "globalsound", // 92 |
| "lotsofglass", // 93 |
| "ifgotweaponce", // 94 |
| "getlastpal", // 95 |
| "pkick", // 96 |
| "mikesnd", // 97 |
| "useractor", // 98 |
| "sizeat", // 99 |
| "addstrength", // 100 [#] |
| "cstator", // 101 |
| "mail", // 102 |
| "paper", // 103 |
| "tossweapon", // 104 |
| "sleeptime", // 105 |
| "nullop", // 106 |
| "definevolumename", // 107 |
| "defineskillname", // 108 |
| "ifnosounds", // 109 |
| "clipdist", // 110 |
| "ifangdiffl" // 111 |
| }; |
| |
| |
| short getincangle(short a,short na) |
| { |
| a &= 2047; |
| na &= 2047; |
| |
| if(klabs(a-na) < 1024) |
| return (na-a); |
| else |
| { |
| if(na > 1024) na -= 2048; |
| if(a > 1024) a -= 2048; |
| |
| na -= 2048; |
| a -= 2048; |
| return (na-a); |
| } |
| } |
| |
| uint8_t ispecial(uint8_t c) |
| { |
| if(c == 0x0a) |
| { |
| line_number++; |
| return 1; |
| } |
| |
| if(c == ' ' || c == 0x0d) |
| return 1; |
| |
| return 0; |
| } |
| |
| uint8_t isaltok(uint8_t c) |
| { |
| return ( isalnum(c) || c == '{' || c == '}' || c == '/' || c == '*' || c == '-' || c == '_' || c == '.'); |
| } |
| |
| void getglobalz(short i) |
| { |
| int32_t hz,lz,zr; |
| |
| spritetype *s = &sprite[i]; |
| |
| if( s->statnum == 10 || s->statnum == 6 || s->statnum == 2 || s->statnum == 1 || s->statnum == 4) |
| { |
| if(s->statnum == 4) |
| zr = 4L; |
| else zr = 127L; |
| |
| getzrange(s->x,s->y,s->z-(FOURSLEIGHT),s->sectnum,&hittype[i].ceilingz,&hz,&hittype[i].floorz,&lz,zr,CLIPMASK0); |
| |
| if( (lz&49152) == 49152 && (sprite[lz&(MAXSPRITES-1)].cstat&48) == 0 ) |
| { |
| lz &= (MAXSPRITES-1); |
| if( badguy(&sprite[lz]) && sprite[lz].pal != 1) |
| { |
| if( s->statnum != 4 ) |
| { |
| hittype[i].dispicnum = -4; // No shadows on actors |
| s->xvel = -256; |
| ssp(i,CLIPMASK0); |
| } |
| } |
| else if(sprite[lz].picnum == APLAYER && badguy(s) ) |
| { |
| hittype[i].dispicnum = -4; // No shadows on actors |
| s->xvel = -256; |
| ssp(i,CLIPMASK0); |
| } |
| else if(s->statnum == 4 && sprite[lz].picnum == APLAYER) |
| if(s->owner == lz) |
| { |
| hittype[i].ceilingz = sector[s->sectnum].ceilingz; |
| hittype[i].floorz = sector[s->sectnum].floorz; |
| } |
| } |
| } |
| else |
| { |
| hittype[i].ceilingz = sector[s->sectnum].ceilingz; |
| hittype[i].floorz = sector[s->sectnum].floorz; |
| } |
| } |
| |
| |
| void makeitfall(short i) |
| { |
| spritetype *s = &sprite[i]; |
| int32_t hz,lz,c; |
| |
| if( floorspace(s->sectnum) ) |
| c = 0; |
| else |
| { |
| if( ceilingspace(s->sectnum) || sector[s->sectnum].lotag == 2) |
| c = gc/6; |
| else c = gc; |
| } |
| |
| if( ( s->statnum == 1 || s->statnum == 10 || s->statnum == 2 || s->statnum == 6 ) ) |
| getzrange(s->x,s->y,s->z-(FOURSLEIGHT),s->sectnum,&hittype[i].ceilingz,&hz,&hittype[i].floorz,&lz,127L,CLIPMASK0); |
| else |
| { |
| hittype[i].ceilingz = sector[s->sectnum].ceilingz; |
| hittype[i].floorz = sector[s->sectnum].floorz; |
| } |
| |
| if( s->z < hittype[i].floorz-(FOURSLEIGHT) ) |
| { |
| if( sector[s->sectnum].lotag == 2 && s->zvel > 3122 ) |
| s->zvel = 3144; |
| if(s->zvel < 6144) |
| s->zvel += c; |
| else s->zvel = 6144; |
| s->z += s->zvel; |
| } |
| if( s->z >= hittype[i].floorz-(FOURSLEIGHT) ) |
| { |
| s->z = hittype[i].floorz - FOURSLEIGHT; |
| s->zvel = 0; |
| } |
| } |
| |
| |
| void getlabel(void) |
| { |
| int32_t i; |
| |
| while( isalnum(*textptr) == 0 ) |
| { |
| if(*textptr == 0x0a) line_number++; |
| textptr++; |
| if( *textptr == 0) |
| return; |
| } |
| |
| i = 0; |
| while( ispecial(*textptr) == 0 ) |
| label[(labelcnt<<6)+i++] = *(textptr++); |
| |
| label[(labelcnt<<6)+i] = 0; |
| } |
| |
| int32_t keyword(void) |
| { |
| int32_t i; |
| char *temptextptr; |
| |
| temptextptr = textptr; |
| |
| while( isaltok(*temptextptr) == 0 ) |
| { |
| temptextptr++; |
| if( *temptextptr == 0 ) |
| return 0; |
| } |
| |
| i = 0; |
| while( isaltok(*temptextptr) ) |
| { |
| tempbuf[i] = *(temptextptr++); |
| i++; |
| } |
| tempbuf[i] = 0; |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( (const char *)tempbuf,keyw[i]) == 0 ) |
| return i; |
| |
| return -1; |
| } |
| |
| int32_t transword(void) //Returns its code # |
| { |
| int32_t i, l; |
| |
| while( isaltok(*textptr) == 0 ) |
| { |
| if(*textptr == 0x0a) line_number++; |
| if( *textptr == 0 ) |
| return -1; |
| textptr++; |
| } |
| |
| l = 0; |
| while( isaltok(*(textptr+l)) ) |
| { |
| tempbuf[l] = textptr[l]; |
| l++; |
| } |
| tempbuf[l] = 0; |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| { |
| if( strcmp( (const char *)tempbuf,keyw[i]) == 0 ) |
| { |
| *scriptptr = i; |
| textptr += l; |
| scriptptr++; |
| return i; |
| } |
| } |
| |
| textptr += l; |
| |
| if( tempbuf[0] == '{' && tempbuf[1] != 0) |
| printf(" * ERROR!(L%hd) Expecting a SPACE or CR between '{' and '%s'.\n",line_number,tempbuf+1); |
| else if( tempbuf[0] == '}' && tempbuf[1] != 0) |
| printf(" * ERROR!(L%hd) Expecting a SPACE or CR between '}' and '%s'.\n",line_number,tempbuf+1); |
| else if( tempbuf[0] == '/' && tempbuf[1] == '/' && tempbuf[2] != 0 ) |
| printf(" * ERROR!(L%hd) Expecting a SPACE between '//' and '%s'.\n",line_number,tempbuf+2); |
| else if( tempbuf[0] == '/' && tempbuf[1] == '*' && tempbuf[2] != 0 ) |
| printf(" * ERROR!(L%hd) Expecting a SPACE between '/*' and '%s'.\n",line_number,tempbuf+2); |
| else if( tempbuf[0] == '*' && tempbuf[1] == '/' && tempbuf[2] != 0 ) |
| printf(" * ERROR!(L%hd) Expecting a SPACE between '*/' and '%s'.\n",line_number,tempbuf+2); |
| else printf(" * ERROR!(L%hd) Expecting key word, but found '%s'.\n",line_number,tempbuf); |
| |
| error++; |
| return -1; |
| } |
| |
| void transnum(void) |
| { |
| int32_t i, l; |
| |
| while( isaltok(*textptr) == 0 ) |
| { |
| if(*textptr == 0x0a) line_number++; |
| textptr++; |
| if( *textptr == 0 ) |
| return; |
| } |
| |
| |
| l = 0; |
| while( isaltok(*(textptr+l)) ) |
| { |
| tempbuf[l] = textptr[l]; |
| l++; |
| } |
| tempbuf[l] = 0; |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( label+(labelcnt<<6),keyw[i]) == 0 ) |
| { |
| error++; |
| printf(" * ERROR!(L%hd) Symbol '%s' is a key word.\n",line_number,label+(labelcnt<<6)); |
| textptr+=l; |
| } |
| |
| |
| for(i=0;i<labelcnt;i++) |
| { |
| if( strcmp((const char *)tempbuf,label+(i<<6)) == 0 ) |
| { |
| *scriptptr = labelcode[i]; |
| scriptptr++; |
| textptr += l; |
| return; |
| } |
| } |
| |
| if( isdigit(*textptr) == 0 && *textptr != '-') |
| { |
| printf(" * ERROR!(L%hd) Parameter '%s' is undefined.\n",line_number,tempbuf); |
| error++; |
| textptr+=l; |
| return; |
| } |
| |
| *scriptptr = atol(textptr); |
| scriptptr++; |
| |
| textptr += l; |
| } |
| |
| |
| uint8_t parsecommand(int readfromGRP) |
| { |
| int32_t i, j, k, *tempscrptr; |
| uint8_t done, temp_ifelse_check; |
| int32_t tw; |
| char *origtptr; |
| short temp_line_number; |
| int fp; |
| |
| if( error > 12 || ( *textptr == '\0' ) || ( *(textptr+1) == '\0' ) ) return 1; |
| |
| tw = transword(); |
| |
| switch(tw) |
| { |
| default: |
| case -1: |
| return 0; //End |
| case 39: //Rem endrem |
| scriptptr--; |
| j = line_number; |
| do |
| { |
| textptr++; |
| if(*textptr == 0x0a) line_number++; |
| if( *textptr == 0 ) |
| { |
| printf(" * ERROR!(L%d) Found '/*' with no '*/'.\n",j); |
| error++; |
| return 0; |
| } |
| } |
| while( *textptr != '*' || *(textptr+1) != '/' ); |
| textptr+=2; |
| return 0; |
| case 17: |
| if( parsing_actor == 0 && parsing_state == 0 ) |
| { |
| getlabel(); |
| scriptptr--; |
| labelcode[labelcnt] = (int32_t) scriptptr; |
| labelcnt++; |
| |
| parsing_state = 1; |
| |
| return 0; |
| } |
| |
| getlabel(); |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( label+(labelcnt<<6),keyw[i]) == 0 ) |
| { |
| error++; |
| printf(" * ERROR!(L%hd) Symbol '%s' is a key word.\n",line_number,label+(labelcnt<<6)); |
| return 0; |
| } |
| |
| for(j=0;j<labelcnt;j++) |
| { |
| if( strcmp(label+(j<<6),label+(labelcnt<<6)) == 0 ) |
| { |
| *scriptptr = labelcode[j]; |
| break; |
| } |
| } |
| |
| if(j==labelcnt) |
| { |
| printf(" * ERROR!(L%hd) State '%s' not found.\n",line_number,label+(labelcnt<<6)); |
| error++; |
| } |
| scriptptr++; |
| return 0; |
| |
| case 15: |
| case 92: |
| case 87: |
| case 89: |
| case 93: |
| transnum(); |
| return 0; |
| |
| case 18: |
| if( parsing_state == 0 ) |
| { |
| printf(" * ERROR!(L%hd) Found 'ends' with no 'state'.\n",line_number); |
| error++; |
| } |
| // else |
| { |
| if( num_squigilly_brackets > 0 ) |
| { |
| printf(" * ERROR!(L%hd) Found more '{' than '}' before 'ends'.\n",line_number); |
| error++; |
| } |
| if( num_squigilly_brackets < 0 ) |
| { |
| printf(" * ERROR!(L%hd) Found more '}' than '{' before 'ends'.\n",line_number); |
| error++; |
| } |
| parsing_state = 0; |
| } |
| return 0; |
| case 19: |
| getlabel(); |
| // Check to see it's already defined |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( label+(labelcnt<<6),keyw[i]) == 0 ) |
| { |
| error++; |
| printf(" * ERROR!(L%hd) Symbol '%s' is a key word.\n",line_number,label+(labelcnt<<6)); |
| return 0; |
| } |
| |
| for(i=0;i<labelcnt;i++) |
| { |
| if( strcmp(label+(labelcnt<<6),label+(i<<6)) == 0 ) |
| { |
| warning++; |
| printf(" * WARNING.(L%hd) Duplicate definition '%s' ignored.\n",line_number,label+(labelcnt<<6)); |
| break; |
| } |
| } |
| |
| transnum(); |
| if(i == labelcnt) |
| labelcode[labelcnt++] = *(scriptptr-1); |
| scriptptr -= 2; |
| return 0; |
| case 14: |
| |
| for(j = 0;j < 4;j++) |
| { |
| if( keyword() == -1 ) |
| transnum(); |
| else break; |
| } |
| |
| while(j < 4) |
| { |
| *scriptptr = 0; |
| scriptptr++; |
| j++; |
| } |
| return 0; |
| |
| case 32: |
| if( parsing_actor || parsing_state ) |
| { |
| transnum(); |
| |
| j = 0; |
| while(keyword() == -1) |
| { |
| transnum(); |
| scriptptr--; |
| j |= *scriptptr; |
| } |
| *scriptptr = j; |
| scriptptr++; |
| } |
| else |
| { |
| scriptptr--; |
| getlabel(); |
| // Check to see it's already defined |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( label+(labelcnt<<6),keyw[i]) == 0 ) |
| { |
| error++; |
| printf(" * ERROR!(L%hd) Symbol '%s' is a key word.\n",line_number,label+(labelcnt<<6)); |
| return 0; |
| } |
| |
| for(i=0;i<labelcnt;i++) |
| if( strcmp(label+(labelcnt<<6),label+(i<<6)) == 0 ) |
| { |
| warning++; |
| printf(" * WARNING.(L%hd) Duplicate move '%s' ignored.\n",line_number,label+(labelcnt<<6)); |
| break; |
| } |
| if(i == labelcnt) |
| labelcode[labelcnt++] = (int32_t) scriptptr; |
| for(j=0;j<2;j++) |
| { |
| if(keyword() >= 0) break; |
| transnum(); |
| } |
| for(k=j;k<2;k++) |
| { |
| *scriptptr = 0; |
| scriptptr++; |
| } |
| } |
| return 0; |
| |
| case 54: |
| { |
| scriptptr--; |
| transnum(); // Volume Number (0/4) |
| scriptptr--; |
| |
| k = *scriptptr-1; |
| |
| if(k >= 0) // if it's background music |
| { |
| i = 0; |
| while(keyword() == -1) |
| { |
| while( isaltok(*textptr) == 0 ) |
| { |
| if(*textptr == 0x0a) line_number++; |
| textptr++; |
| if( *textptr == 0 ) break; |
| } |
| j = 0; |
| while( isaltok(*(textptr+j)) ) |
| { |
| music_fn[k][i][j] = textptr[j]; |
| j++; |
| } |
| music_fn[k][i][j] = '\0'; |
| textptr += j; |
| if(i > 9) break; |
| i++; |
| } |
| } |
| else |
| { |
| i = 0; |
| while(keyword() == -1) |
| { |
| while( isaltok(*textptr) == 0 ) |
| { |
| if(*textptr == 0x0a) line_number++; |
| textptr++; |
| if( *textptr == 0 ) break; |
| } |
| j = 0; |
| while( isaltok(*(textptr+j)) ) |
| { |
| env_music_fn[i][j] = textptr[j]; |
| j++; |
| } |
| env_music_fn[i][j] = '\0'; |
| |
| textptr += j; |
| if(i > 9) break; |
| i++; |
| } |
| } |
| } |
| return 0; |
| case 55: // include other con files. |
| { |
| char includedconfile[512]; |
| scriptptr--; |
| while( isaltok(*textptr) == 0 ) |
| { |
| if(*textptr == 0x0a) line_number++; |
| textptr++; |
| if( *textptr == 0 ) break; |
| } |
| j = 0; |
| while( isaltok(*textptr) ) |
| { |
| tempbuf[j] = *(textptr++); |
| j++; |
| } |
| tempbuf[j] = '\0'; |
| |
| // fix path for unix. (doesn't really matter...) |
| FixFilePath((char *)tempbuf); |
| |
| sprintf(includedconfile, "%s/%s", getGameDir(), tempbuf); |
| |
| fp = TCkopen4load(includedconfile,readfromGRP); |
| if(fp <= 0) |
| { |
| error++; |
| printf(" * ERROR!(ln%hd) Could not find '%s'.\n",line_number,label+(labelcnt<<6)); |
| |
| printf("ERROR: could not open (%s)\n", includedconfile); |
| gameexit(""); |
| return 0; |
| } |
| |
| j = kfilelength(fp); |
| |
| printf("Including: '%s'.\n", includedconfile); |
| |
| temp_line_number = line_number; |
| line_number = 1; |
| temp_ifelse_check = checking_ifelse; |
| checking_ifelse = 0; |
| origtptr = textptr; |
| textptr = last_used_text+last_used_size; |
| |
| *(textptr+j) = 0; |
| |
| kread(fp,(uint8_t *)textptr,j); |
| kclose(fp); |
| ud.conCRC[0] = crc32_update((uint8_t *)textptr, j, ud.conCRC[0]); |
| |
| do |
| done = parsecommand(readfromGRP); |
| while( done == 0 ); |
| |
| textptr = origtptr; |
| total_lines += line_number; |
| line_number = temp_line_number; |
| checking_ifelse = temp_ifelse_check; |
| |
| return 0; |
| } |
| case 24: |
| if( parsing_actor || parsing_state ) |
| transnum(); |
| else |
| { |
| scriptptr--; |
| getlabel(); |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( label+(labelcnt<<6),keyw[i]) == 0 ) |
| { |
| error++; |
| printf(" * ERROR!(L%hd) Symbol '%s' is a key word.\n",line_number,label+(labelcnt<<6)); |
| return 0; |
| } |
| |
| for(i=0;i<labelcnt;i++) |
| if( strcmp(label+(labelcnt<<6),label+(i<<6)) == 0 ) |
| { |
| warning++; |
| printf(" * WARNING.(L%hd) Duplicate ai '%s' ignored.\n",line_number,label+(labelcnt<<6)); |
| break; |
| } |
| |
| if(i == labelcnt) |
| labelcode[labelcnt++] = (int32_t) scriptptr; |
| |
| for(j=0;j<3;j++) |
| { |
| if(keyword() >= 0) break; |
| if(j == 2) |
| { |
| k = 0; |
| while(keyword() == -1) |
| { |
| transnum(); |
| scriptptr--; |
| k |= *scriptptr; |
| } |
| *scriptptr = k; |
| scriptptr++; |
| return 0; |
| } |
| else transnum(); |
| } |
| for(k=j;k<3;k++) |
| { |
| *scriptptr = 0; |
| scriptptr++; |
| } |
| } |
| return 0; |
| |
| case 7: |
| if( parsing_actor || parsing_state ) |
| transnum(); |
| else |
| { |
| scriptptr--; |
| getlabel(); |
| // Check to see it's already defined |
| |
| for(i=0;i<NUMKEYWORDS;i++) |
| if( strcmp( label+(labelcnt<<6),keyw[i]) == 0 ) |
| { |
| error++; |
| printf(" * ERROR!(L%hd) Symbol '%s' is a key word.\n",line_number,label+(labelcnt<<6)); |
| return 0; |
| } |
| |
| for(i=0;i<labelcnt;i++) |
| if( strcmp(label+(labelcnt<<6),label+(i<<6)) == 0 ) |
| { |
| warning++; |
| printf(" * WARNING.(L%hd) Duplicate action '%s' ignored.\n",line_number,label+(labelcnt<<6)); |
| break; |
| } |
| |
| if(i == labelcnt) |
| labelcode[labelcnt++] = (int32_t) scriptptr; |
| |
| for(j=0;j<5;j++) |
| { |
| if(keyword() >= 0) break; |
| transnum(); |
| } |
| for(k=j;k<5;k++) |
| { |
| *scriptptr = 0; |
| scriptptr++; |
| } |
| } |
| return 0; |
| |
| case 1: |
| if( parsing_state ) |
| { |
| printf(" * ERROR!(L%hd) Found 'actor' within 'state'.\n",line_number); |
| error++; |
| } |
| |
| if( parsing_actor ) |
| { |
| printf(" * ERROR!(L%hd) Found 'actor' within 'actor'.\n",line_number); |
| error++; |
| } |
| |
| num_squigilly_brackets = 0; |
| scriptptr--; |
| parsing_actor = scriptptr; |
| |
| transnum(); |
| scriptptr--; |
| actorscrptr[*scriptptr] = parsing_actor; |
| |
| for(j=0;j<4;j++) |
| { |
| *(parsing_actor+j) = 0; |
| if(j == 3) |
| { |
| j = 0; |
| while(keyword() == -1) |
| { |
| transnum(); |
| scriptptr--; |
| j |= *scriptptr; |
| } |
| *scriptptr = j; |
| scriptptr++; |
| break; |
| } |
| else |
| { |
| if(keyword() >= 0) |
| { |
| scriptptr += (4-j); |
| break; |
| } |
| transnum(); |
| |
| *(parsing_actor+j) = *(scriptptr-1); |
| } |
| } |
| |
| checking_ifelse = 0; |
| |
| return 0; |
| |
| case 98: |
| |
| if( parsing_state ) |
| { |
| printf(" * ERROR!(L%hd) Found 'useritem' within 'state'.\n",line_number); |
| error++; |
| } |
| |
| if( parsing_actor ) |
| { |
| printf(" * ERROR!(L%hd) Found 'useritem' within 'actor'.\n",line_number); |
| error++; |
| } |
| |
| num_squigilly_brackets = 0; |
| scriptptr--; |
| parsing_actor = scriptptr; |
| |
| transnum(); |
| scriptptr--; |
| j = *scriptptr; |
| |
| transnum(); |
| scriptptr--; |
| actorscrptr[*scriptptr] = parsing_actor; |
| actortype[*scriptptr] = j; |
| |
| for(j=0;j<4;j++) |
| { |
| *(parsing_actor+j) = 0; |
| if(j == 3) |
| { |
| j = 0; |
| while(keyword() == -1) |
| { |
| transnum(); |
| scriptptr--; |
| j |= *scriptptr; |
| } |
| *scriptptr = j; |
| scriptptr++; |
| break; |
| } |
| else |
| { |
| if(keyword() >= 0) |
| { |
| scriptptr += (4-j); |
| break; |
| } |
| transnum(); |
| |
| *(parsing_actor+j) = *(scriptptr-1); |
| } |
| } |
| |
| checking_ifelse = 0; |
| |
| return 0; |
| |
| |
| |
| case 11: |
| case 13: |
| case 25: |
| case 31: |
| case 40: |
| case 52: |
| case 69: |
| case 74: |
| case 77: |
| case 80: |
| case 86: |
| case 88: |
| case 68: |
| case 100: |
| case 101: |
| case 102: |
| case 103: |
| case 105: |
| case 110: |
| transnum(); |
| return 0; |
| |
| case 2: |
| case 23: |
| case 28: |
| case 99: |
| case 37: |
| case 48: |
| case 58: |
| transnum(); |
| transnum(); |
| break; |
| case 50: |
| transnum(); |
| transnum(); |
| transnum(); |
| transnum(); |
| transnum(); |
| break; |
| case 10: |
| if( checking_ifelse ) |
| { |
| checking_ifelse--; |
| tempscrptr = scriptptr; |
| scriptptr++; //Leave a spot for the fail location |
| parsecommand(readfromGRP); |
| *tempscrptr = (int32_t) scriptptr; |
| } |
| else |
| { |
| scriptptr--; |
| error++; |
| printf(" * ERROR!(L%hd) Found 'else' with no 'if'.\n",line_number); |
| } |
| |
| return 0; |
| |
| case 75: |
| transnum(); |
| case 3: |
| case 8: |
| case 9: |
| case 21: |
| case 33: |
| case 34: |
| case 35: |
| case 41: |
| case 46: |
| case 53: |
| case 56: |
| case 59: |
| case 62: |
| case 72: |
| case 73: |
| // case 74: |
| case 78: |
| case 85: |
| case 94: |
| case 111: |
| transnum(); |
| case 43: |
| case 44: |
| case 49: |
| case 5: |
| case 6: |
| case 27: |
| case 26: |
| case 45: |
| case 51: |
| case 63: |
| case 64: |
| case 65: |
| case 67: |
| case 70: |
| case 71: |
| case 81: |
| case 82: |
| case 90: |
| case 91: |
| case 109: |
| |
| if(tw == 51) |
| { |
| j = 0; |
| do |
| { |
| transnum(); |
| scriptptr--; |
| j |= *scriptptr; |
| } |
| while(keyword() == -1); |
| *scriptptr = j; |
| scriptptr++; |
| } |
| |
| tempscrptr = scriptptr; |
| scriptptr++; //Leave a spot for the fail location |
| |
| do |
| { |
| j = keyword(); |
| if(j == 20 || j == 39) |
| parsecommand(readfromGRP); |
| } while(j == 20 || j == 39); |
| |
| parsecommand(readfromGRP); |
| |
| *tempscrptr = (int32_t) scriptptr; |
| |
| checking_ifelse++; |
| return 0; |
| case 29: |
| num_squigilly_brackets++; |
| do |
| done = parsecommand(readfromGRP); |
| while( done == 0 ); |
| return 0; |
| case 30: |
| num_squigilly_brackets--; |
| if( num_squigilly_brackets < 0 ) |
| { |
| printf(" * ERROR!(L%hd) Found more '}' than '{'.\n",line_number); |
| error++; |
| } |
| return 1; |
| case 76: |
| scriptptr--; |
| j = 0; |
| while( *textptr != 0x0a ) |
| { |
| betaname[j] = *textptr; |
| j++; textptr++; |
| } |
| betaname[j] = 0; |
| return 0; |
| case 20: |
| scriptptr--; //Negate the rem |
| while( *textptr != 0x0a ) |
| textptr++; |
| |
| // line_number++; |
| return 0; |
| |
| case 107: |
| scriptptr--; |
| transnum(); |
| scriptptr--; |
| j = *scriptptr; |
| while( *textptr == ' ' ) textptr++; |
| |
| i = 0; |
| |
| while( *textptr != 0x0a ) |
| { |
| volume_names[j][i] = toupper(*textptr); |
| textptr++,i++; |
| if(i >= 32) |
| { |
| printf(" * ERROR!(L%hd) Volume name exceeds character size limit of 32.\n",line_number); |
| error++; |
| while( *textptr != 0x0a ) textptr++; |
| break; |
| } |
| } |
| volume_names[j][i] = '\0'; |
| return 0; |
| case 108: |
| scriptptr--; |
| transnum(); |
| scriptptr--; |
| j = *scriptptr; |
| while( *textptr == ' ' ) textptr++; |
| |
| i = 0; |
| |
| while( *textptr != 0x0a ) |
| { |
| skill_names[j][i] = toupper(*textptr); |
| textptr++,i++; |
| if(i >= 32) |
| { |
| printf(" * ERROR!(L%hd) Skill name exceeds character size limit of 32.\n",line_number); |
| error++; |
| while( *textptr != 0x0a ) textptr++; |
| break; |
| } |
| } |
| skill_names[j][i] = '\0'; |
| return 0; |
| |
| case 0: |
| scriptptr--; |
| transnum(); |
| scriptptr--; |
| j = *scriptptr; |
| transnum(); |
| scriptptr--; |
| k = *scriptptr; |
| while( *textptr == ' ' ) textptr++; |
| |
| i = 0; |
| while( *textptr != ' ' && *textptr != 0x0a ) |
| { |
| level_file_names[j*11+k][i] = *textptr; |
| textptr++,i++; |
| if(i > 127) |
| { |
| printf(" * ERROR!(L%hd) Level file name exceeds character size limit of 128.\n",line_number); |
| error++; |
| while( *textptr != ' ') textptr++; |
| break; |
| } |
| } |
| level_names[j*11+k][i] = '\0'; |
| while( *textptr == ' ' ) textptr++; |
| |
| partime[j*11+k] = |
| (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*26*60)+ |
| (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))*26); |
| |
| textptr += 5; |
| while( *textptr == ' ' ) textptr++; |
| |
| designertime[j*11+k] = |
| (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*26*60)+ |
| (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))*26); |
| |
| textptr += 5; |
| while( *textptr == ' ' ) textptr++; |
| |
| i = 0; |
| |
| while( *textptr != 0x0a ) |
| { |
| level_names[j*11+k][i] = toupper(*textptr); |
| textptr++,i++; |
| if(i >= 32) |
| { |
| printf(" * ERROR!(L%hd) Level name exceeds character size limit of 32.\n",line_number); |
| error++; |
| while( *textptr != 0x0a ) textptr++; |
| break; |
| } |
| } |
| level_names[j*11+k][i] = '\0'; |
| return 0; |
| |
| case 79: |
| scriptptr--; |
| transnum(); |
| k = *(scriptptr-1); |
| if(k >= NUMOFFIRSTTIMEACTIVE) |
| { |
| printf(" * ERROR!(L%hd) Quote amount exceeds limit of %d characters.\n",line_number,NUMOFFIRSTTIMEACTIVE); |
| error++; |
| } |
| scriptptr--; |
| i = 0; |
| while( *textptr == ' ' ) |
| textptr++; |
| |
| while( *textptr != 0x0a ) |
| { |
| fta_quotes[k][i] = *textptr; |
| textptr++,i++; |
| if(i >= 64) |
| { |
| printf(" * ERROR!(L%hd) Quote exceeds character size limit of 64.\n",line_number); |
| error++; |
| while( *textptr != 0x0a ) textptr++; |
| break; |
| } |
| } |
| fta_quotes[k][i] = '\0'; |
| return 0; |
| case 57: |
| scriptptr--; |
| transnum(); |
| k = *(scriptptr-1); |
| if(k >= NUM_SOUNDS) |
| { |
| printf(" * ERROR!(L%hd) Exceeded sound limit of %d.\n",line_number,NUM_SOUNDS); |
| error++; |
| } |
| scriptptr--; |
| i = 0; |
| while( *textptr == ' ') |
| textptr++; |
| |
| while( *textptr != ' ' ) |
| { |
| sounds[k][i] = *textptr; |
| textptr++,i++; |
| if(i >= 13) |
| { |
| puts(sounds[k]); |
| printf(" * ERROR!(L%hd) Sound filename exceeded limit of 13 characters.\n",line_number); |
| error++; |
| while( *textptr != ' ' ) textptr++; |
| break; |
| } |
| } |
| sounds[k][i] = '\0'; |
| |
| transnum(); |
| soundps[k] = *(scriptptr-1); |
| scriptptr--; |
| transnum(); |
| soundpe[k] = *(scriptptr-1); |
| scriptptr--; |
| transnum(); |
| soundpr[k] = *(scriptptr-1); |
| scriptptr--; |
| transnum(); |
| soundm[k] = *(scriptptr-1); |
| scriptptr--; |
| transnum(); |
| soundvo[k] = *(scriptptr-1); |
| scriptptr--; |
| return 0; |
| |
| case 4: |
| if( parsing_actor == 0 ) |
| { |
| printf(" * ERROR!(L%hd) Found 'enda' without defining 'actor'.\n",line_number); |
| error++; |
| } |
| // else |
| { |
| if( num_squigilly_brackets > 0 ) |
| { |
| printf(" * ERROR!(L%hd) Found more '{' than '}' before 'enda'.\n",line_number); |
| error++; |
| } |
| parsing_actor = 0; |
| } |
| |
| return 0; |
| case 12: |
| case 16: |
| case 84: |
| // case 21: |
| case 22: //KILLIT |
| case 36: |
| case 38: |
| case 42: |
| case 47: |
| case 61: |
| case 66: |
| case 83: |
| case 95: |
| case 96: |
| case 97: |
| case 104: |
| case 106: |
| return 0; |
| case 60: |
| { |
| int32_t params[30]; |
| |
| scriptptr--; |
| for(j = 0; j < 30; j++) |
| { |
| transnum(); |
| scriptptr--; |
| params[j] = *scriptptr; |
| |
| if (j != 25) continue; // we try to guess if we are using 1.3/1.3d or 1.4/1.5 con files |
| |
| if (keyword() != -1) // Is the 26th variable set? If so then it's probably a 1.4/1.5 con file |
| { |
| break; |
| } |
| else |
| { |
| conVersion = 15; |
| } |
| } |
| |
| /* From Jonathon's code --mk |
| v1.3d v1.5 |
| |
| DEFAULTVISIBILITY DEFAULTVISIBILITY |
| GENERICIMPACTDAMAGE GENERICIMPACTDAMAGE |
| MAXPLAYERHEALTH MAXPLAYERHEALTH |
| STARTARMORHEALTH STARTARMORHEALTH |
| RESPAWNACTORTIME RESPAWNACTORTIME |
| RESPAWNITEMTIME RESPAWNITEMTIME |
| RUNNINGSPEED RUNNINGSPEED |
| GRAVITATIONALCONSTANT |
| RPGBLASTRADIUS RPGBLASTRADIUS |
| PIPEBOMBRADIUS PIPEBOMBRADIUS |
| SHRINKERBLASTRADIUS SHRINKERBLASTRADIUS |
| TRIPBOMBBLASTRADIUS TRIPBOMBBLASTRADIUS |
| MORTERBLASTRADIUS MORTERBLASTRADIUS |
| BOUNCEMINEBLASTRADIUS BOUNCEMINEBLASTRADIUS |
| SEENINEBLASTRADIUS SEENINEBLASTRADIUS |
| MAXPISTOLAMMO MAXPISTOLAMMO |
| MAXSHOTGUNAMMO MAXSHOTGUNAMMO |
| MAXCHAINGUNAMMO MAXCHAINGUNAMMO |
| MAXRPGAMMO MAXRPGAMMO |
| MAXHANDBOMBAMMO MAXHANDBOMBAMMO |
| MAXSHRINKERAMMO MAXSHRINKERAMMO |
| MAXDEVISTATORAMMO MAXDEVISTATORAMMO |
| MAXTRIPBOMBAMMO MAXTRIPBOMBAMMO |
| MAXFREEZEAMMO MAXFREEZEAMMO |
| MAXGROWAMMO |
| CAMERASDESTRUCTABLE CAMERASDESTRUCTABLE |
| NUMFREEZEBOUNCES NUMFREEZEBOUNCES |
| FREEZERHURTOWNER FREEZERHURTOWNER |
| QSIZE |
| TRIPBOMBLASERMODE |
| */ |
| |
| // Used Jonathon Fowler's parser. Cool to make the code |
| // robust to 1.3 con files --mk |
| |
| j = 0; |
| |
| ud.const_visibility = params[j++]; |
| impact_damage = params[j++]; |
| max_player_health = params[j++]; |
| max_armour_amount = params[j++]; |
| respawnactortime = params[j++]; |
| respawnitemtime = params[j++]; |
| dukefriction = params[j++]; |
| if (conVersion == 15) |
| gc = params[j++]; |
| else |
| gc = 176; // default (guess) when using 1.3d CONs |
| rpgblastradius = params[j++]; |
| pipebombblastradius = params[j++]; |
| shrinkerblastradius = params[j++]; |
| tripbombblastradius = params[j++]; |
| morterblastradius = params[j++]; |
| bouncemineblastradius = params[j++]; |
| seenineblastradius = params[j++]; |
| max_ammo_amount[PISTOL_WEAPON] = params[j++]; |
| max_ammo_amount[SHOTGUN_WEAPON] = params[j++]; |
| max_ammo_amount[CHAINGUN_WEAPON] = params[j++]; |
| max_ammo_amount[RPG_WEAPON] = params[j++]; |
| max_ammo_amount[HANDBOMB_WEAPON] = params[j++]; |
| max_ammo_amount[SHRINKER_WEAPON] = params[j++]; |
| max_ammo_amount[DEVISTATOR_WEAPON] = params[j++]; |
| max_ammo_amount[TRIPBOMB_WEAPON] = params[j++]; |
| max_ammo_amount[FREEZE_WEAPON] = params[j++]; |
| if (conVersion == 15) |
| max_ammo_amount[GROW_WEAPON] = params[j++]; |
| else |
| max_ammo_amount[GROW_WEAPON] = 50; // default (guess) when using 1.3d CONs |
| camerashitable = params[j++]; |
| numfreezebounces = params[j++]; |
| freezerhurtowner = params[j++]; |
| if (conVersion == 15) |
| { |
| spriteqamount = params[j++]; |
| |
| if(spriteqamount > 1024) |
| spriteqamount = 1024; |
| else if(spriteqamount < 0) |
| spriteqamount = 0; |
| lasermode = params[j++]; |
| } |
| else |
| { |
| // spriteqamount = 64 is the default |
| lasermode = 0; // default (guess) when using 1.3d CONs |
| } |
| } |
| return 0; |
| |
| } // end of switch(tw) |
| |
| return 0; |
| } |
| |
| |
| void passone(int readfromGRP) |
| { |
| |
| while( parsecommand(readfromGRP) == 0 ); |
| |
| if( (error+warning) > 12) |
| puts( " * ERROR! Too many warnings or errors."); |
| |
| } |
| |
| char *defaultcons[3] = |
| { |
| "GAME.CON", |
| "USER.CON", |
| "DEFS.CON" |
| }; |
| |
| void copydefaultcons(void) |
| { |
| int32_t i, fs, fpi; |
| FILE *fpo; |
| |
| for(i=0;i<3;i++) |
| { |
| fpi = TCkopen4load(defaultcons[i],1); |
| fpo = fopen( defaultcons[i],"wb"); |
| |
| if(fpi == 0) |
| { |
| // CTW - MODIFICATION |
| // if(fpo == -1) fclose(fpo); |
| if(fpo == NULL) fclose(fpo); |
| // CTW END - MODIFICATION |
| continue; |
| } |
| // CTW - MODIFICATION |
| // if(fpo == -1) |
| if(fpo == NULL) |
| // CTW END - MODIFICATION |
| { |
| if(fpi == 0) kclose(fpi); |
| continue; |
| } |
| |
| fs = kfilelength(fpi); |
| |
| kread(fpi,&hittype[0],fs); |
| fwrite(&hittype[0],fs,1,fpo); |
| |
| kclose(fpi); |
| fclose(fpo); |
| } |
| } |
| |
| void loadefs(char *filenam, char *mptr, int readfromGRP) |
| { |
| LOGF("loadefs %s", filenam); |
| int32_t fs,fp; |
| uint8_t kbdKey; |
| |
| memset(script, 0, sizeof(script)); |
| |
| // FIX_00071: do not ask for internal default con if |
| // external con or internal con is buggy |
| fp = TCkopen4load(filenam,readfromGRP); |
| if( fp < 0 ) |
| { |
| Error(EXIT_SUCCESS, "ERROR: CON(%s) not found.\n", filenam); |
| } |
| else |
| { |
| printf("Compiling: '%s'.\n",filenam); |
| |
| fs = kfilelength(fp); |
| |
| LOGF("file size: %d bytes", fs); |
| |
| last_used_text = textptr = (char *) mptr; |
| last_used_size = fs; |
| |
| kread(fp,(uint8_t *)textptr,fs); |
| kclose(fp); |
| ud.conCRC[0]=0; |
| //ud.conCRC[0] = crc32_update((uint8_t *)textptr, fs, ud.conCRC[0]); |
| } |
| |
| textptr[fs - 1] = 0; |
| |
| clearbuf(actorscrptr,MAXSPRITES,0L); |
| clearbufbyte(actortype,MAXSPRITES,0L); |
| |
| labelcnt = 0; |
| scriptptr = script+1; |
| warning = 0; |
| error = 0; |
| line_number = 1; |
| total_lines = 0; |
| |
| passone(readfromGRP); //Tokenize |
| *script = (int32_t) scriptptr; |
| |
| if(warning|error) |
| printf("Found %hhd warning(s), '%c' error(s).\n",warning,error); |
| |
| if(error) |
| { |
| Error(EXIT_SUCCESS, "ERROR in CON(%s)\n", filenam); |
| } |
| else |
| { |
| total_lines += line_number; |
| printf("Code Size:%d bytes(%d labels).\n",(int32_t)((scriptptr-script)<<2)-4,labelcnt); |
| ud.conSize[0] = (int32_t)(scriptptr-script)-1; |
| |
| // FIX_00062: Better support and identification for GRP and CON files for 1.3/1.3d/1.4/1.5 |
| if( ud.conSize[0] == 16208 && labelcnt == 1794 && conVersion == 15) |
| conVersion = 14; |
| printf("Con version: Looks like v%d\n", conVersion); |
| |
| // FIX_00022: Automatically recognize the shareware grp (v1.3) + full version (1.3d) + |
| // atomic (1.4/1.5 grp) and the con files version (either 1.3 or 1.4) (JonoF's idea) |
| |
| if(conVersion != 13 && (getGRPcrc32(0)==CRC_BASE_GRP_SHAREWARE_13 || |
| getGRPcrc32(0)==CRC_BASE_GRP_FULL_13) && !getGRPcrc32(1)) |
| { |
| printf( "\nYou are trying to use a v1.3 Shareware/Full *.GRP with v1.4 or v1.5\n" |
| "external *.CON files. You may run in troubles by doing so and/or get\n" |
| "Out Of Synch errors. You can safely delete those files so xDuke will\n" |
| "always use the GRP internal CON files.\n" |
| "\nReload normal GRP internal *.CON files? (Y/N) : "); |
| do |
| kbdKey = getch() | ' '; |
| while(kbdKey != 'y' && kbdKey != 'n'); |
| printf("%c\n", kbdKey); |
| |
| if(kbdKey == 'y') |
| { |
| conVersion = 13; |
| loadefs(filenam, mptr, 1); // force GRP con files |
| } |
| } |
| else if(conVersion != 15 && getGRPcrc32(0)==CRC_BASE_GRP_ATOMIC_15 && !getGRPcrc32(1)) |
| { |
| printf( "\nYou are trying to use a v1.5 ATOMIC *.GRP with v1.4 or v1.3\n" |
| "external *.CON files. You may run in troubles by doing so and/or get\n" |
| "Out Of Synch errors. You can safely delete those files so xDuke will\n" |
| "always use the GRP internal CON files.\n" |
| "\nReload normal GRP internal *.CON files? (Y/N) : "); |
| do |
| kbdKey = getch() | ' '; |
| while(kbdKey != 'y' && kbdKey != 'n'); |
| printf("%c\n", kbdKey); |
| |
| if(kbdKey == 'y') |
| { |
| loadefs(filenam, mptr, 1); // force GRP con files |
| } |
| }else if(conVersion != 14 && getGRPcrc32(0)==CRC_BASE_GRP_PLUTONIUM_14 && !getGRPcrc32(1)) |
| { |
| printf( "\nYou are trying to use a v1.4 PLUTONIUM *.GRP with v1.3 or v1.5\n" |
| "external *.CON files. You may run in troubles by doing so and/or get\n" |
| "Out Of Synch errors. You can safely delete those files so xDuke will\n" |
| "always use the GRP internal CON files.\n" |
| "\nReload normal GRP internal *.CON files? (Y/N) : "); |
| do |
| kbdKey = getch() | ' '; |
| while(kbdKey != 'y' && kbdKey != 'n'); |
| printf("%c\n", kbdKey); |
| |
| if(kbdKey == 'y') |
| { |
| loadefs(filenam, mptr, 1); // force GRP con files |
| } |
| } |
| } |
| } |
| |
| uint8_t dodge(spritetype *s) |
| { |
| short i; |
| int32_t bx,by,mx,my,bxvect,byvect,mxvect,myvect,d; |
| |
| mx = s->x; |
| my = s->y; |
| mxvect = sintable[(s->ang+512)&2047]; myvect = sintable[s->ang&2047]; |
| |
| for(i=headspritestat[4];i>=0;i=nextspritestat[i]) //weapons list |
| { |
| if( OW == i || SECT != s->sectnum) |
| continue; |
| |
| bx = SX-mx; |
| by = SY-my; |
| bxvect = sintable[(SA+512)&2047]; byvect = sintable[SA&2047]; |
| |
| if (mxvect*bx + myvect*by >= 0) |
| if (bxvect*bx + byvect*by < 0) |
| { |
| d = bxvect*by - byvect*bx; |
| if (klabs(d) < 65536*64) |
| { |
| s->ang -= 512+(TRAND&1024); |
| return 1; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| short furthestangle(short i,short angs) |
| { |
| short j, hitsect,hitwall,hitspr,furthest_angle, angincs; |
| int32_t hx, hy, hz, d, greatestd; |
| spritetype *s = &sprite[i]; |
| |
| greatestd = -(1<<30); |
| angincs = 2048/angs; |
| |
| if(s->picnum != APLAYER) |
| if( (g_t[0]&63) > 2 ) return( s->ang + 1024 ); |
| |
| for(j=s->ang;j<(2048+s->ang);j+=angincs) |
| { |
| hitscan(s->x, s->y, s->z-(8<<8), s->sectnum, |
| sintable[(j+512)&2047], |
| sintable[j&2047],0, |
| &hitsect,&hitwall,&hitspr,&hx,&hy,&hz,CLIPMASK1); |
| |
| d = klabs(hx-s->x) + klabs(hy-s->y); |
| |
| if(d > greatestd) |
| { |
| greatestd = d; |
| furthest_angle = j; |
| } |
| } |
| return (furthest_angle&2047); |
| } |
| |
| short furthestcanseepoint(short i,spritetype *ts,int32_t *dax,int32_t *day) |
| { |
| short j, hitsect,hitwall,hitspr, angincs; |
| int32_t hx, hy, hz, d, da;//, d, cd, ca,tempx,tempy,cx,cy; |
| spritetype *s = &sprite[i]; |
| |
| if( (g_t[0]&63) ) return -1; |
| |
| if(ud.multimode < 2 && ud.player_skill < 3) |
| angincs = 2048/2; |
| else angincs = 2048/(1+(TRAND&1)); |
| |
| for(j=ts->ang;j<(2048+ts->ang);j+=(angincs-(TRAND&511))) |
| { |
| hitscan(ts->x, ts->y, ts->z-(16<<8), ts->sectnum, |
| sintable[(j+512)&2047], |
| sintable[j&2047],16384-(TRAND&32767), |
| &hitsect,&hitwall,&hitspr,&hx,&hy,&hz,CLIPMASK1); |
| |
| d = klabs(hx-ts->x)+klabs(hy-ts->y); |
| da = klabs(hx-s->x)+klabs(hy-s->y); |
| |
| if( d < da ) |
| if(cansee(hx,hy,hz,hitsect,s->x,s->y,s->z-(16<<8),s->sectnum)) |
| { |
| *dax = hx; |
| *day = hy; |
| return hitsect; |
| } |
| } |
| return -1; |
| } |
| |
| |
| |
| |
| void alterang(short a) |
| { |
| short aang, angdif, goalang,j; |
| int32_t ticselapsed, *moveptr; |
| |
| moveptr = (int32_t *)g_t[1]; |
| |
| ticselapsed = (g_t[0])&31; |
| |
| aang = g_sp->ang; |
| |
| g_sp->xvel += (*moveptr-g_sp->xvel)/5; |
| if(g_sp->zvel < 648) g_sp->zvel += ((*(moveptr+1)<<4)-g_sp->zvel)/5; |
| |
| if(a&seekplayer) |
| { |
| j = ps[g_p].holoduke_on; |
| |
| if(j >= 0 && cansee(sprite[j].x,sprite[j].y,sprite[j].z,sprite[j].sectnum,g_sp->x,g_sp->y,g_sp->z,g_sp->sectnum) ) |
| g_sp->owner = j; |
| else g_sp->owner = ps[g_p].i; |
| |
| if(sprite[g_sp->owner].picnum == APLAYER) |
| goalang = getangle(hittype[g_i].lastvx-g_sp->x,hittype[g_i].lastvy-g_sp->y); |
| else |
| goalang = getangle(sprite[g_sp->owner].x-g_sp->x,sprite[g_sp->owner].y-g_sp->y); |
| |
| if(g_sp->xvel && g_sp->picnum != DRONE) |
| { |
| angdif = getincangle(aang,goalang); |
| |
| if(ticselapsed < 2) |
| { |
| if( klabs(angdif) < 256) |
| { |
| j = 128-(TRAND&256); |
| g_sp->ang += j; |
| if( hits(g_i) < 844 ) |
| g_sp->ang -= j; |
| } |
| } |
| else if(ticselapsed > 18 && ticselapsed < 26) // choose |
| { |
| if(klabs(angdif>>2) < 128) g_sp->ang = goalang; |
| else g_sp->ang += angdif>>2; |
| } |
| } |
| else g_sp->ang = goalang; |
| } |
| |
| if(ticselapsed < 1) |
| { |
| j = 2; |
| if(a&furthestdir) |
| { |
| goalang = furthestangle(g_i,j); |
| g_sp->ang = goalang; |
| g_sp->owner = ps[g_p].i; |
| } |
| |
| if(a&fleeenemy) |
| { |
| goalang = furthestangle(g_i,j); |
| g_sp->ang = goalang; // += angdif; // = getincangle(aang,goalang)>>1; |
| } |
| } |
| } |
| |
| void move() |
| { |
| int32_t l, *moveptr; |
| short a, goalang, angdif; |
| int32_t daxvel; |
| |
| a = g_sp->hitag; |
| |
| if(a == -1) a = 0; |
| |
| g_t[0]++; |
| |
| if(a&face_player) |
| { |
| if(ps[g_p].newowner >= 0) |
| goalang = getangle(ps[g_p].oposx-g_sp->x,ps[g_p].oposy-g_sp->y); |
| else goalang = getangle(ps[g_p].posx-g_sp->x,ps[g_p].posy-g_sp->y); |
| angdif = getincangle(g_sp->ang,goalang)>>2; |
| if(angdif > -8 && angdif < 0) angdif = 0; |
| g_sp->ang += angdif; |
| } |
| |
| if(a&spin) |
| g_sp->ang += sintable[ ((g_t[0]<<3)&2047) ]>>6; |
| |
| if(a&face_player_slow) |
| { |
| if(ps[g_p].newowner >= 0) |
| goalang = getangle(ps[g_p].oposx-g_sp->x,ps[g_p].oposy-g_sp->y); |
| else goalang = getangle(ps[g_p].posx-g_sp->x,ps[g_p].posy-g_sp->y); |
| angdif = ksgn(getincangle(g_sp->ang,goalang))<<5; |
| if(angdif > -32 && angdif < 0) |
| { |
| angdif = 0; |
| g_sp->ang = goalang; |
| } |
| g_sp->ang += angdif; |
| } |
| |
| |
| if((a&jumptoplayer) == jumptoplayer) |
| { |
| if(g_t[0] < 16) |
| g_sp->zvel -= (sintable[(512+(g_t[0]<<4))&2047]>>5); |
| } |
| |
| if(a&face_player_smart) |
| { |
| int32_t newx,newy; |
| |
| newx = ps[g_p].posx+(ps[g_p].posxv/768); |
| newy = ps[g_p].posy+(ps[g_p].posyv/768); |
| goalang = getangle(newx-g_sp->x,newy-g_sp->y); |
| angdif = getincangle(g_sp->ang,goalang)>>2; |
| if(angdif > -8 && angdif < 0) angdif = 0; |
| g_sp->ang += angdif; |
| } |
| |
| if( g_t[1] == 0 || a == 0 ) |
| { |
| if( ( badguy(g_sp) && g_sp->extra <= 0 ) || (hittype[g_i].bposx != g_sp->x) || (hittype[g_i].bposy != g_sp->y) ) |
| { |
| hittype[g_i].bposx = g_sp->x; |
| hittype[g_i].bposy = g_sp->y; |
| setsprite(g_i,g_sp->x,g_sp->y,g_sp->z); |
| } |
| return; |
| } |
| |
| moveptr = (int32_t *)g_t[1]; |
| |
| if(a&geth) g_sp->xvel += (*moveptr-g_sp->xvel)>>1; |
| if(a&getv) g_sp->zvel += ((*(moveptr+1)<<4)-g_sp->zvel)>>1; |
| |
| if(a&dodgebullet) |
| dodge(g_sp); |
| |
| if(g_sp->picnum != APLAYER) |
| alterang(a); |
| |
| if(g_sp->xvel > -6 && g_sp->xvel < 6 ) g_sp->xvel = 0; |
| |
| a = badguy(g_sp); |
| |
| if(g_sp->xvel || g_sp->zvel) |
| { |
| if(a && g_sp->picnum != ROTATEGUN) |
| { |
| if( (g_sp->picnum == DRONE || g_sp->picnum == COMMANDER) && g_sp->extra > 0) |
| { |
| if(g_sp->picnum == COMMANDER) |
| { |
| hittype[g_i].floorz = l = getflorzofslope(g_sp->sectnum,g_sp->x,g_sp->y); |
| if( g_sp->z > (l-(8<<8)) ) |
| { |
| if( g_sp->z > (l-(8<<8)) ) g_sp->z = l-(8<<8); |
| g_sp->zvel = 0; |
| } |
| |
| hittype[g_i].ceilingz = l = getceilzofslope(g_sp->sectnum,g_sp->x,g_sp->y); |
| if( (g_sp->z-l) < (80<<8) ) |
| { |
| g_sp->z = l+(80<<8); |
| g_sp->zvel = 0; |
| } |
| } |
| else |
| { |
| if( g_sp->zvel > 0 ) |
| { |
| hittype[g_i].floorz = l = getflorzofslope(g_sp->sectnum,g_sp->x,g_sp->y); |
| if( g_sp->z > (l-(30<<8)) ) |
| g_sp->z = l-(30<<8); |
| } |
| else |
| { |
| hittype[g_i].ceilingz = l = getceilzofslope(g_sp->sectnum,g_sp->x,g_sp->y); |
| if( (g_sp->z-l) < (50<<8) ) |
| { |
| g_sp->z = l+(50<<8); |
| g_sp->zvel = 0; |
| } |
| } |
| } |
| } |
| else if(g_sp->picnum != ORGANTIC) |
| { |
| if(g_sp->zvel > 0 && hittype[g_i].floorz < g_sp->z) |
| g_sp->z = hittype[g_i].floorz; |
| if( g_sp->zvel < 0) |
| { |
| l = getceilzofslope(g_sp->sectnum,g_sp->x,g_sp->y); |
| if( (g_sp->z-l) < (66<<8) ) |
| { |
| g_sp->z = l+(66<<8); |
| g_sp->zvel >>= 1; |
| } |
| } |
| } |
| } |
| else if(g_sp->picnum == APLAYER) |
| if( (g_sp->z-hittype[g_i].ceilingz) < (32<<8) ) |
| g_sp->z = hittype[g_i].ceilingz+(32<<8); |
| |
| daxvel = g_sp->xvel; |
| angdif = g_sp->ang; |
| |
| if( a && g_sp->picnum != ROTATEGUN ) |
| { |
| if( g_x < 960 && g_sp->xrepeat > 16 ) |
| { |
| |
| daxvel = -(1024-g_x); |
| angdif = getangle(ps[g_p].posx-g_sp->x,ps[g_p].posy-g_sp->y); |
| |
| if(g_x < 512) |
| { |
| ps[g_p].posxv = 0; |
| ps[g_p].posyv = 0; |
| } |
| else |
| { |
| ps[g_p].posxv = mulscale(ps[g_p].posxv,dukefriction-0x2000,16); |
| ps[g_p].posyv = mulscale(ps[g_p].posyv,dukefriction-0x2000,16); |
| } |
| } |
| else if(g_sp->picnum != DRONE && g_sp->picnum != SHARK && g_sp->picnum != COMMANDER) |
| { |
| if( hittype[g_i].bposz != g_sp->z || ( ud.multimode < 2 && ud.player_skill < 2 ) ) |
| { |
| if( (g_t[0]&1) || ps[g_p].actorsqu == g_i ) return; |
| else daxvel <<= 1; |
| } |
| else |
| { |
| if( (g_t[0]&3) || ps[g_p].actorsqu == g_i ) return; |
| else daxvel <<= 2; |
| } |
| } |
| } |
| |
| hittype[g_i].movflag = movesprite(g_i, |
| (daxvel*(sintable[(angdif+512)&2047]))>>14, |
| (daxvel*(sintable[angdif&2047]))>>14,g_sp->zvel,CLIPMASK0); |
| } |
| |
| if( a ) |
| { |
| if (sector[g_sp->sectnum].ceilingstat&1) |
| g_sp->shade += (sector[g_sp->sectnum].ceilingshade-g_sp->shade)>>1; |
| else g_sp->shade += (sector[g_sp->sectnum].floorshade-g_sp->shade)>>1; |
| |
| if( sector[g_sp->sectnum].floorpicnum == MIRROR ) |
| deletesprite(g_i); |
| } |
| } |
| |
| uint8_t parse(void); |
| |
| void parseifelse(int32_t condition) |
| { |
| if( condition ) |
| { |
| insptr+=2; |
| parse(); |
| } |
| else |
| { |
| insptr = (int32_t *) *(insptr+1); |
| if(*insptr == 10) |
| { |
| insptr+=2; |
| parse(); |
| } |
| } |
| } |
| |
| // int32_t *it = 0x00589a04; |
| |
| uint8_t parse(void) |
| { |
| int32_t j, l, s; |
| |
| if(killit_flag) return 1; |
| |
| // if(*it == 1668249134L) gameexit("\nERR"); |
| |
| switch(*insptr) |
| { |
| case 3: |
| insptr++; |
| parseifelse( rnd(*insptr)); |
| break; |
| case 45: |
| |
| if(g_x > 1024) |
| { |
| short temphit, sclip, angdif; |
| |
| if( badguy(g_sp) && g_sp->xrepeat > 56 ) |
| { |
| sclip = 3084; |
| angdif = 48; |
| } |
| else |
| { |
| sclip = 768; |
| angdif = 16; |
| } |
| |
| j = hitasprite(g_i,&temphit); |
| if(j == (1<<30)) |
| { |
| parseifelse(1); |
| break; |
| } |
| if(j > sclip) |
| { |
| if(temphit >= 0 && sprite[temphit].picnum == g_sp->picnum) |
| j = 0; |
| else |
| { |
| g_sp->ang += angdif;j = hitasprite(g_i,&temphit);g_sp->ang -= angdif; |
| if(j > sclip) |
| { |
| if(temphit >= 0 && sprite[temphit].picnum == g_sp->picnum) |
| j = 0; |
| else |
| { |
| g_sp->ang -= angdif;j = hitasprite(g_i,&temphit);g_sp->ang += angdif; |
| if( j > 768 ) |
| { |
| if(temphit >= 0 && sprite[temphit].picnum == g_sp->picnum) |
| j = 0; |
| else j = 1; |
| } |
| else j = 0; |
| } |
| } |
| else j = 0; |
| } |
| } |
| else j = 0; |
| } |
| else j = 1; |
| |
| parseifelse(j); |
| break; |
| case 91: |
| j = cansee(g_sp->x,g_sp->y,g_sp->z-((TRAND&41)<<8),g_sp->sectnum,ps[g_p].posx,ps[g_p].posy,ps[g_p].posz/*-((TRAND&41)<<8)*/,sprite[ps[g_p].i].sectnum); |
| parseifelse(j); |
| if( j ) hittype[g_i].timetosleep = SLEEPTIME; |
| break; |
| |
| case 49: |
| parseifelse(hittype[g_i].actorstayput == -1); |
| break; |
| case 5: |
| { |
| spritetype *s; |
| |
| if(ps[g_p].holoduke_on >= 0) |
| { |
| s = &sprite[ps[g_p].holoduke_on]; |
| j = cansee(g_sp->x,g_sp->y,g_sp->z-(TRAND&((32<<8)-1)),g_sp->sectnum, |
| s->x,s->y,s->z,s->sectnum); |
| if(j == 0) |
| s = &sprite[ps[g_p].i]; |
| } |
| else s = &sprite[ps[g_p].i]; |
| |
| j = cansee(g_sp->x,g_sp->y,g_sp->z-(TRAND&((47<<8))),g_sp->sectnum, |
| s->x,s->y,s->z-(24<<8),s->sectnum); |
| |
| if(j == 0) |
| { |
| if( ( klabs(hittype[g_i].lastvx-g_sp->x)+klabs(hittype[g_i].lastvy-g_sp->y) ) < |
| ( klabs(hittype[g_i].lastvx-s->x)+klabs(hittype[g_i].lastvy-s->y) ) ) |
| j = 0; |
| |
| if( j == 0 ) |
| { |
| j = furthestcanseepoint(g_i,s,&hittype[g_i].lastvx,&hittype[g_i].lastvy); |
| |
| if(j == -1) j = 0; |
| else j = 1; |
| } |
| } |
| else |
| { |
| hittype[g_i].lastvx = s->x; |
| hittype[g_i].lastvy = s->y; |
| } |
| |
| if( j == 1 && ( g_sp->statnum == 1 || g_sp->statnum == 6 ) ) |
| hittype[g_i].timetosleep = SLEEPTIME; |
| |
| parseifelse(j == 1); |
| break; |
| } |
| |
| case 6: |
| parseifelse(ifhitbyweapon(g_i) >= 0); |
| break; |
| case 27: |
| parseifelse( ifsquished(g_i, g_p) == 1); |
| break; |
| case 26: |
| { |
| j = g_sp->extra; |
| if(g_sp->picnum == APLAYER) |
| j--; |
| parseifelse(j < 0); |
| } |
| break; |
| case 24: |
| insptr++; |
| g_t[5] = *insptr; |
| g_t[4] = *(int32_t *)(g_t[5]); // Action |
| g_t[1] = *(int32_t *)(g_t[5]+4); // move |
| g_sp->hitag = *(int32_t *)(g_t[5]+8); // Ai |
| g_t[0] = g_t[2] = g_t[3] = 0; |
| if(g_sp->hitag&random_angle) |
| g_sp->ang = TRAND&2047; |
| insptr++; |
| break; |
| case 7: |
| insptr++; |
| g_t[2] = 0; |
| g_t[3] = 0; |
| // FIX_00093: fixed crashbugs in multiplayer (mine/blimp) |
| // This is the blimp bug. |
| // *.con code 1.3 and 1.4 are buggy when you try to blow up the |
| // blimp in multiplayer. duke3d_w32 /q2 /m /v3 /l9 |
| // This is because the con code gives a timeout value of 2048 |
| // as a action address instead of giving a real action address. |
| // We simply counter this specific con code bug by resetting |
| // the action address to 0 when we get an address "2048": |
| g_t[4] = ((*insptr)==2048)?0:(*insptr); |
| insptr++; |
| break; |
| |
| case 8: |
| insptr++; |
| parseifelse(g_x < *insptr); |
| if(g_x > MAXSLEEPDIST && hittype[g_i].timetosleep == 0) |
| hittype[g_i].timetosleep = SLEEPTIME; |
| break; |
| case 9: |
| insptr++; |
| parseifelse(g_x > *insptr); |
| if(g_x > MAXSLEEPDIST && hittype[g_i].timetosleep == 0) |
| hittype[g_i].timetosleep = SLEEPTIME; |
| break; |
| case 10: |
| insptr = (int32_t *) *(insptr+1); |
| break; |
| case 100: |
| insptr++; |
| g_sp->extra += *insptr; |
| insptr++; |
| break; |
| case 11: |
| insptr++; |
| g_sp->extra = *insptr; |
| insptr++; |
| break; |
| case 94: |
| insptr++; |
| |
| if(ud.coop >= 1 && ud.multimode > 1) |
| { |
| if(*insptr == 0) |
| { |
| for(j=0;j < ps[g_p].weapreccnt;j++) |
| if( ps[g_p].weaprecs[j] == g_sp->picnum ) |
| break; |
| |
| parseifelse(j < ps[g_p].weapreccnt && g_sp->owner == g_i); |
| } |
| else if(ps[g_p].weapreccnt < 16) |
| { |
| ps[g_p].weaprecs[ps[g_p].weapreccnt++] = g_sp->picnum; |
| parseifelse(g_sp->owner == g_i); |
| } |
| } |
| else parseifelse(0); |
| break; |
| case 95: |
| insptr++; |
| if(g_sp->picnum == APLAYER) |
| g_sp->pal = ps[g_sp->yvel].palookup; |
| else g_sp->pal = hittype[g_i].tempang; |
| hittype[g_i].tempang = 0; |
| break; |
| case 104: |
| insptr++; |
| checkweapons(&ps[g_sp->yvel]); |
| break; |
| case 106: |
| insptr++; |
| break; |
| case 97: |
| insptr++; |
| if(Sound[g_sp->yvel].num == 0) |
| spritesound(g_sp->yvel,g_i); |
| break; |
| case 96: |
| insptr++; |
| |
| if( ud.multimode > 1 && g_sp->picnum == APLAYER ) |
| { |
| if(ps[otherp].quick_kick == 0) |
| ps[otherp].quick_kick = 14; |
| } |
| else if(g_sp->picnum != APLAYER && ps[g_p].quick_kick == 0) |
| ps[g_p].quick_kick = 14; |
| break; |
| case 28: |
| insptr++; |
| |
| j = ((*insptr)-g_sp->xrepeat)<<1; |
| g_sp->xrepeat += ksgn(j); |
| |
| insptr++; |
| |
| if( ( g_sp->picnum == APLAYER && g_sp->yrepeat < 36 ) || |
| *insptr < g_sp->yrepeat || |
| ((g_sp->yrepeat*(tiles[g_sp->picnum].dim.height+8))<<2) < (hittype[g_i].floorz - hittype[g_i].ceilingz) ) |
| { |
| j = ((*insptr)-g_sp->yrepeat)<<1; |
| if( klabs(j) ) g_sp->yrepeat += ksgn(j); |
| } |
| |
| insptr++; |
| |
| break; |
| case 99: |
| insptr++; |
| g_sp->xrepeat = (uint8_t ) *insptr; |
| insptr++; |
| g_sp->yrepeat = (uint8_t ) *insptr; |
| insptr++; |
| break; |
| case 13: |
| insptr++; |
| shoot(g_i,(short)*insptr); |
| insptr++; |
| break; |
| case 87: |
| insptr++; |
| if( Sound[*insptr].num == 0 ) |
| spritesound((short) *insptr,g_i); |
| insptr++; |
| break; |
| case 89: |
| insptr++; |
| if( Sound[*insptr].num > 0 ) |
| stopsound((short)*insptr); |
| insptr++; |
| break; |
| case 92: |
| insptr++; |
| if(g_p == screenpeek || ud.coop==1) |
| spritesound((short) *insptr,ps[screenpeek].i); |
| insptr++; |
| break; |
| case 15: |
| insptr++; |
| spritesound((short) *insptr,g_i); |
| insptr++; |
| break; |
| case 84: |
| insptr++; |
| ps[g_p].tipincs = 26; |
| break; |
| case 16: |
| insptr++; |
| g_sp->xoffset = 0; |
| g_sp->yoffset = 0; |
| // if(!gotz) |
| { |
| int32_t c; |
| |
| if( floorspace(g_sp->sectnum) ) |
| c = 0; |
| else |
| { |
| if( ceilingspace(g_sp->sectnum) || sector[g_sp->sectnum].lotag == 2) |
| c = gc/6; |
| else c = gc; |
| } |
| |
| if( hittype[g_i].cgg <= 0 || (sector[g_sp->sectnum].floorstat&2) ) |
| { |
| getglobalz(g_i); |
| hittype[g_i].cgg = 6; |
| } |
| else hittype[g_i].cgg --; |
| |
| if( g_sp->z < (hittype[g_i].floorz-FOURSLEIGHT) ) |
| { |
| g_sp->zvel += c; |
| g_sp->z+=g_sp->zvel; |
| |
| if(g_sp->zvel > 6144) g_sp->zvel = 6144; |
| } |
| else |
| { |
| g_sp->z = hittype[g_i].floorz - FOURSLEIGHT; |
| |
| if( badguy(g_sp) || ( g_sp->picnum == APLAYER && g_sp->owner >= 0) ) |
| { |
| |
| if( g_sp->zvel > 3084 && g_sp->extra <= 1) |
| { |
| if(g_sp->pal != 1 && g_sp->picnum != DRONE) |
| { |
| if(g_sp->picnum == APLAYER && g_sp->extra > 0) |
| goto SKIPJIBS; |
| guts(g_sp,JIBS6,15,g_p); |
| spritesound(SQUISHED,g_i); |
| spawn(g_i,BLOODPOOL); |
| } |
| |
| SKIPJIBS: |
| |
| hittype[g_i].picnum = SHOTSPARK1; |
| hittype[g_i].extra = 1; |
| g_sp->zvel = 0; |
| } |
| else if(g_sp->zvel > 2048 && sector[g_sp->sectnum].lotag != 1) |
| { |
| |
| j = g_sp->sectnum; |
| pushmove(&g_sp->x,&g_sp->y,&g_sp->z,(short*)&j,128L,(4L<<8),(4L<<8),CLIPMASK0); |
| if(j != g_sp->sectnum && j >= 0 && j < MAXSECTORS) |
| changespritesect(g_i,j); |
| |
| spritesound(THUD,g_i); |
| } |
| } |
| if(sector[g_sp->sectnum].lotag == 1) |
| switch (g_sp->picnum) |
| { |
| case OCTABRAIN: |
| case COMMANDER: |
| case DRONE: |
| break; |
| default: |
| g_sp->z += (24<<8); |
| break; |
| } |
| else g_sp->zvel = 0; |
| } |
| } |
| |
| break; |
| case 4: |
| case 12: |
| case 18: |
| return 1; |
| case 30: |
| insptr++; |
| return 1; |
| case 2: |
| insptr++; |
| if( ps[g_p].ammo_amount[*insptr] >= max_ammo_amount[*insptr] ) |
| { |
| killit_flag = 2; |
| break; |
| } |
| addammo( *insptr, &ps[g_p], *(insptr+1) ); |
| if(ps[g_p].curr_weapon == KNEE_WEAPON) |
| if( ps[g_p].gotweapon[*insptr] ) |
| addweapon( &ps[g_p], *insptr ); |
| insptr += 2; |
| break; |
| case 86: |
| insptr++; |
| lotsofmoney(g_sp,*insptr); |
| insptr++; |
| break; |
| case 102: |
| insptr++; |
| lotsofmail(g_sp,*insptr); |
| insptr++; |
| break; |
| case 105: |
| insptr++; |
| hittype[g_i].timetosleep = (short)*insptr; |
| insptr++; |
| break; |
| case 103: |
| insptr++; |
| lotsofpaper(g_sp,*insptr); |
| insptr++; |
| break; |
| case 88: |
| insptr++; |
| ps[g_p].actors_killed += *insptr; |
| hittype[g_i].actorstayput = -1; |
| insptr++; |
| break; |
| case 93: |
| insptr++; |
| spriteglass(g_i,*insptr); |
| insptr++; |
| break; |
| case 22: |
| insptr++; |
| killit_flag = 1; |
| break; |
| case 23: |
| insptr++; |
| if( ps[g_p].gotweapon[*insptr] == 0 ) addweapon( &ps[g_p], *insptr ); |
| else if( ps[g_p].ammo_amount[*insptr] >= max_ammo_amount[*insptr] ) |
| { |
| killit_flag = 2; |
| break; |
| } |
| addammo( *insptr, &ps[g_p], *(insptr+1) ); |
| if(ps[g_p].curr_weapon == KNEE_WEAPON) |
| if( ps[g_p].gotweapon[*insptr] ) |
| addweapon( &ps[g_p], *insptr ); |
| insptr+=2; |
| break; |
| case 68: |
| insptr++; |
| printf("%d\n",*insptr); |
| insptr++; |
| break; |
| case 69: |
| insptr++; |
| ps[g_p].timebeforeexit = *insptr; |
| ps[g_p].customexitsound = -1; |
| ud.eog = 1; |
| insptr++; |
| break; |
| case 25: |
| insptr++; |
| |
| if(ps[g_p].newowner >= 0) |
| { |
| ps[g_p].newowner = -1; |
| ps[g_p].posx = ps[g_p].oposx; |
| ps[g_p].posy = ps[g_p].oposy; |
| ps[g_p].posz = ps[g_p].oposz; |
| ps[g_p].ang = ps[g_p].oang; |
| updatesector(ps[g_p].posx,ps[g_p].posy,&ps[g_p].cursectnum); |
| setpal(&ps[g_p]); |
| |
| j = headspritestat[1]; |
| while(j >= 0) |
| { |
| if(sprite[j].picnum==CAMERA1) |
| sprite[j].yvel = 0; |
| j = nextspritestat[j]; |
| } |
| } |
| |
| j = sprite[ps[g_p].i].extra; |
| |
| if(g_sp->picnum != ATOMICHEALTH) |
| { |
| if( j > max_player_health && *insptr > 0 ) |
| { |
| insptr++; |
| break; |
| } |
| else |
| { |
| if(j > 0) |
| j += *insptr; |
| if ( j > max_player_health && *insptr > 0 ) |
| j = max_player_health; |
| } |
| } |
| else |
| { |
| if( j > 0 ) |
| j += *insptr; |
| if ( j > (max_player_health<<1) ) |
| j = (max_player_health<<1); |
| } |
| |
| if(j < 0) j = 0; |
| |
| if(ud.god == 0) |
| { |
| if(*insptr > 0) |
| { |
| if( ( j - *insptr ) < (max_player_health>>2) && |
| j >= (max_player_health>>2) ) |
| spritesound(DUKE_GOTHEALTHATLOW,ps[g_p].i); |
| |
| ps[g_p].last_extra = j; |
| } |
| |
| sprite[ps[g_p].i].extra = j; |
| } |
| |
| insptr++; |
| break; |
| case 17: |
| { |
| int32_t *tempscrptr; |
| |
| tempscrptr = insptr+2; |
| |
| insptr = (int32_t *) *(insptr+1); |
| while(1) if(parse()) break; |
| insptr = tempscrptr; |
| } |
| break; |
| case 29: |
| insptr++; |
| while(1) if(parse()) break; |
| break; |
| case 32: |
| g_t[0]=0; |
| insptr++; |
| g_t[1] = *insptr; |
| insptr++; |
| g_sp->hitag = *insptr; |
| insptr++; |
| if(g_sp->hitag&random_angle) |
| g_sp->ang = TRAND&2047; |
| break; |
| case 31: |
| insptr++; |
| if(g_sp->sectnum >= 0 && g_sp->sectnum < MAXSECTORS) |
| spawn(g_i,*insptr); |
| insptr++; |
| break; |
| case 33: |
| insptr++; |
| parseifelse( hittype[g_i].picnum == *insptr); |
| break; |
| case 21: |
| insptr++; |
| parseifelse(g_t[5] == *insptr); |
| break; |
| case 34: |
| insptr++; |
| parseifelse(g_t[4] == *insptr); |
| break; |
| case 35: |
| insptr++; |
| parseifelse(g_t[2] >= *insptr); |
| break; |
| case 36: |
| insptr++; |
| g_t[2] = 0; |
| break; |
| case 37: |
| { |
| short dnum; |
| |
| insptr++; |
| dnum = *insptr; |
| insptr++; |
| |
| if(g_sp->sectnum >= 0 && g_sp->sectnum < MAXSECTORS) |
| for(j=(*insptr)-1;j>=0;j--) |
| { |
| if(g_sp->picnum == BLIMP && dnum == SCRAP1) |
| s = 0; |
| else s = (TRAND%3); |
| |
| l = EGS(g_sp->sectnum, |
| g_sp->x+(TRAND&255)-128,g_sp->y+(TRAND&255)-128,g_sp->z-(8<<8)-(TRAND&8191), |
| dnum+s,g_sp->shade,32+(TRAND&15),32+(TRAND&15), |
| TRAND&2047,(TRAND&127)+32, |
| -(TRAND&2047),g_i,5); |
| if(g_sp->picnum == BLIMP && dnum == SCRAP1) |
| sprite[l].yvel = weaponsandammosprites[j%14]; |
| else sprite[l].yvel = -1; |
| sprite[l].pal = |