Changes for Game Module Files
In g_local.h about line 67 add :
typedef struct gentity_s gentity_t;
typedef struct gclient_s gclient_t;
#ifdef SINGLEPLAYER // npc
typedef enum {
NPC_ST_INACTIVE,
NPC_ST_ACTIVE,
NPC_ST_DEAD
} npcState_t;
typedef enum {
NPC_COM_NONE,
NPC_COM_WAIT,
NPC_COM_GOTO,
NPC_COM_ATTACK,
NPC_COM_SEARCH
} npcCommand_t;
typedef struct {
playerState_t ps;
vec3_t initpos;
vec3_t obj;
vec3_t real_obj;
gentity_t *enemy;
npcCommand_t command;
npcState_t state;
int flyingAlt;
int painAcum;
int dontMoveTime;
float ideal_angle;
int attackTime;
int toFire;
int fireTime;
int meleeTime;
int canStand;
int checkTime;
float shot_factor;
int inFlight;
int altitude;
int goingBack;
int fireCount;
int quakeTime;
} npcData_t;
typedef struct {
vec3_t forward, right, up;
float frametime;
int msec;
int can_do_back_move;
qboolean walking;
qboolean groundPlane;
trace_t groundTrace;
float impactSpeed;
vec3_t previous_origin;
vec3_t previous_velocity;
int previous_waterlevel;
} npml_t;
typedef struct {
// state (in / out)
playerState_t *ps;
gnpc_t *npc;
npcData_t *ns;
// command (in)
usercmd_t cmd;
int tracemask; // collide against these types of surfaces
int debugLevel; // if set, diagnostic output will be printed
qboolean noFootsteps; // if the game is setup for no footsteps by the server
qboolean gauntletHit; // true if a gauntlet attack would actually hit something
int framecount;
// results (out)
int numtouch;
int touchents[MAXTOUCH];
vec3_t mins, maxs; // bounding box size
int watertype;
int waterlevel;
float xyspeed;
// for fixed msec Pmove
int pmove_fixed;
int pmove_msec;
// callbacks to test the world
// these will be different functions during game and cgame
void (*trace)( trace_t *results, const vec3_t start, const vec3_t mins,
const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask );
int (*pointcontents)( const vec3_t point, int passEntityNum );
} npmove_t;
#endif
In g_local.h in struct gentity_s about line 253 add :
// timing variables
float wait;
float random;
gitem_t *item; // for bonus items
#ifdef SINGLEPLAYER // npc
gnpc_t *npc;
npcData_t ns;
int slow_event;
#endif
};
In g_local.h about line 610 add :
gentity_t *fire_rocket (gentity_t *self, vec3_t start, vec3_t dir);
gentity_t *fire_bfg (gentity_t *self, vec3_t start, vec3_t dir);
gentity_t *fire_grapple (gentity_t *self, vec3_t start, vec3_t dir);
#ifdef SINGLEPLAYER // npc
gentity_t *fire_ank_shot (gentity_t *self, vec3_t start, vec3_t dir,gentity_t *enemy);
gentity_t *fire_bat_shot (gentity_t *self, vec3_t start, vec3_t dir);
gentity_t *fire_sealord_big_shot (gentity_t *self, vec3_t start, vec3_t dir);
gentity_t *fire_sealord_small_shot (gentity_t *self, vec3_t start, vec3_t dir);
#endif
In g_local.h about line 652 add :
void Weapon_HookFree (gentity_t *ent);
void Weapon_HookThink (gentity_t *ent);
#ifdef SINGLEPLAYER // npc
void NPC_FireWeapon(gentity_t *ent,vec3_t angle);
#endif
In g_local.h about line 696 add :
void MoveClientToIntermission (gentity_t *client);
void G_SetStats (gentity_t *ent);
void DeathmatchScoreboardMessage (gentity_t *client);
#ifdef SINGLEPLAYER // npc
//
// g_npcs.c
//
extern int npc_skill;
void ClearRegisteredNPCs( void );
void RegisterNPC( gnpc_t *npc );
void SaveRegisteredNPCs( void );
void G_RunNPC( gentity_t *ent );
//
// g_npcmove.c
//
void NPC_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap );
void NPM_StartLegsAnim(int anim);
void NPM_ForceLegsAnim(int anim);
void NPM_ContinueLegsAnim(int anim);
void NPmove( npmove_t *pmove );
//
// g_npcthink.c
//
void NPC_ThinkMove(gentity_t *ent,usercmd_t *ucmd);
void NPC_ThinkView(gentity_t *ent,usercmd_t *ucmd);
void NPC_FindTarget(gentity_t *ent);
int NPC_RecalcLinearObj(gentity_t *ent);
qboolean NPC_InFieldOfVision(vec3_t viewangles, float fov, vec3_t angles);
int NPC_IsVisible(gentity_t *viewer,gentity_t *ent);
#endif
In g_local.h about line 856 add :
#ifdef SINGLEPLAYER // npc
#define NPCOFS(x) ((int)&(((gnpc_t *)0)->x))
#endif
extern vmCvar_t g_gametype;
extern vmCvar_t g_dedicated;
In g_active.c in function ClientThink_real about line 769 add :
// mark the time, so the connection sprite can be removed
ucmd = &ent->client->pers.cmd;
#ifdef SINGLEPLAYER // npc
ucmd->buttons &= ~BUTTON_USE_HOLDABLE;
if (ent->slow_event) {
if (ent->slow_event>level.time)
{
ucmd->forwardmove/=4;
ucmd->rightmove/=4;
ucmd->upmove/=4;
}
else
ent->slow_event=0;
}
#endif
// sanity check the command time to prevent speedup cheating
if ( ucmd->serverTime > level.time + 200 ) {
In g_client.c in function ClientSpawn about line 1185 add :
VectorCopy (playerMins, ent->r.mins);
VectorCopy (playerMaxs, ent->r.maxs);
client->ps.clientNum = index;
#ifdef SINGLEPLAYER // npc
ent->slow_event=level.time+1000;
#endif
#ifndef SINGLEPLAYER
client->ps.stats[STAT_WEAPONS] = ( 1 << WP_MACHINEGUN );
In g_combat.c in function G_Damage about line 975 add :
#ifndef SINGLEPLAYER // npc
// add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
if ( attacker->client && targ != attacker && targ->health > 0
&& targ->s.eType != ET_MISSILE
&& targ->s.eType != ET_GENERAL) {
if ( OnSameTeam( targ, attacker ) ) {
attacker->client->ps.persistant[PERS_HITS]--;
} else {
attacker->client->ps.persistant[PERS_HITS]++;
}
attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]);
}
#endif
In g_items.c in function ClearRegisteredItems about line 804 add :
RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) );
RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) );
#ifdef SINGLEPLAYER // npc
RegisterItem( BG_FindItemForWeapon( WP_FIREBALL ) );
RegisterItem( BG_FindItemForWeapon( WP_BAT ) );
RegisterItem( BG_FindItemForWeapon( WP_SEA1 ) );
RegisterItem( BG_FindItemForWeapon( WP_SEA2 ) );
RegisterItem( BG_FindItemForWeapon( WP_GUN ) );
#endif
In g_main.c in function G_InitGame about line 479 add :
// reserve some spots for dead player bodies
InitBodyQue();
ClearRegisteredItems();
#ifdef SINGLEPLAYER // npc
ClearRegisteredNPCs();
#endif
// parse the key/value pairs and spawn gentities
G_SpawnEntitiesFromString();
In g_main.c in function G_InitGame about line 495 add :
SaveRegisteredItems();
#ifdef SINGLEPLAYER // npc
SaveRegisteredNPCs();
#endif
G_Printf ("-----------------------------------\n");
In g_main.c in function G_RunFrame about line 1812 add :
if ( ent->s.eType == ET_ITEM || ent->physicsObject ) {
G_RunItem( ent );
continue;
}
#ifdef SINGLEPLAYER // npc
if (ent->s.eType == ET_NPC) {
G_RunNPC(ent);
continue;
}
#endif
if ( ent->s.eType == ET_MOVER ) {
G_RunMover( ent );
continue;
}
In g_missle.c at the end of the file add :
#ifdef SINGLEPLAYER // npc
#define ANK_SHOT_SPEED 960
#define BAT_SHOT_SPEED 1200
#define SEALORD_BIG_SHOT_SPEED 1200
#define SEALORD_SMALL_SHOT_SPEED 550
//
// ank homing missile, bat & sealord fire
//
void ank_shot_think( gentity_t *ent ) {
vec3_t targetdir, forward, midbody;
trace_t tr;
gentity_t *enemy;
int length;
enemy=ent->ns.enemy;
if (enemy->health<=0) return;
VectorCopy(ent->s.pos.trDelta, forward);
VectorNormalize(forward);
midbody[0] = enemy->r.currentOrigin[0] +
(enemy->r.mins[0] + enemy->r.maxs[0]) * 0.5;
midbody[1] = enemy->r.currentOrigin[1] +
(enemy->r.mins[1] + enemy->r.maxs[1]) * 0.5;
midbody[2] = enemy->r.currentOrigin[2] +
(enemy->r.mins[2] + enemy->r.maxs[2]) * 0.5;
VectorSubtract(midbody, ent->r.currentOrigin, targetdir);
length = VectorLength(targetdir);
targetdir[0] /= length;
targetdir[1] /= length;
targetdir[2] /= length;
if ( DotProduct(forward, targetdir) < 0.93 ) return;
trap_Trace( &tr, ent->r.currentOrigin, NULL, NULL,
enemy->r.currentOrigin, ENTITYNUM_NONE, MASK_SHOT );
if ( enemy != &g_entities[tr.entityNum] ) return;
ent->nextthink = level.time+1;
VectorMA(forward, 0.08, targetdir, targetdir); // 0.05 es mas suave!
VectorNormalize(targetdir);
VectorScale(targetdir, ANK_SHOT_SPEED, ent->s.pos.trDelta);
}
/*
=================
fire_ank_shot
=================
*/
gentity_t *fire_ank_shot (gentity_t *self, vec3_t start, vec3_t dir,gentity_t *enemy) {
gentity_t *bolt;
VectorNormalize (dir);
bolt = G_Spawn();
bolt->classname = "rocket";
bolt->nextthink = level.time + 1;
bolt->think = ank_shot_think;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
bolt->s.weapon = WP_FIREBALL;
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->ns.enemy=enemy;
bolt->damage = 30*(1+0.25*npc_skill);
bolt->splashDamage = 15*(1+0.25*npc_skill);
bolt->splashRadius = 40;
bolt->methodOfDeath = MOD_ROCKET;
bolt->splashMethodOfDeath = MOD_ROCKET_SPLASH;
bolt->clipmask = MASK_SHOT;
bolt->target_ent = NULL;
bolt->s.pos.trType = TR_LINEAR;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, ANK_SHOT_SPEED, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);
return bolt;
}
/*
=================
fire_bat
=================
*/
gentity_t *fire_bat_shot (gentity_t *self, vec3_t start, vec3_t dir) {
gentity_t *bolt;
VectorNormalize (dir);
bolt = G_Spawn();
bolt->classname = "bfg";
bolt->nextthink = level.time + 10000;
bolt->think = G_ExplodeMissile;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
bolt->s.weapon = WP_BAT;
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->damage = 30*(1+0.25*npc_skill);;
bolt->splashDamage = 15*(1+0.25*npc_skill);;
bolt->splashRadius = 40;
bolt->methodOfDeath = MOD_BFG;
bolt->splashMethodOfDeath = MOD_BFG_SPLASH;
bolt->clipmask = MASK_SHOT;
bolt->target_ent = NULL;
bolt->s.pos.trType = TR_LINEAR;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, BAT_SHOT_SPEED, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);
return bolt;
}
/*
=================
fire_sealord
=================
*/
gentity_t *fire_sealord_big_shot (gentity_t *self, vec3_t start, vec3_t dir) {
gentity_t *bolt;
VectorNormalize (dir);
bolt = G_Spawn();
bolt->classname = "grenade";
bolt->nextthink = level.time + 10000;
bolt->think = G_ExplodeMissile;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
bolt->s.weapon = WP_SEA1;
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->damage = 10000000;
bolt->splashDamage = 35*(1+0.25*npc_skill);
bolt->splashRadius = 30;
bolt->methodOfDeath = MOD_BFG;
bolt->splashMethodOfDeath = MOD_BFG_SPLASH;
bolt->clipmask = MASK_SHOT;
bolt->target_ent = NULL;
bolt->s.pos.trType = TR_LINEAR;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, SEALORD_BIG_SHOT_SPEED, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);
return bolt;
}
gentity_t *fire_sealord_small_shot (gentity_t *self, vec3_t start, vec3_t dir) {
gentity_t *bolt;
VectorNormalize (dir);
bolt = G_Spawn();
bolt->classname = "railgun";
bolt->nextthink = level.time + 10000;
bolt->think = G_ExplodeMissile;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
bolt->s.weapon = WP_SEA2;
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->damage = 20*(1+0.25*npc_skill);
bolt->splashDamage = 10*(1+0.25*npc_skill);
bolt->splashRadius = 30;
bolt->methodOfDeath = MOD_BFG;
bolt->splashMethodOfDeath = MOD_BFG_SPLASH;
bolt->clipmask = MASK_SHOT;
bolt->target_ent = NULL;
bolt->s.pos.trType = TR_LINEAR;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, SEALORD_SMALL_SHOT_SPEED, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);
return bolt;
}
#endif
In g_mover.c in function G_MoverPush about line 358 add :
// only push items and players
#ifndef SINGLEPLAYER // npc
if ( check->s.eType != ET_ITEM && check->s.eType != ET_PLAYER && !check->physicsObject ) {
#else
if ( check->s.eType != ET_ITEM && check->s.eType != ET_NPC &&
check->s.eType != ET_PLAYER && !check->physicsObject ) {
#endif
continue;
}
In g_mover.c in function Blocked_Door about line 812 add :
Team_DroppedFlagThink( other );
return;
}
#ifdef SINGLEPLAYER // npc
if (other->s.eType==ET_NPC)
return;
#endif
G_TempEntity( other->s.origin, EV_ITEM_POP );
G_FreeEntity( other );
In g_savestate.c about line 53 add :
extern void AimAtTarget ( gentity_t * self ) ;
extern void func_timer_think ( gentity_t * self ) ;
#ifdef SINGLEPLAYER // npc
extern void ank_shot_think ( gentity_t * ent ) ;
extern void FinishSpawningNPC ( gentity_t * ent ) ;
#endif
In g_savestate.c about line 95 add :
extern void hurt_use ( gentity_t * self , gentity_t * other , gentity_t * activator ) ;
extern void func_timer_use ( gentity_t * self , gentity_t * other , gentity_t * activator ) ;
#ifdef SINGLEPLAYER // npc
extern void trig_FinishSpawningNPC ( gentity_t * ent , gentity_t * a , gentity_t * b ) ;
#endif
// pain functions
#ifdef SINGLEPLAYER // npc
extern void PainNPC ( gentity_t * self , gentity_t * attacker , int damage ) ;
#endif
// die functions
extern void body_die ( gentity_t * self , gentity_t * inflictor , gentity_t * attacker ,
int damage , int meansOfDeath ) ;
extern void player_die ( gentity_t * self , gentity_t * inflictor , gentity_t * attacker ,
int damage , int meansOfDeath ) ;
#ifdef SINGLEPLAYER // npc
extern void DieNPC ( gentity_t * self , gentity_t * inflictor , gentity_t * attacker ,
int damage , int mod ) ;
#endif
In g_savestate.c about line 136 add :
{"AimAtTarget", (byte *)AimAtTarget},
{"func_timer_think", (byte *)func_timer_think},
#ifdef SINGLEPLAYER // npc
{"ank_shot_think", (byte *)ank_shot_think},
{"FinishSpawningNPC", (byte *)FinishSpawningNPC},
#endif
In g_savestate.c about line 178 add :
{"hurt_use", (byte *)hurt_use},
{"func_timer_use", (byte *)func_timer_use},
#ifdef SINGLEPLAYER // npc
{"trig_FinishSpawningNPC", (byte *)trig_FinishSpawningNPC},
#endif
// pain functions
#ifdef SINGLEPLAYER // npc
{"PainNPC", (byte *)PainNPC},
#endif
// die functions
{"body_die", (byte *)body_die},
{"player_die", (byte *)player_die},
#ifdef SINGLEPLAYER // npc
{"DieNPC", (byte *)DieNPC},
#endif
In g_savestate.c about line 250 add :
{FOFS(teammaster), F_ENTITY},
{FOFS(item), F_ITEM},
#ifdef SINGLEPLAYER // npc
{FOFS(ns.enemy), F_ENTITY},
#endif
In g_savestate.c about line 276 add :
//
// Entity ignore pointers
//
static ignoreField_t gentityIgnoreFields[] = {
#ifdef SINGLEPLAYER // npc
{FOFS(npc), sizeof(gnpc_t *)},
#endif
In g_savestate.c about line 728 add :
ClientThink( ent-g_entities );
}
#ifdef SINGLEPLAYER // npc
//
// NPC time data fixup
//
void NPCTime (gentity_t *ent, int leveltime)
{
if(ent->ns.checkTime!=0)
ent->ns.checkTime = ent->ns.checkTime - leveltime + level.time ;
if(ent->ns.dontMoveTime!=0)
ent->ns.dontMoveTime = ent->ns.dontMoveTime - leveltime + level.time ;
if(ent->ns.attackTime!=0)
ent->ns.attackTime = ent->ns.attackTime - leveltime + level.time ;
if(ent->ns.fireTime!=0)
ent->ns.fireTime = ent->ns.fireTime - leveltime + level.time ;
if(ent->ns.meleeTime!=0)
ent->ns.meleeTime = ent->ns.meleeTime - leveltime + level.time ;
if(ent->ns.quakeTime!=0)
ent->ns.quakeTime = ent->ns.quakeTime - leveltime + level.time ;
if(ent->ns.ps.commandTime!=0)
ent->ns.ps.commandTime = ent->ns.ps.commandTime - leveltime + level.time ;
}
#endif
//
// Entity time fixup
//
void EntTime (gentity_t *ent, int leveltime)
In g_savestate.c in function ReadEntity about line 728 add :
// now copy the temp structure into the existing structure
memcpy( ent, &temp, size );
#ifdef SINGLEPLAYER // npc
//
// Fixup NPCs that are dead to show only last frame of animation
//
if(ent->npc && ent->health<=0)
{
ent->ns.ps.eFlags |= EF_FORCE_END_FRAME;
}
#endif
//
// Fixup entity times
//
EntTime (ent, leveltime);
#ifdef SINGLEPLAYER // npc
NPCTime (ent, leveltime);
#endif
// notify server of changes in position/orientation
if (ent->r.linked) {
In g_spawn.c about line 197 add :
void SP_item_botroam( gentity_t *ent ) {};
#ifdef SINGLEPLAYER // npc
void SP_npc( gentity_t *ent,gnpc_t *npc);
void SP_npcpath( gentity_t *ent);
#endif
spawn_t spawns[] = {
In g_spawn.c about line 278 add :
{"item_botroam", SP_item_botroam},
#ifdef SINGLEPLAYER // npc
{"npcpath", SP_npcpath},
#endif
{0, 0}
};
In g_spawn.c in function G_CallSpawn about line 293 add :
qboolean G_CallSpawn( gentity_t *ent ) {
spawn_t *s;
gitem_t *item;
#ifdef SINGLEPLAYER // npc
gnpc_t *npc;
#endif
if ( !ent->classname ) {
G_Printf ("G_CallSpawn: NULL classname\n");
return qfalse;
}
#ifdef SINGLEPLAYER // npc
// check npc spawn functions
for ( npc=bg_npclist ; npc->classname ; npc++ ) {
if ( !strcmp(npc->classname, ent->classname) ) {
SP_npc( ent, npc );
return qtrue;
}
}
#endif
// check item spawn functions
for ( item=bg_itemlist+1 ; item->classname ; item++ ) {
In g_weapon.c in function Bullet_Fire about line 193 add :
// send bullet impact
#ifndef SINGLEPLAYER // npc
if ( traceEnt->takedamage && traceEnt->client ) {
#else
if ( traceEnt->takedamage && (traceEnt->client || traceEnt->s.eType==ET_NPC)) {
#endif
tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
tent->s.eventParm = traceEnt->s.number;
#ifndef SINGLEPLAYER // npc
if( LogAccuracyHit( traceEnt, ent ) ) {
ent->client->accuracy_hits++;
}
#endif
} else {
In g_weapon.c in function FireWeapon about line 872 add :
case WP_BFG:
BFG_Fire( ent );
break;
#ifdef SINGLEPLAYER // npc
case WP_GUN:
Bullet_Fire( ent, MACHINEGUN_SPREAD, 40 );
break;
#endif
case WP_GRAPPLING_HOOK:
Weapon_GrapplingHook_Fire( ent );
break;
In g_weapon.c at the end of the file add :
#ifdef SINGLEPLAYER // npc
void NPC_FireWeapon(gentity_t *ent,vec3_t target_pos)
{
vec3_t dir,ang;
vec3_t fire_org;
VectorCopy(ent->r.currentOrigin,fire_org);
if (ent->npc->npcType==NPC_SOLDIER1 || ent->npc->npcType==NPC_SOLDIER2
|| ent->npc->npcType==NPC_PILOT || ent->npc->npcType==NPC_ANK)
fire_org[2]+=15;
else if (ent->npc->npcType==NPC_BAT)
fire_org[2]+=33;
else if (ent->npc->npcType==NPC_SEALORD)
{
fire_org[2]+=30;
fire_org[1]-=120;
}
VectorSubtract (target_pos,fire_org, dir);
vectoangles(dir,ang);
if (ent->npc->npcType!=NPC_SEALORD)
{
ang[1]=ent->ns.ps.viewangles[1];
}
else if (ent->ns.fireTime > 0)
{
ang[0]+=rand()%15-7;
ang[1]+=rand()%15-7;
ang[2]+=rand()%15-7;
}
s_quadFactor=1;
AngleVectors (ang, forward, right, up);
VectorMA( fire_org, 1, forward, muzzle);
SnapVector( muzzle );
if (ent->npc->npcType==NPC_SOLDIER1 || ent->npc->npcType==NPC_SOLDIER2 || ent->npc->npcType==NPC_PILOT)
{
Bullet_Fire(ent,50,20*(int)(1.0f+0.25f*(float)npc_skill));
}
else if (ent->npc->npcType==NPC_ANK)
{
fire_ank_shot(ent,muzzle,forward,ent->ns.enemy);
}
else if (ent->npc->npcType==NPC_BAT)
{
fire_bat_shot(ent,muzzle,forward);
}
else if (ent->npc->npcType==NPC_SEALORD)
{
if (ent->ns.meleeTime > 0)
fire_sealord_big_shot(ent,muzzle,forward);
else
fire_sealord_small_shot(ent,muzzle,forward);
}
}
#endif