📄 npc_conscript.cpp
字号:
};
Speak( concepts[random->RandomInt(0,2)] );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CNPC_Conscript::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr )
{
CTakeDamageInfo info = inputInfo;
switch( ptr->hitgroup)
{
case HITGROUP_CHEST:
case HITGROUP_STOMACH:
if (info.GetDamageType() & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
{
info.ScaleDamage( 0.5f );
}
break;
case 10:
if (info.GetDamageType() & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
{
info.SetDamage( info.GetDamage() - 20 );
if (info.GetDamage() <= 0)
{
g_pEffects->Ricochet( ptr->endpos, (vecDir*-1.0f) );
info.SetDamage( 0 );
}
}
// always a head shot
ptr->hitgroup = HITGROUP_HEAD;
break;
}
BaseClass::TraceAttack( info, vecDir, ptr );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
int CNPC_Conscript::TranslateSchedule( int scheduleType )
{
int baseType;
switch( scheduleType )
{
case SCHED_CONSCRIPT_DRAW:
if ( GetEnemy() != NULL )
{
// face enemy, then draw.
return SCHED_CONSCRIPT_DRAW;
}
else
{
// BUGBUG: What is this code supposed to do when there isn't an enemy?
Warning( "BUG IN CONSCRIPT AI!\n");
}
break;
// Hook these to make a looping schedule
case SCHED_TARGET_FACE:
{
// call base class default so that barney will talk
// when 'used'
baseType = BaseClass::TranslateSchedule(scheduleType);
if (baseType == SCHED_IDLE_STAND)
return SCHED_CONSCRIPT_FACE_TARGET; // override this for different target face behavior
else
return baseType;
}
break;
case SCHED_CHASE_ENEMY:
{
// ---------------------------------------------
// If I'm in ducking, cover pause for while
// before running towards my enemy. See if they
// come out first as this is a good place to be!
// ---------------------------------------------
if (HasMemory(bits_MEMORY_INCOVER))
{
Forget( bits_MEMORY_INCOVER );
return SCHED_COMBAT_SWEEP;
}
}
break;
case SCHED_TARGET_CHASE:
return SCHED_CONSCRIPT_FOLLOW;
break;
case SCHED_IDLE_STAND:
{
// call base class default so that scientist will talk
// when standing during idle
baseType = BaseClass::TranslateSchedule(scheduleType);
if (baseType == SCHED_IDLE_STAND)
{
// just look straight ahead
return SCHED_CONSCRIPT_STAND;
}
return baseType;
break;
}
case SCHED_FAIL_ESTABLISH_LINE_OF_FIRE:
{
return SCHED_CONSCRIPT_AIM;
break;
}
}
return BaseClass::TranslateSchedule( scheduleType );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
int CNPC_Conscript::SelectSchedule ( void )
{
// These things are done in any state but dead and prone
if (m_NPCState != NPC_STATE_DEAD && m_NPCState != NPC_STATE_PRONE)
{
if ( HasCondition( COND_HEAR_DANGER ) )
{
return SCHED_TAKE_COVER_FROM_BEST_SOUND;
}
if ( HasCondition( COND_ENEMY_DEAD ) && IsOkToCombatSpeak() )
{
Speak( CONSCRIPT_KILL );
}
}
switch( m_NPCState )
{
case NPC_STATE_PRONE:
{
if (m_bInBarnacleMouth)
{
return SCHED_CONSCRIPT_BARNACLE_CHOMP;
}
else
{
return SCHED_CONSCRIPT_BARNACLE_HIT;
}
}
case NPC_STATE_COMBAT:
{
// dead enemy
if ( HasCondition( COND_ENEMY_DEAD ) )
{
// call base class, all code to handle dead enemies is centralized there.
return BaseClass::SelectSchedule();
}
// always act surprized with a new enemy
if ( HasCondition( COND_NEW_ENEMY ) && HasCondition( COND_LIGHT_DAMAGE) )
return SCHED_SMALL_FLINCH;
// wait for one schedule to draw gun
if (!m_fGunDrawn )
return SCHED_CONSCRIPT_DRAW;
if ( HasCondition( COND_HEAVY_DAMAGE ) )
return SCHED_TAKE_COVER_FROM_ENEMY;
// ---------------------
// no ammo
// ---------------------
if ( HasCondition ( COND_NO_PRIMARY_AMMO ) )
{
Speak( CONSCRIPT_OUT_AMMO );
return SCHED_HIDE_AND_RELOAD;
}
else if (!HasCondition(COND_CAN_RANGE_ATTACK1) && HasCondition( COND_NO_SECONDARY_AMMO ))
{
Speak( CONSCRIPT_OUT_AMMO );
return SCHED_HIDE_AND_RELOAD;
}
/* UNDONE: check distance for genade attacks...
// If player is next to what I'm trying to attack...
if ( HasCondition( COND_WEAPON_PLAYER_NEAR_TARGET ))
{
return SCHED_CONSCRIPT_AIM;
}
*/
// -------------------------------------------
// If I might hit the player shooting...
// -------------------------------------------
if ( HasCondition( COND_WEAPON_PLAYER_IN_SPREAD ))
{
if ( IsOkToCombatSpeak() && m_nextLineFireTime < gpGlobals->curtime)
{
Speak( CONSCRIPT_LINE_FIRE );
m_nextLineFireTime = gpGlobals->curtime + 3.0f;
}
// Run to a new location or stand and aim
if (random->RandomInt(0,2) == 0)
{
return SCHED_ESTABLISH_LINE_OF_FIRE;
}
else
{
return SCHED_CONSCRIPT_AIM;
}
}
// -------------------------------------------
// If I'm in cover and I don't have a line of
// sight to my enemy, wait randomly before attacking
// -------------------------------------------
}
break;
case NPC_STATE_ALERT:
case NPC_STATE_IDLE:
if ( HasCondition(COND_LIGHT_DAMAGE) || HasCondition(COND_HEAVY_DAMAGE))
{
// flinch if hurt
return SCHED_SMALL_FLINCH;
}
// try to say something about smells
TrySmellTalk();
break;
}
return BaseClass::SelectSchedule();
}
//-----------------------------------------------------------------------------
// Purpose: This is a generic function (to be implemented by sub-classes) to
// handle specific interactions between different types of characters
// (For example the barnacle grabbing an NPC)
// Input : Constant for the type of interaction
// Output : true - if sub-class has a response for the interaction
// false - if sub-class has no response
//-----------------------------------------------------------------------------
bool CNPC_Conscript::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt)
{
if (interactionType == g_interactionBarnacleVictimDangle)
{
// Force choosing of a new schedule
ClearSchedule();
m_bInBarnacleMouth = true;
return true;
}
else if ( interactionType == g_interactionBarnacleVictimReleased )
{
m_IdealNPCState = NPC_STATE_IDLE;
CPASAttenuationFilter filter( this );
EmitSound( filter, entindex(), CHAN_VOICE, "barney/ba_close.wav", 1, SNDLVL_TALKING, 0, GetExpresser()->GetVoicePitch());
m_bInBarnacleMouth = false;
SetAbsVelocity( vec3_origin );
SetMoveType( MOVETYPE_STEP );
return true;
}
else if ( interactionType == g_interactionBarnacleVictimGrab )
{
if ( GetFlags() & FL_ONGROUND )
{
RemoveFlag( FL_ONGROUND );
}
m_IdealNPCState = NPC_STATE_PRONE;
PainSound();
return true;
}
return false;
}
void CNPC_Conscript::DeclineFollowing( void )
{
Speak( CONSCRIPT_POK );
}
//-----------------------------------------------------------------------------
//
// Schedules
//
//-----------------------------------------------------------------------------
//=========================================================
// > SCHED_CONSCRIPT_FOLLOW
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_FOLLOW,
" Tasks"
" TASK_GET_PATH_TO_TARGET 0"
" TASK_MOVE_TO_TARGET_RANGE 128" // Move within 128 of target ent (client)
" TASK_SET_SCHEDULE SCHEDULE:SCHED_TARGET_FACE "
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_HEAR_DANGER"
" COND_PROVOKED"
);
//=========================================================
// > SCHED_CONSCRIPT_DRAW
// much better looking draw schedule for when
// conscript knows who he's gonna attack.
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_DRAW,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_FACE_ENEMY 0"
" TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_ARM "
""
" Interrupts"
);
//===============================================
// > SCHED_CONSCRIPT_AIM
//
// Stand in place and aim at enemy (used when
// line of sight blocked by player)
//===============================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_AIM,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_FACE_ENEMY 0"
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_CONSCRIPT_AIM"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_ENEMY_DEAD"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_NO_PRIMARY_AMMO"
" COND_WEAPON_HAS_LOS"
" COND_CAN_MELEE_ATTACK1 "
" COND_CAN_MELEE_ATTACK2 "
" COND_HEAR_DANGER"
);
//=========================================================
// > SCHED_CONSCRIPT_FACE_TARGET
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_FACE_TARGET,
" Tasks"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_FACE_TARGET 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_TARGET_CHASE"
""
" Interrupts"
//" CLIENT_PUSH <<TODO>>
" COND_NEW_ENEMY"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_HEAR_DANGER"
" COND_PROVOKED"
);
//=========================================================
// > SCHED_CONSCRIPT_STAND
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_STAND,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE "
" TASK_WAIT 2" // repick IDLESTAND every two seconds.
" TASK_TALKER_HEADRESET 0" // reset head position
""
" Interrupts "
" COND_NEW_ENEMY"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_SMELL"
" COND_PROVOKED"
" COND_HEAR_COMBAT"
" COND_HEAR_DANGER"
);
//=========================================================
// > SCHED_CONSCRIPT_BARNACLE_HIT
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_BARNACLE_HIT,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_BARNACLE_HIT"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_CONSCRIPT_BARNACLE_PULL"
""
" Interrupts"
);
//=========================================================
// > SCHED_CONSCRIPT_BARNACLE_PULL
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_BARNACLE_PULL,
" Tasks"
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_BARNACLE_PULL"
""
" Interrupts"
);
//=========================================================
// > SCHED_CONSCRIPT_BARNACLE_CHOMP
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_BARNACLE_CHOMP,
" Tasks"
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_BARNACLE_CHOMP"
" TASK_SET_SCHEDULE SCHEDULE:SCHED_CONSCRIPT_BARNACLE_CHEW"
""
" Interrupts"
);
//=========================================================
// > SCHED_CONSCRIPT_BARNACLE_CHEW
//=========================================================
AI_DEFINE_SCHEDULE
(
SCHED_CONSCRIPT_BARNACLE_CHEW,
" Tasks"
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_BARNACLE_CHEW"
);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -