📄 p_enemy.c
字号:
// go into chase stateseeyou: if (actor->info->seesound) { int sound; sound = actor->info->seesound; if(actor->flags2&MF2_BOSS) { // Full volume S_StartSound(NULL, sound); } else { S_StartSound(actor, sound); } } P_SetMobjState(actor, actor->info->seestate);}/*================ A_Chase== Actor has a melee attack, so it tries to close as fast as possible===============*/void A_Chase(mobj_t *actor){ int delta; if(actor->reactiontime) { actor->reactiontime--; } // Modify target threshold if(actor->threshold) { actor->threshold--; } if(gameskill == sk_nightmare) { // Monsters move faster in nightmare mode actor->tics -= actor->tics/2; if(actor->tics < 3) { actor->tics = 3; } }//// turn towards movement direction if not there yet// if(actor->movedir < 8) { actor->angle &= (7<<29); delta = actor->angle-(actor->movedir << 29); if(delta > 0) { actor->angle -= ANG90/2; } else if(delta < 0) { actor->angle += ANG90/2; } } if(!actor->target || !(actor->target->flags&MF_SHOOTABLE)) { // look for a new target if(P_LookForPlayers(actor, true)) { // got a new target return; } P_SetMobjState(actor, actor->info->spawnstate); return; }//// don't attack twice in a row// if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if (gameskill != sk_nightmare) P_NewChaseDir (actor); return; }//// check for melee attack// if (actor->info->meleestate && P_CheckMeleeRange (actor)) { if(actor->info->attacksound) { S_StartSound (actor, actor->info->attacksound); } P_SetMobjState (actor, actor->info->meleestate); return; }//// check for missile attack// if (actor->info->missilestate) { if (gameskill < sk_nightmare && actor->movecount) goto nomissile; if (!P_CheckMissileRange (actor)) goto nomissile; P_SetMobjState (actor, actor->info->missilestate); actor->flags |= MF_JUSTATTACKED; return; }nomissile://// possibly choose another target// if (netgame && !actor->threshold && !P_CheckSight (actor, actor->target) ) { if (P_LookForPlayers(actor,true)) return; // got a new target }//// chase towards player// if (--actor->movecount<0 || !P_Move (actor)) { P_NewChaseDir (actor); }//// make active sound// if(actor->info->activesound && P_Random() < 3) { if(actor->type == MT_BISHOP && P_Random() < 128) { S_StartSound(actor, actor->info->seesound); } else if(actor->type == MT_PIG) { S_StartSound(actor, SFX_PIG_ACTIVE1+(P_Random()&1)); } else if(actor->flags2&MF2_BOSS) { S_StartSound(NULL, actor->info->activesound); } else { S_StartSound(actor, actor->info->activesound); } }}//----------------------------------------------------------------------------//// PROC A_FaceTarget////----------------------------------------------------------------------------void A_FaceTarget(mobj_t *actor){ if(!actor->target) { return; } actor->flags &= ~MF_AMBUSH; actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); if(actor->target->flags&MF_SHADOW) { // Target is a ghost actor->angle += (P_Random()-P_Random())<<21; }}//----------------------------------------------------------------------------//// PROC A_Pain////----------------------------------------------------------------------------void A_Pain(mobj_t *actor){ if(actor->info->painsound) { S_StartSound(actor, actor->info->painsound); }}//============================================================================//// A_SetInvulnerable////============================================================================void A_SetInvulnerable(mobj_t *actor){ actor->flags2 |= MF2_INVULNERABLE;}//============================================================================//// A_UnSetInvulnerable////============================================================================void A_UnSetInvulnerable(mobj_t *actor){ actor->flags2 &= ~MF2_INVULNERABLE;}//============================================================================//// A_SetReflective////============================================================================void A_SetReflective(mobj_t *actor){ actor->flags2 |= MF2_REFLECTIVE; if ((actor->type == MT_CENTAUR) || (actor->type == MT_CENTAURLEADER)) { A_SetInvulnerable(actor); }}//============================================================================//// A_UnSetReflective////============================================================================void A_UnSetReflective(mobj_t *actor){ actor->flags2 &= ~MF2_REFLECTIVE; if ((actor->type == MT_CENTAUR) || (actor->type == MT_CENTAURLEADER)) { A_UnSetInvulnerable(actor); }}//----------------------------------------------------------------------------//// FUNC P_UpdateMorphedMonster//// Returns true if the pig morphs.////----------------------------------------------------------------------------boolean P_UpdateMorphedMonster(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 oldMonster; actor->special1 -= tics; if(actor->special1 > 0) { return(false); } moType = actor->special2; switch(moType) { case MT_WRAITHB: // These must remain morphed case MT_SERPENT: case MT_SERPENTLEADER: case MT_MINOTAUR: return(false); default: break; } x = actor->x; y = actor->y; z = actor->z; oldMonster = *actor; // Save pig vars P_RemoveMobjFromTIDList(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, oldMonster.type); mo->angle = oldMonster.angle; mo->flags = oldMonster.flags; mo->health = oldMonster.health; mo->target = oldMonster.target; mo->special = oldMonster.special; mo->special1 = 5*35; // Next try in 5 seconds mo->special2 = moType; mo->tid = oldMonster.tid; memcpy(mo->args, oldMonster.args, 5); P_InsertMobjIntoTIDList(mo, oldMonster.tid); return(false); } mo->angle = oldMonster.angle; mo->target = oldMonster.target; mo->tid = oldMonster.tid; mo->special = oldMonster.special; memcpy(mo->args, oldMonster.args, 5); P_InsertMobjIntoTIDList(mo, oldMonster.tid); fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG); S_StartSound(fog, SFX_TELEPORT); return(true);}//----------------------------------------------------------------------------//// PROC A_PigLook////----------------------------------------------------------------------------void A_PigLook(mobj_t *actor){ if(P_UpdateMorphedMonster(actor, 10)) { return; } A_Look(actor);}//----------------------------------------------------------------------------//// PROC A_PigChase////----------------------------------------------------------------------------void A_PigChase(mobj_t *actor){ if(P_UpdateMorphedMonster(actor, 3)) { return; } A_Chase(actor);}//============================================================================//// A_PigAttack////============================================================================void A_PigAttack(mobj_t *actor){ if(P_UpdateMorphedMonster(actor, 18)) { return; } if(!actor->target) { return; } if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, 2+(P_Random()&1)); S_StartSound(actor, SFX_PIG_ATTACK); }}//============================================================================//// A_PigPain////============================================================================void A_PigPain(mobj_t *actor){ A_Pain(actor); if(actor->z <= actor->floorz) { actor->momz = 3.5*FRACUNIT; }}void FaceMovementDirection(mobj_t *actor){ switch(actor->movedir) { case DI_EAST: actor->angle = 0<<24; break; case DI_NORTHEAST: actor->angle = 32<<24; break; case DI_NORTH: actor->angle = 64<<24; break; case DI_NORTHWEST: actor->angle = 96<<24; break; case DI_WEST: actor->angle = 128<<24; break; case DI_SOUTHWEST: actor->angle = 160<<24; break; case DI_SOUTH: actor->angle = 192<<24; break; case DI_SOUTHEAST: actor->angle = 224<<24; break; }}//----------------------------------------------------------------------------//// Minotaur variables//// special1 pointer to player that spawned it (mobj_t)// special2 internal to minotaur AI// args[0] args[0]-args[3] together make up minotaur start time// args[1] |// args[2] |// args[3] V// args[4] charge duration countdown//----------------------------------------------------------------------------void A_MinotaurFade0(mobj_t *actor){ actor->flags &= ~MF_ALTSHADOW; actor->flags |= MF_SHADOW;}void A_MinotaurFade1(mobj_t *actor){ // Second level of transparency actor->flags &= ~MF_SHADOW; actor->flags |= MF_ALTSHADOW;}void A_MinotaurFade2(mobj_t *actor){ // Make fully visible actor->flags &= ~MF_SHADOW; actor->flags &= ~MF_ALTSHADOW;}//----------------------------------------------------------------------------//// A_MinotaurRoam - //// //----------------------------------------------------------------------------void A_MinotaurLook(mobj_t *actor);void A_MinotaurRoam(mobj_t *actor){ unsigned int *starttime = (unsigned int *)actor->args; actor->flags &= ~MF_SHADOW; // In case pain caused him to actor->flags &= ~MF_ALTSHADOW; // skip his fade in. if ((leveltime - *starttime) >= MAULATORTICS) { P_DamageMobj(actor,NULL,NULL,10000); return; } if (P_Random()<30) A_MinotaurLook(actor); // adjust to closest target if (P_Random()<6) { //Choose new direction actor->movedir = P_Random() % 8; FaceMovementDirection(actor); } if (!P_Move(actor)) { // Turn if (P_Random() & 1) actor->movedir = (++actor->movedir)%8; else actor->movedir = (actor->movedir+7)%8; FaceMovementDirection(actor); }}//----------------------------------------------------------------------------//// PROC A_MinotaurLook//// Look for enemy of player//----------------------------------------------------------------------------#define MINOTAUR_LOOK_DIST (16*54*FRACUNIT)void A_MinotaurLook(mobj_t *actor){ mobj_t *mo=NULL; player_t *player; thinker_t *think; fixed_t dist; int i; mobj_t *master = (mobj_t *)(actor->special1); actor->target = NULL; if (deathmatch) // Quick search for players { for (i=0; i<MAXPLAYERS; i++) { if (!playeringame[i]) continue; player = &players[i]; mo = player->mo; if (mo == master) continue; if (mo->health <= 0) continue; dist = P_AproxDistance(actor->x - mo->x, actor->y - mo->y); if (dist > MINOTAUR_LOOK_DIST) continue; actor->target = mo; break; } } if (!actor->target) // Near player monster search { if (master && (master->health>0) && (master->player)) mo = P_RoughMonsterSearch(master, 20); else mo = P_RoughMonsterSearch(actor, 20); actor->target = mo; } if (!actor->target) // Normal monster search { for(think = thinkercap.next; think != &thinkercap; think = think->next) { if(think->function != P_MobjThinker) continue; mo = (mobj_t *)think; if (!(mo->flags&MF_COUNTKILL)) continue; if (mo->health <= 0) continue; if (!(mo->flags&MF_SHOOTABLE)) continue; dist = P_AproxDistance(actor->x - mo->x, actor->y - mo->y); if (dist > MINOTAUR_LOOK_DIST) continue; if ((mo == master) || (mo == actor)) continue; if ((mo->type == MT_MINOTAUR) && (mo->special1 == actor->special1)) continue; actor->target = mo; break; // Found mobj to attack } } if (actor->target) { P_SetMobjStateNF(actor, S_MNTR_WALK1); } else { P_SetMobjStateNF(actor, S_MNTR_ROAM1); }}void A_MinotaurChase(mobj_t *actor){ unsigned int *starttime = (unsigned int *)actor->args; actor->flags &= ~MF_SHADOW; // In case pain caused him to actor->flags &= ~MF_ALTSHADOW; // skip his fade in. if ((leveltime - *starttime) >= MAULATORTICS) { P_DamageMobj(actor,NULL,NULL,10000); return; } if (P_Random()<30) A_MinotaurLook(actor); // adjust to closest target if (!actor->target || (actor->target->health <= 0) || !(actor->target->flags&MF_SHOOTABLE)) { // look for a new target P_SetMobjState(actor, S_MNTR_LOOK1); return; } FaceMovementDirection(actor); actor->reactiontime=0; // Melee attack if (actor->info->meleestate && P_CheckMeleeRange(actor)) { if(actor->info->attacksound) { S_StartSound (actor, actor->info->attacksound); } P_SetMobjState (actor, actor->info->meleestate); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -