Iskhodnyy_kod_Doom
.pdfI_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",
mthing->type,
mthing->x, mthing->y);
//don’t spawn keycards and players in deathmatch if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
return;
//don’t spawn any monsters if -nomonsters
if (nomonsters
&&( i == MT_SKULL
||(mobjinfo[i].flags & MF_COUNTKILL)) )
{
return;
}
// spawn it
x = mthing->x << FRACBITS; y = mthing->y << FRACBITS;
if (mobjinfo[i].flags & MF_SPAWNCEILING) z = ONCEILINGZ;
else
z = ONFLOORZ;
mobj = P_SpawnMobj (x,y,z, i); mobj->spawnpoint = *mthing;
if (mobj->tics > 0)
mobj->tics = 1 + (P_Random () % mobj->tics); if (mobj->flags & MF_COUNTKILL)
totalkills++;
if (mobj->flags & MF_COUNTITEM) totalitems++;
mobj->angle = ANG45 * (mthing->angle/45); if (mthing->options & MTF_AMBUSH)
mobj->flags |= MF_AMBUSH;
}
//
// GAME SPAWN FUNCTIONS
//
//
// P_SpawnPuff
//
extern fixed_t attackrange;
void P_SpawnPuff
(fixed_t x, fixed_t y,
fixed_t |
z ) |
{
mobj_t* th;
z += ((P_Random()-P_Random())<<10);
th = P_SpawnMobj (x,y,z, MT_PUFF); th->momz = FRACUNIT;
th->tics -= P_Random()&3;
491
if (th->tics < 1) th->tics = 1;
// don’t make punches spark on the wall if (attackrange == MELEERANGE)
P_SetMobjState (th, S_PUFF3);
}
//
// P_SpawnBlood
//
void P_SpawnBlood
(fixed_t x, fixed_t y,
fixed_t |
z, |
int |
damage ) |
{
mobj_t* th;
z += ((P_Random()-P_Random())<<10); th = P_SpawnMobj (x,y,z, MT_BLOOD); th->momz = FRACUNIT*2;
th->tics -= P_Random()&3;
if (th->tics < 1) th->tics = 1;
if (damage <= 12 && damage >= 9) P_SetMobjState (th,S_BLOOD2);
else if (damage < 9) P_SetMobjState (th,S_BLOOD3);
}
//
//P_CheckMissileSpawn
//Moves the missile forward a bit
//and possibly explodes it right there.
void P_CheckMissileSpawn (mobj_t* th)
{
th->tics -= P_Random()&3; if (th->tics < 1)
th->tics = 1;
//move a little forward so an angle can
//be computed if it immediately explodes th->x += (th->momx>>1);
th->y += (th->momy>>1); th->z += (th->momz>>1);
if (!P_TryMove (th, th->x, th->y)) P_ExplodeMissile (th);
}
//
// P_SpawnMissile
//
mobj_t*
492
P_SpawnMissile |
|
( mobj_t* |
source, |
mobj_t* |
dest, |
mobjtype_t |
type ) |
{ |
|
mobj_t* |
th; |
angle_t |
an; |
int |
dist; |
th = P_SpawnMobj (source->x, source->y,
source->z + 4*8*FRACUNIT, type);
if (th->info->seesound)
S_StartSound (th, th->info->seesound);
th->target = source; // where it came from
an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y);
// fuzzy player
if (dest->flags & MF_SHADOW)
an += (P_Random()-P_Random())<<20;
th->angle = an;
an >>= ANGLETOFINESHIFT;
th->momx = FixedMul (th->info->speed, finecosine[an]); th->momy = FixedMul (th->info->speed, finesine[an]);
dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); dist = dist / th->info->speed;
if (dist < 1) dist = 1;
th->momz = (dest->z - source->z) / dist; P_CheckMissileSpawn (th);
return th;
}
//
//P_SpawnPlayerMissile
//Tries to aim at a nearby monster
void P_SpawnPlayerMissile
( mobj_t* source,
mobjtype_t type )
{
mobj_t* |
th; |
angle_t |
an; |
fixed_t |
x; |
fixed_t |
y; |
fixed_t |
z; |
fixed_t |
slope; |
// see which target is to be aimed at an = source->angle;
slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
if (!linetarget)
{
an += 1<<26;
493
slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
if (!linetarget)
{
an -= 2<<26;
slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
}
if (!linetarget)
{
an = source->angle; slope = 0;
}
}
x = source->x; y = source->y;
z = source->z + 4*8*FRACUNIT;
th = P_SpawnMobj (x,y,z, type);
if (th->info->seesound)
S_StartSound (th, th->info->seesound);
th->target = source; th->angle = an;
th->momx = FixedMul( th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
th->momy = FixedMul( th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
th->momz = FixedMul( th->info->speed, slope);
P_CheckMissileSpawn (th);
}
9.14p mobj.h
// 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.
//
//DESCRIPTION:
//Map Objects, MObj, definition and handling.
//-----------------------------------------------------------------------------
#ifndef __P_MOBJ__ #define __P_MOBJ__
// Basics.
494
#include "tables.h"
#include "m_fixed.h"
//We need the thinker_t stuff. #include "d_think.h"
//We need the WAD data structure for Map things,
//from the THINGS lump.
#include "doomdata.h"
//States are tied to finite states are
//tied to animation frames.
//Needs precompiled tables/data structures. #include "info.h"
#ifdef __GNUG__ #pragma interface #endif
//
//NOTES: mobj_t
//mobj_ts are used to tell the refresh where to draw an image,
//tell the world simulation when objects are contacted,
//and tell the sound driver how to position a sound.
//
//The refresh uses the next and prev links to follow
//lists of things in sectors as they are being drawn.
//The sprite, frame, and angle elements determine which patch_t
//is used to draw the sprite if it is visible.
//The sprite and frame values are allmost allways set
//from state_t structures.
//The statescr.exe utility generates the states.h and states.c
//files that contain the sprite/frame numbers from the
//statescr.txt source file.
//The xyz origin point represents a point at the bottom middle
//of the sprite (between the feet of a biped).
//This is the default origin position for patch_ts grabbed
//with lumpy.exe.
//A walking creature will have its z equal to the floor
//it is standing on.
//
//The sound code uses the x,y, and subsector fields
//to do stereo positioning of any sound effited by the mobj_t.
//The play simulation uses the blocklinks, x,y,z, radius, height
//to determine when mobj_ts are touching each other,
//touching lines in the map, or hit by trace lines (gunshots,
//lines of sight, etc).
//The mobj_t->flags element has various bit flags
//used by the simulation.
//
//Every mobj_t is linked into a single sector
//based on its origin coordinates.
//The subsector_t is found with R_PointInSubsector(x,y),
//and the sector_t can be found with subsector->sector.
//The sector links are only used by the rendering code,
//the play simulation does not care about them at all.
//Any mobj_t that needs to be acted upon by something else
//in the play world (block movement, be shot, etc) will also
495
//need to be linked into the blockmap.
//If the thing has the MF_NOBLOCK flag set, it will not use
//the block links. It can still interact with other things,
//but only as the instigator (missiles will run into other
//things, but nothing can run into a missile).
//Each block in the grid is 128*128 units, and knows about
//every line_t that it contains a piece of, and every
//interactable mobj_t that has its origin contained.
//
//A valid mobj_t is a mobj_t that has the proper subsector_t
//filled in for its xy coordinates and is linked into the
//sector from which the subsector was made, or has the
//MF_NOSECTOR flag set (the subsector_t needs to be valid
//even if MF_NOSECTOR is set), and is linked into a blockmap
//block or has the MF_NOBLOCKMAP flag set.
//Links should only be modified by the P_[Un]SetThingPosition()
//functions.
//Do not change the MF_NO? flags while a thing is valid.
//
// Any questions?
//
//
// Misc. mobj flags
//
typedef enum
{
// Call P_SpecialThing when touched.
MF_SPECIAL |
= 1, |
|
// |
Blocks. |
|
MF_SOLID |
= 2, |
|
// |
Can be hit. |
|
MF_SHOOTABLE |
= 4, |
// Don’t use the sector links (invisible but touchable).
MF_NOSECTOR |
= 8, |
// Don’t use the blocklinks |
(inert but displayable) |
|
MF_NOBLOCKMAP |
= 16, |
|
// Not to be activated by sound, deaf monster. |
||
MF_AMBUSH |
= 32, |
|
// Will try to attack right |
back. |
|
MF_JUSTHIT |
= |
64, |
// Will take at least one step before attacking. |
||
MF_JUSTATTACKED |
= 128, |
//On level spawning (initial position),
//hang from ceiling instead of stand on floor.
MF_SPAWNCEILING |
= 256, |
//Don’t apply gravity (every tic),
//that is, object will float, keeping current height
//or changing it actively.
MF_NOGRAVITY |
= 512, |
//Movement flags.
//This allows jumps from high places.
MF_DROPOFF |
|
= 0x400, |
// For players, will pick |
up items. |
|
MF_PICKUP |
= |
0x800, |
// Player cheat. ??? |
|
|
MF_NOCLIP |
= |
0x1000, |
// Player: keep info about |
sliding along walls. |
|
MF_SLIDE |
= |
0x2000, |
//Allow moves to any height, no gravity.
//For active floaters, e.g. cacodemons, pain elementals.
MF_FLOAT |
= 0x4000, |
// Don’t cross lines
496
//??? or look at heights on teleport.
MF_TELEPORT |
= 0x8000, |
//Don’t hit same species, explode on block.
//Player missiles as well as fireballs of various kinds.
MF_MISSILE |
= 0x10000, |
//Dropped by a demon, not level spawned.
//E.g. ammo clips dropped by dying former humans.
MF_DROPPED |
= 0x20000, |
//Use fuzzy draw (shadow demons or spectres),
//temporary player invisibility powerup.
MF_SHADOW |
= 0x40000, |
//Flag: don’t bleed when shot (use puff),
//barrels and shootable furniture shall not bleed.
MF_NOBLOOD |
= 0x80000, |
//Don’t stop moving halfway off a step,
//that is, have dead bodies slide down all the way.
MF_CORPSE |
= 0x100000, |
//Floating to a height for a move, ???
//don’t auto float to target’s height.
MF_INFLOAT |
= 0x200000, |
//On kill, count this enemy object
//towards intermission kill total.
//Happy gathering.
MF_COUNTKILL |
= 0x400000, |
//On picking up, count this item object
//towards intermission item total.
MF_COUNTITEM |
= 0x800000, |
//Special handling: skull in flight.
//Neither a cacodemon nor a missile.
MF_SKULLFLY |
= 0x1000000, |
//Don’t spawn this object
//in death match mode (e.g. key cards).
MF_NOTDMATCH |
= 0x2000000, |
//Player sprites in multiplayer modes are modified
//using an internal color lookup table for re-indexing.
//If 0x4 0x8 or 0xc,
//use a translation table for player colormaps
MF_TRANSLATION |
= |
0xc000000, |
// Hmm ???. |
|
|
MF_TRANSSHIFT |
= 26 |
|
} mobjflag_t;
// Map Object definition. typedef struct mobj_s
{
// List: thinker links.
thinker_t |
thinker; |
|
// Info |
for drawing: position. |
|
fixed_t |
|
x; |
fixed_t |
|
y; |
fixed_t |
|
z; |
// More |
list: links in sector (if needed) |
|
struct mobj_s* |
snext; |
|
struct mobj_s* |
sprev; |
//More drawing info: to determine current sprite.
497
angle_t |
angle; |
// orientation |
|
spritenum_t |
sprite; |
// used |
to find patch_t and flip value |
int |
frame; |
// might |
be ORed with FF_FULLBRIGHT |
//Interaction info, by BLOCKMAP.
//Links in blocks (if needed).
struct mobj_s* |
bnext; |
|
struct mobj_s* |
bprev; |
|
struct subsector_s* |
subsector; |
|
// The closest interval over all contacted Sectors. |
||
fixed_t |
floorz; |
|
fixed_t |
ceilingz; |
|
// For movement checking. |
|
|
fixed_t |
radius; |
|
fixed_t |
height; |
|
// Momentums, used to update position. |
|
|
fixed_t |
momx; |
|
fixed_t |
momy; |
|
fixed_t |
momz; |
|
// If == validcount, already checked. |
|
|
int |
validcount; |
|
mobjtype_t |
type; |
|
mobjinfo_t* |
info; |
// &mobjinfo[mobj->type] |
int |
tics; |
// state tic counter |
state_t* |
state; |
|
int |
flags; |
|
int |
health; |
|
// Movement direction, movement generation (zig-zagging). |
||
int |
movedir; |
// 0-7 |
int |
movecount; |
// when 0, select a new dir |
//Thing being chased/attacked (or NULL),
//also the originator for missiles.
struct mobj_s* |
target; |
//Reaction time: if non 0, don’t attack yet.
//Used by player to freeze a bit after teleporting.
int |
reactiontime; |
//If >0, the target will be chased
//no matter what (even if shot)
int |
threshold; |
//Additional info record for player avatars only.
//Only valid if type == MT_PLAYER
struct |
player_s* |
player; |
// Player number |
last looked for. |
|
int |
|
lastlook; |
// For |
nightmare |
respawn. |
mapthing_t |
spawnpoint; |
|
// Thing being chased/attacked for tracers. |
||
struct |
mobj_s* |
tracer; |
} mobj_t;
498
#endif
//-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------
9.15 p plats.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:
//Plats (i.e. elevator platforms) code, raising/lowering.
//-----------------------------------------------------------------------------
static const char
rcsid[] = "$Id: p_plats.c,v 1.5 1997/02/03 22:45:12 b1 Exp $";
#include |
"i_system.h" |
#include |
"z_zone.h" |
#include |
"m_random.h" |
#include |
"doomdef.h" |
#include |
"p_local.h" |
#include |
"s_sound.h" |
// State. |
|
#include |
"doomstat.h" |
#include |
"r_state.h" |
// Data. |
|
#include |
"sounds.h" |
plat_t* |
activeplats[MAXPLATS]; |
//
// Move a plat up and down
//
void T_PlatRaise(plat_t* plat)
499
{
result_e res;
switch(plat->status)
{
case up:
res = T_MovePlane(plat->sector,
plat->speed, plat->high, plat->crush,0,1);
if (plat->type == raiseAndChange
|| plat->type == raiseToNearestAndChange)
{
if (!(leveltime&7))
S_StartSound((mobj_t *)&plat->sector->soundorg,
sfx_stnmov);
}
if (res == crushed && (!plat->crush))
{
plat->count = plat->wait; plat->status = down;
S_StartSound((mobj_t *)&plat->sector->soundorg,
sfx_pstart);
}
else
{
if (res == pastdest)
{
plat->count = plat->wait; plat->status = waiting;
S_StartSound((mobj_t *)&plat->sector->soundorg,
sfx_pstop);
switch(plat->type)
{
case blazeDWUS:
case downWaitUpStay: P_RemoveActivePlat(plat); break;
case raiseAndChange:
case raiseToNearestAndChange: P_RemoveActivePlat(plat); break;
default:
break;
}
}
}
break;
case down:
res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
if (res == pastdest)
{
plat->count = plat->wait; plat->status = waiting;
S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop);
}
break;
500