Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Iskhodnyy_kod_Doom

.pdf
Скачиваний:
7
Добавлен:
13.02.2015
Размер:
1.01 Mб
Скачать

tmflags = thing->flags;

tmx = x; tmy = y;

tmbbox[BOXTOP] = y + tmthing->radius; tmbbox[BOXBOTTOM] = y - tmthing->radius; tmbbox[BOXRIGHT] = x + tmthing->radius; tmbbox[BOXLEFT] = x - tmthing->radius;

newsubsec = R_PointInSubsector (x,y); ceilingline = NULL;

//The base floor / ceiling is from the subsector

//that contains the point.

//Any contacted lines the step closer together

//will adjust them.

tmfloorz = tmdropoffz = newsubsec->sector->floorheight; tmceilingz = newsubsec->sector->ceilingheight;

validcount++; numspechit = 0;

if ( tmflags & MF_NOCLIP ) return true;

//Check things first, possibly picking things up.

//The bounding box is extended by MAXRADIUS

//because mobj_ts are grouped into mapblocks

//based on their origin point, and can overlap

//into adjacent blocks by up to MAXRADIUS units.

xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;

for (bx=xl ; bx<=xh ; bx++)

for (by=yl ; by<=yh ; by++)

if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) return false;

// check lines

xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;

for (bx=xl ; bx<=xh ; bx++)

for (by=yl ; by<=yh ; by++)

if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) return false;

return true;

}

//

//P_TryMove

//Attempt to move to a new position,

//crossing special lines unless MF_TELEPORT is set.

boolean P_TryMove

( mobj_t* thing,

fixed_t x,

451

fixed_t

y )

{

 

fixed_t

oldx;

fixed_t

oldy;

int

side;

int

oldside;

line_t*

ld;

floatok = false;

if (!P_CheckPosition (thing, x, y))

return false;

// solid wall or thing

if ( !(thing->flags &

MF_NOCLIP) )

{

 

if (tmceilingz - tmfloorz < thing->height)

return false;

// doesn’t fit

floatok = true;

 

if ( !(thing->flags&MF_TELEPORT)

&&tmceilingz

- thing->z < thing->height)

return false;

// mobj must lower itself to fit

if ( !(thing->flags&MF_TELEPORT)

&& tmfloorz - thing->z > 24*FRACUNIT )

return false; // too big a step up

if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))

&& tmfloorz - tmdropoffz > 24*FRACUNIT )

return false;

// don’t stand over a dropoff

}

 

//the move is ok,

//so link the thing into its new position P_UnsetThingPosition (thing);

oldx = thing->x; oldy = thing->y;

thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; thing->x = x;

thing->y = y;

P_SetThingPosition (thing);

// if any special lines were hit, do the effect if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )

{

while (numspechit--)

{

// see if the line was crossed ld = spechit[numspechit];

side = P_PointOnLineSide (thing->x, thing->y, ld); oldside = P_PointOnLineSide (oldx, oldy, ld);

if (side != oldside)

{

if (ld->special)

P_CrossSpecialLine (ld-lines, oldside, thing);

}

}

}

return true;

}

452

//

//P_ThingHeightClip

//Takes a valid thing and adjusts the thing->floorz,

//thing->ceilingz, and possibly thing->z.

//This is called for all nearby monsters

//whenever a sector changes height.

//If the thing doesn’t fit,

//the z will be set to the lowest value

//and false will be returned.

//

boolean P_ThingHeightClip (mobj_t* thing)

{

boolean

 

onfloor;

 

onfloor

= (thing->z == thing->floorz);

P_CheckPosition (thing,

thing->x,

thing->y);

// what

about stranding

a monster

partially off an edge?

thing->floorz = tmfloorz; thing->ceilingz = tmceilingz;

if (onfloor)

{

// walking monsters rise and fall with the floor thing->z = thing->floorz;

}

else

{

// don’t adjust a floating monster unless forced to if (thing->z+thing->height > thing->ceilingz)

thing->z = thing->ceilingz - thing->height;

}

if (thing->ceilingz - thing->floorz < thing->height) return false;

return true;

}

//

//SLIDE MOVE

//Allows the player to slide along any angled walls.

fixed_t

bestslidefrac;

fixed_t

secondslidefrac;

line_t*

bestslideline;

line_t*

secondslideline;

mobj_t*

slidemo;

fixed_t

tmxmove;

fixed_t

tmymove;

//

//P_HitSlideLine

//Adjusts the xmove / ymove

//so that the next move will slide along the wall.

453

void P_HitSlideLine (line_t* ld)

{

int

side;

angle_t

lineangle;

angle_t

moveangle;

angle_t

deltaangle;

fixed_t

movelen;

fixed_t

newlen;

if (ld->slopetype == ST_HORIZONTAL)

{

tmymove = 0; return;

}

if (ld->slopetype == ST_VERTICAL)

{

tmxmove = 0; return;

}

side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);

lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);

if (side == 1)

lineangle += ANG180;

moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); deltaangle = moveangle-lineangle;

if (deltaangle > ANG180) deltaangle += ANG180;

//I_Error ("SlideLine: ang>ANG180");

lineangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT;

movelen = P_AproxDistance (tmxmove, tmymove);

newlen = FixedMul (movelen, finecosine[deltaangle]);

tmxmove = FixedMul (newlen, finecosine[lineangle]); tmymove = FixedMul (newlen, finesine[lineangle]);

}

//

// PTR_SlideTraverse

//

boolean PTR_SlideTraverse (intercept_t* in)

{

line_t* li;

if (!in->isaline)

I_Error ("PTR_SlideTraverse: not a line?");

li = in->d.line;

if ( ! (li->flags & ML_TWOSIDED) )

{

if (P_PointOnLineSide (slidemo->x, slidemo->y, li))

{

454

// don’t hit the back side return true;

}

goto isblocking;

}

// set openrange, opentop, openbottom P_LineOpening (li);

if (openrange < slidemo->height)

 

goto isblocking;

// doesn’t fit

if (opentop - slidemo->z < slidemo->height)

goto isblocking;

// mobj is too high

if (openbottom - slidemo->z > 24*FRACUNIT )

goto isblocking;

// too big a step up

//this line doesn’t block movement return true;

//the line does block movement,

//see if it is closer than best so far isblocking:

if (in->frac < bestslidefrac)

{

secondslidefrac = bestslidefrac; secondslideline = bestslideline; bestslidefrac = in->frac; bestslideline = li;

}

return false;

// stop

}

//

//P_SlideMove

//The momx / momy move is bad, so try to slide

//along a wall.

//Find the first line hit, move flush to it,

//and slide along it

//

// This is a kludgy mess.

//

void P_SlideMove (mobj_t* mo)

{

fixed_t

leadx;

fixed_t

leady;

fixed_t

trailx;

fixed_t

traily;

fixed_t

newx;

fixed_t

newy;

int

hitcount;

slidemo = mo;

 

hitcount = 0;

 

retry:

 

if (++hitcount == 3)

 

goto stairstep;

// don’t loop forever

// trace along the three leading corners

455

if (mo->momx > 0)

{

leadx = mo->x + mo->radius; trailx = mo->x - mo->radius;

}

else

{

leadx = mo->x - mo->radius; trailx = mo->x + mo->radius;

}

if (mo->momy > 0)

{

leady = mo->y + mo->radius; traily = mo->y - mo->radius;

}

else

{

leady = mo->y - mo->radius; traily = mo->y + mo->radius;

}

bestslidefrac = FRACUNIT+1;

P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_SlideTraverse );

P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_SlideTraverse );

P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, PT_ADDLINES, PTR_SlideTraverse );

// move up to the wall

if (bestslidefrac == FRACUNIT+1)

{

// the move most have hit the middle, so stairstep stairstep:

if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) P_TryMove (mo, mo->x + mo->momx, mo->y);

return;

}

// fudge a bit to make sure it doesn’t hit bestslidefrac -= 0x800;

if (bestslidefrac > 0)

{

newx = FixedMul (mo->momx, bestslidefrac); newy = FixedMul (mo->momy, bestslidefrac);

if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) goto stairstep;

}

//Now continue along the wall.

//First calculate remainder.

bestslidefrac = FRACUNIT-(bestslidefrac+0x800);

if (bestslidefrac > FRACUNIT) bestslidefrac = FRACUNIT;

if (bestslidefrac <= 0) return;

tmxmove = FixedMul (mo->momx, bestslidefrac); tmymove = FixedMul (mo->momy, bestslidefrac);

456

P_HitSlideLine (bestslideline);

// clip the moves

mo->momx = tmxmove; mo->momy = tmymove;

if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove))

{

goto retry;

}

}

//

 

// P_LineAttack

 

//

 

mobj_t*

linetarget;

mobj_t*

shootthing;

//Height if not aiming up or down

//???: use slope for monsters?

fixed_t

shootz;

// who got hit (or NULL)

int

la_damage;

fixed_t

attackrange;

fixed_t

aimslope;

// slopes to top and bottom of target

extern

fixed_t

topslope;

extern

fixed_t

bottomslope;

//

//PTR_AimTraverse

//Sets linetaget and aimslope when a target is aimed at.

boolean

PTR_AimTraverse (intercept_t* in)

{

line_t*

li;

mobj_t*

th;

fixed_t

slope;

fixed_t

thingtopslope;

fixed_t

thingbottomslope;

fixed_t

dist;

if (in->isaline)

 

{

 

li = in->d.line;

 

if ( !(li->flags & ML_TWOSIDED) )

 

return false;

// stop

//Crosses a two sided line.

//A two sided line will restrict

//the possible target ranges.

P_LineOpening (li);

if (openbottom >=

opentop)

return false;

// stop

dist = FixedMul (attackrange, in->frac);

if (li->frontsector->floorheight != li->backsector->floorheight)

{

457

slope = FixedDiv (openbottom - shootz , dist); if (slope > bottomslope)

bottomslope = slope;

}

if (li->frontsector->ceilingheight != li->backsector->ceilingheight)

{

slope = FixedDiv (opentop - shootz , dist); if (slope < topslope)

topslope = slope;

}

 

if (topslope <= bottomslope)

 

return false;

// stop

return true;

// shot continues

}

 

// shoot a thing

 

th = in->d.thing;

 

if (th == shootthing)

 

return true;

// can’t shoot self

if (!(th->flags&MF_SHOOTABLE))

 

return true;

// corpse or something

// check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac);

thingtopslope = FixedDiv (th->z+th->height - shootz , dist);

if (thingtopslope < bottomslope)

 

return true;

// shot over the thing

thingbottomslope = FixedDiv (th->z - shootz, dist);

if (thingbottomslope > topslope)

 

return true;

 

// shot under the thing

//

this thing can

be hit!

if

(thingtopslope

>

topslope)

 

thingtopslope

=

topslope;

if (thingbottomslope < bottomslope) thingbottomslope = bottomslope;

aimslope = (thingtopslope+thingbottomslope)/2; linetarget = th;

return false;

// don’t go any farther

}

//

// PTR_ShootTraverse

//

boolean PTR_ShootTraverse (intercept_t* in)

{

fixed_t

x;

fixed_t

y;

fixed_t

z;

fixed_t

frac;

line_t*

li;

mobj_t*

th;

458

fixed_t

slope;

fixed_t

dist;

fixed_t

thingtopslope;

fixed_t

thingbottomslope;

if (in->isaline)

 

{

 

li = in->d.line;

 

if (li->special)

P_ShootSpecialLine (shootthing, li);

if ( !(li->flags & ML_TWOSIDED) ) goto hitline;

// crosses a two sided line P_LineOpening (li);

dist = FixedMul (attackrange, in->frac);

if (li->frontsector->floorheight != li->backsector->floorheight)

{

slope = FixedDiv (openbottom - shootz , dist); if (slope > aimslope)

goto hitline;

}

if (li->frontsector->ceilingheight != li->backsector->ceilingheight)

{

slope = FixedDiv (opentop - shootz , dist); if (slope < aimslope)

goto hitline;

}

//shot continues return true;

//hit line hitline:

//position a bit closer

frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); x = trace.x + FixedMul (trace.dx, frac);

y = trace.y + FixedMul (trace.dy, frac);

z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));

if (li->frontsector->ceilingpic == skyflatnum)

{

// don’t shoot the sky!

if (z > li->frontsector->ceilingheight)

 

return false;

//

it’s a sky hack wall

if

(li->backsector && li->backsector->ceilingpic == skyflatnum)

 

return false;

}

//Spawn bullet puffs. P_SpawnPuff (x,y,z);

//don’t go any farther return false;

}

459

// shoot a thing

 

th = in->d.thing;

 

if (th == shootthing)

 

return true;

// can’t shoot self

if (!(th->flags&MF_SHOOTABLE))

 

return true;

// corpse or something

// check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac);

thingtopslope = FixedDiv (th->z+th->height - shootz , dist);

if

(thingtopslope < aimslope)

 

 

 

 

return

true;

//

shot over

the thing

thingbottomslope = FixedDiv (th->z

- shootz,

dist);

if

(thingbottomslope > aimslope)

 

 

 

 

return

true;

//

shot under the thing

//hit thing

//position a bit closer

frac = in->frac - FixedDiv (10*FRACUNIT,attackrange);

x = trace.x + FixedMul (trace.dx, frac); y = trace.y + FixedMul (trace.dy, frac);

z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));

//Spawn bullet puffs or blod spots,

//depending on target type.

if (in->d.thing->flags & MF_NOBLOOD) P_SpawnPuff (x,y,z);

else

P_SpawnBlood (x,y,z, la_damage);

if (la_damage)

P_DamageMobj (th, shootthing, shootthing, la_damage);

// don’t go any farther return false;

}

//

// P_AimLineAttack

//

 

fixed_t

 

P_AimLineAttack

 

( mobj_t*

t1,

angle_t

angle,

fixed_t

distance )

{

 

fixed_t

x2;

fixed_t

y2;

angle >>= ANGLETOFINESHIFT; shootthing = t1;

x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];

y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;

// can’t shoot outside view angles

460

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]