--- /dev/null
+/*\r
+=====================\r
+=\r
+= DemoLoop\r
+=\r
+=====================\r
+*/\r
+\r
+static char *ParmStrings[] = {"baby","easy","normal","hard",""};\r
+\r
+void DemoLoop (void)\r
+{\r
+ static int LastDemo;\r
+ int i,level;\r
+ long nsize;\r
+ memptr nullblock;\r
+\r
+//\r
+// check for launch from ted\r
+//\r
+ if (tedlevel)\r
+ {\r
+ NoWait = true;\r
+ NewGame(1,0);\r
+\r
+ for (i = 1;i < _argc;i++)\r
+ {\r
+ if ( (level = US_CheckParm(_argv[i],ParmStrings)) != -1)\r
+ {\r
+ gamestate.difficulty=level;\r
+ break;\r
+ }\r
+ }\r
+\r
+#ifndef SPEAR\r
+ gamestate.episode = tedlevelnum/10;\r
+ gamestate.mapon = tedlevelnum%10;\r
+#else\r
+ gamestate.episode = 0;\r
+ gamestate.mapon = tedlevelnum;\r
+#endif\r
+ GameLoop();\r
+ Quit (NULL);\r
+ }\r
+\r
+\r
+//\r
+// main game cycle\r
+//\r
+\r
+\r
+// nsize = (long)40*1024;\r
+// MM_GetPtr(&nullblock,nsize);\r
+\r
+#ifndef DEMOTEST\r
+\r
+ #ifndef UPLOAD\r
+\r
+ #ifndef GOODTIMES\r
+ #ifndef SPEAR\r
+ #ifndef JAPAN\r
+ if (!NoWait)\r
+ NonShareware();\r
+ #endif\r
+ #else\r
+\r
+ #ifndef GOODTIMES\r
+ #ifndef SPEARDEMO\r
+ CopyProtection();\r
+ #endif\r
+ #endif\r
+\r
+ #endif\r
+ #endif\r
+ #endif\r
+\r
+ StartCPMusic(INTROSONG);\r
+\r
+#ifndef JAPAN\r
+ if (!NoWait)\r
+ PG13 ();\r
+#endif\r
+\r
+#endif\r
+\r
+ while (1)\r
+ {\r
+ while (!NoWait)\r
+ {\r
+//\r
+// title page\r
+//\r
+ MM_SortMem ();\r
+#ifndef DEMOTEST\r
+\r
+#ifdef SPEAR\r
+ CA_CacheGrChunk (TITLEPALETTE);\r
+\r
+ CA_CacheGrChunk (TITLE1PIC);\r
+ VWB_DrawPic (0,0,TITLE1PIC);\r
+ UNCACHEGRCHUNK (TITLE1PIC);\r
+\r
+ CA_CacheGrChunk (TITLE2PIC);\r
+ VWB_DrawPic (0,80,TITLE2PIC);\r
+ UNCACHEGRCHUNK (TITLE2PIC);\r
+ VW_UpdateScreen ();\r
+ VL_FadeIn(0,255,grsegs[TITLEPALETTE],30);\r
+\r
+ UNCACHEGRCHUNK (TITLEPALETTE);\r
+#else\r
+ CA_CacheScreen (TITLEPIC);\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn();\r
+#endif\r
+ if (IN_UserInput(TickBase*15))\r
+ break;\r
+ VW_FadeOut();\r
+//\r
+// credits page\r
+//\r
+ CA_CacheScreen (CREDITSPIC);\r
+ VW_UpdateScreen();\r
+ VW_FadeIn ();\r
+ if (IN_UserInput(TickBase*10))\r
+ break;\r
+ VW_FadeOut ();\r
+//\r
+// high scores\r
+//\r
+ DrawHighScores ();\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn ();\r
+\r
+ if (IN_UserInput(TickBase*10))\r
+ break;\r
+#endif\r
+//\r
+// demo\r
+//\r
+\r
+ #ifndef SPEARDEMO\r
+ PlayDemo (LastDemo++%4);\r
+ #else\r
+ PlayDemo (0);\r
+ #endif\r
+\r
+ if (playstate == ex_abort)\r
+ break;\r
+ StartCPMusic(INTROSONG);\r
+ }\r
+\r
+ VW_FadeOut ();\r
+\r
+#ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && MS_CheckParm("goobers"))\r
+#else\r
+ if (Keyboard[sc_Tab] && MS_CheckParm("debugmode"))\r
+#endif\r
+ RecordDemo ();\r
+ else\r
+ US_ControlPanel (0);\r
+\r
+ if (startgame || loadedgame)\r
+ {\r
+ GameLoop ();\r
+ VW_FadeOut();\r
+ StartCPMusic(INTROSONG);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+// WL_AGENT.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define MAXMOUSETURN 10\r
+\r
+\r
+#define MOVESCALE 150l\r
+#define BACKMOVESCALE 100l\r
+#define ANGLESCALE 20\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+\r
+//\r
+// player state info\r
+//\r
+boolean running;\r
+long thrustspeed;\r
+\r
+unsigned plux,pluy; // player coordinates scaled to unsigned\r
+\r
+int anglefrac;\r
+int gotgatgun; // JR\r
+\r
+objtype *LastAttacker;\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+void T_Player (objtype *ob);\r
+void T_Attack (objtype *ob);\r
+\r
+statetype s_player = {false,0,0,T_Player,NULL,NULL};\r
+statetype s_attack = {false,0,0,T_Attack,NULL,NULL};\r
+\r
+\r
+long playerxmove,playerymove;\r
+\r
+struct atkinf\r
+{\r
+ char tics,attack,frame; // attack is 1 for gun, 2 for knife\r
+} attackinfo[4][14] =\r
+\r
+{\r
+{ {6,0,1},{6,2,2},{6,0,3},{6,-1,4} },\r
+{ {6,0,1},{6,1,2},{6,0,3},{6,-1,4} },\r
+{ {6,0,1},{6,1,2},{6,3,3},{6,-1,4} },\r
+{ {6,0,1},{6,1,2},{6,4,3},{6,-1,4} },\r
+};\r
+\r
+\r
+int strafeangle[9] = {0,90,180,270,45,135,225,315,0};\r
+\r
+void DrawWeapon (void);\r
+void GiveWeapon (int weapon);\r
+void GiveAmmo (int ammo);\r
+\r
+//===========================================================================\r
+\r
+//----------\r
+\r
+void Attack (void);\r
+void Use (void);\r
+void Search (objtype *ob);\r
+void SelectWeapon (void);\r
+void SelectItem (void);\r
+\r
+//----------\r
+\r
+boolean TryMove (objtype *ob);\r
+void T_Player (objtype *ob);\r
+\r
+void ClipMove (objtype *ob, long xmove, long ymove);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ CONTROL STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+======================\r
+=\r
+= CheckWeaponChange\r
+=\r
+= Keys 1-4 change weapons\r
+=\r
+======================\r
+*/\r
+\r
+void CheckWeaponChange (void)\r
+{\r
+ int i,buttons;\r
+\r
+ if (!gamestate.ammo) // must use knife with no ammo\r
+ return;\r
+\r
+ for (i=wp_knife ; i<=gamestate.bestweapon ; i++)\r
+ if (buttonstate[bt_readyknife+i-wp_knife])\r
+ {\r
+ gamestate.weapon = gamestate.chosenweapon = i;\r
+ DrawWeapon ();\r
+ return;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=======================\r
+=\r
+= ControlMovement\r
+=\r
+= Takes controlx,controly, and buttonstate[bt_strafe]\r
+=\r
+= Changes the player's angle and position\r
+=\r
+= There is an angle hack because when going 70 fps, the roundoff becomes\r
+= significant\r
+=\r
+=======================\r
+*/\r
+\r
+void ControlMovement (objtype *ob)\r
+{\r
+ long oldx,oldy;\r
+ int angle,maxxmove;\r
+ int angleunits;\r
+ long speed;\r
+\r
+ thrustspeed = 0;\r
+\r
+ oldx = player->x;\r
+ oldy = player->y;\r
+\r
+//\r
+// side to side move\r
+//\r
+ if (buttonstate[bt_strafe])\r
+ {\r
+ //\r
+ // strafing\r
+ //\r
+ //\r
+ if (controlx > 0)\r
+ {\r
+ angle = ob->angle - ANGLES/4;\r
+ if (angle < 0)\r
+ angle += ANGLES;\r
+ Thrust (angle,controlx*MOVESCALE); // move to left\r
+ }\r
+ else if (controlx < 0)\r
+ {\r
+ angle = ob->angle + ANGLES/4;\r
+ if (angle >= ANGLES)\r
+ angle -= ANGLES;\r
+ Thrust (angle,-controlx*MOVESCALE); // move to right\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // not strafing\r
+ //\r
+ anglefrac += controlx;\r
+ angleunits = anglefrac/ANGLESCALE;\r
+ anglefrac -= angleunits*ANGLESCALE;\r
+ ob->angle -= angleunits;\r
+\r
+ if (ob->angle >= ANGLES)\r
+ ob->angle -= ANGLES;\r
+ if (ob->angle < 0)\r
+ ob->angle += ANGLES;\r
+\r
+ }\r
+\r
+//\r
+// forward/backwards move\r
+//\r
+ if (controly < 0)\r
+ {\r
+ Thrust (ob->angle,-controly*MOVESCALE); // move forwards\r
+ }\r
+ else if (controly > 0)\r
+ {\r
+ angle = ob->angle + ANGLES/2;\r
+ if (angle >= ANGLES)\r
+ angle -= ANGLES;\r
+ Thrust (angle,controly*BACKMOVESCALE); // move backwards\r
+ }\r
+\r
+ if (gamestate.victoryflag) // watching the BJ actor\r
+ return;\r
+\r
+//\r
+// calculate total move\r
+//\r
+ playerxmove = player->x - oldx;\r
+ playerymove = player->y - oldy;\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+ STATUS WINDOW STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= StatusDrawPic\r
+=\r
+==================\r
+*/\r
+\r
+void StatusDrawPic (unsigned x, unsigned y, unsigned picnum)\r
+{\r
+ unsigned temp;\r
+\r
+ temp = bufferofs;\r
+ bufferofs = 0;\r
+\r
+ bufferofs = PAGE1START+(200-STATUSLINES)*SCREENWIDTH;\r
+ LatchDrawPic (x,y,picnum);\r
+ bufferofs = PAGE2START+(200-STATUSLINES)*SCREENWIDTH;\r
+ LatchDrawPic (x,y,picnum);\r
+ bufferofs = PAGE3START+(200-STATUSLINES)*SCREENWIDTH;\r
+ LatchDrawPic (x,y,picnum);\r
+\r
+ bufferofs = temp;\r
+}\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= DrawFace\r
+=\r
+==================\r
+*/\r
+\r
+void DrawFace (void)\r
+{\r
+ if (gamestate.health)\r
+ {\r
+ #ifdef SPEAR\r
+ if (godmode)\r
+ StatusDrawPic (17,4,GODMODEFACE1PIC+gamestate.faceframe);\r
+ else\r
+ #endif\r
+ StatusDrawPic (17,4,FACE1APIC+3*((100-gamestate.health)/16)+gamestate.faceframe);\r
+ }\r
+ else\r
+ {\r
+#ifndef SPEAR\r
+ if (LastAttacker->obclass == needleobj)\r
+ StatusDrawPic (17,4,MUTANTBJPIC);\r
+ else\r
+#endif\r
+ StatusDrawPic (17,4,FACE8APIC);\r
+ }\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= UpdateFace\r
+=\r
+= Calls draw face if time to change\r
+=\r
+===============\r
+*/\r
+\r
+#define FACETICS 70\r
+\r
+int facecount;\r
+\r
+void UpdateFace (void)\r
+{\r
+\r
+ if (SD_SoundPlaying() == GETGATLINGSND)\r
+ return;\r
+\r
+ facecount += tics;\r
+ if (facecount > US_RndT())\r
+ {\r
+ gamestate.faceframe = (US_RndT()>>6);\r
+ if (gamestate.faceframe==3)\r
+ gamestate.faceframe = 1;\r
+\r
+ facecount = 0;\r
+ DrawFace ();\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= LatchNumber\r
+=\r
+= right justifies and pads with blanks\r
+=\r
+===============\r
+*/\r
+\r
+void LatchNumber (int x, int y, int width, long number)\r
+{\r
+ unsigned length,c;\r
+ char str[20];\r
+\r
+ ltoa (number,str,10);\r
+\r
+ length = strlen (str);\r
+\r
+ while (length<width)\r
+ {\r
+ StatusDrawPic (x,y,N_BLANKPIC);\r
+ x++;\r
+ width--;\r
+ }\r
+\r
+ c= length <= width ? 0 : length-width;\r
+\r
+ while (c<length)\r
+ {\r
+ StatusDrawPic (x,y,str[c]-'0'+ N_0PIC);\r
+ x++;\r
+ c++;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= DrawHealth\r
+=\r
+===============\r
+*/\r
+\r
+void DrawHealth (void)\r
+{\r
+ LatchNumber (21,16,3,gamestate.health);\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= TakeDamage\r
+=\r
+===============\r
+*/\r
+\r
+void TakeDamage (int points,objtype *attacker)\r
+{\r
+ LastAttacker = attacker;\r
+\r
+ if (gamestate.victoryflag)\r
+ return;\r
+ if (gamestate.difficulty==gd_baby)\r
+ points>>=2;\r
+\r
+ if (!godmode)\r
+ gamestate.health -= points;\r
+\r
+ if (gamestate.health<=0)\r
+ {\r
+ gamestate.health = 0;\r
+ playstate = ex_died;\r
+ killerobj = attacker;\r
+ }\r
+\r
+ StartDamageFlash (points);\r
+\r
+ gotgatgun=0;\r
+\r
+ DrawHealth ();\r
+ DrawFace ();\r
+\r
+ //\r
+ // MAKE BJ'S EYES BUG IF MAJOR DAMAGE!\r
+ //\r
+ #ifdef SPEAR\r
+ if (points > 30 && gamestate.health!=0 && !godmode)\r
+ {\r
+ StatusDrawPic (17,4,BJOUCHPIC);\r
+ facecount = 0;\r
+ }\r
+ #endif\r
+\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= HealSelf\r
+=\r
+===============\r
+*/\r
+\r
+void HealSelf (int points)\r
+{\r
+ gamestate.health += points;\r
+ if (gamestate.health>100)\r
+ gamestate.health = 100;\r
+\r
+ DrawHealth ();\r
+ gotgatgun = 0; // JR\r
+ DrawFace ();\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= DrawLevel\r
+=\r
+===============\r
+*/\r
+\r
+void DrawLevel (void)\r
+{\r
+#ifdef SPEAR\r
+ if (gamestate.mapon == 20)\r
+ LatchNumber (2,16,2,18);\r
+ else\r
+#endif\r
+ LatchNumber (2,16,2,gamestate.mapon+1);\r
+}\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= DrawLives\r
+=\r
+===============\r
+*/\r
+\r
+void DrawLives (void)\r
+{\r
+ LatchNumber (14,16,1,gamestate.lives);\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= GiveExtraMan\r
+=\r
+===============\r
+*/\r
+\r
+void GiveExtraMan (void)\r
+{\r
+ if (gamestate.lives<9)\r
+ gamestate.lives++;\r
+ DrawLives ();\r
+ SD_PlaySound (BONUS1UPSND);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= DrawScore\r
+=\r
+===============\r
+*/\r
+\r
+void DrawScore (void)\r
+{\r
+ LatchNumber (6,16,6,gamestate.score);\r
+}\r
+\r
+/*\r
+===============\r
+=\r
+= GivePoints\r
+=\r
+===============\r
+*/\r
+\r
+void GivePoints (long points)\r
+{\r
+ gamestate.score += points;\r
+ while (gamestate.score >= gamestate.nextextra)\r
+ {\r
+ gamestate.nextextra += EXTRAPOINTS;\r
+ GiveExtraMan ();\r
+ }\r
+ DrawScore ();\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= DrawWeapon\r
+=\r
+==================\r
+*/\r
+\r
+void DrawWeapon (void)\r
+{\r
+ StatusDrawPic (32,8,KNIFEPIC+gamestate.weapon);\r
+}\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= DrawKeys\r
+=\r
+==================\r
+*/\r
+\r
+void DrawKeys (void)\r
+{\r
+ if (gamestate.keys & 1)\r
+ StatusDrawPic (30,4,GOLDKEYPIC);\r
+ else\r
+ StatusDrawPic (30,4,NOKEYPIC);\r
+\r
+ if (gamestate.keys & 2)\r
+ StatusDrawPic (30,20,SILVERKEYPIC);\r
+ else\r
+ StatusDrawPic (30,20,NOKEYPIC);\r
+}\r
+\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= GiveWeapon\r
+=\r
+==================\r
+*/\r
+\r
+void GiveWeapon (int weapon)\r
+{\r
+ GiveAmmo (6);\r
+\r
+ if (gamestate.bestweapon<weapon)\r
+ gamestate.bestweapon = gamestate.weapon\r
+ = gamestate.chosenweapon = weapon;\r
+\r
+ DrawWeapon ();\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= DrawAmmo\r
+=\r
+===============\r
+*/\r
+\r
+void DrawAmmo (void)\r
+{\r
+ LatchNumber (27,16,2,gamestate.ammo);\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= GiveAmmo\r
+=\r
+===============\r
+*/\r
+\r
+void GiveAmmo (int ammo)\r
+{\r
+ if (!gamestate.ammo) // knife was out\r
+ {\r
+ if (!gamestate.attackframe)\r
+ {\r
+ gamestate.weapon = gamestate.chosenweapon;\r
+ DrawWeapon ();\r
+ }\r
+ }\r
+ gamestate.ammo += ammo;\r
+ if (gamestate.ammo > 99)\r
+ gamestate.ammo = 99;\r
+ DrawAmmo ();\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= GiveKey\r
+=\r
+==================\r
+*/\r
+\r
+void GiveKey (int key)\r
+{\r
+ gamestate.keys |= (1<<key);\r
+ DrawKeys ();\r
+}\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ MOVEMENT\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= GetBonus\r
+=\r
+===================\r
+*/\r
+void GetBonus (statobj_t *check)\r
+{\r
+ switch (check->itemnumber)\r
+ {\r
+ case bo_firstaid:\r
+ if (gamestate.health == 100)\r
+ return;\r
+\r
+ SD_PlaySound (HEALTH2SND);\r
+ HealSelf (25);\r
+ break;\r
+\r
+ case bo_key1:\r
+ case bo_key2:\r
+ case bo_key3:\r
+ case bo_key4:\r
+ GiveKey (check->itemnumber - bo_key1);\r
+ SD_PlaySound (GETKEYSND);\r
+ break;\r
+\r
+ case bo_cross:\r
+ SD_PlaySound (BONUS1SND);\r
+ GivePoints (100);\r
+ gamestate.treasurecount++;\r
+ break;\r
+ case bo_chalice:\r
+ SD_PlaySound (BONUS2SND);\r
+ GivePoints (500);\r
+ gamestate.treasurecount++;\r
+ break;\r
+ case bo_bible:\r
+ SD_PlaySound (BONUS3SND);\r
+ GivePoints (1000);\r
+ gamestate.treasurecount++;\r
+ break;\r
+ case bo_crown:\r
+ SD_PlaySound (BONUS4SND);\r
+ GivePoints (5000);\r
+ gamestate.treasurecount++;\r
+ break;\r
+\r
+ case bo_clip:\r
+ if (gamestate.ammo == 99)\r
+ return;\r
+\r
+ SD_PlaySound (GETAMMOSND);\r
+ GiveAmmo (8);\r
+ break;\r
+ case bo_clip2:\r
+ if (gamestate.ammo == 99)\r
+ return;\r
+\r
+ SD_PlaySound (GETAMMOSND);\r
+ GiveAmmo (4);\r
+ break;\r
+\r
+#ifdef SPEAR\r
+ case bo_25clip:\r
+ if (gamestate.ammo == 99)\r
+ return;\r
+\r
+ SD_PlaySound (GETAMMOBOXSND);\r
+ GiveAmmo (25);\r
+ break;\r
+#endif\r
+\r
+ case bo_machinegun:\r
+ SD_PlaySound (GETMACHINESND);\r
+ GiveWeapon (wp_machinegun);\r
+ break;\r
+ case bo_chaingun:\r
+ SD_PlaySound (GETGATLINGSND);\r
+ GiveWeapon (wp_chaingun);\r
+\r
+ StatusDrawPic (17,4,GOTGATLINGPIC);\r
+ facecount = 0;\r
+ gotgatgun = 1;\r
+ break;\r
+\r
+ case bo_fullheal:\r
+ SD_PlaySound (BONUS1UPSND);\r
+ HealSelf (99);\r
+ GiveAmmo (25);\r
+ GiveExtraMan ();\r
+ gamestate.treasurecount++;\r
+ break;\r
+\r
+ case bo_food:\r
+ if (gamestate.health == 100)\r
+ return;\r
+\r
+ SD_PlaySound (HEALTH1SND);\r
+ HealSelf (10);\r
+ break;\r
+\r
+ case bo_alpo:\r
+ if (gamestate.health == 100)\r
+ return;\r
+\r
+ SD_PlaySound (HEALTH1SND);\r
+ HealSelf (4);\r
+ break;\r
+\r
+ case bo_gibs:\r
+ if (gamestate.health >10)\r
+ return;\r
+\r
+ SD_PlaySound (SLURPIESND);\r
+ HealSelf (1);\r
+ break;\r
+\r
+ case bo_spear:\r
+ spearflag = true;\r
+ spearx = player->x;\r
+ speary = player->y;\r
+ spearangle = player->angle;\r
+ playstate = ex_completed;\r
+ }\r
+\r
+ StartBonusFlash ();\r
+ check->shapenum = -1; // remove from list\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= TryMove\r
+=\r
+= returns true if move ok\r
+= debug: use pointers to optimize\r
+===================\r
+*/\r
+\r
+boolean TryMove (objtype *ob)\r
+{\r
+ int xl,yl,xh,yh,x,y;\r
+ objtype *check;\r
+ long deltax,deltay;\r
+\r
+ xl = (ob->x-PLAYERSIZE) >>TILESHIFT;\r
+ yl = (ob->y-PLAYERSIZE) >>TILESHIFT;\r
+\r
+ xh = (ob->x+PLAYERSIZE) >>TILESHIFT;\r
+ yh = (ob->y+PLAYERSIZE) >>TILESHIFT;\r
+\r
+//\r
+// check for solid walls\r
+//\r
+ for (y=yl;y<=yh;y++)\r
+ for (x=xl;x<=xh;x++)\r
+ {\r
+ check = actorat[x][y];\r
+ if (check && check<objlist)\r
+ return false;\r
+ }\r
+\r
+//\r
+// check for actors\r
+//\r
+ if (yl>0)\r
+ yl--;\r
+ if (yh<MAPSIZE-1)\r
+ yh++;\r
+ if (xl>0)\r
+ xl--;\r
+ if (xh<MAPSIZE-1)\r
+ xh++;\r
+\r
+ for (y=yl;y<=yh;y++)\r
+ for (x=xl;x<=xh;x++)\r
+ {\r
+ check = actorat[x][y];\r
+ if (check > objlist\r
+ && (check->flags & FL_SHOOTABLE) )\r
+ {\r
+ deltax = ob->x - check->x;\r
+ if (deltax < -MINACTORDIST || deltax > MINACTORDIST)\r
+ continue;\r
+ deltay = ob->y - check->y;\r
+ if (deltay < -MINACTORDIST || deltay > MINACTORDIST)\r
+ continue;\r
+\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= ClipMove\r
+=\r
+===================\r
+*/\r
+\r
+void ClipMove (objtype *ob, long xmove, long ymove)\r
+{\r
+ long basex,basey;\r
+\r
+ basex = ob->x;\r
+ basey = ob->y;\r
+\r
+ ob->x = basex+xmove;\r
+ ob->y = basey+ymove;\r
+ if (TryMove (ob))\r
+ return;\r
+\r
+ if (noclip && ob->x > 2*TILEGLOBAL && ob->y > 2*TILEGLOBAL &&\r
+ ob->x < (((long)(mapwidth-1))<<TILESHIFT)\r
+ && ob->y < (((long)(mapheight-1))<<TILESHIFT) )\r
+ return; // walk through walls\r
+\r
+ if (!SD_SoundPlaying())\r
+ SD_PlaySound (HITWALLSND);\r
+\r
+ ob->x = basex+xmove;\r
+ ob->y = basey;\r
+ if (TryMove (ob))\r
+ return;\r
+\r
+ ob->x = basex;\r
+ ob->y = basey+ymove;\r
+ if (TryMove (ob))\r
+ return;\r
+\r
+ ob->x = basex;\r
+ ob->y = basey;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= VictoryTile\r
+=\r
+===================\r
+*/\r
+\r
+void VictoryTile (void)\r
+{\r
+#ifndef SPEAR\r
+ SpawnBJVictory ();\r
+#endif\r
+\r
+ gamestate.victoryflag = true;\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= Thrust\r
+=\r
+===================\r
+*/\r
+\r
+void Thrust (int angle, long speed)\r
+{\r
+ long xmove,ymove;\r
+ long slowmax;\r
+ unsigned offset;\r
+\r
+\r
+ //\r
+ // ZERO FUNNY COUNTER IF MOVED!\r
+ //\r
+ #ifdef SPEAR\r
+ if (speed)\r
+ funnyticount = 0;\r
+ #endif\r
+\r
+ thrustspeed += speed;\r
+//\r
+// moving bounds speed\r
+//\r
+ if (speed >= MINDIST*2)\r
+ speed = MINDIST*2-1;\r
+\r
+ xmove = FixedByFrac(speed,costable[angle]);\r
+ ymove = -FixedByFrac(speed,sintable[angle]);\r
+\r
+ ClipMove(player,xmove,ymove);\r
+\r
+ player->tilex = player->x >> TILESHIFT; // scale to tile values\r
+ player->tiley = player->y >> TILESHIFT;\r
+\r
+ offset = farmapylookup[player->tiley]+player->tilex;\r
+ player->areanumber = *(mapsegs[0] + offset) -AREATILE;\r
+\r
+ if (*(mapsegs[1] + offset) == EXITTILE)\r
+ VictoryTile ();\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ ACTIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= Cmd_Fire\r
+=\r
+===============\r
+*/\r
+\r
+void Cmd_Fire (void)\r
+{\r
+ buttonheld[bt_attack] = true;\r
+\r
+ gamestate.weaponframe = 0;\r
+\r
+ player->state = &s_attack;\r
+\r
+ gamestate.attackframe = 0;\r
+ gamestate.attackcount =\r
+ attackinfo[gamestate.weapon][gamestate.attackframe].tics;\r
+ gamestate.weaponframe =\r
+ attackinfo[gamestate.weapon][gamestate.attackframe].frame;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= Cmd_Use\r
+=\r
+===============\r
+*/\r
+\r
+void Cmd_Use (void)\r
+{\r
+ objtype *check;\r
+ int checkx,checky,doornum,dir;\r
+ boolean elevatorok;\r
+\r
+\r
+//\r
+// find which cardinal direction the player is facing\r
+//\r
+ if (player->angle < ANGLES/8 || player->angle > 7*ANGLES/8)\r
+ {\r
+ checkx = player->tilex + 1;\r
+ checky = player->tiley;\r
+ dir = di_east;\r
+ elevatorok = true;\r
+ }\r
+ else if (player->angle < 3*ANGLES/8)\r
+ {\r
+ checkx = player->tilex;\r
+ checky = player->tiley-1;\r
+ dir = di_north;\r
+ elevatorok = false;\r
+ }\r
+ else if (player->angle < 5*ANGLES/8)\r
+ {\r
+ checkx = player->tilex - 1;\r
+ checky = player->tiley;\r
+ dir = di_west;\r
+ elevatorok = true;\r
+ }\r
+ else\r
+ {\r
+ checkx = player->tilex;\r
+ checky = player->tiley + 1;\r
+ dir = di_south;\r
+ elevatorok = false;\r
+ }\r
+\r
+ doornum = tilemap[checkx][checky];\r
+ if (*(mapsegs[1]+farmapylookup[checky]+checkx) == PUSHABLETILE)\r
+ {\r
+ //\r
+ // pushable wall\r
+ //\r
+\r
+ PushWall (checkx,checky,dir);\r
+ return;\r
+ }\r
+ if (!buttonheld[bt_use] && doornum == ELEVATORTILE && elevatorok)\r
+ {\r
+ //\r
+ // use elevator\r
+ //\r
+ buttonheld[bt_use] = true;\r
+\r
+ tilemap[checkx][checky]++; // flip switch\r
+ if (*(mapsegs[0]+farmapylookup[player->tiley]+player->tilex) == ALTELEVATORTILE)\r
+ playstate = ex_secretlevel;\r
+ else\r
+ playstate = ex_completed;\r
+ SD_PlaySound (LEVELDONESND);\r
+ SD_WaitSoundDone();\r
+ }\r
+ else if (!buttonheld[bt_use] && doornum & 0x80)\r
+ {\r
+ buttonheld[bt_use] = true;\r
+ OperateDoor (doornum & ~0x80);\r
+ }\r
+ else\r
+ SD_PlaySound (DONOTHINGSND);\r
+\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+ PLAYER CONTROL\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnPlayer\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnPlayer (int tilex, int tiley, int dir)\r
+{\r
+ player->obclass = playerobj;\r
+ player->active = true;\r
+ player->tilex = tilex;\r
+ player->tiley = tiley;\r
+ player->areanumber =\r
+ *(mapsegs[0] + farmapylookup[player->tiley]+player->tilex);\r
+ player->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ player->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+ player->state = &s_player;\r
+ player->angle = (1-dir)*90;\r
+ if (player->angle<0)\r
+ player->angle += ANGLES;\r
+ player->flags = FL_NEVERMARK;\r
+ Thrust (0,0); // set some variables\r
+\r
+ InitAreas ();\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= T_KnifeAttack\r
+=\r
+= Update player hands, and try to do damage when the proper frame is reached\r
+=\r
+===============\r
+*/\r
+\r
+void KnifeAttack (objtype *ob)\r
+{\r
+ objtype *check,*closest;\r
+ long dist;\r
+\r
+ SD_PlaySound (ATKKNIFESND);\r
+// actually fire\r
+ dist = 0x7fffffff;\r
+ closest = NULL;\r
+ for (check=ob->next ; check ; check=check->next)\r
+ if ( (check->flags & FL_SHOOTABLE)\r
+ && (check->flags & FL_VISABLE)\r
+ && abs (check->viewx-centerx) < shootdelta\r
+ )\r
+ {\r
+ if (check->transx < dist)\r
+ {\r
+ dist = check->transx;\r
+ closest = check;\r
+ }\r
+ }\r
+\r
+ if (!closest || dist> 0x18000l)\r
+ {\r
+ // missed\r
+\r
+ return;\r
+ }\r
+\r
+// hit something\r
+ DamageActor (closest,US_RndT() >> 4);\r
+}\r
+\r
+\r
+\r
+void GunAttack (objtype *ob)\r
+{\r
+ objtype *check,*closest,*oldclosest;\r
+ int damage;\r
+ int dx,dy,dist;\r
+ long viewdist;\r
+\r
+ switch (gamestate.weapon)\r
+ {\r
+ case wp_pistol:\r
+ SD_PlaySound (ATKPISTOLSND);\r
+ break;\r
+ case wp_machinegun:\r
+ SD_PlaySound (ATKMACHINEGUNSND);\r
+ break;\r
+ case wp_chaingun:\r
+ SD_PlaySound (ATKGATLINGSND);\r
+ break;\r
+ }\r
+\r
+ madenoise = true;\r
+\r
+//\r
+// find potential targets\r
+//\r
+ viewdist = 0x7fffffffl;\r
+ closest = NULL;\r
+\r
+ while (1)\r
+ {\r
+ oldclosest = closest;\r
+\r
+ for (check=ob->next ; check ; check=check->next)\r
+ if ( (check->flags & FL_SHOOTABLE)\r
+ && (check->flags & FL_VISABLE)\r
+ && abs (check->viewx-centerx) < shootdelta\r
+ )\r
+ {\r
+ if (check->transx < viewdist)\r
+ {\r
+ viewdist = check->transx;\r
+ closest = check;\r
+ }\r
+ }\r
+\r
+ if (closest == oldclosest)\r
+ return; // no more targets, all missed\r
+\r
+ //\r
+ // trace a line from player to enemey\r
+ //\r
+ if (CheckLine(closest))\r
+ break;\r
+\r
+ }\r
+\r
+//\r
+// hit something\r
+//\r
+ dx = abs(closest->tilex - player->tilex);\r
+ dy = abs(closest->tiley - player->tiley);\r
+ dist = dx>dy ? dx:dy;\r
+\r
+ if (dist<2)\r
+ damage = US_RndT() / 4;\r
+ else if (dist<4)\r
+ damage = US_RndT() / 6;\r
+ else\r
+ {\r
+ if ( (US_RndT() / 12) < dist) // missed\r
+ return;\r
+ damage = US_RndT() / 6;\r
+ }\r
+\r
+ DamageActor (closest,damage);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= VictorySpin\r
+=\r
+===============\r
+*/\r
+\r
+void VictorySpin (void)\r
+{\r
+ long desty;\r
+\r
+ if (player->angle > 270)\r
+ {\r
+ player->angle -= tics * 3;\r
+ if (player->angle < 270)\r
+ player->angle = 270;\r
+ }\r
+ else if (player->angle < 270)\r
+ {\r
+ player->angle += tics * 3;\r
+ if (player->angle > 270)\r
+ player->angle = 270;\r
+ }\r
+\r
+ desty = (((long)player->tiley-5)<<TILESHIFT)-0x3000;\r
+\r
+ if (player->y > desty)\r
+ {\r
+ player->y -= tics*4096;\r
+ if (player->y < desty)\r
+ player->y = desty;\r
+ }\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= T_Attack\r
+=\r
+===============\r
+*/\r
+\r
+void T_Attack (objtype *ob)\r
+{\r
+ struct atkinf *cur;\r
+\r
+ UpdateFace ();\r
+\r
+ if (gamestate.victoryflag) // watching the BJ actor\r
+ {\r
+ VictorySpin ();\r
+ return;\r
+ }\r
+\r
+ if ( buttonstate[bt_use] && !buttonheld[bt_use] )\r
+ buttonstate[bt_use] = false;\r
+\r
+ if ( buttonstate[bt_attack] && !buttonheld[bt_attack])\r
+ buttonstate[bt_attack] = false;\r
+\r
+ ControlMovement (ob);\r
+ if (gamestate.victoryflag) // watching the BJ actor\r
+ return;\r
+\r
+ plux = player->x >> UNSIGNEDSHIFT; // scale to fit in unsigned\r
+ pluy = player->y >> UNSIGNEDSHIFT;\r
+ player->tilex = player->x >> TILESHIFT; // scale to tile values\r
+ player->tiley = player->y >> TILESHIFT;\r
+\r
+//\r
+// change frame and fire\r
+//\r
+ gamestate.attackcount -= tics;\r
+ while (gamestate.attackcount <= 0)\r
+ {\r
+ cur = &attackinfo[gamestate.weapon][gamestate.attackframe];\r
+ switch (cur->attack)\r
+ {\r
+ case -1:\r
+ ob->state = &s_player;\r
+ if (!gamestate.ammo)\r
+ {\r
+ gamestate.weapon = wp_knife;\r
+ DrawWeapon ();\r
+ }\r
+ else\r
+ {\r
+ if (gamestate.weapon != gamestate.chosenweapon)\r
+ {\r
+ gamestate.weapon = gamestate.chosenweapon;\r
+ DrawWeapon ();\r
+ }\r
+ };\r
+ gamestate.attackframe = gamestate.weaponframe = 0;\r
+ return;\r
+\r
+ case 4:\r
+ if (!gamestate.ammo)\r
+ break;\r
+ if (buttonstate[bt_attack])\r
+ gamestate.attackframe -= 2;\r
+ case 1:\r
+ if (!gamestate.ammo)\r
+ { // can only happen with chain gun\r
+ gamestate.attackframe++;\r
+ break;\r
+ }\r
+ GunAttack (ob);\r
+ gamestate.ammo--;\r
+ DrawAmmo ();\r
+ break;\r
+\r
+ case 2:\r
+ KnifeAttack (ob);\r
+ break;\r
+\r
+ case 3:\r
+ if (gamestate.ammo && buttonstate[bt_attack])\r
+ gamestate.attackframe -= 2;\r
+ break;\r
+ }\r
+\r
+ gamestate.attackcount += cur->tics;\r
+ gamestate.attackframe++;\r
+ gamestate.weaponframe =\r
+ attackinfo[gamestate.weapon][gamestate.attackframe].frame;\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= T_Player\r
+=\r
+===============\r
+*/\r
+\r
+void T_Player (objtype *ob)\r
+{\r
+ if (gamestate.victoryflag) // watching the BJ actor\r
+ {\r
+ VictorySpin ();\r
+ return;\r
+ }\r
+\r
+ UpdateFace ();\r
+ CheckWeaponChange ();\r
+\r
+ if ( buttonstate[bt_use] )\r
+ Cmd_Use ();\r
+\r
+ if ( buttonstate[bt_attack] && !buttonheld[bt_attack])\r
+ Cmd_Fire ();\r
+\r
+ ControlMovement (ob);\r
+ if (gamestate.victoryflag) // watching the BJ actor\r
+ return;\r
+\r
+\r
+ plux = player->x >> UNSIGNEDSHIFT; // scale to fit in unsigned\r
+ pluy = player->y >> UNSIGNEDSHIFT;\r
+ player->tilex = player->x >> TILESHIFT; // scale to tile values\r
+ player->tiley = player->y >> TILESHIFT;\r
+}\r
+\r
+\r
--- /dev/null
+ IDEAL\r
+ MODEL MEDIUM,C\r
+ P286\r
+\r
+SCREENSEG = 0a000h\r
+\r
+FINEANGLES = 3600\r
+DEG90 = 900\r
+DEG180 = 1800\r
+DEG270 = 2700\r
+DEG360 = 3600\r
+\r
+OP_JLE = 07eh\r
+OP_JGE = 07dh\r
+\r
+EXTRN finetangent:DWORD ; far array, starts at offset 0\r
+\r
+EXTRN HitHorizWall:FAR\r
+EXTRN HitVertWall:FAR\r
+EXTRN HitHorizDoor:FAR\r
+EXTRN HitVertDoor:FAR\r
+EXTRN HitHorizPWall:FAR\r
+EXTRN HitVertPWall:FAR\r
+\r
+\r
+DATASEG\r
+\r
+EXTRN viewwidth:WORD\r
+\r
+EXTRN tilemap:BYTE\r
+EXTRN spotvis:BYTE\r
+EXTRN pixelangle:WORD\r
+\r
+\r
+EXTRN midangle:WORD\r
+EXTRN angle:WORD\r
+\r
+EXTRN focaltx:WORD\r
+EXTRN focalty:WORD\r
+EXTRN viewtx:WORD\r
+EXTRN viewty:WORD\r
+EXTRN viewx:DWORD\r
+EXTRN viewy:DWORD\r
+\r
+EXTRN xpartialup:WORD\r
+EXTRN ypartialup:WORD\r
+EXTRN xpartialdown:WORD\r
+EXTRN ypartialdown:WORD\r
+\r
+EXTRN tilehit:WORD\r
+EXTRN pixx:WORD\r
+EXTRN wallheight:WORD ; array of VIEWWIDTH entries\r
+\r
+EXTRN xtile:WORD\r
+EXTRN ytile:WORD\r
+EXTRN xtilestep:WORD\r
+EXTRN ytilestep:WORD\r
+EXTRN xintercept:DWORD\r
+EXTRN yintercept:DWORD\r
+EXTRN xstep:DWORD\r
+EXTRN ystep:DWORD\r
+\r
+EXTRN doorposition:WORD ; table of door position values\r
+\r
+\r
+EXTRN pwallpos:WORD ; amound a pushable wall has been moved\r
+\r
+CODESEG\r
+\r
+;-------------------\r
+;\r
+; xpartialbyystep\r
+;\r
+; multiplies long [ystep] (possibly negative), by word [xpartial] (in BX)\r
+;\r
+; returns dx:ax\r
+; trashes bx,cx,di\r
+;\r
+;-------------------\r
+\r
+PROC xpartialbyystep NEAR\r
+;\r
+; setup\r
+;\r
+ mov ax,[WORD ystep]\r
+ mov cx,[WORD ystep+2]\r
+ or cx,cx ; is ystep negatice?\r
+ jns @@multpos\r
+;\r
+; multiply negative cx:ax by bx\r
+;\r
+ neg cx\r
+ neg ax\r
+ sbb cx,0\r
+\r
+ mul bx ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bx ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ ret\r
+;\r
+; multiply positive cx:ax by bx\r
+;\r
+EVEN\r
+@@multpos:\r
+ mul bx ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bx ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+\r
+ ret\r
+\r
+ENDP\r
+\r
+\r
+\r
+;-------------------\r
+;\r
+; ypartialbyxstep\r
+;\r
+; multiplies long [xstep] (possibly negative), by word [ypartial] (in BP)\r
+;\r
+; returns dx:ax\r
+; trashes cx,di,bp\r
+;\r
+;-------------------\r
+\r
+PROC ypartialbyxstep NEAR\r
+;\r
+; setup\r
+;\r
+ mov ax,[WORD xstep]\r
+ mov cx,[WORD xstep+2]\r
+ or cx,cx ; is ystep negatice?\r
+ jns @@multpos\r
+;\r
+; multiply negative cx:ax by bx\r
+;\r
+ neg cx\r
+ neg ax\r
+ sbb cx,0\r
+\r
+ mul bp ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bp ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ ret\r
+;\r
+; multiply positive cx:ax by bx\r
+;\r
+EVEN\r
+@@multpos:\r
+ mul bp ; fraction*fraction\r
+ mov di,dx ; di is low word of result\r
+ mov ax,cx ;\r
+ mul bp ; units*fraction\r
+ add ax,di\r
+ adc dx,0\r
+ ret\r
+\r
+ENDP\r
+\r
+\r
+;============================\r
+;\r
+; AsmRefresh\r
+;\r
+;\r
+;============================\r
+\r
+PROC AsmRefresh\r
+PUBLIC AsmRefresh\r
+\r
+ push si\r
+ push di\r
+ push bp\r
+\r
+ mov [pixx],0\r
+;---------------------------------------------------------------------------\r
+;\r
+; Setup to trace a ray through pixx view pixel\r
+;\r
+; CX : angle of the ray through pixx\r
+; ES : points to segment of finetangent array for this block of code\r
+;\r
+; Upon entrance to initialize block\r
+;\r
+; BX : xpartial\r
+; BP : ypartial\r
+;\r
+;---------------------------------------------------------------------------\r
+ EVEN\r
+pixxloop:\r
+ mov ax,SEG finetangent\r
+ mov es,ax\r
+ mov cx,[midangle] ; center of view area\r
+ mov bx,[pixx]\r
+ shl bx,1\r
+ add cx,[pixelangle+bx] ; delta for this pixel\r
+ cmp cx,0\r
+ jge not0\r
+;----------\r
+;\r
+; -90 - -1 degree arc\r
+;\r
+;----------\r
+ add cx,FINEANGLES ; -90 is the same as 270\r
+ jmp entry360\r
+\r
+not0:\r
+ cmp cx,DEG90\r
+ jge not90\r
+;----------\r
+;\r
+; 0-89 degree arc\r
+;\r
+;----------\r
+entry90:\r
+ mov [xtilestep],1 ; xtilestep = 1\r
+ mov [ytilestep],-1 ; ytilestep = -1\r
+ mov [BYTE cs:horizop],OP_JGE ; patch a jge in\r
+ mov [BYTE cs:vertop],OP_JLE ; patch a jle in\r
+ mov bx,DEG90-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = finetangent[DEG90-1-angle]\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = -finetangent[angle]\r
+\r
+ mov bx,[xpartialup] ; xpartial = xpartialup\r
+ mov bp,[ypartialdown] ; ypartial = ypartialdown\r
+ jmp initvars\r
+\r
+not90:\r
+ cmp cx,DEG180\r
+ jge not180\r
+;----------\r
+;\r
+; 90-179 degree arc\r
+;\r
+;----------\r
+ mov ax,-1\r
+ mov [xtilestep],ax ; xtilestep = -1\r
+ mov [ytilestep],ax ; ytilestep = -1\r
+ mov [BYTE cs:horizop],OP_JLE ; patch a jle in\r
+ mov [BYTE cs:vertop],OP_JLE ; patch a jle in\r
+\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx-DEG90*4]\r
+ mov dx,[es:bx+2-DEG90*4]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = -finetangent[angle-DEG90]\r
+ mov bx,DEG180-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = -finetangent[DEG180-1-angle]\r
+\r
+ mov bx,[xpartialdown] ; xpartial = xpartialdown\r
+ mov bp,[ypartialdown] ; ypartial = ypartialdown\r
+ jmp initvars\r
+\r
+not180:\r
+ cmp cx,DEG270\r
+ jge not270\r
+;----------\r
+;\r
+; 180-269 degree arc\r
+;\r
+;----------\r
+ mov [xtilestep],-1 ; xtilestep = -1\r
+ mov [ytilestep],1 ; ytilestep = 1\r
+ mov [BYTE cs:horizop],OP_JLE ; patch a jle in\r
+ mov [BYTE cs:vertop],OP_JGE ; patch a jge in\r
+\r
+ mov bx,DEG270-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ neg dx\r
+ neg ax\r
+ sbb dx,0\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = -finetangent[DEG270-1-angle]\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx-DEG180*4]\r
+ mov dx,[es:bx+2-DEG180*4]\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = finetangent[angle-DEG180]\r
+\r
+ mov bx,[xpartialdown] ; xpartial = xpartialdown\r
+ mov bp,[ypartialup] ; ypartial = ypartialup\r
+ jmp initvars\r
+\r
+\r
+not270:\r
+ cmp cx,DEG360\r
+ jge not360\r
+;----------\r
+;\r
+; 270-359 degree arc\r
+;\r
+;----------\r
+entry360:\r
+ mov ax,1\r
+ mov [xtilestep],ax ; xtilestep = 1\r
+ mov [ytilestep],ax ; ytilestep = 1\r
+ mov [BYTE cs:horizop],OP_JGE ; patch a jge in\r
+ mov [BYTE cs:vertop],OP_JGE ; patch a jge in\r
+\r
+ mov bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx-DEG270*4]\r
+ mov dx,[es:bx+2-DEG270*4]\r
+ mov [WORD xstep],ax\r
+ mov [WORD xstep+2],dx ; xstep = finetangent[angle-DEG270]\r
+ mov bx,DEG360-1\r
+ sub bx,cx\r
+ ;begin 8086 hack\r
+ ;shl bx,2\r
+ shl bx,1\r
+ shl bx,1\r
+ ;end 8086 hack\r
+ mov ax,[es:bx]\r
+ mov dx,[es:bx+2]\r
+ mov [WORD ystep],ax\r
+ mov [WORD ystep+2],dx ; ystep = finetangent[DEG360-1-angle]\r
+\r
+ mov bx,[xpartialup] ; xpartial = xpartialup\r
+ mov bp,[ypartialup] ; ypartial = ypartialup\r
+ jmp initvars\r
+\r
+\r
+not360:\r
+;----------\r
+;\r
+; 360-449 degree arc\r
+;\r
+;----------\r
+ sub cx,FINEANGLES ; -449 is the same as 89\r
+ jmp entry90\r
+\r
+;---------------------------------------------------------------------------\r
+;\r
+; initialise variables for intersection testing\r
+;\r
+;---------------------------------------------------------------------------\r
+initvars:\r
+ call NEAR xpartialbyystep ; xpartial is in BX\r
+ add ax,[WORD viewy]\r
+ adc dx,[WORD viewy+2]\r
+ mov [WORD yintercept],ax\r
+ mov [WORD yintercept+2],dx\r
+\r
+ mov si,[focaltx]\r
+ add si,[xtilestep]\r
+ mov [xtile],si ; xtile = focaltx+xtilestep\r
+ ;begin 8086 hack\r
+ ;shl si,6\r
+ push cx\r
+ mov cl,6\r
+ shl si,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add si,dx ; xspot = (xtile<<6) + yinttile\r
+\r
+\r
+ call NEAR ypartialbyxstep ; ypartial is in BP\r
+ add ax,[WORD viewx]\r
+ adc dx,[WORD viewx+2]\r
+ mov [WORD xintercept],ax\r
+ mov cx,dx\r
+\r
+ mov bx,[focalty]\r
+ add bx,[ytilestep]\r
+ mov bp,bx ; ytile = focalty+ytilestep\r
+ mov di,dx\r
+ ;begin 8086 hack\r
+ ;shl di,6\r
+ push cx\r
+ mov cl,6\r
+ shl di,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add di,bx ; yspot = (xinttile<<6) + ytile\r
+\r
+ mov bx,[xtile]\r
+ mov dx,[WORD yintercept+2]\r
+ mov ax,SCREENSEG\r
+ mov es,ax ; faster than mov es,[screenseg]\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+;\r
+; trace along this angle until we hit a wall\r
+;\r
+; CORE LOOP!\r
+;\r
+; All variables are killed when a wall is hit\r
+;\r
+; AX : scratch\r
+; BX : xtile\r
+; CX : high word of xintercept\r
+; DX : high word of yintercept\r
+; SI : xspot (yinttile<<6)+xtile (index into tilemap and spotvis)\r
+; DI : yspot (xinttile<<6)+ytile (index into tilemap and spotvis)\r
+; BP : ytile\r
+; ES : screenseg\r
+;\r
+;---------------------------------------------------------------------------\r
+\r
+;-----------\r
+;\r
+; check intersections with vertical walls\r
+;\r
+;-----------\r
+\r
+ EVEN\r
+vertcheck:\r
+ cmp dx,bp\r
+vertop: ; 0x7e = jle (ytilestep==-1)\r
+ jle horizentry ; 0x7d = jge (ytilestep==1)\r
+vertentry:\r
+ test [BYTE tilemap+si],0ffh ; tilehit = *((byte *)tilemap+xspot);\r
+ jnz hitvert\r
+passvert:\r
+ mov [BYTE spotvis+si],1 ; *((byte *)spotvis+xspot) = true;\r
+ add bx,[xtilestep] ; xtile+=xtilestep\r
+ mov ax,[WORD ystep]\r
+ add [WORD yintercept],ax ; yintercept += ystep\r
+ adc dx,[WORD ystep+2]\r
+ mov si,bx\r
+ ;begin 8086 hack\r
+ ;shl si,6\r
+ push cx\r
+ mov cl,6\r
+ shl si,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add si,dx ; xspot = (xtile<<6)+yinttile\r
+ jmp vertcheck\r
+\r
+ EVEN\r
+hitvert:\r
+ mov al,[BYTE tilemap+si] ; tilehit = *((byte *)tilemap+xspot);\r
+ mov [BYTE tilehit],al\r
+ or al,al ; set flags\r
+ jns notvertdoor\r
+ jmp vertdoor\r
+notvertdoor:\r
+ mov [WORD xintercept],0\r
+ mov [WORD xintercept+2],bx\r
+ mov [xtile],bx\r
+ mov [WORD yintercept+2],dx\r
+ mov [ytile],dx\r
+ call FAR HitVertWall\r
+ jmp nextpix\r
+\r
+\r
+;-----------\r
+;\r
+; check intersections with horizontal walls\r
+;\r
+;-----------\r
+ EVEN\r
+horizcheck:\r
+ cmp cx,bx\r
+horizop: ; 0x7e = jle (xtilestep==-1)\r
+ jle vertentry ; 0x7d = jge (xtilestep==1)\r
+horizentry:\r
+ test [BYTE tilemap+di],0ffh ; tilehit = *((byte *)tilemap+yspot);\r
+ jnz hithoriz\r
+passhoriz:\r
+ mov [BYTE spotvis+di],1 ; *((byte *)spotvis+yspot) = true;\r
+ add bp,[ytilestep] ; ytile+=ytilestep\r
+ mov ax,[WORD xstep]\r
+ add [WORD xintercept],ax ; xintercept += xstep\r
+ adc cx,[WORD xstep+2]\r
+ mov di,cx\r
+ ;begin 8086 hack\r
+ ;shl di,6\r
+ push cx\r
+ mov cl,6\r
+ shl di,cl\r
+ pop cx\r
+ ;end 8086 hack\r
+ add di,bp ; yspot = (xinttile<<6)+ytile\r
+ jmp horizcheck\r
+\r
+ EVEN\r
+hithoriz:\r
+ mov al,[BYTE tilemap+di] ; tilehit = *((byte *)tilemap+yspot);\r
+ mov [BYTE tilehit],al\r
+ or al,al ; set flags\r
+ js horizdoor\r
+ mov [WORD xintercept+2],cx\r
+ mov [xtile],cx\r
+ mov [WORD yintercept],0\r
+ mov [WORD yintercept+2],bp\r
+ mov [ytile],bp\r
+ call FAR HitHorizWall\r
+ jmp nextpix\r
+\r
+;---------------------------------------------------------------------------\r
+;\r
+; next pixel over\r
+;\r
+;---------------------------------------------------------------------------\r
+\r
+nextpix:\r
+ mov ax,[pixx]\r
+ inc ax\r
+ mov [pixx],ax\r
+ cmp ax,[viewwidth]\r
+ jge done\r
+ jmp pixxloop\r
+done:\r
+ pop bp\r
+ pop di\r
+ pop si\r
+ retf\r
+\r
+;===========================================================================\r
+\r
+;=============\r
+;\r
+; hit a special horizontal wall, so find which coordinate a door would be\r
+; intersected at, and check to see if the door is open past that point\r
+;\r
+;=============\r
+horizdoor:\r
+ mov [xtile],bx ; save off live register variables\r
+ mov [WORD yintercept+2],dx\r
+\r
+ test al,040h ; both high bits set == pushable wall\r
+ jnz horizpushwall\r
+\r
+ mov bx,ax\r
+ and bx,7fh ; strip high bit\r
+ shl bx,1 ; index into word width door table\r
+\r
+ mov ax,[WORD xstep]\r
+ mov dx,[WORD xstep+2]\r
+ sar dx,1\r
+ rcr ax,1 ; half a step gets to door position\r
+\r
+ add ax,[WORD xintercept] ; add half step to current intercept pos\r
+ adc dx,cx ; CX hold high word of xintercept\r
+\r
+ cmp cx,dx ; is it still in the same tile?\r
+ je hithmid\r
+;\r
+; midpoint is outside tile, so it hit the side of the wall before a door\r
+;\r
+continuehoriz:\r
+ mov bx,[xtile] ; reload register variables\r
+ mov dx,[WORD yintercept+2]\r
+ jmp passhoriz ; continue tracing\r
+;\r
+; the trace hit the door plane at pixel position AX, see if the door is\r
+; closed that much\r
+;\r
+hithmid:\r
+ cmp ax,[doorposition+bx] ; position of leading edge of door\r
+ jb continuehoriz\r
+;\r
+; draw the door\r
+;\r
+ mov [WORD xintercept],ax ; save pixel intercept position\r
+ mov [WORD xintercept+2],cx\r
+\r
+ mov [WORD yintercept],8000h ; intercept in middle of tile\r
+ mov [WORD yintercept+2],bp\r
+\r
+ call FAR HitHorizDoor\r
+ jmp nextpix\r
+\r
+;============\r
+;\r
+; hit a sliding horizontal wall\r
+;\r
+;============\r
+\r
+horizpushwall:\r
+ mov ax,[WORD xstep+2] ; multiply xstep by pwallmove (0-63)\r
+ mul [pwallpos]\r
+ mov bx,ax\r
+ mov ax,[WORD xstep]\r
+ mul [pwallpos]\r
+ add dx,bx\r
+\r
+ sar dx,1 ; then divide by 64 to accomplish a\r
+ rcr ax,1 ; fixed point multiplication\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+\r
+ add ax,[WORD xintercept] ; add partial step to current intercept\r
+ adc dx,cx ; CX hold high word of xintercept\r
+\r
+ cmp cx,dx ; is it still in the same tile?\r
+ jne continuehoriz ; no, it hit the side\r
+\r
+;\r
+; draw the pushable wall at the new height\r
+;\r
+ mov [WORD xintercept],ax ; save pixel intercept position\r
+ mov [WORD xintercept+2],dx\r
+\r
+ mov [WORD yintercept+2],bp\r
+ mov [WORD yintercept],0\r
+\r
+ call FAR HitHorizPWall\r
+ jmp nextpix\r
+\r
+\r
+\r
+;===========================================================================\r
+\r
+;=============\r
+;\r
+; hit a special vertical wall, so find which coordinate a door would be\r
+; intersected at, and check to see if the door is open past that point\r
+;\r
+;=============\r
+vertdoor:\r
+ mov [xtile],bx ; save off live register variables\r
+ mov [WORD yintercept+2],dx\r
+\r
+ test al,040h ; both high bits set == pushable wall\r
+ jnz vertpushwall\r
+\r
+ mov bx,ax\r
+ and bx,7fh ; strip high bit\r
+ shl bx,1 ; index into word width doorposition\r
+\r
+ mov ax,[WORD ystep]\r
+ mov dx,[WORD ystep+2]\r
+ sar dx,1\r
+ rcr ax,1 ; half a step gets to door position\r
+\r
+ add ax,[WORD yintercept] ; add half step to current intercept pos\r
+ adc dx,[WORD yintercept+2]\r
+\r
+ cmp [WORD yintercept+2],dx ; is it still in the same tile?\r
+ je hitvmid\r
+;\r
+; midpoint is outside tile, so it hit the side of the wall before a door\r
+;\r
+continuevert:\r
+ mov bx,[xtile] ; reload register variables\r
+ mov dx,[WORD yintercept+2]\r
+ jmp passvert ; continue tracing\r
+;\r
+; the trace hit the door plane at pixel position AX, see if the door is\r
+; closed that much\r
+;\r
+hitvmid:\r
+ cmp ax,[doorposition+bx] ; position of leading edge of door\r
+ jb continuevert\r
+;\r
+; draw the door\r
+;\r
+ mov [WORD yintercept],ax ; save pixel intercept position\r
+ mov [WORD xintercept],8000h ; intercept in middle of tile\r
+ mov ax,[xtile]\r
+ mov [WORD xintercept+2],ax\r
+\r
+ call FAR HitVertDoor\r
+ jmp nextpix\r
+\r
+;============\r
+;\r
+; hit a sliding vertical wall\r
+;\r
+;============\r
+\r
+vertpushwall:\r
+ mov ax,[WORD ystep+2] ; multiply ystep by pwallmove (0-63)\r
+ mul [pwallpos]\r
+ mov bx,ax\r
+ mov ax,[WORD ystep]\r
+ mul [pwallpos]\r
+ add dx,bx\r
+\r
+ sar dx,1 ; then divide by 64 to accomplish a\r
+ rcr ax,1 ; fixed point multiplication\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+ sar dx,1\r
+ rcr ax,1\r
+\r
+ add ax,[WORD yintercept] ; add partial step to current intercept\r
+ adc dx,[WORD yintercept+2]\r
+\r
+ cmp [WORD yintercept+2],dx ; is it still in the same tile?\r
+ jne continuevert ; no, it hit the side\r
+\r
+;\r
+; draw the pushable wall at the new height\r
+;\r
+ mov [WORD yintercept],ax ; save pixel intercept position\r
+ mov [WORD yintercept+2],dx\r
+\r
+ mov bx,[xtile]\r
+ mov [WORD xintercept+2],bx\r
+ mov [WORD xintercept],0\r
+\r
+ call FAR HitVertPWall\r
+ jmp nextpix\r
+\r
+\r
+\r
+ENDP\r
+\r
+\r
+END\r
+\r
+\r
--- /dev/null
+// WL_TEXT.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+/*\r
+=============================================================================\r
+\r
+TEXT FORMATTING COMMANDS\r
+------------------------\r
+^C<hex digit> Change text color\r
+^E[enter] End of layout (all pages)\r
+^G<y>,<x>,<pic>[enter] Draw a graphic and push margins\r
+^P[enter] start new page, must be the first chars in a layout\r
+^L<x>,<y>[ENTER] Locate to a specific spot, x in pixels, y in lines\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define BACKCOLOR 0x11\r
+\r
+\r
+#define WORDLIMIT 80\r
+#define FONTHEIGHT 10\r
+#define TOPMARGIN 16\r
+#define BOTTOMMARGIN 32\r
+#define LEFTMARGIN 16\r
+#define RIGHTMARGIN 16\r
+#define PICMARGIN 8\r
+#define TEXTROWS ((200-TOPMARGIN-BOTTOMMARGIN)/FONTHEIGHT)\r
+#define SPACEWIDTH 7\r
+#define SCREENPIXWIDTH 320\r
+#define SCREENMID (SCREENPIXWIDTH/2)\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+int pagenum,numpages;\r
+\r
+unsigned leftmargin[TEXTROWS],rightmargin[TEXTROWS];\r
+char far *text;\r
+unsigned rowon;\r
+\r
+int picx,picy,picnum,picdelay;\r
+boolean layoutdone;\r
+\r
+//===========================================================================\r
+\r
+#ifndef JAPAN\r
+/*\r
+=====================\r
+=\r
+= RipToEOL\r
+=\r
+=====================\r
+*/\r
+\r
+void RipToEOL (void)\r
+{\r
+ while (*text++ != '\n') // scan to end of line\r
+ ;\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= ParseNumber\r
+=\r
+=====================\r
+*/\r
+\r
+int ParseNumber (void)\r
+{\r
+ char ch;\r
+ char num[80],*numptr;\r
+\r
+//\r
+// scan until a number is found\r
+//\r
+ ch = *text;\r
+ while (ch < '0' || ch >'9')\r
+ ch = *++text;\r
+\r
+//\r
+// copy the number out\r
+//\r
+ numptr = num;\r
+ do\r
+ {\r
+ *numptr++ = ch;\r
+ ch = *++text;\r
+ } while (ch >= '0' && ch <= '9');\r
+ *numptr = 0;\r
+\r
+ return atoi (num);\r
+}\r
+\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= ParsePicCommand\r
+=\r
+= Call with text pointing just after a ^P\r
+= Upon exit text points to the start of next line\r
+=\r
+=====================\r
+*/\r
+\r
+void ParsePicCommand (void)\r
+{\r
+ picy=ParseNumber();\r
+ picx=ParseNumber();\r
+ picnum=ParseNumber();\r
+ RipToEOL ();\r
+}\r
+\r
+\r
+void ParseTimedCommand (void)\r
+{\r
+ picy=ParseNumber();\r
+ picx=ParseNumber();\r
+ picnum=ParseNumber();\r
+ picdelay=ParseNumber();\r
+ RipToEOL ();\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= TimedPicCommand\r
+=\r
+= Call with text pointing just after a ^P\r
+= Upon exit text points to the start of next line\r
+=\r
+=====================\r
+*/\r
+\r
+void TimedPicCommand (void)\r
+{\r
+ ParseTimedCommand ();\r
+\r
+//\r
+// update the screen, and wait for time delay\r
+//\r
+ VW_UpdateScreen ();\r
+\r
+//\r
+// wait for time\r
+//\r
+ TimeCount = 0;\r
+ while (TimeCount < picdelay)\r
+ ;\r
+\r
+//\r
+// draw pic\r
+//\r
+ VWB_DrawPic (picx&~7,picy,picnum);\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= HandleCommand\r
+=\r
+=====================\r
+*/\r
+\r
+void HandleCommand (void)\r
+{\r
+ int i,margin,top,bottom;\r
+ int picwidth,picheight,picmid;\r
+\r
+ switch (toupper(*++text))\r
+ {\r
+ case 'B':\r
+ picy=ParseNumber();\r
+ picx=ParseNumber();\r
+ picwidth=ParseNumber();\r
+ picheight=ParseNumber();\r
+ VWB_Bar(picx,picy,picwidth,picheight,BACKCOLOR);\r
+ RipToEOL();\r
+ break;\r
+ case ';': // comment\r
+ RipToEOL();\r
+ break;\r
+ case 'P': // ^P is start of next page, ^E is end of file\r
+ case 'E':\r
+ layoutdone = true;\r
+ text--; // back up to the '^'\r
+ break;\r
+\r
+ case 'C': // ^c<hex digit> changes text color\r
+ i = toupper(*++text);\r
+ if (i>='0' && i<='9')\r
+ fontcolor = i-'0';\r
+ else if (i>='A' && i<='F')\r
+ fontcolor = i-'A'+10;\r
+\r
+ fontcolor *= 16;\r
+ i = toupper(*++text);\r
+ if (i>='0' && i<='9')\r
+ fontcolor += i-'0';\r
+ else if (i>='A' && i<='F')\r
+ fontcolor += i-'A'+10;\r
+ text++;\r
+ break;\r
+\r
+ case '>':\r
+ px = 160;\r
+ text++;\r
+ break;\r
+\r
+ case 'L':\r
+ py=ParseNumber();\r
+ rowon = (py-TOPMARGIN)/FONTHEIGHT;\r
+ py = TOPMARGIN+rowon*FONTHEIGHT;\r
+ px=ParseNumber();\r
+ while (*text++ != '\n') // scan to end of line\r
+ ;\r
+ break;\r
+\r
+ case 'T': // ^Tyyy,xxx,ppp,ttt waits ttt tics, then draws pic\r
+ TimedPicCommand ();\r
+ break;\r
+\r
+ case 'G': // ^Gyyy,xxx,ppp draws graphic\r
+ ParsePicCommand ();\r
+ VWB_DrawPic (picx&~7,picy,picnum);\r
+ picwidth = pictable[picnum-STARTPICS].width;\r
+ picheight = pictable[picnum-STARTPICS].height;\r
+ //\r
+ // adjust margins\r
+ //\r
+ picmid = picx + picwidth/2;\r
+ if (picmid > SCREENMID)\r
+ margin = picx-PICMARGIN; // new right margin\r
+ else\r
+ margin = picx+picwidth+PICMARGIN; // new left margin\r
+\r
+ top = (picy-TOPMARGIN)/FONTHEIGHT;\r
+ if (top<0)\r
+ top = 0;\r
+ bottom = (picy+picheight-TOPMARGIN)/FONTHEIGHT;\r
+ if (bottom>=TEXTROWS)\r
+ bottom = TEXTROWS-1;\r
+\r
+ for (i=top;i<=bottom;i++)\r
+ if (picmid > SCREENMID)\r
+ rightmargin[i] = margin;\r
+ else\r
+ leftmargin[i] = margin;\r
+\r
+ //\r
+ // adjust this line if needed\r
+ //\r
+ if (px < leftmargin[rowon])\r
+ px = leftmargin[rowon];\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= NewLine\r
+=\r
+=====================\r
+*/\r
+\r
+void NewLine (void)\r
+{\r
+ char ch;\r
+\r
+ if (++rowon == TEXTROWS)\r
+ {\r
+ //\r
+ // overflowed the page, so skip until next page break\r
+ //\r
+ layoutdone = true;\r
+ do\r
+ {\r
+ if (*text == '^')\r
+ {\r
+ ch = toupper(*(text+1));\r
+ if (ch == 'E' || ch == 'P')\r
+ {\r
+ layoutdone = true;\r
+ return;\r
+ }\r
+ }\r
+ text++;\r
+\r
+ } while (1);\r
+\r
+ }\r
+ px = leftmargin[rowon];\r
+ py+= FONTHEIGHT;\r
+}\r
+\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= HandleCtrls\r
+=\r
+=====================\r
+*/\r
+\r
+void HandleCtrls (void)\r
+{\r
+ char ch;\r
+\r
+ ch = *text++; // get the character and advance\r
+\r
+ if (ch == '\n')\r
+ {\r
+ NewLine ();\r
+ return;\r
+ }\r
+\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= HandleWord\r
+=\r
+=====================\r
+*/\r
+\r
+void HandleWord (void)\r
+{\r
+ char word[WORDLIMIT];\r
+ int i,wordindex;\r
+ unsigned wwidth,wheight,newpos;\r
+\r
+\r
+ //\r
+ // copy the next word into [word]\r
+ //\r
+ word[0] = *text++;\r
+ wordindex = 1;\r
+ while (*text>32)\r
+ {\r
+ word[wordindex] = *text++;\r
+ if (++wordindex == WORDLIMIT)\r
+ Quit ("PageLayout: Word limit exceeded");\r
+ }\r
+ word[wordindex] = 0; // stick a null at end for C\r
+\r
+ //\r
+ // see if it fits on this line\r
+ //\r
+ VW_MeasurePropString (word,&wwidth,&wheight);\r
+\r
+ while (px+wwidth > rightmargin[rowon])\r
+ {\r
+ NewLine ();\r
+ if (layoutdone)\r
+ return; // overflowed page\r
+ }\r
+\r
+ //\r
+ // print it\r
+ //\r
+ newpos = px+wwidth;\r
+ VWB_DrawPropString (word);\r
+ px = newpos;\r
+\r
+ //\r
+ // suck up any extra spaces\r
+ //\r
+ while (*text == ' ')\r
+ {\r
+ px += SPACEWIDTH;\r
+ text++;\r
+ }\r
+}\r
+\r
+/*\r
+=====================\r
+=\r
+= PageLayout\r
+=\r
+= Clears the screen, draws the pics on the page, and word wraps the text.\r
+= Returns a pointer to the terminating command\r
+=\r
+=====================\r
+*/\r
+\r
+void PageLayout (boolean shownumber)\r
+{\r
+ int i,oldfontcolor;\r
+ char ch;\r
+\r
+ oldfontcolor = fontcolor;\r
+\r
+ fontcolor = 0;\r
+\r
+//\r
+// clear the screen\r
+//\r
+ VWB_Bar (0,0,320,200,BACKCOLOR);\r
+ VWB_DrawPic (0,0,H_TOPWINDOWPIC);\r
+ VWB_DrawPic (0,8,H_LEFTWINDOWPIC);\r
+ VWB_DrawPic (312,8,H_RIGHTWINDOWPIC);\r
+ VWB_DrawPic (8,176,H_BOTTOMINFOPIC);\r
+\r
+\r
+ for (i=0;i<TEXTROWS;i++)\r
+ {\r
+ leftmargin[i] = LEFTMARGIN;\r
+ rightmargin[i] = SCREENPIXWIDTH-RIGHTMARGIN;\r
+ }\r
+\r
+ px = LEFTMARGIN;\r
+ py = TOPMARGIN;\r
+ rowon = 0;\r
+ layoutdone = false;\r
+\r
+//\r
+// make sure we are starting layout text (^P first command)\r
+//\r
+ while (*text <= 32)\r
+ text++;\r
+\r
+ if (*text != '^' || toupper(*++text) != 'P')\r
+ Quit ("PageLayout: Text not headed with ^P");\r
+\r
+ while (*text++ != '\n')\r
+ ;\r
+\r
+\r
+//\r
+// process text stream\r
+//\r
+ do\r
+ {\r
+ ch = *text;\r
+\r
+ if (ch == '^')\r
+ HandleCommand ();\r
+ else\r
+ if (ch == 9)\r
+ {\r
+ px = (px+8)&0xf8;\r
+ text++;\r
+ }\r
+ else if (ch <= 32)\r
+ HandleCtrls ();\r
+ else\r
+ HandleWord ();\r
+\r
+ } while (!layoutdone);\r
+\r
+ pagenum++;\r
+\r
+ if (shownumber)\r
+ {\r
+ #ifdef SPANISH\r
+ strcpy (str,"Hoja ");\r
+ itoa (pagenum,str2,10);\r
+ strcat (str,str2);\r
+ strcat (str," de ");\r
+ py = 183;\r
+ px = 208;\r
+ #else\r
+ strcpy (str,"pg ");\r
+ itoa (pagenum,str2,10);\r
+ strcat (str,str2);\r
+ strcat (str," of ");\r
+ py = 183;\r
+ px = 213;\r
+ #endif\r
+ itoa (numpages,str2,10);\r
+ strcat (str,str2);\r
+ fontcolor = 0x4f; //12^BACKCOLOR;\r
+\r
+ VWB_DrawPropString (str);\r
+ }\r
+\r
+ fontcolor = oldfontcolor;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= BackPage\r
+=\r
+= Scans for a previous ^P\r
+=\r
+=====================\r
+*/\r
+\r
+void BackPage (void)\r
+{\r
+ pagenum--;\r
+ do\r
+ {\r
+ text--;\r
+ if (*text == '^' && toupper(*(text+1)) == 'P')\r
+ return;\r
+ } while (1);\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CacheLayoutGraphics\r
+=\r
+= Scans an entire layout file (until a ^E) marking all graphics used, and\r
+= counting pages, then caches the graphics in\r
+=\r
+=====================\r
+*/\r
+void CacheLayoutGraphics (void)\r
+{\r
+ char far *bombpoint, far *textstart;\r
+ char ch;\r
+\r
+ textstart = text;\r
+ bombpoint = text+30000;\r
+ numpages = pagenum = 0;\r
+\r
+ do\r
+ {\r
+ if (*text == '^')\r
+ {\r
+ ch = toupper(*++text);\r
+ if (ch == 'P') // start of a page\r
+ numpages++;\r
+ if (ch == 'E') // end of file, so load graphics and return\r
+ {\r
+ CA_MarkGrChunk(H_TOPWINDOWPIC);\r
+ CA_MarkGrChunk(H_LEFTWINDOWPIC);\r
+ CA_MarkGrChunk(H_RIGHTWINDOWPIC);\r
+ CA_MarkGrChunk(H_BOTTOMINFOPIC);\r
+ CA_CacheMarks ();\r
+ text = textstart;\r
+ return;\r
+ }\r
+ if (ch == 'G') // draw graphic command, so mark graphics\r
+ {\r
+ ParsePicCommand ();\r
+ CA_MarkGrChunk (picnum);\r
+ }\r
+ if (ch == 'T') // timed draw graphic command, so mark graphics\r
+ {\r
+ ParseTimedCommand ();\r
+ CA_MarkGrChunk (picnum);\r
+ }\r
+ }\r
+ else\r
+ text++;\r
+\r
+ } while (text<bombpoint);\r
+\r
+ Quit ("CacheLayoutGraphics: No ^E to terminate file!");\r
+}\r
+#endif\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= ShowArticle\r
+=\r
+=====================\r
+*/\r
+\r
+#ifdef JAPAN\r
+void ShowArticle (int which)\r
+#else\r
+void ShowArticle (char far *article)\r
+#endif\r
+{\r
+ #ifdef JAPAN\r
+ int snames[10] = { H_HELP1PIC,\r
+ H_HELP2PIC,\r
+ H_HELP3PIC,\r
+ H_HELP4PIC,\r
+ H_HELP5PIC,\r
+ H_HELP6PIC,\r
+ H_HELP7PIC,\r
+ H_HELP8PIC,\r
+ H_HELP9PIC,\r
+ H_HELP10PIC};\r
+ int enames[14] = {\r
+ 0,0,\r
+ #ifndef JAPDEMO\r
+ C_ENDGAME1APIC,\r
+ C_ENDGAME1BPIC,\r
+ C_ENDGAME2APIC,\r
+ C_ENDGAME2BPIC,\r
+ C_ENDGAME3APIC,\r
+ C_ENDGAME3BPIC,\r
+ C_ENDGAME4APIC,\r
+ C_ENDGAME4BPIC,\r
+ C_ENDGAME5APIC,\r
+ C_ENDGAME5BPIC,\r
+ C_ENDGAME6APIC,\r
+ C_ENDGAME6BPIC\r
+ #endif\r
+ };\r
+ #endif\r
+ unsigned oldfontnumber;\r
+ unsigned temp;\r
+ boolean newpage,firstpage;\r
+\r
+ #ifdef JAPAN\r
+ pagenum = 1;\r
+ if (!which)\r
+ numpages = 10;\r
+ else\r
+ numpages = 2;\r
+\r
+ #else\r
+\r
+ text = article;\r
+ oldfontnumber = fontnumber;\r
+ fontnumber = 0;\r
+ CA_MarkGrChunk(STARTFONT);\r
+ VWB_Bar (0,0,320,200,BACKCOLOR);\r
+ CacheLayoutGraphics ();\r
+ #endif\r
+\r
+ newpage = true;\r
+ firstpage = true;\r
+\r
+ do\r
+ {\r
+ if (newpage)\r
+ {\r
+ newpage = false;\r
+ #ifdef JAPAN\r
+ if (!which)\r
+ CA_CacheScreen(snames[pagenum - 1]);\r
+ else\r
+ CA_CacheScreen(enames[which*2 + pagenum - 1]);\r
+ #else\r
+ PageLayout (true);\r
+ #endif\r
+ VW_UpdateScreen ();\r
+ if (firstpage)\r
+ {\r
+ VL_FadeIn(0,255,&gamepal,10);\r
+ // VW_FadeIn ()\r
+ firstpage = false;\r
+ }\r
+ }\r
+\r
+ LastScan = 0;\r
+ while (!LastScan)\r
+ ;\r
+\r
+ switch (LastScan)\r
+ {\r
+ case sc_UpArrow:\r
+ case sc_PgUp:\r
+ case sc_LeftArrow:\r
+ if (pagenum>1)\r
+ {\r
+ #ifndef JAPAN\r
+ BackPage ();\r
+ BackPage ();\r
+ #else\r
+ pagenum--;\r
+ #endif\r
+ newpage = true;\r
+ }\r
+ break;\r
+\r
+ case sc_Enter:\r
+ case sc_DownArrow:\r
+ case sc_PgDn:\r
+ case sc_RightArrow: // the text allready points at next page\r
+ if (pagenum<numpages)\r
+ {\r
+ newpage = true;\r
+ #ifdef JAPAN\r
+ pagenum++;\r
+ #endif\r
+ }\r
+ break;\r
+ }\r
+\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+\r
+ } while (LastScan != sc_Escape);\r
+\r
+ IN_ClearKeysDown ();\r
+ fontnumber = oldfontnumber;\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+#ifndef JAPAN\r
+#ifdef ARTSEXTERN\r
+int endextern = T_ENDART1;\r
+#ifndef SPEAR\r
+int helpextern = T_HELPART;\r
+#endif\r
+#endif\r
+char helpfilename[13] = "HELPART.",\r
+ endfilename[13] = "ENDART1.";\r
+#endif\r
+\r
+/*\r
+=================\r
+=\r
+= HelpScreens\r
+=\r
+=================\r
+*/\r
+#ifndef SPEAR\r
+void HelpScreens (void)\r
+{\r
+ int artnum;\r
+ char far *text;\r
+ memptr layout;\r
+\r
+\r
+ CA_UpLevel ();\r
+ MM_SortMem ();\r
+#ifdef JAPAN\r
+ ShowArticle (0);\r
+ VW_FadeOut();\r
+ FreeMusic ();\r
+ CA_DownLevel ();\r
+ MM_SortMem ();\r
+#else\r
+\r
+\r
+\r
+\r
+#ifdef ARTSEXTERN\r
+ artnum = helpextern;\r
+ CA_CacheGrChunk (artnum);\r
+ text = (char _seg *)grsegs[artnum];\r
+ MM_SetLock (&grsegs[artnum], true);\r
+#else\r
+ CA_LoadFile (helpfilename,&layout);\r
+ text = (char _seg *)layout;\r
+ MM_SetLock (&layout, true);\r
+#endif\r
+\r
+ ShowArticle (text);\r
+\r
+#ifdef ARTSEXTERN\r
+ MM_FreePtr (&grsegs[artnum]);\r
+#else\r
+ MM_FreePtr (&layout);\r
+#endif\r
+\r
+\r
+\r
+ VW_FadeOut();\r
+\r
+ FreeMusic ();\r
+ CA_DownLevel ();\r
+ MM_SortMem ();\r
+#endif\r
+}\r
+#endif\r
+\r
+//\r
+// END ARTICLES\r
+//\r
+void EndText (void)\r
+{\r
+ int artnum;\r
+ char far *text;\r
+ memptr layout;\r
+\r
+\r
+ ClearMemory ();\r
+\r
+ CA_UpLevel ();\r
+ MM_SortMem ();\r
+#ifdef JAPAN\r
+ ShowArticle(gamestate.episode + 1);\r
+\r
+ VW_FadeOut();\r
+\r
+ SETFONTCOLOR(0,15);\r
+ IN_ClearKeysDown();\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+\r
+ FreeMusic ();\r
+ CA_DownLevel ();\r
+ MM_SortMem ();\r
+#else\r
+\r
+\r
+\r
+#ifdef ARTSEXTERN\r
+ artnum = endextern+gamestate.episode;\r
+ CA_CacheGrChunk (artnum);\r
+ text = (char _seg *)grsegs[artnum];\r
+ MM_SetLock (&grsegs[artnum], true);\r
+#else\r
+ endfilename[6] = '1'+gamestate.episode;\r
+ CA_LoadFile (endfilename,&layout);\r
+ text = (char _seg *)layout;\r
+ MM_SetLock (&layout, true);\r
+#endif\r
+\r
+ ShowArticle (text);\r
+\r
+#ifdef ARTSEXTERN\r
+ MM_FreePtr (&grsegs[artnum]);\r
+#else\r
+ MM_FreePtr (&layout);\r
+#endif\r
+\r
+\r
+ VW_FadeOut();\r
+ SETFONTCOLOR(0,15);\r
+ IN_ClearKeysDown();\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+\r
+ FreeMusic ();\r
+ CA_DownLevel ();\r
+ MM_SortMem ();\r
+#endif\r
+}\r
-Subproject commit c0db4996e10f27029bfea27519a3d4057a2310f8
+Subproject commit 63a377675e5ba1f2627d1568fe234880eb9da4b2
--- /dev/null
+// WL_ACT1.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+/*\r
+=============================================================================\r
+\r
+ STATICS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+statobj_t statobjlist[MAXSTATS],*laststatobj;\r
+\r
+\r
+struct\r
+{\r
+ int picnum;\r
+ stat_t type;\r
+} statinfo[] =\r
+{\r
+{SPR_STAT_0}, // puddle spr1v\r
+{SPR_STAT_1,block}, // Green Barrel "\r
+{SPR_STAT_2,block}, // Table/chairs "\r
+{SPR_STAT_3,block}, // Floor lamp "\r
+{SPR_STAT_4}, // Chandelier "\r
+{SPR_STAT_5,block}, // Hanged man "\r
+{SPR_STAT_6,bo_alpo}, // Bad food "\r
+{SPR_STAT_7,block}, // Red pillar "\r
+//\r
+// NEW PAGE\r
+//\r
+{SPR_STAT_8,block}, // Tree spr2v\r
+{SPR_STAT_9}, // Skeleton flat "\r
+{SPR_STAT_10,block}, // Sink " (SOD:gibs)\r
+{SPR_STAT_11,block}, // Potted plant "\r
+{SPR_STAT_12,block}, // Urn "\r
+{SPR_STAT_13,block}, // Bare table "\r
+{SPR_STAT_14}, // Ceiling light "\r
+#ifndef SPEAR\r
+{SPR_STAT_15}, // Kitchen stuff "\r
+#else\r
+{SPR_STAT_15,block}, // Gibs!\r
+#endif\r
+//\r
+// NEW PAGE\r
+//\r
+{SPR_STAT_16,block}, // suit of armor spr3v\r
+{SPR_STAT_17,block}, // Hanging cage "\r
+{SPR_STAT_18,block}, // SkeletoninCage "\r
+{SPR_STAT_19}, // Skeleton relax "\r
+{SPR_STAT_20,bo_key1}, // Key 1 "\r
+{SPR_STAT_21,bo_key2}, // Key 2 "\r
+{SPR_STAT_22,block}, // stuff (SOD:gibs)\r
+{SPR_STAT_23}, // stuff\r
+//\r
+// NEW PAGE\r
+//\r
+{SPR_STAT_24,bo_food}, // Good food spr4v\r
+{SPR_STAT_25,bo_firstaid}, // First aid "\r
+{SPR_STAT_26,bo_clip}, // Clip "\r
+{SPR_STAT_27,bo_machinegun}, // Machine gun "\r
+{SPR_STAT_28,bo_chaingun}, // Gatling gun "\r
+{SPR_STAT_29,bo_cross}, // Cross "\r
+{SPR_STAT_30,bo_chalice}, // Chalice "\r
+{SPR_STAT_31,bo_bible}, // Bible "\r
+//\r
+// NEW PAGE\r
+//\r
+{SPR_STAT_32,bo_crown}, // crown spr5v\r
+{SPR_STAT_33,bo_fullheal}, // one up "\r
+{SPR_STAT_34,bo_gibs}, // gibs "\r
+{SPR_STAT_35,block}, // barrel "\r
+{SPR_STAT_36,block}, // well "\r
+{SPR_STAT_37,block}, // Empty well "\r
+{SPR_STAT_38,bo_gibs}, // Gibs 2 "\r
+{SPR_STAT_39,block}, // flag "\r
+//\r
+// NEW PAGE\r
+//\r
+#ifndef SPEAR\r
+{SPR_STAT_40,block}, // Call Apogee spr7v\r
+#else\r
+{SPR_STAT_40}, // Red light\r
+#endif\r
+//\r
+// NEW PAGE\r
+//\r
+{SPR_STAT_41}, // junk "\r
+{SPR_STAT_42}, // junk "\r
+{SPR_STAT_43}, // junk "\r
+#ifndef SPEAR\r
+{SPR_STAT_44}, // pots "\r
+#else\r
+{SPR_STAT_44,block}, // Gibs!\r
+#endif\r
+{SPR_STAT_45,block}, // stove " (SOD:gibs)\r
+{SPR_STAT_46,block}, // spears " (SOD:gibs)\r
+{SPR_STAT_47}, // vines "\r
+//\r
+// NEW PAGE\r
+//\r
+#ifdef SPEAR\r
+{SPR_STAT_48,block}, // marble pillar\r
+{SPR_STAT_49,bo_25clip}, // bonus 25 clip\r
+{SPR_STAT_50,block}, // truck\r
+{SPR_STAT_51,bo_spear}, // SPEAR OF DESTINY!\r
+#endif\r
+\r
+{SPR_STAT_26,bo_clip2}, // Clip "\r
+{-1} // terminator\r
+};\r
+\r
+/*\r
+===============\r
+=\r
+= InitStaticList\r
+=\r
+===============\r
+*/\r
+\r
+void InitStaticList (void)\r
+{\r
+ laststatobj = &statobjlist[0];\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnStatic\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnStatic (int tilex, int tiley, int type)\r
+{\r
+ laststatobj->shapenum = statinfo[type].picnum;\r
+ laststatobj->tilex = tilex;\r
+ laststatobj->tiley = tiley;\r
+ laststatobj->visspot = &spotvis[tilex][tiley];\r
+\r
+ switch (statinfo[type].type)\r
+ {\r
+ case block:\r
+ (unsigned)actorat[tilex][tiley] = 1; // consider it a blocking tile\r
+ case dressing:\r
+ laststatobj->flags = 0;\r
+ break;\r
+\r
+ case bo_cross:\r
+ case bo_chalice:\r
+ case bo_bible:\r
+ case bo_crown:\r
+ case bo_fullheal:\r
+ if (!loadedgame)\r
+ gamestate.treasuretotal++;\r
+\r
+ case bo_firstaid:\r
+ case bo_key1:\r
+ case bo_key2:\r
+ case bo_key3:\r
+ case bo_key4:\r
+ case bo_clip:\r
+ case bo_25clip:\r
+ case bo_machinegun:\r
+ case bo_chaingun:\r
+ case bo_food:\r
+ case bo_alpo:\r
+ case bo_gibs:\r
+ case bo_spear:\r
+ laststatobj->flags = FL_BONUS;\r
+ laststatobj->itemnumber = statinfo[type].type;\r
+ break;\r
+ }\r
+\r
+ laststatobj++;\r
+\r
+ if (laststatobj == &statobjlist[MAXSTATS])\r
+ Quit ("Too many static objects!\n");\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= PlaceItemType\r
+=\r
+= Called during game play to drop actors' items. It finds the proper\r
+= item number based on the item type (bo_???). If there are no free item\r
+= spots, nothing is done.\r
+=\r
+===============\r
+*/\r
+\r
+void PlaceItemType (int itemtype, int tilex, int tiley)\r
+{\r
+ int type;\r
+ statobj_t *spot;\r
+\r
+//\r
+// find the item number\r
+//\r
+ for (type=0 ; ; type++)\r
+ {\r
+ if (statinfo[type].picnum == -1) // end of list\r
+ Quit ("PlaceItemType: couldn't find type!");\r
+ if (statinfo[type].type == itemtype)\r
+ break;\r
+ }\r
+\r
+//\r
+// find a spot in statobjlist to put it in\r
+//\r
+ for (spot=&statobjlist[0] ; ; spot++)\r
+ {\r
+ if (spot==laststatobj)\r
+ {\r
+ if (spot == &statobjlist[MAXSTATS])\r
+ return; // no free spots\r
+ laststatobj++; // space at end\r
+ break;\r
+ }\r
+\r
+ if (spot->shapenum == -1) // -1 is a free spot\r
+ break;\r
+ }\r
+//\r
+// place it\r
+//\r
+ spot->shapenum = statinfo[type].picnum;\r
+ spot->tilex = tilex;\r
+ spot->tiley = tiley;\r
+ spot->visspot = &spotvis[tilex][tiley];\r
+ spot->flags = FL_BONUS;\r
+ spot->itemnumber = statinfo[type].type;\r
+}\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ DOORS\r
+\r
+doorobjlist[] holds most of the information for the doors\r
+\r
+doorposition[] holds the amount the door is open, ranging from 0 to 0xffff\r
+ this is directly accessed by AsmRefresh during rendering\r
+\r
+The number of doors is limited to 64 because a spot in tilemap holds the\r
+ door number in the low 6 bits, with the high bit meaning a door center\r
+ and bit 6 meaning a door side tile\r
+\r
+Open doors conect two areas, so sounds will travel between them and sight\r
+ will be checked when the player is in a connected area.\r
+\r
+Areaconnect is incremented/decremented by each door. If >0 they connect\r
+\r
+Every time a door opens or closes the areabyplayer matrix gets recalculated.\r
+ An area is true if it connects with the player's current spor.\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define DOORWIDTH 0x7800\r
+#define OPENTICS 300\r
+\r
+doorobj_t doorobjlist[MAXDOORS],*lastdoorobj;\r
+int doornum;\r
+\r
+unsigned doorposition[MAXDOORS]; // leading edge of door 0=closed\r
+ // 0xffff = fully open\r
+\r
+byte far areaconnect[NUMAREAS][NUMAREAS];\r
+\r
+boolean areabyplayer[NUMAREAS];\r
+\r
+\r
+/*\r
+==============\r
+=\r
+= ConnectAreas\r
+=\r
+= Scans outward from playerarea, marking all connected areas\r
+=\r
+==============\r
+*/\r
+\r
+void RecursiveConnect (int areanumber)\r
+{\r
+ int i;\r
+\r
+ for (i=0;i<NUMAREAS;i++)\r
+ {\r
+ if (areaconnect[areanumber][i] && !areabyplayer[i])\r
+ {\r
+ areabyplayer[i] = true;\r
+ RecursiveConnect (i);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+void ConnectAreas (void)\r
+{\r
+ memset (areabyplayer,0,sizeof(areabyplayer));\r
+ areabyplayer[player->areanumber] = true;\r
+ RecursiveConnect (player->areanumber);\r
+}\r
+\r
+\r
+void InitAreas (void)\r
+{\r
+ memset (areabyplayer,0,sizeof(areabyplayer));\r
+ areabyplayer[player->areanumber] = true;\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= InitDoorList\r
+=\r
+===============\r
+*/\r
+\r
+void InitDoorList (void)\r
+{\r
+ memset (areabyplayer,0,sizeof(areabyplayer));\r
+ _fmemset (areaconnect,0,sizeof(areaconnect));\r
+\r
+ lastdoorobj = &doorobjlist[0];\r
+ doornum = 0;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnDoor\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnDoor (int tilex, int tiley, boolean vertical, int lock)\r
+{\r
+ int areanumber;\r
+ unsigned far *map;\r
+\r
+ if (doornum==64)\r
+ Quit ("64+ doors on level!");\r
+\r
+ doorposition[doornum] = 0; // doors start out fully closed\r
+ lastdoorobj->tilex = tilex;\r
+ lastdoorobj->tiley = tiley;\r
+ lastdoorobj->vertical = vertical;\r
+ lastdoorobj->lock = lock;\r
+ lastdoorobj->action = dr_closed;\r
+\r
+ (unsigned)actorat[tilex][tiley] = doornum | 0x80; // consider it a solid wall\r
+\r
+//\r
+// make the door tile a special tile, and mark the adjacent tiles\r
+// for door sides\r
+//\r
+ tilemap[tilex][tiley] = doornum | 0x80;\r
+ map = mapsegs[0] + farmapylookup[tiley]+tilex;\r
+ if (vertical)\r
+ {\r
+ *map = *(map-1); // set area number\r
+ tilemap[tilex][tiley-1] |= 0x40;\r
+ tilemap[tilex][tiley+1] |= 0x40;\r
+ }\r
+ else\r
+ {\r
+ *map = *(map-mapwidth); // set area number\r
+ tilemap[tilex-1][tiley] |= 0x40;\r
+ tilemap[tilex+1][tiley] |= 0x40;\r
+ }\r
+\r
+ doornum++;\r
+ lastdoorobj++;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= OpenDoor\r
+=\r
+=====================\r
+*/\r
+\r
+void OpenDoor (int door)\r
+{\r
+ if (doorobjlist[door].action == dr_open)\r
+ doorobjlist[door].ticcount = 0; // reset open time\r
+ else\r
+ doorobjlist[door].action = dr_opening; // start it opening\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CloseDoor\r
+=\r
+=====================\r
+*/\r
+\r
+void CloseDoor (int door)\r
+{\r
+ int tilex,tiley,area;\r
+ objtype *check;\r
+\r
+//\r
+// don't close on anything solid\r
+//\r
+ tilex = doorobjlist[door].tilex;\r
+ tiley = doorobjlist[door].tiley;\r
+\r
+ if (actorat[tilex][tiley])\r
+ return;\r
+\r
+ if (player->tilex == tilex && player->tiley == tiley)\r
+ return;\r
+\r
+ if (doorobjlist[door].vertical)\r
+ {\r
+ if ( player->tiley == tiley )\r
+ {\r
+ if ( ((player->x+MINDIST) >>TILESHIFT) == tilex )\r
+ return;\r
+ if ( ((player->x-MINDIST) >>TILESHIFT) == tilex )\r
+ return;\r
+ }\r
+ check = actorat[tilex-1][tiley];\r
+ if (check && ((check->x+MINDIST) >> TILESHIFT) == tilex )\r
+ return;\r
+ check = actorat[tilex+1][tiley];\r
+ if (check && ((check->x-MINDIST) >> TILESHIFT) == tilex )\r
+ return;\r
+ }\r
+ else if (!doorobjlist[door].vertical)\r
+ {\r
+ if (player->tilex == tilex)\r
+ {\r
+ if ( ((player->y+MINDIST) >>TILESHIFT) == tiley )\r
+ return;\r
+ if ( ((player->y-MINDIST) >>TILESHIFT) == tiley )\r
+ return;\r
+ }\r
+ check = actorat[tilex][tiley-1];\r
+ if (check && ((check->y+MINDIST) >> TILESHIFT) == tiley )\r
+ return;\r
+ check = actorat[tilex][tiley+1];\r
+ if (check && ((check->y-MINDIST) >> TILESHIFT) == tiley )\r
+ return;\r
+ }\r
+\r
+\r
+//\r
+// play door sound if in a connected area\r
+//\r
+ area = *(mapsegs[0] + farmapylookup[doorobjlist[door].tiley]\r
+ +doorobjlist[door].tilex)-AREATILE;\r
+ if (areabyplayer[area])\r
+ {\r
+ PlaySoundLocTile(CLOSEDOORSND,doorobjlist[door].tilex,doorobjlist[door].tiley); // JAB\r
+ }\r
+\r
+ doorobjlist[door].action = dr_closing;\r
+//\r
+// make the door space solid\r
+//\r
+ (unsigned)actorat[tilex][tiley]\r
+ = door | 0x80;\r
+}\r
+\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= OperateDoor\r
+=\r
+= The player wants to change the door's direction\r
+=\r
+=====================\r
+*/\r
+\r
+void OperateDoor (int door)\r
+{\r
+ int lock;\r
+\r
+ lock = doorobjlist[door].lock;\r
+ if (lock >= dr_lock1 && lock <= dr_lock4)\r
+ {\r
+ if ( ! (gamestate.keys & (1 << (lock-dr_lock1) ) ) )\r
+ {\r
+ SD_PlaySound (NOWAYSND); // locked\r
+ return;\r
+ }\r
+ }\r
+\r
+ switch (doorobjlist[door].action)\r
+ {\r
+ case dr_closed:\r
+ case dr_closing:\r
+ OpenDoor (door);\r
+ break;\r
+ case dr_open:\r
+ case dr_opening:\r
+ CloseDoor (door);\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===============\r
+=\r
+= DoorOpen\r
+=\r
+= Close the door after three seconds\r
+=\r
+===============\r
+*/\r
+\r
+void DoorOpen (int door)\r
+{\r
+ if ( (doorobjlist[door].ticcount += tics) >= OPENTICS)\r
+ CloseDoor (door);\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= DoorOpening\r
+=\r
+===============\r
+*/\r
+\r
+void DoorOpening (int door)\r
+{\r
+ int area1,area2;\r
+ unsigned far *map;\r
+ long position;\r
+\r
+ position = doorposition[door];\r
+ if (!position)\r
+ {\r
+ //\r
+ // door is just starting to open, so connect the areas\r
+ //\r
+ map = mapsegs[0] + farmapylookup[doorobjlist[door].tiley]\r
+ +doorobjlist[door].tilex;\r
+\r
+ if (doorobjlist[door].vertical)\r
+ {\r
+ area1 = *(map+1);\r
+ area2 = *(map-1);\r
+ }\r
+ else\r
+ {\r
+ area1 = *(map-mapwidth);\r
+ area2 = *(map+mapwidth);\r
+ }\r
+ area1 -= AREATILE;\r
+ area2 -= AREATILE;\r
+ areaconnect[area1][area2]++;\r
+ areaconnect[area2][area1]++;\r
+ ConnectAreas ();\r
+ if (areabyplayer[area1])\r
+ {\r
+ PlaySoundLocTile(OPENDOORSND,doorobjlist[door].tilex,doorobjlist[door].tiley); // JAB\r
+ }\r
+ }\r
+\r
+//\r
+// slide the door by an adaptive amount\r
+//\r
+ position += tics<<10;\r
+ if (position >= 0xffff)\r
+ {\r
+ //\r
+ // door is all the way open\r
+ //\r
+ position = 0xffff;\r
+ doorobjlist[door].ticcount = 0;\r
+ doorobjlist[door].action = dr_open;\r
+ actorat[doorobjlist[door].tilex][doorobjlist[door].tiley] = 0;\r
+ }\r
+\r
+ doorposition[door] = position;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= DoorClosing\r
+=\r
+===============\r
+*/\r
+\r
+void DoorClosing (int door)\r
+{\r
+ int area1,area2,move;\r
+ unsigned far *map;\r
+ long position;\r
+ int tilex,tiley;\r
+\r
+ tilex = doorobjlist[door].tilex;\r
+ tiley = doorobjlist[door].tiley;\r
+\r
+ if ( ((unsigned)actorat[tilex][tiley] != (door | 0x80))\r
+ || (player->tilex == tilex && player->tiley == tiley) )\r
+ { // something got inside the door\r
+ OpenDoor (door);\r
+ return;\r
+ };\r
+\r
+ position = doorposition[door];\r
+\r
+//\r
+// slide the door by an adaptive amount\r
+//\r
+ position -= tics<<10;\r
+ if (position <= 0)\r
+ {\r
+ //\r
+ // door is closed all the way, so disconnect the areas\r
+ //\r
+ position = 0;\r
+\r
+ doorobjlist[door].action = dr_closed;\r
+\r
+ map = mapsegs[0] + farmapylookup[doorobjlist[door].tiley]\r
+ +doorobjlist[door].tilex;\r
+\r
+ if (doorobjlist[door].vertical)\r
+ {\r
+ area1 = *(map+1);\r
+ area2 = *(map-1);\r
+ }\r
+ else\r
+ {\r
+ area1 = *(map-mapwidth);\r
+ area2 = *(map+mapwidth);\r
+ }\r
+ area1 -= AREATILE;\r
+ area2 -= AREATILE;\r
+ areaconnect[area1][area2]--;\r
+ areaconnect[area2][area1]--;\r
+\r
+ ConnectAreas ();\r
+ }\r
+\r
+ doorposition[door] = position;\r
+}\r
+\r
+\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= MoveDoors\r
+=\r
+= Called from PlayLoop\r
+=\r
+=====================\r
+*/\r
+\r
+void MoveDoors (void)\r
+{\r
+ int door;\r
+\r
+ if (gamestate.victoryflag) // don't move door during victory sequence\r
+ return;\r
+\r
+ for (door = 0 ; door < doornum ; door++)\r
+ switch (doorobjlist[door].action)\r
+ {\r
+ case dr_open:\r
+ DoorOpen (door);\r
+ break;\r
+\r
+ case dr_opening:\r
+ DoorOpening(door);\r
+ break;\r
+\r
+ case dr_closing:\r
+ DoorClosing(door);\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ PUSHABLE WALLS\r
+\r
+=============================================================================\r
+*/\r
+\r
+unsigned pwallstate;\r
+unsigned pwallpos; // amount a pushable wall has been moved (0-63)\r
+unsigned pwallx,pwally;\r
+int pwalldir;\r
+\r
+/*\r
+===============\r
+=\r
+= PushWall\r
+=\r
+===============\r
+*/\r
+\r
+void PushWall (int checkx, int checky, int dir)\r
+{\r
+ int oldtile;\r
+\r
+ if (pwallstate)\r
+ return;\r
+\r
+\r
+ oldtile = tilemap[checkx][checky];\r
+ if (!oldtile)\r
+ return;\r
+\r
+ switch (dir)\r
+ {\r
+ case di_north:\r
+ if (actorat[checkx][checky-1])\r
+ {\r
+ SD_PlaySound (NOWAYSND);\r
+ return;\r
+ }\r
+ (unsigned)actorat[checkx][checky-1] =\r
+ tilemap[checkx][checky-1] = oldtile;\r
+ break;\r
+\r
+ case di_east:\r
+ if (actorat[checkx+1][checky])\r
+ {\r
+ SD_PlaySound (NOWAYSND);\r
+ return;\r
+ }\r
+ (unsigned)actorat[checkx+1][checky] =\r
+ tilemap[checkx+1][checky] = oldtile;\r
+ break;\r
+\r
+ case di_south:\r
+ if (actorat[checkx][checky+1])\r
+ {\r
+ SD_PlaySound (NOWAYSND);\r
+ return;\r
+ }\r
+ (unsigned)actorat[checkx][checky+1] =\r
+ tilemap[checkx][checky+1] = oldtile;\r
+ break;\r
+\r
+ case di_west:\r
+ if (actorat[checkx-1][checky])\r
+ {\r
+ SD_PlaySound (NOWAYSND);\r
+ return;\r
+ }\r
+ (unsigned)actorat[checkx-1][checky] =\r
+ tilemap[checkx-1][checky] = oldtile;\r
+ break;\r
+ }\r
+\r
+ gamestate.secretcount++;\r
+ pwallx = checkx;\r
+ pwally = checky;\r
+ pwalldir = dir;\r
+ pwallstate = 1;\r
+ pwallpos = 0;\r
+ tilemap[pwallx][pwally] |= 0xc0;\r
+ *(mapsegs[1]+farmapylookup[pwally]+pwallx) = 0; // remove P tile info\r
+\r
+ SD_PlaySound (PUSHWALLSND);\r
+}\r
+\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= MovePWalls\r
+=\r
+=================\r
+*/\r
+\r
+void MovePWalls (void)\r
+{\r
+ int oldblock,oldtile;\r
+\r
+ if (!pwallstate)\r
+ return;\r
+\r
+ oldblock = pwallstate/128;\r
+\r
+ pwallstate += tics;\r
+\r
+ if (pwallstate/128 != oldblock)\r
+ {\r
+ // block crossed into a new block\r
+ oldtile = tilemap[pwallx][pwally] & 63;\r
+\r
+ //\r
+ // the tile can now be walked into\r
+ //\r
+ tilemap[pwallx][pwally] = 0;\r
+ (unsigned)actorat[pwallx][pwally] = 0;\r
+ *(mapsegs[0]+farmapylookup[pwally]+pwallx) = player->areanumber+AREATILE;\r
+\r
+ //\r
+ // see if it should be pushed farther\r
+ //\r
+ if (pwallstate>256)\r
+ {\r
+ //\r
+ // the block has been pushed two tiles\r
+ //\r
+ pwallstate = 0;\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ switch (pwalldir)\r
+ {\r
+ case di_north:\r
+ pwally--;\r
+ if (actorat[pwallx][pwally-1])\r
+ {\r
+ pwallstate = 0;\r
+ return;\r
+ }\r
+ (unsigned)actorat[pwallx][pwally-1] =\r
+ tilemap[pwallx][pwally-1] = oldtile;\r
+ break;\r
+\r
+ case di_east:\r
+ pwallx++;\r
+ if (actorat[pwallx+1][pwally])\r
+ {\r
+ pwallstate = 0;\r
+ return;\r
+ }\r
+ (unsigned)actorat[pwallx+1][pwally] =\r
+ tilemap[pwallx+1][pwally] = oldtile;\r
+ break;\r
+\r
+ case di_south:\r
+ pwally++;\r
+ if (actorat[pwallx][pwally+1])\r
+ {\r
+ pwallstate = 0;\r
+ return;\r
+ }\r
+ (unsigned)actorat[pwallx][pwally+1] =\r
+ tilemap[pwallx][pwally+1] = oldtile;\r
+ break;\r
+\r
+ case di_west:\r
+ pwallx--;\r
+ if (actorat[pwallx-1][pwally])\r
+ {\r
+ pwallstate = 0;\r
+ return;\r
+ }\r
+ (unsigned)actorat[pwallx-1][pwally] =\r
+ tilemap[pwallx-1][pwally] = oldtile;\r
+ break;\r
+ }\r
+\r
+ tilemap[pwallx][pwally] = oldtile | 0xc0;\r
+ }\r
+ }\r
+\r
+\r
+ pwallpos = (pwallstate/2)&63;\r
+\r
+}\r
+\r
--- /dev/null
+// WL_ACT2.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define PROJECTILESIZE 0xc000l\r
+\r
+#define BJRUNSPEED 2048\r
+#define BJJUMPSPEED 680\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+dirtype dirtable[9] = {northwest,north,northeast,west,nodir,east,\r
+ southwest,south,southeast};\r
+\r
+int starthitpoints[4][NUMENEMIES] =\r
+ //\r
+ // BABY MODE\r
+ //\r
+ {\r
+ {25, // guards\r
+ 50, // officer\r
+ 100, // SS\r
+ 1, // dogs\r
+ 850, // Hans\r
+ 850, // Schabbs\r
+ 200, // fake hitler\r
+ 800, // mecha hitler\r
+ 45, // mutants\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+\r
+ 850, // Gretel\r
+ 850, // Gift\r
+ 850, // Fat\r
+ 5, // en_spectre,\r
+ 1450, // en_angel,\r
+ 850, // en_trans,\r
+ 1050, // en_uber,\r
+ 950, // en_will,\r
+ 1250 // en_death\r
+ },\r
+ //\r
+ // DON'T HURT ME MODE\r
+ //\r
+ {25, // guards\r
+ 50, // officer\r
+ 100, // SS\r
+ 1, // dogs\r
+ 950, // Hans\r
+ 950, // Schabbs\r
+ 300, // fake hitler\r
+ 950, // mecha hitler\r
+ 55, // mutants\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+\r
+ 950, // Gretel\r
+ 950, // Gift\r
+ 950, // Fat\r
+ 10, // en_spectre,\r
+ 1550, // en_angel,\r
+ 950, // en_trans,\r
+ 1150, // en_uber,\r
+ 1050, // en_will,\r
+ 1350 // en_death\r
+ },\r
+ //\r
+ // BRING 'EM ON MODE\r
+ //\r
+ {25, // guards\r
+ 50, // officer\r
+ 100, // SS\r
+ 1, // dogs\r
+\r
+ 1050, // Hans\r
+ 1550, // Schabbs\r
+ 400, // fake hitler\r
+ 1050, // mecha hitler\r
+\r
+ 55, // mutants\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+\r
+ 1050, // Gretel\r
+ 1050, // Gift\r
+ 1050, // Fat\r
+ 15, // en_spectre,\r
+ 1650, // en_angel,\r
+ 1050, // en_trans,\r
+ 1250, // en_uber,\r
+ 1150, // en_will,\r
+ 1450 // en_death\r
+ },\r
+ //\r
+ // DEATH INCARNATE MODE\r
+ //\r
+ {25, // guards\r
+ 50, // officer\r
+ 100, // SS\r
+ 1, // dogs\r
+\r
+ 1200, // Hans\r
+ 2400, // Schabbs\r
+ 500, // fake hitler\r
+ 1200, // mecha hitler\r
+\r
+ 65, // mutants\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+ 25, // ghosts\r
+\r
+ 1200, // Gretel\r
+ 1200, // Gift\r
+ 1200, // Fat\r
+ 25, // en_spectre,\r
+ 2000, // en_angel,\r
+ 1200, // en_trans,\r
+ 1400, // en_uber,\r
+ 1300, // en_will,\r
+ 1600 // en_death\r
+ }}\r
+ ;\r
+\r
+void A_StartDeathCam (objtype *ob);\r
+\r
+\r
+void T_Path (objtype *ob);\r
+void T_Shoot (objtype *ob);\r
+void T_Bite (objtype *ob);\r
+void T_DogChase (objtype *ob);\r
+void T_Chase (objtype *ob);\r
+void T_Projectile (objtype *ob);\r
+void T_Stand (objtype *ob);\r
+\r
+void A_DeathScream (objtype *ob);\r
+\r
+extern statetype s_rocket;\r
+extern statetype s_smoke1;\r
+extern statetype s_smoke2;\r
+extern statetype s_smoke3;\r
+extern statetype s_smoke4;\r
+extern statetype s_boom2;\r
+extern statetype s_boom3;\r
+\r
+void A_Smoke (objtype *ob);\r
+\r
+statetype s_rocket = {true,SPR_ROCKET_1,3,T_Projectile,A_Smoke,&s_rocket};\r
+statetype s_smoke1 = {false,SPR_SMOKE_1,3,NULL,NULL,&s_smoke2};\r
+statetype s_smoke2 = {false,SPR_SMOKE_2,3,NULL,NULL,&s_smoke3};\r
+statetype s_smoke3 = {false,SPR_SMOKE_3,3,NULL,NULL,&s_smoke4};\r
+statetype s_smoke4 = {false,SPR_SMOKE_4,3,NULL,NULL,NULL};\r
+\r
+statetype s_boom1 = {false,SPR_BOOM_1,6,NULL,NULL,&s_boom2};\r
+statetype s_boom2 = {false,SPR_BOOM_2,6,NULL,NULL,&s_boom3};\r
+statetype s_boom3 = {false,SPR_BOOM_3,6,NULL,NULL,NULL};\r
+\r
+#ifdef SPEAR\r
+\r
+extern statetype s_hrocket;\r
+extern statetype s_hsmoke1;\r
+extern statetype s_hsmoke2;\r
+extern statetype s_hsmoke3;\r
+extern statetype s_hsmoke4;\r
+extern statetype s_hboom2;\r
+extern statetype s_hboom3;\r
+\r
+void A_Smoke (objtype *ob);\r
+\r
+statetype s_hrocket = {true,SPR_HROCKET_1,3,T_Projectile,A_Smoke,&s_hrocket};\r
+statetype s_hsmoke1 = {false,SPR_HSMOKE_1,3,NULL,NULL,&s_hsmoke2};\r
+statetype s_hsmoke2 = {false,SPR_HSMOKE_2,3,NULL,NULL,&s_hsmoke3};\r
+statetype s_hsmoke3 = {false,SPR_HSMOKE_3,3,NULL,NULL,&s_hsmoke4};\r
+statetype s_hsmoke4 = {false,SPR_HSMOKE_4,3,NULL,NULL,NULL};\r
+\r
+statetype s_hboom1 = {false,SPR_HBOOM_1,6,NULL,NULL,&s_hboom2};\r
+statetype s_hboom2 = {false,SPR_HBOOM_2,6,NULL,NULL,&s_hboom3};\r
+statetype s_hboom3 = {false,SPR_HBOOM_3,6,NULL,NULL,NULL};\r
+\r
+#endif\r
+\r
+void T_Schabb (objtype *ob);\r
+void T_SchabbThrow (objtype *ob);\r
+void T_Fake (objtype *ob);\r
+void T_FakeFire (objtype *ob);\r
+void T_Ghosts (objtype *ob);\r
+\r
+void A_Slurpie (objtype *ob);\r
+void A_HitlerMorph (objtype *ob);\r
+void A_MechaSound (objtype *ob);\r
+\r
+/*\r
+=================\r
+=\r
+= A_Smoke\r
+=\r
+=================\r
+*/\r
+\r
+void A_Smoke (objtype *ob)\r
+{\r
+ GetNewActor ();\r
+#ifdef SPEAR\r
+ if (ob->obclass == hrocketobj)\r
+ new->state = &s_hsmoke1;\r
+ else\r
+#endif\r
+ new->state = &s_smoke1;\r
+ new->ticcount = 6;\r
+\r
+ new->tilex = ob->tilex;\r
+ new->tiley = ob->tiley;\r
+ new->x = ob->x;\r
+ new->y = ob->y;\r
+ new->obclass = inertobj;\r
+ new->active = true;\r
+\r
+ new->flags = FL_NEVERMARK;\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= ProjectileTryMove\r
+=\r
+= returns true if move ok\r
+===================\r
+*/\r
+\r
+#define PROJSIZE 0x2000\r
+\r
+boolean ProjectileTryMove (objtype *ob)\r
+{\r
+ int xl,yl,xh,yh,x,y;\r
+ objtype *check;\r
+ long deltax,deltay;\r
+\r
+ xl = (ob->x-PROJSIZE) >>TILESHIFT;\r
+ yl = (ob->y-PROJSIZE) >>TILESHIFT;\r
+\r
+ xh = (ob->x+PROJSIZE) >>TILESHIFT;\r
+ yh = (ob->y+PROJSIZE) >>TILESHIFT;\r
+\r
+//\r
+// check for solid walls\r
+//\r
+ for (y=yl;y<=yh;y++)\r
+ for (x=xl;x<=xh;x++)\r
+ {\r
+ check = actorat[x][y];\r
+ if (check && check<objlist)\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_Projectile\r
+=\r
+=================\r
+*/\r
+\r
+void T_Projectile (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+ int damage;\r
+ long speed;\r
+\r
+ speed = (long)ob->speed*tics;\r
+\r
+ deltax = FixedByFrac(speed,costable[ob->angle]);\r
+ deltay = -FixedByFrac(speed,sintable[ob->angle]);\r
+\r
+ if (deltax>0x10000l)\r
+ deltax = 0x10000l;\r
+ if (deltay>0x10000l)\r
+ deltay = 0x10000l;\r
+\r
+ ob->x += deltax;\r
+ ob->y += deltay;\r
+\r
+ deltax = LABS(ob->x - player->x);\r
+ deltay = LABS(ob->y - player->y);\r
+\r
+ if (!ProjectileTryMove (ob))\r
+ {\r
+ if (ob->obclass == rocketobj)\r
+ {\r
+ PlaySoundLocActor(MISSILEHITSND,ob);\r
+ ob->state = &s_boom1;\r
+ }\r
+#ifdef SPEAR\r
+ else if (ob->obclass == hrocketobj)\r
+ {\r
+ PlaySoundLocActor(MISSILEHITSND,ob);\r
+ ob->state = &s_hboom1;\r
+ }\r
+#endif\r
+ else\r
+ ob->state = NULL; // mark for removal\r
+\r
+ return;\r
+ }\r
+\r
+ if (deltax < PROJECTILESIZE && deltay < PROJECTILESIZE)\r
+ { // hit the player\r
+ switch (ob->obclass)\r
+ {\r
+ case needleobj:\r
+ damage = (US_RndT() >>3) + 20;\r
+ break;\r
+ case rocketobj:\r
+ case hrocketobj:\r
+ case sparkobj:\r
+ damage = (US_RndT() >>3) + 30;\r
+ break;\r
+ case fireobj:\r
+ damage = (US_RndT() >>3);\r
+ break;\r
+ }\r
+\r
+ TakeDamage (damage,ob);\r
+ ob->state = NULL; // mark for removal\r
+ return;\r
+ }\r
+\r
+ ob->tilex = ob->x >> TILESHIFT;\r
+ ob->tiley = ob->y >> TILESHIFT;\r
+\r
+}\r
+\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GUARD\r
+\r
+=============================================================================\r
+*/\r
+\r
+//\r
+// guards\r
+//\r
+\r
+extern statetype s_grdstand;\r
+\r
+extern statetype s_grdpath1;\r
+extern statetype s_grdpath1s;\r
+extern statetype s_grdpath2;\r
+extern statetype s_grdpath3;\r
+extern statetype s_grdpath3s;\r
+extern statetype s_grdpath4;\r
+\r
+extern statetype s_grdpain;\r
+extern statetype s_grdpain1;\r
+\r
+extern statetype s_grdgiveup;\r
+\r
+extern statetype s_grdshoot1;\r
+extern statetype s_grdshoot2;\r
+extern statetype s_grdshoot3;\r
+extern statetype s_grdshoot4;\r
+\r
+extern statetype s_grdchase1;\r
+extern statetype s_grdchase1s;\r
+extern statetype s_grdchase2;\r
+extern statetype s_grdchase3;\r
+extern statetype s_grdchase3s;\r
+extern statetype s_grdchase4;\r
+\r
+extern statetype s_grddie1;\r
+extern statetype s_grddie1d;\r
+extern statetype s_grddie2;\r
+extern statetype s_grddie3;\r
+extern statetype s_grddie4;\r
+\r
+statetype s_grdstand = {true,SPR_GRD_S_1,0,T_Stand,NULL,&s_grdstand};\r
+\r
+statetype s_grdpath1 = {true,SPR_GRD_W1_1,20,T_Path,NULL,&s_grdpath1s};\r
+statetype s_grdpath1s = {true,SPR_GRD_W1_1,5,NULL,NULL,&s_grdpath2};\r
+statetype s_grdpath2 = {true,SPR_GRD_W2_1,15,T_Path,NULL,&s_grdpath3};\r
+statetype s_grdpath3 = {true,SPR_GRD_W3_1,20,T_Path,NULL,&s_grdpath3s};\r
+statetype s_grdpath3s = {true,SPR_GRD_W3_1,5,NULL,NULL,&s_grdpath4};\r
+statetype s_grdpath4 = {true,SPR_GRD_W4_1,15,T_Path,NULL,&s_grdpath1};\r
+\r
+statetype s_grdpain = {2,SPR_GRD_PAIN_1,10,NULL,NULL,&s_grdchase1};\r
+statetype s_grdpain1 = {2,SPR_GRD_PAIN_2,10,NULL,NULL,&s_grdchase1};\r
+\r
+statetype s_grdshoot1 = {false,SPR_GRD_SHOOT1,20,NULL,NULL,&s_grdshoot2};\r
+statetype s_grdshoot2 = {false,SPR_GRD_SHOOT2,20,NULL,T_Shoot,&s_grdshoot3};\r
+statetype s_grdshoot3 = {false,SPR_GRD_SHOOT3,20,NULL,NULL,&s_grdchase1};\r
+\r
+statetype s_grdchase1 = {true,SPR_GRD_W1_1,10,T_Chase,NULL,&s_grdchase1s};\r
+statetype s_grdchase1s = {true,SPR_GRD_W1_1,3,NULL,NULL,&s_grdchase2};\r
+statetype s_grdchase2 = {true,SPR_GRD_W2_1,8,T_Chase,NULL,&s_grdchase3};\r
+statetype s_grdchase3 = {true,SPR_GRD_W3_1,10,T_Chase,NULL,&s_grdchase3s};\r
+statetype s_grdchase3s = {true,SPR_GRD_W3_1,3,NULL,NULL,&s_grdchase4};\r
+statetype s_grdchase4 = {true,SPR_GRD_W4_1,8,T_Chase,NULL,&s_grdchase1};\r
+\r
+statetype s_grddie1 = {false,SPR_GRD_DIE_1,15,NULL,A_DeathScream,&s_grddie2};\r
+statetype s_grddie2 = {false,SPR_GRD_DIE_2,15,NULL,NULL,&s_grddie3};\r
+statetype s_grddie3 = {false,SPR_GRD_DIE_3,15,NULL,NULL,&s_grddie4};\r
+statetype s_grddie4 = {false,SPR_GRD_DEAD,0,NULL,NULL,&s_grddie4};\r
+\r
+\r
+#ifndef SPEAR\r
+//\r
+// ghosts\r
+//\r
+extern statetype s_blinkychase1;\r
+extern statetype s_blinkychase2;\r
+extern statetype s_inkychase1;\r
+extern statetype s_inkychase2;\r
+extern statetype s_pinkychase1;\r
+extern statetype s_pinkychase2;\r
+extern statetype s_clydechase1;\r
+extern statetype s_clydechase2;\r
+\r
+statetype s_blinkychase1 = {false,SPR_BLINKY_W1,10,T_Ghosts,NULL,&s_blinkychase2};\r
+statetype s_blinkychase2 = {false,SPR_BLINKY_W2,10,T_Ghosts,NULL,&s_blinkychase1};\r
+\r
+statetype s_inkychase1 = {false,SPR_INKY_W1,10,T_Ghosts,NULL,&s_inkychase2};\r
+statetype s_inkychase2 = {false,SPR_INKY_W2,10,T_Ghosts,NULL,&s_inkychase1};\r
+\r
+statetype s_pinkychase1 = {false,SPR_PINKY_W1,10,T_Ghosts,NULL,&s_pinkychase2};\r
+statetype s_pinkychase2 = {false,SPR_PINKY_W2,10,T_Ghosts,NULL,&s_pinkychase1};\r
+\r
+statetype s_clydechase1 = {false,SPR_CLYDE_W1,10,T_Ghosts,NULL,&s_clydechase2};\r
+statetype s_clydechase2 = {false,SPR_CLYDE_W2,10,T_Ghosts,NULL,&s_clydechase1};\r
+#endif\r
+\r
+//\r
+// dogs\r
+//\r
+\r
+extern statetype s_dogpath1;\r
+extern statetype s_dogpath1s;\r
+extern statetype s_dogpath2;\r
+extern statetype s_dogpath3;\r
+extern statetype s_dogpath3s;\r
+extern statetype s_dogpath4;\r
+\r
+extern statetype s_dogjump1;\r
+extern statetype s_dogjump2;\r
+extern statetype s_dogjump3;\r
+extern statetype s_dogjump4;\r
+extern statetype s_dogjump5;\r
+\r
+extern statetype s_dogchase1;\r
+extern statetype s_dogchase1s;\r
+extern statetype s_dogchase2;\r
+extern statetype s_dogchase3;\r
+extern statetype s_dogchase3s;\r
+extern statetype s_dogchase4;\r
+\r
+extern statetype s_dogdie1;\r
+extern statetype s_dogdie1d;\r
+extern statetype s_dogdie2;\r
+extern statetype s_dogdie3;\r
+extern statetype s_dogdead;\r
+\r
+statetype s_dogpath1 = {true,SPR_DOG_W1_1,20,T_Path,NULL,&s_dogpath1s};\r
+statetype s_dogpath1s = {true,SPR_DOG_W1_1,5,NULL,NULL,&s_dogpath2};\r
+statetype s_dogpath2 = {true,SPR_DOG_W2_1,15,T_Path,NULL,&s_dogpath3};\r
+statetype s_dogpath3 = {true,SPR_DOG_W3_1,20,T_Path,NULL,&s_dogpath3s};\r
+statetype s_dogpath3s = {true,SPR_DOG_W3_1,5,NULL,NULL,&s_dogpath4};\r
+statetype s_dogpath4 = {true,SPR_DOG_W4_1,15,T_Path,NULL,&s_dogpath1};\r
+\r
+statetype s_dogjump1 = {false,SPR_DOG_JUMP1,10,NULL,NULL,&s_dogjump2};\r
+statetype s_dogjump2 = {false,SPR_DOG_JUMP2,10,NULL,T_Bite,&s_dogjump3};\r
+statetype s_dogjump3 = {false,SPR_DOG_JUMP3,10,NULL,NULL,&s_dogjump4};\r
+statetype s_dogjump4 = {false,SPR_DOG_JUMP1,10,NULL,NULL,&s_dogjump5};\r
+statetype s_dogjump5 = {false,SPR_DOG_W1_1,10,NULL,NULL,&s_dogchase1};\r
+\r
+statetype s_dogchase1 = {true,SPR_DOG_W1_1,10,T_DogChase,NULL,&s_dogchase1s};\r
+statetype s_dogchase1s = {true,SPR_DOG_W1_1,3,NULL,NULL,&s_dogchase2};\r
+statetype s_dogchase2 = {true,SPR_DOG_W2_1,8,T_DogChase,NULL,&s_dogchase3};\r
+statetype s_dogchase3 = {true,SPR_DOG_W3_1,10,T_DogChase,NULL,&s_dogchase3s};\r
+statetype s_dogchase3s = {true,SPR_DOG_W3_1,3,NULL,NULL,&s_dogchase4};\r
+statetype s_dogchase4 = {true,SPR_DOG_W4_1,8,T_DogChase,NULL,&s_dogchase1};\r
+\r
+statetype s_dogdie1 = {false,SPR_DOG_DIE_1,15,NULL,A_DeathScream,&s_dogdie2};\r
+statetype s_dogdie2 = {false,SPR_DOG_DIE_2,15,NULL,NULL,&s_dogdie3};\r
+statetype s_dogdie3 = {false,SPR_DOG_DIE_3,15,NULL,NULL,&s_dogdead};\r
+statetype s_dogdead = {false,SPR_DOG_DEAD,15,NULL,NULL,&s_dogdead};\r
+\r
+\r
+//\r
+// officers\r
+//\r
+\r
+extern statetype s_ofcstand;\r
+\r
+extern statetype s_ofcpath1;\r
+extern statetype s_ofcpath1s;\r
+extern statetype s_ofcpath2;\r
+extern statetype s_ofcpath3;\r
+extern statetype s_ofcpath3s;\r
+extern statetype s_ofcpath4;\r
+\r
+extern statetype s_ofcpain;\r
+extern statetype s_ofcpain1;\r
+\r
+extern statetype s_ofcgiveup;\r
+\r
+extern statetype s_ofcshoot1;\r
+extern statetype s_ofcshoot2;\r
+extern statetype s_ofcshoot3;\r
+extern statetype s_ofcshoot4;\r
+\r
+extern statetype s_ofcchase1;\r
+extern statetype s_ofcchase1s;\r
+extern statetype s_ofcchase2;\r
+extern statetype s_ofcchase3;\r
+extern statetype s_ofcchase3s;\r
+extern statetype s_ofcchase4;\r
+\r
+extern statetype s_ofcdie1;\r
+extern statetype s_ofcdie2;\r
+extern statetype s_ofcdie3;\r
+extern statetype s_ofcdie4;\r
+extern statetype s_ofcdie5;\r
+\r
+statetype s_ofcstand = {true,SPR_OFC_S_1,0,T_Stand,NULL,&s_ofcstand};\r
+\r
+statetype s_ofcpath1 = {true,SPR_OFC_W1_1,20,T_Path,NULL,&s_ofcpath1s};\r
+statetype s_ofcpath1s = {true,SPR_OFC_W1_1,5,NULL,NULL,&s_ofcpath2};\r
+statetype s_ofcpath2 = {true,SPR_OFC_W2_1,15,T_Path,NULL,&s_ofcpath3};\r
+statetype s_ofcpath3 = {true,SPR_OFC_W3_1,20,T_Path,NULL,&s_ofcpath3s};\r
+statetype s_ofcpath3s = {true,SPR_OFC_W3_1,5,NULL,NULL,&s_ofcpath4};\r
+statetype s_ofcpath4 = {true,SPR_OFC_W4_1,15,T_Path,NULL,&s_ofcpath1};\r
+\r
+statetype s_ofcpain = {2,SPR_OFC_PAIN_1,10,NULL,NULL,&s_ofcchase1};\r
+statetype s_ofcpain1 = {2,SPR_OFC_PAIN_2,10,NULL,NULL,&s_ofcchase1};\r
+\r
+statetype s_ofcshoot1 = {false,SPR_OFC_SHOOT1,6,NULL,NULL,&s_ofcshoot2};\r
+statetype s_ofcshoot2 = {false,SPR_OFC_SHOOT2,20,NULL,T_Shoot,&s_ofcshoot3};\r
+statetype s_ofcshoot3 = {false,SPR_OFC_SHOOT3,10,NULL,NULL,&s_ofcchase1};\r
+\r
+statetype s_ofcchase1 = {true,SPR_OFC_W1_1,10,T_Chase,NULL,&s_ofcchase1s};\r
+statetype s_ofcchase1s = {true,SPR_OFC_W1_1,3,NULL,NULL,&s_ofcchase2};\r
+statetype s_ofcchase2 = {true,SPR_OFC_W2_1,8,T_Chase,NULL,&s_ofcchase3};\r
+statetype s_ofcchase3 = {true,SPR_OFC_W3_1,10,T_Chase,NULL,&s_ofcchase3s};\r
+statetype s_ofcchase3s = {true,SPR_OFC_W3_1,3,NULL,NULL,&s_ofcchase4};\r
+statetype s_ofcchase4 = {true,SPR_OFC_W4_1,8,T_Chase,NULL,&s_ofcchase1};\r
+\r
+statetype s_ofcdie1 = {false,SPR_OFC_DIE_1,11,NULL,A_DeathScream,&s_ofcdie2};\r
+statetype s_ofcdie2 = {false,SPR_OFC_DIE_2,11,NULL,NULL,&s_ofcdie3};\r
+statetype s_ofcdie3 = {false,SPR_OFC_DIE_3,11,NULL,NULL,&s_ofcdie4};\r
+statetype s_ofcdie4 = {false,SPR_OFC_DIE_4,11,NULL,NULL,&s_ofcdie5};\r
+statetype s_ofcdie5 = {false,SPR_OFC_DEAD,0,NULL,NULL,&s_ofcdie5};\r
+\r
+\r
+//\r
+// mutant\r
+//\r
+\r
+extern statetype s_mutstand;\r
+\r
+extern statetype s_mutpath1;\r
+extern statetype s_mutpath1s;\r
+extern statetype s_mutpath2;\r
+extern statetype s_mutpath3;\r
+extern statetype s_mutpath3s;\r
+extern statetype s_mutpath4;\r
+\r
+extern statetype s_mutpain;\r
+extern statetype s_mutpain1;\r
+\r
+extern statetype s_mutgiveup;\r
+\r
+extern statetype s_mutshoot1;\r
+extern statetype s_mutshoot2;\r
+extern statetype s_mutshoot3;\r
+extern statetype s_mutshoot4;\r
+\r
+extern statetype s_mutchase1;\r
+extern statetype s_mutchase1s;\r
+extern statetype s_mutchase2;\r
+extern statetype s_mutchase3;\r
+extern statetype s_mutchase3s;\r
+extern statetype s_mutchase4;\r
+\r
+extern statetype s_mutdie1;\r
+extern statetype s_mutdie2;\r
+extern statetype s_mutdie3;\r
+extern statetype s_mutdie4;\r
+extern statetype s_mutdie5;\r
+\r
+statetype s_mutstand = {true,SPR_MUT_S_1,0,T_Stand,NULL,&s_mutstand};\r
+\r
+statetype s_mutpath1 = {true,SPR_MUT_W1_1,20,T_Path,NULL,&s_mutpath1s};\r
+statetype s_mutpath1s = {true,SPR_MUT_W1_1,5,NULL,NULL,&s_mutpath2};\r
+statetype s_mutpath2 = {true,SPR_MUT_W2_1,15,T_Path,NULL,&s_mutpath3};\r
+statetype s_mutpath3 = {true,SPR_MUT_W3_1,20,T_Path,NULL,&s_mutpath3s};\r
+statetype s_mutpath3s = {true,SPR_MUT_W3_1,5,NULL,NULL,&s_mutpath4};\r
+statetype s_mutpath4 = {true,SPR_MUT_W4_1,15,T_Path,NULL,&s_mutpath1};\r
+\r
+statetype s_mutpain = {2,SPR_MUT_PAIN_1,10,NULL,NULL,&s_mutchase1};\r
+statetype s_mutpain1 = {2,SPR_MUT_PAIN_2,10,NULL,NULL,&s_mutchase1};\r
+\r
+statetype s_mutshoot1 = {false,SPR_MUT_SHOOT1,6,NULL,T_Shoot,&s_mutshoot2};\r
+statetype s_mutshoot2 = {false,SPR_MUT_SHOOT2,20,NULL,NULL,&s_mutshoot3};\r
+statetype s_mutshoot3 = {false,SPR_MUT_SHOOT3,10,NULL,T_Shoot,&s_mutshoot4};\r
+statetype s_mutshoot4 = {false,SPR_MUT_SHOOT4,20,NULL,NULL,&s_mutchase1};\r
+\r
+statetype s_mutchase1 = {true,SPR_MUT_W1_1,10,T_Chase,NULL,&s_mutchase1s};\r
+statetype s_mutchase1s = {true,SPR_MUT_W1_1,3,NULL,NULL,&s_mutchase2};\r
+statetype s_mutchase2 = {true,SPR_MUT_W2_1,8,T_Chase,NULL,&s_mutchase3};\r
+statetype s_mutchase3 = {true,SPR_MUT_W3_1,10,T_Chase,NULL,&s_mutchase3s};\r
+statetype s_mutchase3s = {true,SPR_MUT_W3_1,3,NULL,NULL,&s_mutchase4};\r
+statetype s_mutchase4 = {true,SPR_MUT_W4_1,8,T_Chase,NULL,&s_mutchase1};\r
+\r
+statetype s_mutdie1 = {false,SPR_MUT_DIE_1,7,NULL,A_DeathScream,&s_mutdie2};\r
+statetype s_mutdie2 = {false,SPR_MUT_DIE_2,7,NULL,NULL,&s_mutdie3};\r
+statetype s_mutdie3 = {false,SPR_MUT_DIE_3,7,NULL,NULL,&s_mutdie4};\r
+statetype s_mutdie4 = {false,SPR_MUT_DIE_4,7,NULL,NULL,&s_mutdie5};\r
+statetype s_mutdie5 = {false,SPR_MUT_DEAD,0,NULL,NULL,&s_mutdie5};\r
+\r
+\r
+//\r
+// SS\r
+//\r
+\r
+extern statetype s_ssstand;\r
+\r
+extern statetype s_sspath1;\r
+extern statetype s_sspath1s;\r
+extern statetype s_sspath2;\r
+extern statetype s_sspath3;\r
+extern statetype s_sspath3s;\r
+extern statetype s_sspath4;\r
+\r
+extern statetype s_sspain;\r
+extern statetype s_sspain1;\r
+\r
+extern statetype s_ssshoot1;\r
+extern statetype s_ssshoot2;\r
+extern statetype s_ssshoot3;\r
+extern statetype s_ssshoot4;\r
+extern statetype s_ssshoot5;\r
+extern statetype s_ssshoot6;\r
+extern statetype s_ssshoot7;\r
+extern statetype s_ssshoot8;\r
+extern statetype s_ssshoot9;\r
+\r
+extern statetype s_sschase1;\r
+extern statetype s_sschase1s;\r
+extern statetype s_sschase2;\r
+extern statetype s_sschase3;\r
+extern statetype s_sschase3s;\r
+extern statetype s_sschase4;\r
+\r
+extern statetype s_ssdie1;\r
+extern statetype s_ssdie2;\r
+extern statetype s_ssdie3;\r
+extern statetype s_ssdie4;\r
+\r
+statetype s_ssstand = {true,SPR_SS_S_1,0,T_Stand,NULL,&s_ssstand};\r
+\r
+statetype s_sspath1 = {true,SPR_SS_W1_1,20,T_Path,NULL,&s_sspath1s};\r
+statetype s_sspath1s = {true,SPR_SS_W1_1,5,NULL,NULL,&s_sspath2};\r
+statetype s_sspath2 = {true,SPR_SS_W2_1,15,T_Path,NULL,&s_sspath3};\r
+statetype s_sspath3 = {true,SPR_SS_W3_1,20,T_Path,NULL,&s_sspath3s};\r
+statetype s_sspath3s = {true,SPR_SS_W3_1,5,NULL,NULL,&s_sspath4};\r
+statetype s_sspath4 = {true,SPR_SS_W4_1,15,T_Path,NULL,&s_sspath1};\r
+\r
+statetype s_sspain = {2,SPR_SS_PAIN_1,10,NULL,NULL,&s_sschase1};\r
+statetype s_sspain1 = {2,SPR_SS_PAIN_2,10,NULL,NULL,&s_sschase1};\r
+\r
+statetype s_ssshoot1 = {false,SPR_SS_SHOOT1,20,NULL,NULL,&s_ssshoot2};\r
+statetype s_ssshoot2 = {false,SPR_SS_SHOOT2,20,NULL,T_Shoot,&s_ssshoot3};\r
+statetype s_ssshoot3 = {false,SPR_SS_SHOOT3,10,NULL,NULL,&s_ssshoot4};\r
+statetype s_ssshoot4 = {false,SPR_SS_SHOOT2,10,NULL,T_Shoot,&s_ssshoot5};\r
+statetype s_ssshoot5 = {false,SPR_SS_SHOOT3,10,NULL,NULL,&s_ssshoot6};\r
+statetype s_ssshoot6 = {false,SPR_SS_SHOOT2,10,NULL,T_Shoot,&s_ssshoot7};\r
+statetype s_ssshoot7 = {false,SPR_SS_SHOOT3,10,NULL,NULL,&s_ssshoot8};\r
+statetype s_ssshoot8 = {false,SPR_SS_SHOOT2,10,NULL,T_Shoot,&s_ssshoot9};\r
+statetype s_ssshoot9 = {false,SPR_SS_SHOOT3,10,NULL,NULL,&s_sschase1};\r
+\r
+statetype s_sschase1 = {true,SPR_SS_W1_1,10,T_Chase,NULL,&s_sschase1s};\r
+statetype s_sschase1s = {true,SPR_SS_W1_1,3,NULL,NULL,&s_sschase2};\r
+statetype s_sschase2 = {true,SPR_SS_W2_1,8,T_Chase,NULL,&s_sschase3};\r
+statetype s_sschase3 = {true,SPR_SS_W3_1,10,T_Chase,NULL,&s_sschase3s};\r
+statetype s_sschase3s = {true,SPR_SS_W3_1,3,NULL,NULL,&s_sschase4};\r
+statetype s_sschase4 = {true,SPR_SS_W4_1,8,T_Chase,NULL,&s_sschase1};\r
+\r
+statetype s_ssdie1 = {false,SPR_SS_DIE_1,15,NULL,A_DeathScream,&s_ssdie2};\r
+statetype s_ssdie2 = {false,SPR_SS_DIE_2,15,NULL,NULL,&s_ssdie3};\r
+statetype s_ssdie3 = {false,SPR_SS_DIE_3,15,NULL,NULL,&s_ssdie4};\r
+statetype s_ssdie4 = {false,SPR_SS_DEAD,0,NULL,NULL,&s_ssdie4};\r
+\r
+\r
+#ifndef SPEAR\r
+//\r
+// hans\r
+//\r
+extern statetype s_bossstand;\r
+\r
+extern statetype s_bosschase1;\r
+extern statetype s_bosschase1s;\r
+extern statetype s_bosschase2;\r
+extern statetype s_bosschase3;\r
+extern statetype s_bosschase3s;\r
+extern statetype s_bosschase4;\r
+\r
+extern statetype s_bossdie1;\r
+extern statetype s_bossdie2;\r
+extern statetype s_bossdie3;\r
+extern statetype s_bossdie4;\r
+\r
+extern statetype s_bossshoot1;\r
+extern statetype s_bossshoot2;\r
+extern statetype s_bossshoot3;\r
+extern statetype s_bossshoot4;\r
+extern statetype s_bossshoot5;\r
+extern statetype s_bossshoot6;\r
+extern statetype s_bossshoot7;\r
+extern statetype s_bossshoot8;\r
+\r
+\r
+statetype s_bossstand = {false,SPR_BOSS_W1,0,T_Stand,NULL,&s_bossstand};\r
+\r
+statetype s_bosschase1 = {false,SPR_BOSS_W1,10,T_Chase,NULL,&s_bosschase1s};\r
+statetype s_bosschase1s = {false,SPR_BOSS_W1,3,NULL,NULL,&s_bosschase2};\r
+statetype s_bosschase2 = {false,SPR_BOSS_W2,8,T_Chase,NULL,&s_bosschase3};\r
+statetype s_bosschase3 = {false,SPR_BOSS_W3,10,T_Chase,NULL,&s_bosschase3s};\r
+statetype s_bosschase3s = {false,SPR_BOSS_W3,3,NULL,NULL,&s_bosschase4};\r
+statetype s_bosschase4 = {false,SPR_BOSS_W4,8,T_Chase,NULL,&s_bosschase1};\r
+\r
+statetype s_bossdie1 = {false,SPR_BOSS_DIE1,15,NULL,A_DeathScream,&s_bossdie2};\r
+statetype s_bossdie2 = {false,SPR_BOSS_DIE2,15,NULL,NULL,&s_bossdie3};\r
+statetype s_bossdie3 = {false,SPR_BOSS_DIE3,15,NULL,NULL,&s_bossdie4};\r
+statetype s_bossdie4 = {false,SPR_BOSS_DEAD,0,NULL,NULL,&s_bossdie4};\r
+\r
+statetype s_bossshoot1 = {false,SPR_BOSS_SHOOT1,30,NULL,NULL,&s_bossshoot2};\r
+statetype s_bossshoot2 = {false,SPR_BOSS_SHOOT2,10,NULL,T_Shoot,&s_bossshoot3};\r
+statetype s_bossshoot3 = {false,SPR_BOSS_SHOOT3,10,NULL,T_Shoot,&s_bossshoot4};\r
+statetype s_bossshoot4 = {false,SPR_BOSS_SHOOT2,10,NULL,T_Shoot,&s_bossshoot5};\r
+statetype s_bossshoot5 = {false,SPR_BOSS_SHOOT3,10,NULL,T_Shoot,&s_bossshoot6};\r
+statetype s_bossshoot6 = {false,SPR_BOSS_SHOOT2,10,NULL,T_Shoot,&s_bossshoot7};\r
+statetype s_bossshoot7 = {false,SPR_BOSS_SHOOT3,10,NULL,T_Shoot,&s_bossshoot8};\r
+statetype s_bossshoot8 = {false,SPR_BOSS_SHOOT1,10,NULL,NULL,&s_bosschase1};\r
+\r
+\r
+//\r
+// gretel\r
+//\r
+extern statetype s_gretelstand;\r
+\r
+extern statetype s_gretelchase1;\r
+extern statetype s_gretelchase1s;\r
+extern statetype s_gretelchase2;\r
+extern statetype s_gretelchase3;\r
+extern statetype s_gretelchase3s;\r
+extern statetype s_gretelchase4;\r
+\r
+extern statetype s_greteldie1;\r
+extern statetype s_greteldie2;\r
+extern statetype s_greteldie3;\r
+extern statetype s_greteldie4;\r
+\r
+extern statetype s_gretelshoot1;\r
+extern statetype s_gretelshoot2;\r
+extern statetype s_gretelshoot3;\r
+extern statetype s_gretelshoot4;\r
+extern statetype s_gretelshoot5;\r
+extern statetype s_gretelshoot6;\r
+extern statetype s_gretelshoot7;\r
+extern statetype s_gretelshoot8;\r
+\r
+\r
+statetype s_gretelstand = {false,SPR_GRETEL_W1,0,T_Stand,NULL,&s_gretelstand};\r
+\r
+statetype s_gretelchase1 = {false,SPR_GRETEL_W1,10,T_Chase,NULL,&s_gretelchase1s};\r
+statetype s_gretelchase1s = {false,SPR_GRETEL_W1,3,NULL,NULL,&s_gretelchase2};\r
+statetype s_gretelchase2 = {false,SPR_GRETEL_W2,8,T_Chase,NULL,&s_gretelchase3};\r
+statetype s_gretelchase3 = {false,SPR_GRETEL_W3,10,T_Chase,NULL,&s_gretelchase3s};\r
+statetype s_gretelchase3s = {false,SPR_GRETEL_W3,3,NULL,NULL,&s_gretelchase4};\r
+statetype s_gretelchase4 = {false,SPR_GRETEL_W4,8,T_Chase,NULL,&s_gretelchase1};\r
+\r
+statetype s_greteldie1 = {false,SPR_GRETEL_DIE1,15,NULL,A_DeathScream,&s_greteldie2};\r
+statetype s_greteldie2 = {false,SPR_GRETEL_DIE2,15,NULL,NULL,&s_greteldie3};\r
+statetype s_greteldie3 = {false,SPR_GRETEL_DIE3,15,NULL,NULL,&s_greteldie4};\r
+statetype s_greteldie4 = {false,SPR_GRETEL_DEAD,0,NULL,NULL,&s_greteldie4};\r
+\r
+statetype s_gretelshoot1 = {false,SPR_GRETEL_SHOOT1,30,NULL,NULL,&s_gretelshoot2};\r
+statetype s_gretelshoot2 = {false,SPR_GRETEL_SHOOT2,10,NULL,T_Shoot,&s_gretelshoot3};\r
+statetype s_gretelshoot3 = {false,SPR_GRETEL_SHOOT3,10,NULL,T_Shoot,&s_gretelshoot4};\r
+statetype s_gretelshoot4 = {false,SPR_GRETEL_SHOOT2,10,NULL,T_Shoot,&s_gretelshoot5};\r
+statetype s_gretelshoot5 = {false,SPR_GRETEL_SHOOT3,10,NULL,T_Shoot,&s_gretelshoot6};\r
+statetype s_gretelshoot6 = {false,SPR_GRETEL_SHOOT2,10,NULL,T_Shoot,&s_gretelshoot7};\r
+statetype s_gretelshoot7 = {false,SPR_GRETEL_SHOOT3,10,NULL,T_Shoot,&s_gretelshoot8};\r
+statetype s_gretelshoot8 = {false,SPR_GRETEL_SHOOT1,10,NULL,NULL,&s_gretelchase1};\r
+#endif\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnStand\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnStand (enemy_t which, int tilex, int tiley, int dir)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ switch (which)\r
+ {\r
+ case en_guard:\r
+ SpawnNewObj (tilex,tiley,&s_grdstand);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_officer:\r
+ SpawnNewObj (tilex,tiley,&s_ofcstand);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_mutant:\r
+ SpawnNewObj (tilex,tiley,&s_mutstand);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_ss:\r
+ SpawnNewObj (tilex,tiley,&s_ssstand);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+ }\r
+\r
+\r
+ map = mapsegs[0]+farmapylookup[tiley]+tilex;\r
+ if (*map == AMBUSHTILE)\r
+ {\r
+ tilemap[tilex][tiley] = 0;\r
+\r
+ if (*(map+1) >= AREATILE)\r
+ tile = *(map+1);\r
+ if (*(map-mapwidth) >= AREATILE)\r
+ tile = *(map-mapwidth);\r
+ if (*(map+mapwidth) >= AREATILE)\r
+ tile = *(map+mapwidth);\r
+ if ( *(map-1) >= AREATILE)\r
+ tile = *(map-1);\r
+\r
+ *map = tile;\r
+ new->areanumber = tile-AREATILE;\r
+\r
+ new->flags |= FL_AMBUSH;\r
+ }\r
+\r
+ new->obclass = guardobj+which;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][which];\r
+ new->dir = dir*2;\r
+ new->flags |= FL_SHOOTABLE;\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnDeadGuard\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnDeadGuard (int tilex, int tiley)\r
+{\r
+ SpawnNewObj (tilex,tiley,&s_grddie4);\r
+ new->obclass = inertobj;\r
+}\r
+\r
+\r
+\r
+#ifndef SPEAR\r
+/*\r
+===============\r
+=\r
+= SpawnBoss\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnBoss (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_bossstand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = bossobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_boss];\r
+ new->dir = south;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnGretel\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnGretel (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_gretelstand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = gretelobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_gretel];\r
+ new->dir = north;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+#endif\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnPatrol\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnPatrol (enemy_t which, int tilex, int tiley, int dir)\r
+{\r
+ switch (which)\r
+ {\r
+ case en_guard:\r
+ SpawnNewObj (tilex,tiley,&s_grdpath1);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_officer:\r
+ SpawnNewObj (tilex,tiley,&s_ofcpath1);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_ss:\r
+ SpawnNewObj (tilex,tiley,&s_sspath1);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_mutant:\r
+ SpawnNewObj (tilex,tiley,&s_mutpath1);\r
+ new->speed = SPDPATROL;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+\r
+ case en_dog:\r
+ SpawnNewObj (tilex,tiley,&s_dogpath1);\r
+ new->speed = SPDDOG;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+ break;\r
+ }\r
+\r
+ new->obclass = guardobj+which;\r
+ new->dir = dir*2;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][which];\r
+ new->distance = tileglobal;\r
+ new->flags |= FL_SHOOTABLE;\r
+ new->active = true;\r
+\r
+ actorat[new->tilex][new->tiley] = NULL; // don't use original spot\r
+\r
+ switch (dir)\r
+ {\r
+ case 0:\r
+ new->tilex++;\r
+ break;\r
+ case 1:\r
+ new->tiley--;\r
+ break;\r
+ case 2:\r
+ new->tilex--;\r
+ break;\r
+ case 3:\r
+ new->tiley++;\r
+ break;\r
+ }\r
+\r
+ actorat[new->tilex][new->tiley] = new;\r
+}\r
+\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= A_DeathScream\r
+=\r
+==================\r
+*/\r
+\r
+void A_DeathScream (objtype *ob)\r
+{\r
+#ifndef UPLOAD\r
+#ifndef SPEAR\r
+ if (mapon==9 && !US_RndT())\r
+#else\r
+ if ((mapon==18 || mapon==19) && !US_RndT())\r
+#endif\r
+ {\r
+ switch(ob->obclass)\r
+ {\r
+ case mutantobj:\r
+ case guardobj:\r
+ case officerobj:\r
+ case ssobj:\r
+ case dogobj:\r
+ PlaySoundLocActor(DEATHSCREAM6SND,ob);\r
+ return;\r
+ }\r
+ }\r
+#endif\r
+\r
+ switch (ob->obclass)\r
+ {\r
+ case mutantobj:\r
+ PlaySoundLocActor(AHHHGSND,ob);\r
+ break;\r
+\r
+ case guardobj:\r
+ {\r
+ int sounds[9]={ DEATHSCREAM1SND,\r
+ DEATHSCREAM2SND,\r
+ DEATHSCREAM3SND,\r
+ DEATHSCREAM4SND,\r
+ DEATHSCREAM5SND,\r
+ DEATHSCREAM7SND,\r
+ DEATHSCREAM8SND,\r
+ DEATHSCREAM9SND\r
+ };\r
+\r
+ #ifndef UPLOAD\r
+ PlaySoundLocActor(sounds[US_RndT()%8],ob);\r
+ #else\r
+ PlaySoundLocActor(sounds[US_RndT()%2],ob);\r
+ #endif\r
+ }\r
+ break;\r
+ case officerobj:\r
+ PlaySoundLocActor(NEINSOVASSND,ob);\r
+ break;\r
+ case ssobj:\r
+ PlaySoundLocActor(LEBENSND,ob); // JAB\r
+ break;\r
+ case dogobj:\r
+ PlaySoundLocActor(DOGDEATHSND,ob); // JAB\r
+ break;\r
+#ifndef SPEAR\r
+ case bossobj:\r
+ SD_PlaySound(MUTTISND); // JAB\r
+ break;\r
+ case schabbobj:\r
+ SD_PlaySound(MEINGOTTSND);\r
+ break;\r
+ case fakeobj:\r
+ SD_PlaySound(HITLERHASND);\r
+ break;\r
+ case mechahitlerobj:\r
+ SD_PlaySound(SCHEISTSND);\r
+ break;\r
+ case realhitlerobj:\r
+ SD_PlaySound(EVASND);\r
+ break;\r
+ case gretelobj:\r
+ SD_PlaySound(MEINSND);\r
+ break;\r
+ case giftobj:\r
+ SD_PlaySound(DONNERSND);\r
+ break;\r
+ case fatobj:\r
+ SD_PlaySound(ROSESND);\r
+ break;\r
+#else\r
+ case spectreobj:\r
+ SD_PlaySound(GHOSTFADESND);\r
+ break;\r
+ case angelobj:\r
+ SD_PlaySound(ANGELDEATHSND);\r
+ break;\r
+ case transobj:\r
+ SD_PlaySound(TRANSDEATHSND);\r
+ break;\r
+ case uberobj:\r
+ SD_PlaySound(UBERDEATHSND);\r
+ break;\r
+ case willobj:\r
+ SD_PlaySound(WILHELMDEATHSND);\r
+ break;\r
+ case deathobj:\r
+ SD_PlaySound(KNIGHTDEATHSND);\r
+ break;\r
+#endif\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ SPEAR ACTORS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#ifdef SPEAR\r
+\r
+void T_Launch (objtype *ob);\r
+void T_Will (objtype *ob);\r
+\r
+extern statetype s_angelshoot1;\r
+extern statetype s_deathshoot1;\r
+extern statetype s_spark1;\r
+\r
+//\r
+// trans\r
+//\r
+extern statetype s_transstand;\r
+\r
+extern statetype s_transchase1;\r
+extern statetype s_transchase1s;\r
+extern statetype s_transchase2;\r
+extern statetype s_transchase3;\r
+extern statetype s_transchase3s;\r
+extern statetype s_transchase4;\r
+\r
+extern statetype s_transdie0;\r
+extern statetype s_transdie01;\r
+extern statetype s_transdie1;\r
+extern statetype s_transdie2;\r
+extern statetype s_transdie3;\r
+extern statetype s_transdie4;\r
+\r
+extern statetype s_transshoot1;\r
+extern statetype s_transshoot2;\r
+extern statetype s_transshoot3;\r
+extern statetype s_transshoot4;\r
+extern statetype s_transshoot5;\r
+extern statetype s_transshoot6;\r
+extern statetype s_transshoot7;\r
+extern statetype s_transshoot8;\r
+\r
+\r
+statetype s_transstand = {false,SPR_TRANS_W1,0,T_Stand,NULL,&s_transstand};\r
+\r
+statetype s_transchase1 = {false,SPR_TRANS_W1,10,T_Chase,NULL,&s_transchase1s};\r
+statetype s_transchase1s = {false,SPR_TRANS_W1,3,NULL,NULL,&s_transchase2};\r
+statetype s_transchase2 = {false,SPR_TRANS_W2,8,T_Chase,NULL,&s_transchase3};\r
+statetype s_transchase3 = {false,SPR_TRANS_W3,10,T_Chase,NULL,&s_transchase3s};\r
+statetype s_transchase3s = {false,SPR_TRANS_W3,3,NULL,NULL,&s_transchase4};\r
+statetype s_transchase4 = {false,SPR_TRANS_W4,8,T_Chase,NULL,&s_transchase1};\r
+\r
+statetype s_transdie0 = {false,SPR_TRANS_W1,1,NULL,A_DeathScream,&s_transdie01};\r
+statetype s_transdie01 = {false,SPR_TRANS_W1,1,NULL,NULL,&s_transdie1};\r
+statetype s_transdie1 = {false,SPR_TRANS_DIE1,15,NULL,NULL,&s_transdie2};\r
+statetype s_transdie2 = {false,SPR_TRANS_DIE2,15,NULL,NULL,&s_transdie3};\r
+statetype s_transdie3 = {false,SPR_TRANS_DIE3,15,NULL,NULL,&s_transdie4};\r
+statetype s_transdie4 = {false,SPR_TRANS_DEAD,0,NULL,NULL,&s_transdie4};\r
+\r
+statetype s_transshoot1 = {false,SPR_TRANS_SHOOT1,30,NULL,NULL,&s_transshoot2};\r
+statetype s_transshoot2 = {false,SPR_TRANS_SHOOT2,10,NULL,T_Shoot,&s_transshoot3};\r
+statetype s_transshoot3 = {false,SPR_TRANS_SHOOT3,10,NULL,T_Shoot,&s_transshoot4};\r
+statetype s_transshoot4 = {false,SPR_TRANS_SHOOT2,10,NULL,T_Shoot,&s_transshoot5};\r
+statetype s_transshoot5 = {false,SPR_TRANS_SHOOT3,10,NULL,T_Shoot,&s_transshoot6};\r
+statetype s_transshoot6 = {false,SPR_TRANS_SHOOT2,10,NULL,T_Shoot,&s_transshoot7};\r
+statetype s_transshoot7 = {false,SPR_TRANS_SHOOT3,10,NULL,T_Shoot,&s_transshoot8};\r
+statetype s_transshoot8 = {false,SPR_TRANS_SHOOT1,10,NULL,NULL,&s_transchase1};\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnTrans\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnTrans (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (SoundBlasterPresent && DigiMode != sds_Off)\r
+ s_transdie01.tictime = 105;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_transstand);\r
+ new->obclass = transobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_trans];\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+//\r
+// uber\r
+//\r
+void T_UShoot (objtype *ob);\r
+\r
+extern statetype s_uberstand;\r
+\r
+extern statetype s_uberchase1;\r
+extern statetype s_uberchase1s;\r
+extern statetype s_uberchase2;\r
+extern statetype s_uberchase3;\r
+extern statetype s_uberchase3s;\r
+extern statetype s_uberchase4;\r
+\r
+extern statetype s_uberdie0;\r
+extern statetype s_uberdie01;\r
+extern statetype s_uberdie1;\r
+extern statetype s_uberdie2;\r
+extern statetype s_uberdie3;\r
+extern statetype s_uberdie4;\r
+extern statetype s_uberdie5;\r
+\r
+extern statetype s_ubershoot1;\r
+extern statetype s_ubershoot2;\r
+extern statetype s_ubershoot3;\r
+extern statetype s_ubershoot4;\r
+extern statetype s_ubershoot5;\r
+extern statetype s_ubershoot6;\r
+extern statetype s_ubershoot7;\r
+\r
+\r
+statetype s_uberstand = {false,SPR_UBER_W1,0,T_Stand,NULL,&s_uberstand};\r
+\r
+statetype s_uberchase1 = {false,SPR_UBER_W1,10,T_Chase,NULL,&s_uberchase1s};\r
+statetype s_uberchase1s = {false,SPR_UBER_W1,3,NULL,NULL,&s_uberchase2};\r
+statetype s_uberchase2 = {false,SPR_UBER_W2,8,T_Chase,NULL,&s_uberchase3};\r
+statetype s_uberchase3 = {false,SPR_UBER_W3,10,T_Chase,NULL,&s_uberchase3s};\r
+statetype s_uberchase3s = {false,SPR_UBER_W3,3,NULL,NULL,&s_uberchase4};\r
+statetype s_uberchase4 = {false,SPR_UBER_W4,8,T_Chase,NULL,&s_uberchase1};\r
+\r
+statetype s_uberdie0 = {false,SPR_UBER_W1,1,NULL,A_DeathScream,&s_uberdie01};\r
+statetype s_uberdie01 = {false,SPR_UBER_W1,1,NULL,NULL,&s_uberdie1};\r
+statetype s_uberdie1 = {false,SPR_UBER_DIE1,15,NULL,NULL,&s_uberdie2};\r
+statetype s_uberdie2 = {false,SPR_UBER_DIE2,15,NULL,NULL,&s_uberdie3};\r
+statetype s_uberdie3 = {false,SPR_UBER_DIE3,15,NULL,NULL,&s_uberdie4};\r
+statetype s_uberdie4 = {false,SPR_UBER_DIE4,15,NULL,NULL,&s_uberdie5};\r
+statetype s_uberdie5 = {false,SPR_UBER_DEAD,0,NULL,NULL,&s_uberdie5};\r
+\r
+statetype s_ubershoot1 = {false,SPR_UBER_SHOOT1,30,NULL,NULL,&s_ubershoot2};\r
+statetype s_ubershoot2 = {false,SPR_UBER_SHOOT2,12,NULL,T_UShoot,&s_ubershoot3};\r
+statetype s_ubershoot3 = {false,SPR_UBER_SHOOT3,12,NULL,T_UShoot,&s_ubershoot4};\r
+statetype s_ubershoot4 = {false,SPR_UBER_SHOOT4,12,NULL,T_UShoot,&s_ubershoot5};\r
+statetype s_ubershoot5 = {false,SPR_UBER_SHOOT3,12,NULL,T_UShoot,&s_ubershoot6};\r
+statetype s_ubershoot6 = {false,SPR_UBER_SHOOT2,12,NULL,T_UShoot,&s_ubershoot7};\r
+statetype s_ubershoot7 = {false,SPR_UBER_SHOOT1,12,NULL,NULL,&s_uberchase1};\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnUber\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnUber (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (SoundBlasterPresent && DigiMode != sds_Off)\r
+ s_uberdie01.tictime = 70;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_uberstand);\r
+ new->obclass = uberobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_uber];\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_UShoot\r
+=\r
+===============\r
+*/\r
+\r
+void T_UShoot (objtype *ob)\r
+{\r
+ int dx,dy,dist;\r
+\r
+ T_Shoot (ob);\r
+\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx : dy;\r
+ if (dist <= 1)\r
+ TakeDamage (10,ob);\r
+}\r
+\r
+\r
+//\r
+// will\r
+//\r
+extern statetype s_willstand;\r
+\r
+extern statetype s_willchase1;\r
+extern statetype s_willchase1s;\r
+extern statetype s_willchase2;\r
+extern statetype s_willchase3;\r
+extern statetype s_willchase3s;\r
+extern statetype s_willchase4;\r
+\r
+extern statetype s_willdie1;\r
+extern statetype s_willdie2;\r
+extern statetype s_willdie3;\r
+extern statetype s_willdie4;\r
+extern statetype s_willdie5;\r
+extern statetype s_willdie6;\r
+\r
+extern statetype s_willshoot1;\r
+extern statetype s_willshoot2;\r
+extern statetype s_willshoot3;\r
+extern statetype s_willshoot4;\r
+extern statetype s_willshoot5;\r
+extern statetype s_willshoot6;\r
+\r
+\r
+statetype s_willstand = {false,SPR_WILL_W1,0,T_Stand,NULL,&s_willstand};\r
+\r
+statetype s_willchase1 = {false,SPR_WILL_W1,10,T_Will,NULL,&s_willchase1s};\r
+statetype s_willchase1s = {false,SPR_WILL_W1,3,NULL,NULL,&s_willchase2};\r
+statetype s_willchase2 = {false,SPR_WILL_W2,8,T_Will,NULL,&s_willchase3};\r
+statetype s_willchase3 = {false,SPR_WILL_W3,10,T_Will,NULL,&s_willchase3s};\r
+statetype s_willchase3s = {false,SPR_WILL_W3,3,NULL,NULL,&s_willchase4};\r
+statetype s_willchase4 = {false,SPR_WILL_W4,8,T_Will,NULL,&s_willchase1};\r
+\r
+statetype s_willdeathcam = {false,SPR_WILL_W1,1,NULL,NULL,&s_willdie1};\r
+\r
+statetype s_willdie1 = {false,SPR_WILL_W1,1,NULL,A_DeathScream,&s_willdie2};\r
+statetype s_willdie2 = {false,SPR_WILL_W1,10,NULL,NULL,&s_willdie3};\r
+statetype s_willdie3 = {false,SPR_WILL_DIE1,10,NULL,NULL,&s_willdie4};\r
+statetype s_willdie4 = {false,SPR_WILL_DIE2,10,NULL,NULL,&s_willdie5};\r
+statetype s_willdie5 = {false,SPR_WILL_DIE3,10,NULL,NULL,&s_willdie6};\r
+statetype s_willdie6 = {false,SPR_WILL_DEAD,20,NULL,NULL,&s_willdie6};\r
+\r
+statetype s_willshoot1 = {false,SPR_WILL_SHOOT1,30,NULL,NULL,&s_willshoot2};\r
+statetype s_willshoot2 = {false,SPR_WILL_SHOOT2,10,NULL,T_Launch,&s_willshoot3};\r
+statetype s_willshoot3 = {false,SPR_WILL_SHOOT3,10,NULL,T_Shoot,&s_willshoot4};\r
+statetype s_willshoot4 = {false,SPR_WILL_SHOOT4,10,NULL,T_Shoot,&s_willshoot5};\r
+statetype s_willshoot5 = {false,SPR_WILL_SHOOT3,10,NULL,T_Shoot,&s_willshoot6};\r
+statetype s_willshoot6 = {false,SPR_WILL_SHOOT4,10,NULL,T_Shoot,&s_willchase1};\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnWill\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnWill (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (SoundBlasterPresent && DigiMode != sds_Off)\r
+ s_willdie2.tictime = 70;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_willstand);\r
+ new->obclass = willobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_will];\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+================\r
+=\r
+= T_Will\r
+=\r
+================\r
+*/\r
+\r
+void T_Will (objtype *ob)\r
+{\r
+ long move;\r
+ int dx,dy,dist;\r
+ boolean dodge;\r
+\r
+ dodge = false;\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx : dy;\r
+\r
+ if (CheckLine(ob)) // got a shot at player?\r
+ {\r
+ if ( US_RndT() < (tics<<3) )\r
+ {\r
+ //\r
+ // go into attack frame\r
+ //\r
+ if (ob->obclass == willobj)\r
+ NewState (ob,&s_willshoot1);\r
+ else if (ob->obclass == angelobj)\r
+ NewState (ob,&s_angelshoot1);\r
+ else\r
+ NewState (ob,&s_deathshoot1);\r
+ return;\r
+ }\r
+ dodge = true;\r
+ }\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (ob->distance < 0)\r
+ {\r
+ //\r
+ // waiting for a door to open\r
+ //\r
+ OpenDoor (-ob->distance-1);\r
+ if (doorobjlist[-ob->distance-1].action != dr_open)\r
+ return;\r
+ ob->distance = TILEGLOBAL; // go ahead, the door is now opoen\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ if (dist <4)\r
+ SelectRunDir (ob);\r
+ else if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+\r
+//\r
+// death\r
+//\r
+extern statetype s_deathstand;\r
+\r
+extern statetype s_deathchase1;\r
+extern statetype s_deathchase1s;\r
+extern statetype s_deathchase2;\r
+extern statetype s_deathchase3;\r
+extern statetype s_deathchase3s;\r
+extern statetype s_deathchase4;\r
+\r
+extern statetype s_deathdie1;\r
+extern statetype s_deathdie2;\r
+extern statetype s_deathdie3;\r
+extern statetype s_deathdie4;\r
+extern statetype s_deathdie5;\r
+extern statetype s_deathdie6;\r
+extern statetype s_deathdie7;\r
+extern statetype s_deathdie8;\r
+extern statetype s_deathdie9;\r
+\r
+extern statetype s_deathshoot1;\r
+extern statetype s_deathshoot2;\r
+extern statetype s_deathshoot3;\r
+extern statetype s_deathshoot4;\r
+extern statetype s_deathshoot5;\r
+\r
+\r
+statetype s_deathstand = {false,SPR_DEATH_W1,0,T_Stand,NULL,&s_deathstand};\r
+\r
+statetype s_deathchase1 = {false,SPR_DEATH_W1,10,T_Will,NULL,&s_deathchase1s};\r
+statetype s_deathchase1s = {false,SPR_DEATH_W1,3,NULL,NULL,&s_deathchase2};\r
+statetype s_deathchase2 = {false,SPR_DEATH_W2,8,T_Will,NULL,&s_deathchase3};\r
+statetype s_deathchase3 = {false,SPR_DEATH_W3,10,T_Will,NULL,&s_deathchase3s};\r
+statetype s_deathchase3s = {false,SPR_DEATH_W3,3,NULL,NULL,&s_deathchase4};\r
+statetype s_deathchase4 = {false,SPR_DEATH_W4,8,T_Will,NULL,&s_deathchase1};\r
+\r
+statetype s_deathdeathcam = {false,SPR_DEATH_W1,1,NULL,NULL,&s_deathdie1};\r
+\r
+statetype s_deathdie1 = {false,SPR_DEATH_W1,1,NULL,A_DeathScream,&s_deathdie2};\r
+statetype s_deathdie2 = {false,SPR_DEATH_W1,10,NULL,NULL,&s_deathdie3};\r
+statetype s_deathdie3 = {false,SPR_DEATH_DIE1,10,NULL,NULL,&s_deathdie4};\r
+statetype s_deathdie4 = {false,SPR_DEATH_DIE2,10,NULL,NULL,&s_deathdie5};\r
+statetype s_deathdie5 = {false,SPR_DEATH_DIE3,10,NULL,NULL,&s_deathdie6};\r
+statetype s_deathdie6 = {false,SPR_DEATH_DIE4,10,NULL,NULL,&s_deathdie7};\r
+statetype s_deathdie7 = {false,SPR_DEATH_DIE5,10,NULL,NULL,&s_deathdie8};\r
+statetype s_deathdie8 = {false,SPR_DEATH_DIE6,10,NULL,NULL,&s_deathdie9};\r
+statetype s_deathdie9 = {false,SPR_DEATH_DEAD,0,NULL,NULL,&s_deathdie9};\r
+\r
+statetype s_deathshoot1 = {false,SPR_DEATH_SHOOT1,30,NULL,NULL,&s_deathshoot2};\r
+statetype s_deathshoot2 = {false,SPR_DEATH_SHOOT2,10,NULL,T_Launch,&s_deathshoot3};\r
+statetype s_deathshoot3 = {false,SPR_DEATH_SHOOT4,10,NULL,T_Shoot,&s_deathshoot4};\r
+statetype s_deathshoot4 = {false,SPR_DEATH_SHOOT3,10,NULL,T_Launch,&s_deathshoot5};\r
+statetype s_deathshoot5 = {false,SPR_DEATH_SHOOT4,10,NULL,T_Shoot,&s_deathchase1};\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnDeath\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnDeath (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (SoundBlasterPresent && DigiMode != sds_Off)\r
+ s_deathdie2.tictime = 105;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_deathstand);\r
+ new->obclass = deathobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_death];\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+/*\r
+===============\r
+=\r
+= T_Launch\r
+=\r
+===============\r
+*/\r
+\r
+void T_Launch (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+ float angle;\r
+ int iangle;\r
+\r
+ deltax = player->x - ob->x;\r
+ deltay = ob->y - player->y;\r
+ angle = atan2 (deltay,deltax);\r
+ if (angle<0)\r
+ angle = M_PI*2+angle;\r
+ iangle = angle/(M_PI*2)*ANGLES;\r
+ if (ob->obclass == deathobj)\r
+ {\r
+ T_Shoot (ob);\r
+ if (ob->state == &s_deathshoot2)\r
+ {\r
+ iangle-=4;\r
+ if (iangle<0)\r
+ iangle+=ANGLES;\r
+ }\r
+ else\r
+ {\r
+ iangle+=4;\r
+ if (iangle>=ANGLES)\r
+ iangle-=ANGLES;\r
+ }\r
+ }\r
+\r
+ GetNewActor ();\r
+ new->state = &s_rocket;\r
+ new->ticcount = 1;\r
+\r
+ new->tilex = ob->tilex;\r
+ new->tiley = ob->tiley;\r
+ new->x = ob->x;\r
+ new->y = ob->y;\r
+ new->obclass = rocketobj;\r
+ switch(ob->obclass)\r
+ {\r
+ case deathobj:\r
+ new->state = &s_hrocket;\r
+ new->obclass = hrocketobj;\r
+ PlaySoundLocActor (KNIGHTMISSILESND,new);\r
+ break;\r
+ case angelobj:\r
+ new->state = &s_spark1;\r
+ new->obclass = sparkobj;\r
+ PlaySoundLocActor (ANGELFIRESND,new);\r
+ break;\r
+ default:\r
+ PlaySoundLocActor (MISSILEFIRESND,new);\r
+ }\r
+\r
+ new->dir = nodir;\r
+ new->angle = iangle;\r
+ new->speed = 0x2000l;\r
+ new->flags = FL_NONMARK;\r
+ new->active = true;\r
+}\r
+\r
+\r
+\r
+//\r
+// angel\r
+//\r
+void A_Relaunch (objtype *ob);\r
+void A_Victory (objtype *ob);\r
+void A_StartAttack (objtype *ob);\r
+void A_Breathing (objtype *ob);\r
+\r
+extern statetype s_angelstand;\r
+\r
+extern statetype s_angelchase1;\r
+extern statetype s_angelchase1s;\r
+extern statetype s_angelchase2;\r
+extern statetype s_angelchase3;\r
+extern statetype s_angelchase3s;\r
+extern statetype s_angelchase4;\r
+\r
+extern statetype s_angeldie1;\r
+extern statetype s_angeldie11;\r
+extern statetype s_angeldie2;\r
+extern statetype s_angeldie3;\r
+extern statetype s_angeldie4;\r
+extern statetype s_angeldie5;\r
+extern statetype s_angeldie6;\r
+extern statetype s_angeldie7;\r
+extern statetype s_angeldie8;\r
+extern statetype s_angeldie9;\r
+\r
+extern statetype s_angelshoot1;\r
+extern statetype s_angelshoot2;\r
+extern statetype s_angelshoot3;\r
+extern statetype s_angelshoot4;\r
+extern statetype s_angelshoot5;\r
+extern statetype s_angelshoot6;\r
+\r
+extern statetype s_angeltired;\r
+extern statetype s_angeltired2;\r
+extern statetype s_angeltired3;\r
+extern statetype s_angeltired4;\r
+extern statetype s_angeltired5;\r
+extern statetype s_angeltired6;\r
+extern statetype s_angeltired7;\r
+\r
+extern statetype s_spark1;\r
+extern statetype s_spark2;\r
+extern statetype s_spark3;\r
+extern statetype s_spark4;\r
+\r
+\r
+statetype s_angelstand = {false,SPR_ANGEL_W1,0,T_Stand,NULL,&s_angelstand};\r
+\r
+statetype s_angelchase1 = {false,SPR_ANGEL_W1,10,T_Will,NULL,&s_angelchase1s};\r
+statetype s_angelchase1s = {false,SPR_ANGEL_W1,3,NULL,NULL,&s_angelchase2};\r
+statetype s_angelchase2 = {false,SPR_ANGEL_W2,8,T_Will,NULL,&s_angelchase3};\r
+statetype s_angelchase3 = {false,SPR_ANGEL_W3,10,T_Will,NULL,&s_angelchase3s};\r
+statetype s_angelchase3s = {false,SPR_ANGEL_W3,3,NULL,NULL,&s_angelchase4};\r
+statetype s_angelchase4 = {false,SPR_ANGEL_W4,8,T_Will,NULL,&s_angelchase1};\r
+\r
+statetype s_angeldie1 = {false,SPR_ANGEL_W1,1,NULL,A_DeathScream,&s_angeldie11};\r
+statetype s_angeldie11 = {false,SPR_ANGEL_W1,1,NULL,NULL,&s_angeldie2};\r
+statetype s_angeldie2 = {false,SPR_ANGEL_DIE1,10,NULL,A_Slurpie,&s_angeldie3};\r
+statetype s_angeldie3 = {false,SPR_ANGEL_DIE2,10,NULL,NULL,&s_angeldie4};\r
+statetype s_angeldie4 = {false,SPR_ANGEL_DIE3,10,NULL,NULL,&s_angeldie5};\r
+statetype s_angeldie5 = {false,SPR_ANGEL_DIE4,10,NULL,NULL,&s_angeldie6};\r
+statetype s_angeldie6 = {false,SPR_ANGEL_DIE5,10,NULL,NULL,&s_angeldie7};\r
+statetype s_angeldie7 = {false,SPR_ANGEL_DIE6,10,NULL,NULL,&s_angeldie8};\r
+statetype s_angeldie8 = {false,SPR_ANGEL_DIE7,10,NULL,NULL,&s_angeldie9};\r
+statetype s_angeldie9 = {false,SPR_ANGEL_DEAD,130,NULL,A_Victory,&s_angeldie9};\r
+\r
+statetype s_angelshoot1 = {false,SPR_ANGEL_SHOOT1,10,NULL,A_StartAttack,&s_angelshoot2};\r
+statetype s_angelshoot2 = {false,SPR_ANGEL_SHOOT2,20,NULL,T_Launch,&s_angelshoot3};\r
+statetype s_angelshoot3 = {false,SPR_ANGEL_SHOOT1,10,NULL,A_Relaunch,&s_angelshoot2};\r
+\r
+statetype s_angeltired = {false,SPR_ANGEL_TIRED1,40,NULL,A_Breathing,&s_angeltired2};\r
+statetype s_angeltired2 = {false,SPR_ANGEL_TIRED2,40,NULL,NULL,&s_angeltired3};\r
+statetype s_angeltired3 = {false,SPR_ANGEL_TIRED1,40,NULL,A_Breathing,&s_angeltired4};\r
+statetype s_angeltired4 = {false,SPR_ANGEL_TIRED2,40,NULL,NULL,&s_angeltired5};\r
+statetype s_angeltired5 = {false,SPR_ANGEL_TIRED1,40,NULL,A_Breathing,&s_angeltired6};\r
+statetype s_angeltired6 = {false,SPR_ANGEL_TIRED2,40,NULL,NULL,&s_angeltired7};\r
+statetype s_angeltired7 = {false,SPR_ANGEL_TIRED1,40,NULL,A_Breathing,&s_angelchase1};\r
+\r
+statetype s_spark1 = {false,SPR_SPARK1,6,T_Projectile,NULL,&s_spark2};\r
+statetype s_spark2 = {false,SPR_SPARK2,6,T_Projectile,NULL,&s_spark3};\r
+statetype s_spark3 = {false,SPR_SPARK3,6,T_Projectile,NULL,&s_spark4};\r
+statetype s_spark4 = {false,SPR_SPARK4,6,T_Projectile,NULL,&s_spark1};\r
+\r
+\r
+#pragma argsused\r
+void A_Slurpie (objtype *ob)\r
+{\r
+ SD_PlaySound(SLURPIESND);\r
+}\r
+\r
+#pragma argsused\r
+void A_Breathing (objtype *ob)\r
+{\r
+ SD_PlaySound(ANGELTIREDSND);\r
+}\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnAngel\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnAngel (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+\r
+ if (SoundBlasterPresent && DigiMode != sds_Off)\r
+ s_angeldie11.tictime = 105;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_angelstand);\r
+ new->obclass = angelobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_angel];\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= A_Victory\r
+=\r
+=================\r
+*/\r
+\r
+#pragma argsused\r
+void A_Victory (objtype *ob)\r
+{\r
+ playstate = ex_victorious;\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= A_StartAttack\r
+=\r
+=================\r
+*/\r
+\r
+void A_StartAttack (objtype *ob)\r
+{\r
+ ob->temp1 = 0;\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= A_Relaunch\r
+=\r
+=================\r
+*/\r
+\r
+void A_Relaunch (objtype *ob)\r
+{\r
+ if (++ob->temp1 == 3)\r
+ {\r
+ NewState (ob,&s_angeltired);\r
+ return;\r
+ }\r
+\r
+ if (US_RndT()&1)\r
+ {\r
+ NewState (ob,&s_angelchase1);\r
+ return;\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+//\r
+// spectre\r
+//\r
+void T_SpectreWait (objtype *ob);\r
+void A_Dormant (objtype *ob);\r
+\r
+extern statetype s_spectrewait1;\r
+extern statetype s_spectrewait2;\r
+extern statetype s_spectrewait3;\r
+extern statetype s_spectrewait4;\r
+\r
+extern statetype s_spectrechase1;\r
+extern statetype s_spectrechase2;\r
+extern statetype s_spectrechase3;\r
+extern statetype s_spectrechase4;\r
+\r
+extern statetype s_spectredie1;\r
+extern statetype s_spectredie2;\r
+extern statetype s_spectredie3;\r
+extern statetype s_spectredie4;\r
+\r
+extern statetype s_spectrewake;\r
+\r
+statetype s_spectrewait1 = {false,SPR_SPECTRE_W1,10,T_Stand,NULL,&s_spectrewait2};\r
+statetype s_spectrewait2 = {false,SPR_SPECTRE_W2,10,T_Stand,NULL,&s_spectrewait3};\r
+statetype s_spectrewait3 = {false,SPR_SPECTRE_W3,10,T_Stand,NULL,&s_spectrewait4};\r
+statetype s_spectrewait4 = {false,SPR_SPECTRE_W4,10,T_Stand,NULL,&s_spectrewait1};\r
+\r
+statetype s_spectrechase1 = {false,SPR_SPECTRE_W1,10,T_Ghosts,NULL,&s_spectrechase2};\r
+statetype s_spectrechase2 = {false,SPR_SPECTRE_W2,10,T_Ghosts,NULL,&s_spectrechase3};\r
+statetype s_spectrechase3 = {false,SPR_SPECTRE_W3,10,T_Ghosts,NULL,&s_spectrechase4};\r
+statetype s_spectrechase4 = {false,SPR_SPECTRE_W4,10,T_Ghosts,NULL,&s_spectrechase1};\r
+\r
+statetype s_spectredie1 = {false,SPR_SPECTRE_F1,10,NULL,NULL,&s_spectredie2};\r
+statetype s_spectredie2 = {false,SPR_SPECTRE_F2,10,NULL,NULL,&s_spectredie3};\r
+statetype s_spectredie3 = {false,SPR_SPECTRE_F3,10,NULL,NULL,&s_spectredie4};\r
+statetype s_spectredie4 = {false,SPR_SPECTRE_F4,300,NULL,NULL,&s_spectrewake};\r
+statetype s_spectrewake = {false,SPR_SPECTRE_F4,10,NULL,A_Dormant,&s_spectrewake};\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnSpectre\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnSpectre (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_spectrewait1);\r
+ new->obclass = spectreobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_spectre];\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH; // |FL_NEVERMARK|FL_NONMARK;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= A_Dormant\r
+=\r
+===============\r
+*/\r
+\r
+void A_Dormant (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+ int xl,xh,yl,yh;\r
+ int x,y;\r
+ unsigned tile;\r
+\r
+ deltax = ob->x - player->x;\r
+ if (deltax < -MINACTORDIST || deltax > MINACTORDIST)\r
+ goto moveok;\r
+ deltay = ob->y - player->y;\r
+ if (deltay < -MINACTORDIST || deltay > MINACTORDIST)\r
+ goto moveok;\r
+\r
+ return;\r
+moveok:\r
+\r
+ xl = (ob->x-MINDIST) >> TILESHIFT;\r
+ xh = (ob->x+MINDIST) >> TILESHIFT;\r
+ yl = (ob->y-MINDIST) >> TILESHIFT;\r
+ yh = (ob->y+MINDIST) >> TILESHIFT;\r
+\r
+ for (y=yl ; y<=yh ; y++)\r
+ for (x=xl ; x<=xh ; x++)\r
+ {\r
+ tile = actorat[x][y];\r
+ if (!tile)\r
+ continue;\r
+ if (tile<256)\r
+ return;\r
+ if (((objtype *)tile)->flags&FL_SHOOTABLE)\r
+ return;\r
+ }\r
+\r
+ ob->flags |= FL_AMBUSH | FL_SHOOTABLE;\r
+ ob->flags &= ~FL_ATTACKMODE;\r
+ ob->dir = nodir;\r
+ NewState (ob,&s_spectrewait1);\r
+}\r
+\r
+\r
+#endif\r
+\r
+/*\r
+=============================================================================\r
+\r
+ SCHABBS / GIFT / FAT\r
+\r
+=============================================================================\r
+*/\r
+\r
+#ifndef SPEAR\r
+/*\r
+===============\r
+=\r
+= SpawnGhosts\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnGhosts (int which, int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ switch(which)\r
+ {\r
+ case en_blinky:\r
+ SpawnNewObj (tilex,tiley,&s_blinkychase1);\r
+ break;\r
+ case en_clyde:\r
+ SpawnNewObj (tilex,tiley,&s_clydechase1);\r
+ break;\r
+ case en_pinky:\r
+ SpawnNewObj (tilex,tiley,&s_pinkychase1);\r
+ break;\r
+ case en_inky:\r
+ SpawnNewObj (tilex,tiley,&s_inkychase1);\r
+ break;\r
+ }\r
+\r
+ new->obclass = ghostobj;\r
+ new->speed = SPDDOG;\r
+\r
+ new->dir = east;\r
+ new->flags |= FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+\r
+void T_Gift (objtype *ob);\r
+void T_GiftThrow (objtype *ob);\r
+\r
+void T_Fat (objtype *ob);\r
+void T_FatThrow (objtype *ob);\r
+\r
+//\r
+// schabb\r
+//\r
+extern statetype s_schabbstand;\r
+\r
+extern statetype s_schabbchase1;\r
+extern statetype s_schabbchase1s;\r
+extern statetype s_schabbchase2;\r
+extern statetype s_schabbchase3;\r
+extern statetype s_schabbchase3s;\r
+extern statetype s_schabbchase4;\r
+\r
+extern statetype s_schabbdie1;\r
+extern statetype s_schabbdie2;\r
+extern statetype s_schabbdie3;\r
+extern statetype s_schabbdie4;\r
+extern statetype s_schabbdie5;\r
+extern statetype s_schabbdie6;\r
+\r
+extern statetype s_schabbshoot1;\r
+extern statetype s_schabbshoot2;\r
+\r
+extern statetype s_needle1;\r
+extern statetype s_needle2;\r
+extern statetype s_needle3;\r
+extern statetype s_needle4;\r
+\r
+extern statetype s_schabbdeathcam;\r
+\r
+\r
+statetype s_schabbstand = {false,SPR_SCHABB_W1,0,T_Stand,NULL,&s_schabbstand};\r
+\r
+statetype s_schabbchase1 = {false,SPR_SCHABB_W1,10,T_Schabb,NULL,&s_schabbchase1s};\r
+statetype s_schabbchase1s = {false,SPR_SCHABB_W1,3,NULL,NULL,&s_schabbchase2};\r
+statetype s_schabbchase2 = {false,SPR_SCHABB_W2,8,T_Schabb,NULL,&s_schabbchase3};\r
+statetype s_schabbchase3 = {false,SPR_SCHABB_W3,10,T_Schabb,NULL,&s_schabbchase3s};\r
+statetype s_schabbchase3s = {false,SPR_SCHABB_W3,3,NULL,NULL,&s_schabbchase4};\r
+statetype s_schabbchase4 = {false,SPR_SCHABB_W4,8,T_Schabb,NULL,&s_schabbchase1};\r
+\r
+statetype s_schabbdeathcam = {false,SPR_SCHABB_W1,1,NULL,NULL,&s_schabbdie1};\r
+\r
+statetype s_schabbdie1 = {false,SPR_SCHABB_W1,10,NULL,A_DeathScream,&s_schabbdie2};\r
+statetype s_schabbdie2 = {false,SPR_SCHABB_W1,10,NULL,NULL,&s_schabbdie3};\r
+statetype s_schabbdie3 = {false,SPR_SCHABB_DIE1,10,NULL,NULL,&s_schabbdie4};\r
+statetype s_schabbdie4 = {false,SPR_SCHABB_DIE2,10,NULL,NULL,&s_schabbdie5};\r
+statetype s_schabbdie5 = {false,SPR_SCHABB_DIE3,10,NULL,NULL,&s_schabbdie6};\r
+statetype s_schabbdie6 = {false,SPR_SCHABB_DEAD,20,NULL,A_StartDeathCam,&s_schabbdie6};\r
+\r
+statetype s_schabbshoot1 = {false,SPR_SCHABB_SHOOT1,30,NULL,NULL,&s_schabbshoot2};\r
+statetype s_schabbshoot2 = {false,SPR_SCHABB_SHOOT2,10,NULL,T_SchabbThrow,&s_schabbchase1};\r
+\r
+statetype s_needle1 = {false,SPR_HYPO1,6,T_Projectile,NULL,&s_needle2};\r
+statetype s_needle2 = {false,SPR_HYPO2,6,T_Projectile,NULL,&s_needle3};\r
+statetype s_needle3 = {false,SPR_HYPO3,6,T_Projectile,NULL,&s_needle4};\r
+statetype s_needle4 = {false,SPR_HYPO4,6,T_Projectile,NULL,&s_needle1};\r
+\r
+\r
+//\r
+// gift\r
+//\r
+extern statetype s_giftstand;\r
+\r
+extern statetype s_giftchase1;\r
+extern statetype s_giftchase1s;\r
+extern statetype s_giftchase2;\r
+extern statetype s_giftchase3;\r
+extern statetype s_giftchase3s;\r
+extern statetype s_giftchase4;\r
+\r
+extern statetype s_giftdie1;\r
+extern statetype s_giftdie2;\r
+extern statetype s_giftdie3;\r
+extern statetype s_giftdie4;\r
+extern statetype s_giftdie5;\r
+extern statetype s_giftdie6;\r
+\r
+extern statetype s_giftshoot1;\r
+extern statetype s_giftshoot2;\r
+\r
+extern statetype s_needle1;\r
+extern statetype s_needle2;\r
+extern statetype s_needle3;\r
+extern statetype s_needle4;\r
+\r
+extern statetype s_giftdeathcam;\r
+\r
+extern statetype s_boom1;\r
+extern statetype s_boom2;\r
+extern statetype s_boom3;\r
+\r
+\r
+statetype s_giftstand = {false,SPR_GIFT_W1,0,T_Stand,NULL,&s_giftstand};\r
+\r
+statetype s_giftchase1 = {false,SPR_GIFT_W1,10,T_Gift,NULL,&s_giftchase1s};\r
+statetype s_giftchase1s = {false,SPR_GIFT_W1,3,NULL,NULL,&s_giftchase2};\r
+statetype s_giftchase2 = {false,SPR_GIFT_W2,8,T_Gift,NULL,&s_giftchase3};\r
+statetype s_giftchase3 = {false,SPR_GIFT_W3,10,T_Gift,NULL,&s_giftchase3s};\r
+statetype s_giftchase3s = {false,SPR_GIFT_W3,3,NULL,NULL,&s_giftchase4};\r
+statetype s_giftchase4 = {false,SPR_GIFT_W4,8,T_Gift,NULL,&s_giftchase1};\r
+\r
+statetype s_giftdeathcam = {false,SPR_GIFT_W1,1,NULL,NULL,&s_giftdie1};\r
+\r
+statetype s_giftdie1 = {false,SPR_GIFT_W1,1,NULL,A_DeathScream,&s_giftdie2};\r
+statetype s_giftdie2 = {false,SPR_GIFT_W1,10,NULL,NULL,&s_giftdie3};\r
+statetype s_giftdie3 = {false,SPR_GIFT_DIE1,10,NULL,NULL,&s_giftdie4};\r
+statetype s_giftdie4 = {false,SPR_GIFT_DIE2,10,NULL,NULL,&s_giftdie5};\r
+statetype s_giftdie5 = {false,SPR_GIFT_DIE3,10,NULL,NULL,&s_giftdie6};\r
+statetype s_giftdie6 = {false,SPR_GIFT_DEAD,20,NULL,A_StartDeathCam,&s_giftdie6};\r
+\r
+statetype s_giftshoot1 = {false,SPR_GIFT_SHOOT1,30,NULL,NULL,&s_giftshoot2};\r
+statetype s_giftshoot2 = {false,SPR_GIFT_SHOOT2,10,NULL,T_GiftThrow,&s_giftchase1};\r
+\r
+\r
+//\r
+// fat\r
+//\r
+extern statetype s_fatstand;\r
+\r
+extern statetype s_fatchase1;\r
+extern statetype s_fatchase1s;\r
+extern statetype s_fatchase2;\r
+extern statetype s_fatchase3;\r
+extern statetype s_fatchase3s;\r
+extern statetype s_fatchase4;\r
+\r
+extern statetype s_fatdie1;\r
+extern statetype s_fatdie2;\r
+extern statetype s_fatdie3;\r
+extern statetype s_fatdie4;\r
+extern statetype s_fatdie5;\r
+extern statetype s_fatdie6;\r
+\r
+extern statetype s_fatshoot1;\r
+extern statetype s_fatshoot2;\r
+extern statetype s_fatshoot3;\r
+extern statetype s_fatshoot4;\r
+extern statetype s_fatshoot5;\r
+extern statetype s_fatshoot6;\r
+\r
+extern statetype s_needle1;\r
+extern statetype s_needle2;\r
+extern statetype s_needle3;\r
+extern statetype s_needle4;\r
+\r
+extern statetype s_fatdeathcam;\r
+\r
+\r
+statetype s_fatstand = {false,SPR_FAT_W1,0,T_Stand,NULL,&s_fatstand};\r
+\r
+statetype s_fatchase1 = {false,SPR_FAT_W1,10,T_Fat,NULL,&s_fatchase1s};\r
+statetype s_fatchase1s = {false,SPR_FAT_W1,3,NULL,NULL,&s_fatchase2};\r
+statetype s_fatchase2 = {false,SPR_FAT_W2,8,T_Fat,NULL,&s_fatchase3};\r
+statetype s_fatchase3 = {false,SPR_FAT_W3,10,T_Fat,NULL,&s_fatchase3s};\r
+statetype s_fatchase3s = {false,SPR_FAT_W3,3,NULL,NULL,&s_fatchase4};\r
+statetype s_fatchase4 = {false,SPR_FAT_W4,8,T_Fat,NULL,&s_fatchase1};\r
+\r
+statetype s_fatdeathcam = {false,SPR_FAT_W1,1,NULL,NULL,&s_fatdie1};\r
+\r
+statetype s_fatdie1 = {false,SPR_FAT_W1,1,NULL,A_DeathScream,&s_fatdie2};\r
+statetype s_fatdie2 = {false,SPR_FAT_W1,10,NULL,NULL,&s_fatdie3};\r
+statetype s_fatdie3 = {false,SPR_FAT_DIE1,10,NULL,NULL,&s_fatdie4};\r
+statetype s_fatdie4 = {false,SPR_FAT_DIE2,10,NULL,NULL,&s_fatdie5};\r
+statetype s_fatdie5 = {false,SPR_FAT_DIE3,10,NULL,NULL,&s_fatdie6};\r
+statetype s_fatdie6 = {false,SPR_FAT_DEAD,20,NULL,A_StartDeathCam,&s_fatdie6};\r
+\r
+statetype s_fatshoot1 = {false,SPR_FAT_SHOOT1,30,NULL,NULL,&s_fatshoot2};\r
+statetype s_fatshoot2 = {false,SPR_FAT_SHOOT2,10,NULL,T_GiftThrow,&s_fatshoot3};\r
+statetype s_fatshoot3 = {false,SPR_FAT_SHOOT3,10,NULL,T_Shoot,&s_fatshoot4};\r
+statetype s_fatshoot4 = {false,SPR_FAT_SHOOT4,10,NULL,T_Shoot,&s_fatshoot5};\r
+statetype s_fatshoot5 = {false,SPR_FAT_SHOOT3,10,NULL,T_Shoot,&s_fatshoot6};\r
+statetype s_fatshoot6 = {false,SPR_FAT_SHOOT4,10,NULL,T_Shoot,&s_fatchase1};\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnSchabbs\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnSchabbs (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (DigiMode != sds_Off)\r
+ s_schabbdie2.tictime = 140;\r
+ else\r
+ s_schabbdie2.tictime = 5;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_schabbstand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = schabbobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_schabbs];\r
+ new->dir = south;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnGift\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnGift (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (DigiMode != sds_Off)\r
+ s_giftdie2.tictime = 140;\r
+ else\r
+ s_giftdie2.tictime = 5;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_giftstand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = giftobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_gift];\r
+ new->dir = north;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnFat\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnFat (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (DigiMode != sds_Off)\r
+ s_fatdie2.tictime = 140;\r
+ else\r
+ s_fatdie2.tictime = 5;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_fatstand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = fatobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_fat];\r
+ new->dir = south;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_SchabbThrow\r
+=\r
+=================\r
+*/\r
+\r
+void T_SchabbThrow (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+ float angle;\r
+ int iangle;\r
+\r
+ deltax = player->x - ob->x;\r
+ deltay = ob->y - player->y;\r
+ angle = atan2 (deltay,deltax);\r
+ if (angle<0)\r
+ angle = M_PI*2+angle;\r
+ iangle = angle/(M_PI*2)*ANGLES;\r
+\r
+ GetNewActor ();\r
+ new->state = &s_needle1;\r
+ new->ticcount = 1;\r
+\r
+ new->tilex = ob->tilex;\r
+ new->tiley = ob->tiley;\r
+ new->x = ob->x;\r
+ new->y = ob->y;\r
+ new->obclass = needleobj;\r
+ new->dir = nodir;\r
+ new->angle = iangle;\r
+ new->speed = 0x2000l;\r
+\r
+ new->flags = FL_NONMARK;\r
+ new->active = true;\r
+\r
+ PlaySoundLocActor (SCHABBSTHROWSND,new);\r
+}\r
+\r
+/*\r
+=================\r
+=\r
+= T_GiftThrow\r
+=\r
+=================\r
+*/\r
+\r
+void T_GiftThrow (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+ float angle;\r
+ int iangle;\r
+\r
+ deltax = player->x - ob->x;\r
+ deltay = ob->y - player->y;\r
+ angle = atan2 (deltay,deltax);\r
+ if (angle<0)\r
+ angle = M_PI*2+angle;\r
+ iangle = angle/(M_PI*2)*ANGLES;\r
+\r
+ GetNewActor ();\r
+ new->state = &s_rocket;\r
+ new->ticcount = 1;\r
+\r
+ new->tilex = ob->tilex;\r
+ new->tiley = ob->tiley;\r
+ new->x = ob->x;\r
+ new->y = ob->y;\r
+ new->obclass = rocketobj;\r
+ new->dir = nodir;\r
+ new->angle = iangle;\r
+ new->speed = 0x2000l;\r
+ new->flags = FL_NONMARK;\r
+ new->active = true;\r
+\r
+ PlaySoundLocActor (MISSILEFIRESND,new);\r
+}\r
+\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_Schabb\r
+=\r
+=================\r
+*/\r
+\r
+void T_Schabb (objtype *ob)\r
+{\r
+ long move;\r
+ int dx,dy,dist;\r
+ boolean dodge;\r
+\r
+ dodge = false;\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx : dy;\r
+\r
+ if (CheckLine(ob)) // got a shot at player?\r
+ {\r
+\r
+ if ( US_RndT() < (tics<<3) )\r
+ {\r
+ //\r
+ // go into attack frame\r
+ //\r
+ NewState (ob,&s_schabbshoot1);\r
+ return;\r
+ }\r
+ dodge = true;\r
+ }\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (ob->distance < 0)\r
+ {\r
+ //\r
+ // waiting for a door to open\r
+ //\r
+ OpenDoor (-ob->distance-1);\r
+ if (doorobjlist[-ob->distance-1].action != dr_open)\r
+ return;\r
+ ob->distance = TILEGLOBAL; // go ahead, the door is now opoen\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ if (dist <4)\r
+ SelectRunDir (ob);\r
+ else if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_Gift\r
+=\r
+=================\r
+*/\r
+\r
+void T_Gift (objtype *ob)\r
+{\r
+ long move;\r
+ int dx,dy,dist;\r
+ boolean dodge;\r
+\r
+ dodge = false;\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx : dy;\r
+\r
+ if (CheckLine(ob)) // got a shot at player?\r
+ {\r
+\r
+ if ( US_RndT() < (tics<<3) )\r
+ {\r
+ //\r
+ // go into attack frame\r
+ //\r
+ NewState (ob,&s_giftshoot1);\r
+ return;\r
+ }\r
+ dodge = true;\r
+ }\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (ob->distance < 0)\r
+ {\r
+ //\r
+ // waiting for a door to open\r
+ //\r
+ OpenDoor (-ob->distance-1);\r
+ if (doorobjlist[-ob->distance-1].action != dr_open)\r
+ return;\r
+ ob->distance = TILEGLOBAL; // go ahead, the door is now opoen\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ if (dist <4)\r
+ SelectRunDir (ob);\r
+ else if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_Fat\r
+=\r
+=================\r
+*/\r
+\r
+void T_Fat (objtype *ob)\r
+{\r
+ long move;\r
+ int dx,dy,dist;\r
+ boolean dodge;\r
+\r
+ dodge = false;\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx : dy;\r
+\r
+ if (CheckLine(ob)) // got a shot at player?\r
+ {\r
+\r
+ if ( US_RndT() < (tics<<3) )\r
+ {\r
+ //\r
+ // go into attack frame\r
+ //\r
+ NewState (ob,&s_fatshoot1);\r
+ return;\r
+ }\r
+ dodge = true;\r
+ }\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (ob->distance < 0)\r
+ {\r
+ //\r
+ // waiting for a door to open\r
+ //\r
+ OpenDoor (-ob->distance-1);\r
+ if (doorobjlist[-ob->distance-1].action != dr_open)\r
+ return;\r
+ ob->distance = TILEGLOBAL; // go ahead, the door is now opoen\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ if (dist <4)\r
+ SelectRunDir (ob);\r
+ else if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ HITLERS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+//\r
+// fake\r
+//\r
+extern statetype s_fakestand;\r
+\r
+extern statetype s_fakechase1;\r
+extern statetype s_fakechase1s;\r
+extern statetype s_fakechase2;\r
+extern statetype s_fakechase3;\r
+extern statetype s_fakechase3s;\r
+extern statetype s_fakechase4;\r
+\r
+extern statetype s_fakedie1;\r
+extern statetype s_fakedie2;\r
+extern statetype s_fakedie3;\r
+extern statetype s_fakedie4;\r
+extern statetype s_fakedie5;\r
+extern statetype s_fakedie6;\r
+\r
+extern statetype s_fakeshoot1;\r
+extern statetype s_fakeshoot2;\r
+extern statetype s_fakeshoot3;\r
+extern statetype s_fakeshoot4;\r
+extern statetype s_fakeshoot5;\r
+extern statetype s_fakeshoot6;\r
+extern statetype s_fakeshoot7;\r
+extern statetype s_fakeshoot8;\r
+extern statetype s_fakeshoot9;\r
+\r
+extern statetype s_fire1;\r
+extern statetype s_fire2;\r
+\r
+statetype s_fakestand = {false,SPR_FAKE_W1,0,T_Stand,NULL,&s_fakestand};\r
+\r
+statetype s_fakechase1 = {false,SPR_FAKE_W1,10,T_Fake,NULL,&s_fakechase1s};\r
+statetype s_fakechase1s = {false,SPR_FAKE_W1,3,NULL,NULL,&s_fakechase2};\r
+statetype s_fakechase2 = {false,SPR_FAKE_W2,8,T_Fake,NULL,&s_fakechase3};\r
+statetype s_fakechase3 = {false,SPR_FAKE_W3,10,T_Fake,NULL,&s_fakechase3s};\r
+statetype s_fakechase3s = {false,SPR_FAKE_W3,3,NULL,NULL,&s_fakechase4};\r
+statetype s_fakechase4 = {false,SPR_FAKE_W4,8,T_Fake,NULL,&s_fakechase1};\r
+\r
+statetype s_fakedie1 = {false,SPR_FAKE_DIE1,10,NULL,A_DeathScream,&s_fakedie2};\r
+statetype s_fakedie2 = {false,SPR_FAKE_DIE2,10,NULL,NULL,&s_fakedie3};\r
+statetype s_fakedie3 = {false,SPR_FAKE_DIE3,10,NULL,NULL,&s_fakedie4};\r
+statetype s_fakedie4 = {false,SPR_FAKE_DIE4,10,NULL,NULL,&s_fakedie5};\r
+statetype s_fakedie5 = {false,SPR_FAKE_DIE5,10,NULL,NULL,&s_fakedie6};\r
+statetype s_fakedie6 = {false,SPR_FAKE_DEAD,0,NULL,NULL,&s_fakedie6};\r
+\r
+statetype s_fakeshoot1 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot2};\r
+statetype s_fakeshoot2 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot3};\r
+statetype s_fakeshoot3 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot4};\r
+statetype s_fakeshoot4 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot5};\r
+statetype s_fakeshoot5 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot6};\r
+statetype s_fakeshoot6 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot7};\r
+statetype s_fakeshoot7 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot8};\r
+statetype s_fakeshoot8 = {false,SPR_FAKE_SHOOT,8,NULL,T_FakeFire,&s_fakeshoot9};\r
+statetype s_fakeshoot9 = {false,SPR_FAKE_SHOOT,8,NULL,NULL,&s_fakechase1};\r
+\r
+statetype s_fire1 = {false,SPR_FIRE1,6,NULL,T_Projectile,&s_fire2};\r
+statetype s_fire2 = {false,SPR_FIRE2,6,NULL,T_Projectile,&s_fire1};\r
+\r
+//\r
+// hitler\r
+//\r
+extern statetype s_mechachase1;\r
+extern statetype s_mechachase1s;\r
+extern statetype s_mechachase2;\r
+extern statetype s_mechachase3;\r
+extern statetype s_mechachase3s;\r
+extern statetype s_mechachase4;\r
+\r
+extern statetype s_mechadie1;\r
+extern statetype s_mechadie2;\r
+extern statetype s_mechadie3;\r
+extern statetype s_mechadie4;\r
+\r
+extern statetype s_mechashoot1;\r
+extern statetype s_mechashoot2;\r
+extern statetype s_mechashoot3;\r
+extern statetype s_mechashoot4;\r
+extern statetype s_mechashoot5;\r
+extern statetype s_mechashoot6;\r
+\r
+\r
+extern statetype s_hitlerchase1;\r
+extern statetype s_hitlerchase1s;\r
+extern statetype s_hitlerchase2;\r
+extern statetype s_hitlerchase3;\r
+extern statetype s_hitlerchase3s;\r
+extern statetype s_hitlerchase4;\r
+\r
+extern statetype s_hitlerdie1;\r
+extern statetype s_hitlerdie2;\r
+extern statetype s_hitlerdie3;\r
+extern statetype s_hitlerdie4;\r
+extern statetype s_hitlerdie5;\r
+extern statetype s_hitlerdie6;\r
+extern statetype s_hitlerdie7;\r
+extern statetype s_hitlerdie8;\r
+extern statetype s_hitlerdie9;\r
+extern statetype s_hitlerdie10;\r
+\r
+extern statetype s_hitlershoot1;\r
+extern statetype s_hitlershoot2;\r
+extern statetype s_hitlershoot3;\r
+extern statetype s_hitlershoot4;\r
+extern statetype s_hitlershoot5;\r
+extern statetype s_hitlershoot6;\r
+\r
+extern statetype s_hitlerdeathcam;\r
+\r
+statetype s_mechastand = {false,SPR_MECHA_W1,0,T_Stand,NULL,&s_mechastand};\r
+\r
+statetype s_mechachase1 = {false,SPR_MECHA_W1,10,T_Chase,A_MechaSound,&s_mechachase1s};\r
+statetype s_mechachase1s = {false,SPR_MECHA_W1,6,NULL,NULL,&s_mechachase2};\r
+statetype s_mechachase2 = {false,SPR_MECHA_W2,8,T_Chase,NULL,&s_mechachase3};\r
+statetype s_mechachase3 = {false,SPR_MECHA_W3,10,T_Chase,A_MechaSound,&s_mechachase3s};\r
+statetype s_mechachase3s = {false,SPR_MECHA_W3,6,NULL,NULL,&s_mechachase4};\r
+statetype s_mechachase4 = {false,SPR_MECHA_W4,8,T_Chase,NULL,&s_mechachase1};\r
+\r
+statetype s_mechadie1 = {false,SPR_MECHA_DIE1,10,NULL,A_DeathScream,&s_mechadie2};\r
+statetype s_mechadie2 = {false,SPR_MECHA_DIE2,10,NULL,NULL,&s_mechadie3};\r
+statetype s_mechadie3 = {false,SPR_MECHA_DIE3,10,NULL,A_HitlerMorph,&s_mechadie4};\r
+statetype s_mechadie4 = {false,SPR_MECHA_DEAD,0,NULL,NULL,&s_mechadie4};\r
+\r
+statetype s_mechashoot1 = {false,SPR_MECHA_SHOOT1,30,NULL,NULL,&s_mechashoot2};\r
+statetype s_mechashoot2 = {false,SPR_MECHA_SHOOT2,10,NULL,T_Shoot,&s_mechashoot3};\r
+statetype s_mechashoot3 = {false,SPR_MECHA_SHOOT3,10,NULL,T_Shoot,&s_mechashoot4};\r
+statetype s_mechashoot4 = {false,SPR_MECHA_SHOOT2,10,NULL,T_Shoot,&s_mechashoot5};\r
+statetype s_mechashoot5 = {false,SPR_MECHA_SHOOT3,10,NULL,T_Shoot,&s_mechashoot6};\r
+statetype s_mechashoot6 = {false,SPR_MECHA_SHOOT2,10,NULL,T_Shoot,&s_mechachase1};\r
+\r
+\r
+statetype s_hitlerchase1 = {false,SPR_HITLER_W1,6,T_Chase,NULL,&s_hitlerchase1s};\r
+statetype s_hitlerchase1s = {false,SPR_HITLER_W1,4,NULL,NULL,&s_hitlerchase2};\r
+statetype s_hitlerchase2 = {false,SPR_HITLER_W2,2,T_Chase,NULL,&s_hitlerchase3};\r
+statetype s_hitlerchase3 = {false,SPR_HITLER_W3,6,T_Chase,NULL,&s_hitlerchase3s};\r
+statetype s_hitlerchase3s = {false,SPR_HITLER_W3,4,NULL,NULL,&s_hitlerchase4};\r
+statetype s_hitlerchase4 = {false,SPR_HITLER_W4,2,T_Chase,NULL,&s_hitlerchase1};\r
+\r
+statetype s_hitlerdeathcam = {false,SPR_HITLER_W1,10,NULL,NULL,&s_hitlerdie1};\r
+\r
+statetype s_hitlerdie1 = {false,SPR_HITLER_W1,1,NULL,A_DeathScream,&s_hitlerdie2};\r
+statetype s_hitlerdie2 = {false,SPR_HITLER_W1,10,NULL,NULL,&s_hitlerdie3};\r
+statetype s_hitlerdie3 = {false,SPR_HITLER_DIE1,10,NULL,A_Slurpie,&s_hitlerdie4};\r
+statetype s_hitlerdie4 = {false,SPR_HITLER_DIE2,10,NULL,NULL,&s_hitlerdie5};\r
+statetype s_hitlerdie5 = {false,SPR_HITLER_DIE3,10,NULL,NULL,&s_hitlerdie6};\r
+statetype s_hitlerdie6 = {false,SPR_HITLER_DIE4,10,NULL,NULL,&s_hitlerdie7};\r
+statetype s_hitlerdie7 = {false,SPR_HITLER_DIE5,10,NULL,NULL,&s_hitlerdie8};\r
+statetype s_hitlerdie8 = {false,SPR_HITLER_DIE6,10,NULL,NULL,&s_hitlerdie9};\r
+statetype s_hitlerdie9 = {false,SPR_HITLER_DIE7,10,NULL,NULL,&s_hitlerdie10};\r
+statetype s_hitlerdie10 = {false,SPR_HITLER_DEAD,20,NULL,A_StartDeathCam,&s_hitlerdie10};\r
+\r
+statetype s_hitlershoot1 = {false,SPR_HITLER_SHOOT1,30,NULL,NULL,&s_hitlershoot2};\r
+statetype s_hitlershoot2 = {false,SPR_HITLER_SHOOT2,10,NULL,T_Shoot,&s_hitlershoot3};\r
+statetype s_hitlershoot3 = {false,SPR_HITLER_SHOOT3,10,NULL,T_Shoot,&s_hitlershoot4};\r
+statetype s_hitlershoot4 = {false,SPR_HITLER_SHOOT2,10,NULL,T_Shoot,&s_hitlershoot5};\r
+statetype s_hitlershoot5 = {false,SPR_HITLER_SHOOT3,10,NULL,T_Shoot,&s_hitlershoot6};\r
+statetype s_hitlershoot6 = {false,SPR_HITLER_SHOOT2,10,NULL,T_Shoot,&s_hitlerchase1};\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnFakeHitler\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnFakeHitler (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+\r
+ if (DigiMode != sds_Off)\r
+ s_hitlerdie2.tictime = 140;\r
+ else\r
+ s_hitlerdie2.tictime = 5;\r
+\r
+ SpawnNewObj (tilex,tiley,&s_fakestand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = fakeobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_fake];\r
+ new->dir = north;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnHitler\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnHitler (int tilex, int tiley)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ if (DigiMode != sds_Off)\r
+ s_hitlerdie2.tictime = 140;\r
+ else\r
+ s_hitlerdie2.tictime = 5;\r
+\r
+\r
+ SpawnNewObj (tilex,tiley,&s_mechastand);\r
+ new->speed = SPDPATROL;\r
+\r
+ new->obclass = mechahitlerobj;\r
+ new->hitpoints = starthitpoints[gamestate.difficulty][en_hitler];\r
+ new->dir = south;\r
+ new->flags |= FL_SHOOTABLE|FL_AMBUSH;\r
+ if (!loadedgame)\r
+ gamestate.killtotal++;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= A_HitlerMorph\r
+=\r
+===============\r
+*/\r
+\r
+void A_HitlerMorph (objtype *ob)\r
+{\r
+ unsigned far *map,tile,hitpoints[4]={500,700,800,900};\r
+\r
+\r
+ SpawnNewObj (ob->tilex,ob->tiley,&s_hitlerchase1);\r
+ new->speed = SPDPATROL*5;\r
+\r
+ new->x = ob->x;\r
+ new->y = ob->y;\r
+\r
+ new->distance = ob->distance;\r
+ new->dir = ob->dir;\r
+ new->flags = ob->flags | FL_SHOOTABLE;\r
+\r
+ new->obclass = realhitlerobj;\r
+ new->hitpoints = hitpoints[gamestate.difficulty];\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////\r
+//\r
+// A_MechaSound\r
+// A_Slurpie\r
+//\r
+////////////////////////////////////////////////////////\r
+void A_MechaSound (objtype *ob)\r
+{\r
+ if (areabyplayer[ob->areanumber])\r
+ PlaySoundLocActor (MECHSTEPSND,ob);\r
+}\r
+\r
+\r
+#pragma argsused\r
+void A_Slurpie (objtype *ob)\r
+{\r
+ SD_PlaySound(SLURPIESND);\r
+}\r
+\r
+/*\r
+=================\r
+=\r
+= T_FakeFire\r
+=\r
+=================\r
+*/\r
+\r
+void T_FakeFire (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+ float angle;\r
+ int iangle;\r
+\r
+ deltax = player->x - ob->x;\r
+ deltay = ob->y - player->y;\r
+ angle = atan2 (deltay,deltax);\r
+ if (angle<0)\r
+ angle = M_PI*2+angle;\r
+ iangle = angle/(M_PI*2)*ANGLES;\r
+\r
+ GetNewActor ();\r
+ new->state = &s_fire1;\r
+ new->ticcount = 1;\r
+\r
+ new->tilex = ob->tilex;\r
+ new->tiley = ob->tiley;\r
+ new->x = ob->x;\r
+ new->y = ob->y;\r
+ new->dir = nodir;\r
+ new->angle = iangle;\r
+ new->obclass = fireobj;\r
+ new->speed = 0x1200l;\r
+ new->flags = FL_NEVERMARK;\r
+ new->active = true;\r
+\r
+ PlaySoundLocActor (FLAMETHROWERSND,new);\r
+}\r
+\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_Fake\r
+=\r
+=================\r
+*/\r
+\r
+void T_Fake (objtype *ob)\r
+{\r
+ long move;\r
+ int dx,dy,dist;\r
+ boolean dodge;\r
+\r
+ if (CheckLine(ob)) // got a shot at player?\r
+ {\r
+ if ( US_RndT() < (tics<<1) )\r
+ {\r
+ //\r
+ // go into attack frame\r
+ //\r
+ NewState (ob,&s_fakeshoot1);\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ SelectDodgeDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ SelectDodgeDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+#endif\r
+/*\r
+============================================================================\r
+\r
+ STAND\r
+\r
+============================================================================\r
+*/\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_Stand\r
+=\r
+===============\r
+*/\r
+\r
+void T_Stand (objtype *ob)\r
+{\r
+ SightPlayer (ob);\r
+}\r
+\r
+\r
+/*\r
+============================================================================\r
+\r
+ CHASE\r
+\r
+============================================================================\r
+*/\r
+\r
+/*\r
+=================\r
+=\r
+= T_Chase\r
+=\r
+=================\r
+*/\r
+\r
+void T_Chase (objtype *ob)\r
+{\r
+ long move;\r
+ int dx,dy,dist,chance;\r
+ boolean dodge;\r
+\r
+ if (gamestate.victoryflag)\r
+ return;\r
+\r
+ dodge = false;\r
+ if (CheckLine(ob)) // got a shot at player?\r
+ {\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx : dy;\r
+ if (!dist || (dist==1 && ob->distance<0x4000) )\r
+ chance = 300;\r
+ else\r
+ chance = (tics<<4)/dist;\r
+\r
+ if ( US_RndT()<chance)\r
+ {\r
+ //\r
+ // go into attack frame\r
+ //\r
+ switch (ob->obclass)\r
+ {\r
+ case guardobj:\r
+ NewState (ob,&s_grdshoot1);\r
+ break;\r
+ case officerobj:\r
+ NewState (ob,&s_ofcshoot1);\r
+ break;\r
+ case mutantobj:\r
+ NewState (ob,&s_mutshoot1);\r
+ break;\r
+ case ssobj:\r
+ NewState (ob,&s_ssshoot1);\r
+ break;\r
+#ifndef SPEAR\r
+ case bossobj:\r
+ NewState (ob,&s_bossshoot1);\r
+ break;\r
+ case gretelobj:\r
+ NewState (ob,&s_gretelshoot1);\r
+ break;\r
+ case mechahitlerobj:\r
+ NewState (ob,&s_mechashoot1);\r
+ break;\r
+ case realhitlerobj:\r
+ NewState (ob,&s_hitlershoot1);\r
+ break;\r
+#else\r
+ case angelobj:\r
+ NewState (ob,&s_angelshoot1);\r
+ break;\r
+ case transobj:\r
+ NewState (ob,&s_transshoot1);\r
+ break;\r
+ case uberobj:\r
+ NewState (ob,&s_ubershoot1);\r
+ break;\r
+ case willobj:\r
+ NewState (ob,&s_willshoot1);\r
+ break;\r
+ case deathobj:\r
+ NewState (ob,&s_deathshoot1);\r
+ break;\r
+#endif\r
+ }\r
+ return;\r
+ }\r
+ dodge = true;\r
+ }\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (ob->distance < 0)\r
+ {\r
+ //\r
+ // waiting for a door to open\r
+ //\r
+ OpenDoor (-ob->distance-1);\r
+ if (doorobjlist[-ob->distance-1].action != dr_open)\r
+ return;\r
+ ob->distance = TILEGLOBAL; // go ahead, the door is now opoen\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ if (dodge)\r
+ SelectDodgeDir (ob);\r
+ else\r
+ SelectChaseDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= T_Ghosts\r
+=\r
+=================\r
+*/\r
+\r
+void T_Ghosts (objtype *ob)\r
+{\r
+ long move;\r
+\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ SelectChaseDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ SelectChaseDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+/*\r
+=================\r
+=\r
+= T_DogChase\r
+=\r
+=================\r
+*/\r
+\r
+void T_DogChase (objtype *ob)\r
+{\r
+ long move;\r
+ int dist,chance;\r
+ long dx,dy;\r
+\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ SelectDodgeDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ //\r
+ // check for byte range\r
+ //\r
+ dx = player->x - ob->x;\r
+ if (dx<0)\r
+ dx = -dx;\r
+ dx -= move;\r
+ if (dx <= MINACTORDIST)\r
+ {\r
+ dy = player->y - ob->y;\r
+ if (dy<0)\r
+ dy = -dy;\r
+ dy -= move;\r
+ if (dy <= MINACTORDIST)\r
+ {\r
+ NewState (ob,&s_dogjump1);\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // reached goal tile, so select another one\r
+ //\r
+\r
+ //\r
+ // fix position to account for round off during moving\r
+ //\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+\r
+ move -= ob->distance;\r
+\r
+ SelectDodgeDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // object is blocked in\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+/*\r
+============================================================================\r
+\r
+ PATH\r
+\r
+============================================================================\r
+*/\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SelectPathDir\r
+=\r
+===============\r
+*/\r
+\r
+void SelectPathDir (objtype *ob)\r
+{\r
+ unsigned spot;\r
+\r
+ spot = MAPSPOT(ob->tilex,ob->tiley,1)-ICONARROWS;\r
+\r
+ if (spot<8)\r
+ {\r
+ // new direction\r
+ ob->dir = spot;\r
+ }\r
+\r
+ ob->distance = TILEGLOBAL;\r
+\r
+ if (!TryWalk (ob))\r
+ ob->dir = nodir;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_Path\r
+=\r
+===============\r
+*/\r
+\r
+void T_Path (objtype *ob)\r
+{\r
+ long move;\r
+ long deltax,deltay,size;\r
+\r
+ if (SightPlayer (ob))\r
+ return;\r
+\r
+ if (ob->dir == nodir)\r
+ {\r
+ SelectPathDir (ob);\r
+ if (ob->dir == nodir)\r
+ return; // all movement is blocked\r
+ }\r
+\r
+\r
+ move = ob->speed*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (ob->distance < 0)\r
+ {\r
+ //\r
+ // waiting for a door to open\r
+ //\r
+ OpenDoor (-ob->distance-1);\r
+ if (doorobjlist[-ob->distance-1].action != dr_open)\r
+ return;\r
+ ob->distance = TILEGLOBAL; // go ahead, the door is now opoen\r
+ }\r
+\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+ if (ob->tilex>MAPSIZE || ob->tiley>MAPSIZE)\r
+ {\r
+ sprintf (str,"T_Path hit a wall at %u,%u, dir %u"\r
+ ,ob->tilex,ob->tiley,ob->dir);\r
+ Quit (str);\r
+ }\r
+\r
+\r
+\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+ move -= ob->distance;\r
+\r
+ SelectPathDir (ob);\r
+\r
+ if (ob->dir == nodir)\r
+ return; // all movement is blocked\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ FIGHT\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_Shoot\r
+=\r
+= Try to damage the player, based on skill level and player's speed\r
+=\r
+===============\r
+*/\r
+\r
+void T_Shoot (objtype *ob)\r
+{\r
+ int dx,dy,dist;\r
+ int hitchance,damage;\r
+\r
+ hitchance = 128;\r
+\r
+ if (!areabyplayer[ob->areanumber])\r
+ return;\r
+\r
+ if (!CheckLine (ob)) // player is behind a wall\r
+ return;\r
+\r
+ dx = abs(ob->tilex - player->tilex);\r
+ dy = abs(ob->tiley - player->tiley);\r
+ dist = dx>dy ? dx:dy;\r
+\r
+ if (ob->obclass == ssobj || ob->obclass == bossobj)\r
+ dist = dist*2/3; // ss are better shots\r
+\r
+ if (thrustspeed >= RUNSPEED)\r
+ {\r
+ if (ob->flags&FL_VISABLE)\r
+ hitchance = 160-dist*16; // player can see to dodge\r
+ else\r
+ hitchance = 160-dist*8;\r
+ }\r
+ else\r
+ {\r
+ if (ob->flags&FL_VISABLE)\r
+ hitchance = 256-dist*16; // player can see to dodge\r
+ else\r
+ hitchance = 256-dist*8;\r
+ }\r
+\r
+// see if the shot was a hit\r
+\r
+ if (US_RndT()<hitchance)\r
+ {\r
+ if (dist<2)\r
+ damage = US_RndT()>>2;\r
+ else if (dist<4)\r
+ damage = US_RndT()>>3;\r
+ else\r
+ damage = US_RndT()>>4;\r
+\r
+ TakeDamage (damage,ob);\r
+ }\r
+\r
+ switch(ob->obclass)\r
+ {\r
+ case ssobj:\r
+ PlaySoundLocActor(SSFIRESND,ob);\r
+ break;\r
+#ifndef SPEAR\r
+ case giftobj:\r
+ case fatobj:\r
+ PlaySoundLocActor(MISSILEFIRESND,ob);\r
+ break;\r
+ case mechahitlerobj:\r
+ case realhitlerobj:\r
+ case bossobj:\r
+ PlaySoundLocActor(BOSSFIRESND,ob);\r
+ break;\r
+ case schabbobj:\r
+ PlaySoundLocActor(SCHABBSTHROWSND,ob);\r
+ break;\r
+ case fakeobj:\r
+ PlaySoundLocActor(FLAMETHROWERSND,ob);\r
+ break;\r
+#endif\r
+ default:\r
+ PlaySoundLocActor(NAZIFIRESND,ob);\r
+ }\r
+\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_Bite\r
+=\r
+===============\r
+*/\r
+\r
+void T_Bite (objtype *ob)\r
+{\r
+ long dx,dy;\r
+ int hitchance,damage;\r
+\r
+\r
+ PlaySoundLocActor(DOGATTACKSND,ob); // JAB\r
+\r
+ dx = player->x - ob->x;\r
+ if (dx<0)\r
+ dx = -dx;\r
+ dx -= TILEGLOBAL;\r
+ if (dx <= MINACTORDIST)\r
+ {\r
+ dy = player->y - ob->y;\r
+ if (dy<0)\r
+ dy = -dy;\r
+ dy -= TILEGLOBAL;\r
+ if (dy <= MINACTORDIST)\r
+ {\r
+ if (US_RndT()<180)\r
+ {\r
+ TakeDamage (US_RndT()>>4,ob);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+#ifndef SPEAR\r
+/*\r
+============================================================================\r
+\r
+ BJ VICTORY\r
+\r
+============================================================================\r
+*/\r
+\r
+\r
+//\r
+// BJ victory\r
+//\r
+\r
+void T_BJRun (objtype *ob);\r
+void T_BJJump (objtype *ob);\r
+void T_BJDone (objtype *ob);\r
+void T_BJYell (objtype *ob);\r
+\r
+void T_DeathCam (objtype *ob);\r
+\r
+extern statetype s_bjrun1;\r
+extern statetype s_bjrun1s;\r
+extern statetype s_bjrun2;\r
+extern statetype s_bjrun3;\r
+extern statetype s_bjrun3s;\r
+extern statetype s_bjrun4;\r
+\r
+extern statetype s_bjjump1;\r
+extern statetype s_bjjump2;\r
+extern statetype s_bjjump3;\r
+extern statetype s_bjjump4;\r
+\r
+\r
+statetype s_bjrun1 = {false,SPR_BJ_W1,12,T_BJRun,NULL,&s_bjrun1s};\r
+statetype s_bjrun1s = {false,SPR_BJ_W1,3, NULL,NULL,&s_bjrun2};\r
+statetype s_bjrun2 = {false,SPR_BJ_W2,8,T_BJRun,NULL,&s_bjrun3};\r
+statetype s_bjrun3 = {false,SPR_BJ_W3,12,T_BJRun,NULL,&s_bjrun3s};\r
+statetype s_bjrun3s = {false,SPR_BJ_W3,3, NULL,NULL,&s_bjrun4};\r
+statetype s_bjrun4 = {false,SPR_BJ_W4,8,T_BJRun,NULL,&s_bjrun1};\r
+\r
+\r
+statetype s_bjjump1 = {false,SPR_BJ_JUMP1,14,T_BJJump,NULL,&s_bjjump2};\r
+statetype s_bjjump2 = {false,SPR_BJ_JUMP2,14,T_BJJump,T_BJYell,&s_bjjump3};\r
+statetype s_bjjump3 = {false,SPR_BJ_JUMP3,14,T_BJJump,NULL,&s_bjjump4};\r
+statetype s_bjjump4 = {false,SPR_BJ_JUMP4,300,NULL,T_BJDone,&s_bjjump4};\r
+\r
+\r
+statetype s_deathcam = {false,0,0,NULL,NULL,NULL};\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SpawnBJVictory\r
+=\r
+===============\r
+*/\r
+\r
+void SpawnBJVictory (void)\r
+{\r
+ unsigned far *map,tile;\r
+\r
+ SpawnNewObj (player->tilex,player->tiley+1,&s_bjrun1);\r
+ new->x = player->x;\r
+ new->y = player->y;\r
+ new->obclass = bjobj;\r
+ new->dir = north;\r
+ new->temp1 = 6; // tiles to run forward\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_BJRun\r
+=\r
+===============\r
+*/\r
+\r
+void T_BJRun (objtype *ob)\r
+{\r
+ long move;\r
+\r
+ move = BJRUNSPEED*tics;\r
+\r
+ while (move)\r
+ {\r
+ if (move < ob->distance)\r
+ {\r
+ MoveObj (ob,move);\r
+ break;\r
+ }\r
+\r
+\r
+ ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+ move -= ob->distance;\r
+\r
+ SelectPathDir (ob);\r
+\r
+ if ( !(--ob->temp1) )\r
+ {\r
+ NewState (ob,&s_bjjump1);\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_BJJump\r
+=\r
+===============\r
+*/\r
+\r
+void T_BJJump (objtype *ob)\r
+{\r
+ long move;\r
+\r
+ move = BJJUMPSPEED*tics;\r
+ MoveObj (ob,move);\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_BJYell\r
+=\r
+===============\r
+*/\r
+\r
+void T_BJYell (objtype *ob)\r
+{\r
+ PlaySoundLocActor(YEAHSND,ob); // JAB\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= T_BJDone\r
+=\r
+===============\r
+*/\r
+\r
+#pragma argsused\r
+void T_BJDone (objtype *ob)\r
+{\r
+ playstate = ex_victorious; // exit castle tile\r
+}\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= CheckPosition\r
+=\r
+===============\r
+*/\r
+\r
+boolean CheckPosition (objtype *ob)\r
+{\r
+ int x,y,xl,yl,xh,yh;\r
+ objtype *check;\r
+\r
+ xl = (ob->x-PLAYERSIZE) >>TILESHIFT;\r
+ yl = (ob->y-PLAYERSIZE) >>TILESHIFT;\r
+\r
+ xh = (ob->x+PLAYERSIZE) >>TILESHIFT;\r
+ yh = (ob->y+PLAYERSIZE) >>TILESHIFT;\r
+\r
+ //\r
+ // check for solid walls\r
+ //\r
+ for (y=yl;y<=yh;y++)\r
+ for (x=xl;x<=xh;x++)\r
+ {\r
+ check = actorat[x][y];\r
+ if (check && check<objlist)\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= A_StartDeathCam\r
+=\r
+===============\r
+*/\r
+\r
+void A_StartDeathCam (objtype *ob)\r
+{\r
+ long dx,dy;\r
+ float fangle;\r
+ long xmove,ymove;\r
+ long dist;\r
+ int temp,i;\r
+\r
+ FinishPaletteShifts ();\r
+\r
+ VW_WaitVBL (100);\r
+\r
+ if (gamestate.victoryflag)\r
+ {\r
+ playstate = ex_victorious; // exit castle tile\r
+ return;\r
+ }\r
+\r
+ gamestate.victoryflag = true;\r
+ VW_Bar (0,0,320,200-STATUSLINES,127);\r
+ FizzleFade(bufferofs,displayofs,320,200-STATUSLINES,70,false);\r
+\r
+ PM_UnlockMainMem ();\r
+ CA_UpLevel ();\r
+ CacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END);\r
+ #ifdef JAPAN\r
+ #ifndef JAPDEMO\r
+ CA_CacheScreen(C_LETSSEEPIC);\r
+ #endif\r
+ #else\r
+ Write(0,7,STR_SEEAGAIN);\r
+ #endif\r
+ CA_DownLevel ();\r
+ PM_CheckMainMem ();\r
+\r
+ VW_UpdateScreen ();\r
+\r
+ IN_UserInput(300);\r
+\r
+//\r
+// line angle up exactly\r
+//\r
+ NewState (player,&s_deathcam);\r
+\r
+ player->x = gamestate.killx;\r
+ player->y = gamestate.killy;\r
+\r
+ dx = ob->x - player->x;\r
+ dy = player->y - ob->y;\r
+\r
+ fangle = atan2(dy,dx); // returns -pi to pi\r
+ if (fangle<0)\r
+ fangle = M_PI*2+fangle;\r
+\r
+ player->angle = fangle/(M_PI*2)*ANGLES;\r
+\r
+//\r
+// try to position as close as possible without being in a wall\r
+//\r
+ dist = 0x14000l;\r
+ do\r
+ {\r
+ xmove = FixedByFrac(dist,costable[player->angle]);\r
+ ymove = -FixedByFrac(dist,sintable[player->angle]);\r
+\r
+ player->x = ob->x - xmove;\r
+ player->y = ob->y - ymove;\r
+ dist += 0x1000;\r
+\r
+ } while (!CheckPosition (player));\r
+ plux = player->x >> UNSIGNEDSHIFT; // scale to fit in unsigned\r
+ pluy = player->y >> UNSIGNEDSHIFT;\r
+ player->tilex = player->x >> TILESHIFT; // scale to tile values\r
+ player->tiley = player->y >> TILESHIFT;\r
+\r
+//\r
+// go back to the game\r
+//\r
+ temp = bufferofs;\r
+ for (i=0;i<3;i++)\r
+ {\r
+ bufferofs = screenloc[i];\r
+ DrawPlayBorder ();\r
+ }\r
+ bufferofs = temp;\r
+\r
+ fizzlein = true;\r
+ switch (ob->obclass)\r
+ {\r
+#ifndef SPEAR\r
+ case schabbobj:\r
+ NewState (ob,&s_schabbdeathcam);\r
+ break;\r
+ case realhitlerobj:\r
+ NewState (ob,&s_hitlerdeathcam);\r
+ break;\r
+ case giftobj:\r
+ NewState (ob,&s_giftdeathcam);\r
+ break;\r
+ case fatobj:\r
+ NewState (ob,&s_fatdeathcam);\r
+ break;\r
+#endif\r
+ }\r
+\r
+}\r
+\r
+#endif\r
--- /dev/null
+; JABHACK.ASM\r
+\r
+.386C\r
+IDEAL\r
+MODEL MEDIUM\r
+\r
+EXTRN LDIV@:far\r
+\r
+;============================================================================\r
+\r
+DATASEG\r
+\r
+;============================================================================\r
+\r
+CODESEG\r
+\r
+; Hacked up Juan Jimenez's code a bit to just return 386/not 386\r
+PROC _CheckIs386\r
+PUBLIC _CheckIs386\r
+\r
+;hack to never look for a 386, for benchmark comparisons of same code on all CPUs\r
+; pushf ; Save flag registers, we use them here\r
+; xor ax,ax ; Clear AX and...\r
+; push ax ; ...push it onto the stack\r
+; popf ; Pop 0 into flag registers (all bits to 0),\r
+; pushf ; attempting to set bits 12-15 of flags to 0's\r
+; pop ax ; Recover the save flags\r
+; and ax,08000h ; If bits 12-15 of flags are set to\r
+; cmp ax,08000h ; zero then it's 8088/86 or 80188/186\r
+; jz not386\r
+;\r
+; mov ax,07000h ; Try to set flag bits 12-14 to 1's\r
+; push ax ; Push the test value onto the stack\r
+; popf ; Pop it into the flag register\r
+; pushf ; Push it back onto the stack\r
+; pop ax ; Pop it into AX for check\r
+; and ax,07000h ; if bits 12-14 are cleared then\r
+; jz not386 ; the chip is an 80286\r
+;\r
+; mov ax,1 ; We now assume it's a 80386 or better\r
+; popf\r
+; retf\r
+;end benchmark hack\r
+\r
+not386:\r
+ xor ax,ax\r
+ popf\r
+ retf\r
+\r
+ ENDP\r
+\r
+\r
+PROC _jabhack2\r
+PUBLIC _jabhack2\r
+\r
+ push es\r
+\r
+ mov ax,seg LDIV@\r
+ mov es,ax\r
+ mov ax,9090h ;Two NOP's\r
+ mov [WORD FAR es:LDIV@],ax ;Patch over XOR AX,AX\r
+ mov [WORD FAR es:LDIV@+2],ax ;and over JMP SHORT COMMON\r
+\r
+ pop es\r
+ retf\r
+\r
+ ENDP\r
+\r
+ END\r
--- /dev/null
+// WL_DEBUG.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+#include <BIOS.H>\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define VIEWTILEX (viewwidth/16)\r
+#define VIEWTILEY (viewheight/16)\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+int DebugKeys (void);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+int maporgx;\r
+int maporgy;\r
+enum {mapview,tilemapview,actoratview,visview} viewtype;\r
+\r
+void ViewMap (void);\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= DebugMemory\r
+=\r
+==================\r
+*/\r
+\r
+void DebugMemory (void)\r
+{\r
+ int i;\r
+ char scratch[80],str[10];\r
+ long mem;\r
+ spritetype _seg *block;\r
+\r
+ CenterWindow (16,7);\r
+\r
+ US_CPrint ("Memory Usage");\r
+ US_CPrint ("------------");\r
+ US_Print ("Total :");\r
+ US_PrintUnsigned (mminfo.mainmem/1024);\r
+ US_Print ("k\nFree :");\r
+ US_PrintUnsigned (MM_UnusedMemory()/1024);\r
+ US_Print ("k\nWith purge:");\r
+ US_PrintUnsigned (MM_TotalFree()/1024);\r
+ US_Print ("k\n");\r
+ VW_UpdateScreen();\r
+ IN_Ack ();\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= CountObjects\r
+=\r
+==================\r
+*/\r
+\r
+void CountObjects (void)\r
+{\r
+ int i,total,count,active,inactive,doors;\r
+ objtype *obj;\r
+\r
+ CenterWindow (16,7);\r
+ active = inactive = count = doors = 0;\r
+\r
+ US_Print ("Total statics :");\r
+ total = laststatobj-&statobjlist[0];\r
+ US_PrintUnsigned (total);\r
+\r
+ US_Print ("\nIn use statics:");\r
+ for (i=0;i<total;i++)\r
+ if (statobjlist[i].shapenum != -1)\r
+ count++;\r
+ else\r
+ doors++; //debug\r
+ US_PrintUnsigned (count);\r
+\r
+ US_Print ("\nDoors :");\r
+ US_PrintUnsigned (doornum);\r
+\r
+ for (obj=player->next;obj;obj=obj->next)\r
+ {\r
+ if (obj->active)\r
+ active++;\r
+ else\r
+ inactive++;\r
+ }\r
+\r
+ US_Print ("\nTotal actors :");\r
+ US_PrintUnsigned (active+inactive);\r
+\r
+ US_Print ("\nActive actors :");\r
+ US_PrintUnsigned (active);\r
+\r
+ VW_UpdateScreen();\r
+ IN_Ack ();\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+================\r
+=\r
+= PicturePause\r
+=\r
+================\r
+*/\r
+\r
+void PicturePause (void)\r
+{\r
+ int i;\r
+ byte p;\r
+ unsigned x;\r
+ byte far *dest,far *src;\r
+ memptr buffer;\r
+\r
+ VW_ColorBorder (15);\r
+ FinishPaletteShifts ();\r
+\r
+ LastScan = 0;\r
+ while (!LastScan)\r
+ ;\r
+ if (LastScan != sc_Enter)\r
+ {\r
+ VW_ColorBorder (0);\r
+ return;\r
+ }\r
+\r
+ VW_ColorBorder (1);\r
+ VW_SetScreen (0,0);\r
+//\r
+// vga stuff...\r
+//\r
+\r
+ ClearMemory ();\r
+ CA_SetAllPurge();\r
+ MM_GetPtr (&buffer,64000);\r
+ for (p=0;p<4;p++)\r
+ {\r
+ src = MK_FP(0xa000,displayofs);\r
+ dest = (byte far *)buffer+p;\r
+ VGAREADMAP(p);\r
+ for (x=0;x<16000;x++,dest+=4)\r
+ *dest = *src++;\r
+ }\r
+\r
+\r
+#if 0\r
+ for (p=0;p<4;p++)\r
+ {\r
+ src = MK_FP(0xa000,0);\r
+ dest = (byte far *)buffer+51200+p;\r
+ VGAREADMAP(p);\r
+ for (x=0;x<3200;x++,dest+=4)\r
+ *dest = *src++;\r
+ }\r
+#endif\r
+\r
+ asm mov ax,0x13\r
+ asm int 0x10\r
+\r
+ dest = MK_FP(0xa000,0);\r
+ _fmemcpy (dest,buffer,64000);\r
+\r
+ VL_SetPalette (&gamepal);\r
+\r
+\r
+ IN_Shutdown ();\r
+\r
+ VW_WaitVBL(70);\r
+ bioskey(0);\r
+ VW_WaitVBL(70);\r
+ Quit (NULL);\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+================\r
+=\r
+= ShapeTest\r
+=\r
+================\r
+*/\r
+\r
+#pragma warn -pia\r
+void ShapeTest (void)\r
+{\r
+extern word NumDigi;\r
+extern word _seg *DigiList;\r
+static char buf[10];\r
+\r
+ boolean done;\r
+ ScanCode scan;\r
+ int i,j,k,x;\r
+ longword l;\r
+ memptr addr;\r
+ PageListStruct far *page;\r
+\r
+ CenterWindow(20,16);\r
+ VW_UpdateScreen();\r
+ for (i = 0,done = false;!done;)\r
+ {\r
+ US_ClearWindow();\r
+// sound = -1;\r
+\r
+ page = &PMPages[i];\r
+ US_Print(" Page #");\r
+ US_PrintUnsigned(i);\r
+ if (i < PMSpriteStart)\r
+ US_Print(" (Wall)");\r
+ else if (i < PMSoundStart)\r
+ US_Print(" (Sprite)");\r
+ else if (i == ChunksInFile - 1)\r
+ US_Print(" (Sound Info)");\r
+ else\r
+ US_Print(" (Sound)");\r
+\r
+ US_Print("\n XMS: ");\r
+ if (page->xmsPage != -1)\r
+ US_PrintUnsigned(page->xmsPage);\r
+ else\r
+ US_Print("No");\r
+\r
+ US_Print("\n Main: ");\r
+ if (page->mainPage != -1)\r
+ US_PrintUnsigned(page->mainPage);\r
+ else if (page->emsPage != -1)\r
+ {\r
+ US_Print("EMS ");\r
+ US_PrintUnsigned(page->emsPage);\r
+ }\r
+ else\r
+ US_Print("No");\r
+\r
+ US_Print("\n Last hit: ");\r
+ US_PrintUnsigned(page->lastHit);\r
+\r
+ US_Print("\n Address: ");\r
+ addr = PM_GetPageAddress(i);\r
+ sprintf(buf,"0x%04x",(word)addr);\r
+ US_Print(buf);\r
+\r
+ if (addr)\r
+ {\r
+ if (i < PMSpriteStart)\r
+ {\r
+ //\r
+ // draw the wall\r
+ //\r
+ bufferofs += 32*SCREENWIDTH;\r
+ postx = 128;\r
+ postwidth = 1;\r
+ postsource = ((long)((unsigned)addr))<<16;\r
+ for (x=0;x<64;x++,postx++,postsource+=64)\r
+ {\r
+ wallheight[postx] = 256;\r
+ FarScalePost ();\r
+ }\r
+ bufferofs -= 32*SCREENWIDTH;\r
+ }\r
+ else if (i < PMSoundStart)\r
+ {\r
+ //\r
+ // draw the sprite\r
+ //\r
+ bufferofs += 32*SCREENWIDTH;\r
+ SimpleScaleShape (160, i-PMSpriteStart, 64);\r
+ bufferofs -= 32*SCREENWIDTH;\r
+ }\r
+ else if (i == ChunksInFile - 1)\r
+ {\r
+ US_Print("\n\n Number of sounds: ");\r
+ US_PrintUnsigned(NumDigi);\r
+ for (l = j = k = 0;j < NumDigi;j++)\r
+ {\r
+ l += DigiList[(j * 2) + 1];\r
+ k += (DigiList[(j * 2) + 1] + (PMPageSize - 1)) / PMPageSize;\r
+ }\r
+ US_Print("\n Total bytes: ");\r
+ US_PrintUnsigned(l);\r
+ US_Print("\n Total pages: ");\r
+ US_PrintUnsigned(k);\r
+ }\r
+ else\r
+ {\r
+ byte far *dp = (byte far *)MK_FP(addr,0);\r
+ for (j = 0;j < NumDigi;j++)\r
+ {\r
+ k = (DigiList[(j * 2) + 1] + (PMPageSize - 1)) / PMPageSize;\r
+ if\r
+ (\r
+ (i >= PMSoundStart + DigiList[j * 2])\r
+ && (i < PMSoundStart + DigiList[j * 2] + k)\r
+ )\r
+ break;\r
+ }\r
+ if (j < NumDigi)\r
+ {\r
+// sound = j;\r
+ US_Print("\n Sound #");\r
+ US_PrintUnsigned(j);\r
+ US_Print("\n Segment #");\r
+ US_PrintUnsigned(i - PMSoundStart - DigiList[j * 2]);\r
+ }\r
+ for (j = 0;j < page->length;j += 32)\r
+ {\r
+ byte v = dp[j];\r
+ int v2 = (unsigned)v;\r
+ v2 -= 128;\r
+ v2 /= 4;\r
+ if (v2 < 0)\r
+ VWB_Vlin(WindowY + WindowH - 32 + v2,\r
+ WindowY + WindowH - 32,\r
+ WindowX + 8 + (j / 32),BLACK);\r
+ else\r
+ VWB_Vlin(WindowY + WindowH - 32,\r
+ WindowY + WindowH - 32 + v2,\r
+ WindowX + 8 + (j / 32),BLACK);\r
+ }\r
+ }\r
+ }\r
+\r
+ VW_UpdateScreen();\r
+\r
+ while (!(scan = LastScan))\r
+ SD_Poll();\r
+\r
+ IN_ClearKey(scan);\r
+ switch (scan)\r
+ {\r
+ case sc_LeftArrow:\r
+ if (i)\r
+ i--;\r
+ break;\r
+ case sc_RightArrow:\r
+ if (++i >= ChunksInFile)\r
+ i--;\r
+ break;\r
+ case sc_W: // Walls\r
+ i = 0;\r
+ break;\r
+ case sc_S: // Sprites\r
+ i = PMSpriteStart;\r
+ break;\r
+ case sc_D: // Digitized\r
+ i = PMSoundStart;\r
+ break;\r
+ case sc_I: // Digitized info\r
+ i = ChunksInFile - 1;\r
+ break;\r
+ case sc_L: // Load all pages\r
+ for (j = 0;j < ChunksInFile;j++)\r
+ PM_GetPage(j);\r
+ break;\r
+ case sc_P:\r
+// if (sound != -1)\r
+// SD_PlayDigitized(sound);\r
+ break;\r
+ case sc_Escape:\r
+ done = true;\r
+ break;\r
+ case sc_Enter:\r
+ PM_GetPage(i);\r
+ break;\r
+ }\r
+ }\r
+ SD_StopDigitized();\r
+}\r
+#pragma warn +pia\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+================\r
+=\r
+= DebugKeys\r
+=\r
+================\r
+*/\r
+\r
+int DebugKeys (void)\r
+{\r
+ boolean esc;\r
+ int level,i;\r
+\r
+ if (Keyboard[sc_B]) // B = border color\r
+ {\r
+ CenterWindow(24,3);\r
+ PrintY+=6;\r
+ US_Print(" Border color (0-15):");\r
+ VW_UpdateScreen();\r
+ esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
+ if (!esc)\r
+ {\r
+ level = atoi (str);\r
+ if (level>=0 && level<=15)\r
+ VW_ColorBorder (level);\r
+ }\r
+ return 1;\r
+ }\r
+\r
+ if (Keyboard[sc_C]) // C = count objects\r
+ {\r
+ CountObjects();\r
+ return 1;\r
+ }\r
+\r
+ if (Keyboard[sc_E]) // E = quit level\r
+ {\r
+ if (tedlevel)\r
+ Quit (NULL);\r
+ playstate = ex_completed;\r
+// gamestate.mapon++;\r
+ }\r
+\r
+ if (Keyboard[sc_F]) // F = facing spot\r
+ {\r
+ CenterWindow (14,4);\r
+ US_Print ("X:");\r
+ US_PrintUnsigned (player->x);\r
+ US_Print ("\nY:");\r
+ US_PrintUnsigned (player->y);\r
+ US_Print ("\nA:");\r
+ US_PrintUnsigned (player->angle);\r
+ VW_UpdateScreen();\r
+ IN_Ack();\r
+ return 1;\r
+ }\r
+\r
+ if (Keyboard[sc_G]) // G = god mode\r
+ {\r
+ CenterWindow (12,2);\r
+ if (godmode)\r
+ US_PrintCentered ("God mode OFF");\r
+ else\r
+ US_PrintCentered ("God mode ON");\r
+ VW_UpdateScreen();\r
+ IN_Ack();\r
+ godmode ^= 1;\r
+ return 1;\r
+ }\r
+ if (Keyboard[sc_H]) // H = hurt self\r
+ {\r
+ IN_ClearKeysDown ();\r
+ TakeDamage (16,NULL);\r
+ }\r
+ else if (Keyboard[sc_I]) // I = item cheat\r
+ {\r
+ CenterWindow (12,3);\r
+ US_PrintCentered ("Free items!");\r
+ VW_UpdateScreen();\r
+ GivePoints (100000);\r
+ HealSelf (99);\r
+ if (gamestate.bestweapon<wp_chaingun)\r
+ GiveWeapon (gamestate.bestweapon+1);\r
+ gamestate.ammo += 50;\r
+ if (gamestate.ammo > 99)\r
+ gamestate.ammo = 99;\r
+ DrawAmmo ();\r
+ IN_Ack ();\r
+ return 1;\r
+ }\r
+ else if (Keyboard[sc_M]) // M = memory info\r
+ {\r
+ DebugMemory();\r
+ return 1;\r
+ }\r
+#ifdef SPEAR\r
+ else if (Keyboard[sc_N]) // N = no clip\r
+ {\r
+ noclip^=1;\r
+ CenterWindow (18,3);\r
+ if (noclip)\r
+ US_PrintCentered ("No clipping ON");\r
+ else\r
+ US_PrintCentered ("No clipping OFF");\r
+ VW_UpdateScreen();\r
+ IN_Ack ();\r
+ return 1;\r
+ }\r
+#endif\r
+#if 0\r
+ else if (Keyboard[sc_O]) // O = overhead\r
+ {\r
+ ViewMap();\r
+ return 1;\r
+ }\r
+#endif\r
+ else if (Keyboard[sc_P]) // P = pause with no screen disruptioon\r
+ {\r
+ PicturePause ();\r
+ return 1;\r
+ }\r
+ else if (Keyboard[sc_Q]) // Q = fast quit\r
+ Quit (NULL);\r
+ else if (Keyboard[sc_S]) // S = slow motion\r
+ {\r
+ singlestep^=1;\r
+ CenterWindow (18,3);\r
+ if (singlestep)\r
+ US_PrintCentered ("Slow motion ON");\r
+ else\r
+ US_PrintCentered ("Slow motion OFF");\r
+ VW_UpdateScreen();\r
+ IN_Ack ();\r
+ return 1;\r
+ }\r
+ else if (Keyboard[sc_T]) // T = shape test\r
+ {\r
+ ShapeTest ();\r
+ return 1;\r
+ }\r
+ else if (Keyboard[sc_V]) // V = extra VBLs\r
+ {\r
+ CenterWindow(30,3);\r
+ PrintY+=6;\r
+ US_Print(" Add how many extra VBLs(0-8):");\r
+ VW_UpdateScreen();\r
+ esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
+ if (!esc)\r
+ {\r
+ level = atoi (str);\r
+ if (level>=0 && level<=8)\r
+ extravbls = level;\r
+ }\r
+ return 1;\r
+ }\r
+ else if (Keyboard[sc_W]) // W = warp to level\r
+ {\r
+ CenterWindow(26,3);\r
+ PrintY+=6;\r
+#ifndef SPEAR\r
+ US_Print(" Warp to which level(1-10):");\r
+#else\r
+ US_Print(" Warp to which level(1-21):");\r
+#endif\r
+ VW_UpdateScreen();\r
+ esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
+ if (!esc)\r
+ {\r
+ level = atoi (str);\r
+#ifndef SPEAR\r
+ if (level>0 && level<11)\r
+#else\r
+ if (level>0 && level<22)\r
+#endif\r
+ {\r
+ gamestate.mapon = level-1;\r
+ playstate = ex_warped;\r
+ }\r
+ }\r
+ return 1;\r
+ }\r
+ else if (Keyboard[sc_X]) // X = item cheat\r
+ {\r
+ CenterWindow (12,3);\r
+ US_PrintCentered ("Extra stuff!");\r
+ VW_UpdateScreen();\r
+ // DEBUG: put stuff here\r
+ IN_Ack ();\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+#if 0\r
+/*\r
+===================\r
+=\r
+= OverheadRefresh\r
+=\r
+===================\r
+*/\r
+\r
+void OverheadRefresh (void)\r
+{\r
+ unsigned x,y,endx,endy,sx,sy;\r
+ unsigned tile;\r
+\r
+\r
+ endx = maporgx+VIEWTILEX;\r
+ endy = maporgy+VIEWTILEY;\r
+\r
+ for (y=maporgy;y<endy;y++)\r
+ for (x=maporgx;x<endx;x++)\r
+ {\r
+ sx = (x-maporgx)*16;\r
+ sy = (y-maporgy)*16;\r
+\r
+ switch (viewtype)\r
+ {\r
+#if 0\r
+ case mapview:\r
+ tile = *(mapsegs[0]+farmapylookup[y]+x);\r
+ break;\r
+\r
+ case tilemapview:\r
+ tile = tilemap[x][y];\r
+ break;\r
+\r
+ case visview:\r
+ tile = spotvis[x][y];\r
+ break;\r
+#endif\r
+ case actoratview:\r
+ tile = (unsigned)actorat[x][y];\r
+ break;\r
+ }\r
+\r
+ if (tile<MAXWALLTILES)\r
+ LatchDrawTile(sx,sy,tile);\r
+ else\r
+ {\r
+ LatchDrawChar(sx,sy,NUMBERCHARS+((tile&0xf000)>>12));\r
+ LatchDrawChar(sx+8,sy,NUMBERCHARS+((tile&0x0f00)>>8));\r
+ LatchDrawChar(sx,sy+8,NUMBERCHARS+((tile&0x00f0)>>4));\r
+ LatchDrawChar(sx+8,sy+8,NUMBERCHARS+(tile&0x000f));\r
+ }\r
+ }\r
+\r
+}\r
+#endif\r
+\r
+#if 0\r
+/*\r
+===================\r
+=\r
+= ViewMap\r
+=\r
+===================\r
+*/\r
+\r
+void ViewMap (void)\r
+{\r
+ boolean button0held;\r
+\r
+ viewtype = actoratview;\r
+// button0held = false;\r
+\r
+\r
+ maporgx = player->tilex - VIEWTILEX/2;\r
+ if (maporgx<0)\r
+ maporgx = 0;\r
+ if (maporgx>MAPSIZE-VIEWTILEX)\r
+ maporgx=MAPSIZE-VIEWTILEX;\r
+ maporgy = player->tiley - VIEWTILEY/2;\r
+ if (maporgy<0)\r
+ maporgy = 0;\r
+ if (maporgy>MAPSIZE-VIEWTILEY)\r
+ maporgy=MAPSIZE-VIEWTILEY;\r
+\r
+ do\r
+ {\r
+//\r
+// let user pan around\r
+//\r
+ PollControls ();\r
+ if (controlx < 0 && maporgx>0)\r
+ maporgx--;\r
+ if (controlx > 0 && maporgx<mapwidth-VIEWTILEX)\r
+ maporgx++;\r
+ if (controly < 0 && maporgy>0)\r
+ maporgy--;\r
+ if (controly > 0 && maporgy<mapheight-VIEWTILEY)\r
+ maporgy++;\r
+\r
+#if 0\r
+ if (c.button0 && !button0held)\r
+ {\r
+ button0held = true;\r
+ viewtype++;\r
+ if (viewtype>visview)\r
+ viewtype = mapview;\r
+ }\r
+ if (!c.button0)\r
+ button0held = false;\r
+#endif\r
+\r
+ OverheadRefresh ();\r
+\r
+ } while (!Keyboard[sc_Escape]);\r
+\r
+ IN_ClearKeysDown ();\r
+}\r
+#endif\r
+\r
--- /dev/null
+//#define BETA\r
+#define YEAR 1992\r
+#define MONTH 9\r
+#define DAY 30\r
+\r
+#include "ID_HEADS.H"\r
+#include <MATH.H>\r
+#include <VALUES.H>\r
+\r
+#include "WL_MENU.H"\r
+\r
+#ifdef SPANISH\r
+#include "SPANISH.H"\r
+#else\r
+#include "FOREIGN.H"\r
+#endif\r
+\r
+#ifdef SPEAR\r
+#include "F_SPEAR.H"\r
+#endif\r
+\r
+/*\r
+=============================================================================\r
+\r
+ MACROS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+#define COLORBORDER(color) asm{mov dx,STATUS_REGISTER_1;in al,dx;\\r
+ mov dx,ATR_INDEX;mov al,ATR_OVERSCAN;out dx,al;mov al,color;out dx,al;\\r
+ mov al,32;out dx,al};\r
+\r
+#define MAPSPOT(x,y,plane) (*(mapsegs[plane]+farmapylookup[y]+x))\r
+\r
+#define SIGN(x) ((x)>0?1:-1)\r
+#define ABS(x) ((int)(x)>0?(x):-(x))\r
+#define LABS(x) ((long)(x)>0?(x):-(x))\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define MAXACTORS 150 // max number of nazis, etc / map\r
+#define MAXSTATS 400 // max number of lamps, bonus, etc\r
+#define MAXDOORS 64 // max number of sliding doors\r
+#define MAXWALLTILES 64 // max number of wall tiles\r
+\r
+//\r
+// tile constants\r
+//\r
+\r
+#define ICONARROWS 90\r
+#define PUSHABLETILE 98\r
+#define EXITTILE 99 // at end of castle\r
+#define AREATILE 107 // first of NUMAREAS floor tiles\r
+#define NUMAREAS 37\r
+#define ELEVATORTILE 21\r
+#define AMBUSHTILE 106\r
+#define ALTELEVATORTILE 107\r
+\r
+#define NUMBERCHARS 9\r
+\r
+\r
+//----------------\r
+\r
+#define EXTRAPOINTS 40000\r
+\r
+#define PLAYERSPEED 3000\r
+#define RUNSPEED 6000\r
+\r
+#define SCREENSEG 0xa000\r
+\r
+#define SCREENBWIDE 80\r
+\r
+#define HEIGHTRATIO 0.50 // also defined in id_mm.c\r
+\r
+#define BORDERCOLOR 3\r
+#define FLASHCOLOR 5\r
+#define FLASHTICS 4\r
+\r
+\r
+#define PLAYERSIZE MINDIST // player radius\r
+#define MINACTORDIST 0x10000l // minimum dist from player center\r
+ // to any actor center\r
+\r
+#define NUMLATCHPICS 100\r
+\r
+\r
+#define PI 3.141592657\r
+\r
+#define GLOBAL1 (1l<<16)\r
+#define TILEGLOBAL GLOBAL1\r
+#define PIXGLOBAL (GLOBAL1/64)\r
+#define TILESHIFT 16l\r
+#define UNSIGNEDSHIFT 8\r
+\r
+#define ANGLES 360 // must be divisable by 4\r
+#define ANGLEQUAD (ANGLES/4)\r
+#define FINEANGLES 3600\r
+#define ANG90 (FINEANGLES/4)\r
+#define ANG180 (ANG90*2)\r
+#define ANG270 (ANG90*3)\r
+#define ANG360 (ANG90*4)\r
+#define VANG90 (ANGLES/4)\r
+#define VANG180 (VANG90*2)\r
+#define VANG270 (VANG90*3)\r
+#define VANG360 (VANG90*4)\r
+\r
+#define MINDIST (0x5800l)\r
+\r
+\r
+#define MAXSCALEHEIGHT 256 // largest scale on largest view\r
+\r
+#define MAXVIEWWIDTH 320\r
+\r
+#define MAPSIZE 64 // maps are 64*64 max\r
+#define NORTH 0\r
+#define EAST 1\r
+#define SOUTH 2\r
+#define WEST 3\r
+\r
+\r
+#define STATUSLINES 40\r
+\r
+#define SCREENSIZE (SCREENBWIDE*208)\r
+#define PAGE1START 0\r
+#define PAGE2START (SCREENSIZE)\r
+#define PAGE3START (SCREENSIZE*2u)\r
+#define FREESTART (SCREENSIZE*3u)\r
+\r
+\r
+#define PIXRADIUS 512\r
+\r
+#define STARTAMMO 8\r
+\r
+\r
+// object flag values\r
+\r
+#define FL_SHOOTABLE 1\r
+#define FL_BONUS 2\r
+#define FL_NEVERMARK 4\r
+#define FL_VISABLE 8\r
+#define FL_ATTACKMODE 16\r
+#define FL_FIRSTATTACK 32\r
+#define FL_AMBUSH 64\r
+#define FL_NONMARK 128\r
+\r
+\r
+//\r
+// sprite constants\r
+//\r
+\r
+enum {\r
+ SPR_DEMO,\r
+ SPR_DEATHCAM,\r
+//\r
+// static sprites\r
+//\r
+ SPR_STAT_0,SPR_STAT_1,SPR_STAT_2,SPR_STAT_3,\r
+ SPR_STAT_4,SPR_STAT_5,SPR_STAT_6,SPR_STAT_7,\r
+\r
+ SPR_STAT_8,SPR_STAT_9,SPR_STAT_10,SPR_STAT_11,\r
+ SPR_STAT_12,SPR_STAT_13,SPR_STAT_14,SPR_STAT_15,\r
+\r
+ SPR_STAT_16,SPR_STAT_17,SPR_STAT_18,SPR_STAT_19,\r
+ SPR_STAT_20,SPR_STAT_21,SPR_STAT_22,SPR_STAT_23,\r
+\r
+ SPR_STAT_24,SPR_STAT_25,SPR_STAT_26,SPR_STAT_27,\r
+ SPR_STAT_28,SPR_STAT_29,SPR_STAT_30,SPR_STAT_31,\r
+\r
+ SPR_STAT_32,SPR_STAT_33,SPR_STAT_34,SPR_STAT_35,\r
+ SPR_STAT_36,SPR_STAT_37,SPR_STAT_38,SPR_STAT_39,\r
+\r
+ SPR_STAT_40,SPR_STAT_41,SPR_STAT_42,SPR_STAT_43,\r
+ SPR_STAT_44,SPR_STAT_45,SPR_STAT_46,SPR_STAT_47,\r
+\r
+#ifdef SPEAR\r
+ SPR_STAT_48,SPR_STAT_49,SPR_STAT_50,SPR_STAT_51,\r
+#endif\r
+\r
+//\r
+// guard\r
+//\r
+ SPR_GRD_S_1,SPR_GRD_S_2,SPR_GRD_S_3,SPR_GRD_S_4,\r
+ SPR_GRD_S_5,SPR_GRD_S_6,SPR_GRD_S_7,SPR_GRD_S_8,\r
+\r
+ SPR_GRD_W1_1,SPR_GRD_W1_2,SPR_GRD_W1_3,SPR_GRD_W1_4,\r
+ SPR_GRD_W1_5,SPR_GRD_W1_6,SPR_GRD_W1_7,SPR_GRD_W1_8,\r
+\r
+ SPR_GRD_W2_1,SPR_GRD_W2_2,SPR_GRD_W2_3,SPR_GRD_W2_4,\r
+ SPR_GRD_W2_5,SPR_GRD_W2_6,SPR_GRD_W2_7,SPR_GRD_W2_8,\r
+\r
+ SPR_GRD_W3_1,SPR_GRD_W3_2,SPR_GRD_W3_3,SPR_GRD_W3_4,\r
+ SPR_GRD_W3_5,SPR_GRD_W3_6,SPR_GRD_W3_7,SPR_GRD_W3_8,\r
+\r
+ SPR_GRD_W4_1,SPR_GRD_W4_2,SPR_GRD_W4_3,SPR_GRD_W4_4,\r
+ SPR_GRD_W4_5,SPR_GRD_W4_6,SPR_GRD_W4_7,SPR_GRD_W4_8,\r
+\r
+ SPR_GRD_PAIN_1,SPR_GRD_DIE_1,SPR_GRD_DIE_2,SPR_GRD_DIE_3,\r
+ SPR_GRD_PAIN_2,SPR_GRD_DEAD,\r
+\r
+ SPR_GRD_SHOOT1,SPR_GRD_SHOOT2,SPR_GRD_SHOOT3,\r
+\r
+//\r
+// dogs\r
+//\r
+ SPR_DOG_W1_1,SPR_DOG_W1_2,SPR_DOG_W1_3,SPR_DOG_W1_4,\r
+ SPR_DOG_W1_5,SPR_DOG_W1_6,SPR_DOG_W1_7,SPR_DOG_W1_8,\r
+\r
+ SPR_DOG_W2_1,SPR_DOG_W2_2,SPR_DOG_W2_3,SPR_DOG_W2_4,\r
+ SPR_DOG_W2_5,SPR_DOG_W2_6,SPR_DOG_W2_7,SPR_DOG_W2_8,\r
+\r
+ SPR_DOG_W3_1,SPR_DOG_W3_2,SPR_DOG_W3_3,SPR_DOG_W3_4,\r
+ SPR_DOG_W3_5,SPR_DOG_W3_6,SPR_DOG_W3_7,SPR_DOG_W3_8,\r
+\r
+ SPR_DOG_W4_1,SPR_DOG_W4_2,SPR_DOG_W4_3,SPR_DOG_W4_4,\r
+ SPR_DOG_W4_5,SPR_DOG_W4_6,SPR_DOG_W4_7,SPR_DOG_W4_8,\r
+\r
+ SPR_DOG_DIE_1,SPR_DOG_DIE_2,SPR_DOG_DIE_3,SPR_DOG_DEAD,\r
+ SPR_DOG_JUMP1,SPR_DOG_JUMP2,SPR_DOG_JUMP3,\r
+\r
+\r
+\r
+//\r
+// ss\r
+//\r
+ SPR_SS_S_1,SPR_SS_S_2,SPR_SS_S_3,SPR_SS_S_4,\r
+ SPR_SS_S_5,SPR_SS_S_6,SPR_SS_S_7,SPR_SS_S_8,\r
+\r
+ SPR_SS_W1_1,SPR_SS_W1_2,SPR_SS_W1_3,SPR_SS_W1_4,\r
+ SPR_SS_W1_5,SPR_SS_W1_6,SPR_SS_W1_7,SPR_SS_W1_8,\r
+\r
+ SPR_SS_W2_1,SPR_SS_W2_2,SPR_SS_W2_3,SPR_SS_W2_4,\r
+ SPR_SS_W2_5,SPR_SS_W2_6,SPR_SS_W2_7,SPR_SS_W2_8,\r
+\r
+ SPR_SS_W3_1,SPR_SS_W3_2,SPR_SS_W3_3,SPR_SS_W3_4,\r
+ SPR_SS_W3_5,SPR_SS_W3_6,SPR_SS_W3_7,SPR_SS_W3_8,\r
+\r
+ SPR_SS_W4_1,SPR_SS_W4_2,SPR_SS_W4_3,SPR_SS_W4_4,\r
+ SPR_SS_W4_5,SPR_SS_W4_6,SPR_SS_W4_7,SPR_SS_W4_8,\r
+\r
+ SPR_SS_PAIN_1,SPR_SS_DIE_1,SPR_SS_DIE_2,SPR_SS_DIE_3,\r
+ SPR_SS_PAIN_2,SPR_SS_DEAD,\r
+\r
+ SPR_SS_SHOOT1,SPR_SS_SHOOT2,SPR_SS_SHOOT3,\r
+\r
+//\r
+// mutant\r
+//\r
+ SPR_MUT_S_1,SPR_MUT_S_2,SPR_MUT_S_3,SPR_MUT_S_4,\r
+ SPR_MUT_S_5,SPR_MUT_S_6,SPR_MUT_S_7,SPR_MUT_S_8,\r
+\r
+ SPR_MUT_W1_1,SPR_MUT_W1_2,SPR_MUT_W1_3,SPR_MUT_W1_4,\r
+ SPR_MUT_W1_5,SPR_MUT_W1_6,SPR_MUT_W1_7,SPR_MUT_W1_8,\r
+\r
+ SPR_MUT_W2_1,SPR_MUT_W2_2,SPR_MUT_W2_3,SPR_MUT_W2_4,\r
+ SPR_MUT_W2_5,SPR_MUT_W2_6,SPR_MUT_W2_7,SPR_MUT_W2_8,\r
+\r
+ SPR_MUT_W3_1,SPR_MUT_W3_2,SPR_MUT_W3_3,SPR_MUT_W3_4,\r
+ SPR_MUT_W3_5,SPR_MUT_W3_6,SPR_MUT_W3_7,SPR_MUT_W3_8,\r
+\r
+ SPR_MUT_W4_1,SPR_MUT_W4_2,SPR_MUT_W4_3,SPR_MUT_W4_4,\r
+ SPR_MUT_W4_5,SPR_MUT_W4_6,SPR_MUT_W4_7,SPR_MUT_W4_8,\r
+\r
+ SPR_MUT_PAIN_1,SPR_MUT_DIE_1,SPR_MUT_DIE_2,SPR_MUT_DIE_3,\r
+ SPR_MUT_PAIN_2,SPR_MUT_DIE_4,SPR_MUT_DEAD,\r
+\r
+ SPR_MUT_SHOOT1,SPR_MUT_SHOOT2,SPR_MUT_SHOOT3,SPR_MUT_SHOOT4,\r
+\r
+//\r
+// officer\r
+//\r
+ SPR_OFC_S_1,SPR_OFC_S_2,SPR_OFC_S_3,SPR_OFC_S_4,\r
+ SPR_OFC_S_5,SPR_OFC_S_6,SPR_OFC_S_7,SPR_OFC_S_8,\r
+\r
+ SPR_OFC_W1_1,SPR_OFC_W1_2,SPR_OFC_W1_3,SPR_OFC_W1_4,\r
+ SPR_OFC_W1_5,SPR_OFC_W1_6,SPR_OFC_W1_7,SPR_OFC_W1_8,\r
+\r
+ SPR_OFC_W2_1,SPR_OFC_W2_2,SPR_OFC_W2_3,SPR_OFC_W2_4,\r
+ SPR_OFC_W2_5,SPR_OFC_W2_6,SPR_OFC_W2_7,SPR_OFC_W2_8,\r
+\r
+ SPR_OFC_W3_1,SPR_OFC_W3_2,SPR_OFC_W3_3,SPR_OFC_W3_4,\r
+ SPR_OFC_W3_5,SPR_OFC_W3_6,SPR_OFC_W3_7,SPR_OFC_W3_8,\r
+\r
+ SPR_OFC_W4_1,SPR_OFC_W4_2,SPR_OFC_W4_3,SPR_OFC_W4_4,\r
+ SPR_OFC_W4_5,SPR_OFC_W4_6,SPR_OFC_W4_7,SPR_OFC_W4_8,\r
+\r
+ SPR_OFC_PAIN_1,SPR_OFC_DIE_1,SPR_OFC_DIE_2,SPR_OFC_DIE_3,\r
+ SPR_OFC_PAIN_2,SPR_OFC_DIE_4,SPR_OFC_DEAD,\r
+\r
+ SPR_OFC_SHOOT1,SPR_OFC_SHOOT2,SPR_OFC_SHOOT3,\r
+\r
+#ifndef SPEAR\r
+//\r
+// ghosts\r
+//\r
+ SPR_BLINKY_W1,SPR_BLINKY_W2,SPR_PINKY_W1,SPR_PINKY_W2,\r
+ SPR_CLYDE_W1,SPR_CLYDE_W2,SPR_INKY_W1,SPR_INKY_W2,\r
+\r
+//\r
+// hans\r
+//\r
+ SPR_BOSS_W1,SPR_BOSS_W2,SPR_BOSS_W3,SPR_BOSS_W4,\r
+ SPR_BOSS_SHOOT1,SPR_BOSS_SHOOT2,SPR_BOSS_SHOOT3,SPR_BOSS_DEAD,\r
+\r
+ SPR_BOSS_DIE1,SPR_BOSS_DIE2,SPR_BOSS_DIE3,\r
+\r
+//\r
+// schabbs\r
+//\r
+ SPR_SCHABB_W1,SPR_SCHABB_W2,SPR_SCHABB_W3,SPR_SCHABB_W4,\r
+ SPR_SCHABB_SHOOT1,SPR_SCHABB_SHOOT2,\r
+\r
+ SPR_SCHABB_DIE1,SPR_SCHABB_DIE2,SPR_SCHABB_DIE3,SPR_SCHABB_DEAD,\r
+ SPR_HYPO1,SPR_HYPO2,SPR_HYPO3,SPR_HYPO4,\r
+\r
+//\r
+// fake\r
+//\r
+ SPR_FAKE_W1,SPR_FAKE_W2,SPR_FAKE_W3,SPR_FAKE_W4,\r
+ SPR_FAKE_SHOOT,SPR_FIRE1,SPR_FIRE2,\r
+\r
+ SPR_FAKE_DIE1,SPR_FAKE_DIE2,SPR_FAKE_DIE3,SPR_FAKE_DIE4,\r
+ SPR_FAKE_DIE5,SPR_FAKE_DEAD,\r
+\r
+//\r
+// hitler\r
+//\r
+ SPR_MECHA_W1,SPR_MECHA_W2,SPR_MECHA_W3,SPR_MECHA_W4,\r
+ SPR_MECHA_SHOOT1,SPR_MECHA_SHOOT2,SPR_MECHA_SHOOT3,SPR_MECHA_DEAD,\r
+\r
+ SPR_MECHA_DIE1,SPR_MECHA_DIE2,SPR_MECHA_DIE3,\r
+\r
+ SPR_HITLER_W1,SPR_HITLER_W2,SPR_HITLER_W3,SPR_HITLER_W4,\r
+ SPR_HITLER_SHOOT1,SPR_HITLER_SHOOT2,SPR_HITLER_SHOOT3,SPR_HITLER_DEAD,\r
+\r
+ SPR_HITLER_DIE1,SPR_HITLER_DIE2,SPR_HITLER_DIE3,SPR_HITLER_DIE4,\r
+ SPR_HITLER_DIE5,SPR_HITLER_DIE6,SPR_HITLER_DIE7,\r
+\r
+//\r
+// giftmacher\r
+//\r
+ SPR_GIFT_W1,SPR_GIFT_W2,SPR_GIFT_W3,SPR_GIFT_W4,\r
+ SPR_GIFT_SHOOT1,SPR_GIFT_SHOOT2,\r
+\r
+ SPR_GIFT_DIE1,SPR_GIFT_DIE2,SPR_GIFT_DIE3,SPR_GIFT_DEAD,\r
+#endif\r
+//\r
+// Rocket, smoke and small explosion\r
+//\r
+ SPR_ROCKET_1,SPR_ROCKET_2,SPR_ROCKET_3,SPR_ROCKET_4,\r
+ SPR_ROCKET_5,SPR_ROCKET_6,SPR_ROCKET_7,SPR_ROCKET_8,\r
+\r
+ SPR_SMOKE_1,SPR_SMOKE_2,SPR_SMOKE_3,SPR_SMOKE_4,\r
+ SPR_BOOM_1,SPR_BOOM_2,SPR_BOOM_3,\r
+\r
+//\r
+// Angel of Death's DeathSparks(tm)\r
+//\r
+#ifdef SPEAR\r
+ SPR_HROCKET_1,SPR_HROCKET_2,SPR_HROCKET_3,SPR_HROCKET_4,\r
+ SPR_HROCKET_5,SPR_HROCKET_6,SPR_HROCKET_7,SPR_HROCKET_8,\r
+\r
+ SPR_HSMOKE_1,SPR_HSMOKE_2,SPR_HSMOKE_3,SPR_HSMOKE_4,\r
+ SPR_HBOOM_1,SPR_HBOOM_2,SPR_HBOOM_3,\r
+\r
+ SPR_SPARK1,SPR_SPARK2,SPR_SPARK3,SPR_SPARK4,\r
+#endif\r
+\r
+#ifndef SPEAR\r
+//\r
+// gretel\r
+//\r
+ SPR_GRETEL_W1,SPR_GRETEL_W2,SPR_GRETEL_W3,SPR_GRETEL_W4,\r
+ SPR_GRETEL_SHOOT1,SPR_GRETEL_SHOOT2,SPR_GRETEL_SHOOT3,SPR_GRETEL_DEAD,\r
+\r
+ SPR_GRETEL_DIE1,SPR_GRETEL_DIE2,SPR_GRETEL_DIE3,\r
+\r
+//\r
+// fat face\r
+//\r
+ SPR_FAT_W1,SPR_FAT_W2,SPR_FAT_W3,SPR_FAT_W4,\r
+ SPR_FAT_SHOOT1,SPR_FAT_SHOOT2,SPR_FAT_SHOOT3,SPR_FAT_SHOOT4,\r
+\r
+ SPR_FAT_DIE1,SPR_FAT_DIE2,SPR_FAT_DIE3,SPR_FAT_DEAD,\r
+\r
+//\r
+// bj\r
+//\r
+ SPR_BJ_W1,SPR_BJ_W2,SPR_BJ_W3,SPR_BJ_W4,\r
+ SPR_BJ_JUMP1,SPR_BJ_JUMP2,SPR_BJ_JUMP3,SPR_BJ_JUMP4,\r
+#else\r
+//\r
+// THESE ARE FOR 'SPEAR OF DESTINY'\r
+//\r
+\r
+//\r
+// Trans Grosse\r
+//\r
+ SPR_TRANS_W1,SPR_TRANS_W2,SPR_TRANS_W3,SPR_TRANS_W4,\r
+ SPR_TRANS_SHOOT1,SPR_TRANS_SHOOT2,SPR_TRANS_SHOOT3,SPR_TRANS_DEAD,\r
+\r
+ SPR_TRANS_DIE1,SPR_TRANS_DIE2,SPR_TRANS_DIE3,\r
+\r
+//\r
+// Wilhelm\r
+//\r
+ SPR_WILL_W1,SPR_WILL_W2,SPR_WILL_W3,SPR_WILL_W4,\r
+ SPR_WILL_SHOOT1,SPR_WILL_SHOOT2,SPR_WILL_SHOOT3,SPR_WILL_SHOOT4,\r
+\r
+ SPR_WILL_DIE1,SPR_WILL_DIE2,SPR_WILL_DIE3,SPR_WILL_DEAD,\r
+\r
+//\r
+// UberMutant\r
+//\r
+ SPR_UBER_W1,SPR_UBER_W2,SPR_UBER_W3,SPR_UBER_W4,\r
+ SPR_UBER_SHOOT1,SPR_UBER_SHOOT2,SPR_UBER_SHOOT3,SPR_UBER_SHOOT4,\r
+\r
+ SPR_UBER_DIE1,SPR_UBER_DIE2,SPR_UBER_DIE3,SPR_UBER_DIE4,\r
+ SPR_UBER_DEAD,\r
+\r
+//\r
+// Death Knight\r
+//\r
+ SPR_DEATH_W1,SPR_DEATH_W2,SPR_DEATH_W3,SPR_DEATH_W4,\r
+ SPR_DEATH_SHOOT1,SPR_DEATH_SHOOT2,SPR_DEATH_SHOOT3,SPR_DEATH_SHOOT4,\r
+\r
+ SPR_DEATH_DIE1,SPR_DEATH_DIE2,SPR_DEATH_DIE3,SPR_DEATH_DIE4,\r
+ SPR_DEATH_DIE5,SPR_DEATH_DIE6,SPR_DEATH_DEAD,\r
+\r
+//\r
+// Ghost\r
+//\r
+ SPR_SPECTRE_W1,SPR_SPECTRE_W2,SPR_SPECTRE_W3,SPR_SPECTRE_W4,\r
+ SPR_SPECTRE_F1,SPR_SPECTRE_F2,SPR_SPECTRE_F3,SPR_SPECTRE_F4,\r
+\r
+//\r
+// Angel of Death\r
+//\r
+ SPR_ANGEL_W1,SPR_ANGEL_W2,SPR_ANGEL_W3,SPR_ANGEL_W4,\r
+ SPR_ANGEL_SHOOT1,SPR_ANGEL_SHOOT2,SPR_ANGEL_TIRED1,SPR_ANGEL_TIRED2,\r
+\r
+ SPR_ANGEL_DIE1,SPR_ANGEL_DIE2,SPR_ANGEL_DIE3,SPR_ANGEL_DIE4,\r
+ SPR_ANGEL_DIE5,SPR_ANGEL_DIE6,SPR_ANGEL_DIE7,SPR_ANGEL_DEAD,\r
+\r
+#endif\r
+\r
+//\r
+// player attack frames\r
+//\r
+ SPR_KNIFEREADY,SPR_KNIFEATK1,SPR_KNIFEATK2,SPR_KNIFEATK3,\r
+ SPR_KNIFEATK4,\r
+\r
+ SPR_PISTOLREADY,SPR_PISTOLATK1,SPR_PISTOLATK2,SPR_PISTOLATK3,\r
+ SPR_PISTOLATK4,\r
+\r
+ SPR_MACHINEGUNREADY,SPR_MACHINEGUNATK1,SPR_MACHINEGUNATK2,MACHINEGUNATK3,\r
+ SPR_MACHINEGUNATK4,\r
+\r
+ SPR_CHAINREADY,SPR_CHAINATK1,SPR_CHAINATK2,SPR_CHAINATK3,\r
+ SPR_CHAINATK4,\r
+\r
+ };\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL TYPES\r
+\r
+=============================================================================\r
+*/\r
+\r
+typedef long fixed;\r
+\r
+typedef enum {\r
+ di_north,\r
+ di_east,\r
+ di_south,\r
+ di_west\r
+} controldir_t;\r
+\r
+typedef enum {\r
+ dr_normal,\r
+ dr_lock1,\r
+ dr_lock2,\r
+ dr_lock3,\r
+ dr_lock4,\r
+ dr_elevator\r
+} door_t;\r
+\r
+typedef enum {\r
+ ac_badobject = -1,\r
+ ac_no,\r
+ ac_yes,\r
+ ac_allways\r
+} activetype;\r
+\r
+typedef enum {\r
+ nothing,\r
+ playerobj,\r
+ inertobj,\r
+ guardobj,\r
+ officerobj,\r
+ ssobj,\r
+ dogobj,\r
+ bossobj,\r
+ schabbobj,\r
+ fakeobj,\r
+ mechahitlerobj,\r
+ mutantobj,\r
+ needleobj,\r
+ fireobj,\r
+ bjobj,\r
+ ghostobj,\r
+ realhitlerobj,\r
+ gretelobj,\r
+ giftobj,\r
+ fatobj,\r
+ rocketobj,\r
+\r
+ spectreobj,\r
+ angelobj,\r
+ transobj,\r
+ uberobj,\r
+ willobj,\r
+ deathobj,\r
+ hrocketobj,\r
+ sparkobj\r
+} classtype;\r
+\r
+typedef enum {\r
+ dressing,\r
+ block,\r
+ bo_gibs,\r
+ bo_alpo,\r
+ bo_firstaid,\r
+ bo_key1,\r
+ bo_key2,\r
+ bo_key3,\r
+ bo_key4,\r
+ bo_cross,\r
+ bo_chalice,\r
+ bo_bible,\r
+ bo_crown,\r
+ bo_clip,\r
+ bo_clip2,\r
+ bo_machinegun,\r
+ bo_chaingun,\r
+ bo_food,\r
+ bo_fullheal,\r
+ bo_25clip,\r
+ bo_spear\r
+} stat_t;\r
+\r
+typedef enum {\r
+ east,\r
+ northeast,\r
+ north,\r
+ northwest,\r
+ west,\r
+ southwest,\r
+ south,\r
+ southeast,\r
+ nodir\r
+} dirtype;\r
+\r
+\r
+#define NUMENEMIES 22\r
+typedef enum {\r
+ en_guard,\r
+ en_officer,\r
+ en_ss,\r
+ en_dog,\r
+ en_boss,\r
+ en_schabbs,\r
+ en_fake,\r
+ en_hitler,\r
+ en_mutant,\r
+ en_blinky,\r
+ en_clyde,\r
+ en_pinky,\r
+ en_inky,\r
+ en_gretel,\r
+ en_gift,\r
+ en_fat,\r
+ en_spectre,\r
+ en_angel,\r
+ en_trans,\r
+ en_uber,\r
+ en_will,\r
+ en_death\r
+} enemy_t;\r
+\r
+\r
+typedef struct statestruct\r
+{\r
+ boolean rotate;\r
+ int shapenum; // a shapenum of -1 means get from ob->temp1\r
+ int tictime;\r
+ void (*think) (),(*action) ();\r
+ struct statestruct *next;\r
+} statetype;\r
+\r
+\r
+//---------------------\r
+//\r
+// trivial actor structure\r
+//\r
+//---------------------\r
+\r
+typedef struct statstruct\r
+{\r
+ byte tilex,tiley;\r
+ byte *visspot;\r
+ int shapenum; // if shapenum == -1 the obj has been removed\r
+ byte flags;\r
+ byte itemnumber;\r
+} statobj_t;\r
+\r
+\r
+//---------------------\r
+//\r
+// door actor structure\r
+//\r
+//---------------------\r
+\r
+typedef struct doorstruct\r
+{\r
+ byte tilex,tiley;\r
+ boolean vertical;\r
+ byte lock;\r
+ enum {dr_open,dr_closed,dr_opening,dr_closing} action;\r
+ int ticcount;\r
+} doorobj_t;\r
+\r
+\r
+//--------------------\r
+//\r
+// thinking actor structure\r
+//\r
+//--------------------\r
+\r
+typedef struct objstruct\r
+{\r
+ activetype active;\r
+ int ticcount;\r
+ classtype obclass;\r
+ statetype *state;\r
+\r
+ byte flags; // FL_SHOOTABLE, etc\r
+\r
+ long distance; // if negative, wait for that door to open\r
+ dirtype dir;\r
+\r
+ fixed x,y;\r
+ unsigned tilex,tiley;\r
+ byte areanumber;\r
+\r
+ int viewx;\r
+ unsigned viewheight;\r
+ fixed transx,transy; // in global coord\r
+\r
+ int angle;\r
+ int hitpoints;\r
+ long speed;\r
+\r
+ int temp1,temp2,temp3;\r
+ struct objstruct *next,*prev;\r
+} objtype;\r
+\r
+\r
+#define NUMBUTTONS 8\r
+enum {\r
+ bt_nobutton=-1,\r
+ bt_attack=0,\r
+ bt_strafe,\r
+ bt_run,\r
+ bt_use,\r
+ bt_readyknife,\r
+ bt_readypistol,\r
+ bt_readymachinegun,\r
+ bt_readychaingun\r
+};\r
+\r
+\r
+#define NUMWEAPONS 5\r
+typedef enum {\r
+ wp_knife,\r
+ wp_pistol,\r
+ wp_machinegun,\r
+ wp_chaingun\r
+} weapontype;\r
+\r
+\r
+typedef enum {\r
+ gd_baby,\r
+ gd_easy,\r
+ gd_medium,\r
+ gd_hard\r
+};\r
+\r
+//---------------\r
+//\r
+// gamestate structure\r
+//\r
+//---------------\r
+\r
+typedef struct\r
+{\r
+ int difficulty;\r
+ int mapon;\r
+ long oldscore,score,nextextra;\r
+ int lives;\r
+ int health;\r
+ int ammo;\r
+ int keys;\r
+ weapontype bestweapon,weapon,chosenweapon;\r
+\r
+ int faceframe;\r
+ int attackframe,attackcount,weaponframe;\r
+\r
+ int episode,secretcount,treasurecount,killcount,\r
+ secrettotal,treasuretotal,killtotal;\r
+ long TimeCount;\r
+ long killx,killy;\r
+ boolean victoryflag; // set during victory animations\r
+} gametype;\r
+\r
+\r
+typedef enum {\r
+ ex_stillplaying,\r
+ ex_completed,\r
+ ex_died,\r
+ ex_warped,\r
+ ex_resetgame,\r
+ ex_loadedgame,\r
+ ex_victorious,\r
+ ex_abort,\r
+ ex_demodone,\r
+ ex_secretlevel\r
+} exit_t;\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_MAIN DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+extern boolean MS_CheckParm (char far *string);\r
+\r
+extern char str[80],str2[20];\r
+extern int tedlevelnum;\r
+extern boolean tedlevel;\r
+extern boolean nospr;\r
+extern boolean IsA386;\r
+\r
+extern byte far *scalermemory;\r
+\r
+extern fixed focallength;\r
+extern unsigned viewangles;\r
+extern unsigned screenofs;\r
+extern int viewwidth;\r
+extern int viewheight;\r
+extern int centerx;\r
+extern int shootdelta;\r
+\r
+extern int dirangle[9];\r
+\r
+extern boolean startgame,loadedgame,virtualreality;\r
+extern int mouseadjustment;\r
+//\r
+// math tables\r
+//\r
+extern int pixelangle[MAXVIEWWIDTH];\r
+extern long far finetangent[FINEANGLES/4];\r
+extern fixed far sintable[],far *costable;\r
+\r
+//\r
+// derived constants\r
+//\r
+extern fixed scale,maxslope;\r
+extern long heightnumerator;\r
+extern int minheightdiv;\r
+\r
+extern char configname[13];\r
+\r
+\r
+\r
+void HelpScreens (void);\r
+void OrderingInfo (void);\r
+void TEDDeath(void);\r
+void Quit (char *error);\r
+void CalcProjection (long focal);\r
+boolean SetViewSize (unsigned width, unsigned height);\r
+void NewGame (int difficulty,int episode);\r
+void NewViewSize (int width);\r
+boolean LoadTheGame(int file,int x,int y);\r
+boolean SaveTheGame(int file,int x,int y);\r
+void ShowViewSize (int width);\r
+void ShutdownId (void);\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_GAME DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+extern boolean ingame,fizzlein;\r
+extern unsigned latchpics[NUMLATCHPICS];\r
+extern gametype gamestate;\r
+extern int doornum;\r
+\r
+extern char demoname[13];\r
+\r
+extern long spearx,speary;\r
+extern unsigned spearangle;\r
+extern boolean spearflag;\r
+\r
+\r
+void DrawPlayBorder (void);\r
+void ScanInfoPlane (void);\r
+void SetupGameLevel (void);\r
+void NormalScreen (void);\r
+void DrawPlayScreen (void);\r
+void FizzleOut (void);\r
+void GameLoop (void);\r
+void ClearMemory (void);\r
+void PlayDemo (int demonumber);\r
+void RecordDemo (void);\r
+void DrawAllPlayBorder (void);\r
+void DrawHighScores(void);\r
+void DrawAllPlayBorderSides (void);\r
+\r
+\r
+// JAB\r
+#define PlaySoundLocTile(s,tx,ty) PlaySoundLocGlobal(s,(((long)(tx) << TILESHIFT) + (1L << (TILESHIFT - 1))),(((long)ty << TILESHIFT) + (1L << (TILESHIFT - 1))))\r
+#define PlaySoundLocActor(s,ob) PlaySoundLocGlobal(s,(ob)->x,(ob)->y)\r
+void PlaySoundLocGlobal(word s,fixed gx,fixed gy);\r
+void UpdateSoundLoc(void);\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_PLAY DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#ifdef SPEAR\r
+extern long funnyticount; // FOR FUNNY BJ FACE\r
+#endif\r
+\r
+extern exit_t playstate;\r
+\r
+extern boolean madenoise;\r
+\r
+extern objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,\r
+ *objfreelist,*killerobj;\r
+extern statobj_t statobjlist[MAXSTATS],*laststatobj;\r
+extern doorobj_t doorobjlist[MAXDOORS],*lastdoorobj;\r
+\r
+extern unsigned farmapylookup[MAPSIZE];\r
+extern byte *nearmapylookup[MAPSIZE];\r
+\r
+extern byte tilemap[MAPSIZE][MAPSIZE]; // wall values only\r
+extern byte spotvis[MAPSIZE][MAPSIZE];\r
+extern objtype *actorat[MAPSIZE][MAPSIZE];\r
+\r
+#define UPDATESIZE (UPDATEWIDE*UPDATEHIGH)\r
+extern byte update[UPDATESIZE];\r
+\r
+extern boolean singlestep,godmode,noclip;\r
+extern int extravbls;\r
+\r
+//\r
+// control info\r
+//\r
+extern boolean mouseenabled,joystickenabled,joypadenabled,joystickprogressive;\r
+extern int joystickport;\r
+extern int dirscan[4];\r
+extern int buttonscan[NUMBUTTONS];\r
+extern int buttonmouse[4];\r
+extern int buttonjoy[4];\r
+\r
+extern boolean buttonheld[NUMBUTTONS];\r
+\r
+extern int viewsize;\r
+\r
+//\r
+// curent user input\r
+//\r
+extern int controlx,controly; // range from -100 to 100\r
+extern boolean buttonstate[NUMBUTTONS];\r
+\r
+extern boolean demorecord,demoplayback;\r
+extern char far *demoptr, far *lastdemoptr;\r
+extern memptr demobuffer;\r
+\r
+\r
+\r
+void InitRedShifts (void);\r
+void FinishPaletteShifts (void);\r
+\r
+void CenterWindow(word w,word h);\r
+void InitActorList (void);\r
+void GetNewActor (void);\r
+void RemoveObj (objtype *gone);\r
+void PollControls (void);\r
+void StopMusic(void);\r
+void StartMusic(void);\r
+void PlayLoop (void);\r
+void StartDamageFlash (int damage);\r
+void StartBonusFlash (void);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_INTER\r
+\r
+=============================================================================\r
+*/\r
+\r
+void IntroScreen (void);\r
+void PreloadGraphics(void);\r
+void LevelCompleted (void);\r
+void CheckHighScore (long score,word other);\r
+void Victory (void);\r
+void ClearSplitVWB (void);\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_DEBUG\r
+\r
+=============================================================================\r
+*/\r
+\r
+int DebugKeys (void);\r
+void PicturePause (void);\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_DRAW DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+extern unsigned screenloc[3];\r
+extern unsigned freelatch;\r
+\r
+extern long lasttimecount;\r
+extern long frameon;\r
+extern boolean fizzlein;\r
+\r
+extern unsigned wallheight[MAXVIEWWIDTH];\r
+\r
+extern fixed tileglobal;\r
+extern fixed focallength;\r
+extern fixed mindist;\r
+\r
+//\r
+// math tables\r
+//\r
+extern int pixelangle[MAXVIEWWIDTH];\r
+extern long far finetangent[FINEANGLES/4];\r
+extern fixed far sintable[],far *costable;\r
+\r
+//\r
+// derived constants\r
+//\r
+extern fixed scale;\r
+extern long heightnumerator,mindist;\r
+\r
+//\r
+// refresh variables\r
+//\r
+extern fixed viewx,viewy; // the focal point\r
+extern int viewangle;\r
+extern fixed viewsin,viewcos;\r
+\r
+extern long postsource;\r
+extern unsigned postx;\r
+extern unsigned postwidth;\r
+\r
+\r
+extern int horizwall[],vertwall[];\r
+\r
+extern unsigned pwallpos;\r
+\r
+\r
+fixed FixedByFrac (fixed a, fixed b);\r
+void TransformActor (objtype *ob);\r
+void BuildTables (void);\r
+void ClearScreen (void);\r
+int CalcRotate (objtype *ob);\r
+void DrawScaleds (void);\r
+void CalcTics (void);\r
+void FixOfs (void);\r
+void ThreeDRefresh (void);\r
+void FarScalePost (void);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_STATE DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+#define TURNTICS 10\r
+#define SPDPATROL 512\r
+#define SPDDOG 1500\r
+\r
+\r
+extern dirtype opposite[9];\r
+extern dirtype diagonal[9][9];\r
+\r
+\r
+void InitHitRect (objtype *ob, unsigned radius);\r
+void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);\r
+void NewState (objtype *ob, statetype *state);\r
+\r
+boolean TryWalk (objtype *ob);\r
+void SelectChaseDir (objtype *ob);\r
+void SelectDodgeDir (objtype *ob);\r
+void SelectRunDir (objtype *ob);\r
+void MoveObj (objtype *ob, long move);\r
+boolean SightPlayer (objtype *ob);\r
+\r
+void KillActor (objtype *ob);\r
+void DamageActor (objtype *ob, unsigned damage);\r
+\r
+boolean CheckLine (objtype *ob);\r
+boolean CheckSight (objtype *ob);\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_SCALE DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+#define COMPSCALECODESTART (65*4) // offset to start of code in comp scaler\r
+\r
+typedef struct\r
+{\r
+ unsigned codeofs[65];\r
+ unsigned width[65];\r
+ byte code[];\r
+} t_compscale;\r
+\r
+typedef struct\r
+{\r
+ unsigned leftpix,rightpix;\r
+ unsigned dataofs[64];\r
+// table data after dataofs[rightpix-leftpix+1]\r
+} t_compshape;\r
+\r
+\r
+extern t_compscale _seg *scaledirectory[MAXSCALEHEIGHT+1];\r
+extern long fullscalefarcall[MAXSCALEHEIGHT+1];\r
+\r
+extern byte bitmasks1[8][8];\r
+extern byte bitmasks2[8][8];\r
+extern unsigned wordmasks[8][8];\r
+\r
+extern byte mapmasks1[4][8];\r
+extern byte mapmasks2[4][8];\r
+extern byte mapmasks3[4][8];\r
+\r
+extern int maxscale,maxscaleshl2;\r
+\r
+extern boolean insetupscaling;\r
+\r
+void SetupScaling (int maxscaleheight);\r
+void ScaleShape (int xcenter, int shapenum, unsigned height);\r
+void SimpleScaleShape (int xcenter, int shapenum, unsigned height);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_AGENT DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+//\r
+// player state info\r
+//\r
+extern boolean running;\r
+extern long thrustspeed;\r
+extern unsigned plux,pluy; // player coordinates scaled to unsigned\r
+\r
+extern int anglefrac;\r
+extern int facecount;\r
+\r
+void SpawnPlayer (int tilex, int tiley, int dir);\r
+void DrawFace (void);\r
+void DrawHealth (void);\r
+void TakeDamage (int points,objtype *attacker);\r
+void HealSelf (int points);\r
+void DrawLevel (void);\r
+void DrawLives (void);\r
+void GiveExtraMan (void);\r
+void DrawScore (void);\r
+void GivePoints (long points);\r
+void DrawWeapon (void);\r
+void DrawKeys (void);\r
+void GiveWeapon (int weapon);\r
+void DrawAmmo (void);\r
+void GiveAmmo (int ammo);\r
+void GiveKey (int key);\r
+void GetBonus (statobj_t *check);\r
+\r
+void Thrust (int angle, long speed);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_ACT1 DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+extern doorobj_t doorobjlist[MAXDOORS],*lastdoorobj;\r
+extern int doornum;\r
+\r
+extern unsigned doorposition[MAXDOORS],pwallstate;\r
+\r
+extern byte far areaconnect[NUMAREAS][NUMAREAS];\r
+\r
+extern boolean areabyplayer[NUMAREAS];\r
+\r
+extern unsigned pwallstate;\r
+extern unsigned pwallpos; // amount a pushable wall has been moved (0-63)\r
+extern unsigned pwallx,pwally;\r
+extern int pwalldir;\r
+\r
+\r
+void InitDoorList (void);\r
+void InitStaticList (void);\r
+void SpawnStatic (int tilex, int tiley, int type);\r
+void SpawnDoor (int tilex, int tiley, boolean vertical, int lock);\r
+void MoveDoors (void);\r
+void MovePWalls (void);\r
+void OpenDoor (int door);\r
+void PlaceItemType (int itemtype, int tilex, int tiley);\r
+void PushWall (int checkx, int checky, int dir);\r
+void OperateDoor (int door);\r
+void InitAreas (void);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_ACT2 DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define s_nakedbody s_static10\r
+\r
+extern statetype s_grddie1;\r
+extern statetype s_dogdie1;\r
+extern statetype s_ofcdie1;\r
+extern statetype s_mutdie1;\r
+extern statetype s_ssdie1;\r
+extern statetype s_bossdie1;\r
+extern statetype s_schabbdie1;\r
+extern statetype s_fakedie1;\r
+extern statetype s_mechadie1;\r
+extern statetype s_hitlerdie1;\r
+extern statetype s_greteldie1;\r
+extern statetype s_giftdie1;\r
+extern statetype s_fatdie1;\r
+\r
+extern statetype s_spectredie1;\r
+extern statetype s_angeldie1;\r
+extern statetype s_transdie0;\r
+extern statetype s_uberdie0;\r
+extern statetype s_willdie1;\r
+extern statetype s_deathdie1;\r
+\r
+\r
+extern statetype s_grdchase1;\r
+extern statetype s_dogchase1;\r
+extern statetype s_ofcchase1;\r
+extern statetype s_sschase1;\r
+extern statetype s_mutchase1;\r
+extern statetype s_bosschase1;\r
+extern statetype s_schabbchase1;\r
+extern statetype s_fakechase1;\r
+extern statetype s_mechachase1;\r
+extern statetype s_gretelchase1;\r
+extern statetype s_giftchase1;\r
+extern statetype s_fatchase1;\r
+\r
+extern statetype s_spectrechase1;\r
+extern statetype s_angelchase1;\r
+extern statetype s_transchase1;\r
+extern statetype s_uberchase1;\r
+extern statetype s_willchase1;\r
+extern statetype s_deathchase1;\r
+\r
+extern statetype s_blinkychase1;\r
+extern statetype s_hitlerchase1;\r
+\r
+extern statetype s_grdpain;\r
+extern statetype s_grdpain1;\r
+extern statetype s_ofcpain;\r
+extern statetype s_ofcpain1;\r
+extern statetype s_sspain;\r
+extern statetype s_sspain1;\r
+extern statetype s_mutpain;\r
+extern statetype s_mutpain1;\r
+\r
+extern statetype s_deathcam;\r
+\r
+extern statetype s_schabbdeathcam2;\r
+extern statetype s_hitlerdeathcam2;\r
+extern statetype s_giftdeathcam2;\r
+extern statetype s_fatdeathcam2;\r
+\r
+void SpawnStand (enemy_t which, int tilex, int tiley, int dir);\r
+void SpawnPatrol (enemy_t which, int tilex, int tiley, int dir);\r
+void KillActor (objtype *ob);\r
+\r
+void US_ControlPanel(byte);\r
+\r
+void SpawnDeadGuard (int tilex, int tiley);\r
+void SpawnBoss (int tilex, int tiley);\r
+void SpawnGretel (int tilex, int tiley);\r
+void SpawnTrans (int tilex, int tiley);\r
+void SpawnUber (int tilex, int tiley);\r
+void SpawnWill (int tilex, int tiley);\r
+void SpawnDeath (int tilex, int tiley);\r
+void SpawnAngel (int tilex, int tiley);\r
+void SpawnSpectre (int tilex, int tiley);\r
+void SpawnGhosts (int which, int tilex, int tiley);\r
+void SpawnSchabbs (int tilex, int tiley);\r
+void SpawnGift (int tilex, int tiley);\r
+void SpawnFat (int tilex, int tiley);\r
+void SpawnFakeHitler (int tilex, int tiley);\r
+void SpawnHitler (int tilex, int tiley);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WL_TEXT DEFINITIONS\r
+\r
+=============================================================================\r
+*/\r
+\r
+extern char helpfilename[],endfilename[];\r
+\r
+extern void HelpScreens(void);\r
+extern void EndText(void);\r
--- /dev/null
+// WL_DRAW.C\r
+\r
+#include "WL_DEF.H"\r
+#include <DOS.H>\r
+#pragma hdrstop\r
+\r
+//#define DEBUGWALLS\r
+//#define DEBUGTICS\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+// the door is the last picture before the sprites\r
+#define DOORWALL (PMSpriteStart-8)\r
+\r
+#define ACTORSIZE 0x4000\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+#ifdef DEBUGWALLS\r
+unsigned screenloc[3]= {0,0,0};\r
+#else\r
+unsigned screenloc[3]= {PAGE1START,PAGE2START,PAGE3START};\r
+#endif\r
+unsigned freelatch = FREESTART;\r
+\r
+long lasttimecount;\r
+long frameon;\r
+\r
+unsigned wallheight[MAXVIEWWIDTH];\r
+\r
+fixed tileglobal = TILEGLOBAL;\r
+fixed mindist = MINDIST;\r
+\r
+\r
+//\r
+// math tables\r
+//\r
+int pixelangle[MAXVIEWWIDTH];\r
+long far finetangent[FINEANGLES/4];\r
+fixed far sintable[ANGLES+ANGLES/4],far *costable = sintable+(ANGLES/4);\r
+\r
+//\r
+// refresh variables\r
+//\r
+fixed viewx,viewy; // the focal point\r
+int viewangle;\r
+fixed viewsin,viewcos;\r
+\r
+\r
+\r
+fixed FixedByFrac (fixed a, fixed b);\r
+void TransformActor (objtype *ob);\r
+void BuildTables (void);\r
+void ClearScreen (void);\r
+int CalcRotate (objtype *ob);\r
+void DrawScaleds (void);\r
+void CalcTics (void);\r
+void FixOfs (void);\r
+void ThreeDRefresh (void);\r
+\r
+\r
+\r
+//\r
+// wall optimization variables\r
+//\r
+int lastside; // true for vertical\r
+long lastintercept;\r
+int lasttilehit;\r
+\r
+\r
+//\r
+// ray tracing variables\r
+//\r
+int focaltx,focalty,viewtx,viewty;\r
+\r
+int midangle,angle;\r
+unsigned xpartial,ypartial;\r
+unsigned xpartialup,xpartialdown,ypartialup,ypartialdown;\r
+unsigned xinttile,yinttile;\r
+\r
+unsigned tilehit;\r
+unsigned pixx;\r
+\r
+int xtile,ytile;\r
+int xtilestep,ytilestep;\r
+long xintercept,yintercept;\r
+long xstep,ystep;\r
+\r
+int horizwall[MAXWALLTILES],vertwall[MAXWALLTILES];\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+void AsmRefresh (void); // in WL_DR_A.ASM\r
+\r
+/*\r
+============================================================================\r
+\r
+ 3 - D DEFINITIONS\r
+\r
+============================================================================\r
+*/\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+========================\r
+=\r
+= FixedByFrac\r
+=\r
+= multiply a 16/16 bit, 2's complement fixed point number by a 16 bit\r
+= fraction, passed as a signed magnitude 32 bit number\r
+=\r
+========================\r
+*/\r
+\r
+#pragma warn -rvl // I stick the return value in with ASMs\r
+\r
+fixed FixedByFrac (fixed a, fixed b)\r
+{\r
+//\r
+// setup\r
+//\r
+asm mov si,[WORD PTR b+2] // sign of result = sign of fraction\r
+\r
+asm mov ax,[WORD PTR a]\r
+asm mov cx,[WORD PTR a+2]\r
+\r
+asm or cx,cx\r
+asm jns aok: // negative?\r
+asm neg cx\r
+asm neg ax\r
+asm sbb cx,0\r
+asm xor si,0x8000 // toggle sign of result\r
+aok:\r
+\r
+//\r
+// multiply cx:ax by bx\r
+//\r
+asm mov bx,[WORD PTR b]\r
+asm mul bx // fraction*fraction\r
+asm mov di,dx // di is low word of result\r
+asm mov ax,cx //\r
+asm mul bx // units*fraction\r
+asm add ax,di\r
+asm adc dx,0\r
+\r
+//\r
+// put result dx:ax in 2's complement\r
+//\r
+asm test si,0x8000 // is the result negative?\r
+asm jz ansok:\r
+asm neg dx\r
+asm neg ax\r
+asm sbb dx,0\r
+\r
+ansok:;\r
+\r
+}\r
+\r
+#pragma warn +rvl\r
+\r
+//==========================================================================\r
+\r
+/*\r
+========================\r
+=\r
+= TransformActor\r
+=\r
+= Takes paramaters:\r
+= gx,gy : globalx/globaly of point\r
+=\r
+= globals:\r
+= viewx,viewy : point of view\r
+= viewcos,viewsin : sin/cos of viewangle\r
+= scale : conversion from global value to screen value\r
+=\r
+= sets:\r
+= screenx,transx,transy,screenheight: projected edge location and size\r
+=\r
+========================\r
+*/\r
+\r
+\r
+//\r
+// transform actor\r
+//\r
+void TransformActor (objtype *ob)\r
+{\r
+ int ratio;\r
+ fixed gx,gy,gxt,gyt,nx,ny;\r
+ long temp;\r
+\r
+//\r
+// translate point to view centered coordinates\r
+//\r
+ gx = ob->x-viewx;\r
+ gy = ob->y-viewy;\r
+\r
+//\r
+// calculate newx\r
+//\r
+ gxt = FixedByFrac(gx,viewcos);\r
+ gyt = FixedByFrac(gy,viewsin);\r
+ nx = gxt-gyt-ACTORSIZE; // fudge the shape forward a bit, because\r
+ // the midpoint could put parts of the shape\r
+ // into an adjacent wall\r
+\r
+//\r
+// calculate newy\r
+//\r
+ gxt = FixedByFrac(gx,viewsin);\r
+ gyt = FixedByFrac(gy,viewcos);\r
+ ny = gyt+gxt;\r
+\r
+//\r
+// calculate perspective ratio\r
+//\r
+ ob->transx = nx;\r
+ ob->transy = ny;\r
+\r
+ if (nx<mindist) // too close, don't overflow the divide\r
+ {\r
+ ob->viewheight = 0;\r
+ return;\r
+ }\r
+\r
+ ob->viewx = centerx + ny*scale/nx; // DEBUG: use assembly divide\r
+\r
+//\r
+// calculate height (heightnumerator/(nx>>8))\r
+//\r
+ asm mov ax,[WORD PTR heightnumerator]\r
+ asm mov dx,[WORD PTR heightnumerator+2]\r
+ asm idiv [WORD PTR nx+1] // nx>>8\r
+ asm mov [WORD PTR temp],ax\r
+ asm mov [WORD PTR temp+2],dx\r
+\r
+ ob->viewheight = temp;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+========================\r
+=\r
+= TransformTile\r
+=\r
+= Takes paramaters:\r
+= tx,ty : tile the object is centered in\r
+=\r
+= globals:\r
+= viewx,viewy : point of view\r
+= viewcos,viewsin : sin/cos of viewangle\r
+= scale : conversion from global value to screen value\r
+=\r
+= sets:\r
+= screenx,transx,transy,screenheight: projected edge location and size\r
+=\r
+= Returns true if the tile is withing getting distance\r
+=\r
+========================\r
+*/\r
+\r
+boolean TransformTile (int tx, int ty, int *dispx, int *dispheight)\r
+{\r
+ int ratio;\r
+ fixed gx,gy,gxt,gyt,nx,ny;\r
+ long temp;\r
+\r
+//\r
+// translate point to view centered coordinates\r
+//\r
+ gx = ((long)tx<<TILESHIFT)+0x8000-viewx;\r
+ gy = ((long)ty<<TILESHIFT)+0x8000-viewy;\r
+\r
+//\r
+// calculate newx\r
+//\r
+ gxt = FixedByFrac(gx,viewcos);\r
+ gyt = FixedByFrac(gy,viewsin);\r
+ nx = gxt-gyt-0x2000; // 0x2000 is size of object\r
+\r
+//\r
+// calculate newy\r
+//\r
+ gxt = FixedByFrac(gx,viewsin);\r
+ gyt = FixedByFrac(gy,viewcos);\r
+ ny = gyt+gxt;\r
+\r
+\r
+//\r
+// calculate perspective ratio\r
+//\r
+ if (nx<mindist) // too close, don't overflow the divide\r
+ {\r
+ *dispheight = 0;\r
+ return false;\r
+ }\r
+\r
+ *dispx = centerx + ny*scale/nx; // DEBUG: use assembly divide\r
+\r
+//\r
+// calculate height (heightnumerator/(nx>>8))\r
+//\r
+ asm mov ax,[WORD PTR heightnumerator]\r
+ asm mov dx,[WORD PTR heightnumerator+2]\r
+ asm idiv [WORD PTR nx+1] // nx>>8\r
+ asm mov [WORD PTR temp],ax\r
+ asm mov [WORD PTR temp+2],dx\r
+\r
+ *dispheight = temp;\r
+\r
+//\r
+// see if it should be grabbed\r
+//\r
+ if (nx<TILEGLOBAL && ny>-TILEGLOBAL/2 && ny<TILEGLOBAL/2)\r
+ return true;\r
+ else\r
+ return false;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= CalcHeight\r
+=\r
+= Calculates the height of xintercept,yintercept from viewx,viewy\r
+=\r
+====================\r
+*/\r
+\r
+#pragma warn -rvl // I stick the return value in with ASMs\r
+\r
+int CalcHeight (void)\r
+{\r
+ int transheight;\r
+ int ratio;\r
+ fixed gxt,gyt,nx,ny;\r
+ long gx,gy;\r
+\r
+ gx = xintercept-viewx;\r
+ gxt = FixedByFrac(gx,viewcos);\r
+\r
+ gy = yintercept-viewy;\r
+ gyt = FixedByFrac(gy,viewsin);\r
+\r
+ nx = gxt-gyt;\r
+\r
+ //\r
+ // calculate perspective ratio (heightnumerator/(nx>>8))\r
+ //\r
+ if (nx<mindist)\r
+ nx=mindist; // don't let divide overflow\r
+\r
+ asm mov ax,[WORD PTR heightnumerator]\r
+ asm mov dx,[WORD PTR heightnumerator+2]\r
+ asm idiv [WORD PTR nx+1] // nx>>8\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= ScalePost\r
+=\r
+===================\r
+*/\r
+\r
+long postsource;\r
+unsigned postx;\r
+unsigned postwidth;\r
+\r
+void near ScalePost (void) // VGA version\r
+{\r
+ asm mov ax,SCREENSEG\r
+ asm mov es,ax\r
+\r
+ asm mov bx,[postx]\r
+ asm shl bx,1\r
+ asm mov bp,WORD PTR [wallheight+bx] // fractional height (low 3 bits frac)\r
+ asm and bp,0xfff8 // bp = heightscaler*4\r
+ asm shr bp,1\r
+ asm cmp bp,[maxscaleshl2]\r
+ asm jle heightok\r
+ asm mov bp,[maxscaleshl2]\r
+heightok:\r
+ asm add bp,OFFSET fullscalefarcall\r
+ //\r
+ // scale a byte wide strip of wall\r
+ //\r
+ asm mov bx,[postx]\r
+ asm mov di,bx\r
+ asm shr di,1 // X in bytes\r
+ asm shr di,1\r
+ asm add di,[bufferofs]\r
+\r
+ asm and bx,3\r
+ /* begin 8086 hack\r
+ asm shl bx,3\r
+ */\r
+ asm push cx\r
+ asm mov cl,3\r
+ asm shl bx,cl\r
+ asm pop cx\r
+ /* end 8086 hack */\r
+ asm add bx,[postwidth]\r
+\r
+ asm mov al,BYTE PTR [mapmasks1-1+bx] // -1 because no widths of 0\r
+ asm mov dx,SC_INDEX+1\r
+ asm out dx,al // set bit mask register\r
+ asm lds si,DWORD PTR [postsource]\r
+ asm call DWORD PTR [bp] // scale the line of pixels\r
+\r
+ asm mov al,BYTE PTR [ss:mapmasks2-1+bx] // -1 because no widths of 0\r
+ asm or al,al\r
+ asm jz nomore\r
+\r
+ //\r
+ // draw a second byte for vertical strips that cross two bytes\r
+ //\r
+ asm inc di\r
+ asm out dx,al // set bit mask register\r
+ asm call DWORD PTR [bp] // scale the line of pixels\r
+\r
+ asm mov al,BYTE PTR [ss:mapmasks3-1+bx] // -1 because no widths of 0\r
+ asm or al,al\r
+ asm jz nomore\r
+ //\r
+ // draw a third byte for vertical strips that cross three bytes\r
+ //\r
+ asm inc di\r
+ asm out dx,al // set bit mask register\r
+ asm call DWORD PTR [bp] // scale the line of pixels\r
+\r
+\r
+nomore:\r
+ asm mov ax,ss\r
+ asm mov ds,ax\r
+}\r
+\r
+void FarScalePost (void) // just so other files can call\r
+{\r
+ ScalePost ();\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= HitVertWall\r
+=\r
+= tilehit bit 7 is 0, because it's not a door tile\r
+= if bit 6 is 1 and the adjacent tile is a door tile, use door side pic\r
+=\r
+====================\r
+*/\r
+\r
+void HitVertWall (void)\r
+{\r
+ int wallpic;\r
+ unsigned texture;\r
+\r
+ texture = (yintercept>>4)&0xfc0;\r
+ if (xtilestep == -1)\r
+ {\r
+ texture = 0xfc0-texture;\r
+ xintercept += TILEGLOBAL;\r
+ }\r
+ wallheight[pixx] = CalcHeight();\r
+\r
+ if (lastside==1 && lastintercept == xtile && lasttilehit == tilehit)\r
+ {\r
+ // in the same wall type as last time, so check for optimized draw\r
+ if (texture == (unsigned)postsource)\r
+ {\r
+ // wide scale\r
+ postwidth++;\r
+ wallheight[pixx] = wallheight[pixx-1];\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ScalePost ();\r
+ (unsigned)postsource = texture;\r
+ postwidth = 1;\r
+ postx = pixx;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // new wall\r
+ if (lastside != -1) // if not the first scaled post\r
+ ScalePost ();\r
+\r
+ lastside = true;\r
+ lastintercept = xtile;\r
+\r
+ lasttilehit = tilehit;\r
+ postx = pixx;\r
+ postwidth = 1;\r
+\r
+ if (tilehit & 0x40)\r
+ { // check for adjacent doors\r
+ ytile = yintercept>>TILESHIFT;\r
+ if ( tilemap[xtile-xtilestep][ytile]&0x80 )\r
+ wallpic = DOORWALL+3;\r
+ else\r
+ wallpic = vertwall[tilehit & ~0x40];\r
+ }\r
+ else\r
+ wallpic = vertwall[tilehit];\r
+\r
+ *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+ (unsigned)postsource = texture;\r
+\r
+ }\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= HitHorizWall\r
+=\r
+= tilehit bit 7 is 0, because it's not a door tile\r
+= if bit 6 is 1 and the adjacent tile is a door tile, use door side pic\r
+=\r
+====================\r
+*/\r
+\r
+void HitHorizWall (void)\r
+{\r
+ int wallpic;\r
+ unsigned texture;\r
+\r
+ texture = (xintercept>>4)&0xfc0;\r
+ if (ytilestep == -1)\r
+ yintercept += TILEGLOBAL;\r
+ else\r
+ texture = 0xfc0-texture;\r
+ wallheight[pixx] = CalcHeight();\r
+\r
+ if (lastside==0 && lastintercept == ytile && lasttilehit == tilehit)\r
+ {\r
+ // in the same wall type as last time, so check for optimized draw\r
+ if (texture == (unsigned)postsource)\r
+ {\r
+ // wide scale\r
+ postwidth++;\r
+ wallheight[pixx] = wallheight[pixx-1];\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ScalePost ();\r
+ (unsigned)postsource = texture;\r
+ postwidth = 1;\r
+ postx = pixx;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // new wall\r
+ if (lastside != -1) // if not the first scaled post\r
+ ScalePost ();\r
+\r
+ lastside = 0;\r
+ lastintercept = ytile;\r
+\r
+ lasttilehit = tilehit;\r
+ postx = pixx;\r
+ postwidth = 1;\r
+\r
+ if (tilehit & 0x40)\r
+ { // check for adjacent doors\r
+ xtile = xintercept>>TILESHIFT;\r
+ if ( tilemap[xtile][ytile-ytilestep]&0x80 )\r
+ wallpic = DOORWALL+2;\r
+ else\r
+ wallpic = horizwall[tilehit & ~0x40];\r
+ }\r
+ else\r
+ wallpic = horizwall[tilehit];\r
+\r
+ *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+ (unsigned)postsource = texture;\r
+ }\r
+\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= HitHorizDoor\r
+=\r
+====================\r
+*/\r
+\r
+void HitHorizDoor (void)\r
+{\r
+ unsigned texture,doorpage,doornum;\r
+\r
+ doornum = tilehit&0x7f;\r
+ texture = ( (xintercept-doorposition[doornum]) >> 4) &0xfc0;\r
+\r
+ wallheight[pixx] = CalcHeight();\r
+\r
+ if (lasttilehit == tilehit)\r
+ {\r
+ // in the same door as last time, so check for optimized draw\r
+ if (texture == (unsigned)postsource)\r
+ {\r
+ // wide scale\r
+ postwidth++;\r
+ wallheight[pixx] = wallheight[pixx-1];\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ScalePost ();\r
+ (unsigned)postsource = texture;\r
+ postwidth = 1;\r
+ postx = pixx;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (lastside != -1) // if not the first scaled post\r
+ ScalePost (); // draw last post\r
+ // first pixel in this door\r
+ lastside = 2;\r
+ lasttilehit = tilehit;\r
+ postx = pixx;\r
+ postwidth = 1;\r
+\r
+ switch (doorobjlist[doornum].lock)\r
+ {\r
+ case dr_normal:\r
+ doorpage = DOORWALL;\r
+ break;\r
+ case dr_lock1:\r
+ case dr_lock2:\r
+ case dr_lock3:\r
+ case dr_lock4:\r
+ doorpage = DOORWALL+6;\r
+ break;\r
+ case dr_elevator:\r
+ doorpage = DOORWALL+4;\r
+ break;\r
+ }\r
+\r
+ *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage);\r
+ (unsigned)postsource = texture;\r
+ }\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= HitVertDoor\r
+=\r
+====================\r
+*/\r
+\r
+void HitVertDoor (void)\r
+{\r
+ unsigned texture,doorpage,doornum;\r
+\r
+ doornum = tilehit&0x7f;\r
+ texture = ( (yintercept-doorposition[doornum]) >> 4) &0xfc0;\r
+\r
+ wallheight[pixx] = CalcHeight();\r
+\r
+ if (lasttilehit == tilehit)\r
+ {\r
+ // in the same door as last time, so check for optimized draw\r
+ if (texture == (unsigned)postsource)\r
+ {\r
+ // wide scale\r
+ postwidth++;\r
+ wallheight[pixx] = wallheight[pixx-1];\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ScalePost ();\r
+ (unsigned)postsource = texture;\r
+ postwidth = 1;\r
+ postx = pixx;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (lastside != -1) // if not the first scaled post\r
+ ScalePost (); // draw last post\r
+ // first pixel in this door\r
+ lastside = 2;\r
+ lasttilehit = tilehit;\r
+ postx = pixx;\r
+ postwidth = 1;\r
+\r
+ switch (doorobjlist[doornum].lock)\r
+ {\r
+ case dr_normal:\r
+ doorpage = DOORWALL;\r
+ break;\r
+ case dr_lock1:\r
+ case dr_lock2:\r
+ case dr_lock3:\r
+ case dr_lock4:\r
+ doorpage = DOORWALL+6;\r
+ break;\r
+ case dr_elevator:\r
+ doorpage = DOORWALL+4;\r
+ break;\r
+ }\r
+\r
+ *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(doorpage+1);\r
+ (unsigned)postsource = texture;\r
+ }\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= HitHorizPWall\r
+=\r
+= A pushable wall in action has been hit\r
+=\r
+====================\r
+*/\r
+\r
+void HitHorizPWall (void)\r
+{\r
+ int wallpic;\r
+ unsigned texture,offset;\r
+\r
+ texture = (xintercept>>4)&0xfc0;\r
+ offset = pwallpos<<10;\r
+ if (ytilestep == -1)\r
+ yintercept += TILEGLOBAL-offset;\r
+ else\r
+ {\r
+ texture = 0xfc0-texture;\r
+ yintercept += offset;\r
+ }\r
+\r
+ wallheight[pixx] = CalcHeight();\r
+\r
+ if (lasttilehit == tilehit)\r
+ {\r
+ // in the same wall type as last time, so check for optimized draw\r
+ if (texture == (unsigned)postsource)\r
+ {\r
+ // wide scale\r
+ postwidth++;\r
+ wallheight[pixx] = wallheight[pixx-1];\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ScalePost ();\r
+ (unsigned)postsource = texture;\r
+ postwidth = 1;\r
+ postx = pixx;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // new wall\r
+ if (lastside != -1) // if not the first scaled post\r
+ ScalePost ();\r
+\r
+ lasttilehit = tilehit;\r
+ postx = pixx;\r
+ postwidth = 1;\r
+\r
+ wallpic = horizwall[tilehit&63];\r
+\r
+ *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+ (unsigned)postsource = texture;\r
+ }\r
+\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= HitVertPWall\r
+=\r
+= A pushable wall in action has been hit\r
+=\r
+====================\r
+*/\r
+\r
+void HitVertPWall (void)\r
+{\r
+ int wallpic;\r
+ unsigned texture,offset;\r
+\r
+ texture = (yintercept>>4)&0xfc0;\r
+ offset = pwallpos<<10;\r
+ if (xtilestep == -1)\r
+ {\r
+ xintercept += TILEGLOBAL-offset;\r
+ texture = 0xfc0-texture;\r
+ }\r
+ else\r
+ xintercept += offset;\r
+\r
+ wallheight[pixx] = CalcHeight();\r
+\r
+ if (lasttilehit == tilehit)\r
+ {\r
+ // in the same wall type as last time, so check for optimized draw\r
+ if (texture == (unsigned)postsource)\r
+ {\r
+ // wide scale\r
+ postwidth++;\r
+ wallheight[pixx] = wallheight[pixx-1];\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ ScalePost ();\r
+ (unsigned)postsource = texture;\r
+ postwidth = 1;\r
+ postx = pixx;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // new wall\r
+ if (lastside != -1) // if not the first scaled post\r
+ ScalePost ();\r
+\r
+ lasttilehit = tilehit;\r
+ postx = pixx;\r
+ postwidth = 1;\r
+\r
+ wallpic = vertwall[tilehit&63];\r
+\r
+ *( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);\r
+ (unsigned)postsource = texture;\r
+ }\r
+\r
+}\r
+\r
+//==========================================================================\r
+\r
+//==========================================================================\r
+\r
+#if 0\r
+/*\r
+=====================\r
+=\r
+= ClearScreen\r
+=\r
+=====================\r
+*/\r
+\r
+void ClearScreen (void)\r
+{\r
+ unsigned floor=egaFloor[gamestate.episode*10+mapon],\r
+ ceiling=egaCeiling[gamestate.episode*10+mapon];\r
+\r
+ //\r
+ // clear the screen\r
+ //\r
+asm mov dx,GC_INDEX\r
+asm mov ax,GC_MODE + 256*2 // read mode 0, write mode 2\r
+asm out dx,ax\r
+asm mov ax,GC_BITMASK + 255*256\r
+asm out dx,ax\r
+\r
+asm mov dx,40\r
+asm mov ax,[viewwidth]\r
+asm shr ax,1\r
+asm shr ax,1\r
+asm shr ax,1\r
+asm sub dx,ax // dx = 40-viewwidth/8\r
+\r
+asm mov bx,[viewwidth]\r
+asm shr bx,1 // bl = viewwidth/16\r
+asm shr bx,1\r
+asm shr bx,1\r
+asm shr bx,1\r
+asm mov bh,BYTE PTR [viewheight]\r
+asm shr bh,1 // half height\r
+\r
+asm mov ax,[ceiling]\r
+asm mov es,[screenseg]\r
+asm mov di,[bufferofs]\r
+\r
+toploop:\r
+asm mov cl,bl\r
+asm rep stosw\r
+asm add di,dx\r
+asm dec bh\r
+asm jnz toploop\r
+\r
+asm mov bh,BYTE PTR [viewheight]\r
+asm shr bh,1 // half height\r
+asm mov ax,[floor]\r
+\r
+bottomloop:\r
+asm mov cl,bl\r
+asm rep stosw\r
+asm add di,dx\r
+asm dec bh\r
+asm jnz bottomloop\r
+\r
+\r
+asm mov dx,GC_INDEX\r
+asm mov ax,GC_MODE + 256*10 // read mode 1, write mode 2\r
+asm out dx,ax\r
+asm mov al,GC_BITMASK\r
+asm out dx,al\r
+\r
+}\r
+#endif\r
+//==========================================================================\r
+\r
+unsigned vgaCeiling[]=\r
+{\r
+#ifndef SPEAR\r
+ 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xbfbf,\r
+ 0x4e4e,0x4e4e,0x4e4e,0x1d1d,0x8d8d,0x4e4e,0x1d1d,0x2d2d,0x1d1d,0x8d8d,\r
+ 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x2d2d,0xdddd,0x1d1d,0x1d1d,0x9898,\r
+\r
+ 0x1d1d,0x9d9d,0x2d2d,0xdddd,0xdddd,0x9d9d,0x2d2d,0x4d4d,0x1d1d,0xdddd,\r
+ 0x7d7d,0x1d1d,0x2d2d,0x2d2d,0xdddd,0xd7d7,0x1d1d,0x1d1d,0x1d1d,0x2d2d,\r
+ 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xdddd,0xdddd,0x7d7d,0xdddd,0xdddd,0xdddd\r
+#else\r
+ 0x6f6f,0x4f4f,0x1d1d,0xdede,0xdfdf,0x2e2e,0x7f7f,0x9e9e,0xaeae,0x7f7f,\r
+ 0x1d1d,0xdede,0xdfdf,0xdede,0xdfdf,0xdede,0xe1e1,0xdcdc,0x2e2e,0x1d1d,0xdcdc\r
+#endif\r
+};\r
+\r
+/*\r
+=====================\r
+=\r
+= VGAClearScreen\r
+=\r
+=====================\r
+*/\r
+\r
+void VGAClearScreen (void)\r
+{\r
+ unsigned ceiling=vgaCeiling[gamestate.episode*10+mapon];\r
+\r
+ //\r
+ // clear the screen\r
+ //\r
+asm mov dx,SC_INDEX\r
+asm mov ax,SC_MAPMASK+15*256 // write through all planes\r
+asm out dx,ax\r
+\r
+asm mov dx,80\r
+asm mov ax,[viewwidth]\r
+asm shr ax,1\r
+asm shr ax,1\r
+asm sub dx,ax // dx = 40-viewwidth/2\r
+\r
+asm mov bx,[viewwidth]\r
+asm shr bx,1 // bl = viewwidth/8\r
+asm shr bx,1\r
+asm shr bx,1\r
+asm mov bh,BYTE PTR [viewheight]\r
+asm shr bh,1 // half height\r
+\r
+asm mov es,[screenseg]\r
+asm mov di,[bufferofs]\r
+asm mov ax,[ceiling]\r
+\r
+toploop:\r
+asm mov cl,bl\r
+asm rep stosw\r
+asm add di,dx\r
+asm dec bh\r
+asm jnz toploop\r
+\r
+asm mov bh,BYTE PTR [viewheight]\r
+asm shr bh,1 // half height\r
+asm mov ax,0x1919\r
+\r
+bottomloop:\r
+asm mov cl,bl\r
+asm rep stosw\r
+asm add di,dx\r
+asm dec bh\r
+asm jnz bottomloop\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= CalcRotate\r
+=\r
+=====================\r
+*/\r
+\r
+int CalcRotate (objtype *ob)\r
+{\r
+ int angle,viewangle;\r
+\r
+ // this isn't exactly correct, as it should vary by a trig value,\r
+ // but it is close enough with only eight rotations\r
+\r
+ viewangle = player->angle + (centerx - ob->viewx)/8;\r
+\r
+ if (ob->obclass == rocketobj || ob->obclass == hrocketobj)\r
+ angle = (viewangle-180)- ob->angle;\r
+ else\r
+ angle = (viewangle-180)- dirangle[ob->dir];\r
+\r
+ angle+=ANGLES/16;\r
+ while (angle>=ANGLES)\r
+ angle-=ANGLES;\r
+ while (angle<0)\r
+ angle+=ANGLES;\r
+\r
+ if (ob->state->rotate == 2) // 2 rotation pain frame\r
+ return 4*(angle/(ANGLES/2)); // seperated by 3 (art layout...)\r
+\r
+ return angle/(ANGLES/8);\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= DrawScaleds\r
+=\r
+= Draws all objects that are visable\r
+=\r
+=====================\r
+*/\r
+\r
+#define MAXVISABLE 50\r
+\r
+typedef struct\r
+{\r
+ int viewx,\r
+ viewheight,\r
+ shapenum;\r
+} visobj_t;\r
+\r
+visobj_t vislist[MAXVISABLE],*visptr,*visstep,*farthest;\r
+\r
+void DrawScaleds (void)\r
+{\r
+ int i,j,least,numvisable,height;\r
+ memptr shape;\r
+ byte *tilespot,*visspot;\r
+ int shapenum;\r
+ unsigned spotloc;\r
+\r
+ statobj_t *statptr;\r
+ objtype *obj;\r
+\r
+ visptr = &vislist[0];\r
+\r
+//\r
+// place static objects\r
+//\r
+ for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++)\r
+ {\r
+ if ((visptr->shapenum = statptr->shapenum) == -1)\r
+ continue; // object has been deleted\r
+\r
+ if (!*statptr->visspot)\r
+ continue; // not visable\r
+\r
+ if (TransformTile (statptr->tilex,statptr->tiley\r
+ ,&visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS)\r
+ {\r
+ GetBonus (statptr);\r
+ continue;\r
+ }\r
+\r
+ if (!visptr->viewheight)\r
+ continue; // to close to the object\r
+\r
+ if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow\r
+ visptr++;\r
+ }\r
+\r
+//\r
+// place active objects\r
+//\r
+ for (obj = player->next;obj;obj=obj->next)\r
+ {\r
+ if (!(visptr->shapenum = obj->state->shapenum))\r
+ continue; // no shape\r
+\r
+ spotloc = (obj->tilex<<6)+obj->tiley; // optimize: keep in struct?\r
+ visspot = &spotvis[0][0]+spotloc;\r
+ tilespot = &tilemap[0][0]+spotloc;\r
+\r
+ //\r
+ // could be in any of the nine surrounding tiles\r
+ //\r
+ if (*visspot\r
+ || ( *(visspot-1) && !*(tilespot-1) )\r
+ || ( *(visspot+1) && !*(tilespot+1) )\r
+ || ( *(visspot-65) && !*(tilespot-65) )\r
+ || ( *(visspot-64) && !*(tilespot-64) )\r
+ || ( *(visspot-63) && !*(tilespot-63) )\r
+ || ( *(visspot+65) && !*(tilespot+65) )\r
+ || ( *(visspot+64) && !*(tilespot+64) )\r
+ || ( *(visspot+63) && !*(tilespot+63) ) )\r
+ {\r
+ obj->active = true;\r
+ TransformActor (obj);\r
+ if (!obj->viewheight)\r
+ continue; // too close or far away\r
+\r
+ visptr->viewx = obj->viewx;\r
+ visptr->viewheight = obj->viewheight;\r
+ if (visptr->shapenum == -1)\r
+ visptr->shapenum = obj->temp1; // special shape\r
+\r
+ if (obj->state->rotate)\r
+ visptr->shapenum += CalcRotate (obj);\r
+\r
+ if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow\r
+ visptr++;\r
+ obj->flags |= FL_VISABLE;\r
+ }\r
+ else\r
+ obj->flags &= ~FL_VISABLE;\r
+ }\r
+\r
+//\r
+// draw from back to front\r
+//\r
+ numvisable = visptr-&vislist[0];\r
+\r
+ if (!numvisable)\r
+ return; // no visable objects\r
+\r
+ for (i = 0; i<numvisable; i++)\r
+ {\r
+ least = 32000;\r
+ for (visstep=&vislist[0] ; visstep<visptr ; visstep++)\r
+ {\r
+ height = visstep->viewheight;\r
+ if (height < least)\r
+ {\r
+ least = height;\r
+ farthest = visstep;\r
+ }\r
+ }\r
+ //\r
+ // draw farthest\r
+ //\r
+ ScaleShape(farthest->viewx,farthest->shapenum,farthest->viewheight);\r
+\r
+ farthest->viewheight = 32000;\r
+ }\r
+\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==============\r
+=\r
+= DrawPlayerWeapon\r
+=\r
+= Draw the player's hands\r
+=\r
+==============\r
+*/\r
+\r
+int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY,SPR_PISTOLREADY\r
+ ,SPR_MACHINEGUNREADY,SPR_CHAINREADY};\r
+\r
+void DrawPlayerWeapon (void)\r
+{\r
+ int shapenum;\r
+\r
+#ifndef SPEAR\r
+ if (gamestate.victoryflag)\r
+ {\r
+ if (player->state == &s_deathcam && (TimeCount&32) )\r
+ SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1);\r
+ return;\r
+ }\r
+#endif\r
+\r
+ if (gamestate.weapon != -1)\r
+ {\r
+ shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe;\r
+ SimpleScaleShape(viewwidth/2,shapenum,viewheight+1);\r
+ }\r
+\r
+ if (demorecord || demoplayback)\r
+ SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1);\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CalcTics\r
+=\r
+=====================\r
+*/\r
+\r
+void CalcTics (void)\r
+{\r
+ long newtime,oldtimecount;\r
+\r
+//\r
+// calculate tics since last refresh for adaptive timing\r
+//\r
+ if (lasttimecount > TimeCount)\r
+ TimeCount = lasttimecount; // if the game was paused a LONG time\r
+\r
+ do\r
+ {\r
+ newtime = TimeCount;\r
+ tics = newtime-lasttimecount;\r
+ } while (!tics); // make sure at least one tic passes\r
+\r
+ lasttimecount = newtime;\r
+\r
+#ifdef FILEPROFILE\r
+ strcpy (scratch,"\tTics:");\r
+ itoa (tics,str,10);\r
+ strcat (scratch,str);\r
+ strcat (scratch,"\n");\r
+ write (profilehandle,scratch,strlen(scratch));\r
+#endif\r
+\r
+ if (tics>MAXTICS)\r
+ {\r
+ TimeCount -= (tics-MAXTICS);\r
+ tics = MAXTICS;\r
+ }\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+========================\r
+=\r
+= FixOfs\r
+=\r
+========================\r
+*/\r
+\r
+void FixOfs (void)\r
+{\r
+ VW_ScreenToScreen (displayofs,bufferofs,viewwidth/8,viewheight);\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= WallRefresh\r
+=\r
+====================\r
+*/\r
+\r
+void WallRefresh (void)\r
+{\r
+//\r
+// set up variables for this view\r
+//\r
+ viewangle = player->angle;\r
+ midangle = viewangle*(FINEANGLES/ANGLES);\r
+ viewsin = sintable[viewangle];\r
+ viewcos = costable[viewangle];\r
+ viewx = player->x - FixedByFrac(focallength,viewcos);\r
+ viewy = player->y + FixedByFrac(focallength,viewsin);\r
+\r
+ focaltx = viewx>>TILESHIFT;\r
+ focalty = viewy>>TILESHIFT;\r
+\r
+ viewtx = player->x >> TILESHIFT;\r
+ viewty = player->y >> TILESHIFT;\r
+\r
+ xpartialdown = viewx&(TILEGLOBAL-1);\r
+ xpartialup = TILEGLOBAL-xpartialdown;\r
+ ypartialdown = viewy&(TILEGLOBAL-1);\r
+ ypartialup = TILEGLOBAL-ypartialdown;\r
+\r
+ lastside = -1; // the first pixel is on a new wall\r
+ AsmRefresh ();\r
+ ScalePost (); // no more optimization on last post\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+========================\r
+=\r
+= ThreeDRefresh\r
+=\r
+========================\r
+*/\r
+\r
+void ThreeDRefresh (void)\r
+{\r
+ int tracedir;\r
+\r
+// this wouldn't need to be done except for my debugger/video wierdness\r
+ outportb (SC_INDEX,SC_MAPMASK);\r
+\r
+//\r
+// clear out the traced array\r
+//\r
+asm mov ax,ds\r
+asm mov es,ax\r
+asm mov di,OFFSET spotvis\r
+asm xor ax,ax\r
+asm mov cx,2048 // 64*64 / 2\r
+asm rep stosw\r
+\r
+ bufferofs += screenofs;\r
+\r
+//\r
+// follow the walls from there to the right, drawwing as we go\r
+//\r
+ VGAClearScreen ();\r
+\r
+ WallRefresh ();\r
+\r
+//\r
+// draw all the scaled images\r
+//\r
+ DrawScaleds(); // draw scaled stuff\r
+ DrawPlayerWeapon (); // draw player's hands\r
+\r
+//\r
+// show screen and time last cycle\r
+//\r
+ if (fizzlein)\r
+ {\r
+ FizzleFade(bufferofs,displayofs+screenofs,viewwidth,viewheight,20,false);\r
+ fizzlein = false;\r
+\r
+ lasttimecount = TimeCount = 0; // don't make a big tic count\r
+\r
+ }\r
+\r
+ bufferofs -= screenofs;\r
+ displayofs = bufferofs;\r
+\r
+ asm cli\r
+ asm mov cx,[displayofs]\r
+ asm mov dx,3d4h // CRTC address register\r
+ asm mov al,0ch // start address high register\r
+ asm out dx,al\r
+ asm inc dx\r
+ asm mov al,ch\r
+ asm out dx,al // set the high byte\r
+ asm sti\r
+\r
+ bufferofs += SCREENSIZE;\r
+ if (bufferofs > PAGE3START)\r
+ bufferofs = PAGE1START;\r
+\r
+ frameon++;\r
+ PM_NextFrame();\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
--- /dev/null
+// WL_GAME.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+#ifdef MYPROFILE\r
+#include <TIME.H>\r
+#endif\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+boolean ingame,fizzlein;\r
+unsigned latchpics[NUMLATCHPICS];\r
+gametype gamestate;\r
+\r
+long spearx,speary;\r
+unsigned spearangle;\r
+boolean spearflag;\r
+\r
+//\r
+// ELEVATOR BACK MAPS - REMEMBER (-1)!!\r
+//\r
+int ElevatorBackTo[]={1,1,7,3,5,3};\r
+\r
+void ScanInfoPlane (void);\r
+void SetupGameLevel (void);\r
+void DrawPlayScreen (void);\r
+void LoadLatchMem (void);\r
+void GameLoop (void);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+\r
+//===========================================================================\r
+//===========================================================================\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= SetSoundLoc - Given the location of an object (in terms of global\r
+= coordinates, held in globalsoundx and globalsoundy), munges the values\r
+= for an approximate distance from the left and right ear, and puts\r
+= those values into leftchannel and rightchannel.\r
+=\r
+= JAB\r
+=\r
+==========================\r
+*/\r
+\r
+ fixed globalsoundx,globalsoundy;\r
+ int leftchannel,rightchannel;\r
+#define ATABLEMAX 15\r
+byte righttable[ATABLEMAX][ATABLEMAX * 2] = {\r
+{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, 1, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 4, 0, 0, 0, 0, 0, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 4, 1, 0, 0, 0, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 4, 2, 1, 0, 1, 2, 3, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 4, 3, 2, 2, 3, 3, 5, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}\r
+};\r
+byte lefttable[ATABLEMAX][ATABLEMAX * 2] = {\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 5, 3, 1, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 4, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 1, 0, 0, 0, 1, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 3, 2, 1, 0, 1, 2, 4, 5, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 5, 3, 3, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},\r
+{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}\r
+};\r
+\r
+void\r
+SetSoundLoc(fixed gx,fixed gy)\r
+{\r
+ fixed xt,yt;\r
+ int x,y;\r
+\r
+//\r
+// translate point to view centered coordinates\r
+//\r
+ gx -= viewx;\r
+ gy -= viewy;\r
+\r
+//\r
+// calculate newx\r
+//\r
+ xt = FixedByFrac(gx,viewcos);\r
+ yt = FixedByFrac(gy,viewsin);\r
+ x = (xt - yt) >> TILESHIFT;\r
+\r
+//\r
+// calculate newy\r
+//\r
+ xt = FixedByFrac(gx,viewsin);\r
+ yt = FixedByFrac(gy,viewcos);\r
+ y = (yt + xt) >> TILESHIFT;\r
+\r
+ if (y >= ATABLEMAX)\r
+ y = ATABLEMAX - 1;\r
+ else if (y <= -ATABLEMAX)\r
+ y = -ATABLEMAX;\r
+ if (x < 0)\r
+ x = -x;\r
+ if (x >= ATABLEMAX)\r
+ x = ATABLEMAX - 1;\r
+ leftchannel = lefttable[x][y + ATABLEMAX];\r
+ rightchannel = righttable[x][y + ATABLEMAX];\r
+\r
+#if 0\r
+ CenterWindow(8,1);\r
+ US_PrintSigned(leftchannel);\r
+ US_Print(",");\r
+ US_PrintSigned(rightchannel);\r
+ VW_UpdateScreen();\r
+#endif\r
+}\r
+\r
+/*\r
+==========================\r
+=\r
+= SetSoundLocGlobal - Sets up globalsoundx & globalsoundy and then calls\r
+= UpdateSoundLoc() to transform that into relative channel volumes. Those\r
+= values are then passed to the Sound Manager so that they'll be used for\r
+= the next sound played (if possible).\r
+=\r
+= JAB\r
+=\r
+==========================\r
+*/\r
+void PlaySoundLocGlobal(word s,fixed gx,fixed gy)\r
+{\r
+ SetSoundLoc(gx,gy);\r
+ SD_PositionSound(leftchannel,rightchannel);\r
+ if (SD_PlaySound(s))\r
+ {\r
+ globalsoundx = gx;\r
+ globalsoundy = gy;\r
+ }\r
+}\r
+\r
+void UpdateSoundLoc(void)\r
+{\r
+ if (SoundPositioned)\r
+ {\r
+ SetSoundLoc(globalsoundx,globalsoundy);\r
+ SD_SetPosition(leftchannel,rightchannel);\r
+ }\r
+}\r
+\r
+/*\r
+** JAB End\r
+*/\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= ClearMemory\r
+=\r
+==========================\r
+*/\r
+\r
+void ClearMemory (void)\r
+{\r
+ PM_UnlockMainMem();\r
+ SD_StopDigitized();\r
+ MM_SortMem ();\r
+}\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= ScanInfoPlane\r
+=\r
+= Spawn all actors and mark down special places\r
+=\r
+==========================\r
+*/\r
+\r
+void ScanInfoPlane (void)\r
+{\r
+ unsigned x,y,i,j;\r
+ int tile;\r
+ unsigned far *start;\r
+\r
+ start = mapsegs[1];\r
+ for (y=0;y<mapheight;y++)\r
+ for (x=0;x<mapwidth;x++)\r
+ {\r
+ tile = *start++;\r
+ if (!tile)\r
+ continue;\r
+\r
+ switch (tile)\r
+ {\r
+ case 19:\r
+ case 20:\r
+ case 21:\r
+ case 22:\r
+ SpawnPlayer(x,y,NORTH+tile-19);\r
+ break;\r
+\r
+ case 23:\r
+ case 24:\r
+ case 25:\r
+ case 26:\r
+ case 27:\r
+ case 28:\r
+ case 29:\r
+ case 30:\r
+\r
+ case 31:\r
+ case 32:\r
+ case 33:\r
+ case 34:\r
+ case 35:\r
+ case 36:\r
+ case 37:\r
+ case 38:\r
+\r
+ case 39:\r
+ case 40:\r
+ case 41:\r
+ case 42:\r
+ case 43:\r
+ case 44:\r
+ case 45:\r
+ case 46:\r
+\r
+ case 47:\r
+ case 48:\r
+ case 49:\r
+ case 50:\r
+ case 51:\r
+ case 52:\r
+ case 53:\r
+ case 54:\r
+\r
+ case 55:\r
+ case 56:\r
+ case 57:\r
+ case 58:\r
+ case 59:\r
+ case 60:\r
+ case 61:\r
+ case 62:\r
+\r
+ case 63:\r
+ case 64:\r
+ case 65:\r
+ case 66:\r
+ case 67:\r
+ case 68:\r
+ case 69:\r
+ case 70:\r
+ case 71:\r
+ case 72:\r
+ case 73: // TRUCK AND SPEAR!\r
+ case 74:\r
+\r
+ SpawnStatic(x,y,tile-23);\r
+ break;\r
+\r
+//\r
+// P wall\r
+//\r
+ case 98:\r
+ if (!loadedgame)\r
+ gamestate.secrettotal++;\r
+ break;\r
+\r
+//\r
+// guard\r
+//\r
+ case 180:\r
+ case 181:\r
+ case 182:\r
+ case 183:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 144:\r
+ case 145:\r
+ case 146:\r
+ case 147:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 108:\r
+ case 109:\r
+ case 110:\r
+ case 111:\r
+ SpawnStand(en_guard,x,y,tile-108);\r
+ break;\r
+\r
+\r
+ case 184:\r
+ case 185:\r
+ case 186:\r
+ case 187:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 148:\r
+ case 149:\r
+ case 150:\r
+ case 151:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 112:\r
+ case 113:\r
+ case 114:\r
+ case 115:\r
+ SpawnPatrol(en_guard,x,y,tile-112);\r
+ break;\r
+\r
+ case 124:\r
+ SpawnDeadGuard (x,y);\r
+ break;\r
+//\r
+// officer\r
+//\r
+ case 188:\r
+ case 189:\r
+ case 190:\r
+ case 191:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 152:\r
+ case 153:\r
+ case 154:\r
+ case 155:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 116:\r
+ case 117:\r
+ case 118:\r
+ case 119:\r
+ SpawnStand(en_officer,x,y,tile-116);\r
+ break;\r
+\r
+\r
+ case 192:\r
+ case 193:\r
+ case 194:\r
+ case 195:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 156:\r
+ case 157:\r
+ case 158:\r
+ case 159:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 120:\r
+ case 121:\r
+ case 122:\r
+ case 123:\r
+ SpawnPatrol(en_officer,x,y,tile-120);\r
+ break;\r
+\r
+\r
+//\r
+// ss\r
+//\r
+ case 198:\r
+ case 199:\r
+ case 200:\r
+ case 201:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 162:\r
+ case 163:\r
+ case 164:\r
+ case 165:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 126:\r
+ case 127:\r
+ case 128:\r
+ case 129:\r
+ SpawnStand(en_ss,x,y,tile-126);\r
+ break;\r
+\r
+\r
+ case 202:\r
+ case 203:\r
+ case 204:\r
+ case 205:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 166:\r
+ case 167:\r
+ case 168:\r
+ case 169:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 130:\r
+ case 131:\r
+ case 132:\r
+ case 133:\r
+ SpawnPatrol(en_ss,x,y,tile-130);\r
+ break;\r
+\r
+//\r
+// dogs\r
+//\r
+ case 206:\r
+ case 207:\r
+ case 208:\r
+ case 209:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 170:\r
+ case 171:\r
+ case 172:\r
+ case 173:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 134:\r
+ case 135:\r
+ case 136:\r
+ case 137:\r
+ SpawnStand(en_dog,x,y,tile-134);\r
+ break;\r
+\r
+\r
+ case 210:\r
+ case 211:\r
+ case 212:\r
+ case 213:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 36;\r
+ case 174:\r
+ case 175:\r
+ case 176:\r
+ case 177:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 36;\r
+ case 138:\r
+ case 139:\r
+ case 140:\r
+ case 141:\r
+ SpawnPatrol(en_dog,x,y,tile-138);\r
+ break;\r
+\r
+//\r
+// boss\r
+//\r
+#ifndef SPEAR\r
+ case 214:\r
+ SpawnBoss (x,y);\r
+ break;\r
+ case 197:\r
+ SpawnGretel (x,y);\r
+ break;\r
+ case 215:\r
+ SpawnGift (x,y);\r
+ break;\r
+ case 179:\r
+ SpawnFat (x,y);\r
+ break;\r
+ case 196:\r
+ SpawnSchabbs (x,y);\r
+ break;\r
+ case 160:\r
+ SpawnFakeHitler (x,y);\r
+ break;\r
+ case 178:\r
+ SpawnHitler (x,y);\r
+ break;\r
+#else\r
+ case 106:\r
+ SpawnSpectre (x,y);\r
+ break;\r
+ case 107:\r
+ SpawnAngel (x,y);\r
+ break;\r
+ case 125:\r
+ SpawnTrans (x,y);\r
+ break;\r
+ case 142:\r
+ SpawnUber (x,y);\r
+ break;\r
+ case 143:\r
+ SpawnWill (x,y);\r
+ break;\r
+ case 161:\r
+ SpawnDeath (x,y);\r
+ break;\r
+\r
+#endif\r
+\r
+//\r
+// mutants\r
+//\r
+ case 252:\r
+ case 253:\r
+ case 254:\r
+ case 255:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 18;\r
+ case 234:\r
+ case 235:\r
+ case 236:\r
+ case 237:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 18;\r
+ case 216:\r
+ case 217:\r
+ case 218:\r
+ case 219:\r
+ SpawnStand(en_mutant,x,y,tile-216);\r
+ break;\r
+\r
+ case 256:\r
+ case 257:\r
+ case 258:\r
+ case 259:\r
+ if (gamestate.difficulty<gd_hard)\r
+ break;\r
+ tile -= 18;\r
+ case 238:\r
+ case 239:\r
+ case 240:\r
+ case 241:\r
+ if (gamestate.difficulty<gd_medium)\r
+ break;\r
+ tile -= 18;\r
+ case 220:\r
+ case 221:\r
+ case 222:\r
+ case 223:\r
+ SpawnPatrol(en_mutant,x,y,tile-220);\r
+ break;\r
+\r
+//\r
+// ghosts\r
+//\r
+#ifndef SPEAR\r
+ case 224:\r
+ SpawnGhosts (en_blinky,x,y);\r
+ break;\r
+ case 225:\r
+ SpawnGhosts (en_clyde,x,y);\r
+ break;\r
+ case 226:\r
+ SpawnGhosts (en_pinky,x,y);\r
+ break;\r
+ case 227:\r
+ SpawnGhosts (en_inky,x,y);\r
+ break;\r
+#endif\r
+ }\r
+\r
+ }\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= SetupGameLevel\r
+=\r
+==================\r
+*/\r
+\r
+void SetupGameLevel (void)\r
+{\r
+ int x,y,i;\r
+ unsigned far *map,tile,spot;\r
+\r
+\r
+ if (!loadedgame)\r
+ {\r
+ gamestate.TimeCount=\r
+ gamestate.secrettotal=\r
+ gamestate.killtotal=\r
+ gamestate.treasuretotal=\r
+ gamestate.secretcount=\r
+ gamestate.killcount=\r
+ gamestate.treasurecount=0;\r
+ }\r
+\r
+ if (demoplayback || demorecord)\r
+ US_InitRndT (false);\r
+ else\r
+ US_InitRndT (true);\r
+\r
+//\r
+// load the level\r
+//\r
+ CA_CacheMap (gamestate.mapon+10*gamestate.episode);\r
+ mapon-=gamestate.episode*10;\r
+\r
+ mapwidth = mapheaderseg[mapon]->width;\r
+ mapheight = mapheaderseg[mapon]->height;\r
+\r
+ if (mapwidth != 64 || mapheight != 64)\r
+ Quit ("Map not 64*64!");\r
+\r
+\r
+//\r
+// copy the wall data to a data segment array\r
+//\r
+ memset (tilemap,0,sizeof(tilemap));\r
+ memset (actorat,0,sizeof(actorat));\r
+ map = mapsegs[0];\r
+ for (y=0;y<mapheight;y++)\r
+ for (x=0;x<mapwidth;x++)\r
+ {\r
+ tile = *map++;\r
+ if (tile<AREATILE)\r
+ {\r
+ // solid wall\r
+ tilemap[x][y] = tile;\r
+ (unsigned)actorat[x][y] = tile;\r
+ }\r
+ else\r
+ {\r
+ // area floor\r
+ tilemap[x][y] = 0;\r
+ (unsigned)actorat[x][y] = 0;\r
+ }\r
+ }\r
+\r
+//\r
+// spawn doors\r
+//\r
+ InitActorList (); // start spawning things with a clean slate\r
+ InitDoorList ();\r
+ InitStaticList ();\r
+\r
+ map = mapsegs[0];\r
+ for (y=0;y<mapheight;y++)\r
+ for (x=0;x<mapwidth;x++)\r
+ {\r
+ tile = *map++;\r
+ if (tile >= 90 && tile <= 101)\r
+ {\r
+ // door\r
+ switch (tile)\r
+ {\r
+ case 90:\r
+ case 92:\r
+ case 94:\r
+ case 96:\r
+ case 98:\r
+ case 100:\r
+ SpawnDoor (x,y,1,(tile-90)/2);\r
+ break;\r
+ case 91:\r
+ case 93:\r
+ case 95:\r
+ case 97:\r
+ case 99:\r
+ case 101:\r
+ SpawnDoor (x,y,0,(tile-91)/2);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+//\r
+// spawn actors\r
+//\r
+ ScanInfoPlane ();\r
+\r
+//\r
+// take out the ambush markers\r
+//\r
+ map = mapsegs[0];\r
+ for (y=0;y<mapheight;y++)\r
+ for (x=0;x<mapwidth;x++)\r
+ {\r
+ tile = *map++;\r
+ if (tile == AMBUSHTILE)\r
+ {\r
+ tilemap[x][y] = 0;\r
+ if ( (unsigned)actorat[x][y] == AMBUSHTILE)\r
+ actorat[x][y] = NULL;\r
+\r
+ if (*map >= AREATILE)\r
+ tile = *map;\r
+ if (*(map-1-mapwidth) >= AREATILE)\r
+ tile = *(map-1-mapwidth);\r
+ if (*(map-1+mapwidth) >= AREATILE)\r
+ tile = *(map-1+mapwidth);\r
+ if ( *(map-2) >= AREATILE)\r
+ tile = *(map-2);\r
+\r
+ *(map-1) = tile;\r
+ }\r
+ }\r
+\r
+\r
+\r
+//\r
+// have the caching manager load and purge stuff to make sure all marks\r
+// are in memory\r
+//\r
+ CA_LoadAllSounds ();\r
+\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= DrawPlayBorderSides\r
+=\r
+= To fix window overwrites\r
+=\r
+===================\r
+*/\r
+\r
+void DrawPlayBorderSides (void)\r
+{\r
+ int xl,yl;\r
+\r
+ xl = 160-viewwidth/2;\r
+ yl = (200-STATUSLINES-viewheight)/2;\r
+\r
+ VWB_Bar (0,0,xl-1,200-STATUSLINES,127);\r
+ VWB_Bar (xl+viewwidth+1,0,xl-2,200-STATUSLINES,127);\r
+\r
+ VWB_Vlin (yl-1,yl+viewheight,xl-1,0);\r
+ VWB_Vlin (yl-1,yl+viewheight,xl+viewwidth,125);\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= DrawAllPlayBorderSides\r
+=\r
+===================\r
+*/\r
+\r
+void DrawAllPlayBorderSides (void)\r
+{\r
+ unsigned i,temp;\r
+\r
+ temp = bufferofs;\r
+ for (i=0;i<3;i++)\r
+ {\r
+ bufferofs = screenloc[i];\r
+ DrawPlayBorderSides ();\r
+ }\r
+ bufferofs = temp;\r
+}\r
+\r
+/*\r
+===================\r
+=\r
+= DrawPlayBorder\r
+=\r
+===================\r
+*/\r
+void DrawAllPlayBorder (void)\r
+{\r
+ unsigned i,temp;\r
+\r
+ temp = bufferofs;\r
+ for (i=0;i<3;i++)\r
+ {\r
+ bufferofs = screenloc[i];\r
+ DrawPlayBorder ();\r
+ }\r
+ bufferofs = temp;\r
+}\r
+\r
+/*\r
+===================\r
+=\r
+= DrawPlayBorder\r
+=\r
+===================\r
+*/\r
+\r
+void DrawPlayBorder (void)\r
+{\r
+ int xl,yl;\r
+\r
+ VWB_Bar (0,0,320,200-STATUSLINES,127);\r
+\r
+ xl = 160-viewwidth/2;\r
+ yl = (200-STATUSLINES-viewheight)/2;\r
+ VWB_Bar (xl,yl,viewwidth,viewheight,0);\r
+\r
+ VWB_Hlin (xl-1,xl+viewwidth,yl-1,0);\r
+ VWB_Hlin (xl-1,xl+viewwidth,yl+viewheight,125);\r
+ VWB_Vlin (yl-1,yl+viewheight,xl-1,0);\r
+ VWB_Vlin (yl-1,yl+viewheight,xl+viewwidth,125);\r
+ VWB_Plot (xl-1,yl+viewheight,124);\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= DrawPlayScreen\r
+=\r
+===================\r
+*/\r
+\r
+void DrawPlayScreen (void)\r
+{\r
+ int i,j,p,m;\r
+ unsigned temp;\r
+\r
+ VW_FadeOut ();\r
+\r
+ temp = bufferofs;\r
+\r
+ CA_CacheGrChunk (STATUSBARPIC);\r
+\r
+ for (i=0;i<3;i++)\r
+ {\r
+ bufferofs = screenloc[i];\r
+ DrawPlayBorder ();\r
+ VWB_DrawPic (0,200-STATUSLINES,STATUSBARPIC);\r
+ }\r
+\r
+ bufferofs = temp;\r
+\r
+ UNCACHEGRCHUNK (STATUSBARPIC);\r
+\r
+ DrawFace ();\r
+ DrawHealth ();\r
+ DrawLives ();\r
+ DrawLevel ();\r
+ DrawAmmo ();\r
+ DrawKeys ();\r
+ DrawWeapon ();\r
+ DrawScore ();\r
+}\r
+\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= StartDemoRecord\r
+=\r
+==================\r
+*/\r
+\r
+#define MAXDEMOSIZE 8192\r
+\r
+void StartDemoRecord (int levelnumber)\r
+{\r
+ MM_GetPtr (&demobuffer,MAXDEMOSIZE);\r
+ MM_SetLock (&demobuffer,true);\r
+ demoptr = (char far *)demobuffer;\r
+ lastdemoptr = demoptr+MAXDEMOSIZE;\r
+\r
+ *demoptr = levelnumber;\r
+ demoptr += 4; // leave space for length\r
+ demorecord = true;\r
+}\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= FinishDemoRecord\r
+=\r
+==================\r
+*/\r
+\r
+char demoname[13] = "DEMO?.";\r
+\r
+void FinishDemoRecord (void)\r
+{\r
+ long length,level;\r
+\r
+ demorecord = false;\r
+\r
+ length = demoptr - (char far *)demobuffer;\r
+\r
+ demoptr = ((char far *)demobuffer)+1;\r
+ *(unsigned far *)demoptr = length;\r
+\r
+ CenterWindow(24,3);\r
+ PrintY+=6;\r
+ US_Print(" Demo number (0-9):");\r
+ VW_UpdateScreen();\r
+\r
+ if (US_LineInput (px,py,str,NULL,true,2,0))\r
+ {\r
+ level = atoi (str);\r
+ if (level>=0 && level<=9)\r
+ {\r
+ demoname[4] = '0'+level;\r
+ CA_WriteFile (demoname,(void far *)demobuffer,length);\r
+ }\r
+ }\r
+\r
+\r
+ MM_FreePtr (&demobuffer);\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= RecordDemo\r
+=\r
+= Fades the screen out, then starts a demo. Exits with the screen faded\r
+=\r
+==================\r
+*/\r
+\r
+void RecordDemo (void)\r
+{\r
+ int level,esc;\r
+\r
+ CenterWindow(26,3);\r
+ PrintY+=6;\r
+ CA_CacheGrChunk(STARTFONT);\r
+ fontnumber=0;\r
+ US_Print(" Demo which level(1-10):");\r
+ VW_UpdateScreen();\r
+ VW_FadeIn ();\r
+ esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
+ if (esc)\r
+ return;\r
+\r
+ level = atoi (str);\r
+ level--;\r
+\r
+ SETFONTCOLOR(0,15);\r
+ VW_FadeOut ();\r
+\r
+#ifndef SPEAR\r
+ NewGame (gd_hard,level/10);\r
+ gamestate.mapon = level%10;\r
+#else\r
+ NewGame (gd_hard,0);\r
+ gamestate.mapon = level;\r
+#endif\r
+\r
+ StartDemoRecord (level);\r
+\r
+ DrawPlayScreen ();\r
+ VW_FadeIn ();\r
+\r
+ startgame = false;\r
+ demorecord = true;\r
+\r
+ SetupGameLevel ();\r
+ StartMusic ();\r
+ PM_CheckMainMem ();\r
+ fizzlein = true;\r
+\r
+ PlayLoop ();\r
+\r
+ demoplayback = false;\r
+\r
+ StopMusic ();\r
+ VW_FadeOut ();\r
+ ClearMemory ();\r
+\r
+ FinishDemoRecord ();\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= PlayDemo\r
+=\r
+= Fades the screen out, then starts a demo. Exits with the screen faded\r
+=\r
+==================\r
+*/\r
+\r
+void PlayDemo (int demonumber)\r
+{\r
+ int length;\r
+\r
+#ifdef DEMOSEXTERN\r
+// debug: load chunk\r
+#ifndef SPEARDEMO\r
+ int dems[4]={T_DEMO0,T_DEMO1,T_DEMO2,T_DEMO3};\r
+#else\r
+ int dems[1]={T_DEMO0};\r
+#endif\r
+\r
+ CA_CacheGrChunk(dems[demonumber]);\r
+ demoptr = grsegs[dems[demonumber]];\r
+ MM_SetLock (&grsegs[dems[demonumber]],true);\r
+#else\r
+ demoname[4] = '0'+demonumber;\r
+ CA_LoadFile (demoname,&demobuffer);\r
+ MM_SetLock (&demobuffer,true);\r
+ demoptr = (char far *)demobuffer;\r
+#endif\r
+\r
+ NewGame (1,0);\r
+ gamestate.mapon = *demoptr++;\r
+ gamestate.difficulty = gd_hard;\r
+ length = *((unsigned far *)demoptr)++;\r
+ demoptr++;\r
+ lastdemoptr = demoptr-4+length;\r
+\r
+ VW_FadeOut ();\r
+\r
+ SETFONTCOLOR(0,15);\r
+ DrawPlayScreen ();\r
+ VW_FadeIn ();\r
+\r
+ startgame = false;\r
+ demoplayback = true;\r
+\r
+ SetupGameLevel ();\r
+ StartMusic ();\r
+ PM_CheckMainMem ();\r
+ fizzlein = true;\r
+\r
+ PlayLoop ();\r
+\r
+#ifdef DEMOSEXTERN\r
+ UNCACHEGRCHUNK(dems[demonumber]);\r
+#else\r
+ MM_FreePtr (&demobuffer);\r
+#endif\r
+\r
+ demoplayback = false;\r
+\r
+ StopMusic ();\r
+ VW_FadeOut ();\r
+ ClearMemory ();\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= Died\r
+=\r
+==================\r
+*/\r
+\r
+#define DEATHROTATE 2\r
+\r
+void Died (void)\r
+{\r
+ float fangle;\r
+ long dx,dy;\r
+ int iangle,curangle,clockwise,counter,change;\r
+\r
+ gamestate.weapon = -1; // take away weapon\r
+ SD_PlaySound (PLAYERDEATHSND);\r
+//\r
+// swing around to face attacker\r
+//\r
+ dx = killerobj->x - player->x;\r
+ dy = player->y - killerobj->y;\r
+\r
+ fangle = atan2(dy,dx); // returns -pi to pi\r
+ if (fangle<0)\r
+ fangle = M_PI*2+fangle;\r
+\r
+ iangle = fangle/(M_PI*2)*ANGLES;\r
+\r
+ if (player->angle > iangle)\r
+ {\r
+ counter = player->angle - iangle;\r
+ clockwise = ANGLES-player->angle + iangle;\r
+ }\r
+ else\r
+ {\r
+ clockwise = iangle - player->angle;\r
+ counter = player->angle + ANGLES-iangle;\r
+ }\r
+\r
+ curangle = player->angle;\r
+\r
+ if (clockwise<counter)\r
+ {\r
+ //\r
+ // rotate clockwise\r
+ //\r
+ if (curangle>iangle)\r
+ curangle -= ANGLES;\r
+ do\r
+ {\r
+ change = tics*DEATHROTATE;\r
+ if (curangle + change > iangle)\r
+ change = iangle-curangle;\r
+\r
+ curangle += change;\r
+ player->angle += change;\r
+ if (player->angle >= ANGLES)\r
+ player->angle -= ANGLES;\r
+\r
+ ThreeDRefresh ();\r
+ CalcTics ();\r
+ } while (curangle != iangle);\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // rotate counterclockwise\r
+ //\r
+ if (curangle<iangle)\r
+ curangle += ANGLES;\r
+ do\r
+ {\r
+ change = -tics*DEATHROTATE;\r
+ if (curangle + change < iangle)\r
+ change = iangle-curangle;\r
+\r
+ curangle += change;\r
+ player->angle += change;\r
+ if (player->angle < 0)\r
+ player->angle += ANGLES;\r
+\r
+ ThreeDRefresh ();\r
+ CalcTics ();\r
+ } while (curangle != iangle);\r
+ }\r
+\r
+//\r
+// fade to red\r
+//\r
+ FinishPaletteShifts ();\r
+\r
+ bufferofs += screenofs;\r
+ VW_Bar (0,0,viewwidth,viewheight,4);\r
+ IN_ClearKeysDown ();\r
+ FizzleFade(bufferofs,displayofs+screenofs,viewwidth,viewheight,70,false);\r
+ bufferofs -= screenofs;\r
+ IN_UserInput(100);\r
+ SD_WaitSoundDone ();\r
+\r
+ if (tedlevel == false) // SO'S YA DON'T GET KILLED WHILE LAUNCHING!\r
+ gamestate.lives--;\r
+\r
+ if (gamestate.lives > -1)\r
+ {\r
+ gamestate.health = 100;\r
+ gamestate.weapon = gamestate.bestweapon\r
+ = gamestate.chosenweapon = wp_pistol;\r
+ gamestate.ammo = STARTAMMO;\r
+ gamestate.keys = 0;\r
+ gamestate.attackframe = gamestate.attackcount =\r
+ gamestate.weaponframe = 0;\r
+\r
+ DrawKeys ();\r
+ DrawWeapon ();\r
+ DrawAmmo ();\r
+ DrawHealth ();\r
+ DrawFace ();\r
+ DrawLives ();\r
+ }\r
+\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= GameLoop\r
+=\r
+===================\r
+*/\r
+\r
+void GameLoop (void)\r
+{\r
+ int i,xl,yl,xh,yh;\r
+ char num[20];\r
+ boolean died;\r
+#ifdef MYPROFILE\r
+ clock_t start,end;\r
+#endif\r
+\r
+restartgame:\r
+ ClearMemory ();\r
+ SETFONTCOLOR(0,15);\r
+ DrawPlayScreen ();\r
+ died = false;\r
+restart:\r
+ do\r
+ {\r
+ if (!loadedgame)\r
+ gamestate.score = gamestate.oldscore;\r
+ DrawScore();\r
+\r
+ startgame = false;\r
+ if (loadedgame)\r
+ loadedgame = false;\r
+ else\r
+ SetupGameLevel ();\r
+\r
+#ifdef SPEAR\r
+ if (gamestate.mapon == 20) // give them the key allways\r
+ {\r
+ gamestate.keys |= 1;\r
+ DrawKeys ();\r
+ }\r
+#endif\r
+\r
+ ingame = true;\r
+ StartMusic ();\r
+ PM_CheckMainMem ();\r
+ if (!died)\r
+ PreloadGraphics ();\r
+ else\r
+ died = false;\r
+\r
+ fizzlein = true;\r
+ DrawLevel ();\r
+\r
+startplayloop:\r
+ PlayLoop ();\r
+\r
+#ifdef SPEAR\r
+ if (spearflag)\r
+ {\r
+ SD_StopSound();\r
+ SD_PlaySound(GETSPEARSND);\r
+ if (DigiMode != sds_Off)\r
+ {\r
+ long lasttimecount = TimeCount;\r
+\r
+ while(TimeCount < lasttimecount+150)\r
+ //while(DigiPlaying!=false)\r
+ SD_Poll();\r
+ }\r
+ else\r
+ SD_WaitSoundDone();\r
+\r
+ ClearMemory ();\r
+ gamestate.oldscore = gamestate.score;\r
+ gamestate.mapon = 20;\r
+ SetupGameLevel ();\r
+ StartMusic ();\r
+ PM_CheckMainMem ();\r
+ player->x = spearx;\r
+ player->y = speary;\r
+ player->angle = spearangle;\r
+ spearflag = false;\r
+ Thrust (0,0);\r
+ goto startplayloop;\r
+ }\r
+#endif\r
+\r
+ StopMusic ();\r
+ ingame = false;\r
+\r
+ if (demorecord && playstate != ex_warped)\r
+ FinishDemoRecord ();\r
+\r
+ if (startgame || loadedgame)\r
+ goto restartgame;\r
+\r
+ switch (playstate)\r
+ {\r
+ case ex_completed:\r
+ case ex_secretlevel:\r
+ gamestate.keys = 0;\r
+ DrawKeys ();\r
+ VW_FadeOut ();\r
+\r
+ ClearMemory ();\r
+\r
+ LevelCompleted (); // do the intermission\r
+#ifdef SPEARDEMO\r
+ if (gamestate.mapon == 1)\r
+ {\r
+ died = true; // don't "get psyched!"\r
+\r
+ VW_FadeOut ();\r
+\r
+ ClearMemory ();\r
+\r
+ CheckHighScore (gamestate.score,gamestate.mapon+1);\r
+\r
+ #pragma warn -sus\r
+ #ifndef JAPAN\r
+ _fstrcpy(MainMenu[viewscores].string,STR_VS);\r
+ #endif\r
+ MainMenu[viewscores].routine = CP_ViewScores;\r
+ #pragma warn +sus\r
+\r
+ return;\r
+ }\r
+#endif\r
+\r
+#ifdef JAPDEMO\r
+ if (gamestate.mapon == 3)\r
+ {\r
+ died = true; // don't "get psyched!"\r
+\r
+ VW_FadeOut ();\r
+\r
+ ClearMemory ();\r
+\r
+ CheckHighScore (gamestate.score,gamestate.mapon+1);\r
+\r
+ #pragma warn -sus\r
+ #ifndef JAPAN\r
+ _fstrcpy(MainMenu[viewscores].string,STR_VS);\r
+ #endif\r
+ MainMenu[viewscores].routine = CP_ViewScores;\r
+ #pragma warn +sus\r
+\r
+ return;\r
+ }\r
+#endif\r
+\r
+ gamestate.oldscore = gamestate.score;\r
+\r
+#ifndef SPEAR\r
+ //\r
+ // COMING BACK FROM SECRET LEVEL\r
+ //\r
+ if (gamestate.mapon == 9)\r
+ gamestate.mapon = ElevatorBackTo[gamestate.episode]; // back from secret\r
+ else\r
+ //\r
+ // GOING TO SECRET LEVEL\r
+ //\r
+ if (playstate == ex_secretlevel)\r
+ gamestate.mapon = 9;\r
+#else\r
+\r
+#define FROMSECRET1 3\r
+#define FROMSECRET2 11\r
+\r
+ //\r
+ // GOING TO SECRET LEVEL\r
+ //\r
+ if (playstate == ex_secretlevel)\r
+ switch(gamestate.mapon)\r
+ {\r
+ case FROMSECRET1: gamestate.mapon = 18; break;\r
+ case FROMSECRET2: gamestate.mapon = 19; break;\r
+ }\r
+ else\r
+ //\r
+ // COMING BACK FROM SECRET LEVEL\r
+ //\r
+ if (gamestate.mapon == 18 || gamestate.mapon == 19)\r
+ switch(gamestate.mapon)\r
+ {\r
+ case 18: gamestate.mapon = FROMSECRET1+1; break;\r
+ case 19: gamestate.mapon = FROMSECRET2+1; break;\r
+ }\r
+#endif\r
+ else\r
+ //\r
+ // GOING TO NEXT LEVEL\r
+ //\r
+ gamestate.mapon++;\r
+\r
+\r
+ break;\r
+\r
+ case ex_died:\r
+ Died ();\r
+ died = true; // don't "get psyched!"\r
+\r
+ if (gamestate.lives > -1)\r
+ break; // more lives left\r
+\r
+ VW_FadeOut ();\r
+\r
+ ClearMemory ();\r
+\r
+ CheckHighScore (gamestate.score,gamestate.mapon+1);\r
+\r
+ #pragma warn -sus\r
+ #ifndef JAPAN\r
+ _fstrcpy(MainMenu[viewscores].string,STR_VS);\r
+ #endif\r
+ MainMenu[viewscores].routine = CP_ViewScores;\r
+ #pragma warn +sus\r
+\r
+ return;\r
+\r
+ case ex_victorious:\r
+\r
+#ifndef SPEAR\r
+ VW_FadeOut ();\r
+#else\r
+ VL_FadeOut (0,255,0,17,17,300);\r
+#endif\r
+ ClearMemory ();\r
+\r
+ Victory ();\r
+\r
+ ClearMemory ();\r
+\r
+ CheckHighScore (gamestate.score,gamestate.mapon+1);\r
+\r
+ #pragma warn -sus\r
+ #ifndef JAPAN\r
+ _fstrcpy(MainMenu[viewscores].string,STR_VS);\r
+ #endif\r
+ MainMenu[viewscores].routine = CP_ViewScores;\r
+ #pragma warn +sus\r
+\r
+ return;\r
+\r
+ default:\r
+ ClearMemory ();\r
+ break;\r
+ }\r
+\r
+ } while (1);\r
+\r
+}\r
+\r
--- /dev/null
+// WL_INTER.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= CLearSplitVWB\r
+=\r
+==================\r
+*/\r
+\r
+void ClearSplitVWB (void)\r
+{\r
+ memset (update,0,sizeof(update));\r
+ WindowX = 0;\r
+ WindowY = 0;\r
+ WindowW = 320;\r
+ WindowH = 160;\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+#ifdef SPEAR\r
+#ifndef SPEARDEMO\r
+////////////////////////////////////////////////////////\r
+//\r
+// End of Spear of Destiny\r
+//\r
+////////////////////////////////////////////////////////\r
+\r
+void EndScreen (int palette, int screen)\r
+{\r
+ CA_CacheScreen (screen);\r
+ VW_UpdateScreen ();\r
+ CA_CacheGrChunk (palette);\r
+ VL_FadeIn(0,255,grsegs[palette],30);\r
+ UNCACHEGRCHUNK (palette);\r
+ IN_ClearKeysDown ();\r
+ IN_Ack ();\r
+ VW_FadeOut ();\r
+}\r
+\r
+\r
+void EndSpear(void)\r
+{\r
+ EndScreen (END1PALETTE, ENDSCREEN11PIC);\r
+\r
+ CA_CacheScreen (ENDSCREEN3PIC);\r
+ VW_UpdateScreen ();\r
+ CA_CacheGrChunk (END3PALETTE);\r
+ VL_FadeIn(0,255,grsegs[END3PALETTE],30);\r
+ UNCACHEGRCHUNK (END3PALETTE);\r
+ fontnumber = 0;\r
+ fontcolor = 0xd0;\r
+ WindowX = 0;\r
+ WindowW = 320;\r
+ PrintX = 0;\r
+ PrintY = 180;\r
+ US_CPrint (STR_ENDGAME1"\n");\r
+ US_CPrint (STR_ENDGAME2);\r
+ VW_UpdateScreen ();\r
+ IN_StartAck ();\r
+ TimeCount = 0;\r
+ while (!IN_CheckAck () && TimeCount < 700);\r
+\r
+ PrintX = 0;\r
+ PrintY = 180;\r
+ VWB_Bar(0,180,320,20,0);\r
+ US_CPrint (STR_ENDGAME3"\n");\r
+ US_CPrint (STR_ENDGAME4);\r
+ VW_UpdateScreen ();\r
+ IN_StartAck ();\r
+ TimeCount = 0;\r
+ while (!IN_CheckAck () && TimeCount < 700);\r
+\r
+ VW_FadeOut ();\r
+\r
+ EndScreen (END4PALETTE, ENDSCREEN4PIC);\r
+ EndScreen (END5PALETTE, ENDSCREEN5PIC);\r
+ EndScreen (END6PALETTE, ENDSCREEN6PIC);\r
+ EndScreen (END7PALETTE, ENDSCREEN7PIC);\r
+ EndScreen (END8PALETTE, ENDSCREEN8PIC);\r
+ EndScreen (END9PALETTE, ENDSCREEN9PIC);\r
+\r
+ EndScreen (END2PALETTE, ENDSCREEN12PIC);\r
+\r
+ MainMenu[savegame].active = 0;\r
+}\r
+#endif\r
+#endif\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= Victory\r
+=\r
+==================\r
+*/\r
+\r
+void Victory (void)\r
+{\r
+#ifndef SPEARDEMO\r
+ long sec;\r
+ int i,min,kr,sr,tr,x;\r
+ char tempstr[8];\r
+\r
+#define RATIOX 6\r
+#define RATIOY 14\r
+#define TIMEX 14\r
+#define TIMEY 8\r
+\r
+\r
+#ifdef SPEAR\r
+ StartCPMusic (XTHEEND_MUS);\r
+\r
+ CA_CacheGrChunk(BJCOLLAPSE1PIC);\r
+ CA_CacheGrChunk(BJCOLLAPSE2PIC);\r
+ CA_CacheGrChunk(BJCOLLAPSE3PIC);\r
+ CA_CacheGrChunk(BJCOLLAPSE4PIC);\r
+\r
+ VWB_Bar(0,0,320,200,VIEWCOLOR);\r
+ VWB_DrawPic (124,44,BJCOLLAPSE1PIC);\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn ();\r
+ VW_WaitVBL(2*70);\r
+ VWB_DrawPic (124,44,BJCOLLAPSE2PIC);\r
+ VW_UpdateScreen ();\r
+ VW_WaitVBL(105);\r
+ VWB_DrawPic (124,44,BJCOLLAPSE3PIC);\r
+ VW_UpdateScreen ();\r
+ VW_WaitVBL(105);\r
+ VWB_DrawPic (124,44,BJCOLLAPSE4PIC);\r
+ VW_UpdateScreen ();\r
+ VW_WaitVBL(3*70);\r
+\r
+ UNCACHEGRCHUNK(BJCOLLAPSE1PIC);\r
+ UNCACHEGRCHUNK(BJCOLLAPSE2PIC);\r
+ UNCACHEGRCHUNK(BJCOLLAPSE3PIC);\r
+ UNCACHEGRCHUNK(BJCOLLAPSE4PIC);\r
+ VL_FadeOut (0,255,0,17,17,5);\r
+#endif\r
+\r
+ StartCPMusic (URAHERO_MUS);\r
+ ClearSplitVWB ();\r
+ CacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END);\r
+ CA_CacheGrChunk(STARTFONT);\r
+\r
+#ifndef SPEAR\r
+ CA_CacheGrChunk(C_TIMECODEPIC);\r
+#endif\r
+\r
+\r
+ VWB_Bar (0,0,320,200-STATUSLINES,127);\r
+#ifdef JAPAN\r
+#ifndef JAPDEMO\r
+ CA_CacheGrChunk(C_ENDRATIOSPIC);\r
+ VWB_DrawPic(0,0,C_ENDRATIOSPIC);\r
+ UNCACHEGRCHUNK(C_ENDRATIOSPIC);\r
+#endif\r
+#else\r
+ Write(18,2,STR_YOUWIN);\r
+\r
+ Write(TIMEX,TIMEY-2,STR_TOTALTIME);\r
+\r
+ Write(12,RATIOY-2,"averages");\r
+\r
+ #ifdef SPANISH\r
+ Write(RATIOX+2, RATIOY, STR_RATKILL);\r
+ Write(RATIOX+2, RATIOY+2, STR_RATSECRET);\r
+ Write(RATIOX+2, RATIOY+4,STR_RATTREASURE);\r
+ #else\r
+ Write(RATIOX+8,RATIOY, STR_RATKILL);\r
+ Write(RATIOX+4,RATIOY+2, STR_RATSECRET);\r
+ Write(RATIOX, RATIOY+4,STR_RATTREASURE);\r
+ #endif\r
+\r
+#endif\r
+\r
+#ifndef JAPDEMO\r
+ VWB_DrawPic (8,4,L_BJWINSPIC);\r
+#endif\r
+\r
+\r
+#ifndef SPEAR\r
+ for (kr = sr = tr = sec = i = 0;i < 8;i++)\r
+#else\r
+ for (kr = sr = tr = sec = i = 0;i < 20;i++)\r
+#endif\r
+ {\r
+ sec += LevelRatios[i].time;\r
+ kr += LevelRatios[i].kill;\r
+ sr += LevelRatios[i].secret;\r
+ tr += LevelRatios[i].treasure;\r
+ }\r
+\r
+#ifndef SPEAR\r
+ kr /= 8;\r
+ sr /= 8;\r
+ tr /= 8;\r
+#else\r
+ kr /= 14;\r
+ sr /= 14;\r
+ tr /= 14;\r
+#endif\r
+\r
+ min = sec/60;\r
+ sec %= 60;\r
+\r
+ if (min > 99)\r
+ min = sec = 99;\r
+\r
+ i = TIMEX*8+1;\r
+ VWB_DrawPic(i,TIMEY*8,L_NUM0PIC+(min/10));\r
+ i += 2*8;\r
+ VWB_DrawPic(i,TIMEY*8,L_NUM0PIC+(min%10));\r
+ i += 2*8;\r
+ Write(i/8,TIMEY,":");\r
+ i += 1*8;\r
+ VWB_DrawPic(i,TIMEY*8,L_NUM0PIC+(sec/10));\r
+ i += 2*8;\r
+ VWB_DrawPic(i,TIMEY*8,L_NUM0PIC+(sec%10));\r
+ VW_UpdateScreen ();\r
+\r
+ itoa(kr,tempstr,10);\r
+ x=RATIOX+24-strlen(tempstr)*2;\r
+ Write(x,RATIOY,tempstr);\r
+\r
+ itoa(sr,tempstr,10);\r
+ x=RATIOX+24-strlen(tempstr)*2;\r
+ Write(x,RATIOY+2,tempstr);\r
+\r
+ itoa(tr,tempstr,10);\r
+ x=RATIOX+24-strlen(tempstr)*2;\r
+ Write(x,RATIOY+4,tempstr);\r
+\r
+\r
+#ifndef SPANISH\r
+#ifndef UPLOAD\r
+#ifndef SPEAR\r
+ //\r
+ // TOTAL TIME VERIFICATION CODE\r
+ //\r
+ if (gamestate.difficulty>=gd_medium)\r
+ {\r
+ VWB_DrawPic (30*8,TIMEY*8,C_TIMECODEPIC);\r
+ fontnumber = 0;\r
+ fontcolor = READHCOLOR;\r
+ PrintX = 30*8-3;\r
+ PrintY = TIMEY*8+8;\r
+ PrintX+=4;\r
+ tempstr[0] = (((min/10)^(min%10))^0xa)+'A';\r
+ tempstr[1] = (((sec/10)^(sec%10))^0xa)+'A';\r
+ tempstr[2] = (tempstr[0]^tempstr[1])+'A';\r
+ tempstr[3] = 0;\r
+ US_Print(tempstr);\r
+ }\r
+#endif\r
+#endif\r
+#endif\r
+\r
+\r
+ fontnumber = 1;\r
+\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn ();\r
+\r
+ IN_Ack();\r
+\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+\r
+ VW_FadeOut ();\r
+\r
+#ifndef SPEAR\r
+ UNCACHEGRCHUNK(C_TIMECODEPIC);\r
+#endif\r
+ UnCacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END);\r
+\r
+#ifndef SPEAR\r
+ EndText();\r
+#else\r
+ EndSpear();\r
+#endif\r
+\r
+#endif // SPEARDEMO\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+#ifndef JAPAN\r
+/*\r
+==================\r
+=\r
+= PG13\r
+=\r
+==================\r
+*/\r
+\r
+void PG13 (void)\r
+{\r
+ VW_FadeOut();\r
+ VWB_Bar(0,0,320,200,0x82); // background\r
+\r
+ CA_CacheGrChunk (PG13PIC);\r
+ VWB_DrawPic (216,110,PG13PIC);\r
+ VW_UpdateScreen ();\r
+\r
+ UNCACHEGRCHUNK (PG13PIC);\r
+\r
+ VW_FadeIn();\r
+ IN_UserInput(TickBase*7);\r
+\r
+ VW_FadeOut ();\r
+}\r
+#endif\r
+\r
+\r
+//==========================================================================\r
+\r
+void Write(int x,int y,char *string)\r
+{\r
+ int alpha[]={L_NUM0PIC,L_NUM1PIC,L_NUM2PIC,L_NUM3PIC,L_NUM4PIC,L_NUM5PIC,\r
+ L_NUM6PIC,L_NUM7PIC,L_NUM8PIC,L_NUM9PIC,L_COLONPIC,0,0,0,0,0,0,L_APIC,L_BPIC,\r
+ L_CPIC,L_DPIC,L_EPIC,L_FPIC,L_GPIC,L_HPIC,L_IPIC,L_JPIC,L_KPIC,\r
+ L_LPIC,L_MPIC,L_NPIC,L_OPIC,L_PPIC,L_QPIC,L_RPIC,L_SPIC,L_TPIC,\r
+ L_UPIC,L_VPIC,L_WPIC,L_XPIC,L_YPIC,L_ZPIC};\r
+\r
+ int i,ox,nx,ny;\r
+ char ch;\r
+\r
+\r
+ ox=nx=x*8;\r
+ ny=y*8;\r
+ for (i=0;i<strlen(string);i++)\r
+ if (string[i]=='\n')\r
+ {\r
+ nx=ox;\r
+ ny+=16;\r
+ }\r
+ else\r
+ {\r
+ ch=string[i];\r
+ if (ch>='a')\r
+ ch-=('a'-'A');\r
+ ch-='0';\r
+\r
+ switch(string[i])\r
+ {\r
+ case '!':\r
+ VWB_DrawPic(nx,ny,L_EXPOINTPIC);\r
+ nx+=8;\r
+ continue;\r
+\r
+ case '\'':\r
+ VWB_DrawPic(nx,ny,L_APOSTROPHEPIC);\r
+ nx+=8;\r
+ continue;\r
+\r
+ case ' ': break;\r
+ case 0x3a: // ':'\r
+\r
+ VWB_DrawPic(nx,ny,L_COLONPIC);\r
+ nx+=8;\r
+ continue;\r
+\r
+ case '%':\r
+ VWB_DrawPic(nx,ny,L_PERCENTPIC);\r
+ break;\r
+\r
+ default:\r
+ VWB_DrawPic(nx,ny,alpha[ch]);\r
+ }\r
+ nx+=16;\r
+ }\r
+}\r
+\r
+\r
+//\r
+// Breathe Mr. BJ!!!\r
+//\r
+void BJ_Breathe(void)\r
+{\r
+ static int which=0,max=10;\r
+ int pics[2]={L_GUYPIC,L_GUY2PIC};\r
+\r
+\r
+ if (TimeCount>max)\r
+ {\r
+ which^=1;\r
+ VWB_DrawPic(0,16,pics[which]);\r
+ VW_UpdateScreen();\r
+ TimeCount=0;\r
+ max=35;\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= LevelCompleted\r
+=\r
+= Entered with the screen faded out\r
+= Still in split screen mode with the status bar\r
+=\r
+= Exit with the screen faded out\r
+=\r
+==================\r
+*/\r
+\r
+#ifndef SPEAR\r
+LRstruct LevelRatios[8];\r
+#else\r
+LRstruct LevelRatios[20];\r
+#endif\r
+\r
+void LevelCompleted (void)\r
+{\r
+ #define VBLWAIT 30\r
+ #define PAR_AMOUNT 500\r
+ #define PERCENT100AMT 10000\r
+ typedef struct {\r
+ float time;\r
+ char timestr[6];\r
+ } times;\r
+\r
+ int x,i,min,sec,ratio,kr,sr,tr;\r
+ unsigned temp;\r
+ char tempstr[10];\r
+ long bonus,timeleft=0;\r
+ times parTimes[]=\r
+ {\r
+#ifndef SPEAR\r
+ //\r
+ // Episode One Par Times\r
+ //\r
+ {1.5, "01:30"},\r
+ {2, "02:00"},\r
+ {2, "02:00"},\r
+ {3.5, "03:30"},\r
+ {3, "03:00"},\r
+ {3, "03:00"},\r
+ {2.5, "02:30"},\r
+ {2.5, "02:30"},\r
+ {0, "??:??"}, // Boss level\r
+ {0, "??:??"}, // Secret level\r
+\r
+ //\r
+ // Episode Two Par Times\r
+ //\r
+ {1.5, "01:30"},\r
+ {3.5, "03:30"},\r
+ {3, "03:00"},\r
+ {2, "02:00"},\r
+ {4, "04:00"},\r
+ {6, "06:00"},\r
+ {1, "01:00"},\r
+ {3, "03:00"},\r
+ {0, "??:??"},\r
+ {0, "??:??"},\r
+\r
+ //\r
+ // Episode Three Par Times\r
+ //\r
+ {1.5, "01:30"},\r
+ {1.5, "01:30"},\r
+ {2.5, "02:30"},\r
+ {2.5, "02:30"},\r
+ {3.5, "03:30"},\r
+ {2.5, "02:30"},\r
+ {2, "02:00"},\r
+ {6, "06:00"},\r
+ {0, "??:??"},\r
+ {0, "??:??"},\r
+\r
+ //\r
+ // Episode Four Par Times\r
+ //\r
+ {2, "02:00"},\r
+ {2, "02:00"},\r
+ {1.5, "01:30"},\r
+ {1, "01:00"},\r
+ {4.5, "04:30"},\r
+ {3.5, "03:30"},\r
+ {2, "02:00"},\r
+ {4.5, "04:30"},\r
+ {0, "??:??"},\r
+ {0, "??:??"},\r
+\r
+ //\r
+ // Episode Five Par Times\r
+ //\r
+ {2.5, "02:30"},\r
+ {1.5, "01:30"},\r
+ {2.5, "02:30"},\r
+ {2.5, "02:30"},\r
+ {4, "04:00"},\r
+ {3, "03:00"},\r
+ {4.5, "04:30"},\r
+ {3.5, "03:30"},\r
+ {0, "??:??"},\r
+ {0, "??:??"},\r
+\r
+ //\r
+ // Episode Six Par Times\r
+ //\r
+ {6.5, "06:30"},\r
+ {4, "04:00"},\r
+ {4.5, "04:30"},\r
+ {6, "06:00"},\r
+ {5, "05:00"},\r
+ {5.5, "05:30"},\r
+ {5.5, "05:30"},\r
+ {8.5, "08:30"},\r
+ {0, "??:??"},\r
+ {0, "??:??"}\r
+#else\r
+ //\r
+ // SPEAR OF DESTINY TIMES\r
+ //\r
+ {1.5, "01:30"},\r
+ {3.5, "03:30"},\r
+ {2.75, "02:45"},\r
+ {3.5, "03:30"},\r
+ {0, "??:??"}, // Boss 1\r
+ {4.5, "04:30"},\r
+ {3.25, "03:15"},\r
+ {2.75, "02:45"},\r
+ {4.75, "04:45"},\r
+ {0, "??:??"}, // Boss 2\r
+ {6.5, "06:30"},\r
+ {4.5, "04:30"},\r
+ {2.75, "02:45"},\r
+ {4.5, "04:30"},\r
+ {6, "06:00"},\r
+ {0, "??:??"}, // Boss 3\r
+ {6, "06:00"},\r
+ {0, "??:??"}, // Boss 4\r
+ {0, "??:??"}, // Secret level 1\r
+ {0, "??:??"}, // Secret level 2\r
+#endif\r
+ };\r
+\r
+\r
+\r
+ CacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END);\r
+ ClearSplitVWB (); // set up for double buffering in split screen\r
+ VWB_Bar (0,0,320,200-STATUSLINES,127);\r
+ StartCPMusic(ENDLEVEL_MUS);\r
+\r
+//\r
+// do the intermission\r
+//\r
+ IN_ClearKeysDown();\r
+ IN_StartAck();\r
+\r
+#ifdef JAPAN\r
+ CA_CacheGrChunk(C_INTERMISSIONPIC);\r
+ VWB_DrawPic(0,0,C_INTERMISSIONPIC);\r
+ UNCACHEGRCHUNK(C_INTERMISSIONPIC);\r
+#endif\r
+ VWB_DrawPic(0,16,L_GUYPIC);\r
+\r
+#ifndef SPEAR\r
+ if (mapon<8)\r
+#else\r
+ if (mapon != 4 &&\r
+ mapon != 9 &&\r
+ mapon != 15 &&\r
+ mapon < 17)\r
+#endif\r
+ {\r
+#ifndef JAPAN\r
+ #ifdef SPANISH\r
+ Write(14,2,"piso\ncompletado");\r
+ #else\r
+ Write(14,2,"floor\ncompleted");\r
+ #endif\r
+\r
+ Write(14,7,STR_BONUS" 0");\r
+ Write(16,10,STR_TIME);\r
+ Write(16,12,STR_PAR);\r
+\r
+ #ifdef SPANISH\r
+ Write(11,14, STR_RAT2KILL);\r
+ Write(11,16, STR_RAT2SECRET);\r
+ Write(11,18,STR_RAT2TREASURE);\r
+ #else\r
+ Write(9,14, STR_RAT2KILL);\r
+ Write(5,16, STR_RAT2SECRET);\r
+ Write(1,18,STR_RAT2TREASURE);\r
+ #endif\r
+\r
+ Write(26,2,itoa(gamestate.mapon+1,tempstr,10));\r
+#endif\r
+\r
+ #ifdef SPANISH\r
+ Write(30,12,parTimes[gamestate.episode*10+mapon].timestr);\r
+ #else\r
+ Write(26,12,parTimes[gamestate.episode*10+mapon].timestr);\r
+ #endif\r
+\r
+ //\r
+ // PRINT TIME\r
+ //\r
+ sec=gamestate.TimeCount/70;\r
+\r
+ if (sec > 99*60) // 99 minutes max\r
+ sec = 99*60;\r
+\r
+ if (gamestate.TimeCount<parTimes[gamestate.episode*10+mapon].time*4200)\r
+ timeleft=(parTimes[gamestate.episode*10+mapon].time*4200)/70-sec;\r
+\r
+ min=sec/60;\r
+ sec%=60;\r
+\r
+ #ifdef SPANISH\r
+ i=30*8;\r
+ #else\r
+ i=26*8;\r
+ #endif\r
+ VWB_DrawPic(i,10*8,L_NUM0PIC+(min/10));\r
+ i+=2*8;\r
+ VWB_DrawPic(i,10*8,L_NUM0PIC+(min%10));\r
+ i+=2*8;\r
+ Write(i/8,10,":");\r
+ i+=1*8;\r
+ VWB_DrawPic(i,10*8,L_NUM0PIC+(sec/10));\r
+ i+=2*8;\r
+ VWB_DrawPic(i,10*8,L_NUM0PIC+(sec%10));\r
+\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn ();\r
+\r
+\r
+ //\r
+ // FIGURE RATIOS OUT BEFOREHAND\r
+ //\r
+ kr = sr = tr = 0;\r
+ if (gamestate.killtotal)\r
+ kr=(gamestate.killcount*100)/gamestate.killtotal;\r
+ if (gamestate.secrettotal)\r
+ sr=(gamestate.secretcount*100)/gamestate.secrettotal;\r
+ if (gamestate.treasuretotal)\r
+ tr=(gamestate.treasurecount*100)/gamestate.treasuretotal;\r
+\r
+\r
+ //\r
+ // PRINT TIME BONUS\r
+ //\r
+ bonus=timeleft*PAR_AMOUNT;\r
+ if (bonus)\r
+ {\r
+ for (i=0;i<=timeleft;i++)\r
+ {\r
+ ltoa((long)i*PAR_AMOUNT,tempstr,10);\r
+ x=36-strlen(tempstr)*2;\r
+ Write(x,7,tempstr);\r
+ if (!(i%(PAR_AMOUNT/10)))\r
+ SD_PlaySound(ENDBONUS1SND);\r
+ VW_UpdateScreen();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+ if (IN_CheckAck())\r
+ goto done;\r
+ }\r
+\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(ENDBONUS2SND);\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+ }\r
+\r
+\r
+ #ifdef SPANISH\r
+ #define RATIOXX 33\r
+ #else\r
+ #define RATIOXX 37\r
+ #endif\r
+ //\r
+ // KILL RATIO\r
+ //\r
+ ratio=kr;\r
+ for (i=0;i<=ratio;i++)\r
+ {\r
+ itoa(i,tempstr,10);\r
+ x=RATIOXX-strlen(tempstr)*2;\r
+ Write(x,14,tempstr);\r
+ if (!(i%10))\r
+ SD_PlaySound(ENDBONUS1SND);\r
+ VW_UpdateScreen ();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+\r
+ if (IN_CheckAck())\r
+ goto done;\r
+ }\r
+ if (ratio==100)\r
+ {\r
+ VW_WaitVBL(VBLWAIT);\r
+ SD_StopSound();\r
+ bonus+=PERCENT100AMT;\r
+ ltoa(bonus,tempstr,10);\r
+ x=(RATIOXX-1)-strlen(tempstr)*2;\r
+ Write(x,7,tempstr);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(PERCENT100SND);\r
+ }\r
+ else\r
+ if (!ratio)\r
+ {\r
+ VW_WaitVBL(VBLWAIT);\r
+ SD_StopSound();\r
+ SD_PlaySound(NOBONUSSND);\r
+ }\r
+ else\r
+ SD_PlaySound(ENDBONUS2SND);\r
+\r
+ VW_UpdateScreen();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+\r
+\r
+ //\r
+ // SECRET RATIO\r
+ //\r
+ ratio=sr;\r
+ for (i=0;i<=ratio;i++)\r
+ {\r
+ itoa(i,tempstr,10);\r
+ x=RATIOXX-strlen(tempstr)*2;\r
+ Write(x,16,tempstr);\r
+ if (!(i%10))\r
+ SD_PlaySound(ENDBONUS1SND);\r
+ VW_UpdateScreen ();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+ BJ_Breathe();\r
+\r
+ if (IN_CheckAck())\r
+ goto done;\r
+ }\r
+ if (ratio==100)\r
+ {\r
+ VW_WaitVBL(VBLWAIT);\r
+ SD_StopSound();\r
+ bonus+=PERCENT100AMT;\r
+ ltoa(bonus,tempstr,10);\r
+ x=(RATIOXX-1)-strlen(tempstr)*2;\r
+ Write(x,7,tempstr);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(PERCENT100SND);\r
+ }\r
+ else\r
+ if (!ratio)\r
+ {\r
+ VW_WaitVBL(VBLWAIT);\r
+ SD_StopSound();\r
+ SD_PlaySound(NOBONUSSND);\r
+ }\r
+ else\r
+ SD_PlaySound(ENDBONUS2SND);\r
+ VW_UpdateScreen();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+\r
+\r
+ //\r
+ // TREASURE RATIO\r
+ //\r
+ ratio=tr;\r
+ for (i=0;i<=ratio;i++)\r
+ {\r
+ itoa(i,tempstr,10);\r
+ x=RATIOXX-strlen(tempstr)*2;\r
+ Write(x,18,tempstr);\r
+ if (!(i%10))\r
+ SD_PlaySound(ENDBONUS1SND);\r
+ VW_UpdateScreen ();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+ if (IN_CheckAck())\r
+ goto done;\r
+ }\r
+ if (ratio==100)\r
+ {\r
+ VW_WaitVBL(VBLWAIT);\r
+ SD_StopSound();\r
+ bonus+=PERCENT100AMT;\r
+ ltoa(bonus,tempstr,10);\r
+ x=(RATIOXX-1)-strlen(tempstr)*2;\r
+ Write(x,7,tempstr);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(PERCENT100SND);\r
+ }\r
+ else\r
+ if (!ratio)\r
+ {\r
+ VW_WaitVBL(VBLWAIT);\r
+ SD_StopSound();\r
+ SD_PlaySound(NOBONUSSND);\r
+ }\r
+ else\r
+ SD_PlaySound(ENDBONUS2SND);\r
+ VW_UpdateScreen();\r
+ while(SD_SoundPlaying())\r
+ BJ_Breathe();\r
+\r
+\r
+ //\r
+ // JUMP STRAIGHT HERE IF KEY PRESSED\r
+ //\r
+ done:\r
+\r
+ itoa(kr,tempstr,10);\r
+ x=RATIOXX-strlen(tempstr)*2;\r
+ Write(x,14,tempstr);\r
+\r
+ itoa(sr,tempstr,10);\r
+ x=RATIOXX-strlen(tempstr)*2;\r
+ Write(x,16,tempstr);\r
+\r
+ itoa(tr,tempstr,10);\r
+ x=RATIOXX-strlen(tempstr)*2;\r
+ Write(x,18,tempstr);\r
+\r
+ bonus=(long)timeleft*PAR_AMOUNT+\r
+ (PERCENT100AMT*(kr==100))+\r
+ (PERCENT100AMT*(sr==100))+\r
+ (PERCENT100AMT*(tr==100));\r
+\r
+ GivePoints(bonus);\r
+ ltoa(bonus,tempstr,10);\r
+ x=36-strlen(tempstr)*2;\r
+ Write(x,7,tempstr);\r
+\r
+ //\r
+ // SAVE RATIO INFORMATION FOR ENDGAME\r
+ //\r
+ LevelRatios[mapon].kill=kr;\r
+ LevelRatios[mapon].secret=sr;\r
+ LevelRatios[mapon].treasure=tr;\r
+ LevelRatios[mapon].time=min*60+sec;\r
+ }\r
+ else\r
+ {\r
+#ifdef SPEAR\r
+#ifndef SPEARDEMO\r
+ switch(mapon)\r
+ {\r
+ case 4: Write(14,4," trans\n"\r
+ " grosse\n"\r
+ STR_DEFEATED); break;\r
+ case 9: Write(14,4,"barnacle\n"\r
+ "wilhelm\n"\r
+ STR_DEFEATED); break;\r
+ case 15: Write(14,4,"ubermutant\n"\r
+ STR_DEFEATED); break;\r
+ case 17: Write(14,4," death\n"\r
+ " knight\n"\r
+ STR_DEFEATED); break;\r
+ case 18: Write(13,4,"secret tunnel\n"\r
+ " area\n"\r
+ " completed!"); break;\r
+ case 19: Write(13,4,"secret castle\n"\r
+ " area\n"\r
+ " completed!"); break;\r
+ }\r
+#endif\r
+#else\r
+ Write(14,4,"secret floor\n completed!");\r
+#endif\r
+\r
+ Write(10,16,"15000 bonus!");\r
+\r
+ VW_UpdateScreen();\r
+ VW_FadeIn();\r
+\r
+ GivePoints(15000);\r
+ }\r
+\r
+\r
+ DrawScore();\r
+ VW_UpdateScreen();\r
+\r
+ TimeCount=0;\r
+ IN_StartAck();\r
+ while(!IN_CheckAck())\r
+ BJ_Breathe();\r
+\r
+//\r
+// done\r
+//\r
+#ifdef SPEARDEMO\r
+ if (gamestate.mapon == 1)\r
+ {\r
+ SD_PlaySound (BONUS1UPSND);\r
+\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ Message ("This concludes your demo\n"\r
+ "of Spear of Destiny! Now,\n"\r
+ "go to your local software\n"\r
+ "store and buy it!");\r
+ UNCACHEGRCHUNK (STARTFONT+1);\r
+\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+ }\r
+#endif\r
+\r
+#ifdef JAPDEMO\r
+ if (gamestate.mapon == 3)\r
+ {\r
+ SD_PlaySound (BONUS1UPSND);\r
+\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ Message ("This concludes your demo\n"\r
+ "of Wolfenstein 3-D! Now,\n"\r
+ "go to your local software\n"\r
+ "store and buy it!");\r
+ UNCACHEGRCHUNK (STARTFONT+1);\r
+\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+ }\r
+#endif\r
+\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+\r
+ VW_FadeOut ();\r
+ temp = bufferofs;\r
+ for (i=0;i<3;i++)\r
+ {\r
+ bufferofs = screenloc[i];\r
+ DrawPlayBorder ();\r
+ }\r
+ bufferofs = temp;\r
+\r
+ UnCacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END);\r
+}\r
+\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= PreloadGraphics\r
+=\r
+= Fill the cache up\r
+=\r
+=================\r
+*/\r
+\r
+boolean PreloadUpdate(unsigned current, unsigned total)\r
+{\r
+ unsigned w = WindowW - 10;\r
+\r
+\r
+ VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w,2,BLACK);\r
+ w = ((long)w * current) / total;\r
+ if (w)\r
+ {\r
+ VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w,2,0x37); //SECONDCOLOR);\r
+ VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w-1,1,0x32);\r
+\r
+ }\r
+ VW_UpdateScreen();\r
+// if (LastScan == sc_Escape)\r
+// {\r
+// IN_ClearKeysDown();\r
+// return(true);\r
+// }\r
+// else\r
+ return(false);\r
+}\r
+\r
+void PreloadGraphics(void)\r
+{\r
+ DrawLevel ();\r
+ ClearSplitVWB (); // set up for double buffering in split screen\r
+\r
+ VWB_Bar (0,0,320,200-STATUSLINES,127);\r
+\r
+ LatchDrawPic (20-14,80-3*8,GETPSYCHEDPIC);\r
+\r
+ WindowX = 160-14*8;\r
+ WindowY = 80-3*8;\r
+ WindowW = 28*8;\r
+ WindowH = 48;\r
+ VW_UpdateScreen();\r
+ VW_FadeIn ();\r
+\r
+ PM_Preload (PreloadUpdate);\r
+ IN_UserInput (70);\r
+ VW_FadeOut ();\r
+\r
+ DrawPlayBorder ();\r
+ VW_UpdateScreen ();\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= DrawHighScores\r
+=\r
+==================\r
+*/\r
+\r
+void DrawHighScores(void)\r
+{\r
+ char buffer[16],*str,buffer1[5];\r
+ byte temp,temp1,temp2,temp3;\r
+ word i,j,\r
+ w,h,\r
+ x,y;\r
+ HighScore *s;\r
+\r
+\r
+ MM_SortMem ();\r
+\r
+#ifndef SPEAR\r
+// CA_CacheGrChunk (C_CODEPIC);\r
+ CA_CacheGrChunk (HIGHSCORESPIC);\r
+ CA_CacheGrChunk (STARTFONT);\r
+ CA_CacheGrChunk (C_LEVELPIC);\r
+ CA_CacheGrChunk (C_SCOREPIC);\r
+ CA_CacheGrChunk (C_NAMEPIC);\r
+\r
+ ClearMScreen();\r
+ DrawStripes(10);\r
+\r
+ VWB_DrawPic(48,0,HIGHSCORESPIC);\r
+ UNCACHEGRCHUNK (HIGHSCORESPIC);\r
+\r
+ VWB_DrawPic(4*8,68,C_NAMEPIC);\r
+ VWB_DrawPic(20*8,68,C_LEVELPIC);\r
+ VWB_DrawPic(28*8,68,C_SCOREPIC);\r
+#ifndef UPLOAD\r
+// VWB_DrawPic(35*8,68,C_CODEPIC);\r
+#endif\r
+ fontnumber=0;\r
+\r
+#else\r
+ CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ ClearMScreen();\r
+ DrawStripes(10);\r
+ UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+\r
+ CacheLump (HIGHSCORES_LUMP_START,HIGHSCORES_LUMP_END);\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ VWB_DrawPic (0,0,HIGHSCORESPIC);\r
+\r
+ fontnumber = 1;\r
+#endif\r
+\r
+\r
+#ifndef SPEAR\r
+ SETFONTCOLOR(15,0x29);\r
+#else\r
+ SETFONTCOLOR(HIGHLIGHT,0x29);\r
+#endif\r
+\r
+ for (i = 0,s = Scores;i < MaxScores;i++,s++)\r
+ {\r
+ PrintY = 76 + (16 * i);\r
+\r
+ //\r
+ // name\r
+ //\r
+#ifndef SPEAR\r
+ PrintX = 4*8;\r
+#else\r
+ PrintX = 16;\r
+#endif\r
+ US_Print(s->name);\r
+\r
+ //\r
+ // level\r
+ //\r
+ ultoa(s->completed,buffer,10);\r
+#ifndef SPEAR\r
+ for (str = buffer;*str;str++)\r
+ *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
+ USL_MeasureString(buffer,&w,&h);\r
+ PrintX = (22 * 8)-w;\r
+#else\r
+ USL_MeasureString(buffer,&w,&h);\r
+ PrintX = 194 - w;\r
+#endif\r
+\r
+#ifndef UPLOAD\r
+#ifndef SPEAR\r
+ PrintX -= 6;\r
+ itoa(s->episode+1,buffer1,10);\r
+ US_Print("E");\r
+ US_Print(buffer1);\r
+ US_Print("/L");\r
+#endif\r
+#endif\r
+\r
+#ifdef SPEAR\r
+ if (s->completed == 21)\r
+ VWB_DrawPic (PrintX+8,PrintY-1,C_WONSPEARPIC);\r
+ else\r
+#endif\r
+ US_Print(buffer);\r
+\r
+ //\r
+ // score\r
+ //\r
+ ultoa(s->score,buffer,10);\r
+#ifndef SPEAR\r
+ for (str = buffer;*str;str++)\r
+ *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
+ USL_MeasureString(buffer,&w,&h);\r
+ PrintX = (34 * 8) - 8 - w;\r
+#else\r
+ USL_MeasureString(buffer,&w,&h);\r
+ PrintX = 292 - w;\r
+#endif\r
+ US_Print(buffer);\r
+\r
+ #if 0\r
+#ifndef UPLOAD\r
+#ifndef SPEAR\r
+ //\r
+ // verification #\r
+ //\r
+ if (!i)\r
+ {\r
+ temp=(((s->score >> 28)& 0xf)^\r
+ ((s->score >> 24)& 0xf))+'A';\r
+ temp1=(((s->score >> 20)& 0xf)^\r
+ ((s->score >> 16)& 0xf))+'A';\r
+ temp2=(((s->score >> 12)& 0xf)^\r
+ ((s->score >> 8)& 0xf))+'A';\r
+ temp3=(((s->score >> 4)& 0xf)^\r
+ ((s->score >> 0)& 0xf))+'A';\r
+\r
+ SETFONTCOLOR(0x49,0x29);\r
+ PrintX = 35*8;\r
+ buffer[0]=temp;\r
+ buffer[1]=temp1;\r
+ buffer[2]=temp2;\r
+ buffer[3]=temp3;\r
+ buffer[4]=0;\r
+ US_Print(buffer);\r
+ SETFONTCOLOR(15,0x29);\r
+ }\r
+#endif\r
+#endif\r
+ #endif\r
+ }\r
+\r
+ VW_UpdateScreen ();\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (HIGHSCORES_LUMP_START,HIGHSCORES_LUMP_END);\r
+ fontnumber = 0;\r
+#endif\r
+}\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+=======================\r
+=\r
+= CheckHighScore\r
+=\r
+=======================\r
+*/\r
+\r
+void CheckHighScore (long score,word other)\r
+{\r
+ word i,j;\r
+ int n;\r
+ HighScore myscore;\r
+\r
+ strcpy(myscore.name,"");\r
+ myscore.score = score;\r
+ myscore.episode = gamestate.episode;\r
+ myscore.completed = other;\r
+\r
+ for (i = 0,n = -1;i < MaxScores;i++)\r
+ {\r
+ if\r
+ (\r
+ (myscore.score > Scores[i].score)\r
+ || (\r
+ (myscore.score == Scores[i].score)\r
+ && (myscore.completed > Scores[i].completed)\r
+ )\r
+ )\r
+ {\r
+ for (j = MaxScores;--j > i;)\r
+ Scores[j] = Scores[j - 1];\r
+ Scores[i] = myscore;\r
+ n = i;\r
+ break;\r
+ }\r
+ }\r
+\r
+#ifdef SPEAR\r
+ StartCPMusic (XAWARD_MUS);\r
+#else\r
+ StartCPMusic (ROSTER_MUS);\r
+#endif\r
+ DrawHighScores ();\r
+\r
+ VW_FadeIn ();\r
+\r
+ if (n != -1)\r
+ {\r
+ //\r
+ // got a high score\r
+ //\r
+ PrintY = 76 + (16 * n);\r
+#ifndef SPEAR\r
+ PrintX = 4*8;\r
+ backcolor = BORDCOLOR;\r
+ fontcolor = 15;\r
+ US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,100);\r
+#else\r
+ PrintX = 16;\r
+ fontnumber = 1;\r
+ VWB_Bar (PrintX-2,PrintY-2,145,15,0x9c);\r
+ VW_UpdateScreen ();\r
+ backcolor = 0x9c;\r
+ fontcolor = 15;\r
+ US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,130);\r
+#endif\r
+ }\r
+ else\r
+ {\r
+ IN_ClearKeysDown ();\r
+ IN_UserInput(500);\r
+ }\r
+\r
+}\r
+\r
+\r
+#ifndef UPLOAD\r
+#ifndef SPEAR\r
+#ifndef JAPAN\r
+////////////////////////////////////////////////////////\r
+//\r
+// NON-SHAREWARE NOTICE\r
+//\r
+////////////////////////////////////////////////////////\r
+void NonShareware(void)\r
+{\r
+ VW_FadeOut();\r
+\r
+ ClearMScreen();\r
+ DrawStripes(10);\r
+\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+ fontnumber = 1;\r
+\r
+ SETFONTCOLOR(READHCOLOR,BKGDCOLOR);\r
+ PrintX=110;\r
+ PrintY=15;\r
+\r
+ #ifdef SPANISH\r
+ US_Print("Atencion");\r
+ #else\r
+ US_Print("Attention");\r
+ #endif\r
+\r
+ SETFONTCOLOR(HIGHLIGHT,BKGDCOLOR);\r
+ WindowX=PrintX=40;\r
+ PrintY=60;\r
+ #ifdef SPANISH\r
+ US_Print("Este juego NO es gratis y\n");\r
+ US_Print("NO es Shareware; favor de\n");\r
+ US_Print("no distribuirlo.\n\n");\r
+ #else\r
+ US_Print("This game is NOT shareware.\n");\r
+ US_Print("Please do not distribute it.\n");\r
+ US_Print("Thanks.\n\n");\r
+ #endif\r
+ US_Print(" Id Software\n");\r
+\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn();\r
+ IN_Ack();\r
+}\r
+#endif\r
+#endif\r
+#endif\r
+\r
+#ifdef SPEAR\r
+#ifndef SPEARDEMO\r
+////////////////////////////////////////////////////////\r
+//\r
+// COPY PROTECTION FOR FormGen\r
+//\r
+////////////////////////////////////////////////////////\r
+char far CopyProFailedStrs[][100] = {\r
+ STR_COPY1,\r
+ STR_COPY2,\r
+\r
+ STR_COPY3,\r
+ STR_COPY4,\r
+\r
+ STR_COPY5,\r
+ STR_COPY6,\r
+\r
+ STR_COPY7,\r
+ STR_COPY8,\r
+\r
+ STR_COPY9,\r
+ "",\r
+\r
+ STR_COPY10,\r
+ STR_COPY11,\r
+\r
+ STR_COPY12,\r
+ "",\r
+\r
+ STR_COPY13,\r
+ "",\r
+\r
+ STR_COPY14,\r
+ ""\r
+ },\r
+\r
+ far BackDoorStrs[5][16] = {\r
+ "a spoon?",\r
+ "bite me!",\r
+ "joshua",\r
+ "pelt",\r
+#ifdef BETA\r
+ "beta"\r
+#else\r
+ "snoops"\r
+#endif\r
+ },\r
+\r
+ far GoodBoyStrs[10][40] = {\r
+ "...is the CORRECT ANSWER!",\r
+ "",\r
+\r
+ "Consider yourself bitten, sir.",\r
+ "",\r
+\r
+ "Greetings Professor Falken, would you",\r
+ "like to play Spear of Destiny?",\r
+\r
+ "Do you have any gold spray paint?",\r
+ "",\r
+\r
+#ifdef BETA\r
+ "Beta testing approved.",\r
+#else\r
+ "I wish I had a 21\" monitor...",\r
+#endif\r
+ ""\r
+ },\r
+\r
+ far bossstrs[4][24] = {\r
+ "DEATH KNIGHT",\r
+ "BARNACLE WILHELM",\r
+ "UBERMUTANTUBER MUTANT",\r
+ "TRANS GROSSE"\r
+ },\r
+\r
+ far WordStr[5][20] = {\r
+ "New Game",\r
+ "Sound...F4",\r
+ "Control...F6",\r
+ "Change View...F5",\r
+ "Quit...F10"},\r
+\r
+ far WordCorrect[5][2] = {"3","4","4","5","5"},\r
+\r
+ far MemberStr[10][40] = {\r
+ STR_COPY15,\r
+ "",\r
+\r
+ STR_COPY16,\r
+ "",\r
+\r
+ STR_COPY17,\r
+ STR_COPY18,\r
+\r
+ STR_COPY19,\r
+ STR_COPY20,\r
+\r
+ STR_COPY21,\r
+ STR_COPY22},\r
+\r
+ far MemberCorrect[5][24] = {\r
+ "adrian carmack",\r
+ "john carmackjohn romero",\r
+ "tom hall",\r
+ "jay wilbur",\r
+ "kevin cloud"},\r
+\r
+ far DosMessages[9][80] = {\r
+ STR_NOPE1,\r
+ STR_NOPE2,\r
+ STR_NOPE3,\r
+ STR_NOPE4,\r
+ STR_NOPE5,\r
+ STR_NOPE6,\r
+ STR_NOPE7,\r
+ STR_NOPE8,\r
+ STR_NOPE9},\r
+\r
+ far MiscTitle[4][20] = {\r
+ "BLOOD TEST",\r
+ "STRAIGHT-LACED",\r
+ "QUITE SHAPELY",\r
+ "I AM WHAT I AMMO"\r
+ },\r
+\r
+ far MiscStr[12][40] = {\r
+ STR_MISC1,\r
+ STR_MISC2,\r
+ "",\r
+\r
+ STR_MISC3,\r
+ STR_MISC4,\r
+ "",\r
+\r
+ STR_MISC5,\r
+ STR_MISC6,\r
+ "",\r
+\r
+ STR_MISC7,\r
+ STR_MISC8,\r
+ STR_MISC9\r
+ },\r
+\r
+ far MiscCorrect[4][5] = {"ss","8",STR_STAR,"45"};\r
+\r
+\r
+int BackDoor(char *s)\r
+{\r
+ int i;\r
+\r
+\r
+ strlwr(s);\r
+\r
+ for (i=0;i<5;i++)\r
+ if (!_fstrcmp(s,BackDoorStrs[i]))\r
+ {\r
+ SETFONTCOLOR(14,15);\r
+ fontnumber = 0;\r
+ PrintY = 175;\r
+ VWB_DrawPic (0,20*8,COPYPROTBOXPIC);\r
+ US_CPrint(GoodBoyStrs[i*2]);\r
+ US_CPrint(GoodBoyStrs[i*2+1]);\r
+ VW_UpdateScreen();\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+void CopyProtection(void)\r
+{\r
+#define TYPEBOX_Y 177\r
+#define TYPEBOX_BKGD 0x9c\r
+#define PRINTCOLOR HIGHLIGHT\r
+\r
+ int i,match,whichboss,bossnum,try,whichline,enemypicked[4]={0,0,0,0},\r
+ bosses[4] = { BOSSPIC1PIC,BOSSPIC2PIC,BOSSPIC3PIC,BOSSPIC4PIC },\r
+ whichone,whichpicked[4]={0,0,0,0},quiztype,whichmem,\r
+ memberpicked[5]={0,0,0,0,0},wordpicked[5]={0,0,0,0,0},whichword;\r
+\r
+ char inputbuffer[20],\r
+ message[80];\r
+\r
+ enum\r
+ {\r
+ debriefing,\r
+ checkmanual,\r
+ staffquiz,\r
+ miscquiz,\r
+\r
+ totaltypes\r
+ };\r
+\r
+\r
+\r
+ try = 0;\r
+ VW_FadeOut();\r
+ CA_CacheGrChunk(C_BACKDROPPIC);\r
+ CacheLump(COPYPROT_LUMP_START,COPYPROT_LUMP_END);\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+ CA_LoadAllSounds();\r
+ StartCPMusic(COPYPRO_MUS);\r
+ US_InitRndT(true);\r
+\r
+ while (try<3)\r
+ {\r
+ fontnumber = 1;\r
+ SETFONTCOLOR(PRINTCOLOR-2,15);\r
+ VWB_DrawPic (0,0,C_BACKDROPPIC);\r
+ VWB_DrawPic (0,0,COPYPROTTOPPIC);\r
+ VWB_DrawPic (0,20*8,COPYPROTBOXPIC);\r
+ WindowX = WindowY = 0;\r
+ WindowW = 320;\r
+ WindowH = 200;\r
+ PrintY = 65;\r
+\r
+ quiztype = US_RndT()%totaltypes;\r
+ switch(quiztype)\r
+ {\r
+ //\r
+ // BOSSES QUIZ\r
+ //\r
+ case debriefing:\r
+ PrintX = 0;\r
+ US_Print(STR_DEBRIEF);\r
+ SETFONTCOLOR(PRINTCOLOR,15);\r
+\r
+ while (enemypicked[whichboss = US_RndT()&3]);\r
+ enemypicked[whichboss] = 1;\r
+ bossnum = bosses[whichboss];\r
+ VWB_DrawPic(128,60,bossnum);\r
+ fontnumber = 0;\r
+ PrintY = 130;\r
+ US_CPrint(STR_ENEMY1"\n");\r
+ US_CPrint(STR_ENEMY2"\n\n");\r
+\r
+ VW_UpdateScreen();\r
+ VW_FadeIn();\r
+\r
+ PrintX = 100;\r
+ fontcolor = 15;\r
+ backcolor = TYPEBOX_BKGD;\r
+ inputbuffer[0] = 0;\r
+ PrintY = TYPEBOX_Y;\r
+ fontnumber = 1;\r
+ US_LineInput(PrintX,PrintY,inputbuffer,nil,true,20,100);\r
+\r
+ match = 0;\r
+ for (i=0;i<_fstrlen(bossstrs[whichboss]);i++)\r
+ if (!_fstrnicmp(inputbuffer,bossstrs[whichboss]+i,strlen(inputbuffer)) &&\r
+ strlen(inputbuffer)>3)\r
+ match = 1;\r
+\r
+ match += BackDoor(inputbuffer);\r
+ break;\r
+\r
+ //\r
+ // MANUAL CHECK\r
+ //\r
+ case checkmanual:\r
+ while (wordpicked[whichword = US_RndT()%5]);\r
+ wordpicked[whichword] = 1;\r
+ US_CPrint(STR_CHECKMAN);\r
+ SETFONTCOLOR(PRINTCOLOR,15);\r
+ PrintY += 25;\r
+ US_CPrint(STR_MAN1);\r
+ US_CPrint(STR_MAN2);\r
+ _fstrcpy(message,STR_MAN3" \"");\r
+ _fstrcat(message,WordStr[whichword]);\r
+ _fstrcat(message,"\" "STR_MAN4);\r
+ US_CPrint(message);\r
+ VW_UpdateScreen();\r
+ VW_FadeIn();\r
+\r
+ PrintX = 146;\r
+ fontcolor = 15;\r
+ backcolor = TYPEBOX_BKGD;\r
+ inputbuffer[0] = 0;\r
+ PrintY = TYPEBOX_Y;\r
+ US_LineInput(PrintX,PrintY,inputbuffer,nil,true,6,100);\r
+\r
+ strlwr(inputbuffer);\r
+ match = 1-(_fstrcmp(inputbuffer,WordCorrect[whichword])!=0);\r
+ match += BackDoor(inputbuffer);\r
+ break;\r
+\r
+ //\r
+ // STAFF QUIZ\r
+ //\r
+ case staffquiz:\r
+ while (memberpicked[whichmem = US_RndT()%5]);\r
+ memberpicked[whichmem] = 1;\r
+ US_CPrint(STR_ID1);\r
+ SETFONTCOLOR(PRINTCOLOR,15);\r
+ PrintY += 25;\r
+ US_CPrint(MemberStr[whichmem*2]);\r
+ US_CPrint(MemberStr[whichmem*2+1]);\r
+ VW_UpdateScreen();\r
+ VW_FadeIn();\r
+\r
+ PrintX = 100;\r
+ fontcolor = 15;\r
+ backcolor = TYPEBOX_BKGD;\r
+ inputbuffer[0] = 0;\r
+ PrintY = TYPEBOX_Y;\r
+ US_LineInput(PrintX,PrintY,inputbuffer,nil,true,20,120);\r
+\r
+ strlwr(inputbuffer);\r
+ match = 0;\r
+ for (i=0;i<_fstrlen(MemberCorrect[whichmem]);i++)\r
+ if (!_fstrnicmp(inputbuffer,MemberCorrect[whichmem]+i,strlen(inputbuffer)) &&\r
+ strlen(inputbuffer)>2)\r
+ match = 1;\r
+ match += BackDoor(inputbuffer);\r
+ break;\r
+\r
+ //\r
+ // MISCELLANEOUS QUESTIONS\r
+ //\r
+ case miscquiz:\r
+ while (whichpicked[whichone = US_RndT()&3]);\r
+ whichpicked[whichone] = 1;\r
+ US_CPrint(MiscTitle[whichone]);\r
+ SETFONTCOLOR(PRINTCOLOR,15);\r
+ PrintY += 25;\r
+ US_CPrint(MiscStr[whichone*3]);\r
+ US_CPrint(MiscStr[whichone*3+1]);\r
+ US_CPrint(MiscStr[whichone*3+2]);\r
+ VW_UpdateScreen();\r
+ VW_FadeIn();\r
+\r
+ PrintX = 146;\r
+ fontcolor = 15;\r
+ backcolor = TYPEBOX_BKGD;\r
+ inputbuffer[0] = 0;\r
+ PrintY = TYPEBOX_Y;\r
+ US_LineInput(PrintX,PrintY,inputbuffer,nil,true,6,100);\r
+\r
+ strlwr(inputbuffer);\r
+ match = 1-(_fstrcmp(inputbuffer,MiscCorrect[whichone])!=0);\r
+ match += BackDoor(inputbuffer);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // IF NO MATCH, WE'VE GOT A (MINOR) PROBLEM!\r
+ //\r
+\r
+ if (!match)\r
+ {\r
+ whichline = 2*(US_RndT()%9);\r
+ SETFONTCOLOR(14,15);\r
+ fontnumber = 0;\r
+ PrintY = 175;\r
+ VWB_DrawPic (0,20*8,COPYPROTBOXPIC);\r
+ US_CPrint(CopyProFailedStrs[whichline]);\r
+ US_CPrint(CopyProFailedStrs[whichline+1]);\r
+\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(NOWAYSND);\r
+ IN_UserInput(TickBase*3);\r
+ VW_FadeOut();\r
+ try++;\r
+ }\r
+ else\r
+ {\r
+ int start;\r
+\r
+\r
+ SD_PlaySound(BONUS1UPSND);\r
+ SD_WaitSoundDone();\r
+ UNCACHEGRCHUNK (STARTFONT+1);\r
+ UNCACHEGRCHUNK (C_BACKDROPPIC);\r
+ UnCacheLump (COPYPROT_LUMP_START,COPYPROT_LUMP_END);\r
+\r
+ switch(SoundMode)\r
+ {\r
+ case sdm_Off: return;\r
+ case sdm_PC: start = STARTPCSOUNDS; break;\r
+ case sdm_AdLib: start = STARTADLIBSOUNDS;\r
+ }\r
+\r
+ for (i=0;i<NUMSOUNDS;i++,start++)\r
+ MM_FreePtr ((memptr *)&audiosegs[start]);\r
+ return;\r
+ }\r
+ }\r
+\r
+ ClearMemory();\r
+ ShutdownId();\r
+\r
+ _fstrcpy(message,DosMessages[US_RndT()%9]);\r
+\r
+ _AX = 3;\r
+ geninterrupt(0x10);\r
+\r
+ printf("%s\n",message);\r
+ exit(1);\r
+}\r
+\r
+#endif // SPEARDEMO\r
+#endif // SPEAR\r
+//===========================================================================\r
--- /dev/null
+// WL_MAIN.C\r
+\r
+#include <conio.h>\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ WOLFENSTEIN 3-D\r
+\r
+ An Id Software production\r
+\r
+ by John Carmack\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+#define FOCALLENGTH (0x5700l) // in global coordinates\r
+#define VIEWGLOBAL 0x10000 // globals visable flush to wall\r
+\r
+#define VIEWWIDTH 256 // size of view window\r
+#define VIEWHEIGHT 144\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+char str[80],str2[20];\r
+int tedlevelnum;\r
+boolean tedlevel;\r
+boolean nospr;\r
+boolean IsA386;\r
+int dirangle[9] = {0,ANGLES/8,2*ANGLES/8,3*ANGLES/8,4*ANGLES/8,\r
+ 5*ANGLES/8,6*ANGLES/8,7*ANGLES/8,ANGLES};\r
+\r
+//\r
+// proejection variables\r
+//\r
+fixed focallength;\r
+unsigned screenofs;\r
+int viewwidth;\r
+int viewheight;\r
+int centerx;\r
+int shootdelta; // pixels away from centerx a target can be\r
+fixed scale,maxslope;\r
+long heightnumerator;\r
+int minheightdiv;\r
+\r
+\r
+void Quit (char *error);\r
+\r
+boolean startgame,loadedgame,virtualreality;\r
+int mouseadjustment;\r
+\r
+char configname[13]="CONFIG.";\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= ReadConfig\r
+=\r
+====================\r
+*/\r
+\r
+void ReadConfig(void)\r
+{\r
+ int file;\r
+ SDMode sd;\r
+ SMMode sm;\r
+ SDSMode sds;\r
+\r
+\r
+ if ( (file = open(configname,O_BINARY | O_RDONLY)) != -1)\r
+ {\r
+ //\r
+ // valid config file\r
+ //\r
+ read(file,Scores,sizeof(HighScore) * MaxScores);\r
+\r
+ read(file,&sd,sizeof(sd));\r
+ read(file,&sm,sizeof(sm));\r
+ read(file,&sds,sizeof(sds));\r
+\r
+ read(file,&mouseenabled,sizeof(mouseenabled));\r
+ read(file,&joystickenabled,sizeof(joystickenabled));\r
+ read(file,&joypadenabled,sizeof(joypadenabled));\r
+ read(file,&joystickprogressive,sizeof(joystickprogressive));\r
+ read(file,&joystickport,sizeof(joystickport));\r
+\r
+ read(file,&dirscan,sizeof(dirscan));\r
+ read(file,&buttonscan,sizeof(buttonscan));\r
+ read(file,&buttonmouse,sizeof(buttonmouse));\r
+ read(file,&buttonjoy,sizeof(buttonjoy));\r
+\r
+ read(file,&viewsize,sizeof(viewsize));\r
+ read(file,&mouseadjustment,sizeof(mouseadjustment));\r
+\r
+ close(file);\r
+\r
+ if (sd == sdm_AdLib && !AdLibPresent && !SoundBlasterPresent)\r
+ {\r
+ sd = sdm_PC;\r
+ sd = smm_Off;\r
+ }\r
+\r
+ if ((sds == sds_SoundBlaster && !SoundBlasterPresent) ||\r
+ (sds == sds_SoundSource && !SoundSourcePresent))\r
+ sds = sds_Off;\r
+\r
+ if (!MousePresent)\r
+ mouseenabled = false;\r
+ if (!JoysPresent[joystickport])\r
+ joystickenabled = false;\r
+\r
+ MainMenu[6].active=1;\r
+ MainItems.curpos=0;\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // no config file, so select by hardware\r
+ //\r
+ if (SoundBlasterPresent || AdLibPresent)\r
+ {\r
+ sd = sdm_AdLib;\r
+ sm = smm_AdLib;\r
+ }\r
+ else\r
+ {\r
+ sd = sdm_PC;\r
+ sm = smm_Off;\r
+ }\r
+\r
+ if (SoundBlasterPresent)\r
+ sds = sds_SoundBlaster;\r
+ else if (SoundSourcePresent)\r
+ sds = sds_SoundSource;\r
+ else\r
+ sds = sds_Off;\r
+\r
+ if (MousePresent)\r
+ mouseenabled = true;\r
+\r
+ joystickenabled = false;\r
+ joypadenabled = false;\r
+ joystickport = 0;\r
+ joystickprogressive = false;\r
+\r
+ viewsize = 15;\r
+ mouseadjustment=5;\r
+ }\r
+\r
+ SD_SetMusicMode (sm);\r
+ SD_SetSoundMode (sd);\r
+ SD_SetDigiDevice (sds);\r
+\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= WriteConfig\r
+=\r
+====================\r
+*/\r
+\r
+void WriteConfig(void)\r
+{\r
+ int file;\r
+\r
+ file = open(configname,O_CREAT | O_BINARY | O_WRONLY,\r
+ S_IREAD | S_IWRITE | S_IFREG);\r
+\r
+ if (file != -1)\r
+ {\r
+ write(file,Scores,sizeof(HighScore) * MaxScores);\r
+\r
+ write(file,&SoundMode,sizeof(SoundMode));\r
+ write(file,&MusicMode,sizeof(MusicMode));\r
+ write(file,&DigiMode,sizeof(DigiMode));\r
+\r
+ write(file,&mouseenabled,sizeof(mouseenabled));\r
+ write(file,&joystickenabled,sizeof(joystickenabled));\r
+ write(file,&joypadenabled,sizeof(joypadenabled));\r
+ write(file,&joystickprogressive,sizeof(joystickprogressive));\r
+ write(file,&joystickport,sizeof(joystickport));\r
+\r
+ write(file,&dirscan,sizeof(dirscan));\r
+ write(file,&buttonscan,sizeof(buttonscan));\r
+ write(file,&buttonmouse,sizeof(buttonmouse));\r
+ write(file,&buttonjoy,sizeof(buttonjoy));\r
+\r
+ write(file,&viewsize,sizeof(viewsize));\r
+ write(file,&mouseadjustment,sizeof(mouseadjustment));\r
+\r
+ close(file);\r
+ }\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+========================\r
+=\r
+= Patch386\r
+=\r
+= Patch ldiv to use 32 bit instructions\r
+=\r
+========================\r
+*/\r
+\r
+char *JHParmStrings[] = {"no386",nil};\r
+void Patch386 (void)\r
+{\r
+extern void far jabhack2(void);\r
+extern int far CheckIs386(void);\r
+\r
+ int i;\r
+\r
+ for (i = 1;i < _argc;i++)\r
+ if (US_CheckParm(_argv[i],JHParmStrings) == 0)\r
+ {\r
+ IsA386 = false;\r
+ return;\r
+ }\r
+\r
+ if (CheckIs386())\r
+ {\r
+ IsA386 = true;\r
+ jabhack2();\r
+ }\r
+ else\r
+ IsA386 = false;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= NewGame\r
+=\r
+= Set up new game to start from the beginning\r
+=\r
+=====================\r
+*/\r
+\r
+void NewGame (int difficulty,int episode)\r
+{\r
+ memset (&gamestate,0,sizeof(gamestate));\r
+ gamestate.difficulty = difficulty;\r
+ gamestate.weapon = gamestate.bestweapon\r
+ = gamestate.chosenweapon = wp_pistol;\r
+ gamestate.health = 100;\r
+ gamestate.ammo = STARTAMMO;\r
+ gamestate.lives = 3;\r
+ gamestate.nextextra = EXTRAPOINTS;\r
+ gamestate.episode=episode;\r
+\r
+ startgame = true;\r
+}\r
+\r
+//===========================================================================\r
+\r
+void DiskFlopAnim(int x,int y)\r
+{\r
+ static char which=0;\r
+ if (!x && !y)\r
+ return;\r
+ VWB_DrawPic(x,y,C_DISKLOADING1PIC+which);\r
+ VW_UpdateScreen();\r
+ which^=1;\r
+}\r
+\r
+\r
+long DoChecksum(byte far *source,unsigned size,long checksum)\r
+{\r
+ unsigned i;\r
+\r
+ for (i=0;i<size-1;i++)\r
+ checksum += source[i]^source[i+1];\r
+\r
+ return checksum;\r
+}\r
+\r
+\r
+/*\r
+==================\r
+=\r
+= SaveTheGame\r
+=\r
+==================\r
+*/\r
+\r
+boolean SaveTheGame(int file,int x,int y)\r
+{\r
+ struct diskfree_t dfree;\r
+ long avail,size,checksum;\r
+ objtype *ob,nullobj;\r
+\r
+\r
+ if (_dos_getdiskfree(0,&dfree))\r
+ Quit("Error in _dos_getdiskfree call");\r
+\r
+ avail = (long)dfree.avail_clusters *\r
+ dfree.bytes_per_sector *\r
+ dfree.sectors_per_cluster;\r
+\r
+ size = 0;\r
+ for (ob = player; ob ; ob=ob->next)\r
+ size += sizeof(*ob);\r
+ size += sizeof(nullobj);\r
+\r
+ size += sizeof(gamestate) +\r
+ sizeof(LRstruct)*8 +\r
+ sizeof(tilemap) +\r
+ sizeof(actorat) +\r
+ sizeof(laststatobj) +\r
+ sizeof(statobjlist) +\r
+ sizeof(doorposition) +\r
+ sizeof(pwallstate) +\r
+ sizeof(pwallx) +\r
+ sizeof(pwally) +\r
+ sizeof(pwalldir) +\r
+ sizeof(pwallpos);\r
+\r
+ if (avail < size)\r
+ {\r
+ Message(STR_NOSPACE1"\n"\r
+ STR_NOSPACE2);\r
+ return false;\r
+ }\r
+\r
+ checksum = 0;\r
+\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)&gamestate,sizeof(gamestate));\r
+ checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum);\r
+\r
+ DiskFlopAnim(x,y);\r
+#ifdef SPEAR\r
+ CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20);\r
+ checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum);\r
+#else\r
+ CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8);\r
+ checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum);\r
+#endif\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)tilemap,sizeof(tilemap));\r
+ checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum);\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)actorat,sizeof(actorat));\r
+ checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum);\r
+\r
+ CA_FarWrite (file,(void far *)areaconnect,sizeof(areaconnect));\r
+ CA_FarWrite (file,(void far *)areabyplayer,sizeof(areabyplayer));\r
+\r
+ for (ob = player ; ob ; ob=ob->next)\r
+ {\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)ob,sizeof(*ob));\r
+ }\r
+ nullobj.active = ac_badobject; // end of file marker\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)&nullobj,sizeof(nullobj));\r
+\r
+\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)&laststatobj,sizeof(laststatobj));\r
+ checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum);\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)statobjlist,sizeof(statobjlist));\r
+ checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum);\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)doorposition,sizeof(doorposition));\r
+ checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum);\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)doorobjlist,sizeof(doorobjlist));\r
+ checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum);\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarWrite (file,(void far *)&pwallstate,sizeof(pwallstate));\r
+ checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum);\r
+ CA_FarWrite (file,(void far *)&pwallx,sizeof(pwallx));\r
+ checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum);\r
+ CA_FarWrite (file,(void far *)&pwally,sizeof(pwally));\r
+ checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum);\r
+ CA_FarWrite (file,(void far *)&pwalldir,sizeof(pwalldir));\r
+ checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum);\r
+ CA_FarWrite (file,(void far *)&pwallpos,sizeof(pwallpos));\r
+ checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum);\r
+\r
+ //\r
+ // WRITE OUT CHECKSUM\r
+ //\r
+ CA_FarWrite (file,(void far *)&checksum,sizeof(checksum));\r
+\r
+ return(true);\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= LoadTheGame\r
+=\r
+==================\r
+*/\r
+\r
+boolean LoadTheGame(int file,int x,int y)\r
+{\r
+ long checksum,oldchecksum;\r
+ objtype *ob,nullobj;\r
+\r
+\r
+ checksum = 0;\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)&gamestate,sizeof(gamestate));\r
+ checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum);\r
+\r
+ DiskFlopAnim(x,y);\r
+#ifdef SPEAR\r
+ CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20);\r
+ checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum);\r
+#else\r
+ CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8);\r
+ checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum);\r
+#endif\r
+\r
+ DiskFlopAnim(x,y);\r
+ SetupGameLevel ();\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)tilemap,sizeof(tilemap));\r
+ checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum);\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)actorat,sizeof(actorat));\r
+ checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum);\r
+\r
+ CA_FarRead (file,(void far *)areaconnect,sizeof(areaconnect));\r
+ CA_FarRead (file,(void far *)areabyplayer,sizeof(areabyplayer));\r
+\r
+\r
+\r
+ InitActorList ();\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)player,sizeof(*player));\r
+\r
+ while (1)\r
+ {\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)&nullobj,sizeof(nullobj));\r
+ if (nullobj.active == ac_badobject)\r
+ break;\r
+ GetNewActor ();\r
+ // don't copy over the links\r
+ memcpy (new,&nullobj,sizeof(nullobj)-4);\r
+ }\r
+\r
+\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)&laststatobj,sizeof(laststatobj));\r
+ checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum);\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)statobjlist,sizeof(statobjlist));\r
+ checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum);\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)doorposition,sizeof(doorposition));\r
+ checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum);\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)doorobjlist,sizeof(doorobjlist));\r
+ checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum);\r
+\r
+ DiskFlopAnim(x,y);\r
+ CA_FarRead (file,(void far *)&pwallstate,sizeof(pwallstate));\r
+ checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum);\r
+ CA_FarRead (file,(void far *)&pwallx,sizeof(pwallx));\r
+ checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum);\r
+ CA_FarRead (file,(void far *)&pwally,sizeof(pwally));\r
+ checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum);\r
+ CA_FarRead (file,(void far *)&pwalldir,sizeof(pwalldir));\r
+ checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum);\r
+ CA_FarRead (file,(void far *)&pwallpos,sizeof(pwallpos));\r
+ checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum);\r
+\r
+ CA_FarRead (file,(void far *)&oldchecksum,sizeof(oldchecksum));\r
+\r
+ if (oldchecksum != checksum)\r
+ {\r
+ Message(STR_SAVECHT1"\n"\r
+ STR_SAVECHT2"\n"\r
+ STR_SAVECHT3"\n"\r
+ STR_SAVECHT4);\r
+\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+\r
+ gamestate.score = 0;\r
+ gamestate.lives = 1;\r
+ gamestate.weapon =\r
+ gamestate.chosenweapon =\r
+ gamestate.bestweapon = wp_pistol;\r
+ gamestate.ammo = 8;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= ShutdownId\r
+=\r
+= Shuts down all ID_?? managers\r
+=\r
+==========================\r
+*/\r
+\r
+void ShutdownId (void)\r
+{\r
+ US_Shutdown ();\r
+ SD_Shutdown ();\r
+ PM_Shutdown ();\r
+ IN_Shutdown ();\r
+ VW_Shutdown ();\r
+ CA_Shutdown ();\r
+ MM_Shutdown ();\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==================\r
+=\r
+= BuildTables\r
+=\r
+= Calculates:\r
+=\r
+= scale projection constant\r
+= sintable/costable overlapping fractional tables\r
+=\r
+==================\r
+*/\r
+\r
+const float radtoint = (float)FINEANGLES/2/PI;\r
+\r
+void BuildTables (void)\r
+{\r
+ int i;\r
+ float angle,anglestep;\r
+ double tang;\r
+ fixed value;\r
+\r
+\r
+//\r
+// calculate fine tangents\r
+//\r
+\r
+ for (i=0;i<FINEANGLES/8;i++)\r
+ {\r
+ tang = tan( (i+0.5)/radtoint);\r
+ finetangent[i] = tang*TILEGLOBAL;\r
+ finetangent[FINEANGLES/4-1-i] = 1/tang*TILEGLOBAL;\r
+ }\r
+\r
+//\r
+// costable overlays sintable with a quarter phase shift\r
+// ANGLES is assumed to be divisable by four\r
+//\r
+// The low word of the value is the fraction, the high bit is the sign bit,\r
+// bits 16-30 should be 0\r
+//\r
+\r
+ angle = 0;\r
+ anglestep = PI/2/ANGLEQUAD;\r
+ for (i=0;i<=ANGLEQUAD;i++)\r
+ {\r
+ value=GLOBAL1*sin(angle);\r
+ sintable[i]=\r
+ sintable[i+ANGLES]=\r
+ sintable[ANGLES/2-i] = value;\r
+ sintable[ANGLES-i]=\r
+ sintable[ANGLES/2+i] = value | 0x80000000l;\r
+ angle += anglestep;\r
+ }\r
+\r
+}\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= CalcProjection\r
+=\r
+= Uses focallength\r
+=\r
+====================\r
+*/\r
+\r
+void CalcProjection (long focal)\r
+{\r
+ int i;\r
+ long intang;\r
+ float angle;\r
+ double tang;\r
+ double planedist;\r
+ double globinhalf;\r
+ int halfview;\r
+ double halfangle,facedist;\r
+\r
+\r
+ focallength = focal;\r
+ facedist = focal+MINDIST;\r
+ halfview = viewwidth/2; // half view in pixels\r
+\r
+//\r
+// calculate scale value for vertical height calculations\r
+// and sprite x calculations\r
+//\r
+ scale = halfview*facedist/(VIEWGLOBAL/2);\r
+\r
+//\r
+// divide heightnumerator by a posts distance to get the posts height for\r
+// the heightbuffer. The pixel height is height>>2\r
+//\r
+ heightnumerator = (TILEGLOBAL*scale)>>6;\r
+ minheightdiv = heightnumerator/0x7fff +1;\r
+\r
+//\r
+// calculate the angle offset from view angle of each pixel's ray\r
+//\r
+\r
+ for (i=0;i<halfview;i++)\r
+ {\r
+ // start 1/2 pixel over, so viewangle bisects two middle pixels\r
+ tang = (long)i*VIEWGLOBAL/viewwidth/facedist;\r
+ angle = atan(tang);\r
+ intang = angle*radtoint;\r
+ pixelangle[halfview-1-i] = intang;\r
+ pixelangle[halfview+i] = -intang;\r
+ }\r
+\r
+//\r
+// if a point's abs(y/x) is greater than maxslope, the point is outside\r
+// the view area\r
+//\r
+ maxslope = finetangent[pixelangle[0]];\r
+ maxslope >>= 8;\r
+}\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= SetupWalls\r
+=\r
+= Map tile values to scaled pics\r
+=\r
+===================\r
+*/\r
+\r
+void SetupWalls (void)\r
+{\r
+ int i;\r
+\r
+ for (i=1;i<MAXWALLTILES;i++)\r
+ {\r
+ horizwall[i]=(i-1)*2;\r
+ vertwall[i]=(i-1)*2+1;\r
+ }\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= SignonScreen\r
+=\r
+==========================\r
+*/\r
+\r
+void SignonScreen (void) // VGA version\r
+{\r
+ unsigned segstart,seglength;\r
+\r
+ VL_SetVGAPlaneMode ();\r
+ VL_TestPaletteSet ();\r
+ VL_SetPalette (&gamepal);\r
+\r
+ if (!virtualreality)\r
+ {\r
+ VW_SetScreen(0x8000,0);\r
+ VL_MungePic (&introscn,320,200);\r
+ VL_MemToScreen (&introscn,320,200,0,0);\r
+ VW_SetScreen(0,0);\r
+ }\r
+\r
+//\r
+// reclaim the memory from the linked in signon screen\r
+//\r
+ segstart = FP_SEG(&introscn);\r
+ seglength = 64000/16;\r
+ if (FP_OFF(&introscn))\r
+ {\r
+ segstart++;\r
+ seglength--;\r
+ }\r
+ MML_UseSpace (segstart,seglength);\r
+}\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= FinishSignon\r
+=\r
+==========================\r
+*/\r
+\r
+void FinishSignon (void)\r
+{\r
+\r
+#ifndef SPEAR\r
+ VW_Bar (0,189,300,11,peekb(0xa000,0));\r
+ WindowX = 0;\r
+ WindowW = 320;\r
+ PrintY = 190;\r
+\r
+ #ifndef JAPAN\r
+ SETFONTCOLOR(14,4);\r
+\r
+ #ifdef SPANISH\r
+ US_CPrint ("Oprima una tecla");\r
+ #else\r
+ US_CPrint ("Press a key");\r
+ #endif\r
+\r
+ #endif\r
+\r
+ if (!NoWait)\r
+ IN_Ack ();\r
+\r
+ #ifndef JAPAN\r
+ VW_Bar (0,189,300,11,peekb(0xa000,0));\r
+\r
+ PrintY = 190;\r
+ SETFONTCOLOR(10,4);\r
+\r
+ #ifdef SPANISH\r
+ US_CPrint ("pensando...");\r
+ #else\r
+ US_CPrint ("Working...");\r
+ #endif\r
+\r
+ #endif\r
+\r
+ SETFONTCOLOR(0,15);\r
+#else\r
+ if (!NoWait)\r
+ VW_WaitVBL(3*70);\r
+#endif\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=================\r
+=\r
+= MS_CheckParm\r
+=\r
+=================\r
+*/\r
+\r
+boolean MS_CheckParm (char far *check)\r
+{\r
+ int i;\r
+ char *parm;\r
+\r
+ for (i = 1;i<_argc;i++)\r
+ {\r
+ parm = _argv[i];\r
+\r
+ while ( !isalpha(*parm) ) // skip - / \ etc.. in front of parm\r
+ if (!*parm++)\r
+ break; // hit end of string without an alphanum\r
+\r
+ if ( !_fstricmp(check,parm) )\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= InitDigiMap\r
+=\r
+=====================\r
+*/\r
+\r
+static int wolfdigimap[] =\r
+ {\r
+ // These first sounds are in the upload version\r
+#ifndef SPEAR\r
+ HALTSND, 0,\r
+ DOGBARKSND, 1,\r
+ CLOSEDOORSND, 2,\r
+ OPENDOORSND, 3,\r
+ ATKMACHINEGUNSND, 4,\r
+ ATKPISTOLSND, 5,\r
+ ATKGATLINGSND, 6,\r
+ SCHUTZADSND, 7,\r
+ GUTENTAGSND, 8,\r
+ MUTTISND, 9,\r
+ BOSSFIRESND, 10,\r
+ SSFIRESND, 11,\r
+ DEATHSCREAM1SND, 12,\r
+ DEATHSCREAM2SND, 13,\r
+ DEATHSCREAM3SND, 13,\r
+ TAKEDAMAGESND, 14,\r
+ PUSHWALLSND, 15,\r
+\r
+ LEBENSND, 20,\r
+ NAZIFIRESND, 21,\r
+ SLURPIESND, 22,\r
+\r
+ YEAHSND, 32,\r
+\r
+#ifndef UPLOAD\r
+ // These are in all other episodes\r
+ DOGDEATHSND, 16,\r
+ AHHHGSND, 17,\r
+ DIESND, 18,\r
+ EVASND, 19,\r
+\r
+ TOT_HUNDSND, 23,\r
+ MEINGOTTSND, 24,\r
+ SCHABBSHASND, 25,\r
+ HITLERHASND, 26,\r
+ SPIONSND, 27,\r
+ NEINSOVASSND, 28,\r
+ DOGATTACKSND, 29,\r
+ LEVELDONESND, 30,\r
+ MECHSTEPSND, 31,\r
+\r
+ SCHEISTSND, 33,\r
+ DEATHSCREAM4SND, 34, // AIIEEE\r
+ DEATHSCREAM5SND, 35, // DEE-DEE\r
+ DONNERSND, 36, // EPISODE 4 BOSS DIE\r
+ EINESND, 37, // EPISODE 4 BOSS SIGHTING\r
+ ERLAUBENSND, 38, // EPISODE 6 BOSS SIGHTING\r
+ DEATHSCREAM6SND, 39, // FART\r
+ DEATHSCREAM7SND, 40, // GASP\r
+ DEATHSCREAM8SND, 41, // GUH-BOY!\r
+ DEATHSCREAM9SND, 42, // AH GEEZ!\r
+ KEINSND, 43, // EPISODE 5 BOSS SIGHTING\r
+ MEINSND, 44, // EPISODE 6 BOSS DIE\r
+ ROSESND, 45, // EPISODE 5 BOSS DIE\r
+\r
+#endif\r
+#else\r
+//\r
+// SPEAR OF DESTINY DIGISOUNDS\r
+//\r
+ HALTSND, 0,\r
+ CLOSEDOORSND, 2,\r
+ OPENDOORSND, 3,\r
+ ATKMACHINEGUNSND, 4,\r
+ ATKPISTOLSND, 5,\r
+ ATKGATLINGSND, 6,\r
+ SCHUTZADSND, 7,\r
+ BOSSFIRESND, 8,\r
+ SSFIRESND, 9,\r
+ DEATHSCREAM1SND, 10,\r
+ DEATHSCREAM2SND, 11,\r
+ TAKEDAMAGESND, 12,\r
+ PUSHWALLSND, 13,\r
+ AHHHGSND, 15,\r
+ LEBENSND, 16,\r
+ NAZIFIRESND, 17,\r
+ SLURPIESND, 18,\r
+ LEVELDONESND, 22,\r
+ DEATHSCREAM4SND, 23, // AIIEEE\r
+ DEATHSCREAM3SND, 23, // DOUBLY-MAPPED!!!\r
+ DEATHSCREAM5SND, 24, // DEE-DEE\r
+ DEATHSCREAM6SND, 25, // FART\r
+ DEATHSCREAM7SND, 26, // GASP\r
+ DEATHSCREAM8SND, 27, // GUH-BOY!\r
+ DEATHSCREAM9SND, 28, // AH GEEZ!\r
+ GETGATLINGSND, 38, // Got Gat replacement\r
+\r
+#ifndef SPEARDEMO\r
+ DOGBARKSND, 1,\r
+ DOGDEATHSND, 14,\r
+ SPIONSND, 19,\r
+ NEINSOVASSND, 20,\r
+ DOGATTACKSND, 21,\r
+ TRANSSIGHTSND, 29, // Trans Sight\r
+ TRANSDEATHSND, 30, // Trans Death\r
+ WILHELMSIGHTSND, 31, // Wilhelm Sight\r
+ WILHELMDEATHSND, 32, // Wilhelm Death\r
+ UBERDEATHSND, 33, // Uber Death\r
+ KNIGHTSIGHTSND, 34, // Death Knight Sight\r
+ KNIGHTDEATHSND, 35, // Death Knight Death\r
+ ANGELSIGHTSND, 36, // Angel Sight\r
+ ANGELDEATHSND, 37, // Angel Death\r
+ GETSPEARSND, 39, // Got Spear replacement\r
+#endif\r
+#endif\r
+ LASTSOUND\r
+ };\r
+\r
+\r
+void InitDigiMap (void)\r
+{\r
+ int *map;\r
+\r
+ for (map = wolfdigimap;*map != LASTSOUND;map += 2)\r
+ DigiMap[map[0]] = map[1];\r
+\r
+\r
+}\r
+\r
+\r
+#ifndef SPEAR\r
+CP_iteminfo MusicItems={CTL_X,CTL_Y,6,0,32};\r
+CP_itemtype far MusicMenu[]=\r
+ {\r
+ {1,"Get Them!",0},\r
+ {1,"Searching",0},\r
+ {1,"P.O.W.",0},\r
+ {1,"Suspense",0},\r
+ {1,"War March",0},\r
+ {1,"Around The Corner!",0},\r
+\r
+ {1,"Nazi Anthem",0},\r
+ {1,"Lurking...",0},\r
+ {1,"Going After Hitler",0},\r
+ {1,"Pounding Headache",0},\r
+ {1,"Into the Dungeons",0},\r
+ {1,"Ultimate Conquest",0},\r
+\r
+ {1,"Kill the S.O.B.",0},\r
+ {1,"The Nazi Rap",0},\r
+ {1,"Twelfth Hour",0},\r
+ {1,"Zero Hour",0},\r
+ {1,"Ultimate Conquest",0},\r
+ {1,"Wolfpack",0}\r
+ };\r
+#else\r
+CP_iteminfo MusicItems={CTL_X,CTL_Y-20,9,0,32};\r
+CP_itemtype far MusicMenu[]=\r
+ {\r
+ {1,"Funky Colonel Bill",0},\r
+ {1,"Death To The Nazis",0},\r
+ {1,"Tiptoeing Around",0},\r
+ {1,"Is This THE END?",0},\r
+ {1,"Evil Incarnate",0},\r
+ {1,"Jazzin' Them Nazis",0},\r
+ {1,"Puttin' It To The Enemy",0},\r
+ {1,"The SS Gonna Get You",0},\r
+ {1,"Towering Above",0}\r
+ };\r
+#endif\r
+\r
+#ifndef SPEARDEMO\r
+void DoJukebox(void)\r
+{\r
+ int which,lastsong=-1;\r
+ unsigned start,songs[]=\r
+ {\r
+#ifndef SPEAR\r
+ GETTHEM_MUS,\r
+ SEARCHN_MUS,\r
+ POW_MUS,\r
+ SUSPENSE_MUS,\r
+ WARMARCH_MUS,\r
+ CORNER_MUS,\r
+\r
+ NAZI_OMI_MUS,\r
+ PREGNANT_MUS,\r
+ GOINGAFT_MUS,\r
+ HEADACHE_MUS,\r
+ DUNGEON_MUS,\r
+ ULTIMATE_MUS,\r
+\r
+ INTROCW3_MUS,\r
+ NAZI_RAP_MUS,\r
+ TWELFTH_MUS,\r
+ ZEROHOUR_MUS,\r
+ ULTIMATE_MUS,\r
+ PACMAN_MUS\r
+#else\r
+ XFUNKIE_MUS, // 0\r
+ XDEATH_MUS, // 2\r
+ XTIPTOE_MUS, // 4\r
+ XTHEEND_MUS, // 7\r
+ XEVIL_MUS, // 17\r
+ XJAZNAZI_MUS, // 18\r
+ XPUTIT_MUS, // 21\r
+ XGETYOU_MUS, // 22\r
+ XTOWER2_MUS // 23\r
+#endif\r
+ };\r
+ struct dostime_t time;\r
+\r
+\r
+\r
+ IN_ClearKeysDown();\r
+ if (!AdLibPresent && !SoundBlasterPresent)\r
+ return;\r
+\r
+\r
+ MenuFadeOut();\r
+\r
+#ifndef SPEAR\r
+#ifndef UPLOAD\r
+ _dos_gettime(&time);\r
+ start = (time.hsecond%3)*6;\r
+#else\r
+ start = 0;\r
+#endif\r
+#else\r
+ start = 0;\r
+#endif\r
+\r
+\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+#ifdef SPEAR\r
+ CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+#else\r
+ CacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);\r
+#endif\r
+ CA_LoadAllSounds ();\r
+\r
+ fontnumber=1;\r
+ ClearMScreen ();\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+ DrawStripes (10);\r
+ SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);\r
+\r
+#ifndef SPEAR\r
+ DrawWindow (CTL_X-2,CTL_Y-6,280,13*7,BKGDCOLOR);\r
+#else\r
+ DrawWindow (CTL_X-2,CTL_Y-26,280,13*10,BKGDCOLOR);\r
+#endif\r
+\r
+ DrawMenu (&MusicItems,&MusicMenu[start]);\r
+\r
+ SETFONTCOLOR (READHCOLOR,BKGDCOLOR);\r
+ PrintY=15;\r
+ WindowX = 0;\r
+ WindowY = 320;\r
+ US_CPrint ("Robert's Jukebox");\r
+\r
+ SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);\r
+ VW_UpdateScreen();\r
+ MenuFadeIn();\r
+\r
+ do\r
+ {\r
+ which = HandleMenu(&MusicItems,&MusicMenu[start],NULL);\r
+ if (which>=0)\r
+ {\r
+ if (lastsong >= 0)\r
+ MusicMenu[start+lastsong].active = 1;\r
+\r
+ StartCPMusic(songs[start + which]);\r
+ MusicMenu[start+which].active = 2;\r
+ DrawMenu (&MusicItems,&MusicMenu[start]);\r
+ VW_UpdateScreen();\r
+ lastsong = which;\r
+ }\r
+ } while(which>=0);\r
+\r
+ MenuFadeOut();\r
+ IN_ClearKeysDown();\r
+#ifdef SPEAR\r
+ UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+#else\r
+ UnCacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);\r
+#endif\r
+}\r
+#endif\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= InitGame\r
+=\r
+= Load a few things right away\r
+=\r
+==========================\r
+*/\r
+\r
+void InitGame (void)\r
+{\r
+ int i,x,y;\r
+ unsigned *blockstart;\r
+\r
+ if (MS_CheckParm ("virtual"))\r
+ virtualreality = true;\r
+ else\r
+ virtualreality = false;\r
+\r
+ MM_Startup (); // so the signon screen can be freed\r
+\r
+ SignonScreen ();\r
+\r
+ VW_Startup ();\r
+ IN_Startup ();\r
+ PM_Startup ();\r
+ PM_UnlockMainMem ();\r
+ SD_Startup ();\r
+ CA_Startup ();\r
+ US_Startup ();\r
+\r
+\r
+#ifndef SPEAR\r
+ if (mminfo.mainmem < 235000L)\r
+#else\r
+ if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode"))\r
+#endif\r
+ {\r
+ memptr screen;\r
+\r
+ CA_CacheGrChunk (ERRORSCREEN);\r
+ screen = grsegs[ERRORSCREEN];\r
+ ShutdownId();\r
+ movedata ((unsigned)screen,7+7*160,0xb800,0,17*160);\r
+ gotoxy (1,23);\r
+ exit(1);\r
+ }\r
+\r
+\r
+//\r
+// build some tables\r
+//\r
+ InitDigiMap ();\r
+\r
+ for (i=0;i<MAPSIZE;i++)\r
+ {\r
+ nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;\r
+ farmapylookup[i] = i*64;\r
+ }\r
+\r
+ for (i=0;i<PORTTILESHIGH;i++)\r
+ uwidthtable[i] = UPDATEWIDE*i;\r
+\r
+ blockstart = &blockstarts[0];\r
+ for (y=0;y<UPDATEHIGH;y++)\r
+ for (x=0;x<UPDATEWIDE;x++)\r
+ *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
+\r
+ updateptr = &update[0];\r
+\r
+ bufferofs = 0;\r
+ displayofs = 0;\r
+ ReadConfig ();\r
+\r
+\r
+//\r
+// HOLDING DOWN 'M' KEY?\r
+//\r
+#ifndef SPEARDEMO\r
+ if (Keyboard[sc_M])\r
+ DoJukebox();\r
+ else\r
+#endif\r
+//\r
+// draw intro screen stuff\r
+//\r
+ if (!virtualreality)\r
+ IntroScreen ();\r
+\r
+//\r
+// load in and lock down some basic chunks\r
+//\r
+\r
+ CA_CacheGrChunk(STARTFONT);\r
+ MM_SetLock (&grsegs[STARTFONT],true);\r
+\r
+ LoadLatchMem ();\r
+ BuildTables (); // trig tables\r
+ SetupWalls ();\r
+\r
+#if 0\r
+{\r
+int temp,i;\r
+temp = viewsize;\r
+ profilehandle = open("SCALERS.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
+for (i=1;i<20;i++)\r
+ NewViewSize(i);\r
+viewsize = temp;\r
+close(profilehandle);\r
+}\r
+#endif\r
+\r
+ NewViewSize (viewsize);\r
+\r
+\r
+//\r
+// initialize variables\r
+//\r
+ InitRedShifts ();\r
+ if (!virtualreality)\r
+ FinishSignon();\r
+\r
+ displayofs = PAGE1START;\r
+ bufferofs = PAGE2START;\r
+\r
+ if (virtualreality)\r
+ {\r
+ NoWait = true;\r
+ geninterrupt(0x60);\r
+ }\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= SetViewSize\r
+=\r
+==========================\r
+*/\r
+\r
+boolean SetViewSize (unsigned width, unsigned height)\r
+{\r
+ viewwidth = width&~15; // must be divisable by 16\r
+ viewheight = height&~1; // must be even\r
+ centerx = viewwidth/2-1;\r
+ shootdelta = viewwidth/10;\r
+ screenofs = ((200-STATUSLINES-viewheight)/2*SCREENWIDTH+(320-viewwidth)/8);\r
+\r
+//\r
+// calculate trace angles and projection constants\r
+//\r
+ CalcProjection (FOCALLENGTH);\r
+\r
+//\r
+// build all needed compiled scalers\r
+//\r
+// MM_BombOnError (false);\r
+ SetupScaling (viewwidth*1.5);\r
+#if 0\r
+ MM_BombOnError (true);\r
+ if (mmerror)\r
+ {\r
+ Quit ("Can't build scalers!");\r
+ mmerror = false;\r
+ return false;\r
+ }\r
+#endif\r
+ return true;\r
+}\r
+\r
+\r
+void ShowViewSize (int width)\r
+{\r
+ int oldwidth,oldheight;\r
+\r
+ oldwidth = viewwidth;\r
+ oldheight = viewheight;\r
+\r
+ viewwidth = width*16;\r
+ viewheight = width*16*HEIGHTRATIO;\r
+ DrawPlayBorder ();\r
+\r
+ viewheight = oldheight;\r
+ viewwidth = oldwidth;\r
+}\r
+\r
+\r
+void NewViewSize (int width)\r
+{\r
+ CA_UpLevel ();\r
+ MM_SortMem ();\r
+ viewsize = width;\r
+ SetViewSize (width*16,width*16*HEIGHTRATIO);\r
+ CA_DownLevel ();\r
+}\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==========================\r
+=\r
+= Quit\r
+=\r
+==========================\r
+*/\r
+\r
+void Quit (char *error)\r
+{\r
+ unsigned finscreen;\r
+ memptr screen;\r
+\r
+ if (virtualreality)\r
+ geninterrupt(0x61);\r
+\r
+ ClearMemory ();\r
+ if (!*error)\r
+ {\r
+ #ifndef JAPAN\r
+ CA_CacheGrChunk (ORDERSCREEN);\r
+ screen = grsegs[ORDERSCREEN];\r
+ #endif\r
+ WriteConfig ();\r
+ }\r
+ else\r
+ {\r
+ CA_CacheGrChunk (ERRORSCREEN);\r
+ screen = grsegs[ERRORSCREEN];\r
+ }\r
+\r
+ ShutdownId ();\r
+\r
+ if (error && *error)\r
+ {\r
+ movedata ((unsigned)screen,7,0xb800,0,7*160);\r
+ gotoxy (10,4);\r
+ puts(error);\r
+ gotoxy (1,8);\r
+ exit(1);\r
+ }\r
+ else\r
+ if (!error || !(*error))\r
+ {\r
+ clrscr();\r
+ #ifndef JAPAN\r
+ movedata ((unsigned)screen,7,0xb800,0,4000);\r
+ gotoxy(1,24);\r
+ #endif\r
+//asm mov bh,0\r
+//asm mov dh,23 // row\r
+//asm mov dl,0 // collumn\r
+//asm mov ah,2\r
+//asm int 0x10\r
+ }\r
+\r
+ exit(0);\r
+}\r
+\r
+//===========================================================================\r
+\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= DemoLoop\r
+=\r
+=====================\r
+*/\r
+\r
+static char *ParmStrings[] = {"baby","easy","normal","hard",""};\r
+\r
+void DemoLoop (void)\r
+{\r
+ static int LastDemo;\r
+ int i,level;\r
+ long nsize;\r
+ memptr nullblock;\r
+\r
+//\r
+// check for launch from ted\r
+//\r
+ if (tedlevel)\r
+ {\r
+ NoWait = true;\r
+ NewGame(1,0);\r
+\r
+ for (i = 1;i < _argc;i++)\r
+ {\r
+ if ( (level = US_CheckParm(_argv[i],ParmStrings)) != -1)\r
+ {\r
+ gamestate.difficulty=level;\r
+ break;\r
+ }\r
+ }\r
+\r
+#ifndef SPEAR\r
+ gamestate.episode = tedlevelnum/10;\r
+ gamestate.mapon = tedlevelnum%10;\r
+#else\r
+ gamestate.episode = 0;\r
+ gamestate.mapon = tedlevelnum;\r
+#endif\r
+ GameLoop();\r
+ Quit (NULL);\r
+ }\r
+\r
+\r
+//\r
+// main game cycle\r
+//\r
+\r
+\r
+// nsize = (long)40*1024;\r
+// MM_GetPtr(&nullblock,nsize);\r
+\r
+#ifndef DEMOTEST\r
+\r
+ #ifndef UPLOAD\r
+\r
+ #ifndef GOODTIMES\r
+ #ifndef SPEAR\r
+ #ifndef JAPAN\r
+ if (!NoWait)\r
+ NonShareware();\r
+ #endif\r
+ #else\r
+\r
+ #ifndef GOODTIMES\r
+ #ifndef SPEARDEMO\r
+ CopyProtection();\r
+ #endif\r
+ #endif\r
+\r
+ #endif\r
+ #endif\r
+ #endif\r
+\r
+ StartCPMusic(INTROSONG);\r
+\r
+#ifndef JAPAN\r
+ if (!NoWait)\r
+ PG13 ();\r
+#endif\r
+\r
+#endif\r
+\r
+ while (1)\r
+ {\r
+ while (!NoWait)\r
+ {\r
+//\r
+// title page\r
+//\r
+ MM_SortMem ();\r
+#ifndef DEMOTEST\r
+\r
+#ifdef SPEAR\r
+ CA_CacheGrChunk (TITLEPALETTE);\r
+\r
+ CA_CacheGrChunk (TITLE1PIC);\r
+ VWB_DrawPic (0,0,TITLE1PIC);\r
+ UNCACHEGRCHUNK (TITLE1PIC);\r
+\r
+ CA_CacheGrChunk (TITLE2PIC);\r
+ VWB_DrawPic (0,80,TITLE2PIC);\r
+ UNCACHEGRCHUNK (TITLE2PIC);\r
+ VW_UpdateScreen ();\r
+ VL_FadeIn(0,255,grsegs[TITLEPALETTE],30);\r
+\r
+ UNCACHEGRCHUNK (TITLEPALETTE);\r
+#else\r
+ CA_CacheScreen (TITLEPIC);\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn();\r
+#endif\r
+ if (IN_UserInput(TickBase*15))\r
+ break;\r
+ VW_FadeOut();\r
+//\r
+// credits page\r
+//\r
+ CA_CacheScreen (CREDITSPIC);\r
+ VW_UpdateScreen();\r
+ VW_FadeIn ();\r
+ if (IN_UserInput(TickBase*10))\r
+ break;\r
+ VW_FadeOut ();\r
+//\r
+// high scores\r
+//\r
+ DrawHighScores ();\r
+ VW_UpdateScreen ();\r
+ VW_FadeIn ();\r
+\r
+ if (IN_UserInput(TickBase*10))\r
+ break;\r
+#endif\r
+//\r
+// demo\r
+//\r
+\r
+ #ifndef SPEARDEMO\r
+ PlayDemo (LastDemo++%4);\r
+ #else\r
+ PlayDemo (0);\r
+ #endif\r
+\r
+ if (playstate == ex_abort)\r
+ break;\r
+ StartCPMusic(INTROSONG);\r
+ }\r
+\r
+ VW_FadeOut ();\r
+\r
+#ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && MS_CheckParm("goobers"))\r
+#else\r
+ if (Keyboard[sc_Tab] && MS_CheckParm("debugmode"))\r
+#endif\r
+ RecordDemo ();\r
+ else\r
+ US_ControlPanel (0);\r
+\r
+ if (startgame || loadedgame)\r
+ {\r
+ GameLoop ();\r
+ VW_FadeOut();\r
+ StartCPMusic(INTROSONG);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= main\r
+=\r
+==========================\r
+*/\r
+\r
+char *nosprtxt[] = {"nospr",nil};\r
+\r
+void main (void)\r
+{\r
+ int i;\r
+\r
+\r
+#ifdef BETA\r
+ //\r
+ // THIS IS FOR BETA ONLY!\r
+ //\r
+ struct dosdate_t d;\r
+\r
+ _dos_getdate(&d);\r
+ if (d.year > YEAR ||\r
+ (d.month >= MONTH && d.day >= DAY))\r
+ {\r
+ printf("Sorry, BETA-TESTING is over. Thanks for you help.\n");\r
+ exit(1);\r
+ }\r
+#endif\r
+\r
+ CheckForEpisodes();\r
+\r
+ Patch386 ();\r
+\r
+ InitGame ();\r
+\r
+ DemoLoop();\r
+\r
+ Quit("Demo loop exited???");\r
+}\r
+\r
--- /dev/null
+////////////////////////////////////////////////////////////////////\r
+//\r
+// WL_MENU.C\r
+// by John Romero (C) 1992 Id Software, Inc.\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+#include "wl_def.h"\r
+#pragma hdrstop\r
+\r
+//\r
+// PRIVATE PROTOTYPES\r
+//\r
+void CP_ReadThis(void);\r
+\r
+#ifdef SPEAR\r
+#define STARTITEM newgame\r
+\r
+#else\r
+#ifdef GOODTIMES\r
+#define STARTITEM newgame\r
+\r
+#else\r
+#define STARTITEM readthis\r
+#endif\r
+#endif\r
+\r
+char far endStrings[9][80]=\r
+{\r
+#ifndef SPEAR\r
+ {"Dost thou wish to\nleave with such hasty\nabandon?"},\r
+ {"Chickening out...\nalready?"},\r
+ {"Press N for more carnage.\nPress Y to be a weenie."},\r
+ {"So, you think you can\nquit this easily, huh?"},\r
+ {"Press N to save the world.\nPress Y to abandon it in\nits hour of need."},\r
+ {"Press N if you are brave.\nPress Y to cower in shame."},\r
+ {"Heroes, press N.\nWimps, press Y."},\r
+ {"You are at an intersection.\nA sign says, 'Press Y to quit.'\n>"},\r
+ {"For guns and glory, press N.\nFor work and worry, press Y."}\r
+#else\r
+ ENDSTR1,\r
+ ENDSTR2,\r
+ ENDSTR3,\r
+ ENDSTR4,\r
+ ENDSTR5,\r
+ ENDSTR6,\r
+ ENDSTR7,\r
+ ENDSTR8,\r
+ ENDSTR9\r
+#endif\r
+};\r
+\r
+CP_iteminfo\r
+ MainItems={MENU_X,MENU_Y,10,STARTITEM,24},\r
+ SndItems={SM_X,SM_Y1,12,0,52},\r
+ LSItems={LSM_X,LSM_Y,10,0,24},\r
+ CtlItems={CTL_X,CTL_Y,6,-1,56},\r
+ CusItems={8,CST_Y+13*2,9,-1,0},\r
+ NewEitems={NE_X,NE_Y,11,0,88},\r
+ NewItems={NM_X,NM_Y,4,2,24};\r
+\r
+#pragma warn -sus\r
+CP_itemtype far\r
+MainMenu[]=\r
+{\r
+#ifdef JAPAN\r
+ {1,"",CP_NewGame},\r
+ {1,"",CP_Sound},\r
+ {1,"",CP_Control},\r
+ {1,"",CP_LoadGame},\r
+ {0,"",CP_SaveGame},\r
+ {1,"",CP_ChangeView},\r
+ {2,"",CP_ReadThis},\r
+ {1,"",CP_ViewScores},\r
+ {1,"",0},\r
+ {1,"",0}\r
+#else\r
+\r
+ {1,STR_NG,CP_NewGame},\r
+ {1,STR_SD,CP_Sound},\r
+ {1,STR_CL,CP_Control},\r
+ {1,STR_LG,CP_LoadGame},\r
+ {0,STR_SG,CP_SaveGame},\r
+ {1,STR_CV,CP_ChangeView},\r
+\r
+#ifndef GOODTIMES\r
+#ifndef SPEAR\r
+\r
+ #ifdef SPANISH\r
+ {2,"Ve esto!",CP_ReadThis},\r
+ #else\r
+ {2,"Read This!",CP_ReadThis},\r
+ #endif\r
+\r
+#endif\r
+#endif\r
+\r
+ {1,STR_VS,CP_ViewScores},\r
+ {1,STR_BD,0},\r
+ {1,STR_QT,0}\r
+#endif\r
+},\r
+\r
+far SndMenu[]=\r
+{\r
+#ifdef JAPAN\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+#else\r
+ {1,STR_NONE,0},\r
+ {1,STR_PC,0},\r
+ {1,STR_ALSB,0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {1,STR_NONE,0},\r
+ {1,STR_DISNEY,0},\r
+ {1,STR_SB,0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {1,STR_NONE,0},\r
+ {1,STR_ALSB,0}\r
+#endif\r
+},\r
+\r
+far CtlMenu[]=\r
+{\r
+#ifdef JAPAN\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",MouseSensitivity},\r
+ {1,"",CustomControls}\r
+#else\r
+ {0,STR_MOUSEEN,0},\r
+ {0,STR_JOYEN,0},\r
+ {0,STR_PORT2,0},\r
+ {0,STR_GAMEPAD,0},\r
+ {0,STR_SENS,MouseSensitivity},\r
+ {1,STR_CUSTOM,CustomControls}\r
+#endif\r
+},\r
+\r
+#pragma warn +sus\r
+\r
+#ifndef SPEAR\r
+far NewEmenu[]=\r
+{\r
+#ifdef JAPAN\r
+#ifdef JAPDEMO\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+#else\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0}\r
+#endif\r
+#else\r
+ #ifdef SPANISH\r
+ {1,"Episodio 1\n"\r
+ "Fuga desde Wolfenstein",0},\r
+ {0,"",0},\r
+ {3,"Episodio 2\n"\r
+ "Operacion Eisenfaust",0},\r
+ {0,"",0},\r
+ {3,"Episodio 3\n"\r
+ "Muere, Fuhrer, Muere!",0},\r
+ {0,"",0},\r
+ {3,"Episodio 4\n"\r
+ "Un Negro Secreto",0},\r
+ {0,"",0},\r
+ {3,"Episodio 5\n"\r
+ "Huellas del Loco",0},\r
+ {0,"",0},\r
+ {3,"Episodio 6\n"\r
+ "Confrontacion",0}\r
+ #else\r
+ {1,"Episode 1\n"\r
+ "Escape from Wolfenstein",0},\r
+ {0,"",0},\r
+ {3,"Episode 2\n"\r
+ "Operation: Eisenfaust",0},\r
+ {0,"",0},\r
+ {3,"Episode 3\n"\r
+ "Die, Fuhrer, Die!",0},\r
+ {0,"",0},\r
+ {3,"Episode 4\n"\r
+ "A Dark Secret",0},\r
+ {0,"",0},\r
+ {3,"Episode 5\n"\r
+ "Trail of the Madman",0},\r
+ {0,"",0},\r
+ {3,"Episode 6\n"\r
+ "Confrontation",0}\r
+ #endif\r
+#endif\r
+},\r
+#endif\r
+\r
+\r
+far NewMenu[]=\r
+{\r
+#ifdef JAPAN\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0}\r
+#else\r
+ {1,STR_DADDY,0},\r
+ {1,STR_HURTME,0},\r
+ {1,STR_BRINGEM,0},\r
+ {1,STR_DEATH,0}\r
+#endif\r
+},\r
+\r
+far LSMenu[]=\r
+{\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0},\r
+ {1,"",0}\r
+},\r
+\r
+far CusMenu[]=\r
+{\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {0,"",0},\r
+ {1,"",0},\r
+ {0,"",0},\r
+ {1,"",0}\r
+}\r
+;\r
+\r
+\r
+int color_hlite[]={\r
+ DEACTIVE,\r
+ HIGHLIGHT,\r
+ READHCOLOR,\r
+ 0x67\r
+ },\r
+\r
+ color_norml[]={\r
+ DEACTIVE,\r
+ TEXTCOLOR,\r
+ READCOLOR,\r
+ 0x6b\r
+ };\r
+\r
+int EpisodeSelect[6]={1};\r
+\r
+\r
+int SaveGamesAvail[10],StartGame,SoundStatus=1,pickquick;\r
+char SaveGameNames[10][32],SaveName[13]="SAVEGAM?.";\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// INPUT MANAGER SCANCODE TABLES\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+static byte\r
+ *ScanNames[] = // Scan code names with single chars\r
+ {\r
+ "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
+ "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
+ "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
+ "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
+ "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
+ "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
+ }, // DEBUG - consolidate these\r
+ far ExtScanCodes[] = // Scan codes with >1 char names\r
+ {\r
+ 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
+ 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
+ 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
+ 0x50,0x4b,0x4d,0x00\r
+ },\r
+ *ExtScanNames[] = // Names corresponding to ExtScanCodes\r
+ {\r
+ "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
+ "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
+ "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
+ "Down","Left","Right",""\r
+ };\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Wolfenstein Control Panel! Ta Da!\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void US_ControlPanel(byte scancode)\r
+{\r
+ int which,i,start;\r
+\r
+\r
+ if (ingame)\r
+ if (CP_CheckQuick(scancode))\r
+ return;\r
+\r
+ StartCPMusic(MENUSONG);\r
+ SetupControlPanel();\r
+\r
+ //\r
+ // F-KEYS FROM WITHIN GAME\r
+ //\r
+ switch(scancode)\r
+ {\r
+ case sc_F1:\r
+ #ifdef SPEAR\r
+ BossKey();\r
+ #else\r
+ #ifdef GOODTIMES\r
+ BossKey();\r
+ #else\r
+ HelpScreens();\r
+ #endif\r
+ #endif\r
+ goto finishup;\r
+\r
+ case sc_F2:\r
+ CP_SaveGame(0);\r
+ goto finishup;\r
+\r
+ case sc_F3:\r
+ CP_LoadGame(0);\r
+ goto finishup;\r
+\r
+ case sc_F4:\r
+ CP_Sound();\r
+ goto finishup;\r
+\r
+ case sc_F5:\r
+ CP_ChangeView();\r
+ goto finishup;\r
+\r
+ case sc_F6:\r
+ CP_Control();\r
+ goto finishup;\r
+\r
+ finishup:\r
+ CleanupControlPanel();\r
+ #ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ #endif\r
+ return;\r
+ }\r
+\r
+#ifdef SPEAR\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+\r
+ DrawMainMenu();\r
+ MenuFadeIn();\r
+ StartGame=0;\r
+\r
+ //\r
+ // MAIN MENU LOOP\r
+ //\r
+ do\r
+ {\r
+ which=HandleMenu(&MainItems,&MainMenu[0],NULL);\r
+\r
+ #ifdef SPEAR\r
+ #ifndef SPEARDEMO\r
+ //\r
+ // EASTER EGG FOR SPEAR OF DESTINY!\r
+ //\r
+ if (Keyboard[sc_I] && Keyboard[sc_D])\r
+ {\r
+ VW_FadeOut();\r
+ StartCPMusic (XJAZNAZI_MUS);\r
+ UnCacheLump(OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ UnCacheLump(BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ MM_SortMem ();\r
+ ClearMemory ();\r
+\r
+\r
+ CA_CacheGrChunk (IDGUYS1PIC);\r
+ VWB_DrawPic(0,0,IDGUYS1PIC);\r
+ UNCACHEGRCHUNK(IDGUYS1PIC);\r
+\r
+ CA_CacheGrChunk (IDGUYS2PIC);\r
+ VWB_DrawPic(0,80,IDGUYS2PIC);\r
+ UNCACHEGRCHUNK(IDGUYS2PIC);\r
+\r
+ VW_UpdateScreen();\r
+\r
+ CA_CacheGrChunk (IDGUYSPALETTE);\r
+ VL_FadeIn(0,255,grsegs[IDGUYSPALETTE],30);\r
+ UNCACHEGRCHUNK(IDGUYSPALETTE);\r
+\r
+ while (Keyboard[sc_I] || Keyboard[sc_D]);\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+\r
+ VW_FadeOut();\r
+\r
+ CacheLump(BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ CacheLump(OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ DrawMainMenu();\r
+ StartCPMusic (MENUSONG);\r
+ MenuFadeIn();\r
+ }\r
+ #endif\r
+ #endif\r
+\r
+ switch(which)\r
+ {\r
+ case viewscores:\r
+ if (MainMenu[viewscores].routine == NULL)\r
+ if (CP_EndGame())\r
+ StartGame=1;\r
+\r
+ DrawMainMenu();\r
+ MenuFadeIn();\r
+ break;\r
+\r
+ case backtodemo:\r
+ #ifdef SPEAR\r
+ if (!ingame)\r
+ {\r
+ //\r
+ // DEALLOCATE ALL SOUNDS!\r
+ //\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ start = STARTPCSOUNDS;\r
+ break;\r
+ case sdm_AdLib:\r
+ start = STARTADLIBSOUNDS;\r
+ break;\r
+ }\r
+\r
+ if (SoundMode != sdm_Off)\r
+ for (i=0;i<NUMSOUNDS;i++,start++)\r
+ if (audiosegs[start])\r
+ MM_SetPurge (&(memptr)audiosegs[start],3); // make purgable\r
+ }\r
+ #endif\r
+\r
+ MM_SortMem();\r
+ StartGame=1;\r
+ if (!ingame)\r
+ StartCPMusic(INTROSONG);\r
+ VL_FadeOut(0,255,0,0,0,10);\r
+ break;\r
+\r
+ case -1:\r
+ case quit:\r
+ CP_Quit();\r
+ break;\r
+\r
+ default:\r
+ if (!StartGame)\r
+ {\r
+ DrawMainMenu();\r
+ MenuFadeIn();\r
+ }\r
+ }\r
+\r
+ //\r
+ // "EXIT OPTIONS" OR "NEW GAME" EXITS\r
+ //\r
+ } while(!StartGame);\r
+\r
+ //\r
+ // DEALLOCATE EVERYTHING\r
+ //\r
+ CleanupControlPanel();\r
+\r
+ //\r
+ // CHANGE MAINMENU ITEM\r
+ //\r
+ if (startgame || loadedgame)\r
+ {\r
+ #pragma warn -sus\r
+ MainMenu[viewscores].routine = NULL;\r
+ #ifndef JAPAN\r
+ _fstrcpy(MainMenu[viewscores].string,STR_EG);\r
+ #endif\r
+ #pragma warn +sus\r
+ }\r
+\r
+ // RETURN/START GAME EXECUTION\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ MM_SortMem ();\r
+#endif\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DRAW MAIN MENU SCREEN\r
+//\r
+void DrawMainMenu(void)\r
+{\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_OPTIONSPIC);\r
+#else\r
+ ClearMScreen();\r
+\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+ DrawStripes(10);\r
+ VWB_DrawPic(84,0,C_OPTIONSPIC);\r
+\r
+ #ifdef SPANISH\r
+ DrawWindow(MENU_X-8,MENU_Y-3,MENU_W+8,MENU_H,BKGDCOLOR);\r
+ #else\r
+ DrawWindow(MENU_X-8,MENU_Y-3,MENU_W,MENU_H,BKGDCOLOR);\r
+ #endif\r
+#endif\r
+\r
+ //\r
+ // CHANGE "GAME" AND "DEMO"\r
+ //\r
+ if (ingame)\r
+ {\r
+ #ifndef JAPAN\r
+\r
+ #ifdef SPANISH\r
+ _fstrcpy(&MainMenu[backtodemo].string,STR_GAME);\r
+ #else\r
+ _fstrcpy(&MainMenu[backtodemo].string[8],STR_GAME);\r
+ #endif\r
+\r
+ #else\r
+ CA_CacheGrChunk(C_MRETGAMEPIC);\r
+ VWB_DrawPic(12*8,20*8,C_MRETGAMEPIC);\r
+ UNCACHEGRCHUNK(C_MRETGAMEPIC);\r
+ CA_CacheGrChunk(C_MENDGAMEPIC);\r
+ VWB_DrawPic(12*8,18*8,C_MENDGAMEPIC);\r
+ UNCACHEGRCHUNK(C_MENDGAMEPIC);\r
+ #endif\r
+ MainMenu[backtodemo].active=2;\r
+ }\r
+ else\r
+ {\r
+ #ifndef JAPAN\r
+ #ifdef SPANISH\r
+ _fstrcpy(&MainMenu[backtodemo].string,STR_BD);\r
+ #else\r
+ _fstrcpy(&MainMenu[backtodemo].string[8],STR_DEMO);\r
+ #endif\r
+ #else\r
+ CA_CacheGrChunk(C_MRETDEMOPIC);\r
+ VWB_DrawPic(12*8,20*8,C_MRETDEMOPIC);\r
+ UNCACHEGRCHUNK(C_MRETDEMOPIC);\r
+ CA_CacheGrChunk(C_MSCORESPIC);\r
+ VWB_DrawPic(12*8,18*8,C_MSCORESPIC);\r
+ UNCACHEGRCHUNK(C_MSCORESPIC);\r
+ #endif\r
+ MainMenu[backtodemo].active=1;\r
+ }\r
+\r
+ DrawMenu(&MainItems,&MainMenu[0]);\r
+ VW_UpdateScreen();\r
+}\r
+\r
+#ifndef GOODTIMES\r
+#ifndef SPEAR\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// READ THIS!\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_ReadThis(void)\r
+{\r
+ StartCPMusic(CORNER_MUS);\r
+ HelpScreens();\r
+ StartCPMusic(MENUSONG);\r
+}\r
+#endif\r
+#endif\r
+\r
+#ifndef SPEAR\r
+#ifndef GOODTIMES\r
+#else\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// BOSS KEY\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void BossKey(void)\r
+{\r
+ SD_MusicOff();\r
+ _AX = 3;\r
+ geninterrupt(0x10);\r
+ printf("C>");\r
+ while (!Keyboard[sc_Escape])\r
+ IN_ClearKeysDown();\r
+\r
+ SD_MusicOn();\r
+ VL_SetVGAPlaneMode ();\r
+ VL_TestPaletteSet ();\r
+ VL_SetPalette (&gamepal);\r
+ LoadLatchMem();\r
+}\r
+#endif\r
+#endif\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// CHECK QUICK-KEYS & QUIT (WHILE IN A GAME)\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int CP_CheckQuick(unsigned scancode)\r
+{\r
+ switch(scancode)\r
+ {\r
+ //\r
+ // END GAME\r
+ //\r
+ case sc_F7:\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+\r
+ WindowH=160;\r
+ #ifdef JAPAN\r
+ if (GetYorN(7,8,C_JAPQUITPIC))\r
+ #else\r
+ if (Confirm(ENDGAMESTR))\r
+ #endif\r
+ {\r
+ playstate = ex_died;\r
+ pickquick = gamestate.lives = 0;\r
+ }\r
+\r
+ DrawAllPlayBorder();\r
+ WindowH=200;\r
+ fontnumber=0;\r
+ MainMenu[savegame].active = 0;\r
+ return 1;\r
+\r
+ //\r
+ // QUICKSAVE\r
+ //\r
+ case sc_F8:\r
+ if (SaveGamesAvail[LSItems.curpos] && pickquick)\r
+ {\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+ fontnumber = 1;\r
+ Message(STR_SAVING"...");\r
+ CP_SaveGame(1);\r
+ fontnumber=0;\r
+ }\r
+ else\r
+ {\r
+ #ifndef SPEAR\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+ CA_CacheGrChunk(C_CURSOR1PIC);\r
+ CA_CacheGrChunk(C_CURSOR2PIC);\r
+ CA_CacheGrChunk(C_DISKLOADING1PIC);\r
+ CA_CacheGrChunk(C_DISKLOADING2PIC);\r
+ CA_CacheGrChunk(C_SAVEGAMEPIC);\r
+ CA_CacheGrChunk(C_MOUSELBACKPIC);\r
+ #else\r
+ CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ CA_CacheGrChunk(C_CURSOR1PIC);\r
+ #endif\r
+\r
+ VW_FadeOut ();\r
+\r
+ StartCPMusic(MENUSONG);\r
+ pickquick=CP_SaveGame(0);\r
+\r
+ SETFONTCOLOR(0,15);\r
+ IN_ClearKeysDown();\r
+ DrawPlayScreen ();\r
+\r
+ if (!startgame && !loadedgame)\r
+ {\r
+ VW_FadeIn ();\r
+ StartMusic ();\r
+ }\r
+\r
+ if (loadedgame)\r
+ playstate = ex_abort;\r
+ lasttimecount = TimeCount;\r
+\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+\r
+ PM_CheckMainMem ();\r
+\r
+ #ifndef SPEAR\r
+ UNCACHEGRCHUNK(C_CURSOR1PIC);\r
+ UNCACHEGRCHUNK(C_CURSOR2PIC);\r
+ UNCACHEGRCHUNK(C_DISKLOADING1PIC);\r
+ UNCACHEGRCHUNK(C_DISKLOADING2PIC);\r
+ UNCACHEGRCHUNK(C_SAVEGAMEPIC);\r
+ UNCACHEGRCHUNK(C_MOUSELBACKPIC);\r
+ #else\r
+ UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ #endif\r
+ }\r
+ return 1;\r
+\r
+ //\r
+ // QUICKLOAD\r
+ //\r
+ case sc_F9:\r
+ if (SaveGamesAvail[LSItems.curpos] && pickquick)\r
+ {\r
+ char string[100]=STR_LGC;\r
+\r
+\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+ fontnumber = 1;\r
+\r
+ strcat(string,SaveGameNames[LSItems.curpos]);\r
+ strcat(string,"\"?");\r
+\r
+ if (Confirm(string))\r
+ CP_LoadGame(1);\r
+\r
+ DrawAllPlayBorder();\r
+ fontnumber=0;\r
+ }\r
+ else\r
+ {\r
+ #ifndef SPEAR\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+ CA_CacheGrChunk(C_CURSOR1PIC);\r
+ CA_CacheGrChunk(C_CURSOR2PIC);\r
+ CA_CacheGrChunk(C_DISKLOADING1PIC);\r
+ CA_CacheGrChunk(C_DISKLOADING2PIC);\r
+ CA_CacheGrChunk(C_LOADGAMEPIC);\r
+ CA_CacheGrChunk(C_MOUSELBACKPIC);\r
+ #else\r
+ CA_CacheGrChunk(C_CURSOR1PIC);\r
+ CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ #endif\r
+\r
+ VW_FadeOut ();\r
+\r
+ StartCPMusic(MENUSONG);\r
+ pickquick=CP_LoadGame(0);\r
+\r
+ SETFONTCOLOR(0,15);\r
+ IN_ClearKeysDown();\r
+ DrawPlayScreen ();\r
+\r
+ if (!startgame && !loadedgame)\r
+ {\r
+ VW_FadeIn ();\r
+ StartMusic ();\r
+ }\r
+\r
+ if (loadedgame)\r
+ playstate = ex_abort;\r
+\r
+ lasttimecount = TimeCount;\r
+\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+ PM_CheckMainMem ();\r
+\r
+ #ifndef SPEAR\r
+ UNCACHEGRCHUNK(C_CURSOR1PIC);\r
+ UNCACHEGRCHUNK(C_CURSOR2PIC);\r
+ UNCACHEGRCHUNK(C_DISKLOADING1PIC);\r
+ UNCACHEGRCHUNK(C_DISKLOADING2PIC);\r
+ UNCACHEGRCHUNK(C_LOADGAMEPIC);\r
+ UNCACHEGRCHUNK(C_MOUSELBACKPIC);\r
+ #else\r
+ UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ #endif\r
+ }\r
+ return 1;\r
+\r
+ //\r
+ // QUIT\r
+ //\r
+ case sc_F10:\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+\r
+ WindowX=WindowY=0;\r
+ WindowW=320;\r
+ WindowH=160;\r
+ #ifdef JAPAN\r
+ if (GetYorN(7,8,C_QUITMSGPIC))\r
+ #else\r
+ #ifdef SPANISH\r
+ if (Confirm(ENDGAMESTR))\r
+ #else\r
+ if (Confirm(endStrings[US_RndT()&0x7+(US_RndT()&1)]))\r
+ #endif\r
+ #endif\r
+ {\r
+ int i;\r
+\r
+\r
+ VW_UpdateScreen();\r
+ SD_MusicOff();\r
+ SD_StopSound();\r
+ MenuFadeOut();\r
+\r
+ //\r
+ // SHUT-UP THE ADLIB\r
+ //\r
+ for (i=1;i<=0xf5;i++)\r
+ alOut(i,0);\r
+ Quit(NULL);\r
+ }\r
+\r
+ DrawAllPlayBorder();\r
+ WindowH=200;\r
+ fontnumber=0;\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// END THE CURRENT GAME\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int CP_EndGame(void)\r
+{\r
+#ifdef JAPAN\r
+ if (!GetYorN(7,8,C_JAPQUITPIC))\r
+#else\r
+ if (!Confirm(ENDGAMESTR))\r
+#endif\r
+ return 0;\r
+\r
+ pickquick = gamestate.lives = 0;\r
+ playstate = ex_died;\r
+\r
+ #pragma warn -sus\r
+ MainMenu[savegame].active = 0;\r
+ MainMenu[viewscores].routine=CP_ViewScores;\r
+ #ifndef JAPAN\r
+ _fstrcpy(MainMenu[viewscores].string,STR_VS);\r
+ #endif\r
+ #pragma warn +sus\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// VIEW THE HIGH SCORES\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_ViewScores(void)\r
+{\r
+ fontnumber=0;\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ StartCPMusic (XAWARD_MUS);\r
+#else\r
+ StartCPMusic (ROSTER_MUS);\r
+#endif\r
+\r
+ DrawHighScores ();\r
+ VW_UpdateScreen ();\r
+ MenuFadeIn();\r
+ fontnumber=1;\r
+\r
+ IN_Ack();\r
+\r
+ StartCPMusic(MENUSONG);\r
+ MenuFadeOut();\r
+\r
+#ifdef SPEAR\r
+ CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// START A NEW GAME\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_NewGame(void)\r
+{\r
+ int which,episode;\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+\r
+\r
+#ifndef SPEAR\r
+firstpart:\r
+\r
+ DrawNewEpisode();\r
+ do\r
+ {\r
+ which=HandleMenu(&NewEitems,&NewEmenu[0],NULL);\r
+ switch(which)\r
+ {\r
+ case -1:\r
+ MenuFadeOut();\r
+ return;\r
+\r
+ default:\r
+ if (!EpisodeSelect[which/2])\r
+ {\r
+ SD_PlaySound (NOWAYSND);\r
+ Message("Please select \"Read This!\"\n"\r
+ "from the Options menu to\n"\r
+ "find out how to order this\n"\r
+ "episode from Apogee.");\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+ DrawNewEpisode();\r
+ which = 0;\r
+ }\r
+ else\r
+ {\r
+ episode = which/2;\r
+ which = 1;\r
+ }\r
+ break;\r
+ }\r
+\r
+ } while (!which);\r
+\r
+ ShootSnd();\r
+\r
+ //\r
+ // ALREADY IN A GAME?\r
+ //\r
+ if (ingame)\r
+ #ifdef JAPAN\r
+ if (!GetYorN(7,8,C_JAPNEWGAMEPIC))\r
+ #else\r
+ if (!Confirm(CURGAME))\r
+ #endif\r
+ {\r
+ MenuFadeOut();\r
+ return;\r
+ }\r
+\r
+ MenuFadeOut();\r
+\r
+#else\r
+ episode = 0;\r
+\r
+ //\r
+ // ALREADY IN A GAME?\r
+ //\r
+ CacheLump (NEWGAME_LUMP_START,NEWGAME_LUMP_END);\r
+ DrawNewGame();\r
+ if (ingame)\r
+ if (!Confirm(CURGAME))\r
+ {\r
+ MenuFadeOut();\r
+ UnCacheLump (NEWGAME_LUMP_START,NEWGAME_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ return;\r
+ }\r
+\r
+#endif\r
+\r
+ DrawNewGame();\r
+ which=HandleMenu(&NewItems,&NewMenu[0],DrawNewGameDiff);\r
+ if (which<0)\r
+ {\r
+ MenuFadeOut();\r
+ #ifndef SPEAR\r
+ goto firstpart;\r
+ #else\r
+ UnCacheLump (NEWGAME_LUMP_START,NEWGAME_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ return;\r
+ #endif\r
+ }\r
+\r
+ ShootSnd();\r
+ NewGame(which,episode);\r
+ StartGame=1;\r
+ MenuFadeOut();\r
+\r
+ //\r
+ // CHANGE "READ THIS!" TO NORMAL COLOR\r
+ //\r
+ #ifndef SPEAR\r
+ #ifndef GOODTIMES\r
+ MainMenu[readthis].active=1;\r
+ #endif\r
+ #endif\r
+\r
+ pickquick = 0;\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (NEWGAME_LUMP_START,NEWGAME_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+}\r
+\r
+\r
+#ifndef SPEAR\r
+/////////////////////\r
+//\r
+// DRAW NEW EPISODE MENU\r
+//\r
+void DrawNewEpisode(void)\r
+{\r
+ int i;\r
+\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_EPISODEPIC);\r
+#else\r
+ ClearMScreen();\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+\r
+ DrawWindow(NE_X-4,NE_Y-4,NE_W+8,NE_H+8,BKGDCOLOR);\r
+ SETFONTCOLOR(READHCOLOR,BKGDCOLOR);\r
+ PrintY=2;\r
+ WindowX=0;\r
+ #ifdef SPANISH\r
+ US_CPrint("Cual episodio jugar?");\r
+ #else\r
+ US_CPrint("Which episode to play?");\r
+ #endif\r
+#endif\r
+\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ DrawMenu(&NewEitems,&NewEmenu[0]);\r
+\r
+ for (i=0;i<6;i++)\r
+ VWB_DrawPic(NE_X+32,NE_Y+i*26,C_EPISODE1PIC+i);\r
+\r
+ VW_UpdateScreen();\r
+ MenuFadeIn();\r
+ WaitKeyUp();\r
+}\r
+#endif\r
+\r
+/////////////////////\r
+//\r
+// DRAW NEW GAME MENU\r
+//\r
+void DrawNewGame(void)\r
+{\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_SKILLPIC);\r
+#else\r
+ ClearMScreen();\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+\r
+ SETFONTCOLOR(READHCOLOR,BKGDCOLOR);\r
+ PrintX=NM_X+20;\r
+ PrintY=NM_Y-32;\r
+\r
+#ifndef SPEAR\r
+ #ifdef SPANISH\r
+ US_Print("Eres macho?");\r
+ #else\r
+ US_Print("How tough are you?");\r
+ #endif\r
+#else\r
+ VWB_DrawPic (PrintX,PrintY,C_HOWTOUGHPIC);\r
+#endif\r
+\r
+ DrawWindow(NM_X-5,NM_Y-10,NM_W,NM_H,BKGDCOLOR);\r
+#endif\r
+\r
+ DrawMenu(&NewItems,&NewMenu[0]);\r
+ DrawNewGameDiff(NewItems.curpos);\r
+ VW_UpdateScreen();\r
+ MenuFadeIn();\r
+ WaitKeyUp();\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DRAW NEW GAME GRAPHIC\r
+//\r
+void DrawNewGameDiff(int w)\r
+{\r
+ VWB_DrawPic(NM_X+185,NM_Y+7,w+C_BABYMODEPIC);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// HANDLE SOUND MENU\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_Sound(void)\r
+{\r
+ int which,i;\r
+\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ CacheLump (SOUND_LUMP_START,SOUND_LUMP_END);\r
+#endif\r
+\r
+ DrawSoundMenu();\r
+ MenuFadeIn();\r
+ WaitKeyUp();\r
+\r
+ do\r
+ {\r
+ which=HandleMenu(&SndItems,&SndMenu[0],NULL);\r
+ //\r
+ // HANDLE MENU CHOICES\r
+ //\r
+ switch(which)\r
+ {\r
+ //\r
+ // SOUND EFFECTS\r
+ //\r
+ case 0:\r
+ if (SoundMode!=sdm_Off)\r
+ {\r
+ SD_WaitSoundDone();\r
+ SD_SetSoundMode(sdm_Off);\r
+ DrawSoundMenu();\r
+ }\r
+ break;\r
+ case 1:\r
+ if (SoundMode!=sdm_PC)\r
+ {\r
+ SD_WaitSoundDone();\r
+ SD_SetSoundMode(sdm_PC);\r
+ CA_LoadAllSounds();\r
+ DrawSoundMenu();\r
+ ShootSnd();\r
+ }\r
+ break;\r
+ case 2:\r
+ if (SoundMode!=sdm_AdLib)\r
+ {\r
+ SD_WaitSoundDone();\r
+ SD_SetSoundMode(sdm_AdLib);\r
+ CA_LoadAllSounds();\r
+ DrawSoundMenu();\r
+ ShootSnd();\r
+ }\r
+ break;\r
+\r
+ //\r
+ // DIGITIZED SOUND\r
+ //\r
+ case 5:\r
+ if (DigiMode!=sds_Off)\r
+ {\r
+ SD_SetDigiDevice(sds_Off);\r
+ DrawSoundMenu();\r
+ }\r
+ break;\r
+ case 6:\r
+ if (DigiMode!=sds_SoundSource)\r
+ {\r
+ SD_SetDigiDevice(sds_SoundSource);\r
+ DrawSoundMenu();\r
+ ShootSnd();\r
+ }\r
+ break;\r
+ case 7:\r
+ if (DigiMode!=sds_SoundBlaster)\r
+ {\r
+ SD_SetDigiDevice(sds_SoundBlaster);\r
+ DrawSoundMenu();\r
+ ShootSnd();\r
+ }\r
+ break;\r
+\r
+ //\r
+ // MUSIC\r
+ //\r
+ case 10:\r
+ if (MusicMode!=smm_Off)\r
+ {\r
+ SD_SetMusicMode(smm_Off);\r
+ DrawSoundMenu();\r
+ ShootSnd();\r
+ }\r
+ break;\r
+ case 11:\r
+ if (MusicMode!=smm_AdLib)\r
+ {\r
+ SD_SetMusicMode(smm_AdLib);\r
+ DrawSoundMenu();\r
+ ShootSnd();\r
+ StartCPMusic(MENUSONG);\r
+ }\r
+ break;\r
+ }\r
+ } while(which>=0);\r
+\r
+ MenuFadeOut();\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (SOUND_LUMP_START,SOUND_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+}\r
+\r
+\r
+//////////////////////\r
+//\r
+// DRAW THE SOUND MENU\r
+//\r
+void DrawSoundMenu(void)\r
+{\r
+ int i,on;\r
+\r
+\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_SOUNDPIC);\r
+#else\r
+ //\r
+ // DRAW SOUND MENU\r
+ //\r
+ ClearMScreen();\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+\r
+ DrawWindow(SM_X-8,SM_Y1-3,SM_W,SM_H1,BKGDCOLOR);\r
+ DrawWindow(SM_X-8,SM_Y2-3,SM_W,SM_H2,BKGDCOLOR);\r
+ DrawWindow(SM_X-8,SM_Y3-3,SM_W,SM_H3,BKGDCOLOR);\r
+#endif\r
+\r
+ //\r
+ // IF NO ADLIB, NON-CHOOSENESS!\r
+ //\r
+ if (!AdLibPresent && !SoundBlasterPresent)\r
+ {\r
+ SndMenu[2].active=SndMenu[10].active=SndMenu[11].active=0;\r
+ }\r
+\r
+ if (!SoundSourcePresent)\r
+ SndMenu[6].active=0;\r
+\r
+ if (!SoundBlasterPresent)\r
+ SndMenu[7].active=0;\r
+\r
+ if (!SoundSourcePresent && !SoundBlasterPresent)\r
+ SndMenu[5].active=0;\r
+\r
+ DrawMenu(&SndItems,&SndMenu[0]);\r
+#ifndef JAPAN\r
+ VWB_DrawPic(100,SM_Y1-20,C_FXTITLEPIC);\r
+ VWB_DrawPic(100,SM_Y2-20,C_DIGITITLEPIC);\r
+ VWB_DrawPic(100,SM_Y3-20,C_MUSICTITLEPIC);\r
+#endif\r
+\r
+ for (i=0;i<SndItems.amount;i++)\r
+#ifdef JAPAN\r
+ if (i!=3 && i!=4 && i!=8 && i!=9)\r
+#else\r
+ if (SndMenu[i].string[0])\r
+#endif\r
+ {\r
+ //\r
+ // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS\r
+ //\r
+ on=0;\r
+ switch(i)\r
+ {\r
+ //\r
+ // SOUND EFFECTS\r
+ //\r
+ case 0: if (SoundMode==sdm_Off) on=1; break;\r
+ case 1: if (SoundMode==sdm_PC) on=1; break;\r
+ case 2: if (SoundMode==sdm_AdLib) on=1; break;\r
+\r
+ //\r
+ // DIGITIZED SOUND\r
+ //\r
+ case 5: if (DigiMode==sds_Off) on=1; break;\r
+ case 6: if (DigiMode==sds_SoundSource) on=1; break;\r
+ case 7: if (DigiMode==sds_SoundBlaster) on=1; break;\r
+\r
+ //\r
+ // MUSIC\r
+ //\r
+ case 10: if (MusicMode==smm_Off) on=1; break;\r
+ case 11: if (MusicMode==smm_AdLib) on=1; break;\r
+ }\r
+\r
+ if (on)\r
+ VWB_DrawPic(SM_X+24,SM_Y1+i*13+2,C_SELECTEDPIC);\r
+ else\r
+ VWB_DrawPic(SM_X+24,SM_Y1+i*13+2,C_NOTSELECTEDPIC);\r
+ }\r
+\r
+ DrawMenuGun(&SndItems);\r
+ VW_UpdateScreen();\r
+}\r
+\r
+\r
+//\r
+// DRAW LOAD/SAVE IN PROGRESS\r
+//\r
+void DrawLSAction(int which)\r
+{\r
+ #define LSA_X 96\r
+ #define LSA_Y 80\r
+ #define LSA_W 130\r
+ #define LSA_H 42\r
+\r
+ DrawWindow(LSA_X,LSA_Y,LSA_W,LSA_H,TEXTCOLOR);\r
+ DrawOutline(LSA_X,LSA_Y,LSA_W,LSA_H,0,HIGHLIGHT);\r
+ VWB_DrawPic(LSA_X+8,LSA_Y+5,C_DISKLOADING1PIC);\r
+\r
+ fontnumber=1;\r
+ SETFONTCOLOR(0,TEXTCOLOR);\r
+ PrintX=LSA_X+46;\r
+ PrintY=LSA_Y+13;\r
+\r
+ if (!which)\r
+ US_Print(STR_LOADING"...");\r
+ else\r
+ US_Print(STR_SAVING"...");\r
+\r
+ VW_UpdateScreen();\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// LOAD SAVED GAMES\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int CP_LoadGame(int quick)\r
+{\r
+ int handle,which,exit=0;\r
+ char name[13];\r
+\r
+\r
+ strcpy(name,SaveName);\r
+\r
+ //\r
+ // QUICKLOAD?\r
+ //\r
+ if (quick)\r
+ {\r
+ which=LSItems.curpos;\r
+\r
+ if (SaveGamesAvail[which])\r
+ {\r
+ name[7]=which+'0';\r
+ handle=open(name,O_BINARY);\r
+ lseek(handle,32,SEEK_SET);\r
+ loadedgame=true;\r
+ LoadTheGame(handle,0,0);\r
+ loadedgame=false;\r
+ close(handle);\r
+\r
+ DrawFace ();\r
+ DrawHealth ();\r
+ DrawLives ();\r
+ DrawLevel ();\r
+ DrawAmmo ();\r
+ DrawKeys ();\r
+ DrawWeapon ();\r
+ DrawScore ();\r
+ return 1;\r
+ }\r
+ }\r
+\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ CacheLump (LOADSAVE_LUMP_START,LOADSAVE_LUMP_END);\r
+#endif\r
+\r
+ DrawLoadSaveScreen(0);\r
+\r
+ do\r
+ {\r
+ which=HandleMenu(&LSItems,&LSMenu[0],TrackWhichGame);\r
+ if (which>=0 && SaveGamesAvail[which])\r
+ {\r
+ ShootSnd();\r
+ name[7]=which+'0';\r
+\r
+ handle=open(name,O_BINARY);\r
+ lseek(handle,32,SEEK_SET);\r
+\r
+ DrawLSAction(0);\r
+ loadedgame=true;\r
+\r
+ LoadTheGame(handle,LSA_X+8,LSA_Y+5);\r
+ close(handle);\r
+\r
+ StartGame=1;\r
+ ShootSnd();\r
+ //\r
+ // CHANGE "READ THIS!" TO NORMAL COLOR\r
+ //\r
+\r
+ #ifndef SPEAR\r
+ #ifndef GOODTIMES\r
+ MainMenu[readthis].active=1;\r
+ #endif\r
+ #endif\r
+\r
+ exit=1;\r
+ break;\r
+ }\r
+\r
+ } while(which>=0);\r
+\r
+ MenuFadeOut();\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (LOADSAVE_LUMP_START,LOADSAVE_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+\r
+ return exit;\r
+}\r
+\r
+\r
+///////////////////////////////////\r
+//\r
+// HIGHLIGHT CURRENT SELECTED ENTRY\r
+//\r
+void TrackWhichGame(int w)\r
+{\r
+ static int lastgameon=0;\r
+\r
+ PrintLSEntry(lastgameon,TEXTCOLOR);\r
+ PrintLSEntry(w,HIGHLIGHT);\r
+\r
+ lastgameon=w;\r
+}\r
+\r
+\r
+////////////////////////////\r
+//\r
+// DRAW THE LOAD/SAVE SCREEN\r
+//\r
+void DrawLoadSaveScreen(int loadsave)\r
+{\r
+ #define DISKX 100\r
+ #define DISKY 0\r
+\r
+ int i;\r
+\r
+\r
+ ClearMScreen();\r
+ fontnumber=1;\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+ DrawWindow(LSM_X-10,LSM_Y-5,LSM_W,LSM_H,BKGDCOLOR);\r
+ DrawStripes(10);\r
+\r
+ if (!loadsave)\r
+ VWB_DrawPic(60,0,C_LOADGAMEPIC);\r
+ else\r
+ VWB_DrawPic(60,0,C_SAVEGAMEPIC);\r
+\r
+ for (i=0;i<10;i++)\r
+ PrintLSEntry(i,TEXTCOLOR);\r
+\r
+ DrawMenu(&LSItems,&LSMenu[0]);\r
+ VW_UpdateScreen();\r
+ MenuFadeIn();\r
+ WaitKeyUp();\r
+}\r
+\r
+\r
+///////////////////////////////////////////\r
+//\r
+// PRINT LOAD/SAVE GAME ENTRY W/BOX OUTLINE\r
+//\r
+void PrintLSEntry(int w,int color)\r
+{\r
+ SETFONTCOLOR(color,BKGDCOLOR);\r
+ DrawOutline(LSM_X+LSItems.indent,LSM_Y+w*13,LSM_W-LSItems.indent-15,11,color,color);\r
+ PrintX=LSM_X+LSItems.indent+2;\r
+ PrintY=LSM_Y+w*13+1;\r
+ fontnumber=0;\r
+\r
+ if (SaveGamesAvail[w])\r
+ US_Print(SaveGameNames[w]);\r
+ else\r
+ US_Print(" - "STR_EMPTY" -");\r
+\r
+ fontnumber=1;\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// SAVE CURRENT GAME\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int CP_SaveGame(int quick)\r
+{\r
+ int handle,which,exit=0;\r
+ unsigned nwritten;\r
+ char name[13],input[32];\r
+\r
+\r
+ strcpy(name,SaveName);\r
+\r
+ //\r
+ // QUICKSAVE?\r
+ //\r
+ if (quick)\r
+ {\r
+ which=LSItems.curpos;\r
+\r
+ if (SaveGamesAvail[which])\r
+ {\r
+ name[7]=which+'0';\r
+ unlink(name);\r
+ handle=creat(name,S_IREAD|S_IWRITE);\r
+\r
+ strcpy(input,&SaveGameNames[which][0]);\r
+\r
+ _dos_write(handle,(void far *)input,32,&nwritten);\r
+ lseek(handle,32,SEEK_SET);\r
+ SaveTheGame(handle,0,0);\r
+ close(handle);\r
+\r
+ return 1;\r
+ }\r
+ }\r
+\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ CacheLump (LOADSAVE_LUMP_START,LOADSAVE_LUMP_END);\r
+#endif\r
+\r
+ DrawLoadSaveScreen(1);\r
+\r
+ do\r
+ {\r
+ which=HandleMenu(&LSItems,&LSMenu[0],TrackWhichGame);\r
+ if (which>=0)\r
+ {\r
+ //\r
+ // OVERWRITE EXISTING SAVEGAME?\r
+ //\r
+ if (SaveGamesAvail[which])\r
+ #ifdef JAPAN\r
+ if (!GetYorN(7,8,C_JAPSAVEOVERPIC))\r
+ #else\r
+ if (!Confirm(GAMESVD))\r
+ #endif\r
+ {\r
+ DrawLoadSaveScreen(1);\r
+ continue;\r
+ }\r
+ else\r
+ {\r
+ DrawLoadSaveScreen(1);\r
+ PrintLSEntry(which,HIGHLIGHT);\r
+ VW_UpdateScreen();\r
+ }\r
+\r
+ ShootSnd();\r
+\r
+ strcpy(input,&SaveGameNames[which][0]);\r
+ name[7]=which+'0';\r
+\r
+ fontnumber=0;\r
+ if (!SaveGamesAvail[which])\r
+ VWB_Bar(LSM_X+LSItems.indent+1,LSM_Y+which*13+1,LSM_W-LSItems.indent-16,10,BKGDCOLOR);\r
+ VW_UpdateScreen();\r
+\r
+ if (US_LineInput(LSM_X+LSItems.indent+2,LSM_Y+which*13+1,input,input,true,31,LSM_W-LSItems.indent-30))\r
+ {\r
+ SaveGamesAvail[which]=1;\r
+ strcpy(&SaveGameNames[which][0],input);\r
+\r
+ unlink(name);\r
+ handle=creat(name,S_IREAD|S_IWRITE);\r
+ _dos_write(handle,(void far *)input,32,&nwritten);\r
+ lseek(handle,32,SEEK_SET);\r
+\r
+ DrawLSAction(1);\r
+ SaveTheGame(handle,LSA_X+8,LSA_Y+5);\r
+\r
+ close(handle);\r
+\r
+ ShootSnd();\r
+ exit=1;\r
+ }\r
+ else\r
+ {\r
+ VWB_Bar(LSM_X+LSItems.indent+1,LSM_Y+which*13+1,LSM_W-LSItems.indent-16,10,BKGDCOLOR);\r
+ PrintLSEntry(which,HIGHLIGHT);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(ESCPRESSEDSND);\r
+ continue;\r
+ }\r
+\r
+ fontnumber=1;\r
+ break;\r
+ }\r
+\r
+ } while(which>=0);\r
+\r
+ MenuFadeOut();\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (LOADSAVE_LUMP_START,LOADSAVE_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+\r
+ return exit;\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// CALIBRATE JOYSTICK\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int CalibrateJoystick(void)\r
+{\r
+ #define CALX 85\r
+ #define CALY 40\r
+ #define CALW 158\r
+ #define CALH 140\r
+\r
+ unsigned xmin,ymin,xmax,ymax,jb;\r
+\r
+\r
+\r
+ #ifdef JAPAN\r
+ VWB_DrawPic(CALX,CALY,C_JOY0PIC);\r
+ #else\r
+ DrawWindow(CALX-5,CALY-5,CALW,CALH,TEXTCOLOR);\r
+ DrawOutline(CALX-5,CALY-5,CALW,CALH,0,HIGHLIGHT);\r
+ SETFONTCOLOR(0,TEXTCOLOR);\r
+\r
+ WindowX = PrintX = CALX;\r
+ WindowW = CALW;\r
+ WindowH = CALH;\r
+ WindowY = PrintY = CALY;\r
+ US_Print(" "STR_CALIB"\n "STR_JOYST"\n");\r
+ VWB_DrawPic(CALX+40,CALY+30,C_JOY1PIC);\r
+ PrintY = CALY+80;\r
+ US_Print(STR_MOVEJOY);\r
+ SETFONTCOLOR(BKGDCOLOR,TEXTCOLOR);\r
+ US_Print(" "STR_ESCEXIT);\r
+ #endif\r
+ VW_UpdateScreen();\r
+\r
+ do\r
+ {\r
+ jb=IN_JoyButtons();\r
+ if (Keyboard[sc_Escape])\r
+ return 0;\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+\r
+ } while(!(jb&1));\r
+\r
+ SD_PlaySound(SHOOTSND);\r
+ IN_GetJoyAbs(joystickport,&xmin,&ymin);\r
+\r
+\r
+ #ifdef JAPAN\r
+ VWB_DrawPic(CALX,CALY,C_JOY1PIC);\r
+ #else\r
+ DrawWindow(CALX-5,CALY-5,CALW,CALH,TEXTCOLOR);\r
+ DrawOutline(CALX-5,CALY-5,CALW,CALH,0,HIGHLIGHT);\r
+ SETFONTCOLOR(0,TEXTCOLOR);\r
+\r
+ PrintX = CALX;\r
+ PrintY = CALY;\r
+ US_Print(" "STR_CALIB"\n "STR_JOYST"\n");\r
+ VWB_DrawPic(CALX+40,CALY+30,C_JOY2PIC);\r
+ PrintY = CALY+80;\r
+ US_Print(STR_MOVEJOY2);\r
+ SETFONTCOLOR(BKGDCOLOR,TEXTCOLOR);\r
+ US_Print(" "STR_ESCEXIT);\r
+ #endif\r
+ VW_UpdateScreen();\r
+\r
+ do\r
+ {\r
+ jb=IN_JoyButtons();\r
+ if (Keyboard[sc_Escape])\r
+ return 0;\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+ } while(!(jb&2));\r
+\r
+ IN_GetJoyAbs(joystickport,&xmax,&ymax);\r
+ SD_PlaySound(SHOOTSND);\r
+\r
+ while (IN_JoyButtons());\r
+\r
+ //\r
+ // ASSIGN ACTUAL VALUES HERE\r
+ //\r
+ if ((xmin != xmax) && (ymin != ymax))\r
+ IN_SetupJoy(joystickport,xmin,xmax,ymin,ymax);\r
+ else\r
+ return 0;\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// DEFINE CONTROLS\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_Control(void)\r
+{\r
+ #define CTL_SPC 70\r
+ enum {MOUSEENABLE,JOYENABLE,USEPORT2,PADENABLE,MOUSESENS,CUSTOMIZE};\r
+ int i,which;\r
+\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+ CacheLump (CONTROL_LUMP_START,CONTROL_LUMP_END);\r
+#endif\r
+\r
+ DrawCtlScreen();\r
+ MenuFadeIn();\r
+ WaitKeyUp();\r
+\r
+ do\r
+ {\r
+ which=HandleMenu(&CtlItems,&CtlMenu[0],NULL);\r
+ switch(which)\r
+ {\r
+ case MOUSEENABLE:\r
+ mouseenabled^=1;\r
+ _CX=_DX=CENTER;\r
+ Mouse(4);\r
+ DrawCtlScreen();\r
+ CusItems.curpos=-1;\r
+ ShootSnd();\r
+ break;\r
+\r
+ case JOYENABLE:\r
+ joystickenabled^=1;\r
+ if (joystickenabled)\r
+ if (!CalibrateJoystick())\r
+ joystickenabled = 0;\r
+ DrawCtlScreen();\r
+ CusItems.curpos=-1;\r
+ ShootSnd();\r
+ break;\r
+\r
+ case USEPORT2:\r
+ joystickport^=1;\r
+ DrawCtlScreen();\r
+ ShootSnd();\r
+ break;\r
+\r
+ case PADENABLE:\r
+ joypadenabled^=1;\r
+ DrawCtlScreen();\r
+ ShootSnd();\r
+ break;\r
+\r
+ case MOUSESENS:\r
+ case CUSTOMIZE:\r
+ DrawCtlScreen();\r
+ MenuFadeIn();\r
+ WaitKeyUp();\r
+ break;\r
+ }\r
+ } while(which>=0);\r
+\r
+ MenuFadeOut();\r
+\r
+#ifdef SPEAR\r
+ UnCacheLump (CONTROL_LUMP_START,CONTROL_LUMP_END);\r
+ CacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);\r
+#endif\r
+}\r
+\r
+\r
+////////////////////////////////\r
+//\r
+// DRAW MOUSE SENSITIVITY SCREEN\r
+//\r
+void DrawMouseSens(void)\r
+{\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_MOUSESENSPIC);\r
+#else\r
+ ClearMScreen();\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+ #ifdef SPANISH\r
+ DrawWindow(10,80,300,43,BKGDCOLOR);\r
+ #else\r
+ DrawWindow(10,80,300,30,BKGDCOLOR);\r
+ #endif\r
+\r
+ WindowX=0;\r
+ WindowW=320;\r
+ PrintY=82;\r
+ SETFONTCOLOR(READCOLOR,BKGDCOLOR);\r
+ US_CPrint(STR_MOUSEADJ);\r
+\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ #ifdef SPANISH\r
+ PrintX=14;\r
+ PrintY=95+13;\r
+ US_Print(STR_SLOW);\r
+ PrintX=252;\r
+ US_Print(STR_FAST);\r
+ #else\r
+ PrintX=14;\r
+ PrintY=95;\r
+ US_Print(STR_SLOW);\r
+ PrintX=269;\r
+ US_Print(STR_FAST);\r
+ #endif\r
+#endif\r
+\r
+ VWB_Bar(60,97,200,10,TEXTCOLOR);\r
+ DrawOutline(60,97,200,10,0,HIGHLIGHT);\r
+ DrawOutline(60+20*mouseadjustment,97,20,10,0,READCOLOR);\r
+ VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR);\r
+\r
+ VW_UpdateScreen();\r
+ MenuFadeIn();\r
+}\r
+\r
+\r
+///////////////////////////\r
+//\r
+// ADJUST MOUSE SENSITIVITY\r
+//\r
+void MouseSensitivity(void)\r
+{\r
+ ControlInfo ci;\r
+ int exit=0,oldMA;\r
+\r
+\r
+ oldMA=mouseadjustment;\r
+ DrawMouseSens();\r
+ do\r
+ {\r
+ ReadAnyControl(&ci);\r
+ switch(ci.dir)\r
+ {\r
+ case dir_North:\r
+ case dir_West:\r
+ if (mouseadjustment)\r
+ {\r
+ mouseadjustment--;\r
+ VWB_Bar(60,97,200,10,TEXTCOLOR);\r
+ DrawOutline(60,97,200,10,0,HIGHLIGHT);\r
+ DrawOutline(60+20*mouseadjustment,97,20,10,0,READCOLOR);\r
+ VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(MOVEGUN1SND);\r
+ while(Keyboard[sc_LeftArrow]);\r
+ WaitKeyUp();\r
+ }\r
+ break;\r
+\r
+ case dir_South:\r
+ case dir_East:\r
+ if (mouseadjustment<9)\r
+ {\r
+ mouseadjustment++;\r
+ VWB_Bar(60,97,200,10,TEXTCOLOR);\r
+ DrawOutline(60,97,200,10,0,HIGHLIGHT);\r
+ DrawOutline(60+20*mouseadjustment,97,20,10,0,READCOLOR);\r
+ VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(MOVEGUN1SND);\r
+ while(Keyboard[sc_RightArrow]);\r
+ WaitKeyUp();\r
+ }\r
+ break;\r
+ }\r
+\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ #else\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode"))\r
+ #endif\r
+ PicturePause();\r
+\r
+ if (ci.button0 || Keyboard[sc_Space] || Keyboard[sc_Enter])\r
+ exit=1;\r
+ else\r
+ if (ci.button1 || Keyboard[sc_Escape])\r
+ exit=2;\r
+\r
+ } while(!exit);\r
+\r
+ if (exit==2)\r
+ {\r
+ mouseadjustment=oldMA;\r
+ SD_PlaySound(ESCPRESSEDSND);\r
+ }\r
+ else\r
+ SD_PlaySound(SHOOTSND);\r
+\r
+ WaitKeyUp();\r
+ MenuFadeOut();\r
+}\r
+\r
+\r
+///////////////////////////\r
+//\r
+// DRAW CONTROL MENU SCREEN\r
+//\r
+void DrawCtlScreen(void)\r
+{\r
+ int i,x,y;\r
+\r
+\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_CONTROLPIC);\r
+#else\r
+ ClearMScreen();\r
+ DrawStripes(10);\r
+ VWB_DrawPic(80,0,C_CONTROLPIC);\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+ DrawWindow(CTL_X-8,CTL_Y-5,CTL_W,CTL_H,BKGDCOLOR);\r
+#endif\r
+ WindowX=0;\r
+ WindowW=320;\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+\r
+ if (JoysPresent[0])\r
+ CtlMenu[1].active=\r
+ CtlMenu[2].active=\r
+ CtlMenu[3].active=1;\r
+\r
+ CtlMenu[2].active=CtlMenu[3].active=joystickenabled;\r
+\r
+ if (MousePresent)\r
+ {\r
+ CtlMenu[4].active=\r
+ CtlMenu[0].active=1;\r
+ }\r
+\r
+ CtlMenu[4].active=mouseenabled;\r
+\r
+\r
+ DrawMenu(&CtlItems,&CtlMenu[0]);\r
+\r
+\r
+ x=CTL_X+CtlItems.indent-24;\r
+ y=CTL_Y+3;\r
+ if (mouseenabled)\r
+ VWB_DrawPic(x,y,C_SELECTEDPIC);\r
+ else\r
+ VWB_DrawPic(x,y,C_NOTSELECTEDPIC);\r
+\r
+ y=CTL_Y+16;\r
+ if (joystickenabled)\r
+ VWB_DrawPic(x,y,C_SELECTEDPIC);\r
+ else\r
+ VWB_DrawPic(x,y,C_NOTSELECTEDPIC);\r
+\r
+ y=CTL_Y+29;\r
+ if (joystickport)\r
+ VWB_DrawPic(x,y,C_SELECTEDPIC);\r
+ else\r
+ VWB_DrawPic(x,y,C_NOTSELECTEDPIC);\r
+\r
+ y=CTL_Y+42;\r
+ if (joypadenabled)\r
+ VWB_DrawPic(x,y,C_SELECTEDPIC);\r
+ else\r
+ VWB_DrawPic(x,y,C_NOTSELECTEDPIC);\r
+\r
+ //\r
+ // PICK FIRST AVAILABLE SPOT\r
+ //\r
+ if (CtlItems.curpos<0 || !CtlMenu[CtlItems.curpos].active)\r
+ for (i=0;i<6;i++)\r
+ if (CtlMenu[i].active)\r
+ {\r
+ CtlItems.curpos=i;\r
+ break;\r
+ }\r
+\r
+ DrawMenuGun(&CtlItems);\r
+ VW_UpdateScreen();\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// CUSTOMIZE CONTROLS\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+enum {FIRE,STRAFE,RUN,OPEN};\r
+char mbarray[4][3]={"b0","b1","b2","b3"},\r
+ order[4]={RUN,OPEN,FIRE,STRAFE};\r
+\r
+\r
+void CustomControls(void)\r
+{\r
+ int which;\r
+\r
+\r
+ DrawCustomScreen();\r
+ do\r
+ {\r
+ which=HandleMenu(&CusItems,&CusMenu[0],FixupCustom);\r
+ switch(which)\r
+ {\r
+ case 0:\r
+ DefineMouseBtns();\r
+ DrawCustMouse(1);\r
+ break;\r
+ case 3:\r
+ DefineJoyBtns();\r
+ DrawCustJoy(0);\r
+ break;\r
+ case 6:\r
+ DefineKeyBtns();\r
+ DrawCustKeybd(0);\r
+ break;\r
+ case 8:\r
+ DefineKeyMove();\r
+ DrawCustKeys(0);\r
+ }\r
+ } while(which>=0);\r
+\r
+\r
+\r
+ MenuFadeOut();\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DEFINE THE MOUSE BUTTONS\r
+//\r
+void DefineMouseBtns(void)\r
+{\r
+ CustomCtrls mouseallowed={0,1,1,1};\r
+ EnterCtrlData(2,&mouseallowed,DrawCustMouse,PrintCustMouse,MOUSE);\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DEFINE THE JOYSTICK BUTTONS\r
+//\r
+void DefineJoyBtns(void)\r
+{\r
+ CustomCtrls joyallowed={1,1,1,1};\r
+ EnterCtrlData(5,&joyallowed,DrawCustJoy,PrintCustJoy,JOYSTICK);\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DEFINE THE KEYBOARD BUTTONS\r
+//\r
+void DefineKeyBtns(void)\r
+{\r
+ CustomCtrls keyallowed={1,1,1,1};\r
+ EnterCtrlData(8,&keyallowed,DrawCustKeybd,PrintCustKeybd,KEYBOARDBTNS);\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DEFINE THE KEYBOARD BUTTONS\r
+//\r
+void DefineKeyMove(void)\r
+{\r
+ CustomCtrls keyallowed={1,1,1,1};\r
+ EnterCtrlData(10,&keyallowed,DrawCustKeys,PrintCustKeys,KEYBOARDMOVE);\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// ENTER CONTROL DATA FOR ANY TYPE OF CONTROL\r
+//\r
+enum {FWRD,RIGHT,BKWD,LEFT};\r
+int moveorder[4]={LEFT,RIGHT,FWRD,BKWD};\r
+\r
+void EnterCtrlData(int index,CustomCtrls *cust,void (*DrawRtn)(int),void (*PrintRtn)(int),int type)\r
+{\r
+ int j,exit,tick,redraw,which,x,picked;\r
+ ControlInfo ci;\r
+\r
+\r
+ ShootSnd();\r
+ PrintY=CST_Y+13*index;\r
+ IN_ClearKeysDown();\r
+ exit=0;\r
+ redraw=1;\r
+ //\r
+ // FIND FIRST SPOT IN ALLOWED ARRAY\r
+ //\r
+ for (j=0;j<4;j++)\r
+ if (cust->allowed[j])\r
+ {\r
+ which=j;\r
+ break;\r
+ }\r
+\r
+ do\r
+ {\r
+ if (redraw)\r
+ {\r
+ x=CST_START+CST_SPC*which;\r
+ DrawWindow(5,PrintY-1,310,13,BKGDCOLOR);\r
+\r
+ DrawRtn(1);\r
+ DrawWindow(x-2,PrintY,CST_SPC,11,TEXTCOLOR);\r
+ DrawOutline(x-2,PrintY,CST_SPC,11,0,HIGHLIGHT);\r
+ SETFONTCOLOR(0,TEXTCOLOR);\r
+ PrintRtn(which);\r
+ PrintX=x;\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ VW_UpdateScreen();\r
+ WaitKeyUp();\r
+ redraw=0;\r
+ }\r
+\r
+ ReadAnyControl(&ci);\r
+\r
+ if (type==MOUSE || type==JOYSTICK)\r
+ if (IN_KeyDown(sc_Enter)||IN_KeyDown(sc_Control)||IN_KeyDown(sc_Alt))\r
+ {\r
+ IN_ClearKeysDown();\r
+ ci.button0=ci.button1=false;\r
+ }\r
+\r
+ //\r
+ // CHANGE BUTTON VALUE?\r
+ //\r
+ if ((ci.button0|ci.button1|ci.button2|ci.button3)||\r
+ ((type==KEYBOARDBTNS||type==KEYBOARDMOVE) && LastScan==sc_Enter))\r
+ {\r
+ tick=TimeCount=picked=0;\r
+ SETFONTCOLOR(0,TEXTCOLOR);\r
+\r
+ do\r
+ {\r
+ int button,result=0;\r
+\r
+\r
+ if (type==KEYBOARDBTNS||type==KEYBOARDMOVE)\r
+ IN_ClearKeysDown();\r
+\r
+ //\r
+ // FLASH CURSOR\r
+ //\r
+ if (TimeCount>10)\r
+ {\r
+ switch(tick)\r
+ {\r
+ case 0:\r
+ VWB_Bar(x,PrintY+1,CST_SPC-2,10,TEXTCOLOR);\r
+ break;\r
+ case 1:\r
+ PrintX=x;\r
+ US_Print("?");\r
+ SD_PlaySound(HITWALLSND);\r
+ }\r
+ tick^=1;\r
+ TimeCount=0;\r
+ VW_UpdateScreen();\r
+ }\r
+\r
+ //\r
+ // WHICH TYPE OF INPUT DO WE PROCESS?\r
+ //\r
+ switch(type)\r
+ {\r
+ case MOUSE:\r
+ Mouse(3);\r
+ button=_BX;\r
+ switch(button)\r
+ {\r
+ case 1: result=1; break;\r
+ case 2: result=2; break;\r
+ case 4: result=3; break;\r
+ }\r
+\r
+ if (result)\r
+ {\r
+ int z;\r
+\r
+\r
+ for (z=0;z<4;z++)\r
+ if (order[which]==buttonmouse[z])\r
+ {\r
+ buttonmouse[z]=bt_nobutton;\r
+ break;\r
+ }\r
+\r
+ buttonmouse[result-1]=order[which];\r
+ picked=1;\r
+ SD_PlaySound(SHOOTDOORSND);\r
+ }\r
+ break;\r
+\r
+ case JOYSTICK:\r
+ if (ci.button0) result=1;\r
+ else\r
+ if (ci.button1) result=2;\r
+ else\r
+ if (ci.button2) result=3;\r
+ else\r
+ if (ci.button3) result=4;\r
+\r
+ if (result)\r
+ {\r
+ int z;\r
+\r
+\r
+ for (z=0;z<4;z++)\r
+ if (order[which]==buttonjoy[z])\r
+ {\r
+ buttonjoy[z]=bt_nobutton;\r
+ break;\r
+ }\r
+\r
+ buttonjoy[result-1]=order[which];\r
+ picked=1;\r
+ SD_PlaySound(SHOOTDOORSND);\r
+ }\r
+ break;\r
+\r
+ case KEYBOARDBTNS:\r
+ if (LastScan)\r
+ {\r
+ buttonscan[order[which]]=LastScan;\r
+ picked=1;\r
+ ShootSnd();\r
+ IN_ClearKeysDown();\r
+ }\r
+ break;\r
+\r
+ case KEYBOARDMOVE:\r
+ if (LastScan)\r
+ {\r
+ dirscan[moveorder[which]]=LastScan;\r
+ picked=1;\r
+ ShootSnd();\r
+ IN_ClearKeysDown();\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // EXIT INPUT?\r
+ //\r
+ if (IN_KeyDown(sc_Escape))\r
+ {\r
+ picked=1;\r
+ continue;\r
+ }\r
+\r
+ } while(!picked);\r
+\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ redraw=1;\r
+ WaitKeyUp();\r
+ continue;\r
+ }\r
+\r
+ if (ci.button1 || IN_KeyDown(sc_Escape))\r
+ exit=1;\r
+\r
+ //\r
+ // MOVE TO ANOTHER SPOT?\r
+ //\r
+ switch(ci.dir)\r
+ {\r
+ case dir_West:\r
+ do\r
+ {\r
+ which--;\r
+ if (which<0)\r
+ which=3;\r
+ } while(!cust->allowed[which]);\r
+ redraw=1;\r
+ SD_PlaySound(MOVEGUN1SND);\r
+ while(ReadAnyControl(&ci),ci.dir!=dir_None);\r
+ IN_ClearKeysDown();\r
+ break;\r
+\r
+ case dir_East:\r
+ do\r
+ {\r
+ which++;\r
+ if (which>3)\r
+ which=0;\r
+ } while(!cust->allowed[which]);\r
+ redraw=1;\r
+ SD_PlaySound(MOVEGUN1SND);\r
+ while(ReadAnyControl(&ci),ci.dir!=dir_None);\r
+ IN_ClearKeysDown();\r
+ break;\r
+ case dir_North:\r
+ case dir_South:\r
+ exit=1;\r
+ }\r
+ } while(!exit);\r
+\r
+ SD_PlaySound(ESCPRESSEDSND);\r
+ WaitKeyUp();\r
+ DrawWindow(5,PrintY-1,310,13,BKGDCOLOR);\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// FIXUP GUN CURSOR OVERDRAW SHIT\r
+//\r
+void FixupCustom(int w)\r
+{\r
+ static int lastwhich=-1;\r
+ int y=CST_Y+26+w*13;\r
+\r
+\r
+ VWB_Hlin(7,32,y-1,DEACTIVE);\r
+ VWB_Hlin(7,32,y+12,BORD2COLOR);\r
+#ifndef SPEAR\r
+ VWB_Hlin(7,32,y-2,BORDCOLOR);\r
+ VWB_Hlin(7,32,y+13,BORDCOLOR);\r
+#else\r
+ VWB_Hlin(7,32,y-2,BORD2COLOR);\r
+ VWB_Hlin(7,32,y+13,BORD2COLOR);\r
+#endif\r
+\r
+ switch(w)\r
+ {\r
+ case 0: DrawCustMouse(1); break;\r
+ case 3: DrawCustJoy(1); break;\r
+ case 6: DrawCustKeybd(1); break;\r
+ case 8: DrawCustKeys(1);\r
+ }\r
+\r
+\r
+ if (lastwhich>=0)\r
+ {\r
+ y=CST_Y+26+lastwhich*13;\r
+ VWB_Hlin(7,32,y-1,DEACTIVE);\r
+ VWB_Hlin(7,32,y+12,BORD2COLOR);\r
+#ifndef SPEAR\r
+ VWB_Hlin(7,32,y-2,BORDCOLOR);\r
+ VWB_Hlin(7,32,y+13,BORDCOLOR);\r
+#else\r
+ VWB_Hlin(7,32,y-2,BORD2COLOR);\r
+ VWB_Hlin(7,32,y+13,BORD2COLOR);\r
+#endif\r
+\r
+ if (lastwhich!=w)\r
+ switch(lastwhich)\r
+ {\r
+ case 0: DrawCustMouse(0); break;\r
+ case 3: DrawCustJoy(0); break;\r
+ case 6: DrawCustKeybd(0); break;\r
+ case 8: DrawCustKeys(0);\r
+ }\r
+ }\r
+\r
+ lastwhich=w;\r
+}\r
+\r
+\r
+////////////////////////\r
+//\r
+// DRAW CUSTOMIZE SCREEN\r
+//\r
+void DrawCustomScreen(void)\r
+{\r
+ int i;\r
+\r
+\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_CUSTOMPIC);\r
+ fontnumber=1;\r
+\r
+ PrintX=CST_START;\r
+ PrintY = CST_Y+26;\r
+ DrawCustMouse(0);\r
+\r
+ PrintX=CST_START;\r
+ US_Print("\n\n\n");\r
+ DrawCustJoy(0);\r
+\r
+ PrintX=CST_START;\r
+ US_Print("\n\n\n");\r
+ DrawCustKeybd(0);\r
+\r
+ PrintX=CST_START;\r
+ US_Print("\n\n\n");\r
+ DrawCustKeys(0);\r
+#else\r
+ ClearMScreen();\r
+ WindowX=0;\r
+ WindowW=320;\r
+ VWB_DrawPic(112,184,C_MOUSELBACKPIC);\r
+ DrawStripes(10);\r
+ VWB_DrawPic(80,0,C_CUSTOMIZEPIC);\r
+\r
+ //\r
+ // MOUSE\r
+ //\r
+ SETFONTCOLOR(READCOLOR,BKGDCOLOR);\r
+ WindowX=0;\r
+ WindowW=320;\r
+\r
+#ifndef SPEAR\r
+ PrintY=CST_Y;\r
+ US_CPrint("Mouse\n");\r
+#else\r
+ PrintY = CST_Y+13;\r
+ VWB_DrawPic (128,48,C_MOUSEPIC);\r
+#endif\r
+\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ #ifdef SPANISH\r
+ PrintX=CST_START-16;\r
+ US_Print(STR_CRUN);\r
+ PrintX=CST_START-16+CST_SPC*1;\r
+ US_Print(STR_COPEN);\r
+ PrintX=CST_START-16+CST_SPC*2;\r
+ US_Print(STR_CFIRE);\r
+ PrintX=CST_START-16+CST_SPC*3;\r
+ US_Print(STR_CSTRAFE"\n");\r
+ #else\r
+ PrintX=CST_START;\r
+ US_Print(STR_CRUN);\r
+ PrintX=CST_START+CST_SPC*1;\r
+ US_Print(STR_COPEN);\r
+ PrintX=CST_START+CST_SPC*2;\r
+ US_Print(STR_CFIRE);\r
+ PrintX=CST_START+CST_SPC*3;\r
+ US_Print(STR_CSTRAFE"\n");\r
+ #endif\r
+\r
+ DrawWindow(5,PrintY-1,310,13,BKGDCOLOR);\r
+ DrawCustMouse(0);\r
+ US_Print("\n");\r
+\r
+\r
+ //\r
+ // JOYSTICK/PAD\r
+ //\r
+#ifndef SPEAR\r
+ SETFONTCOLOR(READCOLOR,BKGDCOLOR);\r
+ US_CPrint("Joystick/Gravis GamePad\n");\r
+#else\r
+ PrintY += 13;\r
+ VWB_DrawPic (40,88,C_JOYSTICKPIC);\r
+#endif\r
+\r
+#ifdef SPEAR\r
+ VWB_DrawPic (112,120,C_KEYBOARDPIC);\r
+#endif\r
+\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ #ifdef SPANISH\r
+ PrintX=CST_START-16;\r
+ US_Print(STR_CRUN);\r
+ PrintX=CST_START-16+CST_SPC*1;\r
+ US_Print(STR_COPEN);\r
+ PrintX=CST_START-16+CST_SPC*2;\r
+ US_Print(STR_CFIRE);\r
+ PrintX=CST_START-16+CST_SPC*3;\r
+ US_Print(STR_CSTRAFE"\n");\r
+ #else\r
+ PrintX=CST_START;\r
+ US_Print(STR_CRUN);\r
+ PrintX=CST_START+CST_SPC*1;\r
+ US_Print(STR_COPEN);\r
+ PrintX=CST_START+CST_SPC*2;\r
+ US_Print(STR_CFIRE);\r
+ PrintX=CST_START+CST_SPC*3;\r
+ US_Print(STR_CSTRAFE"\n");\r
+ #endif\r
+ DrawWindow(5,PrintY-1,310,13,BKGDCOLOR);\r
+ DrawCustJoy(0);\r
+ US_Print("\n");\r
+\r
+\r
+ //\r
+ // KEYBOARD\r
+ //\r
+#ifndef SPEAR\r
+ SETFONTCOLOR(READCOLOR,BKGDCOLOR);\r
+ US_CPrint("Keyboard\n");\r
+#else\r
+ PrintY += 13;\r
+#endif\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ #ifdef SPANISH\r
+ PrintX=CST_START-16;\r
+ US_Print(STR_CRUN);\r
+ PrintX=CST_START-16+CST_SPC*1;\r
+ US_Print(STR_COPEN);\r
+ PrintX=CST_START-16+CST_SPC*2;\r
+ US_Print(STR_CFIRE);\r
+ PrintX=CST_START-16+CST_SPC*3;\r
+ US_Print(STR_CSTRAFE"\n");\r
+ #else\r
+ PrintX=CST_START;\r
+ US_Print(STR_CRUN);\r
+ PrintX=CST_START+CST_SPC*1;\r
+ US_Print(STR_COPEN);\r
+ PrintX=CST_START+CST_SPC*2;\r
+ US_Print(STR_CFIRE);\r
+ PrintX=CST_START+CST_SPC*3;\r
+ US_Print(STR_CSTRAFE"\n");\r
+ #endif\r
+ DrawWindow(5,PrintY-1,310,13,BKGDCOLOR);\r
+ DrawCustKeybd(0);\r
+ US_Print("\n");\r
+\r
+\r
+ //\r
+ // KEYBOARD MOVE KEYS\r
+ //\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ #ifdef SPANISH\r
+ PrintX=4;\r
+ US_Print(STR_LEFT);\r
+ US_Print("/");\r
+ US_Print(STR_RIGHT);\r
+ US_Print("/");\r
+ US_Print(STR_FRWD);\r
+ US_Print("/");\r
+ US_Print(STR_BKWD"\n");\r
+ #else\r
+ PrintX=CST_START;\r
+ US_Print(STR_LEFT);\r
+ PrintX=CST_START+CST_SPC*1;\r
+ US_Print(STR_RIGHT);\r
+ PrintX=CST_START+CST_SPC*2;\r
+ US_Print(STR_FRWD);\r
+ PrintX=CST_START+CST_SPC*3;\r
+ US_Print(STR_BKWD"\n");\r
+ #endif\r
+ DrawWindow(5,PrintY-1,310,13,BKGDCOLOR);\r
+ DrawCustKeys(0);\r
+#endif\r
+ //\r
+ // PICK STARTING POINT IN MENU\r
+ //\r
+ if (CusItems.curpos<0)\r
+ for (i=0;i<CusItems.amount;i++)\r
+ if (CusMenu[i].active)\r
+ {\r
+ CusItems.curpos=i;\r
+ break;\r
+ }\r
+\r
+\r
+ VW_UpdateScreen();\r
+ MenuFadeIn();\r
+}\r
+\r
+\r
+void PrintCustMouse(int i)\r
+{\r
+ int j;\r
+\r
+ for (j=0;j<4;j++)\r
+ if (order[i]==buttonmouse[j])\r
+ {\r
+ PrintX=CST_START+CST_SPC*i;\r
+ US_Print(mbarray[j]);\r
+ break;\r
+ }\r
+}\r
+\r
+void DrawCustMouse(int hilight)\r
+{\r
+ int i,color;\r
+\r
+\r
+ color=TEXTCOLOR;\r
+ if (hilight)\r
+ color=HIGHLIGHT;\r
+ SETFONTCOLOR(color,BKGDCOLOR);\r
+\r
+ if (!mouseenabled)\r
+ {\r
+ SETFONTCOLOR(DEACTIVE,BKGDCOLOR);\r
+ CusMenu[0].active=0;\r
+ }\r
+ else\r
+ CusMenu[0].active=1;\r
+\r
+ PrintY=CST_Y+13*2;\r
+ for (i=0;i<4;i++)\r
+ PrintCustMouse(i);\r
+}\r
+\r
+void PrintCustJoy(int i)\r
+{\r
+ int j;\r
+\r
+ for (j=0;j<4;j++)\r
+ if (order[i]==buttonjoy[j])\r
+ {\r
+ PrintX=CST_START+CST_SPC*i;\r
+ US_Print(mbarray[j]);\r
+ break;\r
+ }\r
+}\r
+\r
+void DrawCustJoy(int hilight)\r
+{\r
+ int i,color;\r
+\r
+\r
+ color=TEXTCOLOR;\r
+ if (hilight)\r
+ color=HIGHLIGHT;\r
+ SETFONTCOLOR(color,BKGDCOLOR);\r
+\r
+ if (!joystickenabled)\r
+ {\r
+ SETFONTCOLOR(DEACTIVE,BKGDCOLOR);\r
+ CusMenu[3].active=0;\r
+ }\r
+ else\r
+ CusMenu[3].active=1;\r
+\r
+ PrintY=CST_Y+13*5;\r
+ for (i=0;i<4;i++)\r
+ PrintCustJoy(i);\r
+}\r
+\r
+\r
+void PrintCustKeybd(int i)\r
+{\r
+ PrintX=CST_START+CST_SPC*i;\r
+ US_Print(IN_GetScanName(buttonscan[order[i]]));\r
+}\r
+\r
+void DrawCustKeybd(int hilight)\r
+{\r
+ int i,color;\r
+\r
+\r
+ color=TEXTCOLOR;\r
+ if (hilight)\r
+ color=HIGHLIGHT;\r
+ SETFONTCOLOR(color,BKGDCOLOR);\r
+\r
+ PrintY=CST_Y+13*8;\r
+ for (i=0;i<4;i++)\r
+ PrintCustKeybd(i);\r
+}\r
+\r
+void PrintCustKeys(int i)\r
+{\r
+ PrintX=CST_START+CST_SPC*i;\r
+ US_Print(IN_GetScanName(dirscan[moveorder[i]]));\r
+}\r
+\r
+void DrawCustKeys(int hilight)\r
+{\r
+ int i,color;\r
+\r
+\r
+ color=TEXTCOLOR;\r
+ if (hilight)\r
+ color=HIGHLIGHT;\r
+ SETFONTCOLOR(color,BKGDCOLOR);\r
+\r
+ PrintY=CST_Y+13*10;\r
+ for (i=0;i<4;i++)\r
+ PrintCustKeys(i);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// CHANGE SCREEN VIEWING SIZE\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_ChangeView(void)\r
+{\r
+ int exit=0,oldview,newview;\r
+ ControlInfo ci;\r
+\r
+\r
+ WindowX=WindowY=0;\r
+ WindowW=320;\r
+ WindowH=200;\r
+ newview=oldview=viewwidth/16;\r
+ DrawChangeView(oldview);\r
+\r
+ do\r
+ {\r
+ CheckPause();\r
+ ReadAnyControl(&ci);\r
+ switch(ci.dir)\r
+ {\r
+ case dir_South:\r
+ case dir_West:\r
+ newview--;\r
+ if (newview<4)\r
+ newview=4;\r
+ ShowViewSize(newview);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(HITWALLSND);\r
+ TicDelay(10);\r
+ break;\r
+\r
+ case dir_North:\r
+ case dir_East:\r
+ newview++;\r
+ if (newview>19)\r
+ newview=19;\r
+ ShowViewSize(newview);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(HITWALLSND);\r
+ TicDelay(10);\r
+ break;\r
+ }\r
+\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ #else\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode"))\r
+ #endif\r
+ PicturePause();\r
+\r
+ if (ci.button0 || Keyboard[sc_Enter])\r
+ exit=1;\r
+ else\r
+ if (ci.button1 || Keyboard[sc_Escape])\r
+ {\r
+ viewwidth=oldview*16;\r
+ SD_PlaySound(ESCPRESSEDSND);\r
+ MenuFadeOut();\r
+ return;\r
+ }\r
+\r
+ } while(!exit);\r
+\r
+\r
+ if (oldview!=newview)\r
+ {\r
+ SD_PlaySound (SHOOTSND);\r
+ Message(STR_THINK"...");\r
+ NewViewSize(newview);\r
+ }\r
+\r
+ ShootSnd();\r
+ MenuFadeOut();\r
+}\r
+\r
+\r
+/////////////////////////////\r
+//\r
+// DRAW THE CHANGEVIEW SCREEN\r
+//\r
+void DrawChangeView(int view)\r
+{\r
+#ifdef JAPAN\r
+ CA_CacheScreen(S_CHANGEPIC);\r
+\r
+ ShowViewSize(view);\r
+#else\r
+ VWB_Bar(0,160,320,40,VIEWCOLOR);\r
+ ShowViewSize(view);\r
+\r
+ PrintY=161;\r
+ WindowX=0;\r
+ WindowY=320;\r
+ SETFONTCOLOR(HIGHLIGHT,BKGDCOLOR);\r
+\r
+ US_CPrint(STR_SIZE1"\n");\r
+ US_CPrint(STR_SIZE2"\n");\r
+ US_CPrint(STR_SIZE3);\r
+#endif\r
+ VW_UpdateScreen();\r
+\r
+ MenuFadeIn();\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// QUIT THIS INFERNAL GAME!\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CP_Quit(void)\r
+{\r
+ int i;\r
+\r
+\r
+ #ifdef JAPAN\r
+ if (GetYorN(7,11,C_QUITMSGPIC))\r
+ #else\r
+\r
+ #ifdef SPANISH\r
+ if (Confirm(ENDGAMESTR))\r
+ #else\r
+ if (Confirm(endStrings[US_RndT()&0x7+(US_RndT()&1)]))\r
+ #endif\r
+\r
+ #endif\r
+ {\r
+ VW_UpdateScreen();\r
+ SD_MusicOff();\r
+ SD_StopSound();\r
+ MenuFadeOut();\r
+ //\r
+ // SHUT-UP THE ADLIB\r
+ //\r
+ for (i=1;i<=0xf5;i++)\r
+ alOut(i,0);\r
+ Quit(NULL);\r
+ }\r
+\r
+ DrawMainMenu();\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// HANDLE INTRO SCREEN (SYSTEM CONFIG)\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void IntroScreen(void)\r
+{\r
+#ifdef SPEAR\r
+\r
+#define MAINCOLOR 0x4f\r
+#define EMSCOLOR 0x4f\r
+#define XMSCOLOR 0x4f\r
+\r
+#else\r
+\r
+#define MAINCOLOR 0x6c\r
+#define EMSCOLOR 0x6c\r
+#define XMSCOLOR 0x6c\r
+\r
+#endif\r
+#define FILLCOLOR 14\r
+\r
+ long memory,emshere,xmshere;\r
+ int i,num,ems[10]={100,200,300,400,500,600,700,800,900,1000},\r
+ xms[10]={100,200,300,400,500,600,700,800,900,1000},\r
+ main[10]={32,64,96,128,160,192,224,256,288,320};\r
+\r
+\r
+ //\r
+ // DRAW MAIN MEMORY\r
+ //\r
+ memory=(1023l+mminfo.nearheap+mminfo.farheap)/1024l;\r
+ for (i=0;i<10;i++)\r
+ if (memory>=main[i])\r
+ VWB_Bar(49,163-8*i,6,5,MAINCOLOR-i);\r
+\r
+\r
+ //\r
+ // DRAW EMS MEMORY\r
+ //\r
+ if (EMSPresent)\r
+ {\r
+ emshere=4l*EMSPagesAvail;\r
+ for (i=0;i<10;i++)\r
+ if (emshere>=ems[i])\r
+ VWB_Bar(89,163-8*i,6,5,EMSCOLOR-i);\r
+ }\r
+\r
+ //\r
+ // DRAW XMS MEMORY\r
+ //\r
+ if (XMSPresent)\r
+ {\r
+ xmshere=4l*XMSPagesAvail;\r
+ for (i=0;i<10;i++)\r
+ if (xmshere>=xms[i])\r
+ VWB_Bar(129,163-8*i,6,5,XMSCOLOR-i);\r
+ }\r
+\r
+ //\r
+ // FILL BOXES\r
+ //\r
+ if (MousePresent)\r
+ VWB_Bar(164,82,12,2,FILLCOLOR);\r
+\r
+ if (JoysPresent[0] || JoysPresent[1])\r
+ VWB_Bar(164,105,12,2,FILLCOLOR);\r
+\r
+ if (AdLibPresent && !SoundBlasterPresent)\r
+ VWB_Bar(164,128,12,2,FILLCOLOR);\r
+\r
+ if (SoundBlasterPresent)\r
+ VWB_Bar(164,151,12,2,FILLCOLOR);\r
+\r
+ if (SoundSourcePresent)\r
+ VWB_Bar(164,174,12,2,FILLCOLOR);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// SUPPORT ROUTINES\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Clear Menu screens to dark red\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void ClearMScreen(void)\r
+{\r
+#ifndef SPEAR\r
+ VWB_Bar(0,0,320,200,BORDCOLOR);\r
+#else\r
+ VWB_DrawPic(0,0,C_BACKDROPPIC);\r
+#endif\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Un/Cache a LUMP of graphics\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CacheLump(int lumpstart,int lumpend)\r
+{\r
+ int i;\r
+\r
+ for (i=lumpstart;i<=lumpend;i++)\r
+ CA_CacheGrChunk(i);\r
+}\r
+\r
+\r
+void UnCacheLump(int lumpstart,int lumpend)\r
+{\r
+ int i;\r
+\r
+ for (i=lumpstart;i<=lumpend;i++)\r
+ if (grsegs[i])\r
+ UNCACHEGRCHUNK(i);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Draw a window for a menu\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void DrawWindow(int x,int y,int w,int h,int wcolor)\r
+{\r
+ VWB_Bar(x,y,w,h,wcolor);\r
+ DrawOutline(x,y,w,h,BORD2COLOR,DEACTIVE);\r
+}\r
+\r
+\r
+void DrawOutline(int x,int y,int w,int h,int color1,int color2)\r
+{\r
+ VWB_Hlin(x,x+w,y,color2);\r
+ VWB_Vlin(y,y+h,x,color2);\r
+ VWB_Hlin(x,x+w,y+h,color1);\r
+ VWB_Vlin(y,y+h,x+w,color1);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Setup Control Panel stuff - graphics, etc.\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void SetupControlPanel(void)\r
+{\r
+ struct ffblk f;\r
+ char name[13];\r
+ int which,i;\r
+\r
+\r
+ //\r
+ // CACHE GRAPHICS & SOUNDS\r
+ //\r
+ CA_CacheGrChunk(STARTFONT+1);\r
+#ifndef SPEAR\r
+ CacheLump(CONTROLS_LUMP_START,CONTROLS_LUMP_END);\r
+#else\r
+ CacheLump(BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+#endif\r
+\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ fontnumber=1;\r
+ WindowH=200;\r
+\r
+ if (!ingame)\r
+ CA_LoadAllSounds();\r
+ else\r
+ MainMenu[savegame].active=1;\r
+\r
+ //\r
+ // SEE WHICH SAVE GAME FILES ARE AVAILABLE & READ STRING IN\r
+ //\r
+ strcpy(name,SaveName);\r
+ if (!findfirst(name,&f,0))\r
+ do\r
+ {\r
+ which=f.ff_name[7]-'0';\r
+ if (which<10)\r
+ {\r
+ int handle;\r
+ char temp[32];\r
+\r
+ SaveGamesAvail[which]=1;\r
+ handle=open(f.ff_name,O_BINARY);\r
+ read(handle,temp,32);\r
+ close(handle);\r
+ strcpy(&SaveGameNames[which][0],temp);\r
+ }\r
+ } while(!findnext(&f));\r
+\r
+ //\r
+ // CENTER MOUSE\r
+ //\r
+ _CX=_DX=CENTER;\r
+ Mouse(4);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Clean up all the Control Panel stuff\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void CleanupControlPanel(void)\r
+{\r
+#ifndef SPEAR\r
+ UnCacheLump(CONTROLS_LUMP_START,CONTROLS_LUMP_END);\r
+#else\r
+ UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);\r
+#endif\r
+\r
+ fontnumber = 0;\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Handle moving gun around a menu\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int HandleMenu(CP_iteminfo *item_i,CP_itemtype far *items,void (*routine)(int w))\r
+{\r
+ char key;\r
+ static int redrawitem=1,lastitem=-1;\r
+ int i,x,y,basey,exit,which,shape,timer;\r
+ ControlInfo ci;\r
+\r
+\r
+ which=item_i->curpos;\r
+ x=item_i->x&-8;\r
+ basey=item_i->y-2;\r
+ y=basey+which*13;\r
+\r
+ VWB_DrawPic(x,y,C_CURSOR1PIC);\r
+ SetTextColor(items+which,1);\r
+ if (redrawitem)\r
+ {\r
+ PrintX=item_i->x+item_i->indent;\r
+ PrintY=item_i->y+which*13;\r
+ US_Print((items+which)->string);\r
+ }\r
+ //\r
+ // CALL CUSTOM ROUTINE IF IT IS NEEDED\r
+ //\r
+ if (routine)\r
+ routine(which);\r
+ VW_UpdateScreen();\r
+\r
+ shape=C_CURSOR1PIC;\r
+ timer=8;\r
+ exit=0;\r
+ TimeCount=0;\r
+ IN_ClearKeysDown();\r
+\r
+\r
+ do\r
+ {\r
+ //\r
+ // CHANGE GUN SHAPE\r
+ //\r
+ if (TimeCount>timer)\r
+ {\r
+ TimeCount=0;\r
+ if (shape==C_CURSOR1PIC)\r
+ {\r
+ shape=C_CURSOR2PIC;\r
+ timer=8;\r
+ }\r
+ else\r
+ {\r
+ shape=C_CURSOR1PIC;\r
+ timer=70;\r
+ }\r
+ VWB_DrawPic(x,y,shape);\r
+ if (routine)\r
+ routine(which);\r
+ VW_UpdateScreen();\r
+ }\r
+\r
+ CheckPause();\r
+\r
+ //\r
+ // SEE IF ANY KEYS ARE PRESSED FOR INITIAL CHAR FINDING\r
+ //\r
+ key=LastASCII;\r
+ if (key)\r
+ {\r
+ int ok=0;\r
+\r
+ //\r
+ // CHECK FOR SCREEN CAPTURE\r
+ //\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ #else\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode"))\r
+ #endif\r
+ PicturePause();\r
+\r
+\r
+ if (key>='a')\r
+ key-='a'-'A';\r
+\r
+ for (i=which+1;i<item_i->amount;i++)\r
+ if ((items+i)->active && (items+i)->string[0]==key)\r
+ {\r
+ EraseGun(item_i,items,x,y,which);\r
+ which=i;\r
+ DrawGun(item_i,items,x,&y,which,basey,routine);\r
+ ok=1;\r
+ IN_ClearKeysDown();\r
+ break;\r
+ }\r
+\r
+ //\r
+ // DIDN'T FIND A MATCH FIRST TIME THRU. CHECK AGAIN.\r
+ //\r
+ if (!ok)\r
+ {\r
+ for (i=0;i<which;i++)\r
+ if ((items+i)->active && (items+i)->string[0]==key)\r
+ {\r
+ EraseGun(item_i,items,x,y,which);\r
+ which=i;\r
+ DrawGun(item_i,items,x,&y,which,basey,routine);\r
+ IN_ClearKeysDown();\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // GET INPUT\r
+ //\r
+ ReadAnyControl(&ci);\r
+ switch(ci.dir)\r
+ {\r
+ ////////////////////////////////////////////////\r
+ //\r
+ // MOVE UP\r
+ //\r
+ case dir_North:\r
+\r
+ EraseGun(item_i,items,x,y,which);\r
+\r
+ //\r
+ // ANIMATE HALF-STEP\r
+ //\r
+ if (which && (items+which-1)->active)\r
+ {\r
+ y-=6;\r
+ DrawHalfStep(x,y);\r
+ }\r
+\r
+ //\r
+ // MOVE TO NEXT AVAILABLE SPOT\r
+ //\r
+ do\r
+ {\r
+ if (!which)\r
+ which=item_i->amount-1;\r
+ else\r
+ which--;\r
+ } while(!(items+which)->active);\r
+\r
+ DrawGun(item_i,items,x,&y,which,basey,routine);\r
+ //\r
+ // WAIT FOR BUTTON-UP OR DELAY NEXT MOVE\r
+ //\r
+ TicDelay(20);\r
+ break;\r
+\r
+ ////////////////////////////////////////////////\r
+ //\r
+ // MOVE DOWN\r
+ //\r
+ case dir_South:\r
+\r
+ EraseGun(item_i,items,x,y,which);\r
+ //\r
+ // ANIMATE HALF-STEP\r
+ //\r
+ if (which!=item_i->amount-1 && (items+which+1)->active)\r
+ {\r
+ y+=6;\r
+ DrawHalfStep(x,y);\r
+ }\r
+\r
+ do\r
+ {\r
+ if (which==item_i->amount-1)\r
+ which=0;\r
+ else\r
+ which++;\r
+ } while(!(items+which)->active);\r
+\r
+ DrawGun(item_i,items,x,&y,which,basey,routine);\r
+\r
+ //\r
+ // WAIT FOR BUTTON-UP OR DELAY NEXT MOVE\r
+ //\r
+ TicDelay(20);\r
+ break;\r
+ }\r
+\r
+ if (ci.button0 ||\r
+ Keyboard[sc_Space] ||\r
+ Keyboard[sc_Enter])\r
+ exit=1;\r
+\r
+ if (ci.button1 ||\r
+ Keyboard[sc_Escape])\r
+ exit=2;\r
+\r
+ } while(!exit);\r
+\r
+\r
+ IN_ClearKeysDown();\r
+\r
+ //\r
+ // ERASE EVERYTHING\r
+ //\r
+ if (lastitem!=which)\r
+ {\r
+ VWB_Bar(x-1,y,25,16,BKGDCOLOR);\r
+ PrintX=item_i->x+item_i->indent;\r
+ PrintY=item_i->y+which*13;\r
+ US_Print((items+which)->string);\r
+ redrawitem=1;\r
+ }\r
+ else\r
+ redrawitem=0;\r
+\r
+ if (routine)\r
+ routine(which);\r
+ VW_UpdateScreen();\r
+\r
+ item_i->curpos=which;\r
+\r
+ lastitem=which;\r
+ switch(exit)\r
+ {\r
+ case 1:\r
+ //\r
+ // CALL THE ROUTINE\r
+ //\r
+ if ((items+which)->routine!=NULL)\r
+ {\r
+ ShootSnd();\r
+ MenuFadeOut();\r
+ (items+which)->routine(0);\r
+ }\r
+ return which;\r
+\r
+ case 2:\r
+ SD_PlaySound(ESCPRESSEDSND);\r
+ return -1;\r
+ }\r
+\r
+ return 0; // JUST TO SHUT UP THE ERROR MESSAGES!\r
+}\r
+\r
+\r
+//\r
+// ERASE GUN & DE-HIGHLIGHT STRING\r
+//\r
+void EraseGun(CP_iteminfo *item_i,CP_itemtype far *items,int x,int y,int which)\r
+{\r
+ VWB_Bar(x-1,y,25,16,BKGDCOLOR);\r
+ SetTextColor(items+which,0);\r
+\r
+ PrintX=item_i->x+item_i->indent;\r
+ PrintY=item_i->y+which*13;\r
+ US_Print((items+which)->string);\r
+ VW_UpdateScreen();\r
+}\r
+\r
+\r
+//\r
+// DRAW HALF STEP OF GUN TO NEXT POSITION\r
+//\r
+void DrawHalfStep(int x,int y)\r
+{\r
+ VWB_DrawPic(x,y,C_CURSOR1PIC);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(MOVEGUN1SND);\r
+ TimeCount=0;\r
+ while(TimeCount<8);\r
+}\r
+\r
+\r
+//\r
+// DRAW GUN AT NEW POSITION\r
+//\r
+void DrawGun(CP_iteminfo *item_i,CP_itemtype far *items,int x,int *y,int which,int basey,void (*routine)(int w))\r
+{\r
+ VWB_Bar(x-1,*y,25,16,BKGDCOLOR);\r
+ *y=basey+which*13;\r
+ VWB_DrawPic(x,*y,C_CURSOR1PIC);\r
+ SetTextColor(items+which,1);\r
+\r
+ PrintX=item_i->x+item_i->indent;\r
+ PrintY=item_i->y+which*13;\r
+ US_Print((items+which)->string);\r
+\r
+ //\r
+ // CALL CUSTOM ROUTINE IF IT IS NEEDED\r
+ //\r
+ if (routine)\r
+ routine(which);\r
+ VW_UpdateScreen();\r
+ SD_PlaySound(MOVEGUN2SND);\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// DELAY FOR AN AMOUNT OF TICS OR UNTIL CONTROLS ARE INACTIVE\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void TicDelay(int count)\r
+{\r
+ ControlInfo ci;\r
+\r
+\r
+ TimeCount=0;\r
+ do\r
+ {\r
+ ReadAnyControl(&ci);\r
+ } while(TimeCount<count && ci.dir!=dir_None);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// Draw a menu\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void DrawMenu(CP_iteminfo *item_i,CP_itemtype far *items)\r
+{\r
+ int i,which=item_i->curpos;\r
+\r
+\r
+ WindowX=PrintX=item_i->x+item_i->indent;\r
+ WindowY=PrintY=item_i->y;\r
+ WindowW=320;\r
+ WindowH=200;\r
+\r
+ for (i=0;i<item_i->amount;i++)\r
+ {\r
+ SetTextColor(items+i,which==i);\r
+\r
+ PrintY=item_i->y+i*13;\r
+ if ((items+i)->active)\r
+ US_Print((items+i)->string);\r
+ else\r
+ {\r
+ SETFONTCOLOR(DEACTIVE,BKGDCOLOR);\r
+ US_Print((items+i)->string);\r
+ SETFONTCOLOR(TEXTCOLOR,BKGDCOLOR);\r
+ }\r
+\r
+ US_Print("\n");\r
+ }\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// SET TEXT COLOR (HIGHLIGHT OR NO)\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void SetTextColor(CP_itemtype far *items,int hlight)\r
+{\r
+ if (hlight)\r
+ {SETFONTCOLOR(color_hlite[items->active],BKGDCOLOR);}\r
+ else\r
+ {SETFONTCOLOR(color_norml[items->active],BKGDCOLOR);}\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// WAIT FOR CTRLKEY-UP OR BUTTON-UP\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void WaitKeyUp(void)\r
+{\r
+ ControlInfo ci;\r
+ while(ReadAnyControl(&ci), ci.button0|\r
+ ci.button1|\r
+ ci.button2|\r
+ ci.button3|\r
+ Keyboard[sc_Space]|\r
+ Keyboard[sc_Enter]|\r
+ Keyboard[sc_Escape]);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// READ KEYBOARD, JOYSTICK AND MOUSE FOR INPUT\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void ReadAnyControl(ControlInfo *ci)\r
+{\r
+ int mouseactive=0;\r
+\r
+\r
+ IN_ReadControl(0,ci);\r
+\r
+ if (mouseenabled)\r
+ {\r
+ int mousey,mousex;\r
+\r
+\r
+ // READ MOUSE MOTION COUNTERS\r
+ // RETURN DIRECTION\r
+ // HOME MOUSE\r
+ // CHECK MOUSE BUTTONS\r
+\r
+ Mouse(3);\r
+ mousex=_CX;\r
+ mousey=_DX;\r
+\r
+ if (mousey<CENTER-SENSITIVE)\r
+ {\r
+ ci->dir=dir_North;\r
+ _CX=_DX=CENTER;\r
+ Mouse(4);\r
+ mouseactive=1;\r
+ }\r
+ else\r
+ if (mousey>CENTER+SENSITIVE)\r
+ {\r
+ ci->dir=dir_South;\r
+ _CX=_DX=CENTER;\r
+ Mouse(4);\r
+ mouseactive=1;\r
+ }\r
+\r
+ if (mousex<CENTER-SENSITIVE)\r
+ {\r
+ ci->dir=dir_West;\r
+ _CX=_DX=CENTER;\r
+ Mouse(4);\r
+ mouseactive=1;\r
+ }\r
+ else\r
+ if (mousex>CENTER+SENSITIVE)\r
+ {\r
+ ci->dir=dir_East;\r
+ _CX=_DX=CENTER;\r
+ Mouse(4);\r
+ mouseactive=1;\r
+ }\r
+\r
+ if (IN_MouseButtons())\r
+ {\r
+ ci->button0=IN_MouseButtons()&1;\r
+ ci->button1=IN_MouseButtons()&2;\r
+ ci->button2=IN_MouseButtons()&4;\r
+ ci->button3=false;\r
+ mouseactive=1;\r
+ }\r
+ }\r
+\r
+ if (joystickenabled && !mouseactive)\r
+ {\r
+ int jx,jy,jb;\r
+\r
+\r
+ INL_GetJoyDelta(joystickport,&jx,&jy);\r
+ if (jy<-SENSITIVE)\r
+ ci->dir=dir_North;\r
+ else\r
+ if (jy>SENSITIVE)\r
+ ci->dir=dir_South;\r
+\r
+ if (jx<-SENSITIVE)\r
+ ci->dir=dir_West;\r
+ else\r
+ if (jx>SENSITIVE)\r
+ ci->dir=dir_East;\r
+\r
+ jb=IN_JoyButtons();\r
+ if (jb)\r
+ {\r
+ ci->button0=jb&1;\r
+ ci->button1=jb&2;\r
+ if (joypadenabled)\r
+ {\r
+ ci->button2=jb&4;\r
+ ci->button3=jb&8;\r
+ }\r
+ else\r
+ ci->button2=ci->button3=false;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// DRAW DIALOG AND CONFIRM YES OR NO TO QUESTION\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int Confirm(char far *string)\r
+{\r
+ int xit=0,i,x,y,tick=0,time,whichsnd[2]={ESCPRESSEDSND,SHOOTSND};\r
+\r
+\r
+ Message(string);\r
+ IN_ClearKeysDown();\r
+\r
+ //\r
+ // BLINK CURSOR\r
+ //\r
+ x=PrintX;\r
+ y=PrintY;\r
+ TimeCount=0;\r
+\r
+ do\r
+ {\r
+ if (TimeCount>=10)\r
+ {\r
+ switch(tick)\r
+ {\r
+ case 0:\r
+ VWB_Bar(x,y,8,13,TEXTCOLOR);\r
+ break;\r
+ case 1:\r
+ PrintX=x;\r
+ PrintY=y;\r
+ US_Print("_");\r
+ }\r
+ VW_UpdateScreen();\r
+ tick^=1;\r
+ TimeCount=0;\r
+ }\r
+\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+\r
+ #ifdef SPANISH\r
+ } while(!Keyboard[sc_S] && !Keyboard[sc_N] && !Keyboard[sc_Escape]);\r
+ #else\r
+ } while(!Keyboard[sc_Y] && !Keyboard[sc_N] && !Keyboard[sc_Escape]);\r
+ #endif\r
+\r
+ #ifdef SPANISH\r
+ if (Keyboard[sc_S])\r
+ {\r
+ xit=1;\r
+ ShootSnd();\r
+ }\r
+\r
+ while(Keyboard[sc_S] || Keyboard[sc_N] || Keyboard[sc_Escape]);\r
+\r
+ #else\r
+\r
+ if (Keyboard[sc_Y])\r
+ {\r
+ xit=1;\r
+ ShootSnd();\r
+ }\r
+\r
+ while(Keyboard[sc_Y] || Keyboard[sc_N] || Keyboard[sc_Escape]);\r
+ #endif\r
+\r
+ IN_ClearKeysDown();\r
+ SD_PlaySound(whichsnd[xit]);\r
+ return xit;\r
+}\r
+\r
+#ifdef JAPAN\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// DRAW MESSAGE & GET Y OR N\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+int GetYorN(int x,int y,int pic)\r
+{\r
+ int xit=0,whichsnd[2]={ESCPRESSEDSND,SHOOTSND};\r
+\r
+\r
+ CA_CacheGrChunk(pic);\r
+ VWB_DrawPic(x * 8,y * 8,pic);\r
+ UNCACHEGRCHUNK(pic);\r
+ VW_UpdateScreen();\r
+ IN_ClearKeysDown();\r
+\r
+ do\r
+ {\r
+ #ifndef SPEAR\r
+ if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))\r
+ PicturePause();\r
+ #endif\r
+\r
+ #ifdef SPANISH\r
+ } while(!Keyboard[sc_S] && !Keyboard[sc_N] && !Keyboard[sc_Escape]);\r
+ #else\r
+ } while(!Keyboard[sc_Y] && !Keyboard[sc_N] && !Keyboard[sc_Escape]);\r
+ #endif\r
+\r
+ #ifdef SPANISH\r
+ if (Keyboard[sc_S])\r
+ {\r
+ xit=1;\r
+ ShootSnd();\r
+ }\r
+\r
+ while(Keyboard[sc_S] || Keyboard[sc_N] || Keyboard[sc_Escape]);\r
+\r
+ #else\r
+\r
+ if (Keyboard[sc_Y])\r
+ {\r
+ xit=1;\r
+ ShootSnd();\r
+ }\r
+\r
+ while(Keyboard[sc_Y] || Keyboard[sc_N] || Keyboard[sc_Escape]);\r
+ #endif\r
+\r
+ IN_ClearKeysDown();\r
+ SD_PlaySound(whichsnd[xit]);\r
+ return xit;\r
+}\r
+#endif\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// PRINT A MESSAGE IN A WINDOW\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+void Message(char far *string)\r
+{\r
+ int h=0,w=0,mw=0,i,x,y,time;\r
+ fontstruct _seg *font;\r
+\r
+\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ fontnumber=1;\r
+ font=grsegs[STARTFONT+fontnumber];\r
+ h=font->height;\r
+ for (i=0;i<_fstrlen(string);i++)\r
+ if (string[i]=='\n')\r
+ {\r
+ if (w>mw)\r
+ mw=w;\r
+ w=0;\r
+ h+=font->height;\r
+ }\r
+ else\r
+ w+=font->width[string[i]];\r
+\r
+ if (w+10>mw)\r
+ mw=w+10;\r
+\r
+ PrintY=(WindowH/2)-h/2;\r
+ PrintX=WindowX=160-mw/2;\r
+\r
+ DrawWindow(WindowX-5,PrintY-5,mw+10,h+10,TEXTCOLOR);\r
+ DrawOutline(WindowX-5,PrintY-5,mw+10,h+10,0,HIGHLIGHT);\r
+ SETFONTCOLOR(0,TEXTCOLOR);\r
+ US_Print(string);\r
+ VW_UpdateScreen();\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+//\r
+// THIS MAY BE FIXED A LITTLE LATER...\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+static int lastmusic;\r
+\r
+void StartCPMusic(int song)\r
+{\r
+ musicnames chunk;\r
+\r
+ if (audiosegs[STARTMUSIC + lastmusic]) // JDC\r
+ MM_FreePtr ((memptr *)&audiosegs[STARTMUSIC + lastmusic]);\r
+ lastmusic = song;\r
+\r
+ SD_MusicOff();\r
+ chunk = song;\r
+\r
+ MM_BombOnError (false);\r
+ CA_CacheAudioChunk(STARTMUSIC + chunk);\r
+ MM_BombOnError (true);\r
+ if (mmerror)\r
+ mmerror = false;\r
+ else\r
+ {\r
+ MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);\r
+ SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);\r
+ }\r
+}\r
+\r
+void FreeMusic (void)\r
+{\r
+ if (audiosegs[STARTMUSIC + lastmusic]) // JDC\r
+ MM_FreePtr ((memptr *)&audiosegs[STARTMUSIC + lastmusic]);\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// IN_GetScanName() - Returns a string containing the name of the\r
+// specified scan code\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+byte *\r
+IN_GetScanName(ScanCode scan)\r
+{\r
+ byte **p;\r
+ ScanCode far *s;\r
+\r
+ for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)\r
+ if (*s == scan)\r
+ return(*p);\r
+\r
+ return(ScanNames[scan]);\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// CHECK FOR PAUSE KEY (FOR MUSIC ONLY)\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void CheckPause(void)\r
+{\r
+ if (Paused)\r
+ {\r
+ switch(SoundStatus)\r
+ {\r
+ case 0: SD_MusicOn(); break;\r
+ case 1: SD_MusicOff(); break;\r
+ }\r
+\r
+ SoundStatus^=1;\r
+ VW_WaitVBL(3);\r
+ IN_ClearKeysDown();\r
+ Paused=false;\r
+ }\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// DRAW GUN CURSOR AT CORRECT POSITION IN MENU\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void DrawMenuGun(CP_iteminfo *iteminfo)\r
+{\r
+ int x,y;\r
+\r
+\r
+ x=iteminfo->x;\r
+ y=iteminfo->y+iteminfo->curpos*13-2;\r
+ VWB_DrawPic(x,y,C_CURSOR1PIC);\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// DRAW SCREEN TITLE STRIPES\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void DrawStripes(int y)\r
+{\r
+#ifndef SPEAR\r
+ VWB_Bar(0,y,320,24,0);\r
+ VWB_Hlin(0,319,y+22,STRIPE);\r
+#else\r
+ VWB_Bar(0,y,320,22,0);\r
+ VWB_Hlin(0,319,y+23,0);\r
+#endif\r
+}\r
+\r
+void ShootSnd(void)\r
+{\r
+ SD_PlaySound(SHOOTSND);\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// CHECK FOR EPISODES\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void CheckForEpisodes(void)\r
+{\r
+ struct ffblk f;\r
+\r
+//\r
+// JAPANESE VERSION\r
+//\r
+#ifdef JAPAN\r
+#ifdef JAPDEMO\r
+ if (!findfirst("*.WJ1",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"WJ1");\r
+#else\r
+ if (!findfirst("*.WJ6",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"WJ6");\r
+#endif\r
+ strcat(configname,extension);\r
+ strcat(SaveName,extension);\r
+ strcat(PageFileName,extension);\r
+ strcat(audioname,extension);\r
+ strcat(demoname,extension);\r
+ EpisodeSelect[1] =\r
+ EpisodeSelect[2] =\r
+ EpisodeSelect[3] =\r
+ EpisodeSelect[4] =\r
+ EpisodeSelect[5] = 1;\r
+ }\r
+ else\r
+ Quit("NO JAPANESE WOLFENSTEIN 3-D DATA FILES to be found!");\r
+#else\r
+\r
+//\r
+// ENGLISH\r
+//\r
+#ifndef UPLOAD\r
+#ifndef SPEAR\r
+ if (!findfirst("*.WL6",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"WL6");\r
+ NewEmenu[2].active =\r
+ NewEmenu[4].active =\r
+ NewEmenu[6].active =\r
+ NewEmenu[8].active =\r
+ NewEmenu[10].active =\r
+ EpisodeSelect[1] =\r
+ EpisodeSelect[2] =\r
+ EpisodeSelect[3] =\r
+ EpisodeSelect[4] =\r
+ EpisodeSelect[5] = 1;\r
+ }\r
+ else\r
+ if (!findfirst("*.WL3",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"WL3");\r
+ NewEmenu[2].active =\r
+ NewEmenu[4].active =\r
+ EpisodeSelect[1] =\r
+ EpisodeSelect[2] = 1;\r
+ }\r
+ else\r
+#endif\r
+#endif\r
+\r
+\r
+\r
+#ifdef SPEAR\r
+#ifndef SPEARDEMO\r
+ if (!findfirst("*.SOD",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"SOD");\r
+ }\r
+ else\r
+ Quit("NO SPEAR OF DESTINY DATA FILES TO BE FOUND!");\r
+#else\r
+ if (!findfirst("*.SDM",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"SDM");\r
+ }\r
+ else\r
+ Quit("NO SPEAR OF DESTINY DEMO DATA FILES TO BE FOUND!");\r
+#endif\r
+\r
+#else\r
+ if (!findfirst("*.WL1",&f,FA_ARCH))\r
+ {\r
+ strcpy(extension,"WL1");\r
+ }\r
+ else\r
+ Quit("NO WOLFENSTEIN 3-D DATA FILES to be found!");\r
+#endif\r
+\r
+ strcat(configname,extension);\r
+ strcat(SaveName,extension);\r
+ strcat(PageFileName,extension);\r
+ strcat(audioname,extension);\r
+ strcat(demoname,extension);\r
+#ifndef SPEAR\r
+#ifndef GOODTIMES\r
+ strcat(helpfilename,extension);\r
+#endif\r
+ strcat(endfilename,extension);\r
+#endif\r
+#endif\r
+}\r
--- /dev/null
+//\r
+// WL_MENU.H\r
+//\r
+#ifdef SPEAR\r
+\r
+#define BORDCOLOR 0x99\r
+#define BORD2COLOR 0x93\r
+#define DEACTIVE 0x9b\r
+#define BKGDCOLOR 0x9d\r
+//#define STRIPE 0x9c\r
+\r
+#define MenuFadeOut() VL_FadeOut(0,255,0,0,51,10)\r
+\r
+#else\r
+\r
+#define BORDCOLOR 0x29\r
+#define BORD2COLOR 0x23\r
+#define DEACTIVE 0x2b\r
+#define BKGDCOLOR 0x2d\r
+#define STRIPE 0x2c\r
+\r
+#define MenuFadeOut() VL_FadeOut(0,255,43,0,0,10)\r
+\r
+#endif\r
+\r
+#define READCOLOR 0x4a\r
+#define READHCOLOR 0x47\r
+#define VIEWCOLOR 0x7f\r
+#define TEXTCOLOR 0x17\r
+#define HIGHLIGHT 0x13\r
+#define MenuFadeIn() VL_FadeIn(0,255,&gamepal,10)\r
+\r
+\r
+#define MENUSONG WONDERIN_MUS\r
+\r
+#ifndef SPEAR\r
+#define INTROSONG NAZI_NOR_MUS\r
+#else\r
+#define INTROSONG XTOWER2_MUS\r
+#endif\r
+\r
+#define SENSITIVE 60\r
+#define CENTER SENSITIVE*2\r
+\r
+#define MENU_X 76\r
+#define MENU_Y 55\r
+#define MENU_W 178\r
+#ifndef SPEAR\r
+#define MENU_H 13*10+6\r
+#else\r
+#define MENU_H 13*9+6\r
+#endif\r
+\r
+#define SM_X 48\r
+#define SM_W 250\r
+\r
+#define SM_Y1 20\r
+#define SM_H1 4*13-7\r
+#define SM_Y2 SM_Y1+5*13\r
+#define SM_H2 4*13-7\r
+#define SM_Y3 SM_Y2+5*13\r
+#define SM_H3 3*13-7\r
+\r
+#define CTL_X 24\r
+#define CTL_Y 70\r
+#define CTL_W 284\r
+#define CTL_H 13*7-7\r
+\r
+#define LSM_X 85\r
+#define LSM_Y 55\r
+#define LSM_W 175\r
+#define LSM_H 10*13+10\r
+\r
+#define NM_X 50\r
+#define NM_Y 100\r
+#define NM_W 225\r
+#define NM_H 13*4+15\r
+\r
+#define NE_X 10\r
+#define NE_Y 23\r
+#define NE_W 320-NE_X*2\r
+#define NE_H 200-NE_Y*2\r
+\r
+#define CST_X 20\r
+#define CST_Y 48\r
+#define CST_START 60\r
+#define CST_SPC 60\r
+\r
+\r
+//\r
+// TYPEDEFS\r
+//\r
+typedef struct {\r
+ int x,y,amount,curpos,indent;\r
+ } CP_iteminfo;\r
+\r
+typedef struct {\r
+ int active;\r
+ char string[36];\r
+ void (* routine)(int temp1);\r
+ } CP_itemtype;\r
+\r
+typedef struct {\r
+ int allowed[4];\r
+ } CustomCtrls;\r
+\r
+extern CP_itemtype far MainMenu[],far NewEMenu[];\r
+extern CP_iteminfo MainItems;\r
+\r
+//\r
+// FUNCTION PROTOTYPES\r
+//\r
+void SetupControlPanel(void);\r
+void CleanupControlPanel(void);\r
+\r
+void DrawMenu(CP_iteminfo *item_i,CP_itemtype far *items);\r
+int HandleMenu(CP_iteminfo *item_i,\r
+ CP_itemtype far *items,\r
+ void (*routine)(int w));\r
+void ClearMScreen(void);\r
+void DrawWindow(int x,int y,int w,int h,int wcolor);\r
+void DrawOutline(int x,int y,int w,int h,int color1,int color2);\r
+void WaitKeyUp(void);\r
+void ReadAnyControl(ControlInfo *ci);\r
+void TicDelay(int count);\r
+void CacheLump(int lumpstart,int lumpend);\r
+void UnCacheLump(int lumpstart,int lumpend);\r
+void StartCPMusic(int song);\r
+int Confirm(char far *string);\r
+void Message(char far *string);\r
+void CheckPause(void);\r
+void ShootSnd(void);\r
+void CheckSecretMissions(void);\r
+void BossKey(void);\r
+\r
+void DrawGun(CP_iteminfo *item_i,CP_itemtype far *items,int x,int *y,int which,int basey,void (*routine)(int w));\r
+void DrawHalfStep(int x,int y);\r
+void EraseGun(CP_iteminfo *item_i,CP_itemtype far *items,int x,int y,int which);\r
+void SetTextColor(CP_itemtype far *items,int hlight);\r
+void DrawMenuGun(CP_iteminfo *iteminfo);\r
+void DrawStripes(int y);\r
+\r
+void DefineMouseBtns(void);\r
+void DefineJoyBtns(void);\r
+void DefineKeyBtns(void);\r
+void DefineKeyMove(void);\r
+void EnterCtrlData(int index,CustomCtrls *cust,void (*DrawRtn)(int),void (*PrintRtn)(int),int type);\r
+\r
+void DrawMainMenu(void);\r
+void DrawSoundMenu(void);\r
+void DrawLoadSaveScreen(int loadsave);\r
+void DrawNewEpisode(void);\r
+void DrawNewGame(void);\r
+void DrawChangeView(int view);\r
+void DrawMouseSens(void);\r
+void DrawCtlScreen(void);\r
+void DrawCustomScreen(void);\r
+void DrawLSAction(int which);\r
+void DrawCustMouse(int hilight);\r
+void DrawCustJoy(int hilight);\r
+void DrawCustKeybd(int hilight);\r
+void DrawCustKeys(int hilight);\r
+void PrintCustMouse(int i);\r
+void PrintCustJoy(int i);\r
+void PrintCustKeybd(int i);\r
+void PrintCustKeys(int i);\r
+\r
+void PrintLSEntry(int w,int color);\r
+void TrackWhichGame(int w);\r
+void DrawNewGameDiff(int w);\r
+void FixupCustom(int w);\r
+\r
+void CP_NewGame(void);\r
+void CP_Sound(void);\r
+int CP_LoadGame(int quick);\r
+int CP_SaveGame(int quick);\r
+void CP_Control(void);\r
+void CP_ChangeView(void);\r
+void CP_ExitOptions(void);\r
+void CP_Quit(void);\r
+void CP_ViewScores(void);\r
+int CP_EndGame(void);\r
+int CP_CheckQuick(unsigned scancode);\r
+void CustomControls(void);\r
+void MouseSensitivity(void);\r
+\r
+void CheckForEpisodes(void);\r
+\r
+//\r
+// VARIABLES\r
+//\r
+extern int SaveGamesAvail[10],StartGame,SoundStatus;\r
+extern char SaveGameNames[10][32],SaveName[13];\r
+\r
+enum {MOUSE,JOYSTICK,KEYBOARDBTNS,KEYBOARDMOVE}; // FOR INPUT TYPES\r
+\r
+#ifndef USO_FIX1\r
+extern\r
+#endif\r
+enum\r
+{\r
+ newgame,\r
+ soundmenu,\r
+ control,\r
+ loadgame,\r
+ savegame,\r
+ changeview,\r
+\r
+#ifndef GOODTIMES\r
+#ifndef SPEAR\r
+ readthis,\r
+#endif\r
+#endif\r
+\r
+ viewscores,\r
+ backtodemo,\r
+ quit\r
+} menuitems;\r
+\r
+//\r
+// WL_INTER\r
+//\r
+typedef struct {\r
+ int kill,secret,treasure;\r
+ long time;\r
+ } LRstruct;\r
+\r
+extern LRstruct LevelRatios[];\r
+\r
+void Write (int x,int y,char *string);\r
+void NonShareware(void);\r
+int GetYorN(int x,int y,int pic);\r
+\r
+\r
--- /dev/null
+// WL_PLAY.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define sc_Question 0x35\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+boolean madenoise; // true when shooting or screaming\r
+\r
+exit_t playstate;\r
+\r
+int DebugOk;\r
+\r
+objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,\r
+ *objfreelist,*killerobj;\r
+\r
+unsigned farmapylookup[MAPSIZE];\r
+byte *nearmapylookup[MAPSIZE];\r
+\r
+boolean singlestep,godmode,noclip;\r
+int extravbls;\r
+\r
+byte tilemap[MAPSIZE][MAPSIZE]; // wall values only\r
+byte spotvis[MAPSIZE][MAPSIZE];\r
+objtype *actorat[MAPSIZE][MAPSIZE];\r
+\r
+//\r
+// replacing refresh manager\r
+//\r
+unsigned mapwidth,mapheight,tics;\r
+boolean compatability;\r
+byte *updateptr;\r
+unsigned mapwidthtable[64];\r
+unsigned uwidthtable[UPDATEHIGH];\r
+unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
+//uso: replace: byte update[UPDATESIZE];\r
+//uso: is needed? byte update[UPDATEHIGH][UPDATEWIDE];\r
+\r
+//\r
+// control info\r
+//\r
+boolean mouseenabled,joystickenabled,joypadenabled,joystickprogressive;\r
+int joystickport;\r
+int dirscan[4] = {sc_UpArrow,sc_RightArrow,sc_DownArrow,sc_LeftArrow};\r
+int buttonscan[NUMBUTTONS] =\r
+ {sc_Control,sc_Alt,sc_RShift,sc_Space,sc_1,sc_2,sc_3,sc_4};\r
+int buttonmouse[4]={bt_attack,bt_strafe,bt_use,bt_nobutton};\r
+int buttonjoy[4]={bt_attack,bt_strafe,bt_use,bt_run};\r
+\r
+int viewsize;\r
+\r
+boolean buttonheld[NUMBUTTONS];\r
+\r
+boolean demorecord,demoplayback;\r
+char far *demoptr, far *lastdemoptr;\r
+memptr demobuffer;\r
+\r
+//\r
+// curent user input\r
+//\r
+int controlx,controly; // range from -100 to 100 per tic\r
+boolean buttonstate[NUMBUTTONS];\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+void CenterWindow(word w,word h);\r
+void InitObjList (void);\r
+void RemoveObj (objtype *gone);\r
+void PollControls (void);\r
+void StopMusic(void);\r
+void StartMusic(void);\r
+void PlayLoop (void);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+objtype dummyobj;\r
+\r
+//\r
+// LIST OF SONGS FOR EACH VERSION\r
+//\r
+int songs[]=\r
+{\r
+#ifndef SPEAR\r
+ //\r
+ // Episode One\r
+ //\r
+ GETTHEM_MUS,\r
+ SEARCHN_MUS,\r
+ POW_MUS,\r
+ SUSPENSE_MUS,\r
+ GETTHEM_MUS,\r
+ SEARCHN_MUS,\r
+ POW_MUS,\r
+ SUSPENSE_MUS,\r
+\r
+ WARMARCH_MUS, // Boss level\r
+ CORNER_MUS, // Secret level\r
+\r
+ //\r
+ // Episode Two\r
+ //\r
+ NAZI_OMI_MUS,\r
+ PREGNANT_MUS,\r
+ GOINGAFT_MUS,\r
+ HEADACHE_MUS,\r
+ NAZI_OMI_MUS,\r
+ PREGNANT_MUS,\r
+ HEADACHE_MUS,\r
+ GOINGAFT_MUS,\r
+\r
+ WARMARCH_MUS, // Boss level\r
+ DUNGEON_MUS, // Secret level\r
+\r
+ //\r
+ // Episode Three\r
+ //\r
+ INTROCW3_MUS,\r
+ NAZI_RAP_MUS,\r
+ TWELFTH_MUS,\r
+ ZEROHOUR_MUS,\r
+ INTROCW3_MUS,\r
+ NAZI_RAP_MUS,\r
+ TWELFTH_MUS,\r
+ ZEROHOUR_MUS,\r
+\r
+ ULTIMATE_MUS, // Boss level\r
+ PACMAN_MUS, // Secret level\r
+\r
+ //\r
+ // Episode Four\r
+ //\r
+ GETTHEM_MUS,\r
+ SEARCHN_MUS,\r
+ POW_MUS,\r
+ SUSPENSE_MUS,\r
+ GETTHEM_MUS,\r
+ SEARCHN_MUS,\r
+ POW_MUS,\r
+ SUSPENSE_MUS,\r
+\r
+ WARMARCH_MUS, // Boss level\r
+ CORNER_MUS, // Secret level\r
+\r
+ //\r
+ // Episode Five\r
+ //\r
+ NAZI_OMI_MUS,\r
+ PREGNANT_MUS,\r
+ GOINGAFT_MUS,\r
+ HEADACHE_MUS,\r
+ NAZI_OMI_MUS,\r
+ PREGNANT_MUS,\r
+ HEADACHE_MUS,\r
+ GOINGAFT_MUS,\r
+\r
+ WARMARCH_MUS, // Boss level\r
+ DUNGEON_MUS, // Secret level\r
+\r
+ //\r
+ // Episode Six\r
+ //\r
+ INTROCW3_MUS,\r
+ NAZI_RAP_MUS,\r
+ TWELFTH_MUS,\r
+ ZEROHOUR_MUS,\r
+ INTROCW3_MUS,\r
+ NAZI_RAP_MUS,\r
+ TWELFTH_MUS,\r
+ ZEROHOUR_MUS,\r
+\r
+ ULTIMATE_MUS, // Boss level\r
+ FUNKYOU_MUS // Secret level\r
+#else\r
+\r
+ //////////////////////////////////////////////////////////////\r
+ //\r
+ // SPEAR OF DESTINY TRACKS\r
+ //\r
+ //////////////////////////////////////////////////////////////\r
+ XTIPTOE_MUS,\r
+ XFUNKIE_MUS,\r
+ XDEATH_MUS,\r
+ XGETYOU_MUS, // DON'T KNOW\r
+ ULTIMATE_MUS, // Trans Gr\94sse\r
+\r
+ DUNGEON_MUS,\r
+ GOINGAFT_MUS,\r
+ POW_MUS,\r
+ TWELFTH_MUS,\r
+ ULTIMATE_MUS, // Barnacle Wilhelm BOSS\r
+\r
+ NAZI_OMI_MUS,\r
+ GETTHEM_MUS,\r
+ SUSPENSE_MUS,\r
+ SEARCHN_MUS,\r
+ ZEROHOUR_MUS,\r
+ ULTIMATE_MUS, // Super Mutant BOSS\r
+\r
+ XPUTIT_MUS,\r
+ ULTIMATE_MUS, // Death Knight BOSS\r
+\r
+ XJAZNAZI_MUS, // Secret level\r
+ XFUNKIE_MUS, // Secret level (DON'T KNOW)\r
+\r
+ XEVIL_MUS // Angel of Death BOSS\r
+\r
+#endif\r
+};\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ USER CONTROL\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+#define BASEMOVE 35\r
+#define RUNMOVE 70\r
+#define BASETURN 35\r
+#define RUNTURN 70\r
+\r
+#define JOYSCALE 2\r
+\r
+/*\r
+===================\r
+=\r
+= PollKeyboardButtons\r
+=\r
+===================\r
+*/\r
+\r
+void PollKeyboardButtons (void)\r
+{\r
+ int i;\r
+\r
+ for (i=0;i<NUMBUTTONS;i++)\r
+ if (Keyboard[buttonscan[i]])\r
+ buttonstate[i] = true;\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PollMouseButtons\r
+=\r
+===================\r
+*/\r
+\r
+void PollMouseButtons (void)\r
+{\r
+ int buttons;\r
+\r
+ buttons = IN_MouseButtons ();\r
+\r
+ if (buttons&1)\r
+ buttonstate[buttonmouse[0]] = true;\r
+ if (buttons&2)\r
+ buttonstate[buttonmouse[1]] = true;\r
+ if (buttons&4)\r
+ buttonstate[buttonmouse[2]] = true;\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PollJoystickButtons\r
+=\r
+===================\r
+*/\r
+\r
+void PollJoystickButtons (void)\r
+{\r
+ int buttons;\r
+\r
+ buttons = IN_JoyButtons ();\r
+\r
+ if (joystickport && !joypadenabled)\r
+ {\r
+ if (buttons&4)\r
+ buttonstate[buttonjoy[0]] = true;\r
+ if (buttons&8)\r
+ buttonstate[buttonjoy[1]] = true;\r
+ }\r
+ else\r
+ {\r
+ if (buttons&1)\r
+ buttonstate[buttonjoy[0]] = true;\r
+ if (buttons&2)\r
+ buttonstate[buttonjoy[1]] = true;\r
+ if (joypadenabled)\r
+ {\r
+ if (buttons&4)\r
+ buttonstate[buttonjoy[2]] = true;\r
+ if (buttons&8)\r
+ buttonstate[buttonjoy[3]] = true;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PollKeyboardMove\r
+=\r
+===================\r
+*/\r
+\r
+void PollKeyboardMove (void)\r
+{\r
+ if (buttonstate[bt_run])\r
+ {\r
+ if (Keyboard[dirscan[di_north]])\r
+ controly -= RUNMOVE*tics;\r
+ if (Keyboard[dirscan[di_south]])\r
+ controly += RUNMOVE*tics;\r
+ if (Keyboard[dirscan[di_west]])\r
+ controlx -= RUNMOVE*tics;\r
+ if (Keyboard[dirscan[di_east]])\r
+ controlx += RUNMOVE*tics;\r
+ }\r
+ else\r
+ {\r
+ if (Keyboard[dirscan[di_north]])\r
+ controly -= BASEMOVE*tics;\r
+ if (Keyboard[dirscan[di_south]])\r
+ controly += BASEMOVE*tics;\r
+ if (Keyboard[dirscan[di_west]])\r
+ controlx -= BASEMOVE*tics;\r
+ if (Keyboard[dirscan[di_east]])\r
+ controlx += BASEMOVE*tics;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PollMouseMove\r
+=\r
+===================\r
+*/\r
+\r
+void PollMouseMove (void)\r
+{\r
+ int mousexmove,mouseymove;\r
+\r
+ Mouse(MDelta);\r
+ mousexmove = _CX;\r
+ mouseymove = _DX;\r
+\r
+ controlx += mousexmove*10/(13-mouseadjustment);\r
+ controly += mouseymove*20/(13-mouseadjustment);\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PollJoystickMove\r
+=\r
+===================\r
+*/\r
+\r
+void PollJoystickMove (void)\r
+{\r
+ int joyx,joyy;\r
+\r
+ INL_GetJoyDelta(joystickport,&joyx,&joyy);\r
+\r
+ if (joystickprogressive)\r
+ {\r
+ if (joyx > 64)\r
+ controlx += (joyx-64)*JOYSCALE*tics;\r
+ else if (joyx < -64)\r
+ controlx -= (-joyx-64)*JOYSCALE*tics;\r
+ if (joyy > 64)\r
+ controlx += (joyy-64)*JOYSCALE*tics;\r
+ else if (joyy < -64)\r
+ controly -= (-joyy-64)*JOYSCALE*tics;\r
+ }\r
+ else if (buttonstate[bt_run])\r
+ {\r
+ if (joyx > 64)\r
+ controlx += RUNMOVE*tics;\r
+ else if (joyx < -64)\r
+ controlx -= RUNMOVE*tics;\r
+ if (joyy > 64)\r
+ controly += RUNMOVE*tics;\r
+ else if (joyy < -64)\r
+ controly -= RUNMOVE*tics;\r
+ }\r
+ else\r
+ {\r
+ if (joyx > 64)\r
+ controlx += BASEMOVE*tics;\r
+ else if (joyx < -64)\r
+ controlx -= BASEMOVE*tics;\r
+ if (joyy > 64)\r
+ controly += BASEMOVE*tics;\r
+ else if (joyy < -64)\r
+ controly -= BASEMOVE*tics;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PollControls\r
+=\r
+= Gets user or demo input, call once each frame\r
+=\r
+= controlx set between -100 and 100 per tic\r
+= controly\r
+= buttonheld[] the state of the buttons LAST frame\r
+= buttonstate[] the state of the buttons THIS frame\r
+=\r
+===================\r
+*/\r
+\r
+void PollControls (void)\r
+{\r
+ int max,min,i;\r
+ byte buttonbits;\r
+\r
+//\r
+// get timing info for last frame\r
+//\r
+ if (demoplayback)\r
+ {\r
+ while (TimeCount<lasttimecount+DEMOTICS)\r
+ ;\r
+ TimeCount = lasttimecount + DEMOTICS;\r
+ lasttimecount += DEMOTICS;\r
+ tics = DEMOTICS;\r
+ }\r
+ else if (demorecord) // demo recording and playback needs\r
+ { // to be constant\r
+//\r
+// take DEMOTICS or more tics, and modify Timecount to reflect time taken\r
+//\r
+ while (TimeCount<lasttimecount+DEMOTICS)\r
+ ;\r
+ TimeCount = lasttimecount + DEMOTICS;\r
+ lasttimecount += DEMOTICS;\r
+ tics = DEMOTICS;\r
+ }\r
+ else\r
+ CalcTics ();\r
+\r
+ controlx = 0;\r
+ controly = 0;\r
+ memcpy (buttonheld,buttonstate,sizeof(buttonstate));\r
+ memset (buttonstate,0,sizeof(buttonstate));\r
+\r
+ if (demoplayback)\r
+ {\r
+ //\r
+ // read commands from demo buffer\r
+ //\r
+ buttonbits = *demoptr++;\r
+ for (i=0;i<NUMBUTTONS;i++)\r
+ {\r
+ buttonstate[i] = buttonbits&1;\r
+ buttonbits >>= 1;\r
+ }\r
+\r
+ controlx = *demoptr++;\r
+ controly = *demoptr++;\r
+\r
+ if (demoptr == lastdemoptr)\r
+ playstate = ex_completed; // demo is done\r
+\r
+ controlx *= (int)tics;\r
+ controly *= (int)tics;\r
+\r
+ return;\r
+ }\r
+\r
+\r
+//\r
+// get button states\r
+//\r
+ PollKeyboardButtons ();\r
+\r
+ if (mouseenabled)\r
+ PollMouseButtons ();\r
+\r
+ if (joystickenabled)\r
+ PollJoystickButtons ();\r
+\r
+//\r
+// get movements\r
+//\r
+ PollKeyboardMove ();\r
+\r
+ if (mouseenabled)\r
+ PollMouseMove ();\r
+\r
+ if (joystickenabled)\r
+ PollJoystickMove ();\r
+\r
+//\r
+// bound movement to a maximum\r
+//\r
+ max = 100*tics;\r
+ min = -max;\r
+ if (controlx > max)\r
+ controlx = max;\r
+ else if (controlx < min)\r
+ controlx = min;\r
+\r
+ if (controly > max)\r
+ controly = max;\r
+ else if (controly < min)\r
+ controly = min;\r
+\r
+ if (demorecord)\r
+ {\r
+ //\r
+ // save info out to demo buffer\r
+ //\r
+ controlx /= (int)tics;\r
+ controly /= (int)tics;\r
+\r
+ buttonbits = 0;\r
+\r
+ for (i=NUMBUTTONS-1;i>=0;i--)\r
+ {\r
+ buttonbits <<= 1;\r
+ if (buttonstate[i])\r
+ buttonbits |= 1;\r
+ }\r
+\r
+ *demoptr++ = buttonbits;\r
+ *demoptr++ = controlx;\r
+ *demoptr++ = controly;\r
+\r
+ if (demoptr >= lastdemoptr)\r
+ Quit ("Demo buffer overflowed!");\r
+\r
+ controlx *= (int)tics;\r
+ controly *= (int)tics;\r
+ }\r
+}\r
+\r
+\r
+\r
+//==========================================================================\r
+\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// CenterWindow() - Generates a window of a given width & height in the\r
+// middle of the screen\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+\r
+#define MAXX 320\r
+#define MAXY 160\r
+\r
+void CenterWindow(word w,word h)\r
+{\r
+ FixOfs ();\r
+ US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);\r
+}\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CheckKeys\r
+=\r
+=====================\r
+*/\r
+\r
+void CheckKeys (void)\r
+{\r
+ int i;\r
+ byte scan;\r
+ unsigned temp;\r
+\r
+\r
+ if (screenfaded || demoplayback) // don't do anything with a faded screen\r
+ return;\r
+\r
+ scan = LastScan;\r
+\r
+\r
+ #ifdef SPEAR\r
+ //\r
+ // SECRET CHEAT CODE: TAB-G-F10\r
+ //\r
+ if (Keyboard[sc_Tab] &&\r
+ Keyboard[sc_G] &&\r
+ Keyboard[sc_F10])\r
+ {\r
+ WindowH = 160;\r
+ if (godmode)\r
+ {\r
+ Message ("God mode OFF");\r
+ SD_PlaySound (NOBONUSSND);\r
+ }\r
+ else\r
+ {\r
+ Message ("God mode ON");\r
+ SD_PlaySound (ENDBONUS2SND);\r
+ }\r
+\r
+ IN_Ack();\r
+ godmode ^= 1;\r
+ DrawAllPlayBorderSides ();\r
+ IN_ClearKeysDown();\r
+ return;\r
+ }\r
+ #endif\r
+\r
+\r
+ //\r
+ // SECRET CHEAT CODE: 'MLI'\r
+ //\r
+ if (Keyboard[sc_M] &&\r
+ Keyboard[sc_L] &&\r
+ Keyboard[sc_I])\r
+ {\r
+ gamestate.health = 100;\r
+ gamestate.ammo = 99;\r
+ gamestate.keys = 3;\r
+ gamestate.score = 0;\r
+ gamestate.TimeCount += 42000L;\r
+ GiveWeapon (wp_chaingun);\r
+\r
+ DrawWeapon();\r
+ DrawHealth();\r
+ DrawKeys();\r
+ DrawAmmo();\r
+ DrawScore();\r
+\r
+ ClearMemory ();\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ ClearSplitVWB ();\r
+ VW_ScreenToScreen (displayofs,bufferofs,80,160);\r
+\r
+ Message(STR_CHEATER1"\n"\r
+ STR_CHEATER2"\n\n"\r
+ STR_CHEATER3"\n"\r
+ STR_CHEATER4"\n"\r
+ STR_CHEATER5);\r
+\r
+ UNCACHEGRCHUNK(STARTFONT+1);\r
+ PM_CheckMainMem ();\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+\r
+ DrawAllPlayBorder ();\r
+ }\r
+\r
+ //\r
+ // OPEN UP DEBUG KEYS\r
+ //\r
+#ifndef SPEAR\r
+ if (Keyboard[sc_BackSpace] &&\r
+ Keyboard[sc_LShift] &&\r
+ Keyboard[sc_Alt] &&\r
+ MS_CheckParm("goobers"))\r
+#else\r
+ if (Keyboard[sc_BackSpace] &&\r
+ Keyboard[sc_LShift] &&\r
+ Keyboard[sc_Alt] &&\r
+ MS_CheckParm("debugmode"))\r
+#endif\r
+ {\r
+ ClearMemory ();\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ ClearSplitVWB ();\r
+ VW_ScreenToScreen (displayofs,bufferofs,80,160);\r
+\r
+ Message("Debugging keys are\nnow available!");\r
+ UNCACHEGRCHUNK(STARTFONT+1);\r
+ PM_CheckMainMem ();\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+\r
+ DrawAllPlayBorderSides ();\r
+ DebugOk=1;\r
+ }\r
+\r
+ //\r
+ // TRYING THE KEEN CHEAT CODE!\r
+ //\r
+ if (Keyboard[sc_B] &&\r
+ Keyboard[sc_A] &&\r
+ Keyboard[sc_T])\r
+ {\r
+ ClearMemory ();\r
+ CA_CacheGrChunk (STARTFONT+1);\r
+ ClearSplitVWB ();\r
+ VW_ScreenToScreen (displayofs,bufferofs,80,160);\r
+\r
+ Message("Commander Keen is also\n"\r
+ "available from Apogee, but\n"\r
+ "then, you already know\n"\r
+ "that - right, Cheatmeister?!");\r
+\r
+ UNCACHEGRCHUNK(STARTFONT+1);\r
+ PM_CheckMainMem ();\r
+ IN_ClearKeysDown();\r
+ IN_Ack();\r
+\r
+ DrawAllPlayBorder ();\r
+ }\r
+\r
+//\r
+// pause key weirdness can't be checked as a scan code\r
+//\r
+ if (Paused)\r
+ {\r
+ bufferofs = displayofs;\r
+ LatchDrawPic (20-4,80-2*8,PAUSEDPIC);\r
+ SD_MusicOff();\r
+ IN_Ack();\r
+ IN_ClearKeysDown ();\r
+ SD_MusicOn();\r
+ Paused = false;\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+ return;\r
+ }\r
+\r
+\r
+//\r
+// F1-F7/ESC to enter control panel\r
+//\r
+ if (\r
+#ifndef DEBCHECK\r
+ scan == sc_F10 ||\r
+#endif\r
+ scan == sc_F9 ||\r
+ scan == sc_F7 ||\r
+ scan == sc_F8) // pop up quit dialog\r
+ {\r
+ ClearMemory ();\r
+ ClearSplitVWB ();\r
+ VW_ScreenToScreen (displayofs,bufferofs,80,160);\r
+ US_ControlPanel(scan);\r
+\r
+ DrawAllPlayBorderSides ();\r
+\r
+ if (scan == sc_F9)\r
+ StartMusic ();\r
+\r
+ PM_CheckMainMem ();\r
+ SETFONTCOLOR(0,15);\r
+ IN_ClearKeysDown();\r
+ return;\r
+ }\r
+\r
+ if ( (scan >= sc_F1 && scan <= sc_F9) || scan == sc_Escape)\r
+ {\r
+ StopMusic ();\r
+ ClearMemory ();\r
+ VW_FadeOut ();\r
+\r
+ US_ControlPanel(scan);\r
+\r
+ SETFONTCOLOR(0,15);\r
+ IN_ClearKeysDown();\r
+ DrawPlayScreen ();\r
+ if (!startgame && !loadedgame)\r
+ {\r
+ VW_FadeIn ();\r
+ StartMusic ();\r
+ }\r
+ if (loadedgame)\r
+ playstate = ex_abort;\r
+ lasttimecount = TimeCount;\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+ PM_CheckMainMem ();\r
+ return;\r
+ }\r
+\r
+//\r
+// TAB-? debug keys\r
+//\r
+ if (Keyboard[sc_Tab] && DebugOk)\r
+ {\r
+ CA_CacheGrChunk (STARTFONT);\r
+ fontnumber=0;\r
+ SETFONTCOLOR(0,15);\r
+ DebugKeys();\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+ lasttimecount = TimeCount;\r
+ return;\r
+ }\r
+\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+#############################################################################\r
+\r
+ The objlist data structure\r
+\r
+#############################################################################\r
+\r
+objlist containt structures for every actor currently playing. The structure\r
+is accessed as a linked list starting at *player, ending when ob->next ==\r
+NULL. GetNewObj inserts a new object at the end of the list, meaning that\r
+if an actor spawn another actor, the new one WILL get to think and react the\r
+same frame. RemoveObj unlinks the given object and returns it to the free\r
+list, but does not damage the objects ->next pointer, so if the current object\r
+removes itself, a linked list following loop can still safely get to the\r
+next element.\r
+\r
+<backwardly linked free list>\r
+\r
+#############################################################################\r
+*/\r
+\r
+\r
+/*\r
+=========================\r
+=\r
+= InitActorList\r
+=\r
+= Call to clear out the actor object lists returning them all to the free\r
+= list. Allocates a special spot for the player.\r
+=\r
+=========================\r
+*/\r
+\r
+int objcount;\r
+\r
+void InitActorList (void)\r
+{\r
+ int i;\r
+\r
+//\r
+// init the actor lists\r
+//\r
+ for (i=0;i<MAXACTORS;i++)\r
+ {\r
+ objlist[i].prev = &objlist[i+1];\r
+ objlist[i].next = NULL;\r
+ }\r
+\r
+ objlist[MAXACTORS-1].prev = NULL;\r
+\r
+ objfreelist = &objlist[0];\r
+ lastobj = NULL;\r
+\r
+ objcount = 0;\r
+\r
+//\r
+// give the player the first free spots\r
+//\r
+ GetNewActor ();\r
+ player = new;\r
+\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=========================\r
+=\r
+= GetNewActor\r
+=\r
+= Sets the global variable new to point to a free spot in objlist.\r
+= The free spot is inserted at the end of the liked list\r
+=\r
+= When the object list is full, the caller can either have it bomb out ot\r
+= return a dummy object pointer that will never get used\r
+=\r
+=========================\r
+*/\r
+\r
+void GetNewActor (void)\r
+{\r
+ if (!objfreelist)\r
+ Quit ("GetNewActor: No free spots in objlist!");\r
+\r
+ new = objfreelist;\r
+ objfreelist = new->prev;\r
+ memset (new,0,sizeof(*new));\r
+\r
+ if (lastobj)\r
+ lastobj->next = new;\r
+ new->prev = lastobj; // new->next is allready NULL from memset\r
+\r
+ new->active = false;\r
+ lastobj = new;\r
+\r
+ objcount++;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=========================\r
+=\r
+= RemoveObj\r
+=\r
+= Add the given object back into the free list, and unlink it from it's\r
+= neighbors\r
+=\r
+=========================\r
+*/\r
+\r
+void RemoveObj (objtype *gone)\r
+{\r
+ objtype **spotat;\r
+\r
+ if (gone == player)\r
+ Quit ("RemoveObj: Tried to remove the player!");\r
+\r
+ gone->state = NULL;\r
+\r
+//\r
+// fix the next object's back link\r
+//\r
+ if (gone == lastobj)\r
+ lastobj = (objtype *)gone->prev;\r
+ else\r
+ gone->next->prev = gone->prev;\r
+\r
+//\r
+// fix the previous object's forward link\r
+//\r
+ gone->prev->next = gone->next;\r
+\r
+//\r
+// add it back in to the free list\r
+//\r
+ gone->prev = objfreelist;\r
+ objfreelist = gone;\r
+\r
+ objcount--;\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+ MUSIC STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= StopMusic\r
+=\r
+=================\r
+*/\r
+\r
+void StopMusic(void)\r
+{\r
+ int i;\r
+\r
+ SD_MusicOff();\r
+ for (i = 0;i < LASTMUSIC;i++)\r
+ if (audiosegs[STARTMUSIC + i])\r
+ {\r
+ MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);\r
+ MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);\r
+ }\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= StartMusic\r
+=\r
+=================\r
+*/\r
+\r
+void StartMusic(void)\r
+{\r
+ musicnames chunk;\r
+\r
+ SD_MusicOff();\r
+ chunk = songs[gamestate.mapon+gamestate.episode*10];\r
+\r
+// if ((chunk == -1) || (MusicMode != smm_AdLib))\r
+//DEBUG control panel return;\r
+\r
+ MM_BombOnError (false);\r
+ CA_CacheAudioChunk(STARTMUSIC + chunk);\r
+ MM_BombOnError (true);\r
+ if (mmerror)\r
+ mmerror = false;\r
+ else\r
+ {\r
+ MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);\r
+ SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ PALETTE SHIFTING STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define NUMREDSHIFTS 6\r
+#define REDSTEPS 8\r
+\r
+#define NUMWHITESHIFTS 3\r
+#define WHITESTEPS 20\r
+#define WHITETICS 6\r
+\r
+\r
+byte far redshifts[NUMREDSHIFTS][768];\r
+byte far whiteshifts[NUMREDSHIFTS][768];\r
+\r
+int damagecount,bonuscount;\r
+boolean palshifted;\r
+\r
+extern byte far gamepal;\r
+\r
+/*\r
+=====================\r
+=\r
+= InitRedShifts\r
+=\r
+=====================\r
+*/\r
+\r
+void InitRedShifts (void)\r
+{\r
+ byte far *workptr, far *baseptr;\r
+ int i,j,delta;\r
+\r
+\r
+//\r
+// fade through intermediate frames\r
+//\r
+ for (i=1;i<=NUMREDSHIFTS;i++)\r
+ {\r
+ workptr = (byte far *)&redshifts[i-1][0];\r
+ baseptr = &gamepal;\r
+\r
+ for (j=0;j<=255;j++)\r
+ {\r
+ delta = 64-*baseptr;\r
+ *workptr++ = *baseptr++ + delta * i / REDSTEPS;\r
+ delta = -*baseptr;\r
+ *workptr++ = *baseptr++ + delta * i / REDSTEPS;\r
+ delta = -*baseptr;\r
+ *workptr++ = *baseptr++ + delta * i / REDSTEPS;\r
+ }\r
+ }\r
+\r
+ for (i=1;i<=NUMWHITESHIFTS;i++)\r
+ {\r
+ workptr = (byte far *)&whiteshifts[i-1][0];\r
+ baseptr = &gamepal;\r
+\r
+ for (j=0;j<=255;j++)\r
+ {\r
+ delta = 64-*baseptr;\r
+ *workptr++ = *baseptr++ + delta * i / WHITESTEPS;\r
+ delta = 62-*baseptr;\r
+ *workptr++ = *baseptr++ + delta * i / WHITESTEPS;\r
+ delta = 0-*baseptr;\r
+ *workptr++ = *baseptr++ + delta * i / WHITESTEPS;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= ClearPaletteShifts\r
+=\r
+=====================\r
+*/\r
+\r
+void ClearPaletteShifts (void)\r
+{\r
+ bonuscount = damagecount = 0;\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= StartBonusFlash\r
+=\r
+=====================\r
+*/\r
+\r
+void StartBonusFlash (void)\r
+{\r
+ bonuscount = NUMWHITESHIFTS*WHITETICS; // white shift palette\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= StartDamageFlash\r
+=\r
+=====================\r
+*/\r
+\r
+void StartDamageFlash (int damage)\r
+{\r
+ damagecount += damage;\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= UpdatePaletteShifts\r
+=\r
+=====================\r
+*/\r
+\r
+void UpdatePaletteShifts (void)\r
+{\r
+ int red,white;\r
+\r
+ if (bonuscount)\r
+ {\r
+ white = bonuscount/WHITETICS +1;\r
+ if (white>NUMWHITESHIFTS)\r
+ white = NUMWHITESHIFTS;\r
+ bonuscount -= tics;\r
+ if (bonuscount < 0)\r
+ bonuscount = 0;\r
+ }\r
+ else\r
+ white = 0;\r
+\r
+\r
+ if (damagecount)\r
+ {\r
+ red = damagecount/10 +1;\r
+ if (red>NUMREDSHIFTS)\r
+ red = NUMREDSHIFTS;\r
+\r
+ damagecount -= tics;\r
+ if (damagecount < 0)\r
+ damagecount = 0;\r
+ }\r
+ else\r
+ red = 0;\r
+\r
+ if (red)\r
+ {\r
+ VW_WaitVBL(1);\r
+ VL_SetPalette (redshifts[red-1]);\r
+ palshifted = true;\r
+ }\r
+ else if (white)\r
+ {\r
+ VW_WaitVBL(1);\r
+ VL_SetPalette (whiteshifts[white-1]);\r
+ palshifted = true;\r
+ }\r
+ else if (palshifted)\r
+ {\r
+ VW_WaitVBL(1);\r
+ VL_SetPalette (&gamepal); // back to normal\r
+ palshifted = false;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= FinishPaletteShifts\r
+=\r
+= Resets palette to normal if needed\r
+=\r
+=====================\r
+*/\r
+\r
+void FinishPaletteShifts (void)\r
+{\r
+ if (palshifted)\r
+ {\r
+ palshifted = 0;\r
+ VW_WaitVBL(1);\r
+ VL_SetPalette (&gamepal);\r
+ }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ CORE PLAYLOOP\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= DoActor\r
+=\r
+=====================\r
+*/\r
+\r
+void DoActor (objtype *ob)\r
+{\r
+ void (*think)(objtype *);\r
+\r
+ if (!ob->active && !areabyplayer[ob->areanumber])\r
+ return;\r
+\r
+ if (!(ob->flags&(FL_NONMARK|FL_NEVERMARK)) )\r
+ actorat[ob->tilex][ob->tiley] = NULL;\r
+\r
+//\r
+// non transitional object\r
+//\r
+\r
+ if (!ob->ticcount)\r
+ {\r
+ think = ob->state->think;\r
+ if (think)\r
+ {\r
+ think (ob);\r
+ if (!ob->state)\r
+ {\r
+ RemoveObj (ob);\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (ob->flags&FL_NEVERMARK)\r
+ return;\r
+\r
+ if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley])\r
+ return;\r
+\r
+ actorat[ob->tilex][ob->tiley] = ob;\r
+ return;\r
+ }\r
+\r
+//\r
+// transitional object\r
+//\r
+ ob->ticcount-=tics;\r
+ while ( ob->ticcount <= 0)\r
+ {\r
+ think = ob->state->action; // end of state action\r
+ if (think)\r
+ {\r
+ think (ob);\r
+ if (!ob->state)\r
+ {\r
+ RemoveObj (ob);\r
+ return;\r
+ }\r
+ }\r
+\r
+ ob->state = ob->state->next;\r
+\r
+ if (!ob->state)\r
+ {\r
+ RemoveObj (ob);\r
+ return;\r
+ }\r
+\r
+ if (!ob->state->tictime)\r
+ {\r
+ ob->ticcount = 0;\r
+ goto think;\r
+ }\r
+\r
+ ob->ticcount += ob->state->tictime;\r
+ }\r
+\r
+think:\r
+ //\r
+ // think\r
+ //\r
+ think = ob->state->think;\r
+ if (think)\r
+ {\r
+ think (ob);\r
+ if (!ob->state)\r
+ {\r
+ RemoveObj (ob);\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (ob->flags&FL_NEVERMARK)\r
+ return;\r
+\r
+ if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley])\r
+ return;\r
+\r
+ actorat[ob->tilex][ob->tiley] = ob;\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PlayLoop\r
+=\r
+===================\r
+*/\r
+long funnyticount;\r
+\r
+\r
+void PlayLoop (void)\r
+{\r
+ int give;\r
+ int helmetangle;\r
+\r
+ playstate = TimeCount = lasttimecount = 0;\r
+ frameon = 0;\r
+ running = false;\r
+ anglefrac = 0;\r
+ facecount = 0;\r
+ funnyticount = 0;\r
+ memset (buttonstate,0,sizeof(buttonstate));\r
+ ClearPaletteShifts ();\r
+\r
+ if (MousePresent)\r
+ Mouse(MDelta); // Clear accumulated mouse movement\r
+\r
+ if (demoplayback)\r
+ IN_StartAck ();\r
+\r
+ do\r
+ {\r
+ if (virtualreality)\r
+ {\r
+ helmetangle = peek (0x40,0xf0);\r
+ player->angle += helmetangle;\r
+ if (player->angle >= ANGLES)\r
+ player->angle -= ANGLES;\r
+ }\r
+\r
+\r
+ PollControls();\r
+\r
+//\r
+// actor thinking\r
+//\r
+ madenoise = false;\r
+\r
+ MoveDoors ();\r
+ MovePWalls ();\r
+\r
+ for (obj = player;obj;obj = obj->next)\r
+ DoActor (obj);\r
+\r
+ UpdatePaletteShifts ();\r
+\r
+ ThreeDRefresh ();\r
+\r
+ //\r
+ // MAKE FUNNY FACE IF BJ DOESN'T MOVE FOR AWHILE\r
+ //\r
+ #ifdef SPEAR\r
+ funnyticount += tics;\r
+ if (funnyticount > 30l*70)\r
+ {\r
+ funnyticount = 0;\r
+ StatusDrawPic (17,4,BJWAITING1PIC+(US_RndT()&1));\r
+ facecount = 0;\r
+ }\r
+ #endif\r
+\r
+ gamestate.TimeCount+=tics;\r
+\r
+ SD_Poll ();\r
+ UpdateSoundLoc(); // JAB\r
+\r
+ if (screenfaded)\r
+ VW_FadeIn ();\r
+\r
+ CheckKeys();\r
+\r
+//\r
+// debug aids\r
+//\r
+ if (singlestep)\r
+ {\r
+ VW_WaitVBL(14);\r
+ lasttimecount = TimeCount;\r
+ }\r
+ if (extravbls)\r
+ VW_WaitVBL(extravbls);\r
+\r
+ if (demoplayback)\r
+ {\r
+ if (IN_CheckAck ())\r
+ {\r
+ IN_ClearKeysDown ();\r
+ playstate = ex_abort;\r
+ }\r
+ }\r
+\r
+\r
+ if (virtualreality)\r
+ {\r
+ player->angle -= helmetangle;\r
+ if (player->angle < 0)\r
+ player->angle += ANGLES;\r
+ }\r
+\r
+ }while (!playstate && !startgame);\r
+\r
+ if (playstate != ex_died)\r
+ FinishPaletteShifts ();\r
+}\r
+\r
--- /dev/null
+// WL_SCALE.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+#define OP_RETF 0xcb\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBALS\r
+\r
+=============================================================================\r
+*/\r
+\r
+t_compscale _seg *scaledirectory[MAXSCALEHEIGHT+1];\r
+long fullscalefarcall[MAXSCALEHEIGHT+1];\r
+\r
+int maxscale,maxscaleshl2;\r
+\r
+boolean insetupscaling;\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCALS\r
+\r
+=============================================================================\r
+*/\r
+\r
+t_compscale _seg *work;\r
+unsigned BuildCompScale (int height, memptr *finalspot);\r
+\r
+int stepbytwo;\r
+\r
+//===========================================================================\r
+\r
+/*\r
+==============\r
+=\r
+= BadScale\r
+=\r
+==============\r
+*/\r
+\r
+void far BadScale (void)\r
+{\r
+ Quit ("BadScale called!");\r
+}\r
+\r
+\r
+/*\r
+==========================\r
+=\r
+= SetupScaling\r
+=\r
+==========================\r
+*/\r
+\r
+void SetupScaling (int maxscaleheight)\r
+{\r
+ int i,x,y;\r
+ byte far *dest;\r
+\r
+ insetupscaling = true;\r
+\r
+ maxscaleheight/=2; // one scaler every two pixels\r
+\r
+ maxscale = maxscaleheight-1;\r
+ maxscaleshl2 = maxscale<<2;\r
+\r
+//\r
+// free up old scalers\r
+//\r
+ for (i=1;i<MAXSCALEHEIGHT;i++)\r
+ {\r
+ if (scaledirectory[i])\r
+ MM_FreePtr (&(memptr)scaledirectory[i]);\r
+ if (i>=stepbytwo)\r
+ i += 2;\r
+ }\r
+ memset (scaledirectory,0,sizeof(scaledirectory));\r
+\r
+ MM_SortMem ();\r
+\r
+//\r
+// build the compiled scalers\r
+//\r
+ stepbytwo = viewheight/2; // save space by double stepping\r
+ MM_GetPtr (&(memptr)work,20000);\r
+\r
+ for (i=1;i<=maxscaleheight;i++)\r
+ {\r
+ BuildCompScale (i*2,&(memptr)scaledirectory[i]);\r
+ if (i>=stepbytwo)\r
+ i+= 2;\r
+ }\r
+ MM_FreePtr (&(memptr)work);\r
+\r
+//\r
+// compact memory and lock down scalers\r
+//\r
+ MM_SortMem ();\r
+ for (i=1;i<=maxscaleheight;i++)\r
+ {\r
+ MM_SetLock (&(memptr)scaledirectory[i],true);\r
+ fullscalefarcall[i] = (unsigned)scaledirectory[i];\r
+ fullscalefarcall[i] <<=16;\r
+ fullscalefarcall[i] += scaledirectory[i]->codeofs[0];\r
+ if (i>=stepbytwo)\r
+ {\r
+ scaledirectory[i+1] = scaledirectory[i];\r
+ fullscalefarcall[i+1] = fullscalefarcall[i];\r
+ scaledirectory[i+2] = scaledirectory[i];\r
+ fullscalefarcall[i+2] = fullscalefarcall[i];\r
+ i+=2;\r
+ }\r
+ }\r
+ scaledirectory[0] = scaledirectory[1];\r
+ fullscalefarcall[0] = fullscalefarcall[1];\r
+\r
+//\r
+// check for oversize wall drawing\r
+//\r
+ for (i=maxscaleheight;i<MAXSCALEHEIGHT;i++)\r
+ fullscalefarcall[i] = (long)BadScale;\r
+\r
+ insetupscaling = false;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+========================\r
+=\r
+= BuildCompScale\r
+=\r
+= Builds a compiled scaler object that will scale a 64 tall object to\r
+= the given height (centered vertically on the screen)\r
+=\r
+= height should be even\r
+=\r
+= Call with\r
+= ---------\r
+= DS:SI Source for scale\r
+= ES:DI Dest for scale\r
+=\r
+= Calling the compiled scaler only destroys AL\r
+=\r
+========================\r
+*/\r
+\r
+unsigned BuildCompScale (int height, memptr *finalspot)\r
+{\r
+ byte far *code;\r
+\r
+ int i;\r
+ long fix,step;\r
+ unsigned src,totalscaled,totalsize;\r
+ int startpix,endpix,toppix;\r
+\r
+\r
+ step = ((long)height<<16) / 64;\r
+ code = &work->code[0];\r
+ toppix = (viewheight-height)/2;\r
+ fix = 0;\r
+\r
+ for (src=0;src<=64;src++)\r
+ {\r
+ startpix = fix>>16;\r
+ fix += step;\r
+ endpix = fix>>16;\r
+\r
+ if (endpix>startpix)\r
+ work->width[src] = endpix-startpix;\r
+ else\r
+ work->width[src] = 0;\r
+\r
+//\r
+// mark the start of the code\r
+//\r
+ work->codeofs[src] = FP_OFF(code);\r
+\r
+//\r
+// compile some code if the source pixel generates any screen pixels\r
+//\r
+ startpix+=toppix;\r
+ endpix+=toppix;\r
+\r
+ if (startpix == endpix || endpix < 0 || startpix >= viewheight || src == 64)\r
+ continue;\r
+\r
+ //\r
+ // mov al,[si+src]\r
+ //\r
+ *code++ = 0x8a;\r
+ *code++ = 0x44;\r
+ *code++ = src;\r
+\r
+ for (;startpix<endpix;startpix++)\r
+ {\r
+ if (startpix >= viewheight)\r
+ break; // off the bottom of the view area\r
+ if (startpix < 0)\r
+ continue; // not into the view area\r
+\r
+ //\r
+ // mov [es:di+heightofs],al\r
+ //\r
+ *code++ = 0x26;\r
+ *code++ = 0x88;\r
+ *code++ = 0x85;\r
+ *((unsigned far *)code)++ = startpix*SCREENBWIDE;\r
+ }\r
+\r
+ }\r
+\r
+//\r
+// retf\r
+//\r
+ *code++ = 0xcb;\r
+\r
+ totalsize = FP_OFF(code);\r
+ MM_GetPtr (finalspot,totalsize);\r
+ _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);\r
+\r
+ return totalsize;\r
+}\r
+\r
+\r
+/*\r
+=======================\r
+=\r
+= ScaleLine\r
+=\r
+= linescale should have the high word set to the segment of the scaler\r
+=\r
+=======================\r
+*/\r
+\r
+extern int slinex,slinewidth;\r
+extern unsigned far *linecmds;\r
+extern long linescale;\r
+extern unsigned maskword;\r
+\r
+byte mask1,mask2,mask3;\r
+\r
+\r
+void near ScaleLine (void)\r
+{\r
+asm mov cx,WORD PTR [linescale+2]\r
+asm mov es,cx // segment of scaler\r
+\r
+asm mov bp,WORD PTR [linecmds]\r
+asm mov dx,SC_INDEX+1 // to set SC_MAPMASK\r
+\r
+asm mov bx,[slinex]\r
+asm mov di,bx\r
+asm shr di,1 // X in bytes\r
+asm shr di,1\r
+asm add di,[bufferofs]\r
+asm and bx,3\r
+/* begin 8086 hack\r
+asm shl bx,3\r
+*/\r
+asm push cx\r
+asm mov cl,3\r
+asm shl bx,cl\r
+asm pop cx\r
+/* end 8086 hack */\r
+asm add bx,[slinewidth] // bx = (pixel*8+pixwidth)\r
+asm mov al,BYTE [mapmasks3-1+bx] // -1 because pixwidth of 1 is first\r
+asm mov ds,WORD PTR [linecmds+2]\r
+asm or al,al\r
+asm jz notthreebyte // scale across three bytes\r
+asm jmp threebyte\r
+notthreebyte:\r
+asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first\r
+asm or al,al\r
+asm jnz twobyte // scale across two bytes\r
+\r
+//\r
+// one byte scaling\r
+//\r
+asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first\r
+asm out dx,al // set map mask register\r
+\r
+scalesingle:\r
+\r
+asm mov bx,[ds:bp] // table location of rtl to patch\r
+asm or bx,bx\r
+asm jz linedone // 0 signals end of segment list\r
+asm mov bx,[es:bx]\r
+asm mov dl,[es:bx] // save old value\r
+asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in\r
+asm mov si,[ds:bp+4] // table location of entry spot\r
+asm mov ax,[es:si]\r
+asm mov WORD PTR ss:[linescale],ax // call here to start scaling\r
+asm mov si,[ds:bp+2] // corrected top of shape for this segment\r
+asm add bp,6 // next segment list\r
+\r
+asm mov ax,SCREENSEG\r
+asm mov es,ax\r
+asm call ss:[linescale] // scale the segment of pixels\r
+\r
+asm mov es,cx // segment of scaler\r
+asm mov BYTE PTR es:[bx],dl // unpatch the RETF\r
+asm jmp scalesingle // do the next segment\r
+\r
+\r
+//\r
+// done\r
+//\r
+linedone:\r
+asm mov ax,ss\r
+asm mov ds,ax\r
+return;\r
+\r
+//\r
+// two byte scaling\r
+//\r
+twobyte:\r
+asm mov ss:[mask2],al\r
+asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first\r
+asm mov ss:[mask1],al\r
+\r
+scaledouble:\r
+\r
+asm mov bx,[ds:bp] // table location of rtl to patch\r
+asm or bx,bx\r
+asm jz linedone // 0 signals end of segment list\r
+asm mov bx,[es:bx]\r
+asm mov cl,[es:bx] // save old value\r
+asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in\r
+asm mov si,[ds:bp+4] // table location of entry spot\r
+asm mov ax,[es:si]\r
+asm mov WORD PTR ss:[linescale],ax // call here to start scaling\r
+asm mov si,[ds:bp+2] // corrected top of shape for this segment\r
+asm add bp,6 // next segment list\r
+\r
+asm mov ax,SCREENSEG\r
+asm mov es,ax\r
+asm mov al,ss:[mask1]\r
+asm out dx,al // set map mask register\r
+asm call ss:[linescale] // scale the segment of pixels\r
+asm inc di\r
+asm mov al,ss:[mask2]\r
+asm out dx,al // set map mask register\r
+asm call ss:[linescale] // scale the segment of pixels\r
+asm dec di\r
+\r
+asm mov es,WORD PTR ss:[linescale+2] // segment of scaler\r
+asm mov BYTE PTR es:[bx],cl // unpatch the RETF\r
+asm jmp scaledouble // do the next segment\r
+\r
+\r
+//\r
+// three byte scaling\r
+//\r
+threebyte:\r
+asm mov ss:[mask3],al\r
+asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first\r
+asm mov ss:[mask2],al\r
+asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first\r
+asm mov ss:[mask1],al\r
+\r
+scaletriple:\r
+\r
+asm mov bx,[ds:bp] // table location of rtl to patch\r
+asm or bx,bx\r
+asm jz linedone // 0 signals end of segment list\r
+asm mov bx,[es:bx]\r
+asm mov cl,[es:bx] // save old value\r
+asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in\r
+asm mov si,[ds:bp+4] // table location of entry spot\r
+asm mov ax,[es:si]\r
+asm mov WORD PTR ss:[linescale],ax // call here to start scaling\r
+asm mov si,[ds:bp+2] // corrected top of shape for this segment\r
+asm add bp,6 // next segment list\r
+\r
+asm mov ax,SCREENSEG\r
+asm mov es,ax\r
+asm mov al,ss:[mask1]\r
+asm out dx,al // set map mask register\r
+asm call ss:[linescale] // scale the segment of pixels\r
+asm inc di\r
+asm mov al,ss:[mask2]\r
+asm out dx,al // set map mask register\r
+asm call ss:[linescale] // scale the segment of pixels\r
+asm inc di\r
+asm mov al,ss:[mask3]\r
+asm out dx,al // set map mask register\r
+asm call ss:[linescale] // scale the segment of pixels\r
+asm dec di\r
+asm dec di\r
+\r
+asm mov es,WORD PTR ss:[linescale+2] // segment of scaler\r
+asm mov BYTE PTR es:[bx],cl // unpatch the RETF\r
+asm jmp scaletriple // do the next segment\r
+\r
+\r
+}\r
+\r
+\r
+/*\r
+=======================\r
+=\r
+= ScaleShape\r
+=\r
+= Draws a compiled shape at [scale] pixels high\r
+=\r
+= each vertical line of the shape has a pointer to segment data:\r
+= end of segment pixel*2 (0 terminates line) used to patch rtl in scaler\r
+= top of virtual line with segment in proper place\r
+= start of segment pixel*2, used to jsl into compiled scaler\r
+= <repeat>\r
+=\r
+= Setup for call\r
+= --------------\r
+= GC_MODE read mode 1, write mode 2\r
+= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
+= GC_INDEX pointing at GC_BITMASK\r
+=\r
+=======================\r
+*/\r
+\r
+static long longtemp;\r
+\r
+void ScaleShape (int xcenter, int shapenum, unsigned height)\r
+{\r
+ t_compshape _seg *shape;\r
+ t_compscale _seg *comptable;\r
+ unsigned scale,srcx,stopx,tempx;\r
+ int t;\r
+ unsigned far *cmdptr;\r
+ boolean leftvis,rightvis;\r
+\r
+\r
+ shape = PM_GetSpritePage (shapenum);\r
+\r
+ scale = height>>3; // low three bits are fractional\r
+ if (!scale || scale>maxscale)\r
+ return; // too close or far away\r
+ comptable = scaledirectory[scale];\r
+\r
+ *(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call\r
+ *(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape\r
+\r
+//\r
+// scale to the left (from pixel 31 to shape->leftpix)\r
+//\r
+ srcx = 32;\r
+ slinex = xcenter;\r
+ stopx = shape->leftpix;\r
+ cmdptr = &shape->dataofs[31-stopx];\r
+\r
+ while ( --srcx >=stopx && slinex>0)\r
+ {\r
+ (unsigned)linecmds = *cmdptr--;\r
+ if ( !(slinewidth = comptable->width[srcx]) )\r
+ continue;\r
+\r
+ if (slinewidth == 1)\r
+ {\r
+ slinex--;\r
+ if (slinex<viewwidth)\r
+ {\r
+ if (wallheight[slinex] >= height)\r
+ continue; // obscured by closer wall\r
+ ScaleLine ();\r
+ }\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // handle multi pixel lines\r
+ //\r
+ if (slinex>viewwidth)\r
+ {\r
+ slinex -= slinewidth;\r
+ slinewidth = viewwidth-slinex;\r
+ if (slinewidth<1)\r
+ continue; // still off the right side\r
+ }\r
+ else\r
+ {\r
+ if (slinewidth>slinex)\r
+ slinewidth = slinex;\r
+ slinex -= slinewidth;\r
+ }\r
+\r
+\r
+ leftvis = (wallheight[slinex] < height);\r
+ rightvis = (wallheight[slinex+slinewidth-1] < height);\r
+\r
+ if (leftvis)\r
+ {\r
+ if (rightvis)\r
+ ScaleLine ();\r
+ else\r
+ {\r
+ while (wallheight[slinex+slinewidth-1] >= height)\r
+ slinewidth--;\r
+ ScaleLine ();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (!rightvis)\r
+ continue; // totally obscured\r
+\r
+ while (wallheight[slinex] >= height)\r
+ {\r
+ slinex++;\r
+ slinewidth--;\r
+ }\r
+ ScaleLine ();\r
+ break; // the rest of the shape is gone\r
+ }\r
+ }\r
+\r
+\r
+//\r
+// scale to the right\r
+//\r
+ slinex = xcenter;\r
+ stopx = shape->rightpix;\r
+ if (shape->leftpix<31)\r
+ {\r
+ srcx = 31;\r
+ cmdptr = &shape->dataofs[32-shape->leftpix];\r
+ }\r
+ else\r
+ {\r
+ srcx = shape->leftpix-1;\r
+ cmdptr = &shape->dataofs[0];\r
+ }\r
+ slinewidth = 0;\r
+\r
+ while ( ++srcx <= stopx && (slinex+=slinewidth)<viewwidth)\r
+ {\r
+ (unsigned)linecmds = *cmdptr++;\r
+ if ( !(slinewidth = comptable->width[srcx]) )\r
+ continue;\r
+\r
+ if (slinewidth == 1)\r
+ {\r
+ if (slinex>=0 && wallheight[slinex] < height)\r
+ {\r
+ ScaleLine ();\r
+ }\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // handle multi pixel lines\r
+ //\r
+ if (slinex<0)\r
+ {\r
+ if (slinewidth <= -slinex)\r
+ continue; // still off the left edge\r
+\r
+ slinewidth += slinex;\r
+ slinex = 0;\r
+ }\r
+ else\r
+ {\r
+ if (slinex + slinewidth > viewwidth)\r
+ slinewidth = viewwidth-slinex;\r
+ }\r
+\r
+\r
+ leftvis = (wallheight[slinex] < height);\r
+ rightvis = (wallheight[slinex+slinewidth-1] < height);\r
+\r
+ if (leftvis)\r
+ {\r
+ if (rightvis)\r
+ {\r
+ ScaleLine ();\r
+ }\r
+ else\r
+ {\r
+ while (wallheight[slinex+slinewidth-1] >= height)\r
+ slinewidth--;\r
+ ScaleLine ();\r
+ break; // the rest of the shape is gone\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (rightvis)\r
+ {\r
+ while (wallheight[slinex] >= height)\r
+ {\r
+ slinex++;\r
+ slinewidth--;\r
+ }\r
+ ScaleLine ();\r
+ }\r
+ else\r
+ continue; // totally obscured\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+=======================\r
+=\r
+= SimpleScaleShape\r
+=\r
+= NO CLIPPING, height in pixels\r
+=\r
+= Draws a compiled shape at [scale] pixels high\r
+=\r
+= each vertical line of the shape has a pointer to segment data:\r
+= end of segment pixel*2 (0 terminates line) used to patch rtl in scaler\r
+= top of virtual line with segment in proper place\r
+= start of segment pixel*2, used to jsl into compiled scaler\r
+= <repeat>\r
+=\r
+= Setup for call\r
+= --------------\r
+= GC_MODE read mode 1, write mode 2\r
+= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
+= GC_INDEX pointing at GC_BITMASK\r
+=\r
+=======================\r
+*/\r
+\r
+void SimpleScaleShape (int xcenter, int shapenum, unsigned height)\r
+{\r
+ t_compshape _seg *shape;\r
+ t_compscale _seg *comptable;\r
+ unsigned scale,srcx,stopx,tempx;\r
+ int t;\r
+ unsigned far *cmdptr;\r
+ boolean leftvis,rightvis;\r
+\r
+\r
+ shape = PM_GetSpritePage (shapenum);\r
+\r
+ scale = height>>1;\r
+ comptable = scaledirectory[scale];\r
+\r
+ *(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call\r
+ *(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape\r
+\r
+//\r
+// scale to the left (from pixel 31 to shape->leftpix)\r
+//\r
+ srcx = 32;\r
+ slinex = xcenter;\r
+ stopx = shape->leftpix;\r
+ cmdptr = &shape->dataofs[31-stopx];\r
+\r
+ while ( --srcx >=stopx )\r
+ {\r
+ (unsigned)linecmds = *cmdptr--;\r
+ if ( !(slinewidth = comptable->width[srcx]) )\r
+ continue;\r
+\r
+ slinex -= slinewidth;\r
+ ScaleLine ();\r
+ }\r
+\r
+\r
+//\r
+// scale to the right\r
+//\r
+ slinex = xcenter;\r
+ stopx = shape->rightpix;\r
+ if (shape->leftpix<31)\r
+ {\r
+ srcx = 31;\r
+ cmdptr = &shape->dataofs[32-shape->leftpix];\r
+ }\r
+ else\r
+ {\r
+ srcx = shape->leftpix-1;\r
+ cmdptr = &shape->dataofs[0];\r
+ }\r
+ slinewidth = 0;\r
+\r
+ while ( ++srcx <= stopx )\r
+ {\r
+ (unsigned)linecmds = *cmdptr++;\r
+ if ( !(slinewidth = comptable->width[srcx]) )\r
+ continue;\r
+\r
+ ScaleLine ();\r
+ slinex+=slinewidth;\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+//\r
+// bit mask tables for drawing scaled strips up to eight pixels wide\r
+//\r
+// down here so the STUPID inline assembler doesn't get confused!\r
+//\r
+\r
+\r
+byte mapmasks1[4][8] = {\r
+{1 ,3 ,7 ,15,15,15,15,15},\r
+{2 ,6 ,14,14,14,14,14,14},\r
+{4 ,12,12,12,12,12,12,12},\r
+{8 ,8 ,8 ,8 ,8 ,8 ,8 ,8} };\r
+\r
+byte mapmasks2[4][8] = {\r
+{0 ,0 ,0 ,0 ,1 ,3 ,7 ,15},\r
+{0 ,0 ,0 ,1 ,3 ,7 ,15,15},\r
+{0 ,0 ,1 ,3 ,7 ,15,15,15},\r
+{0 ,1 ,3 ,7 ,15,15,15,15} };\r
+\r
+byte mapmasks3[4][8] = {\r
+{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0},\r
+{0 ,0 ,0 ,0 ,0 ,0 ,0 ,1},\r
+{0 ,0 ,0 ,0 ,0 ,0 ,1 ,3},\r
+{0 ,0 ,0 ,0 ,0 ,1 ,3 ,7} };\r
+\r
+\r
+unsigned wordmasks[8][8] = {\r
+{0x0080,0x00c0,0x00e0,0x00f0,0x00f8,0x00fc,0x00fe,0x00ff},\r
+{0x0040,0x0060,0x0070,0x0078,0x007c,0x007e,0x007f,0x807f},\r
+{0x0020,0x0030,0x0038,0x003c,0x003e,0x003f,0x803f,0xc03f},\r
+{0x0010,0x0018,0x001c,0x001e,0x001f,0x801f,0xc01f,0xe01f},\r
+{0x0008,0x000c,0x000e,0x000f,0x800f,0xc00f,0xe00f,0xf00f},\r
+{0x0004,0x0006,0x0007,0x8007,0xc007,0xe007,0xf007,0xf807},\r
+{0x0002,0x0003,0x8003,0xc003,0xe003,0xf003,0xf803,0xfc03},\r
+{0x0001,0x8001,0xc001,0xe001,0xf001,0xf801,0xfc01,0xfe01} };\r
+\r
+int slinex,slinewidth;\r
+unsigned far *linecmds;\r
+long linescale;\r
+unsigned maskword;\r
+\r
--- /dev/null
+// WL_STATE.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+dirtype opposite[9] =\r
+ {west,southwest,south,southeast,east,northeast,north,northwest,nodir};\r
+\r
+dirtype diagonal[9][9] =\r
+{\r
+/* east */ {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},\r
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+/* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},\r
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+/* west */ {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},\r
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+/* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},\r
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}\r
+};\r
+\r
+\r
+\r
+void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);\r
+void NewState (objtype *ob, statetype *state);\r
+\r
+boolean TryWalk (objtype *ob);\r
+void MoveObj (objtype *ob, long move);\r
+\r
+void KillActor (objtype *ob);\r
+void DamageActor (objtype *ob, unsigned damage);\r
+\r
+boolean CheckLine (objtype *ob);\r
+void FirstSighting (objtype *ob);\r
+boolean CheckSight (objtype *ob);\r
+\r
+/*\r
+=============================================================================\r
+\r
+ LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= SpawnNewObj\r
+=\r
+= Spaws a new actor at the given TILE coordinates, with the given state, and\r
+= the given size in GLOBAL units.\r
+=\r
+= new = a pointer to an initialized new actor\r
+=\r
+===================\r
+*/\r
+\r
+void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state)\r
+{\r
+ GetNewActor ();\r
+ new->state = state;\r
+ if (state->tictime)\r
+ new->ticcount = US_RndT () % state->tictime;\r
+ else\r
+ new->ticcount = 0;\r
+\r
+ new->tilex = tilex;\r
+ new->tiley = tiley;\r
+ new->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+ new->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+ new->dir = nodir;\r
+\r
+ actorat[tilex][tiley] = new;\r
+ new->areanumber =\r
+ *(mapsegs[0] + farmapylookup[new->tiley]+new->tilex) - AREATILE;\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= NewState\r
+=\r
+= Changes ob to a new state, setting ticcount to the max for that state\r
+=\r
+===================\r
+*/\r
+\r
+void NewState (objtype *ob, statetype *state)\r
+{\r
+ ob->state = state;\r
+ ob->ticcount = state->tictime;\r
+}\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+ ENEMY TILE WORLD MOVEMENT CODE\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+==================================\r
+=\r
+= TryWalk\r
+=\r
+= Attempts to move ob in its current (ob->dir) direction.\r
+=\r
+= If blocked by either a wall or an actor returns FALSE\r
+=\r
+= If move is either clear or blocked only by a door, returns TRUE and sets\r
+=\r
+= ob->tilex = new destination\r
+= ob->tiley\r
+= ob->areanumber = the floor tile number (0-(NUMAREAS-1)) of destination\r
+= ob->distance = TILEGLOBAl, or -doornumber if a door is blocking the way\r
+=\r
+= If a door is in the way, an OpenDoor call is made to start it opening.\r
+= The actor code should wait until\r
+= doorobjlist[-ob->distance].action = dr_open, meaning the door has been\r
+= fully opened\r
+=\r
+==================================\r
+*/\r
+\r
+#define CHECKDIAG(x,y) \\r
+{ \\r
+ temp=(unsigned)actorat[x][y]; \\r
+ if (temp) \\r
+ { \\r
+ if (temp<256) \\r
+ return false; \\r
+ if (((objtype *)temp)->flags&FL_SHOOTABLE) \\r
+ return false; \\r
+ } \\r
+}\r
+\r
+#define CHECKSIDE(x,y) \\r
+{ \\r
+ temp=(unsigned)actorat[x][y]; \\r
+ if (temp) \\r
+ { \\r
+ if (temp<128) \\r
+ return false; \\r
+ if (temp<256) \\r
+ doornum = temp&63; \\r
+ else if (((objtype *)temp)->flags&FL_SHOOTABLE)\\r
+ return false; \\r
+ } \\r
+}\r
+\r
+\r
+boolean TryWalk (objtype *ob)\r
+{\r
+ int doornum;\r
+ unsigned temp;\r
+\r
+ doornum = -1;\r
+\r
+ if (ob->obclass == inertobj)\r
+ {\r
+ switch (ob->dir)\r
+ {\r
+ case north:\r
+ ob->tiley--;\r
+ break;\r
+\r
+ case northeast:\r
+ ob->tilex++;\r
+ ob->tiley--;\r
+ break;\r
+\r
+ case east:\r
+ ob->tilex++;\r
+ break;\r
+\r
+ case southeast:\r
+ ob->tilex++;\r
+ ob->tiley++;\r
+ break;\r
+\r
+ case south:\r
+ ob->tiley++;\r
+ break;\r
+\r
+ case southwest:\r
+ ob->tilex--;\r
+ ob->tiley++;\r
+ break;\r
+\r
+ case west:\r
+ ob->tilex--;\r
+ break;\r
+\r
+ case northwest:\r
+ ob->tilex--;\r
+ ob->tiley--;\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ switch (ob->dir)\r
+ {\r
+ case north:\r
+ if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+ {\r
+ CHECKDIAG(ob->tilex,ob->tiley-1);\r
+ }\r
+ else\r
+ {\r
+ CHECKSIDE(ob->tilex,ob->tiley-1);\r
+ }\r
+ ob->tiley--;\r
+ break;\r
+\r
+ case northeast:\r
+ CHECKDIAG(ob->tilex+1,ob->tiley-1);\r
+ CHECKDIAG(ob->tilex+1,ob->tiley);\r
+ CHECKDIAG(ob->tilex,ob->tiley-1);\r
+ ob->tilex++;\r
+ ob->tiley--;\r
+ break;\r
+\r
+ case east:\r
+ if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+ {\r
+ CHECKDIAG(ob->tilex+1,ob->tiley);\r
+ }\r
+ else\r
+ {\r
+ CHECKSIDE(ob->tilex+1,ob->tiley);\r
+ }\r
+ ob->tilex++;\r
+ break;\r
+\r
+ case southeast:\r
+ CHECKDIAG(ob->tilex+1,ob->tiley+1);\r
+ CHECKDIAG(ob->tilex+1,ob->tiley);\r
+ CHECKDIAG(ob->tilex,ob->tiley+1);\r
+ ob->tilex++;\r
+ ob->tiley++;\r
+ break;\r
+\r
+ case south:\r
+ if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+ {\r
+ CHECKDIAG(ob->tilex,ob->tiley+1);\r
+ }\r
+ else\r
+ {\r
+ CHECKSIDE(ob->tilex,ob->tiley+1);\r
+ }\r
+ ob->tiley++;\r
+ break;\r
+\r
+ case southwest:\r
+ CHECKDIAG(ob->tilex-1,ob->tiley+1);\r
+ CHECKDIAG(ob->tilex-1,ob->tiley);\r
+ CHECKDIAG(ob->tilex,ob->tiley+1);\r
+ ob->tilex--;\r
+ ob->tiley++;\r
+ break;\r
+\r
+ case west:\r
+ if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+ {\r
+ CHECKDIAG(ob->tilex-1,ob->tiley);\r
+ }\r
+ else\r
+ {\r
+ CHECKSIDE(ob->tilex-1,ob->tiley);\r
+ }\r
+ ob->tilex--;\r
+ break;\r
+\r
+ case northwest:\r
+ CHECKDIAG(ob->tilex-1,ob->tiley-1);\r
+ CHECKDIAG(ob->tilex-1,ob->tiley);\r
+ CHECKDIAG(ob->tilex,ob->tiley-1);\r
+ ob->tilex--;\r
+ ob->tiley--;\r
+ break;\r
+\r
+ case nodir:\r
+ return false;\r
+\r
+ default:\r
+ Quit ("Walk: Bad dir");\r
+ }\r
+\r
+ if (doornum != -1)\r
+ {\r
+ OpenDoor (doornum);\r
+ ob->distance = -doornum-1;\r
+ return true;\r
+ }\r
+\r
+\r
+ ob->areanumber =\r
+ *(mapsegs[0] + farmapylookup[ob->tiley]+ob->tilex) - AREATILE;\r
+\r
+ ob->distance = TILEGLOBAL;\r
+ return true;\r
+}\r
+\r
+\r
+\r
+/*\r
+==================================\r
+=\r
+= SelectDodgeDir\r
+=\r
+= Attempts to choose and initiate a movement for ob that sends it towards\r
+= the player while dodging\r
+=\r
+= If there is no possible move (ob is totally surrounded)\r
+=\r
+= ob->dir = nodir\r
+=\r
+= Otherwise\r
+=\r
+= ob->dir = new direction to follow\r
+= ob->distance = TILEGLOBAL or -doornumber\r
+= ob->tilex = new destination\r
+= ob->tiley\r
+= ob->areanumber = the floor tile number (0-(NUMAREAS-1)) of destination\r
+=\r
+==================================\r
+*/\r
+\r
+void SelectDodgeDir (objtype *ob)\r
+{\r
+ int deltax,deltay,i;\r
+ unsigned absdx,absdy;\r
+ dirtype dirtry[5];\r
+ dirtype turnaround,tdir;\r
+\r
+ if (ob->flags & FL_FIRSTATTACK)\r
+ {\r
+ //\r
+ // turning around is only ok the very first time after noticing the\r
+ // player\r
+ //\r
+ turnaround = nodir;\r
+ ob->flags &= ~FL_FIRSTATTACK;\r
+ }\r
+ else\r
+ turnaround=opposite[ob->dir];\r
+\r
+ deltax = player->tilex - ob->tilex;\r
+ deltay = player->tiley - ob->tiley;\r
+\r
+//\r
+// arange 5 direction choices in order of preference\r
+// the four cardinal directions plus the diagonal straight towards\r
+// the player\r
+//\r
+\r
+ if (deltax>0)\r
+ {\r
+ dirtry[1]= east;\r
+ dirtry[3]= west;\r
+ }\r
+ else\r
+ {\r
+ dirtry[1]= west;\r
+ dirtry[3]= east;\r
+ }\r
+\r
+ if (deltay>0)\r
+ {\r
+ dirtry[2]= south;\r
+ dirtry[4]= north;\r
+ }\r
+ else\r
+ {\r
+ dirtry[2]= north;\r
+ dirtry[4]= south;\r
+ }\r
+\r
+//\r
+// randomize a bit for dodging\r
+//\r
+ absdx = abs(deltax);\r
+ absdy = abs(deltay);\r
+\r
+ if (absdx > absdy)\r
+ {\r
+ tdir = dirtry[1];\r
+ dirtry[1] = dirtry[2];\r
+ dirtry[2] = tdir;\r
+ tdir = dirtry[3];\r
+ dirtry[3] = dirtry[4];\r
+ dirtry[4] = tdir;\r
+ }\r
+\r
+ if (US_RndT() < 128)\r
+ {\r
+ tdir = dirtry[1];\r
+ dirtry[1] = dirtry[2];\r
+ dirtry[2] = tdir;\r
+ tdir = dirtry[3];\r
+ dirtry[3] = dirtry[4];\r
+ dirtry[4] = tdir;\r
+ }\r
+\r
+ dirtry[0] = diagonal [ dirtry[1] ] [ dirtry[2] ];\r
+\r
+//\r
+// try the directions util one works\r
+//\r
+ for (i=0;i<5;i++)\r
+ {\r
+ if ( dirtry[i] == nodir || dirtry[i] == turnaround)\r
+ continue;\r
+\r
+ ob->dir = dirtry[i];\r
+ if (TryWalk(ob))\r
+ return;\r
+ }\r
+\r
+//\r
+// turn around only as a last resort\r
+//\r
+ if (turnaround != nodir)\r
+ {\r
+ ob->dir = turnaround;\r
+\r
+ if (TryWalk(ob))\r
+ return;\r
+ }\r
+\r
+ ob->dir = nodir;\r
+}\r
+\r
+\r
+/*\r
+============================\r
+=\r
+= SelectChaseDir\r
+=\r
+= As SelectDodgeDir, but doesn't try to dodge\r
+=\r
+============================\r
+*/\r
+\r
+void SelectChaseDir (objtype *ob)\r
+{\r
+ int deltax,deltay,i;\r
+ dirtype d[3];\r
+ dirtype tdir, olddir, turnaround;\r
+\r
+\r
+ olddir=ob->dir;\r
+ turnaround=opposite[olddir];\r
+\r
+ deltax=player->tilex - ob->tilex;\r
+ deltay=player->tiley - ob->tiley;\r
+\r
+ d[1]=nodir;\r
+ d[2]=nodir;\r
+\r
+ if (deltax>0)\r
+ d[1]= east;\r
+ else if (deltax<0)\r
+ d[1]= west;\r
+ if (deltay>0)\r
+ d[2]=south;\r
+ else if (deltay<0)\r
+ d[2]=north;\r
+\r
+ if (abs(deltay)>abs(deltax))\r
+ {\r
+ tdir=d[1];\r
+ d[1]=d[2];\r
+ d[2]=tdir;\r
+ }\r
+\r
+ if (d[1]==turnaround)\r
+ d[1]=nodir;\r
+ if (d[2]==turnaround)\r
+ d[2]=nodir;\r
+\r
+\r
+ if (d[1]!=nodir)\r
+ {\r
+ ob->dir=d[1];\r
+ if (TryWalk(ob))\r
+ return; /*either moved forward or attacked*/\r
+ }\r
+\r
+ if (d[2]!=nodir)\r
+ {\r
+ ob->dir=d[2];\r
+ if (TryWalk(ob))\r
+ return;\r
+ }\r
+\r
+/* there is no direct path to the player, so pick another direction */\r
+\r
+ if (olddir!=nodir)\r
+ {\r
+ ob->dir=olddir;\r
+ if (TryWalk(ob))\r
+ return;\r
+ }\r
+\r
+ if (US_RndT()>128) /*randomly determine direction of search*/\r
+ {\r
+ for (tdir=north;tdir<=west;tdir++)\r
+ {\r
+ if (tdir!=turnaround)\r
+ {\r
+ ob->dir=tdir;\r
+ if ( TryWalk(ob) )\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (tdir=west;tdir>=north;tdir--)\r
+ {\r
+ if (tdir!=turnaround)\r
+ {\r
+ ob->dir=tdir;\r
+ if ( TryWalk(ob) )\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (turnaround != nodir)\r
+ {\r
+ ob->dir=turnaround;\r
+ if (ob->dir != nodir)\r
+ {\r
+ if ( TryWalk(ob) )\r
+ return;\r
+ }\r
+ }\r
+\r
+ ob->dir = nodir; // can't move\r
+}\r
+\r
+\r
+/*\r
+============================\r
+=\r
+= SelectRunDir\r
+=\r
+= Run Away from player\r
+=\r
+============================\r
+*/\r
+\r
+void SelectRunDir (objtype *ob)\r
+{\r
+ int deltax,deltay,i;\r
+ dirtype d[3];\r
+ dirtype tdir, olddir, turnaround;\r
+\r
+\r
+ deltax=player->tilex - ob->tilex;\r
+ deltay=player->tiley - ob->tiley;\r
+\r
+ if (deltax<0)\r
+ d[1]= east;\r
+ else\r
+ d[1]= west;\r
+ if (deltay<0)\r
+ d[2]=south;\r
+ else\r
+ d[2]=north;\r
+\r
+ if (abs(deltay)>abs(deltax))\r
+ {\r
+ tdir=d[1];\r
+ d[1]=d[2];\r
+ d[2]=tdir;\r
+ }\r
+\r
+ ob->dir=d[1];\r
+ if (TryWalk(ob))\r
+ return; /*either moved forward or attacked*/\r
+\r
+ ob->dir=d[2];\r
+ if (TryWalk(ob))\r
+ return;\r
+\r
+/* there is no direct path to the player, so pick another direction */\r
+\r
+ if (US_RndT()>128) /*randomly determine direction of search*/\r
+ {\r
+ for (tdir=north;tdir<=west;tdir++)\r
+ {\r
+ ob->dir=tdir;\r
+ if ( TryWalk(ob) )\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (tdir=west;tdir>=north;tdir--)\r
+ {\r
+ ob->dir=tdir;\r
+ if ( TryWalk(ob) )\r
+ return;\r
+ }\r
+ }\r
+\r
+ ob->dir = nodir; // can't move\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= MoveObj\r
+=\r
+= Moves ob be move global units in ob->dir direction\r
+= Actors are not allowed to move inside the player\r
+= Does NOT check to see if the move is tile map valid\r
+=\r
+= ob->x = adjusted for new position\r
+= ob->y\r
+=\r
+=================\r
+*/\r
+\r
+void MoveObj (objtype *ob, long move)\r
+{\r
+ long deltax,deltay;\r
+\r
+ switch (ob->dir)\r
+ {\r
+ case north:\r
+ ob->y -= move;\r
+ break;\r
+ case northeast:\r
+ ob->x += move;\r
+ ob->y -= move;\r
+ break;\r
+ case east:\r
+ ob->x += move;\r
+ break;\r
+ case southeast:\r
+ ob->x += move;\r
+ ob->y += move;\r
+ break;\r
+ case south:\r
+ ob->y += move;\r
+ break;\r
+ case southwest:\r
+ ob->x -= move;\r
+ ob->y += move;\r
+ break;\r
+ case west:\r
+ ob->x -= move;\r
+ break;\r
+ case northwest:\r
+ ob->x -= move;\r
+ ob->y -= move;\r
+ break;\r
+\r
+ case nodir:\r
+ return;\r
+\r
+ default:\r
+ Quit ("MoveObj: bad dir!");\r
+ }\r
+\r
+//\r
+// check to make sure it's not on top of player\r
+//\r
+ if (areabyplayer[ob->areanumber])\r
+ {\r
+ deltax = ob->x - player->x;\r
+ if (deltax < -MINACTORDIST || deltax > MINACTORDIST)\r
+ goto moveok;\r
+ deltay = ob->y - player->y;\r
+ if (deltay < -MINACTORDIST || deltay > MINACTORDIST)\r
+ goto moveok;\r
+\r
+ if (ob->obclass == ghostobj || ob->obclass == spectreobj)\r
+ TakeDamage (tics*2,ob);\r
+\r
+ //\r
+ // back up\r
+ //\r
+ switch (ob->dir)\r
+ {\r
+ case north:\r
+ ob->y += move;\r
+ break;\r
+ case northeast:\r
+ ob->x -= move;\r
+ ob->y += move;\r
+ break;\r
+ case east:\r
+ ob->x -= move;\r
+ break;\r
+ case southeast:\r
+ ob->x -= move;\r
+ ob->y -= move;\r
+ break;\r
+ case south:\r
+ ob->y -= move;\r
+ break;\r
+ case southwest:\r
+ ob->x += move;\r
+ ob->y -= move;\r
+ break;\r
+ case west:\r
+ ob->x += move;\r
+ break;\r
+ case northwest:\r
+ ob->x += move;\r
+ ob->y += move;\r
+ break;\r
+\r
+ case nodir:\r
+ return;\r
+ }\r
+ return;\r
+ }\r
+moveok:\r
+ ob->distance -=move;\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+ STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+===============\r
+=\r
+= DropItem\r
+=\r
+= Tries to drop a bonus item somewhere in the tiles surrounding the\r
+= given tilex/tiley\r
+=\r
+===============\r
+*/\r
+\r
+void DropItem (stat_t itemtype, int tilex, int tiley)\r
+{\r
+ int x,y,xl,xh,yl,yh;\r
+\r
+//\r
+// find a free spot to put it in\r
+//\r
+ if (!actorat[tilex][tiley])\r
+ {\r
+ PlaceItemType (itemtype, tilex,tiley);\r
+ return;\r
+ }\r
+\r
+ xl = tilex-1;\r
+ xh = tilex+1;\r
+ yl = tiley-1;\r
+ yh = tiley+1;\r
+\r
+ for (x=xl ; x<= xh ; x++)\r
+ for (y=yl ; y<= yh ; y++)\r
+ if (!actorat[x][y])\r
+ {\r
+ PlaceItemType (itemtype, x,y);\r
+ return;\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= KillActor\r
+=\r
+===============\r
+*/\r
+\r
+void KillActor (objtype *ob)\r
+{\r
+ int tilex,tiley;\r
+\r
+ tilex = ob->tilex = ob->x >> TILESHIFT; // drop item on center\r
+ tiley = ob->tiley = ob->y >> TILESHIFT;\r
+\r
+ switch (ob->obclass)\r
+ {\r
+ case guardobj:\r
+ GivePoints (100);\r
+ NewState (ob,&s_grddie1);\r
+ PlaceItemType (bo_clip2,tilex,tiley);\r
+ break;\r
+\r
+ case officerobj:\r
+ GivePoints (400);\r
+ NewState (ob,&s_ofcdie1);\r
+ PlaceItemType (bo_clip2,tilex,tiley);\r
+ break;\r
+\r
+ case mutantobj:\r
+ GivePoints (700);\r
+ NewState (ob,&s_mutdie1);\r
+ PlaceItemType (bo_clip2,tilex,tiley);\r
+ break;\r
+\r
+ case ssobj:\r
+ GivePoints (500);\r
+ NewState (ob,&s_ssdie1);\r
+ if (gamestate.bestweapon < wp_machinegun)\r
+ PlaceItemType (bo_machinegun,tilex,tiley);\r
+ else\r
+ PlaceItemType (bo_clip2,tilex,tiley);\r
+ break;\r
+\r
+ case dogobj:\r
+ GivePoints (200);\r
+ NewState (ob,&s_dogdie1);\r
+ break;\r
+\r
+#ifndef SPEAR\r
+ case bossobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_bossdie1);\r
+ PlaceItemType (bo_key1,tilex,tiley);\r
+ break;\r
+\r
+ case gretelobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_greteldie1);\r
+ PlaceItemType (bo_key1,tilex,tiley);\r
+ break;\r
+\r
+ case giftobj:\r
+ GivePoints (5000);\r
+ gamestate.killx = player->x;\r
+ gamestate.killy = player->y;\r
+ NewState (ob,&s_giftdie1);\r
+ break;\r
+\r
+ case fatobj:\r
+ GivePoints (5000);\r
+ gamestate.killx = player->x;\r
+ gamestate.killy = player->y;\r
+ NewState (ob,&s_fatdie1);\r
+ break;\r
+\r
+ case schabbobj:\r
+ GivePoints (5000);\r
+ gamestate.killx = player->x;\r
+ gamestate.killy = player->y;\r
+ NewState (ob,&s_schabbdie1);\r
+ A_DeathScream(ob);\r
+ break;\r
+ case fakeobj:\r
+ GivePoints (2000);\r
+ NewState (ob,&s_fakedie1);\r
+ break;\r
+\r
+ case mechahitlerobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_mechadie1);\r
+ break;\r
+ case realhitlerobj:\r
+ GivePoints (5000);\r
+ gamestate.killx = player->x;\r
+ gamestate.killy = player->y;\r
+ NewState (ob,&s_hitlerdie1);\r
+ A_DeathScream(ob);\r
+ break;\r
+#else\r
+ case spectreobj:\r
+ GivePoints (200);\r
+ NewState (ob,&s_spectredie1);\r
+ break;\r
+\r
+ case angelobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_angeldie1);\r
+ break;\r
+\r
+ case transobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_transdie0);\r
+ PlaceItemType (bo_key1,tilex,tiley);\r
+ break;\r
+\r
+ case uberobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_uberdie0);\r
+ PlaceItemType (bo_key1,tilex,tiley);\r
+ break;\r
+\r
+ case willobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_willdie1);\r
+ PlaceItemType (bo_key1,tilex,tiley);\r
+ break;\r
+\r
+ case deathobj:\r
+ GivePoints (5000);\r
+ NewState (ob,&s_deathdie1);\r
+ PlaceItemType (bo_key1,tilex,tiley);\r
+ break;\r
+#endif\r
+ }\r
+\r
+ gamestate.killcount++;\r
+ ob->flags &= ~FL_SHOOTABLE;\r
+ actorat[ob->tilex][ob->tiley] = NULL;\r
+ ob->flags |= FL_NONMARK;\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= DamageActor\r
+=\r
+= Called when the player succesfully hits an enemy.\r
+=\r
+= Does damage points to enemy ob, either putting it into a stun frame or\r
+= killing it.\r
+=\r
+===================\r
+*/\r
+\r
+void DamageActor (objtype *ob, unsigned damage)\r
+{\r
+ madenoise = true;\r
+\r
+//\r
+// do double damage if shooting a non attack mode actor\r
+//\r
+ if ( !(ob->flags & FL_ATTACKMODE) )\r
+ damage <<= 1;\r
+\r
+ ob->hitpoints -= damage;\r
+\r
+ if (ob->hitpoints<=0)\r
+ KillActor (ob);\r
+ else\r
+ {\r
+ if (! (ob->flags & FL_ATTACKMODE) )\r
+ FirstSighting (ob); // put into combat mode\r
+\r
+ switch (ob->obclass) // dogs only have one hit point\r
+ {\r
+ case guardobj:\r
+ if (ob->hitpoints&1)\r
+ NewState (ob,&s_grdpain);\r
+ else\r
+ NewState (ob,&s_grdpain1);\r
+ break;\r
+\r
+ case officerobj:\r
+ if (ob->hitpoints&1)\r
+ NewState (ob,&s_ofcpain);\r
+ else\r
+ NewState (ob,&s_ofcpain1);\r
+ break;\r
+\r
+ case mutantobj:\r
+ if (ob->hitpoints&1)\r
+ NewState (ob,&s_mutpain);\r
+ else\r
+ NewState (ob,&s_mutpain1);\r
+ break;\r
+\r
+ case ssobj:\r
+ if (ob->hitpoints&1)\r
+ NewState (ob,&s_sspain);\r
+ else\r
+ NewState (ob,&s_sspain1);\r
+\r
+ break;\r
+\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+ CHECKSIGHT\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CheckLine\r
+=\r
+= Returns true if a straight line between the player and ob is unobstructed\r
+=\r
+=====================\r
+*/\r
+\r
+boolean CheckLine (objtype *ob)\r
+{\r
+ int x1,y1,xt1,yt1,x2,y2,xt2,yt2;\r
+ int x,y;\r
+ int xdist,ydist,xstep,ystep;\r
+ int temp;\r
+ int partial,delta;\r
+ long ltemp;\r
+ int xfrac,yfrac,deltafrac;\r
+ unsigned value,intercept;\r
+\r
+ x1 = ob->x >> UNSIGNEDSHIFT; // 1/256 tile precision\r
+ y1 = ob->y >> UNSIGNEDSHIFT;\r
+ xt1 = x1 >> 8;\r
+ yt1 = y1 >> 8;\r
+\r
+ x2 = plux;\r
+ y2 = pluy;\r
+ xt2 = player->tilex;\r
+ yt2 = player->tiley;\r
+\r
+\r
+ xdist = abs(xt2-xt1);\r
+\r
+ if (xdist > 0)\r
+ {\r
+ if (xt2 > xt1)\r
+ {\r
+ partial = 256-(x1&0xff);\r
+ xstep = 1;\r
+ }\r
+ else\r
+ {\r
+ partial = x1&0xff;\r
+ xstep = -1;\r
+ }\r
+\r
+ deltafrac = abs(x2-x1);\r
+ delta = y2-y1;\r
+ ltemp = ((long)delta<<8)/deltafrac;\r
+ if (ltemp > 0x7fffl)\r
+ ystep = 0x7fff;\r
+ else if (ltemp < -0x7fffl)\r
+ ystep = -0x7fff;\r
+ else\r
+ ystep = ltemp;\r
+ yfrac = y1 + (((long)ystep*partial) >>8);\r
+\r
+ x = xt1+xstep;\r
+ xt2 += xstep;\r
+ do\r
+ {\r
+ y = yfrac>>8;\r
+ yfrac += ystep;\r
+\r
+ value = (unsigned)tilemap[x][y];\r
+ x += xstep;\r
+\r
+ if (!value)\r
+ continue;\r
+\r
+ if (value<128 || value>256)\r
+ return false;\r
+\r
+ //\r
+ // see if the door is open enough\r
+ //\r
+ value &= ~0x80;\r
+ intercept = yfrac-ystep/2;\r
+\r
+ if (intercept>doorposition[value])\r
+ return false;\r
+\r
+ } while (x != xt2);\r
+ }\r
+\r
+ ydist = abs(yt2-yt1);\r
+\r
+ if (ydist > 0)\r
+ {\r
+ if (yt2 > yt1)\r
+ {\r
+ partial = 256-(y1&0xff);\r
+ ystep = 1;\r
+ }\r
+ else\r
+ {\r
+ partial = y1&0xff;\r
+ ystep = -1;\r
+ }\r
+\r
+ deltafrac = abs(y2-y1);\r
+ delta = x2-x1;\r
+ ltemp = ((long)delta<<8)/deltafrac;\r
+ if (ltemp > 0x7fffl)\r
+ xstep = 0x7fff;\r
+ else if (ltemp < -0x7fffl)\r
+ xstep = -0x7fff;\r
+ else\r
+ xstep = ltemp;\r
+ xfrac = x1 + (((long)xstep*partial) >>8);\r
+\r
+ y = yt1 + ystep;\r
+ yt2 += ystep;\r
+ do\r
+ {\r
+ x = xfrac>>8;\r
+ xfrac += xstep;\r
+\r
+ value = (unsigned)tilemap[x][y];\r
+ y += ystep;\r
+\r
+ if (!value)\r
+ continue;\r
+\r
+ if (value<128 || value>256)\r
+ return false;\r
+\r
+ //\r
+ // see if the door is open enough\r
+ //\r
+ value &= ~0x80;\r
+ intercept = xfrac-xstep/2;\r
+\r
+ if (intercept>doorposition[value])\r
+ return false;\r
+ } while (y != yt2);\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+\r
+/*\r
+================\r
+=\r
+= CheckSight\r
+=\r
+= Checks a straight line between player and current object\r
+=\r
+= If the sight is ok, check alertness and angle to see if they notice\r
+=\r
+= returns true if the player has been spoted\r
+=\r
+================\r
+*/\r
+\r
+#define MINSIGHT 0x18000l\r
+\r
+boolean CheckSight (objtype *ob)\r
+{\r
+ long deltax,deltay;\r
+\r
+//\r
+// don't bother tracing a line if the area isn't connected to the player's\r
+//\r
+ if (!areabyplayer[ob->areanumber])\r
+ return false;\r
+\r
+//\r
+// if the player is real close, sight is automatic\r
+//\r
+ deltax = player->x - ob->x;\r
+ deltay = player->y - ob->y;\r
+\r
+ if (deltax > -MINSIGHT && deltax < MINSIGHT\r
+ && deltay > -MINSIGHT && deltay < MINSIGHT)\r
+ return true;\r
+\r
+//\r
+// see if they are looking in the right direction\r
+//\r
+ switch (ob->dir)\r
+ {\r
+ case north:\r
+ if (deltay > 0)\r
+ return false;\r
+ break;\r
+\r
+ case east:\r
+ if (deltax < 0)\r
+ return false;\r
+ break;\r
+\r
+ case south:\r
+ if (deltay < 0)\r
+ return false;\r
+ break;\r
+\r
+ case west:\r
+ if (deltax > 0)\r
+ return false;\r
+ break;\r
+ }\r
+\r
+//\r
+// trace a line to check for blocking tiles (corners)\r
+//\r
+ return CheckLine (ob);\r
+\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= FirstSighting\r
+=\r
+= Puts an actor into attack mode and possibly reverses the direction\r
+= if the player is behind it\r
+=\r
+===============\r
+*/\r
+\r
+void FirstSighting (objtype *ob)\r
+{\r
+//\r
+// react to the player\r
+//\r
+ switch (ob->obclass)\r
+ {\r
+ case guardobj:\r
+ PlaySoundLocActor(HALTSND,ob);\r
+ NewState (ob,&s_grdchase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case officerobj:\r
+ PlaySoundLocActor(SPIONSND,ob);\r
+ NewState (ob,&s_ofcchase1);\r
+ ob->speed *= 5; // go faster when chasing player\r
+ break;\r
+\r
+ case mutantobj:\r
+ NewState (ob,&s_mutchase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case ssobj:\r
+ PlaySoundLocActor(SCHUTZADSND,ob);\r
+ NewState (ob,&s_sschase1);\r
+ ob->speed *= 4; // go faster when chasing player\r
+ break;\r
+\r
+ case dogobj:\r
+ PlaySoundLocActor(DOGBARKSND,ob);\r
+ NewState (ob,&s_dogchase1);\r
+ ob->speed *= 2; // go faster when chasing player\r
+ break;\r
+\r
+#ifndef SPEAR\r
+ case bossobj:\r
+ SD_PlaySound(GUTENTAGSND);\r
+ NewState (ob,&s_bosschase1);\r
+ ob->speed = SPDPATROL*3; // go faster when chasing player\r
+ break;\r
+\r
+ case gretelobj:\r
+ SD_PlaySound(KEINSND);\r
+ NewState (ob,&s_gretelchase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case giftobj:\r
+ SD_PlaySound(EINESND);\r
+ NewState (ob,&s_giftchase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case fatobj:\r
+ SD_PlaySound(ERLAUBENSND);\r
+ NewState (ob,&s_fatchase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case schabbobj:\r
+ SD_PlaySound(SCHABBSHASND);\r
+ NewState (ob,&s_schabbchase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case fakeobj:\r
+ SD_PlaySound(TOT_HUNDSND);\r
+ NewState (ob,&s_fakechase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case mechahitlerobj:\r
+ SD_PlaySound(DIESND);\r
+ NewState (ob,&s_mechachase1);\r
+ ob->speed *= 3; // go faster when chasing player\r
+ break;\r
+\r
+ case realhitlerobj:\r
+ SD_PlaySound(DIESND);\r
+ NewState (ob,&s_hitlerchase1);\r
+ ob->speed *= 5; // go faster when chasing player\r
+ break;\r
+\r
+ case ghostobj:\r
+ NewState (ob,&s_blinkychase1);\r
+ ob->speed *= 2; // go faster when chasing player\r
+ break;\r
+#else\r
+\r
+ case spectreobj:\r
+ SD_PlaySound(GHOSTSIGHTSND);\r
+ NewState (ob,&s_spectrechase1);\r
+ ob->speed = 800; // go faster when chasing player\r
+ break;\r
+\r
+ case angelobj:\r
+ SD_PlaySound(ANGELSIGHTSND);\r
+ NewState (ob,&s_angelchase1);\r
+ ob->speed = 1536; // go faster when chasing player\r
+ break;\r
+\r
+ case transobj:\r
+ SD_PlaySound(TRANSSIGHTSND);\r
+ NewState (ob,&s_transchase1);\r
+ ob->speed = 1536; // go faster when chasing player\r
+ break;\r
+\r
+ case uberobj:\r
+ NewState (ob,&s_uberchase1);\r
+ ob->speed = 3000; // go faster when chasing player\r
+ break;\r
+\r
+ case willobj:\r
+ SD_PlaySound(WILHELMSIGHTSND);\r
+ NewState (ob,&s_willchase1);\r
+ ob->speed = 2048; // go faster when chasing player\r
+ break;\r
+\r
+ case deathobj:\r
+ SD_PlaySound(KNIGHTSIGHTSND);\r
+ NewState (ob,&s_deathchase1);\r
+ ob->speed = 2048; // go faster when chasing player\r
+ break;\r
+\r
+#endif\r
+ }\r
+\r
+ if (ob->distance < 0)\r
+ ob->distance = 0; // ignore the door opening command\r
+\r
+ ob->flags |= FL_ATTACKMODE|FL_FIRSTATTACK;\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SightPlayer\r
+=\r
+= Called by actors that ARE NOT chasing the player. If the player\r
+= is detected (by sight, noise, or proximity), the actor is put into\r
+= it's combat frame and true is returned.\r
+=\r
+= Incorporates a random reaction delay\r
+=\r
+===============\r
+*/\r
+\r
+boolean SightPlayer (objtype *ob)\r
+{\r
+ if (ob->flags & FL_ATTACKMODE)\r
+ Quit ("An actor in ATTACKMODE called SightPlayer!");\r
+\r
+ if (ob->temp2)\r
+ {\r
+ //\r
+ // count down reaction time\r
+ //\r
+ ob->temp2 -= tics;\r
+ if (ob->temp2 > 0)\r
+ return false;\r
+ ob->temp2 = 0; // time to react\r
+ }\r
+ else\r
+ {\r
+ if (!areabyplayer[ob->areanumber])\r
+ return false;\r
+\r
+ if (ob->flags & FL_AMBUSH)\r
+ {\r
+ if (!CheckSight (ob))\r
+ return false;\r
+ ob->flags &= ~FL_AMBUSH;\r
+ }\r
+ else\r
+ {\r
+ if (!madenoise && !CheckSight (ob))\r
+ return false;\r
+ }\r
+\r
+\r
+ switch (ob->obclass)\r
+ {\r
+ case guardobj:\r
+ ob->temp2 = 1+US_RndT()/4;\r
+ break;\r
+ case officerobj:\r
+ ob->temp2 = 2;\r
+ break;\r
+ case mutantobj:\r
+ ob->temp2 = 1+US_RndT()/6;\r
+ break;\r
+ case ssobj:\r
+ ob->temp2 = 1+US_RndT()/6;\r
+ break;\r
+ case dogobj:\r
+ ob->temp2 = 1+US_RndT()/8;\r
+ break;\r
+\r
+ case bossobj:\r
+ case schabbobj:\r
+ case fakeobj:\r
+ case mechahitlerobj:\r
+ case realhitlerobj:\r
+ case gretelobj:\r
+ case giftobj:\r
+ case fatobj:\r
+ case spectreobj:\r
+ case angelobj:\r
+ case transobj:\r
+ case uberobj:\r
+ case willobj:\r
+ case deathobj:\r
+ ob->temp2 = 1;\r
+ break;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ FirstSighting (ob);\r
+\r
+ return true;\r
+}\r
+\r
+\r