shithub: choc

Download patch

ref: f7768ad7dcfbefce525d846ce2f565dacf99f546
parent: cb79caae119fe361d0c5835ae91a9a1f0bf8147f
author: James Haley <haleyjd@hotmail.com>
date: Sun Sep 5 19:28:16 EDT 2010

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

--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -498,7 +498,7 @@
 	{
 	    TryRunTics (); // will run at least one tic
 	}
-		
+
 	S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
 
 	// Update display, next frame, with current state.
--- a/src/strife/d_net.c
+++ b/src/strife/d_net.c
@@ -604,6 +604,7 @@
 	    G_Ticker ();
 	    gametic++;
 	    
+
 	    // modify command for duplicated tics
 	    if (i != ticdup-1)
 	    {
--- a/src/strife/doomdef.h
+++ b/src/strife/doomdef.h
@@ -79,9 +79,9 @@
 //
 
 // 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 @@
 // 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
 
 
 
--- a/src/strife/doomstat.h
+++ b/src/strife/doomstat.h
@@ -141,6 +141,8 @@
 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?
 
 
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -493,7 +493,6 @@
              cmd->buttons |= BT_ATTACK;
          else
              --mouse_fire_countdown;
-
     }
  
     if (gamekeydown[key_use]
@@ -816,9 +815,7 @@
  
     return false; 
 } 
- 
- 
- 
+
 //
 // G_Ticker
 // Make ticcmd_ts for the players.
@@ -828,7 +825,7 @@
     int		i;
     int		buf; 
     ticcmd_t*	cmd;
-    
+
     // do player reborns if needed
     for (i=0 ; i<MAXPLAYERS ; i++) 
 	if (playeringame[i] && players[i].playerstate == PST_REBORN) 
@@ -885,9 +882,9 @@
  
 	    memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t)); 
  
-	    if (demoplayback) 
+	    if (demoplayback)
 		G_ReadDemoTiccmd (cmd); 
-	    if (demorecording) 
+	    if (demorecording)
 		G_WriteDemoTiccmd (cmd);
 	    
 	    // check for turbo cheats
--- a/src/strife/info.c
+++ b/src/strife/info.c
@@ -3570,7 +3570,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
@@ -3653,7 +3653,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
@@ -3682,7 +3682,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
@@ -3711,7 +3711,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
@@ -3740,7 +3740,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
@@ -3769,7 +3769,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
@@ -3798,7 +3798,7 @@
         sfx_alnact,     //activesound
         MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST
         |MF_FLOAT|MF_INCOMBAT|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH
-        |MF_MOREVISIBLE|MF_SPECTRAL,        //flags
+        |MF_MVIS|MF_SPECTRAL,        //flags
         NULL,       //namepointer
     },
 
--- a/src/strife/m_menu.c
+++ b/src/strife/m_menu.c
@@ -125,7 +125,9 @@
 
 boolean                 inhelpscreens;
 boolean                 menuactive;
-boolean                 menupause; // haleyjd 08/29/10: [STRIFE] New global
+boolean                 menupause;     // haleyjd 08/29/10: [STRIFE] New global
+int                     menupausetime; // haleyjd 09/04/10: [STRIFE] New global
+boolean                 menuindialog;  // haleyjd 09/04/10: ditto
 
 // haleyjd 08/27/10: [STRIFE] SKULLXOFF == -28, LINEHEIGHT == 19
 #define CURSORXOFF		-28
@@ -136,39 +138,9 @@
 
 char	endstring[160];
 
+// haleyjd 09/04/10: [STRIFE] Moved menuitem / menu structures into header
+// because they are needed externally by the dialog engine.
 
-//
-// MENU TYPEDEFS
-//
-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;
-
 // haleyjd 08/27/10: [STRIFE] skull* stuff changed to cursor* stuff
 short		itemOn;			// menu item skull is on
 short		cursorAnimCounter;	// skull animation counter
@@ -230,7 +202,6 @@
 void M_DrawThermo(int x,int y,int thermWidth,int thermDot);
 void M_DrawEmptyCell(menu_t *menu,int item);
 void M_DrawSelCell(menu_t *menu,int item);
-void M_WriteText(int x, int y, char *string);
 int  M_StringWidth(char *string);
 int  M_StringHeight(char *string);
 void M_StartControlPanel(void);
@@ -1391,9 +1362,13 @@
 
 
 //
-//      Write a string using the hu_font
+// M_WriteText
 //
-void
+// Write a string using the hu_font
+// haleyjd 09/04/10: [STRIFE]
+// * Rogue made a lot of changes to this for the dialog system.
+//
+int
 M_WriteText
 ( int		x,
   int		y,
@@ -1404,41 +1379,144 @@
     int		c;
     int		cx;
     int		cy;
-		
 
     ch = string;
     cx = x;
     cy = y;
-	
+
     while(1)
     {
-	c = *ch++;
-	if (!c)
-	    break;
-	if (c == '\n')
-	{
-	    cx = x;
-	    cy += 12;
-	    continue;
-	}
-		
-	c = toupper(c) - HU_FONTSTART;
-	if (c < 0 || c>= 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
+}
+
+
 //
 // CONTROL PANEL
 //
@@ -1461,7 +1539,7 @@
     // "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 @@
 {
     // intro might call this repeatedly
     if (menuactive)
-	return;
+        return;
     
     menuactive = 1;
     currentMenu = &MainDef;         // JDC
--- a/src/strife/m_menu.h
+++ b/src/strife/m_menu.h
@@ -28,10 +28,41 @@
 #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 @@
 // 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    
--- 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,7 +47,26 @@
 // 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 @@
 // 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 @@
         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 @@
 // 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 @@
     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
+}
--- 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
--- 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 @@
 // Recursively traverse adjacent sectors,
 // sound blocking lines cut off traversal.
 //
+// haleyjd 09/05/10: [STRIFE] Verified unmodified
+//
 
 mobj_t*		soundtarget;
 
@@ -156,6 +160,8 @@
 // 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_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 @@
    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 @@
          (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 @@
          (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 @@
 //
 // 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 @@
 
     // 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 @@
 // 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 @@
 {
     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 @@
 
     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;
+        // 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;
+            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 @@
 // 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 @@
         P_SetMobjState(actor, actor->info->spawnstate);
         return;
     }
-		
+
     olddir = actor->movedir;
     turnaround=opposite[olddir];
 
@@ -477,58 +514,58 @@
     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,
@@ -535,49 +572,49 @@
     // 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 @@
 
 //
 // 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 @@
         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 @@
                 }
 
                 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 @@
 // 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 @@
 //
 // 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 @@
     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)
 {
--- a/src/strife/p_map.c
+++ b/src/strife/p_map.c
@@ -1234,11 +1234,11 @@
     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);
 }
  
 
--- a/src/strife/p_mobj.c
+++ b/src/strife/p_mobj.c
@@ -836,16 +836,16 @@
     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,28 +855,29 @@
 
         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;
@@ -883,8 +884,8 @@
 	
     // 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,18 +896,15 @@
     // 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;
@@ -913,25 +911,33 @@
     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 @@
     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 @@
     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;
--- a/src/strife/p_mobj.h
+++ b/src/strife/p_mobj.h
@@ -213,8 +213,8 @@
     // 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 @@
 
 
 // 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;
 
--- a/src/strife/p_pspr.c
+++ b/src/strife/p_pspr.c
@@ -644,7 +644,7 @@
 fixed_t		bulletslope;
 
 
-void P_BulletSlope (mobj_t*	mo)
+void P_BulletSlope (mobj_t *mo)
 {
     angle_t	an;
     
--- a/src/strife/p_setup.c
+++ b/src/strife/p_setup.c
@@ -342,6 +342,7 @@
 
         // 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 @@
         }
         if (spawn == false)
             break;
+        */
 
         // Do spawn all other stuff. 
         spawnthing.x = SHORT(mt->x);
--- a/src/strife/p_tick.c
+++ b/src/strife/p_tick.c
@@ -94,8 +94,6 @@
 {
 }
 
-
-
 //
 // P_RunThinkers
 //
@@ -121,8 +119,6 @@
 	currentthinker = currentthinker->next;
     }
 }
-
-
 
 //
 // P_Ticker
--- a/src/strife/r_draw.c
+++ b/src/strife/r_draw.c
@@ -547,7 +547,7 @@
 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 @@
     // 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 @@
             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 @@
             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 @@
             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 @@
         }
         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 @@
         }
         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 @@
             translationtables[i+5*256]=
             translationtables[i+6*256]=i;
         }
+
+        ++col1;
+        ++col2;
     }
 }