Iskhodnyy_kod_Doom
.pdf#define |
MAXHEALTH |
100 |
#define |
VIEWHEIGHT |
(41*FRACUNIT) |
//mapblocks are used to check movement
//against lines and things
#define MAPBLOCKUNITS |
128 |
#define MAPBLOCKSIZE |
(MAPBLOCKUNITS*FRACUNIT) |
#define MAPBLOCKSHIFT |
(FRACBITS+7) |
#define MAPBMASK |
(MAPBLOCKSIZE-1) |
#define MAPBTOFRAC |
(MAPBLOCKSHIFT-FRACBITS) |
// player radius for movement checking |
|
#define PLAYERRADIUS |
16*FRACUNIT |
//MAXRADIUS is for precalculated sector block boxes
//the spider demon is larger,
//but we do not have any moving sectors nearby
#define MAXRADIUS |
32*FRACUNIT |
|
#define GRAVITY |
|
FRACUNIT |
#define MAXMOVE |
|
(30*FRACUNIT) |
#define USERANGE |
(64*FRACUNIT) |
|
#define MELEERANGE |
(64*FRACUNIT) |
|
#define MISSILERANGE |
(32*64*FRACUNIT) |
|
// follow a player exlusively for 3 seconds |
||
#define |
BASETHRESHOLD |
100 |
//
//P_TICK
//both the head and tail of the thinker list
extern |
thinker_t |
thinkercap; |
|
void P_InitThinkers (void); |
|
||
void |
P_AddThinker (thinker_t* thinker); |
||
void |
P_RemoveThinker (thinker_t* thinker); |
||
//
// P_PSPR
//
void P_SetupPsprites (player_t* curplayer); void P_MovePsprites (player_t* curplayer); void P_DropWeapon (player_t* player);
// |
|
|
// P_USER |
|
|
// |
|
|
void |
P_PlayerThink (player_t* player); |
|
// |
|
|
// P_MOBJ |
|
|
// |
|
|
#define ONFLOORZ |
MININT |
|
441
#define ONCEILINGZ |
MAXINT |
// Time interval for item respawning. |
|
#define ITEMQUESIZE |
128 |
extern mapthing_t |
itemrespawnque[ITEMQUESIZE]; |
extern int |
itemrespawntime[ITEMQUESIZE]; |
extern int |
iquehead; |
extern int |
iquetail; |
void P_RespawnSpecials (void);
mobj_t* P_SpawnMobj
(fixed_t x, fixed_t y, fixed_t z,
mobjtype_t |
type ); |
void |
P_RemoveMobj (mobj_t* th); |
boolean |
P_SetMobjState (mobj_t* mobj, statenum_t state); |
void |
P_MobjThinker (mobj_t* mobj); |
void |
P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); |
void |
P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); |
mobj_t* P_SpawnMissile (mobj_t* source, mobj_t* dest, mobjtype_t type);
void P_SpawnPlayerMissile (mobj_t* source, mobjtype_t type);
//
// P_ENEMY
//
void P_NoiseAlert (mobj_t* target, mobj_t* emmiter);
// |
|
|
// P_MAPUTL |
|
|
// |
|
|
typedef struct |
|
|
{ |
|
|
fixed_t |
x; |
|
fixed_t |
y; |
|
fixed_t |
dx; |
|
fixed_t |
dy; |
|
} divline_t; |
|
|
typedef struct |
|
|
{ |
|
|
fixed_t |
frac; |
// along trace line |
boolean |
isaline; |
|
union { |
|
|
mobj_t* |
thing; |
line_t* |
line; |
} |
d; |
} intercept_t; |
|
#define MAXINTERCEPTS |
128 |
extern intercept_t |
intercepts[MAXINTERCEPTS]; |
extern intercept_t* |
intercept_p; |
typedef boolean (*traverser_t) (intercept_t *in);
442
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); |
|
||
int |
P_PointOnLineSide (fixed_t x, fixed_t y, |
line_t* line); |
|
int |
P_PointOnDivlineSide (fixed_t x, fixed_t |
y, divline_t* line); |
|
void |
P_MakeDivline (line_t* li, divline_t* dl); |
||
fixed_t P_InterceptVector (divline_t* v2, divline_t* |
v1); |
||
int |
P_BoxOnLineSide (fixed_t* tmbox, line_t* |
ld); |
|
extern fixed_t |
opentop; |
|
|
extern fixed_t |
openbottom; |
|
|
extern fixed_t |
openrange; |
|
|
extern fixed_t |
lowfloor; |
|
|
void |
P_LineOpening (line_t* linedef); |
|
|
boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) );
#define PT_ADDLINES |
1 |
#define PT_ADDTHINGS |
2 |
#define PT_EARLYOUT |
4 |
extern divline_t |
trace; |
boolean P_PathTraverse
(fixed_t x1, fixed_t y1, fixed_t x2,
fixed_t |
y2, |
int |
flags, |
boolean |
(*trav) (intercept_t *)); |
void P_UnsetThingPosition (mobj_t* thing); void P_SetThingPosition (mobj_t* thing);
//
//P_MAP
//If "floatok" true, move would be ok
//if within "tmfloorz - tmceilingz".
extern boolean |
floatok; |
|
extern |
fixed_t |
tmfloorz; |
extern |
fixed_t |
tmceilingz; |
extern line_t* ceilingline;
boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y);
void |
P_SlideMove (mobj_t* mo); |
|
|
boolean P_CheckSight (mobj_t* t1, mobj_t* t2); |
|||
void |
P_UseLines (player_t* player); |
||
boolean P_ChangeSector (sector_t* sector, boolean crunch); |
|||
extern mobj_t* |
linetarget; |
// who got hit (or NULL) |
|
fixed_t |
|
|
|
P_AimLineAttack |
|
|
|
(mobj_t* t1, angle_t angle,
fixed_t |
distance ); |
443
void |
|
|
P_LineAttack |
|
|
( mobj_t* |
t1, |
|
angle_t |
angle, |
|
fixed_t |
distance, |
|
fixed_t |
slope, |
|
int |
damage ); |
|
void |
|
|
P_RadiusAttack |
|
|
( mobj_t* |
spot, |
|
mobj_t* |
source, |
|
int |
damage ); |
|
// |
|
|
// P_SETUP |
|
|
// |
|
|
extern byte* |
rejectmatrix; |
// for fast sight rejection |
extern short* |
blockmaplump; |
// offsets in blockmap are from here |
extern short* |
blockmap; |
|
extern int |
bmapwidth; |
|
extern int |
bmapheight; |
// in mapblocks |
extern fixed_t |
bmaporgx; |
|
extern fixed_t |
bmaporgy; |
// origin of block map |
extern mobj_t** |
blocklinks; |
// for thing chains |
// |
|
|
// P_INTER |
|
|
// |
|
|
extern int |
maxammo[NUMAMMO]; |
|
extern int |
clipammo[NUMAMMO]; |
|
void P_TouchSpecialThing
( mobj_t* special, mobj_t* toucher );
void P_DamageMobj
(mobj_t* target, mobj_t* inflictor,
mobj_t* |
source, |
int |
damage ); |
//
// P_SPEC
//
#include "p_spec.h"
#endif |
// __P_LOCAL__ |
//----------------------------------------------------------------------------- |
|
// |
|
// $Log:$ |
|
// |
|
//----------------------------------------------------------------------------- |
|
444
9.11 p map.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 handling.
//Shooting and aiming.
//
//-----------------------------------------------------------------------------
static const char
rcsid[] = "$Id: p_map.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
#include |
<stdlib.h> |
#include |
"m_bbox.h" |
#include |
"m_random.h" |
#include |
"i_system.h" |
#include |
"doomdef.h" |
#include |
"p_local.h" |
#include |
"s_sound.h" |
// State. |
|
#include |
"doomstat.h" |
#include |
"r_state.h" |
// Data. |
|
#include |
"sounds.h" |
fixed_t |
tmbbox[4]; |
mobj_t* |
tmthing; |
int |
tmflags; |
fixed_t |
tmx; |
fixed_t |
tmy; |
//If "floatok" true, move would be ok
//if within "tmfloorz - tmceilingz".
boolean |
floatok; |
fixed_t |
tmfloorz; |
fixed_t |
tmceilingz; |
fixed_t |
tmdropoffz; |
//keep track of the line that lowers the ceiling,
//so missiles don’t explode against sky hack walls
line_t* |
ceilingline; |
445
//keep track of special lines as they are hit,
//but don’t process them until the move is proven valid
#define MAXSPECIALCROSS |
8 |
|
line_t* |
|
spechit[MAXSPECIALCROSS]; |
int |
numspechit; |
|
//
// TELEPORT MOVE
//
//
// PIT_StompThing
//
boolean PIT_StompThing (mobj_t* thing)
{
fixed_t blockdist;
if (!(thing->flags & MF_SHOOTABLE) ) return true;
blockdist = thing->radius + tmthing->radius;
if ( abs(thing->x - tmx) >= blockdist
|| abs(thing->y - tmy) >= blockdist )
{
// didn’t hit it return true;
}
//don’t clip against self if (thing == tmthing)
return true;
//monsters don’t stomp things except on boss level if ( !tmthing->player && gamemap != 30)
return false;
P_DamageMobj (thing, tmthing, tmthing, 10000);
return true;
} |
|
// |
|
// P_TeleportMove |
|
// |
|
boolean |
|
P_TeleportMove |
|
( mobj_t* |
thing, |
fixed_t |
x, |
fixed_t |
y ) |
{ |
|
int |
xl; |
int |
xh; |
int |
yl; |
int |
yh; |
int |
bx; |
int |
by; |
subsector_t* |
newsubsec; |
446
// kill |
anything occupying the position |
tmthing |
= thing; |
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;
// stomp on any things contacted
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_StompThing)) return false;
//the move is ok,
//so link the thing into its new position P_UnsetThingPosition (thing);
thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; thing->x = x;
thing->y = y;
P_SetThingPosition (thing);
return true;
}
//
// MOVEMENT ITERATOR FUNCTIONS
//
//
//PIT_CheckLine
//Adjusts tmfloorz and tmceilingz as lines are contacted
boolean PIT_CheckLine (line_t* ld)
{
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
||tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
||tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
447
|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) return true;
if (P_BoxOnLineSide (tmbbox, ld) != -1) return true;
//A line has been hit
//The moving thing’s destination position will cross
//the given line.
//If this should not be allowed, return false.
//If the line is special, keep track of it
//to process later if the move is proven ok.
//NOTE: specials are NOT sorted by order,
//so two special lines that are only 8 pixels apart
//could be crossed in either order.
if (!ld->backsector) |
|
return false; |
// one sided line |
if (!(tmthing->flags & MF_MISSILE) )
{
if ( ld->flags & ML_BLOCKING )
return |
false; |
// explicitly blocking |
everything |
if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS ) |
|||
return |
false; |
// block monsters only |
|
}
//set openrange, opentop, openbottom P_LineOpening (ld);
//adjust floor / ceiling heights
if (opentop < tmceilingz)
{
tmceilingz = opentop; ceilingline = ld;
}
if (openbottom > tmfloorz) tmfloorz = openbottom;
if (lowfloor < tmdropoffz) tmdropoffz = lowfloor;
// if contacted a special line, add it to the list if (ld->special)
{
spechit[numspechit] = ld; numspechit++;
}
return true;
}
//
// PIT_CheckThing
//
boolean PIT_CheckThing (mobj_t* thing)
{
fixed_t |
blockdist; |
boolean |
solid; |
int |
damage; |
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))
448
return true;
blockdist = thing->radius + tmthing->radius;
if ( abs(thing->x - tmx) >= blockdist
|| abs(thing->y - tmy) >= blockdist )
{
// didn’t hit it return true;
}
//don’t clip against self if (thing == tmthing)
return true;
//check for skulls slamming into things if (tmthing->flags & MF_SKULLFLY)
{
damage = ((P_Random()%8)+1)*tmthing->info->damage;
P_DamageMobj (thing, tmthing, tmthing, damage);
tmthing->flags &= ~MF_SKULLFLY;
tmthing->momx = tmthing->momy = tmthing->momz = 0;
P_SetMobjState (tmthing, tmthing->info->spawnstate);
return false; |
// stop moving |
} |
|
// missiles can hit other things if (tmthing->flags & MF_MISSILE)
{
// see if it went over / under |
|
|
||
if |
(tmthing->z > thing->z + thing->height) |
|||
|
return |
true; |
// |
overhead |
if |
(tmthing->z+tmthing->height < thing->z) |
|||
|
return |
true; |
// |
underneath |
if (tmthing->target && ( tmthing->target->type == thing->type ||
(tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)|| (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) )
{
// Don’t hit same species as originator. if (thing == tmthing->target)
return true;
if (thing->type != MT_PLAYER)
{
//Explode, but do no damage.
//Let players missile other players. return false;
}
}
if (! (thing->flags & MF_SHOOTABLE) )
{
// didn’t do any damage
return !(thing->flags & MF_SOLID);
}
// damage / explode
damage = ((P_Random()%8)+1)*tmthing->info->damage;
449
P_DamageMobj (thing, tmthing, tmthing->target, damage);
// don’t traverse any more return false;
}
// check for special pickup
if (thing->flags & MF_SPECIAL)
{
solid = thing->flags&MF_SOLID; if (tmflags&MF_PICKUP)
{
// can remove thing P_TouchSpecialThing (thing, tmthing);
}
return !solid;
}
return !(thing->flags & MF_SOLID);
}
//
// MOVEMENT CLIPPING
//
//
//P_CheckPosition
//This is purely informative, nothing is modified
//(except things picked up).
//
//in:
//a mobj_t (can be valid or invalid)
//a position to be checked
//(doesn’t need to be related to the mobj_t->x,y)
//during:
//special things are touched if MF_PICKUP
//early out on solid lines?
//
//out:
//newsubsec
//floorz
//ceilingz
//tmdropoffz
//the lowest point contacted
//(monsters won’t move to a dropoff)
//speciallines[]
//numspeciallines
// |
|
boolean |
|
P_CheckPosition |
|
( mobj_t* |
thing, |
fixed_t |
x, |
fixed_t |
y ) |
{ |
|
int |
xl; |
int |
xh; |
int |
yl; |
int |
yh; |
int |
bx; |
int |
by; |
subsector_t* |
newsubsec; |
tmthing = thing; |
|
450
