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

Iskhodnyy_kod_Doom

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

topslope = 100*FRACUNIT/160; bottomslope = -100*FRACUNIT/160;

attackrange = distance; linetarget = NULL;

P_PathTraverse ( t1->x, t1->y,

x2, y2,

PT_ADDLINES|PT_ADDTHINGS,

PTR_AimTraverse );

if (linetarget) return aimslope;

return 0;

}

//

//P_LineAttack

//If damage == 0, it is just a test trace

//that will leave linetarget set.

//

void P_LineAttack

(mobj_t* t1, angle_t angle, fixed_t distance,

fixed_t

slope,

int

damage )

{

 

fixed_t

x2;

fixed_t

y2;

angle >>= ANGLETOFINESHIFT; shootthing = t1;

la_damage = damage;

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

y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; 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 );

}

//

 

// USE LINES

 

//

 

mobj_t*

usething;

boolean

PTR_UseTraverse (intercept_t* in)

{

 

int

side;

if (!in->d.line->special)

{

P_LineOpening (in->d.line); if (openrange <= 0)

{

461

S_StartSound (usething, sfx_noway);

// can’t use through a wall return false;

}

// not a special line, but keep checking return true ;

}

side = 0;

if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1)

 

side = 1;

 

//

return false;

// don’t use back side

P_UseSpecialLine (usething, in->d.line, side);

// can’t use for than one special line in a row return false;

}

//

//P_UseLines

//Looks for special lines in front of the player to activate.

void P_UseLines (player_t*

player)

{

 

 

int

angle;

 

fixed_t

x1;

 

fixed_t

y1;

 

fixed_t

x2;

 

fixed_t

y2;

 

usething = player->mo;

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];

P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );

}

//

 

// RADIUS ATTACK

 

//

 

mobj_t*

bombsource;

mobj_t*

bombspot;

int

bombdamage;

//

//PIT_RadiusAttack

//"bombsource" is the creature

//that caused the explosion at "bombspot".

boolean PIT_RadiusAttack (mobj_t* thing)

{

fixed_t

dx;

fixed_t

dy;

fixed_t

dist;

462

if (!(thing->flags & MF_SHOOTABLE) ) return true;

//Boss spider and cyborg

//take no damage from concussion. if (thing->type == MT_CYBORG

||thing->type == MT_SPIDER) 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

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 caused the explosion at spot.

void P_RadiusAttack

( mobj_t* spot,

mobj_t*

source,

int

damage )

{

 

int

x;

int

y;

int

xl;

int

xh;

int

yl;

int

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 );

}

463

//

//SECTOR HEIGHT CHANGING

//After modifying a sectors floor or ceiling height,

//call this routine to adjust the positions

//of all things that touch the sector.

//

//If anything doesn’t fit anymore, true will be returned.

//If crunch is true, they will take damage

//as they are being crushed.

//If Crunch is false, you should set the sector height back

//the way it was and call P_ChangeSector again

//to undo the changes.

//

 

boolean

crushchange;

boolean

nofit;

//

// PIT_ChangeSector

//

boolean PIT_ChangeSector (mobj_t* thing)

{

mobj_t* mo;

if (P_ThingHeightClip (thing))

{

// keep checking return true;

}

// crunch bodies to giblets if (thing->health <= 0)

{

P_SetMobjState (thing, S_GIBS);

thing->flags &= ~MF_SOLID; thing->height = 0; thing->radius = 0;

// keep checking return true;

}

// crunch dropped items

if (thing->flags & MF_DROPPED)

{

P_RemoveMobj (thing);

// keep checking return true;

}

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

{

// assume it is bloody gibs or something return true;

}

nofit = true;

if (crushchange && !(leveltime&3) )

464

{

P_DamageMobj(thing,NULL,NULL,10);

// spray blood in a random direction mo = P_SpawnMobj (thing->x,

thing->y,

thing->z + thing->height/2, MT_BLOOD);

mo->momx = (P_Random() - P_Random ())<<12; mo->momy = (P_Random() - P_Random ())<<12;

}

// keep checking (crush other things) return true;

}

 

//

 

// P_ChangeSector

 

//

 

boolean

 

P_ChangeSector

 

( sector_t*

sector,

boolean

crunch )

{

 

int

x;

int

y;

nofit = false; crushchange = crunch;

// re-check heights for all things near the moving sector

for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)

P_BlockThingsIterator (x, y, PIT_ChangeSector);

return nofit;

}

9.12 p maputl.c

// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------

//

//$Id:$

//Copyright (C) 1993-1996 by id Software, Inc.

//This program is free software; you can redistribute it and/or

//modify it under the terms of the GNU General Public License

//as published by the Free Software Foundation; either version 2

//of the License, or (at your option) any later version.

//

//This program is distributed in the hope that it will be useful,

//but WITHOUT ANY WARRANTY; without even the implied warranty of

//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

//GNU General Public License for more details.

//

//$Log:$

//DESCRIPTION:

//Movement/collision utility functions,

465

//as used by function in p_map.c.

//BLOCKMAP Iterator functions,

//and some PIT_* functions to use for iteration.

//-----------------------------------------------------------------------------

static const char

rcsid[] = "$Id: p_maputl.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";

#include <stdlib.h>

#include "m_bbox.h"

#include "doomdef.h" #include "p_local.h"

// State.

#include "r_state.h"

//

// P_AproxDistance

// Gives an estimation of distance (not exact)

//

fixed_t

 

P_AproxDistance

 

( fixed_t

dx,

fixed_t

dy )

{

 

dx = abs(dx);

 

dy = abs(dy); if (dx < dy)

return dx+dy-(dx>>1); return dx+dy-(dy>>1);

}

//

//P_PointOnLineSide

//Returns 0 or 1

//

int P_PointOnLineSide

(fixed_t x, fixed_t y,

line_t*

line )

{

 

fixed_t

dx;

fixed_t

dy;

fixed_t

left;

fixed_t

right;

if (!line->dx)

{

if (x <= line->v1->x) return line->dy > 0;

return line->dy < 0;

}

if (!line->dy)

{

if (y <= line->v1->y)

466

return line->dx < 0;

return line->dx > 0;

}

dx = (x - line->v1->x); dy = (y - line->v1->y);

left = FixedMul ( line->dy>>FRACBITS , dx ); right = FixedMul ( dy , line->dx>>FRACBITS );

if (right < left)

 

return 0;

// front side

return 1;

// back side

}

//

//P_BoxOnLineSide

//Considers the line to be infinite

//Returns side 0 or 1, -1 if box crosses the line.

int P_BoxOnLineSide

( fixed_t* tmbox,

line_t*

 

ld )

{

 

 

int

 

p1;

int

 

p2;

switch

(ld->slopetype)

{

 

 

case

ST_HORIZONTAL:

p1

= tmbox[BOXTOP] > ld->v1->y;

p2

= tmbox[BOXBOTTOM] > ld->v1->y;

if

(ld->dx < 0)

{

 

 

 

p1

^= 1;

 

p2

^= 1;

}

 

 

break;

 

case

ST_VERTICAL:

p1

= tmbox[BOXRIGHT] < ld->v1->x;

p2

= tmbox[BOXLEFT] < ld->v1->x;

if

(ld->dy < 0)

{

 

 

 

p1

^= 1;

 

p2

^= 1;

}

 

 

break;

 

case

ST_POSITIVE:

p1

= P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld);

p2

= P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);

break;

 

case

ST_NEGATIVE:

p1

= P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld);

p2

= P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);

break;

 

}

 

 

if (p1

== p2)

467

return p1; return -1;

}

//

//P_PointOnDivlineSide

//Returns 0 or 1.

//

int P_PointOnDivlineSide ( fixed_t x,

fixed_t y, divline_t* line )

{

fixed_t

dx;

fixed_t

dy;

fixed_t

left;

fixed_t

right;

if (!line->dx)

{

if (x <= line->x)

return line->dy > 0;

return line->dy < 0;

}

if (!line->dy)

{

if (y <= line->y)

return line->dx < 0;

return line->dx > 0;

}

dx = (x - line->x); dy = (y - line->y);

// try to quickly decide by looking at sign bits if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )

{

if ( (line->dy ^ dx) & 0x80000000 )

return 1;

// (left is negative)

return 0;

 

}

 

left = FixedMul ( line->dy>>8, dx>>8 ); right = FixedMul ( dy>>8 , line->dx>>8 );

if (right < left)

return 0;

// front side

return 1;

// back side

}

 

//

 

// P_MakeDivline

 

//

 

void

 

P_MakeDivline

 

( line_t*

li,

divline_t*

dl )

{

 

dl->x = li->v1->x;

468

dl->y = li->v1->y; dl->dx = li->dx; dl->dy = li->dy;

}

//

//P_InterceptVector

//Returns the fractional intercept point

//along the first divline.

//This is only called by the addthings

//and addlines traversers.

//

 

fixed_t

 

P_InterceptVector

 

( divline_t*

v2,

divline_t*

v1 )

{

 

#if 1

 

fixed_t

frac;

fixed_t

num;

fixed_t

den;

den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);

if (den == 0) return 0;

//I_Error ("P_InterceptVector: parallel");

num =

FixedMul

( (v1->x - v2->x)>>8 ,v1->dy )

+FixedMul ( (v2->y - v1->y)>>8, v1->dx );

frac = FixedDiv (num , den);

return frac;

 

#else

// UNUSED, float debug.

float

 

frac;

float

 

num;

float

 

den;

float

 

v1x;

float

 

v1y;

float

 

v1dx;

float

 

v1dy;

float

 

v2x;

float

 

v2y;

float

 

v2dx;

float

 

v2dy;

v1x = (float)v1->x/FRACUNIT; v1y = (float)v1->y/FRACUNIT; v1dx = (float)v1->dx/FRACUNIT; v1dy = (float)v1->dy/FRACUNIT; v2x = (float)v2->x/FRACUNIT; v2y = (float)v2->y/FRACUNIT; v2dx = (float)v2->dx/FRACUNIT; v2dy = (float)v2->dy/FRACUNIT;

den = v1dy*v2dx - v1dx*v2dy;

if (den ==

0)

 

return

0;

// parallel

num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;

469

frac = num / den;

return frac*FRACUNIT; #endif

}

//

//P_LineOpening

//Sets opentop and openbottom to the window

//through a two sided line.

//OPTIMIZE: keep this precalculated

//

fixed_t opentop; fixed_t openbottom; fixed_t openrange;

fixed_t lowfloor;

void P_LineOpening (line_t* linedef)

{

sector_t* front; sector_t* back;

if (linedef->sidenum[1] == -1)

{

// single sided line openrange = 0; return;

}

front = linedef->frontsector; back = linedef->backsector;

if (front->ceilingheight < back->ceilingheight) opentop = front->ceilingheight;

else

opentop = back->ceilingheight;

if (front->floorheight > back->floorheight)

{

openbottom = front->floorheight; lowfloor = back->floorheight;

}

else

{

openbottom = back->floorheight; lowfloor = front->floorheight;

}

openrange = opentop - openbottom;

}

//

// THING POSITION SETTING

//

//

//P_UnsetThingPosition

//Unlinks a thing from block map and sectors.

//On each position change, BLOCKMAP and other

//lookups maintaining lists ot things inside

//these structures need to be updated.

470

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