Source to src/p_map.c
/* P_map.c */
#include "doomdef.h"
#include "p_local.h"
int DSPRead (void volatile *adr);
/*============================================================================= */
/*================== */
/* */
/* in */
/* */
/*================== */
mobj_t *tmthing;
fixed_t tmx, tmy;
boolean checkposonly;
/*================== */
/* */
/* out */
/* */
/*================== */
extern boolean trymove2;
extern boolean floatok; /* if true, move would be ok if */
/* within tmfloorz - tmceilingz */
extern fixed_t tmfloorz, tmceilingz, tmdropoffz;
extern mobj_t *movething;
/*============================================================================= */
/*
===================
=
= P_TryMove
=
in:
tmthing a mobj_t (can be valid or invalid)
tmx,tmy a position to be checked (doesn't need relate to the mobj_t->x,y)
out:
newsubsec
floatok if true, move would be ok if within tmfloorz - tmceilingz
floorz
ceilingz
tmdropoffz the lowest point contacted (monsters won't move to a dropoff)
movething
==================
*/
void P_TryMove2 (void);
int checkpostics;
boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y)
{
tmthing = thing;
tmx = x;
tmy = y;
checkposonly = true;
#ifdef JAGUAR
{
extern p_move_start;
checkpostics += DSPFunction (&p_move_start);
}
#else
P_TryMove2 ();
#endif
return trymove2;
}
boolean P_TryMove (mobj_t *thing, fixed_t x, fixed_t y)
{
int damage;
mobj_t *latchedmovething;
tmthing = thing;
tmx = x;
tmy = y;
#ifdef JAGUAR
{
extern int p_move_start;
checkpostics += DSPFunction (&p_move_start);
}
#else
P_TryMove2 ();
#endif
/* */
/* pick up the specials */
/* */
latchedmovething = (mobj_t *)DSPRead (&movething);
if (latchedmovething)
{
if (thing->flags & MF_MISSILE)
{ /* missile bash into a monster */
damage = ((P_Random()&7)+1)*thing->info->damage;
P_DamageMobj (latchedmovething, thing, thing->target, damage);
}
else if (thing->flags & MF_SKULLFLY)
{ /* skull bash into a monster */
damage = ((P_Random()&7)+1)*thing->info->damage;
P_DamageMobj (latchedmovething, thing, thing, damage);
thing->flags &= ~MF_SKULLFLY;
thing->momx = thing->momy = thing->momz = 0;
P_SetMobjState (thing, thing->info->spawnstate);
}
else /* pick up */
P_TouchSpecialThing (latchedmovething, thing);
}
return trymove2;
}
/*
==============================================================================
USE LINES
==============================================================================
*/
int usebbox[4];
divline_t useline;
line_t *closeline;
fixed_t closedist;
/*
===============
=
= P_InterceptVector
=
= Returns the fractional intercept point along the first divline
=
===============
*/
fixed_t P_InterceptVector (divline_t *v2, divline_t *v1)
{
fixed_t frac, num, den;
den = (v1->dy>>16)*(v2->dx>>16) - (v1->dx>>16)*(v2->dy>>16);
if (den == 0)
return -1;
num = ((v1->x-v2->x)>>16) *(v1->dy>>16) +
((v2->y-v1->y)>>16) * (v1->dx>>16);
frac = (num<<16) / den;
return frac;
}
/*
================
=
= PIT_UseLines
=
================
*/
boolean PIT_UseLines (line_t *li)
{
divline_t dl;
fixed_t frac;
/* */
/* check bounding box first */
/* */
if (usebbox[BOXRIGHT] <= li->bbox[BOXLEFT]
|| usebbox[BOXLEFT] >= li->bbox[BOXRIGHT]
|| usebbox[BOXTOP] <= li->bbox[BOXBOTTOM]
|| usebbox[BOXBOTTOM] >= li->bbox[BOXTOP] )
return true;
/* */
/* find distance along usetrace */
/* */
P_MakeDivline (li, &dl);
frac = P_InterceptVector (&useline, &dl);
if (frac < 0)
return true; /* behind source */
if (frac > closedist)
return true; /* too far away */
/* */
/* the line is actually hit, find the distance */
/* */
if (!li->special)
{
P_LineOpening (li);
if (openrange > 0)
return true; /* keep going */
}
closeline = li;
closedist = frac;
return true; /* can't use for than one special line in a row */
}
/*
================
=
= P_UseLines
=
= Looks for special lines in front of the player to activate
================
*/
void P_UseLines (player_t *player)
{
int angle;
fixed_t x1, y1, x2, y2;
int x,y, xl, xh, yl, yh;
angle = player->mo->angle >> ANGLETOFINESHIFT;
x1 = player->mo->x;
y1 = player->mo->y;
x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
useline.x = x1;
useline.y = y1;
useline.dx = x2-x1;
useline.dy = y2-y1;
if (useline.dx > 0)
{
usebbox[BOXRIGHT] = x2;
usebbox[BOXLEFT] = x1;
}
else
{
usebbox[BOXRIGHT] = x1;
usebbox[BOXLEFT] = x2;
}
if (useline.dy > 0)
{
usebbox[BOXTOP] = y2;
usebbox[BOXBOTTOM] = y1;
}
else
{
usebbox[BOXTOP] = y1;
usebbox[BOXBOTTOM] = y2;
}
yh = (usebbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
yl = (usebbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
xh = (usebbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
xl = (usebbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
closeline = NULL;
closedist = FRACUNIT;
validcount++;
for (y=yl ; y<=yh ; y++)
for (x=xl ; x<=xh ; x++)
P_BlockLinesIterator (x, y, PIT_UseLines );
/* */
/* check closest line */
/* */
if (!closeline)
return;
if (!closeline->special)
S_StartSound (player->mo, sfx_noway);
else
P_UseSpecialLine (player->mo, closeline);
}
/*
==============================================================================
RADIUS ATTACK
==============================================================================
*/
mobj_t *bombsource;
mobj_t *bombspot;
int bombdamage;
/*
=================
=
= PIT_RadiusAttack
=
= Source is the creature that casued the explosion at spot
=================
*/
boolean PIT_RadiusAttack (mobj_t *thing)
{
fixed_t dx, dy, dist;
if (!(thing->flags & MF_SHOOTABLE) )
return true;
dx = abs(thing->x - bombspot->x);
dy = abs(thing->y - bombspot->y);
dist = dx>dy ? dx : dy;
dist = (dist - thing->radius) >> FRACBITS;
if (dist < 0)
dist = 0;
if (dist >= bombdamage)
return true; /* out of range */
/* FIXME? if ( P_CheckSight (thing, bombspot) ) // must be in direct path */
P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
return true;
}
/*
=================
=
= P_RadiusAttack
=
= Source is the creature that casued the explosion at spot
=================
*/
void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage)
{
int x,y, xl, xh, yl, yh;
fixed_t dist;
dist = (damage+MAXRADIUS)<<FRACBITS;
yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT;
bombspot = spot;
bombsource = source;
bombdamage = damage;
for (y=yl ; y<=yh ; y++)
for (x=xl ; x<=xh ; x++)
P_BlockThingsIterator (x, y, PIT_RadiusAttack );
}
/*============================================================================ */
int sightcounts[2];
/*=================== */
/* */
/* IN */
/* */
/* A line will be traced from the middle of shooter in the direction of */
/* attackangle until either a shootable mobj is within the visible */
/* aimtopslope / aimbottomslope range, or a solid wall blocks further */
/* tracing. If no thing is targeted along the entire range, the first line */
/* that blocks the midpoint of the trace will be hit. */
/*=================== */
mobj_t *shooter;
angle_t attackangle;
fixed_t attackrange;
fixed_t aimtopslope;
fixed_t aimbottomslope;
/*=================== */
/* */
/* OUT */
/* */
/*=================== */
extern line_t *shootline;
extern mobj_t *shootmobj;
extern fixed_t shootslope; /* between aimtop and aimbottom */
extern fixed_t shootx, shooty, shootz; /* location for puff/blood */
void P_Shoot2 (void);
mobj_t *linetarget; /* shootmobj latched in main memory */
int shoottics;
#ifdef JAGUAR
int dspterminate;
int dsppc;
int goodreads;
int badreads;
int doublebadreads;
int val1, val2;
int DSPRead (void volatile *adr)
{
reread:
val1 = *(int volatile *)adr;
val2 = *(int volatile *)adr;
if (val1 != val2)
goto reread;
return val1;
}
int DSPFunction (void *start)
{
int samp;
while (DSPRead (&dspfinished) != 0xdef6)
;
samp = samplecount;
dspfinished = 0x1234;
dspcodestart = (int)start;
do
{
dspterminate = DSPRead(&dspfinished);
} while (dspterminate != 0xdef6);
return samplecount-samp;
}
#else
int DSPRead (void volatile *adr)
{
return *(int *)adr;
}
#endif
/*
=================
=
= P_AimLineAttack
=
=================
*/
fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t distance)
{
shooter = t1;
attackrange = distance;
attackangle = angle;
aimtopslope = 100*FRACUNIT/160; /* can't shoot outside view angles */
aimbottomslope = -100*FRACUNIT/160;
validcount++;
#ifdef JAGUAR
{
extern int p_shoot_start;
shoottics += DSPFunction (&p_shoot_start);
}
#else
P_Shoot2 ();
#endif
linetarget = (mobj_t *)DSPRead (&shootmobj);
if (shootmobj)
return DSPRead(&shootslope);
return 0;
}
/*
=================
=
= P_LineAttack
=
= If slope == MAXINT, use screen bounds for attacking
=
=================
*/
void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, int damage)
{
line_t *shootline2;
int shootx2, shooty2, shootz2;
shooter = t1;
attackrange = distance;
attackangle = angle;
if (slope == MAXINT)
{
aimtopslope = 100*FRACUNIT/160; /* can't shoot outside view angles */
aimbottomslope = -100*FRACUNIT/160;
}
else
{
aimtopslope = slope+1;
aimbottomslope = slope-1;
}
validcount++;
#ifdef JAGUAR
{
extern int p_shoot_start;
shoottics += DSPFunction (&p_shoot_start);
}
#else
P_Shoot2 ();
#endif
linetarget = (mobj_t *)DSPRead (&shootmobj);
shootline2 = (line_t *)DSPRead (&shootline);
shootx2 = DSPRead (&shootx);
shooty2 = DSPRead (&shooty);
shootz2 = DSPRead (&shootz);
/* */
/* shoot thing */
/* */
if (linetarget)
{
if (linetarget->flags & MF_NOBLOOD)
P_SpawnPuff (shootx2,shooty2,shootz2);
else
P_SpawnBlood (shootx2,shooty2,shootz2, damage);
P_DamageMobj (linetarget, t1, t1, damage);
return;
}
/* */
/* shoot wall */
/* */
if (shootline2)
{
if (shootline2->special)
P_ShootSpecialLine (t1, shootline2);
if (shootline2->frontsector->ceilingpic == -1)
{
if (shootz2 > shootline2->frontsector->ceilingheight)
return; /* don't shoot the sky! */
if (shootline2->backsector
&& shootline2->backsector->ceilingpic == -1)
return; /* it's a sky hack wall */
}
P_SpawnPuff (shootx2,shooty2,shootz2);
}
}