📄 p_enemy.c
字号:
// Missile attack if (actor->info->missilestate && P_CheckMissileRange(actor)) { P_SetMobjState (actor, actor->info->missilestate); return; } // chase towards target if (!P_Move(actor)) { P_NewChaseDir(actor); } // Active sound if(actor->info->activesound && P_Random() < 6) { S_StartSound(actor, actor->info->activesound); }}//----------------------------------------------------------------------------//// PROC A_MinotaurAtk1//// Melee attack.////----------------------------------------------------------------------------void A_MinotaurAtk1(mobj_t *actor){ if (!actor->target) return; S_StartSound(actor, SFX_MAULATOR_HAMMER_SWING); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(4)); }}//----------------------------------------------------------------------------//// PROC A_MinotaurDecide//// Choose a missile attack.////----------------------------------------------------------------------------#define MNTR_CHARGE_SPEED (23*FRACUNIT)void A_MinotaurDecide(mobj_t *actor){ angle_t angle; mobj_t *target = actor->target; int dist; if (!target) return; dist = P_AproxDistance(actor->x-target->x, actor->y-target->y); if(target->z+target->height > actor->z && target->z+target->height < actor->z+actor->height && dist < 16*64*FRACUNIT && dist > 1*64*FRACUNIT && P_Random() < 230) { // Charge attack // Don't call the state function right away P_SetMobjStateNF(actor, S_MNTR_ATK4_1); actor->flags |= MF_SKULLFLY; A_FaceTarget(actor); angle = actor->angle>>ANGLETOFINESHIFT; actor->momx = FixedMul(MNTR_CHARGE_SPEED, finecosine[angle]); actor->momy = FixedMul(MNTR_CHARGE_SPEED, finesine[angle]); actor->args[4] = 35/2; // Charge duration } else if(target->z == target->floorz && dist < 9*64*FRACUNIT && P_Random() < 100) { // Floor fire attack P_SetMobjState(actor, S_MNTR_ATK3_1); actor->special2 = 0; } else { // Swing attack A_FaceTarget(actor); // Don't need to call P_SetMobjState because the current state // falls through to the swing attack }}//----------------------------------------------------------------------------//// PROC A_MinotaurCharge////----------------------------------------------------------------------------void A_MinotaurCharge(mobj_t *actor){ mobj_t *puff; if (!actor->target) return; if(actor->args[4] > 0) { puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PUNCHPUFF); puff->momz = 2*FRACUNIT; actor->args[4]--; } else { actor->flags &= ~MF_SKULLFLY; P_SetMobjState(actor, actor->info->seestate); }}//----------------------------------------------------------------------------//// PROC A_MinotaurAtk2//// Swing attack.////----------------------------------------------------------------------------void A_MinotaurAtk2(mobj_t *actor){ mobj_t *mo; angle_t angle; fixed_t momz; if(!actor->target) return; S_StartSound(actor, SFX_MAULATOR_HAMMER_SWING); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(3)); return; } mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX1); if(mo) { //S_StartSound(mo, sfx_minat2); momz = mo->momz; angle = mo->angle; P_SpawnMissileAngle(actor, MT_MNTRFX1, angle-(ANG45/8), momz); P_SpawnMissileAngle(actor, MT_MNTRFX1, angle+(ANG45/8), momz); P_SpawnMissileAngle(actor, MT_MNTRFX1, angle-(ANG45/16), momz); P_SpawnMissileAngle(actor, MT_MNTRFX1, angle+(ANG45/16), momz); }}//----------------------------------------------------------------------------//// PROC A_MinotaurAtk3//// Floor fire attack.////----------------------------------------------------------------------------void A_MinotaurAtk3(mobj_t *actor){ mobj_t *mo; player_t *player; if(!actor->target) { return; } if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(3)); if((player = actor->target->player) != NULL) { // Squish the player player->deltaviewheight = -16*FRACUNIT; } } else { mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX2); if(mo != NULL) { S_StartSound(mo, SFX_MAULATOR_HAMMER_HIT); } } if(P_Random() < 192 && actor->special2 == 0) { P_SetMobjState(actor, S_MNTR_ATK3_4); actor->special2 = 1; }}//----------------------------------------------------------------------------//// PROC A_MntrFloorFire////----------------------------------------------------------------------------void A_MntrFloorFire(mobj_t *actor){ mobj_t *mo; actor->z = actor->floorz; mo = P_SpawnMobj(actor->x+((P_Random()-P_Random())<<10), actor->y+((P_Random()-P_Random())<<10), ONFLOORZ, MT_MNTRFX3); mo->target = actor->target; mo->momx = 1; // Force block checking P_CheckMissileSpawn(mo);}//----------------------------------------------------------------------------//// PROC A_Scream////----------------------------------------------------------------------------void A_Scream(mobj_t *actor){ int sound; S_StopSound(actor); if(actor->player) { if(actor->player->morphTics) { S_StartSound(actor, actor->info->deathsound); } else { // Handle the different player death screams if(actor->momz <= -39*FRACUNIT) { // Falling splat sound = SFX_PLAYER_FALLING_SPLAT; } else if(actor->health > -50) { // Normal death sound switch(actor->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_NORMAL_DEATH; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_NORMAL_DEATH; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_NORMAL_DEATH; break; default: sound = SFX_NONE; break; } } else if(actor->health > -100) { // Crazy death sound switch(actor->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_CRAZY_DEATH; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_CRAZY_DEATH; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_CRAZY_DEATH; break; default: sound = SFX_NONE; break; } } else { // Extreme death sound switch(actor->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_EXTREME1_DEATH; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_EXTREME1_DEATH; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_EXTREME1_DEATH; break; default: sound = SFX_NONE; break; } sound += P_Random()%3; // Three different extreme deaths } S_StartSound(actor, sound); } } else { S_StartSound(actor, actor->info->deathsound); }}//---------------------------------------------------------------------------//// PROC P_DropItem////---------------------------------------------------------------------------/*void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance){ mobj_t *mo; if(P_Random() > chance) { return; } mo = P_SpawnMobj(source->x, source->y, source->z+(source->height>>1), type); mo->momx = (P_Random()-P_Random())<<8; mo->momy = (P_Random()-P_Random())<<8; mo->momz = FRACUNIT*5+(P_Random()<<10); mo->flags2 |= MF2_DROPPED; mo->health = special;}*///----------------------------------------------------------------------------//// PROC A_NoBlocking////----------------------------------------------------------------------------void A_NoBlocking(mobj_t *actor){ actor->flags &= ~MF_SOLID; // Check for monsters dropping things/* switch(actor->type) { // Add the monster dropped items here case MT_MUMMYLEADERGHOST: P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84); break; default: break; }*/}//----------------------------------------------------------------------------//// PROC A_Explode//// Handles a bunch of exploding things.////----------------------------------------------------------------------------void A_Explode(mobj_t *actor){ int damage; int distance; boolean damageSelf; damage = 128; distance = 128; damageSelf = true; switch(actor->type) { case MT_FIREBOMB: // Time Bombs actor->z += 32*FRACUNIT; actor->flags &= ~MF_SHADOW; break; case MT_MNTRFX2: // Minotaur floor fire damage = 24; break; case MT_BISHOP: // Bishop radius death damage = 25+(P_Random()&15); break; case MT_HAMMER_MISSILE: // Fighter Hammer damage = 128; damageSelf = false; break; case MT_FSWORD_MISSILE: // Fighter Runesword damage = 64; damageSelf = false; break; case MT_CIRCLEFLAME: // Cleric Flame secondary flames damage = 20; damageSelf = false; break; case MT_SORCBALL1: // Sorcerer balls case MT_SORCBALL2: case MT_SORCBALL3: distance = 255; damage = 255; actor->args[0] = 1; // don't play bounce break; case MT_SORCFX1: // Sorcerer spell 1 damage = 30; break; case MT_SORCFX4: // Sorcerer spell 4 damage = 20; break; case MT_TREEDESTRUCTIBLE: damage = 10; break; case MT_DRAGON_FX2: damage = 80; damageSelf = false; break; case MT_MSTAFF_FX: damage = 64; distance = 192; damageSelf = false; break; case MT_MSTAFF_FX2: damage = 80; distance = 192; damageSelf = false; break; case MT_POISONCLOUD: damage = 4; distance = 40; break; case MT_ZXMAS_TREE: case MT_ZSHRUB2: damage = 30; distance = 64; break; default: break; } P_RadiusAttack(actor, actor->target, damage, distance, damageSelf); if(actor->z <= actor->floorz+(distance<<FRACBITS) && actor->type != MT_POISONCLOUD) { P_HitFloor(actor); }}//----------------------------------------------------------------------------//// PROC P_Massacre//// Kills all monsters.////----------------------------------------------------------------------------int P_Massacre(void){ int count; mobj_t *mo; thinker_t *think; count = 0; for(think = thinkercap.next; think != &thinkercap; think = think->next) { if(think->function != P_MobjThinker) { // Not a mobj thinker continue; } mo = (mobj_t *)think; if((mo->flags&MF_COUNTKILL) && (mo->health > 0)) { mo->flags2 &= ~(MF2_NONSHOOTABLE+MF2_INVULNERABLE); mo->flags |= MF_SHOOTABLE; P_DamageMobj(mo, NULL, NULL, 10000); count++; } } return count;}//----------------------------------------------------------------------------//// PROC A_SkullPop////----------------------------------------------------------------------------void A_SkullPop(mobj_t *actor){ mobj_t *mo; player_t *player; if(!actor->player) { return; } actor->flags &= ~MF_SOLID; mo = P_SpawnMobj(actor->x, actor->y, actor->z+48*FRACUNIT, MT_BLOODYSKULL); //mo->target = actor; mo->momx = (P_Random()-P_Random())<<9; mo->momy = (P_Random()-P_Random())<<9; mo->momz = FRACUNIT*2+(P_Random()<<6); // Attach player mobj to bloody skull player = actor->player; actor->player = NULL; actor->special1 = player->class; mo->player = player; mo->health = actor->health; mo->angle = actor->angle; player->mo = mo; player->lookdir = 0; player->damagecount = 32;}//----------------------------------------------------------------------------//// PROC A_CheckSkullFloor////----------------------------------------------------------------------------void A_CheckSkullFloor(mobj_t *actor){ if(actor->z <= actor->floorz) { P_SetMobjState(actor, S_BLOODYSKULLX1); S_StartSound(actor, SFX_DRIP); }}//----------------------------------------------------------------------------//// PROC A_CheckSkullDone////----------------------------------------------------------------------------void A_CheckSkullDone(mobj_t *actor){ if(actor->special2 == 666) { P_SetMobjState(actor, S_BLOODYSKULLX2); }}//----------------------------------------------------------------------------//// PROC A_CheckBurnGone////----------------------------------------------------------------------------void A_CheckBurnGone(mobj_t *actor){ if(actor->special2 == 666) { P_SetMobjState(actor, S_PLAY_FDTH20); }}//----------------------------------------------------------------------------//// PROC A_FreeTargMobj////----------------------------------------------------------------------------void A_FreeTargMobj(mobj_t *mo){ mo->momx = mo->momy = mo->momz = 0; mo->z = mo->ceilingz+4*FRACUNIT; mo->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_SOLID|MF_COUNTKILL); mo->flags |= MF_CORPSE|MF_DROPOFF|MF_NOGRAVITY; mo->flags2 &= ~(MF2_PASSMOBJ|MF2_LOGRAV); mo->flags2 |= MF2_DONTDRAW; mo->player = NULL; mo->health = -1000; // Don't resurrect}//----------------------------------------------------------------------------//// CorpseQueue Routines////----------------------------------------------------------------------------// Corpse queue for monsters - this should be saved out#define CORPSEQUEUESIZE 64mobj_t *corpseQueue[CORPSEQUEUESIZE];int corpseQueueSlot;// throw another corpse on the queuevoid A_QueueCorpse(mobj_t *actor){ mobj_t *corpse; if(corpseQueueSlot >= CORPSEQUEUESIZE) { // Too many corpses - remove an old one corpse = corpseQueue[corpseQueueSlot%CORPSEQUEUESIZE]; if (corpse) P_RemoveMobj(corpse); } corpseQueue[corpseQueueSlot%CORPSEQUEUESIZE] = actor; corpseQueueSlot++;}// Remove a mobj from the queue (for resurrection)void A_DeQueueCorpse(mobj_t *actor){ int slot; for (slot=0; slot<CORPSEQUEUESIZE; slot++) { if (corpseQueue[slot] == actor) { corpseQueue[slot] = NULL; break; } }}void P_InitCreatureCorpseQueue(boolean corpseScan){ thinker_t *think; mobj_t *mo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -