Skip to content

Commit

Permalink
All Games: Fixed monsters only attempting to target players #0..3
Browse files Browse the repository at this point in the history
Also fixed Hexen's Minotaur targeting it's master.
  • Loading branch information
danij-deng committed Jan 3, 2012
1 parent 2fff589 commit c203ad1
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 234 deletions.
9 changes: 8 additions & 1 deletion doomsday/plugins/common/include/mobj.h
Expand Up @@ -28,7 +28,14 @@

#include "g_common.h"

void Mobj_XYMoveStopping(mobj_t* mo);
void Mobj_XYMoveStopping(mobj_t* mo);

boolean Mobj_IsPlayerClMobj(mobj_t* thing);

/**
* @param allAround @c false= only look 180 degrees in front.
* @return @c true iff a player was targeted.
*/
boolean Mobj_LookForPlayers(mobj_t* mo, boolean allAround);

#endif // __LIBCOMMON_MOBJ__
9 changes: 9 additions & 0 deletions doomsday/plugins/common/include/p_player.h
Expand Up @@ -66,6 +66,15 @@ weapontype_t P_WeaponSlotCycle(weapontype_t type, boolean prev);
int P_GetPlayerNum(player_t* plr);
int P_GetPlayerCheats(const player_t* plr);

/**
* Count the number of players currently marked as "in game". Note that
* an in-game player may not yet have a (CL)Mobj assigned to them, this
* is a count of players in the current game session.
*
* @return Total count.
*/
int P_CountPlayersInGame(void);

boolean P_PlayerInWalkState(player_t* plr);

weapontype_t P_PlayerFindWeapon(player_t* plr, boolean prev);
Expand Down
87 changes: 85 additions & 2 deletions doomsday/plugins/common/src/mobj.c
Expand Up @@ -29,12 +29,13 @@
# pragma optimize("g", off)
#endif

// HEADER FILES ------------------------------------------------------------

#include <math.h>
#include <assert.h>

#include "mobj.h"
#include "p_actor.h"
#include "p_player.h"
#include "p_map.h"
#include "dmu_lib.h"

#define DROPOFFMOMENTUM_THRESHOLD (1.0f / 4)
Expand Down Expand Up @@ -170,3 +171,85 @@ boolean Mobj_IsPlayerClMobj(mobj_t* thing)
}
return false;
}

boolean Mobj_LookForPlayers(mobj_t* mo, boolean allAround)
{
const int playerCount = P_CountPlayersInGame();
boolean foundTarget = false;
int from, to, cand, tries = 0;

// Nobody to target?
if(!playerCount) return false;

from = mo->lastLook % MAXPLAYERS;
to = (from+MAXPLAYERS-1) % MAXPLAYERS;

for(cand = from; cand != to; cand = (cand < (MAXPLAYERS-1)? cand + 1 : 0))
{
player_t* player = players + cand;
mobj_t* plrmo;

// Is player in the game?
if(!player->plr->inGame || !player->plr->mo) continue;
plrmo = player->plr->mo;

// Do not target camera players.
if(P_MobjIsCamera(plrmo)) continue;

// Only look ahead a fixed number of times.
if(tries++ == 2) break;

// Do not target dead players.
if(player->health <= 0) continue;

// Within sight?
if(!P_CheckSight(mo, plrmo)) continue;

if(!allAround)
{
angle_t an = R_PointToAngle2(mo->pos[VX], mo->pos[VY],
plrmo->pos[VX], plrmo->pos[VY]);
an -= mo->angle;

if(an > ANG90 && an < ANG270)
{
// If real close, react anyway.
float dist = P_ApproxDistance(plrmo->pos[VX] - mo->pos[VX],
plrmo->pos[VY] - mo->pos[VY]);
// Behind us?
if(dist > MELEERANGE) continue;
}
}

#if __JHERETIC__ || __JHEXEN__
// If player is invisible we may not detect if too far or randomly.
if(plrmo->flags & MF_SHADOW)
{
if((P_ApproxDistance(plrmo->pos[VX] - mo->pos[VX],
plrmo->pos[VY] - mo->pos[VY]) > 2 * MELEERANGE) &&
P_ApproxDistance(plrmo->mom[MX], plrmo->mom[MY]) < 5)
{
// Too far; can't detect.
continue;
}

// Randomly overlook the player regardless.
if(P_Random() < 225) continue;
}
#endif

#if __JHEXEN__
// Minotaurs do not target their master.
if(mo->type == MT_MINOTAUR && mo->tracer &&
mo->tracer->player == player) continue;
#endif

// Found our quarry.
mo->target = plrmo;
foundTarget = true;
}

// Start looking from here next time.
mo->lastLook = cand;
return foundTarget;
}
11 changes: 11 additions & 0 deletions doomsday/plugins/common/src/p_player.c
Expand Up @@ -309,6 +309,17 @@ int P_GetPlayerCheats(const player_t* player)
}
}

int P_CountPlayersInGame(void)
{
int c, count = 0;
for(c = 0; c < MAXPLAYERS; ++c)
{
player_t* player = players + c;
if(player->plr->inGame) count += 1;
}
return count;
}

/**
* Determines whether the player's state is one of the walking states.
*
Expand Down
81 changes: 4 additions & 77 deletions doomsday/plugins/jdoom/src/p_enemy.c
Expand Up @@ -452,77 +452,6 @@ static void newChaseDir(mobj_t *actor)
doNewChaseDir(actor, deltaX, deltaY);
}

/**
* If allaround is false, only look 180 degrees in front.
*
* @return @c true, if a player is targeted.
*/
static boolean lookForPlayers(mobj_t *actor, boolean allAround)
{
int c, stop, playerCount;
player_t *player;
angle_t an;
float dist;

playerCount = 0;
for(c = 0; c < MAXPLAYERS; ++c)
{
if(players[c].plr->inGame)
playerCount++;
}

// Are there any players?
if(!playerCount)
return false;

c = 0;
stop = (actor->lastLook - 1) & 3;

for(;; actor->lastLook = (actor->lastLook + 1) & 3)
{
if(!players[actor->lastLook].plr->inGame)
continue;

if(c++ == 2 || actor->lastLook == stop)
{ // Done looking.
return false;
}

player = &players[actor->lastLook];

if(P_MobjIsCamera(player->plr->mo))
continue;

if(player->health <= 0)
continue; // Player is already dead.

if(!P_CheckSight(actor, player->plr->mo))
continue; // Player is out of sight.

if(!allAround)
{
an = R_PointToAngle2(actor->pos[VX],
actor->pos[VY],
player->plr->mo->pos[VX],
player->plr->mo->pos[VY]);
an -= actor->angle;

if(an > ANG90 && an < ANG270)
{
dist =
P_ApproxDistance(player->plr->mo->pos[VX] - actor->pos[VX],
player->plr->mo->pos[VY] - actor->pos[VY]);
// If real close, react anyway.
if(dist > MELEERANGE)
continue; // Behind back.
}
}

actor->target = player->plr->mo;
return true;
}
}

static int massacreMobj(thinker_t* th, void* context)
{
int* count = (int*) context;
Expand Down Expand Up @@ -553,7 +482,6 @@ int P_Massacre(void)
return count;
}


typedef struct {
mobjtype_t type;
size_t count;
Expand Down Expand Up @@ -623,8 +551,7 @@ void C_DECL A_Look(mobj_t* actor)
goto seeyou;
}

if(!lookForPlayers(actor, false))
return;
if(!Mobj_LookForPlayers(actor, false)) return;

// Go into chase state.
seeyou:
Expand Down Expand Up @@ -701,7 +628,7 @@ void C_DECL A_Chase(mobj_t* actor)
P_MobjIsCamera(actor->target))
{
// Look for a new target.
if(lookForPlayers(actor, true))
if(Mobj_LookForPlayers(actor, true))
{ // Got a new target.
}
else
Expand Down Expand Up @@ -751,7 +678,7 @@ void C_DECL A_Chase(mobj_t* actor)
if(IS_NETGAME && !actor->threshold &&
!P_CheckSight(actor, actor->target))
{
if(lookForPlayers(actor, true))
if(Mobj_LookForPlayers(actor, true))
return; // Got a new target.
}

Expand Down Expand Up @@ -1958,7 +1885,7 @@ void C_DECL A_SpawnFly(mobj_t *mo)

if((newmobj = P_SpawnMobj3fv(type, targ->pos, P_Random() << 24, 0)))
{
if(lookForPlayers(newmobj, true))
if(Mobj_LookForPlayers(newmobj, true))
P_MobjChangeState(newmobj, P_GetState(newmobj->type, SN_SEE));

// Telefrag anything in this spot.
Expand Down
8 changes: 4 additions & 4 deletions doomsday/plugins/jdoom64/src/p_enemy.c
Expand Up @@ -458,7 +458,7 @@ static void newChaseDir(mobj_t *actor)
*
* @return @c true, if a player is targeted.
*/
static boolean lookForPlayers(mobj_t *actor, boolean allAround)
static boolean Mobj_LookForPlayers(mobj_t *actor, boolean allAround)
{
int c, stop, playerCount;
player_t *player;
Expand Down Expand Up @@ -952,7 +952,7 @@ void C_DECL A_Look(mobj_t *actor)
goto seeyou;
}

if(!lookForPlayers(actor, false))
if(!Mobj_LookForPlayers(actor, false))
return;

// Go into chase state.
Expand Down Expand Up @@ -1064,7 +1064,7 @@ void C_DECL A_Chase(mobj_t* actor)
if(!actor->target || !(actor->target->flags & MF_SHOOTABLE))
{
// Look for a new target.
if(lookForPlayers(actor, true))
if(Mobj_LookForPlayers(actor, true))
{ // Got a new target.
}
else
Expand Down Expand Up @@ -1114,7 +1114,7 @@ void C_DECL A_Chase(mobj_t* actor)
if(IS_NETGAME && !actor->threshold &&
!P_CheckSight(actor, actor->target))
{
if(lookForPlayers(actor, true))
if(Mobj_LookForPlayers(actor, true))
return; // Got a new target.
}

Expand Down

0 comments on commit c203ad1

Please sign in to comment.