From f7768ad7dcfbefce525d846ce2f565dacf99f546 Mon Sep 17 00:00:00 2001 From: James Haley Date: Sun, 5 Sep 2010 23:28:16 +0000 Subject: Corrections to some of Kaiser's previous commits. Also, significant work on dialog engine, p_enemy code, and support for all new mapthing_t flag values in P_SpawnMapThing. Subversion-branch: /branches/strife-branch Subversion-revision: 2015 --- src/strife/d_main.c | 2 +- src/strife/d_net.c | 1 + src/strife/doomdef.h | 14 +- src/strife/doomstat.h | 2 + src/strife/g_game.c | 11 +- src/strife/info.c | 14 +- src/strife/m_menu.c | 202 +++++++---- src/strife/m_menu.h | 39 ++- src/strife/p_dialog.c | 579 +++++++++++++++++++++++++++++++- src/strife/p_dialog.h | 32 +- src/strife/p_enemy.c | 911 +++++++++++++++++++++++++++++++------------------- src/strife/p_map.c | 10 +- src/strife/p_mobj.c | 80 +++-- src/strife/p_mobj.h | 82 +++-- src/strife/p_pspr.c | 2 +- src/strife/p_setup.c | 2 + src/strife/p_tick.c | 4 - src/strife/r_draw.c | 62 ++-- 18 files changed, 1465 insertions(+), 584 deletions(-) diff --git a/src/strife/d_main.c b/src/strife/d_main.c index a203ef3d..ba0d8145 100644 --- a/src/strife/d_main.c +++ b/src/strife/d_main.c @@ -498,7 +498,7 @@ void D_DoomLoop (void) { TryRunTics (); // will run at least one tic } - + S_UpdateSounds (players[consoleplayer].mo);// move positional sounds // Update display, next frame, with current state. diff --git a/src/strife/d_net.c b/src/strife/d_net.c index e30ead83..c8742c71 100644 --- a/src/strife/d_net.c +++ b/src/strife/d_net.c @@ -604,6 +604,7 @@ void TryRunTics (void) G_Ticker (); gametic++; + // modify command for duplicated tics if (i != ticdup-1) { diff --git a/src/strife/doomdef.h b/src/strife/doomdef.h index 50db2fc8..c73a0b78 100644 --- a/src/strife/doomdef.h +++ b/src/strife/doomdef.h @@ -79,9 +79,9 @@ typedef enum // // Skill flags. -#define MTF_EASY 1 -#define MTF_NORMAL 2 -#define MTF_HARD 4 +#define MTF_EASY 1 +#define MTF_NORMAL 2 +#define MTF_HARD 4 // villsa [STRIFE] standing monsters #define MTF_STAND 8 // villsa [STRIFE] don't spawn in single player @@ -91,13 +91,13 @@ typedef enum // villsa [STRIFE] friendly to players #define MTF_FRIEND 64 // villsa [STRIFE] TODO - identify -#define MTF_UNKNOWN 128 -// villsa [STRIFE] thing is translucent +#define MTF_UNKNOWN1 128 +// villsa [STRIFE] thing is translucent - STRIFE-TODO: But how much? #define MTF_TRANSLUCENT 256 -// villsa [STRIFE] TODO - identify +// villsa [STRIFE] thing is more - or less? - translucent - STRIFE-TODO #define MTF_MVIS 512 // villsa [STRIFE] TODO - identify -#define MTF_RESERVED 1024 +#define MTF_UNKNOWN2 1024 diff --git a/src/strife/doomstat.h b/src/strife/doomstat.h index 6aaaf976..81095ed4 100644 --- a/src/strife/doomstat.h +++ b/src/strife/doomstat.h @@ -141,6 +141,8 @@ extern boolean statusbaractive; extern boolean automapactive; // In AutoMap mode? extern boolean menuactive; // Menu overlayed? extern boolean menupause; // haleyjd 08/29/10: [STRIFE] +extern int menupausetime; // haleyjd 09/04/10: [STRIFE] +extern boolean menuindialog; // haleyjd: ditto extern boolean paused; // Game Pause? diff --git a/src/strife/g_game.c b/src/strife/g_game.c index 2b7c2cb0..49c4ef24 100644 --- a/src/strife/g_game.c +++ b/src/strife/g_game.c @@ -493,7 +493,6 @@ void G_BuildTiccmd (ticcmd_t* cmd) cmd->buttons |= BT_ATTACK; else --mouse_fire_countdown; - } if (gamekeydown[key_use] @@ -816,9 +815,7 @@ boolean G_Responder (event_t* ev) return false; } - - - + // // G_Ticker // Make ticcmd_ts for the players. @@ -828,7 +825,7 @@ void G_Ticker (void) int i; int buf; ticcmd_t* cmd; - + // do player reborns if needed for (i=0 ; i= HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - if (cx+w > SCREENWIDTH) - break; - V_DrawPatchDirect(cx, cy, hu_font[c]); - cx+=w; + c = *ch++; + if (!c) + break; + + // haleyjd 09/04/10: [STRIFE] Don't draw spaces at the start of lines. + if(c == ' ' && cx == x) + continue; + + if (c == '\n') + { + cx = x; + cy += 11; // haleyjd 09/04/10: [STRIFE]: Changed 12 -> 11 + continue; + } + + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c>= HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + + // haleyjd 09/04/10: [STRIFE] Different linebreak handling + if (cx + w > SCREENWIDTH - 20) + { + cx = x; + cy += 11; + --ch; + } + else + { + V_DrawPatchDirect(cx, cy, hu_font[c]); + cx += w; + } } + + // [STRIFE] Return final y coordinate. + return cy + 12; } +// +// M_DialogDimMsg +// +// [STRIFE] New function +// haleyjd 09/04/10: Painstakingly transformed from the assembly code, as the +// decompiler could not touch it. Redimensions a string to fit on screen, leaving +// at least a 20 pixel margin on the right side. The string passed in must be +// writable. +// +void M_DialogDimMsg(int x, int y, char *str, boolean useyfont) +{ + int rightbound = (SCREENWIDTH - 20) - x; + patch_t **fontarray; // ebp + int linewidth = 0; // esi + int i = 0; // edx + char *message = str; // edi + char bl; // bl + + /* + STRIFE-TODO: + if(useyfont) + fontarray = yfont; + else + fontarray = hu_font; + */ + fontarray = hu_font; + + bl = toupper(*message); + + if(!bl) + return; + + // outer loop - run to end of string + do + { + if(bl != '\n') + { + int charwidth; // eax + int tempwidth; // ecx + + if(bl < HU_FONTSTART || bl > HU_FONTEND) + charwidth = 4; + else + charwidth = SHORT(fontarray[bl - HU_FONTSTART]->width); + + tempwidth = linewidth + charwidth; + + // Test if the line still fits within the boundary... + if(tempwidth >= rightbound) + { + // Doesn't fit... + char *tempptr = &message[i]; // ebx + char al; // al + + // inner loop - run backward til a space (or the start of the + // string) is found, subtracting width off the current line. + // BUG: shouldn't we stop at a previous '\n' too? + while(*tempptr != ' ' && i > 0) + { + tempptr--; + // BUG: they didn't add the first char to linewidth yet... + linewidth -= charwidth; + i--; + al = toupper(*tempptr); + if(al < HU_FONTSTART || al > HU_FONTEND) + charwidth = 4; + else + charwidth = SHORT(fontarray[al - HU_FONTSTART]->width); + } + // Replace the space with a linebreak. + // BUG: what if i is zero? ... infinite loop time! + message[i] = '\n'; + linewidth = 0; + } + else + { + // The line does fit. + // Spaces at the start of a line don't count though. + if(!(bl == ' ' && linewidth == 0)) + linewidth += charwidth; + } + } + else + linewidth = 0; // '\n' seen, so reset the line width + } + while((bl = toupper(message[++i])) != 0); // step to the next character +} // @@ -1461,7 +1539,7 @@ boolean M_Responder (event_t* ev) // "close" button pressed on window? if (ev->type == ev_quit) { - S_StartSound(NULL,sfx_swtchn); + S_StartSound(NULL, sfx_swtchn); M_QuitDOOM(0); return true; } @@ -1899,7 +1977,7 @@ void M_StartControlPanel (void) { // intro might call this repeatedly if (menuactive) - return; + return; menuactive = 1; currentMenu = &MainDef; // JDC diff --git a/src/strife/m_menu.h b/src/strife/m_menu.h index c06fe981..82848126 100644 --- a/src/strife/m_menu.h +++ b/src/strife/m_menu.h @@ -28,9 +28,40 @@ #ifndef __M_MENU__ #define __M_MENU__ +#include "d_event.h" +// +// MENU TYPEDEFS +// -#include "d_event.h" +// haleyjd 09/04/10: [STRIFE] Made external + +typedef struct +{ + // 0 = no cursor here, 1 = ok, 2 = arrows ok + short status; + + char name[10]; + + // choice = menu item #. + // if status = 2, + // choice=0:leftarrow,1:rightarrow + void (*routine)(int choice); + + // hotkey in menu + char alphaKey; +} menuitem_t; + +typedef struct menu_s +{ + short numitems; // # of menu items + struct menu_s* prevMenu; // previous menu + menuitem_t* menuitems; // menu items + void (*routine)(); // draw routine + short x; + short y; // x,y of menu + short lastOn; // last item user was on in menu +} menu_t; // // MENUS @@ -59,11 +90,13 @@ void M_Init (void); // does nothing if menu is already up. void M_StartControlPanel (void); +// haleyjd 09/04/10: Externalized. Draws menu text. +int M_WriteText(int x, int y, char *string); +// haleyjd 09/04/10: [STRIFE] New function. +void M_DialogDimMsg(int x, int y, char *str, boolean useyfont); extern int detailLevel; extern int screenblocks; - - #endif diff --git a/src/strife/p_dialog.c b/src/strife/p_dialog.c index 2b20f55d..853fe15b 100644 --- a/src/strife/p_dialog.c +++ b/src/strife/p_dialog.c @@ -33,6 +33,10 @@ #include "deh_str.h" #include "d_player.h" #include "doomstat.h" +#include "m_random.h" +#include "m_menu.h" +#include "r_main.h" +#include "v_video.h" #include "p_dialog.h" @@ -43,6 +47,25 @@ // haleyjd: size of the original Strife mapdialog_t structure. #define ORIG_MAPDIALOG_SIZE 0x5EC +#define DIALOG_INT(field, ptr) \ + field = ((int)ptr[0] | \ + ((int)ptr[1] << 8) | \ + ((int)ptr[2] << 16) | \ + ((int)ptr[3] << 24)); \ + ptr += 4; + +#define DIALOG_STR(field, ptr, len) \ + memcpy(field, ptr, len); \ + ptr += len; + +// +// Globals +// + +// This can be toggled at runtime to determine if the full dialog messages +// are subtitled on screen or not. Defaults to off. +boolean dialogshowtext = false; + // // Static Globals // @@ -64,27 +87,291 @@ static mapdialog_t *script0dialogs; // Number of dialogs defined in the SCRIPT00 lump. static int numscript0dialogs; +// The player engaged in dialog. This is always player 1, though, since Rogue +// never completed the ability to use dialog outside of single-player mode. +player_t *dialogplayer; + +// The object to which the player is speaking. +mobj_t *dialogtalker; + +// The currently active mapdialog object. +static mapdialog_t *currentdialog; + +//============================================================================= // -// Routines +// Dialog State Sets +// +// These are used to animate certain actors in response to what happens in +// their dialog sequences. // -#define DIALOG_INT(field, ptr) \ - field = ((int)ptr[0] | \ - ((int)ptr[1] << 8) | \ - ((int)ptr[2] << 16) | \ - ((int)ptr[3] << 24)); \ - ptr += 4; +typedef struct dialogstateset_s +{ + mobjtype_t type; // the type of object + statenum_t greet; // greeting state, for start of dialog + statenum_t yes; // "yes" state, for an affirmative response + statenum_t no; // "no" state, when you don't have the right items +} dialogstateset_t; -#define DIALOG_STR(field, ptr, len) \ - memcpy(field, ptr, len); \ - ptr += len; +static dialogstateset_t dialogstatesets[] = +{ + { MT_PLAYER, S_NULL, S_NULL, S_NULL }, + { MT_SHOPKEEPER_W, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, + { MT_SHOPKEEPER_B, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, + { MT_SHOPKEEPER_A, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, + { MT_SHOPKEEPER_M, S_MRGT_00, S_MRYS_00, S_MRNO_00 } +}; + +// Rogue stored this in a static global rather than making it a define... +static int numdialogstatesets = arrlen(dialogstatesets); + +//============================================================================= +// +// Random Messages +// +// Rogue hard-coded these so they wouldn't have to repeat them several times +// in the SCRIPT00 lump, apparently. +// + +#define MAXRNDMESSAGES 10 + +typedef struct rndmessage_s +{ + const char *type_name; + int nummessages; + const char *messages[MAXRNDMESSAGES]; +} rndmessage_t; + +static rndmessage_t rndMessages[] = +{ + // Peasants + { + "PEASANT", + 10, + { + "PLEASE DON'T HURT ME.", + + "IF YOU'RE LOOKING TO HURT ME, I'M \n" + "NOT REALLY WORTH THE EFFORT.", + + "I DON'T KNOW ANYTHING.", + + "GO AWAY OR I'LL CALL THE GUARDS!", + + "I WISH SOMETIMES THAT ALL THESE \n" + "REBELS WOULD JUST LEARN THEIR \n" + "PLACE AND STOP THIS NONSENSE.", + + "JUST LEAVE ME ALONE, OK?", + + "I'M NOT SURE, BUT SOMETIMES I THINK \n" + "THAT I KNOW SOME OF THE ACOLYTES.", + + "THE ORDER'S GOT EVERYTHING AROUND HERE PRETTY WELL LOCKED UP TIGHT.", + + "THERE'S NO WAY THAT THIS IS JUST A \n" + "SECURITY FORCE.", + + "I'VE HEARD THAT THE ORDER IS REALLY \n" + "NERVOUS ABOUT THE FRONT'S \n" + "ACTIONS AROUND HERE." + } + }, + // Rebel + { + "REBEL", + 10, + { + "THERE'S NO WAY THE ORDER WILL \n" + "STAND AGAINST US.", + + "WE'RE ALMOST READY TO STRIKE. \n" + "MACIL'S PLANES ARE FALLING IN PLACE.", + + "WE'RE ALL BEHIND YOU, DON'T WORRY.", + + "DON'T GET TOO CLOSE TO ANY OF THOSE BIG ROBOTS. THEY'LL MELT YOU DOWN \n" + "FOR SCRAP!", + + "THE DAY OF OUR GLORY WILL SOON \n" + "COME, AND THOSE WHO OPPOSE US WILL \n" + "BE CRUSHED!", + + "DON'T GET TOO COMFORTABLE. WE'VE \n" + "STILL GOT OUR WORK CUT OUT FOR US.", + + "MACIL SAYS THAT YOU'RE THE NEW \n" + "HOPE. BEAR THAT IN MIND.", + + "ONCE WE'VE TAKEN THESE CHARLATANS DOWN, WE'LL BE ABLE TO REBUILD THIS " + "WORLD AS IT SHOULD BE.", + + "REMEMBER THAT YOU AREN'T FIGHTING \n" + "JUST FOR YOURSELF, BUT FOR \n" + "EVERYONE HERE AND OUTSIDE.", + + "AS LONG AS ONE OF US STILL STANDS, \n" + "WE WILL WIN." + } + }, + // Acolyte + { + "AGUARD", + 10, + { + "MOVE ALONG, PEASANT.", + + "FOLLOW THE TRUE FAITH, ONLY THEN \n" + "WILL YOU BEGIN TO UNDERSTAND.", + + "ONLY THROUGH DEATH CAN ONE BE \n" + "TRULY REBORN.", + + "I'M NOT INTERESTED IN YOUR USELESS \n" + "DRIVEL.", + + "IF I HAD WANTED TO TALK YOU I \n" + "WOULD HAVE TOLD YOU SO.", + + "GO AND ANNOY SOMEONE ELSE!", + + "KEEP MOVING!", + + "IF THE ALARM GOES OFF, JUST STAY OUT OF OUR WAY!", + + "THE ORDER WILL CLEANSE THE WORLD \n" + "AND USHER IT INTO THE NEW ERA.", + + "PROBLEM? NO, I THOUGHT NOT.", + } + }, + // Beggar + { + "BEGGAR", + 10, + { + "ALMS FOR THE POOR?", + + "WHAT ARE YOU LOOKING AT, SURFACER?", + + "YOU WOULDN'T HAVE ANY EXTRA FOOD, WOULD YOU?", + + "YOU SURFACE PEOPLE WILL NEVER \n" + " " + " UNDERSTAND US.", + + "HA, THE GUARDS CAN'T FIND US. THOSE \n" + "IDIOTS DON'T EVEN KNOW WE EXIST.", + + "ONE DAY EVERYONE BUT THOSE WHO SERVE THE ORDER WILL BE FORCED TO " + " JOIN US.", + + "STARE NOW, BUT YOU KNOW THAT THIS WILL BE YOUR OWN FACE ONE DAY.", + + "THERE'S NOTHING THING MORE \n" + "ANNOYING THAN A SURFACER WITH AN ATTITUDE!", + + "THE ORDER WILL MAKE SHORT WORK OF YOUR PATHETIC FRONT.", + + "WATCH YOURSELF SURFACER. WE KNOW OUR ENEMIES!" + } + }, + // Templar + { + "PGUARD", + 10, + { + "WE ARE THE HANDS OF FATE. TO EARN \n" + "OUR WRATH IS TO FIND OBLIVION!", + + "THE ORDER WILL CLEANSE THE WORLD \n" + "OF THE WEAK AND CORRUPT!", + + "OBEY THE WILL OF THE MASTERS!", + + "LONG LIFE TO THE BROTHERS OF THE \n" + "ORDER!", + + "FREE WILL IS AN ILLUSION THAT BINDS \n" + "THE WEAK MINDED.", + + "POWER IS THE PATH TO GLORY. TO \n" + "FOLLOW THE ORDER IS TO WALK THAT \n" + "PATH!", + + "TAKE YOUR PLACE AMONG THE \n" + "RIGHTEOUS, JOIN US!", + + "THE ORDER PROTECTS ITS OWN.", + + "ACOLYTES? THEY HAVE YET TO SEE THE FULL GLORY OF THE ORDER.", + + "IF THERE IS ANY HONOR INSIDE THAT \n" + "PATHETIC SHELL OF A BODY, \n" + "YOU'LL ENTER INTO THE ARMS OF THE \n" + "ORDER." + } + } +}; + +// And again, this could have been a define, but was a variable. +static int numrndmessages = arrlen(rndMessages); + +//============================================================================= +// +// Dialog Menu Structure +// +// The Strife dialog system is actually just a serious abuse of the DOOM menu +// engine. Hence why it doesn't work in multiplayer games or during demo +// recording. +// + +#define NUMDIALOGMENUITEMS 6 + +static void P_DialogDrawer(void); +static void P_DialogDoChoice(int choice); + +static menuitem_t dialogmenuitems[] = +{ + { 1, "", P_DialogDoChoice, '1' }, // These items are loaded dynamically + { 1, "", P_DialogDoChoice, '2' }, + { 1, "", P_DialogDoChoice, '3' }, + { 1, "", P_DialogDoChoice, '4' }, + { 1, "", P_DialogDoChoice, '5' }, + { 1, "", P_DialogDoChoice, '6' } // Item 6 is always the dismissal item +}; + +static menu_t dialogmenu = +{ + NUMDIALOGMENUITEMS, + NULL, + dialogmenuitems, + P_DialogDrawer, + 42, + 75, + 0 +}; + +// Lump number of the dialog background picture, if any. +static int dialogbgpiclumpnum; + +// Name of current speaking character. +static char *dialogname; + +// Current dialog text. +static char *dialogtext; + +//============================================================================= +// +// Routines +// // // P_ParseDialogLump // -// haleyjd 09/02/10: This is a new function added to parse out the dialogs -// from the dialog lump rather than reading them raw from the lump pointer. -// This avoids problems with structure packing. +// haleyjd 09/02/10: This is an original function added to parse out the +// dialogs from the dialog lump rather than reading them raw from the lump +// pointer. This avoids problems with structure packing. // static void P_ParseDialogLump(byte *lump, mapdialog_t **dialogs, int numdialogs, int tag) @@ -114,10 +401,10 @@ static void P_ParseDialogLump(byte *lump, mapdialog_t **dialogs, for(j = 0; j < 5; j++) { mapdlgchoice_t *curchoice = &(curdialog->choices[j]); - DIALOG_INT(curchoice->giveitem, rover); - DIALOG_INT(curchoice->needitem1, rover); - DIALOG_INT(curchoice->needitem2, rover); - DIALOG_INT(curchoice->needitem3, rover); + DIALOG_INT(curchoice->giveitem, rover); + DIALOG_INT(curchoice->needitem1, rover); + DIALOG_INT(curchoice->needitem2, rover); + DIALOG_INT(curchoice->needitem3, rover); DIALOG_INT(curchoice->needamount1, rover); DIALOG_INT(curchoice->needamount2, rover); DIALOG_INT(curchoice->needamount3, rover); @@ -137,7 +424,7 @@ static void P_ParseDialogLump(byte *lump, mapdialog_t **dialogs, // haleyjd 09/02/10: Loads the dialog script for the current map. Also loads // SCRIPT00 if it has not yet been loaded. // -void P_DialogLoad(int eax0, int a2, int a3, int a4) +void P_DialogLoad(void) { char lumpname[9]; int lumpnum; @@ -206,3 +493,259 @@ int P_PlayerHasItem(player_t *player, mobjtype_t type) return 0; } +// +// P_DialogFind +// +// [STRIFE] New function +// haleyjd 09/03/10: Looks for a dialog definition matching the given +// Script ID # for an mobj. +// +mapdialog_t *P_DialogFind(int type) +{ + int i; + + // check the map-specific dialogs first + for(i = 0; i < numleveldialogs; i++) + { + if(type == leveldialogs[i].speakerid) + return &leveldialogs[i]; + } + + // check SCRIPT00 dialogs next + for(i = 0; i < numscript0dialogs; i++) + { + if(type == script0dialogs[i].speakerid) + return &script0dialogs[i]; + } + + // the default dialog is script 0 in the SCRIPT00 lump. + return &script0dialogs[0]; +} + +// +// P_DialogGetStates +// +// [STRIFE] New function +// haleyjd 09/03/10: Find the set of special dialog states (greetings, yes, no) +// for a particular thing type. +// STRIFE-TODO: Or is it a conversation ID? +// +static dialogstateset_t *P_DialogGetStates(mobjtype_t type) +{ + int i; + + // look for a match by type + for(i = 0; i < numdialogstatesets; i++) + { + if(type == dialogstatesets[i].type) + return &dialogstatesets[i]; + } + + // return the default 0 record if no match. + return &dialogstatesets[0]; +} + +// +// P_DialogGetMsg +// +// [STRIFE] New function +// haleyjd 09/03/10: Redirects dialog messages when the script indicates that +// the actor should use a random message stored in the executable instead. +// +static const char *P_DialogGetMsg(const char *message) +{ + // if the message starts with "RANDOM"... + if(!strncasecmp(message, "RANDOM", 6)) + { + int i; + const char *nameloc = message + 7; + + // look for a match in rndMessages for the string starting + // 7 chars after "RANDOM_" + for(i = 0; i < numrndmessages; i++) + { + if(!strncasecmp(nameloc, rndMessages[i].type_name, 4)) + { + // found a match, so return a random message + int rnd = M_Random(); + int nummessages = rndMessages[i].nummessages; + return rndMessages[i].messages[rnd % nummessages]; + } + } + } + + // otherwise, just return the message passed in. + return message; +} + +// +// P_GiveInventoryItem +// +// [STRIFE] New function +// haleyjd 09/03/10: Give an inventory item to the player, if possible. +// +boolean P_GiveInventoryItem(player_t *player, int a2, int a3) +{ + int v3 = 0; + int v15 = a2; + int v4 = a3; + + // repaint the status bar due to inventory changing + player->st_update = true; + + // STRIFE-TODO: do an insertion sort on the inventory... + // Too bad the code is nearly impossible to understand!!! + + return true; +} + +// +// P_GiveItemToPlayer +// +// [STRIFE] New function +// haleyjd 09/03/10: Sorts out how to give something to the player. +// Not strictly just for inventory items. +// +boolean P_GiveItemToPlayer(player_t *player, int sprnum, mobjtype_t type) +{ + // haleyjd: STRIFE-TODO + return true; +} + +// +// P_TakeDialogItem +// +// [STRIFE] New function +// haleyjd 09/03/10: Removes needed items from the player's inventory. +// +static void P_TakeDialogItem(player_t *player, int type, int amount) +{ + int i; + + if(amount <= 0) + return; + + for(i = 0; i < player->numinventory; i++) + { + // find a matching item + if(type != player->inventory[i].type) + continue; + + // if there is none left... + if((player->inventory[i].amount -= amount) < 1) + { + // ...shift everything above it down + int j; + + // BUG: They should have stopped at j < numinventory. This + // seems to implicitly assume that numinventory is always at + // least one less than the max # of slots, otherwise it + // pulls in data from the following player_t fields: + // st_update, numinventory, inventorycursor, accuracy, stamina + for(j = i + 1; j <= player->numinventory; j++) + { + inventory_t *item1 = &(player->inventory[j - 1]); + inventory_t *item2 = &(player->inventory[j]); + + *item1 = *item2; + } + + // blank the topmost slot + // BUG: This will overwrite the aforementioned fields if + // numinventory is equal to the number of slots! + // STRIFE-TODO: Overflow emulation? + player->inventory[player->numinventory].type = NUMMOBJTYPES; + player->inventory[player->numinventory].sprite = -1; + player->numinventory--; + + // update cursor position + if(player->inventorycursor >= player->numinventory) + { + if(player->inventorycursor) + player->inventorycursor--; + } + } // end if + + return; // done! + + } // end for +} + +// +// P_DialogDrawer +// +// This function is set as the drawer callback for the dialog menu. +// +static void P_DialogDrawer(void) +{ + angle_t angle; + int y; + int height; + int finaly; + + // Run down bonuscount faster than usual so that flashes from being given + // items are less obvious. + if(dialogplayer->bonuscount) + { + dialogplayer->bonuscount -= 3; + if(dialogplayer->bonuscount < 0) + dialogplayer->bonuscount = 0; + } + + angle = R_PointToAngle2(dialogplayer->mo->x, + dialogplayer->mo->y, + dialogtalker->x, + dialogtalker->y); + angle -= dialogplayer->mo->angle; + + // Dismiss the dialog if the player is out of alignment, or the thing he was + // talking to is now engaged in battle. + if(angle > 0x20000000 && angle < 0xE0000000 || dialogtalker->flags & MF_INCOMBAT) + P_DialogDoChoice(dialogmenu.numitems - 1); + + dialogtalker->reactiontime = 2; + + if(dialogbgpiclumpnum != -1) + { + patch_t *patch = W_CacheLumpNum(dialogbgpiclumpnum, PU_CACHE); + V_DrawPatchDirect(0, 0, patch); + } + + if(menupausetime <= gametic) + { + if(menuindialog) + { + if(menupausetime + 3 < gametic) + menupause = true; + } + M_WriteText(12, 18, dialogname); + y = 28; + + if(dialogshowtext || currentdialog->voice[0] == '\0') + y = M_WriteText(20, 28, dialogtext); + + height = 20 * dialogmenu.numitems; + + finaly = 175 - height; // preferred height + if(y > finaly) + finaly = 199 - height; // height it will bump down to if necessary. + + M_WriteText(42, finaly - 6, "______________________________"); + + /* + dialogmenu + */ + } +} + +// +// P_DialogDoChoice +// +// [STRIFE] New function +// haleyjd 09/05/10: Handles making a choice in a dialog. Installed as the +// callback for all items in the dialogmenu structure. +// +static void P_DialogDoChoice(int choice) +{ + // STRIFE-TODO +} diff --git a/src/strife/p_dialog.h b/src/strife/p_dialog.h index 17ff46ca..3da79ba8 100644 --- a/src/strife/p_dialog.h +++ b/src/strife/p_dialog.h @@ -40,28 +40,28 @@ typedef struct mapdlgchoice_s { - int giveitem; // item given when successful - int needitem1; // first item needed for success - int needitem2; // second item needed for success, if any - int needitem3; // third item needed for success, if any - int needamount1; // amount of first item needed - int needamount2; // amount of second item needed - int needamount3; // amount of third item needed + int giveitem; // item given when successful + int needitem1; // first item needed for success + int needitem2; // second item needed for success, if any + int needitem3; // third item needed for success, if any + int needamount1; // amount of first item needed + int needamount2; // amount of second item needed + int needamount3; // amount of third item needed char text[MDLG_CHOICELEN]; // normal text char textok[MDLG_MSGLEN]; // message given on success - int next; // next dialog? - int objective; // ??? - char textno[MDLG_MSGLEN]; // message given on failure + int next; // next dialog? + int objective; // ??? + char textno[MDLG_MSGLEN]; // message given on failure } mapdlgchoice_t; typedef struct mapdialog_s { - int speakerid; // script ID# for thingtype that will use this dialog - int dropitem; // item to drop if that thingtype is killed - int checkitem1; // first item needed to see this dialog - int checkitem2; // second item needed to see this dialog, if any - int checkitem3; // third item needed to see this dialog, if any - int jumptoconv; // conversation to jump to when... ? + int speakerid; // script ID# for mobjtype that will use this dialog + int dropitem; // item to drop if that thingtype is killed + int checkitem1; // first item needed to see this dialog + int checkitem2; // second item needed to see this dialog, if any + int checkitem3; // third item needed to see this dialog, if any + int jumptoconv; // conversation to jump to when... ? char name[MDLG_NAMELEN]; // name of speaker char voice[MDLG_LUMPLEN]; // voice file to play char backpic[MDLG_LUMPLEN]; // backdrop pic for character, if any diff --git a/src/strife/p_enemy.c b/src/strife/p_enemy.c index 9f3fb7a6..46a31881 100644 --- a/src/strife/p_enemy.c +++ b/src/strife/p_enemy.c @@ -47,6 +47,8 @@ #include "sounds.h" +// Forward Declarations: +void A_RandomWalk(mobj_t *); typedef enum @@ -100,6 +102,8 @@ void A_Fall (mobj_t *actor); // Recursively traverse adjacent sectors, // sound blocking lines cut off traversal. // +// haleyjd 09/05/10: [STRIFE] Verified unmodified +// mobj_t* soundtarget; @@ -156,6 +160,8 @@ P_RecursiveSound // If a monster yells at a player, // it will alert other monsters to the player. // +// haleyjd 09/05/10: [STRIFE] Verified unmodified +// void P_NoiseAlert ( mobj_t* target, @@ -168,23 +174,25 @@ P_NoiseAlert // // P_WakeUpThing -// villsa [STRIFE] new function // - -static void P_WakeUpThing(mobj_t* puncher, mobj_t* rover) +// villsa [STRIFE] New function +// Wakes up an mobj.nearby when somebody has been punched. +// +static void P_WakeUpThing(mobj_t* puncher, mobj_t* bystander) { - if(!(rover->flags & MF_INCOMBAT)) + if(!(bystander->flags & MF_INCOMBAT)) { - rover->target = puncher; - if(rover->info->seesound) - S_StartSound(rover, rover->info->seesound); - P_SetMobjState(rover, rover->info->seestate); + bystander->target = puncher; + if(bystander->info->seesound) + S_StartSound(bystander, bystander->info->seesound); + P_SetMobjState(bystander, bystander->info->seestate); } } // // P_DoPunchAlert -// villsa [STRIFE] - new function +// +// villsa [STRIFE] New function (by Quasar ;) // Wake up buddies nearby when the player thinks he's gotten too clever // with the punch dagger. Walks sector links. // @@ -204,9 +212,9 @@ void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee) if(!(punchee->flags & MF_COUNTKILL) || punchee->flags & MF_INCOMBAT) return; - // wake up punchee + // make the punchee hurt - haleyjd 09/05/10: Fixed to use painstate. punchee->target = puncher; - P_SetMobjState(punchee, punchee->info->seestate); + P_SetMobjState(punchee, punchee->info->painstate); // wake up everybody nearby @@ -218,7 +226,7 @@ void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee) (P_CheckSight(rover, puncher) || P_CheckSight(rover, punchee))) { P_WakeUpThing(puncher, rover); - rover->flags |= MF_INCOMBAT; // huh? why? + rover->flags |= MF_INCOMBAT; } } @@ -230,7 +238,7 @@ void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee) (P_CheckSight(rover, puncher) || P_CheckSight(rover, punchee))) { P_WakeUpThing(puncher, rover); - rover->flags |= MF_INCOMBAT; // huh? why? + rover->flags |= MF_INCOMBAT; } } } @@ -241,14 +249,16 @@ void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee) // // P_CheckMeleeRange // +// [STRIFE] Minor change to meleerange. +// boolean P_CheckMeleeRange(mobj_t* actor) { mobj_t* pl; fixed_t dist; - + if(!actor->target) - return false; - + return false; + pl = actor->target; if(actor->z + 3 * actor->height / 2 < pl->z) // villsa [STRIFE] return false; @@ -257,81 +267,101 @@ boolean P_CheckMeleeRange(mobj_t* actor) // villsa [STRIFE] change to 36 if(dist >= MELEERANGE - 36*FRACUNIT + pl->info->radius) - return false; - + return false; + if(!P_CheckSight (actor, actor->target)) - return false; - - return true; + return false; + + return true; } // // P_CheckMissileRange // +// [STRIFE] +// Changes to eliminate DOOM-specific code and to allow for +// varying attack ranges for Strife monsters, as well as a general tweak +// to considered distance for all monsters. +// boolean P_CheckMissileRange(mobj_t* actor) { fixed_t dist; - + if(!P_CheckSight(actor, actor->target)) - return false; - + return false; + if(actor->flags & MF_JUSTHIT) { - // the target just hit the enemy, - // so fight back! - actor->flags &= ~MF_JUSTHIT; - return true; + // the target just hit the enemy, + // so fight back! + actor->flags &= ~MF_JUSTHIT; + return true; } - + if(actor->reactiontime) - return false; // do not attack yet - + return false; // do not attack yet + // OPTIMIZE: get this from a global checksight dist = P_AproxDistance(actor->x-actor->target->x, - actor->y-actor->target->y) - 64*FRACUNIT; + actor->y-actor->target->y) - 64*FRACUNIT; if (!actor->info->meleestate) - dist -= 128*FRACUNIT; // no melee attack, so fire more + dist -= 128*FRACUNIT; // no melee attack, so fire more dist >>= 16; // villsa [STRIFE] checks for acolytes - if(actor->type == MT_SHADOWGUARD || - (actor->type >= MT_GUARD1 && actor->type <= MT_GUARD6)) + // haleyjd 09/05/10: Repaired to match disassembly: Was including + // SHADOWGUARD in the wrong case, was missing MT_SENTINEL entirely. + // Structure of ASM also indicates this was probably a switch + // statement turned into a cascading if/else by the compiler. + switch(actor->type) { + case MT_GUARD1: + case MT_GUARD2: + case MT_GUARD3: + case MT_GUARD4: + case MT_GUARD5: + case MT_GUARD6: + // oddly, not all Acolytes are included here... dist >>= 4; - } - // villsa [STRIFE] check for Crusader - else if(actor->type == MT_CRUSADER) + break; + case MT_SHADOWGUARD: + case MT_CRUSADER: + case MT_SENTINEL: dist >>= 1; + break; + default: + break; + } // villsa [STRIFE] changed to 150 if (dist > 150) - dist = 150; - + dist = 150; + if (P_Random () < dist) - return false; - + return false; + return true; } // // P_CheckRobotRange -// villsa [STRIFE] new function // - +// villsa [STRIFE] New function +// boolean P_CheckRobotRange(mobj_t *actor) { fixed_t dist; if(!P_CheckSight(actor, actor->target)) - return false; + return false; if(actor->reactiontime) - return false; // do not attack yet + return false; // do not attack yet dist = (P_AproxDistance(actor->x-actor->target->x, - actor->y-actor->target->y) - 64*FRACUNIT) >> FRACBITS; + actor->y-actor->target->y) - 64*FRACUNIT) >> FRACBITS; return (dist < 200); } @@ -342,6 +372,10 @@ boolean P_CheckRobotRange(mobj_t *actor) // Move in the current direction, // returns false if the move is blocked. // +// [STRIFE] +// villsa/haleyjd 09/05/10: Modified for terrain types and 3D object +// clipping. Below constants are verified to be unmodified: +// fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; @@ -354,20 +388,20 @@ boolean P_Move (mobj_t* actor) { fixed_t tryx; fixed_t tryy; - + line_t* ld; - + // warning: 'catch', 'throw', and 'try' // are all C++ reserved words boolean try_ok; boolean good; - + if (actor->movedir == DI_NODIR) - return false; - + return false; + if ((unsigned)actor->movedir >= 8) - I_Error ("Weird actor->movedir!"); - + I_Error ("Weird actor->movedir!"); + tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; @@ -375,48 +409,49 @@ boolean P_Move (mobj_t* actor) if (!try_ok) { - // open any specials - if (actor->flags & MF_FLOAT && floatok) - { - // must adjust height - if (actor->z < tmfloorz) - actor->z += FLOATSPEED; - else - actor->z -= FLOATSPEED; - - actor->flags |= MF_INFLOAT; - return true; - } - - if (!numspechit) - return false; - - actor->movedir = DI_NODIR; - good = false; - while (numspechit--) - { - ld = spechit[numspechit]; - // if the special is not a door - // that can be opened, - // return false - if (P_UseSpecialLine (actor, ld,0)) - good = true; - } - return good; + // open any specials + if (actor->flags & MF_FLOAT && floatok) + { + // must adjust height + if (actor->z < tmfloorz) + actor->z += FLOATSPEED; // [STRIFE] Note FLOATSPEED == 5*FRACUNIT + else + actor->z -= FLOATSPEED; + + actor->flags |= MF_INFLOAT; + return true; + } + + if (!numspechit) + return false; + + actor->movedir = DI_NODIR; + good = false; + while (numspechit--) + { + ld = spechit[numspechit]; + // if the special is not a door + // that can be opened, + // return false + if (P_UseSpecialLine (actor, ld,0)) + good = true; + } + return good; } else { - actor->flags &= ~(MF_INFLOAT|MF_FEETCLIPPED); // villsa [STRIFE] + actor->flags &= ~(MF_INFLOAT|MF_FEETCLIPPED); // villsa [STRIFE] // villsa [STRIFE] if(P_GetTerrainType(actor) != FLOOR_SOLID) actor->flags |= MF_FEETCLIPPED; } - - // villsa [STRIFE] TODO - verify + + // villsa [STRIFE] Removed pulling non-floating actors down to the ground. + // (haleyjd 09/05/10: Verified) /*if (! (actor->flags & MF_FLOAT) ) - actor->z = actor->floorz;*/ + actor->z = actor->floorz;*/ return true; } @@ -433,11 +468,13 @@ boolean P_Move (mobj_t* actor) // If a door is in the way, // an OpenDoor call is made to start it opening. // +// haleyjd 09/05/10: [STRIFE] Verified unmodified. +// boolean P_TryWalk (mobj_t* actor) -{ +{ if (!P_Move (actor)) { - return false; + return false; } actor->movecount = P_Random()&15; @@ -469,7 +506,7 @@ void P_NewChaseDir(mobj_t* actor) P_SetMobjState(actor, actor->info->spawnstate); return; } - + olddir = actor->movedir; turnaround=opposite[olddir]; @@ -477,107 +514,107 @@ void P_NewChaseDir(mobj_t* actor) deltay = actor->target->y - actor->y; if (deltax>10*FRACUNIT) - d[1]= DI_EAST; + d[1]= DI_EAST; else if (deltax<-10*FRACUNIT) - d[1]= DI_WEST; + d[1]= DI_WEST; else - d[1]=DI_NODIR; + d[1]=DI_NODIR; if (deltay<-10*FRACUNIT) - d[2]= DI_SOUTH; + d[2]= DI_SOUTH; else if (deltay>10*FRACUNIT) - d[2]= DI_NORTH; + d[2]= DI_NORTH; else - d[2]=DI_NODIR; + d[2]=DI_NODIR; // try direct route if (d[1] != DI_NODIR - && d[2] != DI_NODIR) + && d[2] != DI_NODIR) { - actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; - if (actor->movedir != (int) turnaround && P_TryWalk(actor)) - return; + actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; + if (actor->movedir != (int) turnaround && P_TryWalk(actor)) + return; } // try other directions if (P_Random() > 200 - || abs(deltay)>abs(deltax)) + || abs(deltay)>abs(deltax)) { - tdir=d[1]; - d[1]=d[2]; - d[2]=tdir; + tdir=d[1]; + d[1]=d[2]; + d[2]=tdir; } if (d[1]==turnaround) - d[1]=DI_NODIR; + d[1]=DI_NODIR; if (d[2]==turnaround) - d[2]=DI_NODIR; - + d[2]=DI_NODIR; + if (d[1]!=DI_NODIR) { - actor->movedir = d[1]; - if (P_TryWalk(actor)) - { - // either moved forward or attacked - return; - } + actor->movedir = d[1]; + if (P_TryWalk(actor)) + { + // either moved forward or attacked + return; + } } if (d[2]!=DI_NODIR) { - actor->movedir =d[2]; + actor->movedir =d[2]; - if (P_TryWalk(actor)) - return; + if (P_TryWalk(actor)) + return; } // there is no direct path to the player, // so pick another direction. if (olddir!=DI_NODIR) { - actor->movedir =olddir; + actor->movedir =olddir; - if (P_TryWalk(actor)) - return; + if (P_TryWalk(actor)) + return; } // randomly determine direction of search if (P_Random()&1) { - for ( tdir=DI_EAST; - tdir<=DI_SOUTHEAST; - tdir++ ) - { - if (tdir != (int) turnaround) - { - actor->movedir =tdir; - - if ( P_TryWalk(actor) ) - return; - } - } + for ( tdir=DI_EAST; + tdir<=DI_SOUTHEAST; + tdir++ ) + { + if (tdir != (int) turnaround) + { + actor->movedir =tdir; + + if ( P_TryWalk(actor) ) + return; + } + } } else { - for ( tdir=DI_SOUTHEAST; - tdir != (DI_EAST-1); - tdir-- ) - { - if (tdir != (int) turnaround) - { - actor->movedir = tdir; - - if ( P_TryWalk(actor) ) - return; - } - } + for ( tdir=DI_SOUTHEAST; + tdir != (DI_EAST-1); + tdir-- ) + { + if (tdir != (int) turnaround) + { + actor->movedir = tdir; + + if ( P_TryWalk(actor) ) + return; + } + } } if (turnaround != DI_NODIR) { - actor->movedir =turnaround; - if ( P_TryWalk(actor) ) - return; + actor->movedir =turnaround; + if ( P_TryWalk(actor) ) + return; } actor->movedir = DI_NODIR; // can not move @@ -585,13 +622,20 @@ void P_NewChaseDir(mobj_t* actor) // // P_NewRandomDir +// // villsa [STRIFE] new function // - +// haleyjd: Almost identical to the tail-end of P_NewChaseDir, this function +// finds a purely random direction for an object to walk. Called from +// A_RandomWalk. +// +// Shockingly similar to the RandomWalk pointer in Eternity :) +// void P_NewRandomDir(mobj_t* actor) { int dir = 0; + // randomly determine direction of search if(P_Random() & 1) { for(dir = 0; dir < DI_NODIR; dir++) @@ -612,11 +656,16 @@ void P_NewRandomDir(mobj_t* actor) dir = DI_SOUTHEAST; while(1) { + // haleyjd 09/05/10: P_TryWalk -> P_Move, missing random code. if(dir != opposite[actor->movedir]) { actor->movedir = dir; - if(P_TryWalk(actor)) - break; + + if(P_Move(actor)) + { + actor->movecount = P_Random() & 15; + return; + } } if(--dir == -1) @@ -628,120 +677,150 @@ void P_NewRandomDir(mobj_t* actor) } actor->movedir = opposite[actor->movedir]; - if(!P_TryWalk(actor)) + if(P_Move(actor)) + { + actor->movecount = P_Random() & 15; + return; + } + else { actor->movedir = DI_NODIR; return; } - } - } - } + } // end if(--dir == -1) + } // end while(1) + } // end else } +// haleyjd 09/05/10: Needed below. +extern void P_BulletSlope (mobj_t *mo); +#define LOCAL_MELEERANGE 64*FRACUNIT // // P_LookForPlayers +// // If allaround is false, only look 180 degrees in front. // Returns true if a player is targeted. // +// [STRIFE] +// haleyjd 09/05/10: Modifications to support friendly units. +// boolean P_LookForPlayers ( mobj_t* actor, boolean allaround ) { - int c; - int stop; - player_t* player; - sector_t* sector; - angle_t an; - fixed_t dist; - + int c; + int stop; + player_t* player; + sector_t* sector; + angle_t an; + fixed_t dist; + mobj_t * master = players[actor->allegiance].mo; + + // haleyjd 09/05/10: handle Allies + if(actor->flags & MF_ALLY) + { + // Deathmatch: support team behavior for Rebels. + if(netgame) + { + // Rebels adopt the allied player's target if it is not of the same + // allegiance. Other allies do it unconditionally. + if(master && master->target && + (master->target->type != MT_REBEL1 || + master->target->allegiance != actor->allegiance)) + { + actor->target = master->target; + } + else + { + P_BulletSlope(actor); + + // Clear target if nothing is visible, or if the target is a + // friendly Rebel or the allied player. + if(!linetarget || + actor->target->target == MT_REBEL1 && + actor->target->allegiance == actor->allegiance || + actor->target == master) + { + actor->target = NULL; + return false; + } + } + } + else + { + // Single-player: Adopt any non-allied player target. + if(master && master->target && !(master->target->flags & MF_ALLY)) + { + actor->target = master->target; + return true; + } + + P_BulletSlope(actor); + + // Clear target if nothing is visible, or if the target is an ally. + if(!linetarget || actor->target->flags & MF_ALLY) + { + actor->target = NULL; + return false; + } + } + + return true; + } + sector = actor->subsector->sector; - + c = 0; stop = (actor->lastlook-1)&3; - + for ( ; ; actor->lastlook = (actor->lastlook+1)&3 ) { - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2 - || actor->lastlook == stop) - { - // done looking - return false; - } - - player = &players[actor->lastlook]; + if (!playeringame[actor->lastlook]) + continue; - if (player->health <= 0) - continue; // dead + if (c++ == 2 + || actor->lastlook == stop) + { + // done looking + return false; + } - if (!P_CheckSight (actor, player->mo)) - continue; // out of sight - - if (!allaround) - { - an = R_PointToAngle2 (actor->x, - actor->y, - player->mo->x, - player->mo->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - dist = P_AproxDistance (player->mo->x - actor->x, - player->mo->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - - actor->target = player->mo; - return true; - } + player = &players[actor->lastlook]; - return false; -} + if (player->health <= 0) + continue; // dead + if (!P_CheckSight (actor, player->mo)) + continue; // out of sight -// -// A_KeenDie -// DOOM II special, map 32. -// Uses special tag 666. -// -void A_KeenDie (mobj_t* mo) -{ - thinker_t* th; - mobj_t* mo2; - line_t junk; + if (!allaround) + { + an = R_PointToAngle2(actor->x, + actor->y, + player->mo->x, + player->mo->y) - actor->angle; - A_Fall (mo); - - // scan the remaining thinkers - // to see if all Keens are dead - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; + if (an > ANG90 && an < ANG270) + { + dist = P_AproxDistance (player->mo->x - actor->x, + player->mo->y - actor->y); + // if real close, react anyway + if (dist > LOCAL_MELEERANGE) // haleyjd: ...... + continue; // behind back + } + } - mo2 = (mobj_t *)th; - if (mo2 != mo - && mo2->type == mo->type - && mo2->health > 0) - { - // other Keen not dead - return; - } + actor->target = player->mo; + return true; } - junk.tag = 666; - EV_DoDoor(&junk,open); + return false; } +// haleyjd 09/05/10: [STRIFE] Removed A_KeenDie // // ACTION ROUTINES @@ -751,178 +830,308 @@ void A_KeenDie (mobj_t* mo) // A_Look // Stay in state until a player is sighted. // +// [STRIFE] +// haleyjd 09/05/10: Adjusted for allies, Inquisitors, etc. +// void A_Look (mobj_t* actor) { - mobj_t* targ; - - actor->threshold = 0; // any shot will wake up + mobj_t* targ; + + actor->threshold = 0; // any shot will wake up targ = actor->subsector->sector->soundtarget; if (targ - && (targ->flags & MF_SHOOTABLE) ) + && (targ->flags & MF_SHOOTABLE) ) { - actor->target = targ; + // [STRIFE] Allies wander when they call this. + if(actor->flags & MF_ALLY) + A_RandomWalk(actor); + else + { + actor->target = targ; - if ( actor->flags & MF_AMBUSH ) - { - if (P_CheckSight (actor, actor->target)) - goto seeyou; - } - else - goto seeyou; + if ( actor->flags & MF_AMBUSH ) + { + if (P_CheckSight (actor, actor->target)) + goto seeyou; + } + else + goto seeyou; + } } - - - if (!P_LookForPlayers (actor, false) ) - return; - + + // haleyjd 09/05/10: This is bizarre, as Rogue keeps using the GIVEQUEST flag + // as a parameter to control allaround look behavior. Did they just run out of + // flags, or what? + // STRIFE-TODO: Needs serious verification. + if (!P_LookForPlayers (actor, actor->flags & MF_GIVEQUEST) ) + return; + // go into chase state - seeyou: +seeyou: if (actor->info->seesound) { - int sound; - - switch (actor->info->seesound) - { - case sfx_pespna: // villsa [STRIFE] TODO - fix sounds - case sfx_pespnb: // villsa [STRIFE] TODO - fix sounds - case sfx_pespnc: // villsa [STRIFE] TODO - fix sounds - sound = sfx_pespna+P_Random()%3; // villsa [STRIFE] TODO - fix sounds - break; + int sound = actor->info->seesound; + mobj_t * emitter = actor; - case sfx_agrac1: // villsa [STRIFE] TODO - fix sounds - case sfx_agrac2: // villsa [STRIFE] TODO - fix sounds - sound = sfx_agrac1+P_Random()%2; // villsa [STRIFE] TODO - fix sounds - break; + // [STRIFE] Removed DOOM random sounds. - default: - sound = actor->info->seesound; - break; - } + // [STRIFE] Only Inquisitors roar loudly here. + if (actor->type == MT_INQUISITOR) + emitter = NULL; - // villsa [STRIFE] TODO replace with proper strife bosses - /*if (actor->type==MT_SPIDER - || actor->type == MT_CYBORG) - { - // full volume - S_StartSound (NULL, sound); - } - else*/ - S_StartSound (actor, sound); + S_StartSound (emitter, sound); } + // [STRIFE] Set threshold (kinda odd as it's still set to 0 above...) + actor->threshold = 20; + P_SetMobjState (actor, actor->info->seestate); } +// +// A_RandomWalk +// +// [STRIFE] New function. +// haleyjd 09/05/10: Action routine used to meander about. +// +void A_RandomWalk(mobj_t* actor) +{ + // Standing actors do not wander. + if(actor->flags & MF_STAND) + return; + + if(actor->reactiontime) + actor->reactiontime--; // count down reaction time + else + { + // turn to a new angle + if(actor->movedir < DI_NODIR) + { + int delta; + + actor->angle &= (7 << 29); + delta = actor->angle - (actor->movedir << 29); + + if(delta < 0) + actor->angle += ANG90/2; + else if(delta > 0) + actor->angle -= ANG90/2; + } + + // try moving + if(--actor->movecount < 0 || !P_Move(actor)) + { + P_NewRandomDir(actor); + actor->movecount += 5; + } + } +} + +// +// A_FriendLook +// +// [STRIFE] New function +// haleyjd 09/05/10: Action function used mostly by mundane characters such as +// peasants. +// +void A_FriendLook(mobj_t* actor) +{ + mobj_t *soundtarget = actor->subsector->sector->soundtarget; + + actor->threshold = 0; + + if(soundtarget && soundtarget->flags & MF_SHOOTABLE) + { + // Handle allies, except on maps 3 and 34 (Front Base/Movement Base) + if((actor->flags & MF_ALLY) == (soundtarget->flags & MF_ALLY) && + gamemap != 3 && gamemap != 34) + { + // STRIFE-TODO: Needs serious verification. + if(P_LookForPlayers(actor, actor->flags & MF_GIVEQUEST)) + { + P_SetMobjState(actor, actor->info->seestate); + actor->flags |= MF_INCOMBAT; + return; + } + } + else + { + actor->target = soundtarget; + + if(!(actor->flags & MF_AMBUSH) || P_CheckSight(actor, actor->target)) + { + actor->threshold = 10; + P_SetMobjState(actor, actor->info->seestate); + return; + } + } + } + + // do some idle animation + if(P_Random() < 30) + P_SetMobjState(actor, actor->info->spawnstate + 1 + (P_Random() & 1)); + + // wander around a bit + if(!(actor->flags & MF_STAND) && P_Random() < 40) + P_SetMobjState(actor, actor->info->spawnstate + 3); +} + +// +// A_Listen +// +// [STRIFE] New function +// haleyjd 09/05/10: Action routine used to strictly listen for a target. +// +void A_Listen(mobj_t* actor) +{ + mobj_t *soundtarget; + + actor->threshold = 0; + + soundtarget = actor->subsector->sector->soundtarget; + + if(soundtarget && soundtarget->flags & MF_SHOOTABLE) + { + if(actor->flags & MF_ALLY != soundtarget->flags & MF_ALLY) + { + actor->target = soundtarget; + + if(!(actor->flags & MF_AMBUSH) || P_CheckSight(actor, actor->target)) + { + if(actor->info->seesound) + S_StartSound(actor, actor->info->seesound); + + actor->threshold = 10; + + P_SetMobjState(actor, actor->info->seestate); + } + } + } +} + // // A_Chase // Actor has a melee attack, // so it tries to close as fast as possible // +// haleyjd 09/05/10: [STRIFE] Various minor changes +// void A_Chase (mobj_t* actor) { - int delta; + int delta; if (actor->reactiontime) - actor->reactiontime--; - + actor->reactiontime--; // modify target threshold if (actor->threshold) { - if (!actor->target - || actor->target->health <= 0) - { - actor->threshold = 0; - } - else - actor->threshold--; + if (!actor->target + || actor->target->health <= 0) + { + actor->threshold = 0; + } + else + actor->threshold--; } // turn towards movement direction if not there yet if (actor->movedir < 8) { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANG90/2; - else if (delta < 0) - actor->angle += ANG90/2; + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANG90/2; + else if (delta < 0) + actor->angle += ANG90/2; } if (!actor->target - || !(actor->target->flags&MF_SHOOTABLE)) + || !(actor->target->flags&MF_SHOOTABLE)) { - // look for a new target - if (P_LookForPlayers(actor,true)) - return; // got a new target - - P_SetMobjState (actor, actor->info->spawnstate); - return; + // look for a new target + if (P_LookForPlayers(actor,true)) + return; // got a new target + + P_SetMobjState (actor, actor->info->spawnstate); + return; } // do not attack twice in a row if (actor->flags & MF_JUSTATTACKED) { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare && !fastparm) - P_NewChaseDir (actor); - return; + actor->flags &= ~MF_JUSTATTACKED; + // [STRIFE] Checks only against fastparm, not gameskill == 5 + if (!fastparm) + P_NewChaseDir (actor); + return; } // check for melee attack if (actor->info->meleestate - && P_CheckMeleeRange (actor)) + && P_CheckMeleeRange (actor)) { - if (actor->info->attacksound) - S_StartSound (actor, actor->info->attacksound); + if (actor->info->attacksound) + S_StartSound (actor, actor->info->attacksound); - P_SetMobjState (actor, actor->info->meleestate); - return; + P_SetMobjState (actor, actor->info->meleestate); + return; } // check for missile attack if (actor->info->missilestate) { - if (gameskill < sk_nightmare - && !fastparm && actor->movecount) - { - goto nomissile; - } - - if (!P_CheckMissileRange (actor)) - goto nomissile; - - P_SetMobjState (actor, actor->info->missilestate); - actor->flags |= MF_JUSTATTACKED; - return; + // [STRIFE] Checks only fastparm. + if (!fastparm && actor->movecount) + { + goto nomissile; + } + + if (!P_CheckMissileRange (actor)) + goto nomissile; + + P_SetMobjState (actor, actor->info->missilestate); + + // [STRIFE] Add INCOMBAT flag to disable dialog + actor->flags |= (MF_INCOMBAT|MF_JUSTATTACKED); + return; } // ? - nomissile: +nomissile: // possibly choose another target if (netgame - && !actor->threshold - && !P_CheckSight (actor, actor->target) ) + && !actor->threshold + && !P_CheckSight (actor, actor->target) ) { - if (P_LookForPlayers(actor,true)) - return; // got a new target + if (P_LookForPlayers(actor,true)) + return; // got a new target } // chase towards player if (--actor->movecount<0 - || !P_Move (actor)) + || !P_Move (actor)) { - P_NewChaseDir (actor); + P_NewChaseDir (actor); } - + + // [STRIFE] Changes to active sound behavior: + // * Significantly more frequent + // * Acolytes have randomized wandering sounds + // make active sound - if (actor->info->activesound - && P_Random () < 3) + if (actor->info->activesound && P_Random () < 38) { - S_StartSound (actor, actor->info->activesound); + if(actor->info->activesound >= sfx_agrac1 && + actor->info->activesound <= sfx_agrac4) + { + S_StartSound(actor, sfx_agrac1 + P_Random() % 4); + } + else + S_StartSound (actor, actor->info->activesound); } } @@ -930,20 +1139,34 @@ void A_Chase (mobj_t* actor) // // A_FaceTarget // +// [STRIFE] +// haleyjd 09/05/10: Modified handling for various visibility +// modifying flags. +// void A_FaceTarget (mobj_t* actor) { if (!actor->target) - return; - + return; + actor->flags &= ~MF_AMBUSH; - + actor->angle = R_PointToAngle2 (actor->x, - actor->y, - actor->target->x, - actor->target->y); - - if (actor->target->flags & MF_SHADOW) - actor->angle += (P_Random()-P_Random())<<21; + actor->y, + actor->target->x, + actor->target->y); + + if(actor->target->flags & MF_SHADOW) + { + // [STRIFE] increased SHADOW inaccuracy by a power of 2 + int t = P_Random(); + actor->angle += (t - P_Random()) << 22; + } + else if(actor->target->flags & MF_MVIS) + { + // [STRIFE] MVIS gives even worse aiming! + int t = P_Random(); + actor->angle += (t - P_Random()) << 23; + } } @@ -2189,20 +2412,6 @@ void A_PlayerScream (mobj_t* mo) S_StartSound (mo, sound); } -void A_RandomWalk(mobj_t* actor) -{ - -} - -void A_FriendLook(mobj_t* actor) -{ - -} - -void A_Listen(mobj_t* actor) -{ - -} void A_PeasantPunch(mobj_t* actor) { diff --git a/src/strife/p_map.c b/src/strife/p_map.c index 4897d164..f83851cf 100644 --- a/src/strife/p_map.c +++ b/src/strife/p_map.c @@ -1234,11 +1234,11 @@ P_LineAttack shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; attackrange = distance; aimslope = slope; - - P_PathTraverse ( t1->x, t1->y, - x2, y2, - PT_ADDLINES|PT_ADDTHINGS, - PTR_ShootTraverse ); + + P_PathTraverse(t1->x, t1->y, + x2, y2, + PT_ADDLINES|PT_ADDTHINGS, + PTR_ShootTraverse); } diff --git a/src/strife/p_mobj.c b/src/strife/p_mobj.c index 5f7e258a..d2c2e5de 100644 --- a/src/strife/p_mobj.c +++ b/src/strife/p_mobj.c @@ -836,16 +836,16 @@ void P_SpawnMapThing (mapthing_t* mthing) fixed_t x; fixed_t y; fixed_t z; - + // count deathmatch start positions if (mthing->type == 11) { - if (deathmatch_p < &deathmatchstarts[10]) - { - memcpy (deathmatch_p, mthing, sizeof(*mthing)); - deathmatch_p++; - } - return; + if (deathmatch_p < &deathmatchstarts[10]) + { + memcpy (deathmatch_p, mthing, sizeof(*mthing)); + deathmatch_p++; + } + return; } if (mthing->type <= 0) @@ -855,36 +855,37 @@ void P_SpawnMapThing (mapthing_t* mthing) return; } - + // check for players specially + // STRIFE-TODO: Need 8 player starts if (mthing->type <= 4) { - // save spots for respawning in network games - playerstarts[mthing->type-1] = *mthing; - if (!deathmatch) - P_SpawnPlayer (mthing); + // save spots for respawning in network games + playerstarts[mthing->type-1] = *mthing; + if (!deathmatch) + P_SpawnPlayer (mthing); - return; + return; } // check for apropriate skill level if (!netgame && (mthing->options & 16) ) - return; - + return; + if (gameskill == sk_baby) - bit = 1; + bit = 1; else if (gameskill == sk_nightmare) - bit = 4; + bit = 4; else - bit = 1<<(gameskill-1); + bit = 1<<(gameskill-1); if (!(mthing->options & bit) ) return; // find which type to spawn for (i=0 ; i< NUMMOBJTYPES ; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; + if (mthing->type == mobjinfo[i].doomednum) + break; /* if (i==NUMMOBJTYPES) @@ -895,43 +896,48 @@ void P_SpawnMapThing (mapthing_t* mthing) // haleyjd 08/29/10: STRIFE-FIXME: Temporarily disabled I_Error for testing purposes if (i == NUMMOBJTYPES) return; - + // don't spawn keycards and players in deathmatch if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) - return; + return; // don't spawn any monsters if -nomonsters - if (nomonsters - && ( /*i == MT_SKULL // villsa [STRIFE] unused - ||*/ (mobjinfo[i].flags & MF_COUNTKILL)) ) - { - return; - } + // villsa [STRIFE] Removed MT_SKULL + if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) + return; // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; if (mobjinfo[i].flags & MF_SPAWNCEILING) - z = ONCEILINGZ; + z = ONCEILINGZ; else - z = ONFLOORZ; + z = ONFLOORZ; mobj = P_SpawnMobj (x,y,z, i); mobj->spawnpoint = *mthing; if (mobj->tics > 0) - mobj->tics = 1 + (P_Random () % mobj->tics); + mobj->tics = 1 + (P_Random () % mobj->tics); if (mobj->flags & MF_COUNTKILL) - totalkills++; + totalkills++; // villsa [STRIFE] unused /*if (mobj->flags & MF_COUNTITEM) - totalitems++;*/ - + totalitems++;*/ + mobj->angle = ANG45 * (mthing->angle/45); if (mthing->options & MTF_AMBUSH) - mobj->flags |= MF_AMBUSH; + mobj->flags |= MF_AMBUSH; + if (mthing->options & MTF_STAND) // [STRIFE] Standing mode, for NPCs + mobj->flags |= MF_STAND; + if (mthing->options & MTF_FRIEND) // [STRIFE] Allies + mobj->flags |= MF_ALLY; + if (mthing->options & MTF_TRANSLUCENT) // [STRIFE] Translucent object + mobj->flags |= MF_SHADOW; + if (mthing->options & MTF_MVIS) // [STRIFE] Alt. Translucency + mobj->flags |= MF_MVIS; } @@ -1090,7 +1096,7 @@ P_SpawnMissile if (dest->flags & MF_SHADOW) an += (P_Random()-P_Random())<<21; // villsa [STRIFE] check for heavily transparent things - else if(dest->flags & MF_MOREVISIBLE) + else if(dest->flags & MF_MVIS) an += (P_Random()-P_Random())<<22; th->angle = an; @@ -1134,7 +1140,7 @@ mobj_t* P_SpawnFacingMissile(mobj_t* source, mobj_t* target, mobjtype_t type) if (target->flags & MF_SHADOW) an += (P_Random()-P_Random())<<21; // villsa [STRIFE] check for heavily transparent things - else if(target->flags & MF_MOREVISIBLE) + else if(target->flags & MF_MVIS) an += (P_Random()-P_Random())<<22; th->angle = an; diff --git a/src/strife/p_mobj.h b/src/strife/p_mobj.h index 38c04075..67c1c35d 100644 --- a/src/strife/p_mobj.h +++ b/src/strife/p_mobj.h @@ -213,8 +213,8 @@ typedef enum // villsa [STRIFE] friendly towards player with matching flag MF_ALLY = 0x4000000, - // villsa [STRIFE] 75% transparency? - MF_MOREVISIBLE = 0x8000000, + // villsa [STRIFE] 75% transparency? -- NEEDS VERIFICATION + MF_MVIS = 0x8000000, // villsa [STRIFE] color translation MF_COLORSWAP1 = 0x10000000, @@ -242,84 +242,92 @@ typedef enum // Map Object definition. +// +// [STRIFE]: Amazingly, only one modification was made to mobj_t over DOOM +// 1.666, and that was the addition of the single-byte allegiance field for +// tracking with which player friendly monsters are allied. +// typedef struct mobj_s { // List: thinker links. - thinker_t thinker; + thinker_t thinker; // Info for drawing: position. - fixed_t x; - fixed_t y; - fixed_t z; + fixed_t x; + fixed_t y; + fixed_t z; // More list: links in sector (if needed) - struct mobj_s* snext; - struct mobj_s* sprev; + struct mobj_s* snext; + struct mobj_s* sprev; //More drawing info: to determine current sprite. - angle_t angle; // orientation - spritenum_t sprite; // used to find patch_t and flip value - int frame; // might be ORed with FF_FULLBRIGHT + angle_t angle; // orientation + spritenum_t sprite; // used to find patch_t and flip value + int frame; // might be ORed with FF_FULLBRIGHT // Interaction info, by BLOCKMAP. // Links in blocks (if needed). - struct mobj_s* bnext; - struct mobj_s* bprev; + struct mobj_s* bnext; + struct mobj_s* bprev; - struct subsector_s* subsector; + struct subsector_s* subsector; // The closest interval over all contacted Sectors. - fixed_t floorz; - fixed_t ceilingz; + fixed_t floorz; + fixed_t ceilingz; // For movement checking. - fixed_t radius; - fixed_t height; + fixed_t radius; + fixed_t height; // Momentums, used to update position. - fixed_t momx; - fixed_t momy; - fixed_t momz; + fixed_t momx; + fixed_t momy; + fixed_t momz; // If == validcount, already checked. - int validcount; + int validcount; - mobjtype_t type; - mobjinfo_t* info; // &mobjinfo[mobj->type] + mobjtype_t type; + mobjinfo_t* info; // &mobjinfo[mobj->type] - int tics; // state tic counter - state_t* state; - int flags; - int health; + int tics; // state tic counter + state_t* state; + int flags; + int health; // Movement direction, movement generation (zig-zagging). - int movedir; // 0-7 - int movecount; // when 0, select a new dir + int movedir; // 0-7 + int movecount; // when 0, select a new dir // Thing being chased/attacked (or NULL), // also the originator for missiles. - struct mobj_s* target; + struct mobj_s* target; // Reaction time: if non 0, don't attack yet. // Used by player to freeze a bit after teleporting. - int reactiontime; + int reactiontime; // If >0, the target will be chased // no matter what (even if shot) - int threshold; + int threshold; // Additional info record for player avatars only. // Only valid if type == MT_PLAYER - struct player_s* player; + struct player_s* player; // Player number last looked for. - int lastlook; + int lastlook; // For nightmare respawn. - mapthing_t spawnpoint; + mapthing_t spawnpoint; // Thing being chased/attacked for tracers. - struct mobj_s* tracer; + struct mobj_s* tracer; + + // [STRIFE] haleyjd 09/05/10: allegiance, for friends and teleport beacons + byte allegiance; } mobj_t; diff --git a/src/strife/p_pspr.c b/src/strife/p_pspr.c index 6696e153..55264a20 100644 --- a/src/strife/p_pspr.c +++ b/src/strife/p_pspr.c @@ -644,7 +644,7 @@ void A_FirePoisonBolt(player_t* player, pspdef_t* pspr) fixed_t bulletslope; -void P_BulletSlope (mobj_t* mo) +void P_BulletSlope (mobj_t *mo) { angle_t an; diff --git a/src/strife/p_setup.c b/src/strife/p_setup.c index eeefe2dc..652d86df 100644 --- a/src/strife/p_setup.c +++ b/src/strife/p_setup.c @@ -342,6 +342,7 @@ void P_LoadThings (int lump) // Do not spawn cool, new monsters if !commercial // STRIFE-TODO: replace with isregistered stuff + /* if (gamemode != commercial) { switch (SHORT(mt->type)) @@ -362,6 +363,7 @@ void P_LoadThings (int lump) } if (spawn == false) break; + */ // Do spawn all other stuff. spawnthing.x = SHORT(mt->x); diff --git a/src/strife/p_tick.c b/src/strife/p_tick.c index 9429cf20..55e893ab 100644 --- a/src/strife/p_tick.c +++ b/src/strife/p_tick.c @@ -94,8 +94,6 @@ void P_AllocateThinker (thinker_t* thinker) { } - - // // P_RunThinkers // @@ -122,8 +120,6 @@ void P_RunThinkers (void) } } - - // // P_Ticker // diff --git a/src/strife/r_draw.c b/src/strife/r_draw.c index 9d0882d9..b8adbf9b 100644 --- a/src/strife/r_draw.c +++ b/src/strife/r_draw.c @@ -547,7 +547,7 @@ byte *xlatab; void R_InitTranslationTables (void) { int i; - int j; + byte col1, col2; // [STRIFE] Load xlatab. Here's how Rogue did it: // v7 = W_CacheLumpName("XLATAB", PU_CACHE); // note potential cache bug... @@ -567,18 +567,21 @@ void R_InitTranslationTables (void) // villsa [STRIFE] allocate a larger size for translation tables translationtables = Z_Malloc (256*8, PU_STATIC, 0); + col1 = 0xFA; + col2 = 0xE0; + // villsa [STRIFE] setup all translation tables - for(i = 0, j = -6; i < 256; i++, j++) + for(i = 0; i < 256; i++) { - if(i >= 0x80 && i<= 0x8f) + if(i >= 0x80 && i <= 0x8f) { - translationtables [i ] = (i & 0xf) + 64; - translationtables [i+ 256] = (i & 0xf) - 80; - translationtables [i+2*256] = (i & 0xf) + 16; - translationtables [i+3*256] = (i & 0xf) + 48; - translationtables [i+4*256] = (i & 0xf) + 80; - translationtables [i+5*256] = (i & 0xf) + 96; - translationtables [i+6*256] = (i & 0xf) - 112; + translationtables [i ] = (i & 0x0f) + 64; + translationtables [i+ 256] = (i & 0x0f) - 80; + translationtables [i+2*256] = (i & 0x0f) + 16; + translationtables [i+3*256] = (i & 0x0f) + 48; + translationtables [i+4*256] = (i & 0x0f) + 80; + translationtables [i+5*256] = (i & 0x0f) + 96; + translationtables [i+6*256] = (i & 0x0f) - 112; } else if(i >= 0x50 && i<= 0x5f) @@ -587,9 +590,9 @@ void R_InitTranslationTables (void) translationtables [i+ 256] = i; translationtables [i+2*256] = i; translationtables [i+3*256] = i; - translationtables [i+4*256] = (i & 0xf) + -128; - translationtables [i+5*256] = (i & 0xf) + 16; - translationtables [i+6*256] = (i & 0xf) + 64; + translationtables [i+4*256] = (i & 0x0f) + -128; + translationtables [i+5*256] = (i & 0x0f) + 16; + translationtables [i+6*256] = (i & 0x0f) + 64; } else if(i >= 0xd0 && i<= 0xdf) { @@ -597,9 +600,9 @@ void R_InitTranslationTables (void) translationtables [i+ 256] = i; translationtables [i+2*256] = i; translationtables [i+3*256] = i; - translationtables [i+4*256] = (i & 0xf) - 80; - translationtables [i+5*256] = (i & 0xf) + 48; - translationtables [i+6*256] = (i & 0xf) + 16; + translationtables [i+4*256] = (i & 0x0f) - 80; + translationtables [i+5*256] = (i & 0x0f) + 48; + translationtables [i+6*256] = (i & 0x0f) + 16; } else if(i >= 0xc0 && i<= 0xcf) { @@ -607,13 +610,13 @@ void R_InitTranslationTables (void) translationtables [i+ 256] = i; translationtables [i+2*256] = i; translationtables [i+3*256] = i; - translationtables [i+4*256] = (i & 0xf) - 96; - translationtables [i+5*256] = (i & 0xf) + 32; - translationtables [i+6*256] = (i & 0xf); + translationtables [i+4*256] = (i & 0x0f) - 96; + translationtables [i+5*256] = (i & 0x0f) + 32; + translationtables [i+6*256] = (i & 0x0f); } else if(i >= 0xf7 && i<= 0xfb) { - translationtables [i ] = j; + translationtables [i ] = col1; translationtables [i+ 256] = i; translationtables [i+2*256] = i; translationtables [i+3*256] = i; @@ -623,7 +626,7 @@ void R_InitTranslationTables (void) } else if(i >= 0xf1 && i<= 0xf6) { - translationtables [i ] = (i & 0xf) - 33; + translationtables [i ] = (i & 0x0f) - 33; translationtables [i+ 256] = i; translationtables [i+2*256] = i; translationtables [i+3*256] = i; @@ -633,13 +636,13 @@ void R_InitTranslationTables (void) } else if(i >= 0x20 && i<= 0x40) { - translationtables [i ] = i; - translationtables [i+ 256] = i; - translationtables [i+2*256] = (i & 0xf) - 48; - translationtables [i+3*256] = (i & 0xf) - 48; - translationtables [i+4*256] = i; - translationtables [i+5*256] = i; - translationtables [i+6*256] = i; + translationtables [i ] = col2; + translationtables [i+ 256] = col2; + translationtables [i+2*256] = (i & 0x0f) - 48; + translationtables [i+3*256] = (i & 0x0f) - 48; + translationtables [i+4*256] = col2; + translationtables [i+5*256] = col2; + translationtables [i+6*256] = col2; } else // Keep all other colors as is. { @@ -651,6 +654,9 @@ void R_InitTranslationTables (void) translationtables[i+5*256]= translationtables[i+6*256]=i; } + + ++col1; + ++col2; } } -- cgit v1.2.3