Add a New NPC class with individual behaviour ,code in the animations, .dat file additions in code and file x2 different ways (MP Differes from SP),effects code.
Its was quite a fair bit of work.
switch( team )
{// not sure if TEAM_ENEMY is appropriate here, I think I should be using NPC_class to check for behavior - dmv
case TEAM_ENEMY:
// special cases for enemy droids
switch( NPC->client->NPC_class)
{
case CLASS_ATST:
NPC_BehaviorSet_ATST( bState );
return;
case CLASS_PROBE:
NPC_BehaviorSet_ImperialProbe(bState);
return;
case CLASS_DROIDEKA:
NPC_BehaviorSet_DROIDEKA(bState);
return;
case CLASS_REMOTE:
NPC_BehaviorSet_Remote( bState );
return;
The behaviour state set up
/*
-------------------------
NPC_BehaviorSet_DROIDEKA
-------------------------
*/
void NPC_BehaviorSet_DROIDEKA( int bState )
{
switch( bState )
{
case BS_STAND_GUARD:
case BS_DEFAULT:
case BS_PATROL:
case BS_STAND_AND_SHOOT:
case BS_HUNT_AND_KILL:
NPC_BSDROIDEKA_Default();
break;
default:
NPC_BehaviorSet_Default( bState );
break;
}
}
and the i made a whole new NPC AI set up for this bad boy
void G_DROIDEKACheckPain( gentity_t *self, gentity_t *other, const vec3_t point, int damage, int mod,int hitLoc )
{
if ( rand() & 1 )
{
G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/droideka/pain25" );
}
else
{
G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/droideka/pain100" );
}
}
/*
-------------------------
NPC_DROIDEKA_Pain
-------------------------
*/
void NPC_DROIDEKA_Pain( gentity_t *self, gentity_t *inflictor, gentity_t *other, const vec3_t point, int damage, int mod,int hitLoc )
{
G_DROIDEKACheckPain( self, other, point, damage, mod, hitLoc );
NPC_Pain( self, inflictor, other, point, damage, mod );
}
/*
-------------------------
DROIDEKA_Hunt
-------------------------`
*/
void DROIDEKA_Hunt( qboolean visible, qboolean advance )
{
//If we're not supposed to stand still, pursue the player
if ( NPCInfo->standTime < level.time )
{
//Move towards our goal
NPCInfo->goalEntity = NPC->enemy;
NPCInfo->goalRadius = 12;
NPC_MoveToGoal( qtrue );
}
if ( NPCInfo->goalEntity == NULL )
{//hunt
NPCInfo->goalEntity = NPC->enemy;
}
NPCInfo->combatMove = qtrue;
NPC_MoveToGoal( qtrue );
NPC_FaceEnemy();
//Update our angles regardless
NPC_UpdateAngles( qtrue, qtrue );
}
/*
-------------------------
DROIDEKA_Ranged
-------------------------
*/
void DROIDEKA_Ranged( qboolean visible, qboolean advance, qboolean altAttack )
{
if ( TIMER_Done( NPC, "atkDelay" ) && visible ) // Attack?
{
TIMER_Set( NPC, "atkDelay", Q_irand( 500, 1000 ) );
ucmd.buttons |= BUTTON_ATTACK;
}
if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES )
{
DROIDEKA_Hunt( visible, advance );
}
}
/*
-------------------------
DROIDEKA_Attack
-------------------------
*/
void DROIDEKA_Attack( void )
{
qboolean altAttack=qfalse;
// Rate our distance to the target, and our visibilty
float distance = (int) DistanceHorizontalSquared( NPC->currentOrigin, NPC->enemy->currentOrigin );
distance_e distRate = ( distance > MIN_MELEE_RANGE_SQR ) ? DIST_LONG : DIST_MELEE;
qboolean visible = NPC_ClearLOS( NPC->enemy );
qboolean advance = (qboolean)(distance > MIN_DISTANCE_SQR);
if ( NPC_CheckEnemyExt() == qfalse )
{
NPC->enemy = NULL;
DROIDEKA_Hunt( visible, advance );
return;
}
NPC_FaceEnemy( qtrue );
// If we cannot see our target, move to see it
if ( visible == qfalse )
{
if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES )
{
DROIDEKA_Hunt( visible, advance );
return;
}
}
// Decide what type of attack to do
//If we're too far away, then keep walking forward
if ( distRate != DIST_MELEE )
{
DROIDEKA_Hunt( visible, advance );
return;
}
NPC_FaceEnemy( qtrue );
DROIDEKA_Ranged( visible, advance,altAttack );
}
/*
-------------------------
DROIDEKA_Patrol
-------------------------
*/
void DROIDEKA_Patrol( void )
{
if ( NPC_CheckPlayerTeamStealth() )
{
NPC_UpdateAngles( qtrue, qtrue );
return;
}
//If we have somewhere to go, then do that
if (!NPC->enemy)
{
if ( UpdateGoal() )
{
ucmd.buttons |= BUTTON_WALKING;
NPC_MoveToGoal( qtrue );
NPC_UpdateAngles( qtrue, qtrue );
}
}
}
/*
-------------------------
DROIDEKA_Idle
-------------------------
*/
void DROIDEKA_Idle( void )
{
BubbleShield_Update();
}
/*
-------------------------
NPC_BSDROIDEKA_Default
-------------------------
*/
void NPC_BSDROIDEKA_Default( void )
{
if ( NPC->enemy )
{
if( (NPCInfo->scriptFlags & SCF_CHASE_ENEMIES) )
{
NPCInfo->goalEntity = NPC->enemy;
}
DROIDEKA_Attack();
}
else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
{
DROIDEKA_Patrol();
}
else
{
DROIDEKA_Idle();
}
}
as a result ,you can script the decca easily.
Did the same with SBD also.
you can download examples of the code and build your own version