Skip to content

Commit

Permalink
Heretic/Hexen: Turn torches toward walls
Browse files Browse the repository at this point in the history
Fixed the logic for turning wall torch mobjs to face the
nearest wall.
  • Loading branch information
skyjake committed Dec 17, 2011
1 parent 13ef316 commit d1df968
Showing 1 changed file with 103 additions and 28 deletions.
131 changes: 103 additions & 28 deletions doomsday/plugins/common/src/p_start.c
Expand Up @@ -1080,6 +1080,34 @@ void G_DeathMatchSpawnPlayer(int playerNum)
}
}

/**
* @param offset Returns the position of the nearest point along the line (0..1).
*/
float P_PointLineDistance(linedef_t *line, float x, float y, float *offset)
{
float a[2], b[2], c[2], d[2], len;

P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, a);
P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, b);

c[VX] = x;
c[VY] = y;

d[VX] = b[VX] - a[VX];
d[VY] = b[VY] - a[VY];
len = sqrt(d[VX] * d[VX] + d[VY] * d[VY]); // Accurate.

if(offset)
{
*offset = ((a[VY] - c[VY]) * (a[VY] - b[VY]) -
(a[VX] - c[VX]) * (b[VX] - a[VX])) / len;
}
return ((a[VY] - c[VY]) * (b[VX] - a[VX]) -
(a[VX] - c[VX]) * (b[VY] - a[VY])) / len;
}

#if defined(__JHERETIC__) || defined(__JHEXEN__)

typedef struct {
float pos[2], minDist;
} unstuckmobjinlinedefparams_t;
Expand Down Expand Up @@ -1139,7 +1167,75 @@ int unstuckMobjInLinedef(linedef_t* li, void* context)
return false; // Continue iteration.
}

int iterateLinedefsNearMobj(thinker_t* th, void* context)
typedef struct nearestfacinglineparams_s {
mobj_t* mo;
float dist;
linedef_t* line;
} nearestfacinglineparams_t;

static int PIT_FindNearestFacingLine(linedef_t* line, void* ptr)
{
nearestfacinglineparams_t* params = (nearestfacinglineparams_t*) ptr;
float dist;
float off;

dist = P_PointLineDistance(line, params->mo->pos[VX], params->mo->pos[VY], &off);
if(off < 0 || off > P_GetFloatp(line, DMU_LENGTH) || dist < 0)
return false; // Wrong way or too far.

if(!params->line || dist < params->dist)
{
params->line = line;
params->dist = dist;
}

return false; // Continue.
}

static int turnMobjToNearestLine(thinker_t* th, void* context)
{
mobj_t* mo = (mobj_t*) th;
mobjtype_t type = *((mobjtype_t*) context);
nearestfacinglineparams_t params;
AABoxf aaBox;

if(mo->type != type)
return false; // Continue iteration.

#ifdef _DEBUG
VERBOSE( Con_Message("Checking mo %i...\n", mo->thinker.id) );
#endif

memset(&params, 0, sizeof(params));
params.mo = mo;

aaBox.minX = mo->pos[VX] - 50;
aaBox.minY = mo->pos[VY] - 50;
aaBox.maxX = mo->pos[VX] + 50;
aaBox.maxY = mo->pos[VY] + 50;

VALIDCOUNT++;

P_LinesBoxIterator(&aaBox, PIT_FindNearestFacingLine, &params);

if(params.line)
{
mo->angle = P_GetAnglep(params.line, DMU_ANGLE) - ANGLE_90;
#ifdef _DEBUG
VERBOSE( Con_Message("turnMobjToNearestLine: mo=%i angle=%x\n", mo->thinker.id, mo->angle) );
#endif
}
else
{
#ifdef _DEBUG
VERBOSE( Con_Message(" => no nearest list found\n") );
#endif
}

return false; // Continue iteration.
}

static int iterateLinedefsNearMobj(thinker_t* th, void* context)
{
mobj_t* mo = (mobj_t*) th;
mobjtype_t type = *((mobjtype_t*) context);
Expand All @@ -1166,7 +1262,6 @@ int iterateLinedefsNearMobj(thinker_t* th, void* context)

if(mo->pos[VX] != params.pos[VX] || mo->pos[VY] != params.pos[VY])
{
mo->angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], params.pos[VX], params.pos[VY]);
P_MobjUnsetPosition(mo);
mo->pos[VX] = params.pos[VX];
mo->pos[VY] = params.pos[VY];
Expand All @@ -1179,7 +1274,7 @@ int iterateLinedefsNearMobj(thinker_t* th, void* context)
/**
* Only affects torches, which are often placed inside walls in the
* original maps. The DOOM engine allowed these kinds of things but a
* Z-buffer doesn't.
* Z-buffer doesn't. Also turns the torches so they face the nearest line.
*/
void P_MoveThingsOutOfWalls(void)
{
Expand All @@ -1196,34 +1291,15 @@ void P_MoveThingsOutOfWalls(void)

for(i = 0; types[i] != NUMMOBJTYPES; ++i)
{
mobjtype_t type = types[i];

mobjtype_t type = types[i];
DD_IterateThinkers(P_MobjThinker, iterateLinedefsNearMobj, &type);
DD_IterateThinkers(P_MobjThinker, turnMobjToNearestLine, &type);
}
}

#if __JHERETIC__
float P_PointLineDistance(linedef_t *line, float x, float y, float *offset)
{
float a[2], b[2], c[2], d[2], len;

P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, a);
P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, b);

c[VX] = x;
c[VY] = y;

d[VX] = b[VX] - a[VX];
d[VY] = b[VY] - a[VY];
len = sqrt(d[VX] * d[VX] + d[VY] * d[VY]); // Accurate.

if(offset)
*offset = ((a[VY] - c[VY]) * (a[VY] - b[VY]) -
(a[VX] - c[VX]) * (b[VX] - a[VX])) / len;
return ((a[VY] - c[VY]) * (b[VX] - a[VX]) -
(a[VX] - c[VX]) * (b[VY] - a[VY])) / len;
}
#endif

#ifdef __JHERETIC__
/**
* Fails in some places, but works most of the time.
*/
Expand Down Expand Up @@ -1279,8 +1355,7 @@ void P_TurnGizmosAwayFromDoors(void)
P_GetFloatpv(li, DMU_DXY, d1);
linelen = P_ApproxDistance(d1[0], d1[1]);

dist = fabs(P_PointLineDistance(li, iter->pos[VX],
iter->pos[VY], &off));
dist = fabs(P_PointLineDistance(li, iter->pos[VX], iter->pos[VY], &off));
if(!closestline || dist < closestdist)
{
closestdist = dist;
Expand Down

0 comments on commit d1df968

Please sign in to comment.