📄 p_enemy.c
字号:
//
// Mancubus attack,
// firing three missiles (bruisers)
// in three different directions?
// Doesn't look like it.
//
#define FATSPREAD (ANG90/8)
void A_FatRaise (mobj_t *actor)
{
A_FaceTarget (actor);
S_StartSound (actor, sfx_manatk);
}
void A_FatAttack1 (mobj_t* actor)
{
mobj_t* mo;
int an;
A_FaceTarget (actor);
// Change direction to ...
actor->angle += FATSPREAD;
P_SpawnMissile (actor, actor->target, MT_FATSHOT);
mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
mo->angle += FATSPREAD;
an = mo->angle >> ANGLETOFINESHIFT;
mo->momx = FixedMul (mo->info->speed, finecosine[an]);
mo->momy = FixedMul (mo->info->speed, finesine[an]);
}
void A_FatAttack2 (mobj_t* actor)
{
mobj_t* mo;
int an;
A_FaceTarget (actor);
// Now here choose opposite deviation.
actor->angle -= FATSPREAD;
P_SpawnMissile (actor, actor->target, MT_FATSHOT);
mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
mo->angle -= FATSPREAD*2;
an = mo->angle >> ANGLETOFINESHIFT;
mo->momx = FixedMul (mo->info->speed, finecosine[an]);
mo->momy = FixedMul (mo->info->speed, finesine[an]);
}
void A_FatAttack3 (mobj_t* actor)
{
mobj_t* mo;
int an;
A_FaceTarget (actor);
mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
mo->angle -= FATSPREAD/2;
an = mo->angle >> ANGLETOFINESHIFT;
mo->momx = FixedMul (mo->info->speed, finecosine[an]);
mo->momy = FixedMul (mo->info->speed, finesine[an]);
mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
mo->angle += FATSPREAD/2;
an = mo->angle >> ANGLETOFINESHIFT;
mo->momx = FixedMul (mo->info->speed, finecosine[an]);
mo->momy = FixedMul (mo->info->speed, finesine[an]);
}
//
// SkullAttack
// Fly at the player like a missile.
//
#define SKULLSPEED (20*FRACUNIT)
void A_SkullAttack (mobj_t* actor)
{
mobj_t* dest;
angle_t an;
int dist;
if (!actor->target)
return;
dest = actor->target;
actor->flags |= MF_SKULLFLY;
S_StartSound (actor, actor->info->attacksound);
A_FaceTarget (actor);
an = actor->angle >> ANGLETOFINESHIFT;
actor->momx = FixedMul (SKULLSPEED, finecosine[an]);
actor->momy = FixedMul (SKULLSPEED, finesine[an]);
dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y);
dist = dist / SKULLSPEED;
if (dist < 1)
dist = 1;
actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
}
//
// A_PainShootSkull
// Spawn a lost soul and launch it at the target
//
void
A_PainShootSkull
( mobj_t* actor,
angle_t angle )
{
fixed_t x;
fixed_t y;
fixed_t z;
mobj_t* newmobj;
angle_t an;
int prestep;
int count;
thinker_t* currentthinker;
// count total number of skull currently on the level
count = 0;
currentthinker = thinkercap.next;
while (currentthinker != &thinkercap)
{
if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
&& ((mobj_t *)currentthinker)->type == MT_SKULL)
count++;
currentthinker = currentthinker->next;
}
// if there are allready 20 skulls on the level,
// don't spit another one
if (count > 20)
return;
// okay, there's playe for another one
an = angle >> ANGLETOFINESHIFT;
prestep =
4*FRACUNIT
+ 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
x = actor->x + FixedMul (prestep, finecosine[an]);
y = actor->y + FixedMul (prestep, finesine[an]);
z = actor->z + 8*FRACUNIT;
newmobj = P_SpawnMobj (x , y, z, MT_SKULL);
// Check for movements.
if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
{
// kill it immediately
P_DamageMobj (newmobj,actor,actor,10000);
return;
}
newmobj->target = actor->target;
A_SkullAttack (newmobj);
}
//
// A_PainAttack
// Spawn a lost soul and launch it at the target
//
void A_PainAttack (mobj_t* actor)
{
if (!actor->target)
return;
A_FaceTarget (actor);
A_PainShootSkull (actor, actor->angle);
}
void A_PainDie (mobj_t* actor)
{
A_Fall (actor);
A_PainShootSkull (actor, actor->angle+ANG90);
A_PainShootSkull (actor, actor->angle+ANG180);
A_PainShootSkull (actor, actor->angle+ANG270);
}
void A_Scream (mobj_t* actor)
{
int sound;
switch (actor->info->deathsound)
{
case 0:
return;
case sfx_podth1:
case sfx_podth2:
case sfx_podth3:
sound = sfx_podth1 + P_Random ()%3;
break;
case sfx_bgdth1:
case sfx_bgdth2:
sound = sfx_bgdth1 + P_Random ()%2;
break;
default:
sound = actor->info->deathsound;
break;
}
// Check for bosses.
if (actor->type==MT_SPIDER
|| actor->type == MT_CYBORG)
{
// full volume
S_StartSound (NULL, sound);
}
else
S_StartSound (actor, sound);
}
void A_XScream (mobj_t* actor)
{
S_StartSound (actor, sfx_slop);
}
void A_Pain (mobj_t* actor)
{
if (actor->info->painsound)
S_StartSound (actor, actor->info->painsound);
}
void A_Fall (mobj_t *actor)
{
// actor is on ground, it can be walked over
actor->flags &= ~MF_SOLID;
// So change this if corpse objects
// are meant to be obstacles.
}
//
// A_Explode
//
void A_Explode (mobj_t* thingy)
{
P_RadiusAttack ( thingy, thingy->target, 128 );
}
//
// A_BossDeath
// Possibly trigger special effects
// if on first boss level
//
void A_BossDeath (mobj_t* mo)
{
thinker_t* th;
mobj_t* mo2;
line_t junk;
int i;
if ( gamemode == commercial)
{
if (gamemap != 7)
return;
if ((mo->type != MT_FATSO)
&& (mo->type != MT_BABY))
return;
}
else
{
switch(gameepisode)
{
case 1:
if (gamemap != 8)
return;
if (mo->type != MT_BRUISER)
return;
break;
case 2:
if (gamemap != 8)
return;
if (mo->type != MT_CYBORG)
return;
break;
case 3:
if (gamemap != 8)
return;
if (mo->type != MT_SPIDER)
return;
break;
case 4:
switch(gamemap)
{
case 6:
if (mo->type != MT_CYBORG)
return;
break;
case 8:
if (mo->type != MT_SPIDER)
return;
break;
default:
return;
break;
}
break;
default:
if (gamemap != 8)
return;
break;
}
}
// make sure there is a player alive for victory
for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i] && players[i].health > 0)
break;
if (i==MAXPLAYERS)
return; // no one left alive, so do not end game
// scan the remaining thinkers to see
// if all bosses are dead
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 != mo
&& mo2->type == mo->type
&& mo2->health > 0)
{
// other boss not dead
return;
}
}
// victory!
if ( gamemode == commercial)
{
if (gamemap == 7)
{
if (mo->type == MT_FATSO)
{
junk.tag = 666;
EV_DoFloor(&junk,lowerFloorToLowest);
return;
}
if (mo->type == MT_BABY)
{
junk.tag = 667;
EV_DoFloor(&junk,raiseToTexture);
return;
}
}
}
else
{
switch(gameepisode)
{
case 1:
junk.tag = 666;
EV_DoFloor (&junk, lowerFloorToLowest);
return;
break;
case 4:
switch(gamemap)
{
case 6:
junk.tag = 666;
EV_DoDoor (&junk, blazeOpen);
return;
break;
case 8:
junk.tag = 666;
EV_DoFloor (&junk, lowerFloorToLowest);
return;
break;
}
}
}
G_ExitLevel ();
}
void A_Hoof (mobj_t* mo)
{
S_StartSound (mo, sfx_hoof);
A_Chase (mo);
}
void A_Metal (mobj_t* mo)
{
S_StartSound (mo, sfx_metal);
A_Chase (mo);
}
void A_BabyMetal (mobj_t* mo)
{
S_StartSound (mo, sfx_bspwlk);
A_Chase (mo);
}
void
A_OpenShotgun2
( player_t* player,
pspdef_t* psp )
{
S_StartSound (player->mo, sfx_dbopn);
}
void
A_LoadShotgun2
( player_t* player,
pspdef_t* psp )
{
S_StartSound (player->mo, sfx_dbload);
}
void
A_ReFire
( player_t* player,
pspdef_t* psp );
void
A_CloseShotgun2
( player_t* player,
pspdef_t* psp )
{
S_StartSound (player->mo, sfx_dbcls);
A_ReFire(player,psp);
}
mobj_t* braintargets[32];
int numbraintargets;
int braintargeton;
void A_BrainAwake (mobj_t* mo)
{
thinker_t* thinker;
mobj_t* m;
// find all the target spots
numbraintargets = 0;
braintargeton = 0;
thinker = thinkercap.next;
for (thinker = thinkercap.next ;
thinker != &thinkercap ;
thinker = thinker->next)
{
if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj
m = (mobj_t *)thinker;
if (m->type == MT_BOSSTARGET )
{
braintargets[numbraintargets] = m;
numbraintargets++;
}
}
S_StartSound (NULL,sfx_bossit);
}
void A_BrainPain (mobj_t* mo)
{
S_StartSound (NULL,sfx_bospn);
}
void A_BrainScream (mobj_t* mo)
{
int x;
int y;
int z;
mobj_t* th;
for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
{
y = mo->y - 320*FRACUNIT;
z = 128 + P_Random()*2*FRACUNIT;
th = P_SpawnMobj (x,y,z, MT_ROCKET);
th->momz = P_Random()*512;
P_SetMobjState (th, S_BRAINEXPLODE1);
th->tics -= P_Random()&7;
if (th->tics < 1)
th->tics = 1;
}
S_StartSound (NULL,sfx_bosdth);
}
void A_BrainExplode (mobj_t* mo)
{
int x;
int y;
int z;
mobj_t* th;
x = mo->x + (P_Random () - P_Random ())*2048;
y = mo->y;
z = 128 + P_Random()*2*FRACUNIT;
th = P_SpawnMobj (x,y,z, MT_ROCKET);
th->momz = P_Random()*512;
P_SetMobjState (th, S_BRAINEXPLODE1);
th->tics -= P_Random()&7;
if (th->tics < 1)
th->tics = 1;
}
void A_BrainDie (mobj_t* mo)
{
G_ExitLevel ();
}
void A_BrainSpit (mobj_t* mo)
{
mobj_t* targ;
mobj_t* newmobj;
static int easy = 0;
easy ^= 1;
if (gameskill <= sk_easy && (!easy))
return;
// shoot a cube at current target
targ = braintargets[braintargeton];
braintargeton = (braintargeton+1)%numbraintargets;
// spawn brain missile
newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
newmobj->target = targ;
newmobj->reactiontime =
((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
S_StartSound(NULL, sfx_bospit);
}
void A_SpawnFly (mobj_t* mo);
// travelling cube sound
void A_SpawnSound (mobj_t* mo)
{
S_StartSound (mo,sfx_boscub);
A_SpawnFly(mo);
}
void A_SpawnFly (mobj_t* mo)
{
mobj_t* newmobj;
mobj_t* fog;
mobj_t* targ;
int r;
mobjtype_t type;
if (--mo->reactiontime)
return; // still flying
targ = mo->target;
// First spawn teleport fog.
fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
S_StartSound (fog, sfx_telept);
// Randomly select monster to spawn.
r = P_Random ();
// Probability distribution (kind of :),
// decreasing likelihood.
if ( r<50 )
type = MT_TROOP;
else if (r<90)
type = MT_SERGEANT;
else if (r<120)
type = MT_SHADOWS;
else if (r<130)
type = MT_PAIN;
else if (r<160)
type = MT_HEAD;
else if (r<162)
type = MT_VILE;
else if (r<172)
type = MT_UNDEAD;
else if (r<192)
type = MT_BABY;
else if (r<222)
type = MT_FATSO;
else if (r<246)
type = MT_KNIGHT;
else
type = MT_BRUISER;
newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type);
if (P_LookForPlayers (newmobj, true) )
P_SetMobjState (newmobj, newmobj->info->seestate);
// telefrag anything in this spot
P_TeleportMove (newmobj, newmobj->x, newmobj->y);
// remove self (i.e., cube).
P_RemoveMobj (mo);
}
void A_PlayerScream (mobj_t* mo)
{
// Default death sound.
int sound = sfx_pldeth;
if ( (gamemode == commercial)
&& (mo->health < -50))
{
// IF THE PLAYER DIES
// LESS THAN -50% WITHOUT GIBBING
sound = sfx_pdiehi;
}
S_StartSound (mo, sound);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -