📄 p_henemy.c
字号:
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------//// $Id: p_henemy.c,v 1.4 2001/04/17 22:26:07 calumr Exp $//// Copyright (C) 1993-1996 by Raven Software, Corp.// 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_henemy.c,v $// Revision 1.4 2001/04/17 22:26:07 calumr// Initial Mac add//// Revision 1.3 2001/02/24 13:35:20 bpereira// no message//////// DESCRIPTION:// this file is include by P_enemy.c// it contain all heretic enemey specific////-----------------------------------------------------------------------------// Macros#define MAX_BOSS_SPOTS 8// Typestypedef struct{ fixed_t x; fixed_t y; angle_t angle;} BossSpot_t;// Private Datastatic int BossSpotCount;static BossSpot_t BossSpots[MAX_BOSS_SPOTS];// Proto//----------------------------------------------------------------------------//// PROC P_InitMonsters//// Called at level load.////----------------------------------------------------------------------------void P_InitMonsters(void){ BossSpotCount = 0;}//----------------------------------------------------------------------------//// PROC P_AddBossSpot////----------------------------------------------------------------------------void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle){ if(BossSpotCount == MAX_BOSS_SPOTS) { I_Error("Too many boss spots."); } BossSpots[BossSpotCount].x = x; BossSpots[BossSpotCount].y = y; BossSpots[BossSpotCount].angle = angle; BossSpotCount++;}//---------------------------------------------------------------------------//// FUNC P_LookForMonsters////---------------------------------------------------------------------------#define MONS_LOOK_RANGE (20*64*FRACUNIT)#define MONS_LOOK_LIMIT 64boolean P_LookForMonsters(mobj_t *actor){ int count; mobj_t *mo; thinker_t *think; if(!P_CheckSight(players[0].mo, actor)) { // Player can't see monster return(false); } count = 0; for(think = thinkercap.next; think != &thinkercap; think = think->next) { if(think->function.acp1 != (actionf_p1)P_MobjThinker) { // Not a mobj thinker continue; } mo = (mobj_t *)think; if(!(mo->flags&MF_COUNTKILL) || (mo == actor) || (mo->health <= 0)) { // Not a valid monster continue; } if(P_AproxDistance(actor->x-mo->x, actor->y-mo->y) > MONS_LOOK_RANGE) { // Out of range continue; } if(P_Random() < 16) { // Skip continue; } if(count++ > MONS_LOOK_LIMIT) { // Stop searching return(false); } if(!P_CheckSight(actor, mo)) { // Out of sight continue; } // Found a target monster actor->target = mo; return(true); } return(false);}/*=============================================================================== ACTION ROUTINES===============================================================================*///----------------------------------------------------------------------------//// PROC A_DripBlood////----------------------------------------------------------------------------void A_DripBlood(mobj_t *actor){ mobj_t *mo; int r,s; // evaluation order isn't define in C r = P_SignedRandom(); s = P_SignedRandom(); mo = P_SpawnMobj(actor->x+(r<<11), actor->y+(s<<11), actor->z, MT_BLOOD); mo->momx = P_SignedRandom()<<10; mo->momy = P_SignedRandom()<<10; mo->flags2 |= MF2_LOGRAV;}//----------------------------------------------------------------------------//// PROC A_KnightAttack////----------------------------------------------------------------------------void A_KnightAttack(mobj_t *actor){ if(!actor->target) { return; } if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(3)); S_StartSound(actor, sfx_kgtat2); return; } // Throw axe S_StartSound(actor, actor->info->attacksound); if(actor->type == MT_KNIGHTGHOST || P_Random() < 40) { // Red axe P_SpawnMissile(actor, actor->target, MT_REDAXE); return; } // Green axe P_SpawnMissile(actor, actor->target, MT_KNIGHTAXE);}//----------------------------------------------------------------------------//// PROC A_ImpExplode////----------------------------------------------------------------------------void A_ImpExplode(mobj_t *actor){ mobj_t *mo; mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK1); mo->momx = P_SignedRandom()<<10; mo->momy = P_SignedRandom()<<10; mo->momz = 9*FRACUNIT; mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK2); mo->momx = P_SignedRandom()<<10; mo->momy = P_SignedRandom()<<10; mo->momz = 9*FRACUNIT; if(actor->special1 == 666) { // Extreme death crash P_SetMobjState(actor, S_IMP_XCRASH1); }}//----------------------------------------------------------------------------//// PROC A_BeastPuff////----------------------------------------------------------------------------void A_BeastPuff(mobj_t *actor){ if(P_Random() > 64) { int r,s,t; r = P_SignedRandom(); s = P_SignedRandom(); t = P_SignedRandom(); P_SpawnMobj(actor->x+(r<<10), actor->y+(s<<10), actor->z+(t<<10), MT_PUFFY); }}//----------------------------------------------------------------------------//// PROC A_ImpMeAttack////----------------------------------------------------------------------------void A_ImpMeAttack(mobj_t *actor){ if(!actor->target) { return; } S_StartSound(actor, actor->info->attacksound); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, 5+(P_Random()&7)); }}//----------------------------------------------------------------------------//// PROC A_ImpMsAttack////----------------------------------------------------------------------------void A_ImpMsAttack(mobj_t *actor){ mobj_t *dest; angle_t an; int dist; if(!actor->target || P_Random() > 64) { P_SetMobjState(actor, actor->info->seestate); return; } dest = actor->target; actor->flags |= MF_SKULLFLY; S_StartSound(actor, actor->info->attacksound); A_FaceTarget(actor); an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul(12*FRACUNIT, finecosine[an]); actor->momy = FixedMul(12*FRACUNIT, finesine[an]); dist = P_AproxDistance(dest->x-actor->x, dest->y-actor->y); dist = dist/(12*FRACUNIT); if(dist < 1) { dist = 1; } actor->momz = (dest->z+(dest->height>>1)-actor->z)/dist;}//----------------------------------------------------------------------------//// PROC A_ImpMsAttack2//// Fireball attack of the imp leader.////----------------------------------------------------------------------------void A_ImpMsAttack2(mobj_t *actor){ if(!actor->target) { return; } S_StartSound(actor, actor->info->attacksound); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, 5+(P_Random()&7)); return; } P_SpawnMissile(actor, actor->target, MT_IMPBALL);}//----------------------------------------------------------------------------//// PROC A_ImpDeath////----------------------------------------------------------------------------void A_ImpDeath(mobj_t *actor){ actor->flags &= ~MF_SOLID; actor->flags2 |= MF2_FOOTCLIP; actor->flags |= MF_CORPSE|MF_DROPOFF; actor->height >>= 2; actor->radius -= (actor->radius>>4); //for solid corpses if(actor->z <= actor->floorz) { P_SetMobjState(actor, S_IMP_CRASH1); actor->flags &= ~MF_CORPSE; }}//----------------------------------------------------------------------------//// PROC A_ImpXDeath1////----------------------------------------------------------------------------void A_ImpXDeath1(mobj_t *actor){ actor->flags &= ~MF_SOLID; actor->flags |= MF_NOGRAVITY; actor->flags |= MF_CORPSE|MF_DROPOFF; actor->height >>= 2; actor->radius -= (actor->radius>>4); //for solid corpses actor->flags2 |= MF2_FOOTCLIP; actor->special1 = 666; // Flag the crash routine}//----------------------------------------------------------------------------//// PROC A_ImpXDeath2////----------------------------------------------------------------------------void A_ImpXDeath2(mobj_t *actor){ actor->flags &= ~MF_NOGRAVITY; if(actor->z <= actor->floorz) { P_SetMobjState(actor, S_IMP_CRASH1); actor->flags &= ~MF_CORPSE; }}//----------------------------------------------------------------------------//// FUNC P_UpdateChicken//// Returns true if the chicken morphs.////----------------------------------------------------------------------------#define TELEFOGHEIGHT (32*FRACUNIT)boolean P_UpdateChicken(mobj_t *actor, int tics){ mobj_t *fog; fixed_t x; fixed_t y; fixed_t z; mobjtype_t moType; mobj_t *mo; mobj_t oldChicken; actor->special1 -= tics; if(actor->special1 > 0) { return(false); } moType = actor->special2; x = actor->x; y = actor->y; z = actor->z; oldChicken = *actor; P_SetMobjState(actor, S_FREETARGMOBJ); mo = P_SpawnMobj(x, y, z, moType); if(P_TestMobjLocation(mo) == false) { // Didn't fit P_RemoveMobj(mo); mo = P_SpawnMobj(x, y, z, MT_CHICKEN); mo->angle = oldChicken.angle; mo->flags = oldChicken.flags; mo->health = oldChicken.health; mo->target = oldChicken.target; mo->special1 = 5*35; // Next try in 5 seconds mo->special2 = moType; return(false); } mo->angle = oldChicken.angle; mo->target = oldChicken.target; fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG); S_StartSound(fog, sfx_telept); return(true);}//----------------------------------------------------------------------------//// PROC A_ChicAttack////----------------------------------------------------------------------------void A_ChicAttack(mobj_t *actor){ if(P_UpdateChicken(actor, 18)) { return; } if(!actor->target) { return; } if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, 1+(P_Random()&1)); }}//----------------------------------------------------------------------------//// PROC A_ChicLook////----------------------------------------------------------------------------void A_ChicLook(mobj_t *actor){ if(P_UpdateChicken(actor, 10)) { return; } A_Look(actor);}//----------------------------------------------------------------------------//// PROC A_ChicChase////----------------------------------------------------------------------------void A_ChicChase(mobj_t *actor){ if(P_UpdateChicken(actor, 3)) { return; } A_Chase(actor);}//----------------------------------------------------------------------------//// PROC A_ChicPain////----------------------------------------------------------------------------void A_ChicPain(mobj_t *actor){ if(P_UpdateChicken(actor, 10)) { return; } S_StartSound(actor, actor->info->painsound);}//----------------------------------------------------------------------------//// PROC A_Feathers////----------------------------------------------------------------------------void A_Feathers(mobj_t *actor){ int i; int count; mobj_t *mo; if(actor->health > 0) { // Pain count = P_Random() < 32 ? 2 : 1; } else { // Death count = 5+(P_Random()&3); } for(i = 0; i < count; i++) { mo = P_SpawnMobj(actor->x, actor->y, actor->z+20*FRACUNIT, MT_FEATHER); mo->target = actor; mo->momx = P_SignedRandom()<<8; mo->momy = P_SignedRandom()<<8; mo->momz = FRACUNIT+(P_Random()<<9); P_SetMobjState(mo, S_FEATHER1+(P_Random()&7)); }}//----------------------------------------------------------------------------//// PROC A_MummyAttack////----------------------------------------------------------------------------void A_MummyAttack(mobj_t *actor){ if(!actor->target) { return; } S_StartSound(actor, actor->info->attacksound); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(2)); S_StartSound(actor, sfx_mumat2); return; } S_StartSound(actor, sfx_mumat1);}//----------------------------------------------------------------------------//// PROC A_MummyAttack2//// Mummy leader missile attack.////----------------------------------------------------------------------------void A_MummyAttack2(mobj_t *actor){ mobj_t *mo; if(!actor->target) { return; } //S_StartSound(actor, actor->info->attacksound); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(2)); return; } mo = P_SpawnMissile(actor, actor->target, MT_MUMMYFX1); //mo = P_SpawnMissile(actor, actor->target, MT_EGGFX); if(mo != NULL) { mo->special1 = (int)actor->target; }}//----------------------------------------------------------------------------//// PROC A_MummyFX1Seek////----------------------------------------------------------------------------void A_MummyFX1Seek(mobj_t *actor){ P_SeekerMissile(actor, ANGLE_1*10, ANGLE_1*20);}//----------------------------------------------------------------------------//// PROC A_MummySoul////----------------------------------------------------------------------------void A_MummySoul(mobj_t *mummy){ mobj_t *mo; mo = P_SpawnMobj(mummy->x, mummy->y, mummy->z+10*FRACUNIT, MT_MUMMYSOUL); mo->momz = FRACUNIT;}//----------------------------------------------------------------------------//// PROC A_Sor1Pain////----------------------------------------------------------------------------void A_Sor1Pain(mobj_t *actor){ actor->special1 = 20; // Number of steps to walk fast A_Pain(actor);}//----------------------------------------------------------------------------//// PROC A_Sor1Chase////----------------------------------------------------------------------------void A_Sor1Chase(mobj_t *actor){ if(actor->special1) { actor->special1--; actor->tics -= 3; } A_Chase(actor);}//----------------------------------------------------------------------------//// PROC A_Srcr1Attack//// Sorcerer demon attack.////----------------------------------------------------------------------------void A_Srcr1Attack(mobj_t *actor){ mobj_t *mo; fixed_t momz; angle_t angle; if(!actor->target) { return; } S_StartSound(actor, actor->info->attacksound); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(8)); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -