📄 p_enemy.c
字号:
//
void A_Chase (mobj_t* actor)
{
int delta;
if (actor->reactiontime)
actor->reactiontime--;
// modify target threshold
if (actor->threshold)
{
if (!actor->target
|| actor->target->health <= 0)
{
actor->threshold = 0;
}
else
actor->threshold--;
}
// 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))
return; // got a new target
P_SetMobjState (actor, actor->info->spawnstate);
return;
}
// do not attack twice in a row
if (actor->flags & MF_JUSTATTACKED)
{
actor->flags &= ~MF_JUSTATTACKED;
if (gameskill != sk_nightmare && !fastparm)
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
&& !fastparm && 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)
{
S_StartSound (actor, actor->info->activesound);
}
}
//
// 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)
actor->angle += (P_Random()-P_Random())<<21;
}
//
// A_PosAttack
//
void A_PosAttack (mobj_t* actor)
{
int angle;
int damage;
int slope;
if (!actor->target)
return;
A_FaceTarget (actor);
angle = actor->angle;
slope = P_AimLineAttack (actor, angle, MISSILERANGE);
S_StartSound (actor, sfx_pistol);
angle += (P_Random()-P_Random())<<20;
damage = ((P_Random()%5)+1)*3;
P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
}
void A_SPosAttack (mobj_t* actor)
{
int i;
int angle;
int bangle;
int damage;
int slope;
if (!actor->target)
return;
S_StartSound (actor, sfx_shotgn);
A_FaceTarget (actor);
bangle = actor->angle;
slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
for (i=0 ; i<3 ; i++)
{
angle = bangle + ((P_Random()-P_Random())<<20);
damage = ((P_Random()%5)+1)*3;
P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
}
}
void A_CPosAttack (mobj_t* actor)
{
int angle;
int bangle;
int damage;
int slope;
if (!actor->target)
return;
S_StartSound (actor, sfx_shotgn);
A_FaceTarget (actor);
bangle = actor->angle;
slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
angle = bangle + ((P_Random()-P_Random())<<20);
damage = ((P_Random()%5)+1)*3;
P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
}
void A_CPosRefire (mobj_t* actor)
{
// keep firing unless target got out of sight
A_FaceTarget (actor);
if (P_Random () < 40)
return;
if (!actor->target
|| actor->target->health <= 0
|| !P_CheckSight (actor, actor->target) )
{
P_SetMobjState (actor, actor->info->seestate);
}
}
void A_SpidRefire (mobj_t* actor)
{
// keep firing unless target got out of sight
A_FaceTarget (actor);
if (P_Random () < 10)
return;
if (!actor->target
|| actor->target->health <= 0
|| !P_CheckSight (actor, actor->target) )
{
P_SetMobjState (actor, actor->info->seestate);
}
}
void A_BspiAttack (mobj_t *actor)
{
if (!actor->target)
return;
A_FaceTarget (actor);
// launch a missile
P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ);
}
//
// A_TroopAttack
//
void A_TroopAttack (mobj_t* actor)
{
int damage;
if (!actor->target)
return;
A_FaceTarget (actor);
if (P_CheckMeleeRange (actor))
{
S_StartSound (actor, sfx_claw);
damage = (P_Random()%8+1)*3;
P_DamageMobj (actor->target, actor, actor, damage);
return;
}
// launch a missile
P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);
}
void A_SargAttack (mobj_t* actor)
{
int damage;
if (!actor->target)
return;
A_FaceTarget (actor);
if (P_CheckMeleeRange (actor))
{
damage = ((P_Random()%10)+1)*4;
P_DamageMobj (actor->target, actor, actor, damage);
}
}
void A_HeadAttack (mobj_t* actor)
{
int damage;
if (!actor->target)
return;
A_FaceTarget (actor);
if (P_CheckMeleeRange (actor))
{
damage = (P_Random()%6+1)*10;
P_DamageMobj (actor->target, actor, actor, damage);
return;
}
// launch a missile
P_SpawnMissile (actor, actor->target, MT_HEADSHOT);
}
void A_CyberAttack (mobj_t* actor)
{
if (!actor->target)
return;
A_FaceTarget (actor);
P_SpawnMissile (actor, actor->target, MT_ROCKET);
}
void A_BruisAttack (mobj_t* actor)
{
int damage;
if (!actor->target)
return;
if (P_CheckMeleeRange (actor))
{
S_StartSound (actor, sfx_claw);
damage = (P_Random()%8+1)*10;
P_DamageMobj (actor->target, actor, actor, damage);
return;
}
// launch a missile
P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT);
}
//
// A_SkelMissile
//
void A_SkelMissile (mobj_t* actor)
{
mobj_t* mo;
if (!actor->target)
return;
A_FaceTarget (actor);
actor->z += 16*FRACUNIT; // so missile spawns higher
mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
actor->z -= 16*FRACUNIT; // back to normal
mo->x += mo->momx;
mo->y += mo->momy;
mo->tracer = actor->target;
}
int TRACEANGLE = 0xc000000;
void A_Tracer (mobj_t* actor)
{
angle_t exact;
fixed_t dist;
fixed_t slope;
mobj_t* dest;
mobj_t* th;
if (gametic & 3)
return;
// spawn a puff of smoke behind the rocket
P_SpawnPuff (actor->x, actor->y, actor->z);
th = P_SpawnMobj (actor->x-actor->momx,
actor->y-actor->momy,
actor->z, MT_SMOKE);
th->momz = FRACUNIT;
th->tics -= P_Random()&3;
if (th->tics < 1)
th->tics = 1;
// adjust direction
dest = actor->tracer;
if (!dest || dest->health <= 0)
return;
// change angle
exact = R_PointToAngle2 (actor->x,
actor->y,
dest->x,
dest->y);
if (exact != actor->angle)
{
if (exact - actor->angle > 0x80000000)
{
actor->angle -= TRACEANGLE;
if (exact - actor->angle < 0x80000000)
actor->angle = exact;
}
else
{
actor->angle += TRACEANGLE;
if (exact - actor->angle > 0x80000000)
actor->angle = exact;
}
}
exact = actor->angle>>ANGLETOFINESHIFT;
actor->momx = FixedMul (actor->info->speed, finecosine[exact]);
actor->momy = FixedMul (actor->info->speed, finesine[exact]);
// change slope
dist = P_AproxDistance (dest->x - actor->x,
dest->y - actor->y);
dist = dist / actor->info->speed;
if (dist < 1)
dist = 1;
slope = (dest->z+40*FRACUNIT - actor->z) / dist;
if (slope < actor->momz)
actor->momz -= FRACUNIT/8;
else
actor->momz += FRACUNIT/8;
}
void A_SkelWhoosh (mobj_t* actor)
{
if (!actor->target)
return;
A_FaceTarget (actor);
S_StartSound (actor,sfx_skeswg);
}
void A_SkelFist (mobj_t* actor)
{
int damage;
if (!actor->target)
return;
A_FaceTarget (actor);
if (P_CheckMeleeRange (actor))
{
damage = ((P_Random()%10)+1)*6;
S_StartSound (actor, sfx_skepch);
P_DamageMobj (actor->target, actor, actor, damage);
}
}
//
// PIT_VileCheck
// Detect a corpse that could be raised.
//
mobj_t* corpsehit;
mobj_t* vileobj;
fixed_t viletryx;
fixed_t viletryy;
boolean PIT_VileCheck (mobj_t* thing)
{
int maxdist;
boolean check;
if (!(thing->flags & MF_CORPSE) )
return true; // not a monster
if (thing->tics != -1)
return true; // not lying still yet
if (thing->info->raisestate == S_NULL)
return true; // monster doesn't have a raise state
maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
if ( abs(thing->x - viletryx) > maxdist
|| abs(thing->y - viletryy) > maxdist )
return true; // not actually touching
corpsehit = thing;
corpsehit->momx = corpsehit->momy = 0;
corpsehit->height <<= 2;
check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
corpsehit->height >>= 2;
if (!check)
return true; // doesn't fit here
return false; // got one, so stop checking
}
//
// A_VileChase
// Check for ressurecting a body
//
void A_VileChase (mobj_t* actor)
{
int xl;
int xh;
int yl;
int yh;
int bx;
int by;
mobjinfo_t* info;
mobj_t* temp;
if (actor->movedir != DI_NODIR)
{
// check for corpses to raise
viletryx =
actor->x + actor->info->speed*xspeed[actor->movedir];
viletryy =
actor->y + actor->info->speed*yspeed[actor->movedir];
xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
vileobj = actor;
for (bx=xl ; bx<=xh ; bx++)
{
for (by=yl ; by<=yh ; by++)
{
// Call PIT_VileCheck to check
// whether object is a corpse
// that canbe raised.
if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
{
// got one!
temp = actor->target;
actor->target = corpsehit;
A_FaceTarget (actor);
actor->target = temp;
P_SetMobjState (actor, S_VILE_HEAL1);
S_StartSound (corpsehit, sfx_slop);
info = corpsehit->info;
P_SetMobjState (corpsehit,info->raisestate);
corpsehit->height <<= 2;
corpsehit->flags = info->flags;
corpsehit->health = info->spawnhealth;
corpsehit->target = NULL;
return;
}
}
}
}
// Return to normal attack.
A_Chase (actor);
}
//
// A_VileStart
//
void A_VileStart (mobj_t* actor)
{
S_StartSound (actor, sfx_vilatk);
}
//
// A_Fire
// Keep fire in front of player unless out of sight
//
void A_Fire (mobj_t* actor);
void A_StartFire (mobj_t* actor)
{
S_StartSound(actor,sfx_flamst);
A_Fire(actor);
}
void A_FireCrackle (mobj_t* actor)
{
S_StartSound(actor,sfx_flame);
A_Fire(actor);
}
void A_Fire (mobj_t* actor)
{
mobj_t* dest;
unsigned an;
dest = actor->tracer;
if (!dest)
return;
// don't move it if the vile lost sight
if (!P_CheckSight (actor->target, dest) )
return;
an = dest->angle >> ANGLETOFINESHIFT;
P_UnsetThingPosition (actor);
actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]);
actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]);
actor->z = dest->z;
P_SetThingPosition (actor);
}
//
// A_VileTarget
// Spawn the hellfire
//
void A_VileTarget (mobj_t* actor)
{
mobj_t* fog;
if (!actor->target)
return;
A_FaceTarget (actor);
fog = P_SpawnMobj (actor->target->x,
actor->target->x,
actor->target->z, MT_FIRE);
actor->tracer = fog;
fog->target = actor;
fog->tracer = actor->target;
A_Fire (fog);
}
//
// A_VileAttack
//
void A_VileAttack (mobj_t* actor)
{
mobj_t* fire;
int an;
if (!actor->target)
return;
A_FaceTarget (actor);
if (!P_CheckSight (actor, actor->target) )
return;
S_StartSound (actor, sfx_barexp);
P_DamageMobj (actor->target, actor, actor, 20);
actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
an = actor->angle >> ANGLETOFINESHIFT;
fire = actor->tracer;
if (!fire)
return;
// move the fire between the vile and the player
fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
P_RadiusAttack (fire, actor, 70 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -