⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_enemy.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 4 页
字号:
// Emacs style mode select   -*- C++ -*-//-----------------------------------------------------------------------------//// $Id: p_enemy.c,v 1.12 2001/04/04 20:24:21 judgecutor Exp $//// Copyright (C) 1993-1996 by id Software, Inc.// Portions Copyright (C) 1998-2000 by DooM Legacy Team.//// 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: p_enemy.c,v $// Revision 1.12  2001/04/04 20:24:21  judgecutor// Added support for the 3D Sound//// Revision 1.11  2001/03/30 17:12:50  bpereira// no message//// Revision 1.10  2001/03/19 21:18:48  metzgermeister//   * missing textures in HW mode are replaced by default texture//   * fixed crash bug with P_SpawnMissile(.) returning NULL//   * deep water trick and other nasty thing work now in HW mode (tested with tnt/map02 eternal/map02)//   * added cvar gr_correcttricks//// Revision 1.9  2001/01/25 22:15:43  bpereira// added heretic support//// Revision 1.8  2000/10/21 08:43:30  bpereira// no message//// Revision 1.7  2000/10/08 13:30:01  bpereira// no message//// Revision 1.6  2000/10/01 10:18:17  bpereira// no message//// Revision 1.5  2000/04/30 10:30:10  bpereira// no message//// Revision 1.4  2000/04/11 19:07:24  stroggonmeth// Finished my logs, fixed a crashing bug.//// Revision 1.3  2000/04/04 00:32:46  stroggonmeth// Initial Boom compatability plus few misc changes all around.//// Revision 1.2  2000/02/27 00:42:10  hurdler// fix CR+LF problem//// Revision 1.1.1.1  2000/02/22 20:32:32  hurdler// Initial import into CVS (v1.29 pr3)////// DESCRIPTION://      Enemy thinking, AI.//      Action Pointer Functions//      that are associated with states/frames.////-----------------------------------------------------------------------------#include "doomdef.h"#include "g_game.h"#include "p_local.h"#include "r_main.h"#include "r_state.h"#include "s_sound.h"#include "m_random.h"#ifdef HW3SOUND#include "hardware/hw3sound.h"#endifvoid FastMonster_OnChange(void);// enable the solid corpses option : still not finishedconsvar_t cv_solidcorpse = {"solidcorpse","0",CV_NETVAR | CV_SAVE,CV_OnOff};consvar_t cv_fastmonsters = {"fastmonsters","0",CV_NETVAR | CV_CALL,CV_OnOff,FastMonster_OnChange};typedef enum{    DI_EAST,    DI_NORTHEAST,    DI_NORTH,    DI_NORTHWEST,    DI_WEST,    DI_SOUTHWEST,    DI_SOUTH,    DI_SOUTHEAST,    DI_NODIR,    NUMDIRS} dirtype_t;//// P_NewChaseDir related LUT.//static dirtype_t opposite[] ={  DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,  DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR};static dirtype_t diags[] ={    DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST};void A_Fall (mobj_t *actor);void FastMonster_OnChange(void){static boolean fast=false;static const struct    {        mobjtype_t type;        int speed[2];    } MonsterMissileInfo[] =    {        // doom        { MT_BRUISERSHOT, {15, 20}},        { MT_HEADSHOT,    {10, 20}},        { MT_TROOPSHOT,   {10, 20}},                // heretic        { MT_IMPBALL,     {10, 20}},        { MT_MUMMYFX1,    { 9, 18}},        { MT_KNIGHTAXE,   { 9, 18}},        { MT_REDAXE,      { 9, 18}},        { MT_BEASTBALL,   {12, 20}},        { MT_WIZFX1,      {18, 24}},        { MT_SNAKEPRO_A,  {14, 20}},        { MT_SNAKEPRO_B,  {14, 20}},        { MT_HEADFX1,     {13, 20}},        { MT_HEADFX3,     {10, 18}},        { MT_MNTRFX1,     {20, 26}},        { MT_MNTRFX2,     {14, 20}},        { MT_SRCRFX1,     {20, 28}},        { MT_SOR2FX1,     {20, 28}},                { -1, {-1, -1} } // Terminator    };    int i;    if (cv_fastmonsters.value && !fast)    {        for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)            states[i].tics >>= 1;        fast=true;    }    else    if(!cv_fastmonsters.value && fast)    {        for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)            states[i].tics <<= 1;        fast=false;    }    for(i = 0; MonsterMissileInfo[i].type != -1; i++)    {        mobjinfo[MonsterMissileInfo[i].type].speed            = MonsterMissileInfo[i].speed[cv_fastmonsters.value]<<FRACBITS;    }}//// ENEMY THINKING// Enemies are allways spawned// with targetplayer = -1, threshold = 0// Most monsters are spawned unaware of all players,// but some can be made preaware////// Called by P_NoiseAlert.// Recursively traverse adjacent sectors,// sound blocking lines cut off traversal.//static mobj_t*         soundtarget;static void P_RecursiveSound ( sector_t*     sec,  int           soundblocks ){    int         i;    line_t*     check;    sector_t*   other;    // wake up all monsters in this sector    if (sec->validcount == validcount        && sec->soundtraversed <= soundblocks+1)    {        return;         // already flooded    }    sec->validcount = validcount;    sec->soundtraversed = soundblocks+1;    sec->soundtarget = soundtarget;    for (i=0 ;i<sec->linecount ; i++)    {        check = sec->lines[i];        if (! (check->flags & ML_TWOSIDED) )            continue;        P_LineOpening (check);        if (openrange <= 0)            continue;   // closed door        if ( sides[ check->sidenum[0] ].sector == sec)            other = sides[ check->sidenum[1] ].sector;        else            other = sides[ check->sidenum[0] ].sector;        if (check->flags & ML_SOUNDBLOCK)        {            if (!soundblocks)                P_RecursiveSound (other, 1);        }        else            P_RecursiveSound (other, soundblocks);    }}//// P_NoiseAlert// If a monster yells at a player,// it will alert other monsters to the player.//void P_NoiseAlert ( mobj_t*       target,  mobj_t*       emmiter ){    soundtarget = target;    validcount++;    P_RecursiveSound (emmiter->subsector->sector, 0);}//// P_CheckMeleeRange//static boolean P_CheckMeleeRange (mobj_t*      actor){    mobj_t*     pl;    fixed_t     dist;    if (!actor->target)        return false;    pl = actor->target;    dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);    if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)        return false;    //added:19-03-98: check height now, so that damn imps cant attack    //                you if you stand on a higher ledge.    if ( demoversion>111 &&         ((pl->z > actor->z+actor->height) ||         (actor->z > pl->z + pl->height) ))         return false;    if (! P_CheckSight (actor, actor->target) )        return false;    return true;}//// P_CheckMissileRange//static boolean P_CheckMissileRange (mobj_t* actor){    fixed_t     dist;    if (! P_CheckSight (actor, actor->target) )        return false;    if ( actor->flags & MF_JUSTHIT )    {        // the target just hit the enemy,        // so fight back!        actor->flags &= ~MF_JUSTHIT;        return true;    }    if (actor->reactiontime)        return false;   // do not attack yet    // OPTIMIZE: get this from a global checksight    dist = P_AproxDistance ( actor->x-actor->target->x,                             actor->y-actor->target->y) - 64*FRACUNIT;    if (!actor->info->meleestate)        dist -= 128*FRACUNIT;   // no melee attack, so fire more    dist >>= 16;    if (actor->type == MT_VILE)    {        if (dist > 14*64)            return false;       // too far away    }    if (actor->type == MT_UNDEAD)    {        if (dist < 196)            return false;       // close for fist attack        dist >>= 1;    }    if (actor->type == MT_CYBORG        || actor->type == MT_SPIDER        || actor->type == MT_SKULL        || actor->type == MT_IMP) // heretic monster    {        dist >>= 1;    }    if (dist > 200)        dist = 200;    if (actor->type == MT_CYBORG && dist > 160)        dist = 160;    if (P_Random () < dist)        return false;    return true;}//// P_Move// Move in the current direction,// returns false if the move is blocked.//static const fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};static const fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};static boolean P_Move (mobj_t* actor){    fixed_t     tryx;    fixed_t     tryy;    line_t*     ld;    boolean     good;    if (actor->movedir == DI_NODIR)        return false;#ifdef PARANOIA    if ((unsigned)actor->movedir >= 8)        I_Error ("Weird actor->movedir!");#endif    tryx = actor->x + actor->info->speed*xspeed[actor->movedir];    tryy = actor->y + actor->info->speed*yspeed[actor->movedir];    if (!P_TryMove (actor, tryx, tryy, false))    {        // open any specials        if (actor->flags & MF_FLOAT && floatok)        {            // must adjust height            if (actor->z < tmfloorz)                actor->z += FLOATSPEED;            else                actor->z -= FLOATSPEED;            actor->flags |= MF_INFLOAT;            return true;        }        if (!numspechit)            return false;        actor->movedir = DI_NODIR;        good = false;        while (numspechit--)        {            ld = lines + spechit[numspechit];            // if the special is not a door            // that can be opened,            // return false            if (P_UseSpecialLine (actor, ld,0))                good = true;        }        return good;    }    else    {        actor->flags &= ~MF_INFLOAT;    }    if (! (actor->flags & MF_FLOAT) )    {        if(actor->z > actor->floorz)           P_HitFloor(actor);        actor->z = actor->floorz;    }    return true;}//// TryWalk// Attempts to move actor on// in its current (ob->moveangle) direction.// If blocked by either a wall or an actor// returns FALSE// If move is either clear or blocked only by a door,// returns TRUE and sets...// If a door is in the way,// an OpenDoor call is made to start it opening.//static boolean P_TryWalk (mobj_t* actor){    if (!P_Move (actor))    {        return false;    }    actor->movecount = P_Random()&15;    return true;}static void P_NewChaseDir (mobj_t*     actor){    fixed_t     deltax;    fixed_t     deltay;    dirtype_t   d[3];    int         tdir;    dirtype_t   olddir;    dirtype_t   turnaround;    if (!actor->target)        I_Error ("P_NewChaseDir: called with no target");    olddir = actor->movedir;    turnaround=opposite[olddir];    deltax = actor->target->x - actor->x;    deltay = actor->target->y - actor->y;    if (deltax>10*FRACUNIT)        d[1]= DI_EAST;    else if (deltax<-10*FRACUNIT)        d[1]= DI_WEST;    else        d[1]= DI_NODIR;    if (deltay<-10*FRACUNIT)        d[2]= DI_SOUTH;    else if (deltay>10*FRACUNIT)        d[2]= DI_NORTH;    else        d[2]= DI_NODIR;    // try direct route    if (   d[1] != DI_NODIR        && d[2] != DI_NODIR)    {        actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];        if (actor->movedir != turnaround && P_TryWalk(actor))            return;    }    // try other directions    if (P_Random() > 200        ||  abs(deltay)>abs(deltax))    {        tdir=d[1];        d[1]=d[2];        d[2]=tdir;    }    if (d[1]==turnaround)        d[1]=DI_NODIR;    if (d[2]==turnaround)        d[2]=DI_NODIR;    if (d[1]!=DI_NODIR)    {        actor->movedir = d[1];        if (P_TryWalk(actor))        {            // either moved forward or attacked            return;        }    }    if (d[2]!=DI_NODIR)    {        actor->movedir =d[2];        if (P_TryWalk(actor))            return;    }    // there is no direct path to the player,    // so pick another direction.    if (olddir!=DI_NODIR)    {        actor->movedir =olddir;        if (P_TryWalk(actor))            return;    }    // randomly determine direction of search    if (P_Random()&1)    {        for ( tdir=DI_EAST;              tdir<=DI_SOUTHEAST;              tdir++ )        {            if (tdir!=turnaround)            {                actor->movedir =tdir;                if ( P_TryWalk(actor) )                    return;            }        }    }    else    {        for ( tdir=DI_SOUTHEAST;              tdir >= DI_EAST;              tdir-- )        {            if (tdir!=turnaround)            {                actor->movedir =tdir;                if ( P_TryWalk(actor) )                    return;            }        }    }    if (turnaround !=  DI_NODIR)    {        actor->movedir =turnaround;        if ( P_TryWalk(actor) )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -