mirror of
https://github.com/ValveSoftware/source-sdk-2013.git
synced 2025-02-17 09:31:42 +00:00
Nav stuff
This commit is contained in:
parent
56accfdb9c
commit
d191c2e886
10 changed files with 619 additions and 2 deletions
|
@ -1,3 +1,3 @@
|
|||
pushd %~dp0
|
||||
devtools\bin\vpc.exe /hl2 /episodic +everything /mksln everything.sln
|
||||
devtools\bin\vpc.exe /hl2 /episodic /2010 /navmesh +everything /mksln everything.sln
|
||||
popd
|
||||
|
|
|
@ -1803,7 +1803,7 @@ void CTempEnts::MuzzleFlash( int type, ClientEntityHandle_t hEntity, int attachm
|
|||
//-----------------------------------------------------------------------------
|
||||
void CTempEnts::MuzzleFlash( const Vector& pos1, const QAngle& angles, int type, ClientEntityHandle_t hEntity, bool firstPerson )
|
||||
{
|
||||
#ifdef CSTRIKE_DLL
|
||||
#ifndef CSTRIKE_DLL
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
//@todo: bad dependency!
|
||||
#include "ai_navigator.h"
|
||||
|
||||
// support for nav mesh
|
||||
#include "nav_mesh.h"
|
||||
#include "nav_pathfind.h"
|
||||
#include "nav_area.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
@ -1426,6 +1431,23 @@ AI_Waypoint_t *CAI_Pathfinder::BuildRoute( const Vector &vStart, const Vector &v
|
|||
buildFlags, goalTolerance);
|
||||
}
|
||||
|
||||
// If the local fails, try a nav mesh route
|
||||
// the nav mesh doesn't supports flying npc's, like the strider or gunship
|
||||
if ( !pResult && curNavType != NAV_FLY )
|
||||
{
|
||||
/*CNavArea *closestArea = NULL;
|
||||
CNavArea *startArea = TheNavMesh->GetNearestNavArea(vStart);
|
||||
CNavArea *goalArea = TheNavMesh->GetNearestNavArea(vEnd);
|
||||
|
||||
ShortestPathCost costfunc;
|
||||
|
||||
if( NavAreaBuildPath( startArea, goalArea, &vEnd, costfunc, buildFlags, goalTolerance, &closestArea) )
|
||||
{
|
||||
AI_Waypoint_t *newway = new AI_Waypoint_t( vEnd, 0, curNavType, bits_WP_TO_GOAL, NO_NODE );
|
||||
pResult = BuildNavRoute( startArea, closestArea, vEnd, newway, curNavType );
|
||||
}*/
|
||||
}
|
||||
|
||||
// If the fails, try a node route
|
||||
if ( !pResult )
|
||||
{
|
||||
|
@ -1437,6 +1459,319 @@ AI_Waypoint_t *CAI_Pathfinder::BuildRoute( const Vector &vStart, const Vector &v
|
|||
return pResult;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is our cost func. This should likely do something different
|
||||
// then return 0.0f...
|
||||
//-----------------------------------------------------------------------------
|
||||
class CNavArea;
|
||||
class CNavLadder;
|
||||
|
||||
float checkCost( CNavArea *nav1, CNavArea *nav2, const CNavLadder *nav3 )
|
||||
{
|
||||
if(nav3) // ignore ladders
|
||||
return 0.0f;
|
||||
|
||||
if( !nav1 || !nav2 )
|
||||
return 0.0f;
|
||||
|
||||
// just take the lenght of the two centers. This should be enough.
|
||||
return nav1->GetTotalCost() + (nav1->GetCenter() - nav2->GetCenter()).Length2D();
|
||||
|
||||
//return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Find path from startArea to goalArea via an A* search, using supplied cost heuristic.
|
||||
* If cost functor returns -1 for an area, that area is considered a dead end.
|
||||
* This doesn't actually build a path, but the path is defined by following parent
|
||||
* pointers back from goalArea to startArea.
|
||||
* If 'closestArea' is non-NULL, the closest area to the goal is returned (useful if the path fails).
|
||||
* If 'goalArea' is NULL, will compute a path as close as possible to 'goalPos'.
|
||||
* If 'goalPos' is NULL, will use the center of 'goalArea' as the goal position.
|
||||
* Returns true if a path exists.
|
||||
* Updated for hl2wars and hl2 npc's
|
||||
*/
|
||||
template< typename CostFunctor >
|
||||
bool CAI_Pathfinder::NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, CostFunctor &costFunc, int buildFlags, float goalTolerance, CNavArea **closestArea )
|
||||
{
|
||||
/*if (startArea == NULL)
|
||||
return false;
|
||||
|
||||
if (goalArea == NULL && goalPos == NULL)
|
||||
return false;
|
||||
|
||||
startArea->SetParent( NULL );
|
||||
|
||||
// if we are already in the goal area, build trivial path
|
||||
if (startArea == goalArea)
|
||||
{
|
||||
goalArea->SetParent( NULL );
|
||||
return true;
|
||||
}
|
||||
|
||||
// determine actual goal position
|
||||
Vector actualGoalPos = (goalPos) ? *goalPos : goalArea->GetCenter();
|
||||
|
||||
// start search
|
||||
CNavArea::ClearSearchLists();
|
||||
|
||||
// compute estimate of path length
|
||||
/// @todo Cost might work as "manhattan distance"
|
||||
startArea->SetTotalCost( (startArea->GetCenter() - actualGoalPos).Length() );
|
||||
|
||||
float initCost = checkCost( startArea, NULL, NULL );
|
||||
if (initCost < 0.0f)
|
||||
return false;
|
||||
startArea->SetCostSoFar( initCost );
|
||||
|
||||
startArea->AddToOpenList();
|
||||
|
||||
// keep track of the area we visit that is closest to the goal
|
||||
if (closestArea)
|
||||
*closestArea = startArea;
|
||||
float closestAreaDist = startArea->GetTotalCost();
|
||||
|
||||
// do A* search
|
||||
while( !CNavArea::IsOpenListEmpty() )
|
||||
{
|
||||
// get next area to check
|
||||
CNavArea *area = CNavArea::PopOpenList();
|
||||
|
||||
// don't consider jump area's
|
||||
if( area->GetAttributes() & NAV_MESH_JUMP)
|
||||
continue;
|
||||
|
||||
// check if we have found the goal area or position
|
||||
if (area == goalArea || (goalArea == NULL && goalPos && area->Contains( *goalPos )))
|
||||
{
|
||||
if (closestArea)
|
||||
{
|
||||
*closestArea = area;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// search adjacent areas
|
||||
bool searchFloor = true;
|
||||
int dir = NORTH;
|
||||
const NavConnectVector *floorList = area->GetAdjacentAreas( NORTH );
|
||||
int floorIter = 0;
|
||||
|
||||
bool ladderUp = true;
|
||||
const NavLadderConnectVector *ladderList = NULL;
|
||||
int ladderIter = NavLadderConnectList::InvalidIndex();
|
||||
enum { AHEAD = 0, LEFT, RIGHT, BEHIND, NUM_TOP_DIRECTIONS };
|
||||
int ladderTopDir = AHEAD;
|
||||
|
||||
while(true)
|
||||
{
|
||||
CNavArea *newArea;
|
||||
NavTraverseType how;
|
||||
const CNavLadder *ladder = NULL;
|
||||
|
||||
//
|
||||
// Get next adjacent area - either on floor or via ladder
|
||||
//
|
||||
if (searchFloor)
|
||||
{
|
||||
// if exhausted adjacent connections in current direction, begin checking next direction
|
||||
if (floorIter == floorList->InvalidIndex())
|
||||
{
|
||||
++dir;
|
||||
|
||||
if (dir == NUM_DIRECTIONS)
|
||||
{
|
||||
// checked all directions on floor - check ladders next
|
||||
searchFloor = false;
|
||||
|
||||
ladderList = area->GetLadders( CNavLadder::LADDER_UP );
|
||||
ladderIter = 0;
|
||||
ladderTopDir = AHEAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
// start next direction
|
||||
floorList = area->GetAdjacentAreas( (NavDirType)dir );
|
||||
floorIter = 0;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
newArea = floorList->Element(floorIter).area;
|
||||
how = (NavTraverseType)dir;
|
||||
floorIter++;
|
||||
}
|
||||
else // search ladders
|
||||
{
|
||||
if (ladderIter == ladderList->InvalidIndex())
|
||||
{
|
||||
if (!ladderUp)
|
||||
{
|
||||
// checked both ladder directions - done
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check down ladders
|
||||
ladderUp = false;
|
||||
ladderList = area->GetLadders( CNavLadder::LADDER_DOWN );
|
||||
ladderIter = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ladderUp)
|
||||
{
|
||||
ladder = ladderList->Element( ladderIter ).ladder;
|
||||
|
||||
// do not use BEHIND connection, as its very hard to get to when going up a ladder
|
||||
if (ladderTopDir == AHEAD)
|
||||
newArea = ladder->m_topForwardArea;
|
||||
else if (ladderTopDir == LEFT)
|
||||
newArea = ladder->m_topLeftArea;
|
||||
else if (ladderTopDir == RIGHT)
|
||||
newArea = ladder->m_topRightArea;
|
||||
else
|
||||
{
|
||||
ladderIter++;
|
||||
ladderTopDir = AHEAD;
|
||||
continue;
|
||||
}
|
||||
|
||||
how = GO_LADDER_UP;
|
||||
++ladderTopDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
newArea = ladderList->Element(ladderIter).ladder->m_bottomArea;
|
||||
how = GO_LADDER_DOWN;
|
||||
ladder = ladderList->Element(ladderIter).ladder;
|
||||
ladderIter++;
|
||||
}
|
||||
|
||||
if (newArea == NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't backtrack
|
||||
if (newArea == area)
|
||||
continue;
|
||||
|
||||
// don't consider jump area's
|
||||
if( newArea->GetAttributes() & NAV_MESH_JUMP)
|
||||
continue;
|
||||
|
||||
float newCostSoFar = checkCost( newArea, area, ladder );
|
||||
|
||||
// check if cost functor says this area is a dead-end
|
||||
if (newCostSoFar < 0.0f)
|
||||
continue;
|
||||
|
||||
if ((newArea->IsOpen() || newArea->IsClosed()) && newArea->GetCostSoFar() <= newCostSoFar)
|
||||
{
|
||||
// this is a worse path - skip it
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compute estimate of distance left to go
|
||||
float newCostRemaining = (newArea->GetCenter() - actualGoalPos).Length();
|
||||
|
||||
// track closest area to goal in case path fails
|
||||
if (closestArea && newCostRemaining < closestAreaDist)
|
||||
{
|
||||
*closestArea = newArea;
|
||||
closestAreaDist = newCostRemaining;
|
||||
}
|
||||
|
||||
newArea->SetParent( area, how );
|
||||
newArea->SetCostSoFar( newCostSoFar );
|
||||
newArea->SetTotalCost( newCostSoFar + newCostRemaining );
|
||||
|
||||
if (newArea->IsClosed())
|
||||
newArea->RemoveFromClosedList();
|
||||
|
||||
if (newArea->IsOpen())
|
||||
{
|
||||
// area already on open list, update the list order to keep costs sorted
|
||||
newArea->UpdateOnOpenList();
|
||||
}
|
||||
else
|
||||
{
|
||||
newArea->AddToOpenList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have searched this area
|
||||
area->AddToClosedList();
|
||||
}
|
||||
|
||||
return false;*/
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Builds a route to the given vecGoal using the navigation mesh result
|
||||
//-----------------------------------------------------------------------------
|
||||
AI_Waypoint_t *CAI_Pathfinder::BuildNavRoute( CNavArea *startArea, CNavArea *goalArea, const Vector &from, AI_Waypoint_t *waypoint, Navigation_t curNavType )
|
||||
{
|
||||
if( !goalArea )
|
||||
return waypoint;
|
||||
|
||||
int nodeID, endFlags;
|
||||
nodeID = NO_NODE;
|
||||
|
||||
endFlags = 0;
|
||||
Vector center, center_portal, delta;
|
||||
float hwidth, hwidthhull;
|
||||
NavDirType dir;
|
||||
|
||||
Vector closestpoint;
|
||||
if( goalArea->GetParent() )
|
||||
{
|
||||
center = goalArea->GetParent()->GetCenter();
|
||||
dir = goalArea->ComputeDirection(¢er);
|
||||
goalArea->ComputePortal( goalArea->GetParent(), dir, ¢er_portal, &hwidth );
|
||||
goalArea->ComputeClosestPointInPortal( goalArea->GetParent(), dir, goalArea->GetParent()->GetCenter(), &closestpoint );
|
||||
|
||||
// this point would be the closest route. But does or our hull fits?
|
||||
trace_t trace;
|
||||
CTraceFilterWorldOnly traceFilter;
|
||||
AI_TraceHull( closestpoint, closestpoint, WorldAlignMins(), WorldAlignMaxs(), MASK_SOLID, &traceFilter, &trace );
|
||||
if ( trace.fraction != 1.0f )
|
||||
{
|
||||
// move a bit to the center
|
||||
delta = closestpoint - center_portal;
|
||||
hwidthhull = GetOuter()->GetHullWidth() / 2.0f;
|
||||
if( delta.IsLengthGreaterThan( hwidthhull ) )
|
||||
{
|
||||
closestpoint = closestpoint + ( (hwidthhull / delta.Length() ) * delta );
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: try to make the connection look less forced by randomly moving it a bit.
|
||||
|
||||
|
||||
|
||||
closestpoint.z = goalArea->GetZ( closestpoint );
|
||||
AI_Waypoint_t *newway = new AI_Waypoint_t( closestpoint, 0, curNavType, endFlags, nodeID );
|
||||
if( waypoint )
|
||||
newway->SetNext(waypoint);
|
||||
return BuildNavRoute( startArea, goalArea->GetParent(), closestpoint, newway, curNavType );
|
||||
}
|
||||
else
|
||||
{
|
||||
return waypoint;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CAI_Pathfinder::UnlockRouteNodes( AI_Waypoint_t *pPath )
|
||||
{
|
||||
CAI_Node *pNode;
|
||||
|
|
|
@ -80,6 +80,8 @@ public:
|
|||
|
||||
// --------------------------------
|
||||
|
||||
template< typename CostFunctor > bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, CostFunctor &costFunc, int buildFlags, float goalTolerance, CNavArea **closestArea );
|
||||
virtual AI_Waypoint_t *BuildNavRoute( CNavArea *startArea, CNavArea *goalArea, const Vector &from, AI_Waypoint_t *waypoint, Navigation_t curNavType );
|
||||
virtual AI_Waypoint_t *BuildNodeRoute( const Vector &vStart, const Vector &vEnd, int buildFlags, float goalTolerance );
|
||||
virtual AI_Waypoint_t *BuildLocalRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, int buildFlags, float goalTolerance);
|
||||
virtual AI_Waypoint_t *BuildRadialRoute( const Vector &vStartPos, const Vector &vCenterPos, const Vector &vGoalPos, float flRadius, float flArc, float flStepDist, bool bClockwise, float goalTolerance, bool bAirRoute );
|
||||
|
|
|
@ -120,6 +120,7 @@ enum Class_T
|
|||
CLASS_EARTH_FAUNA,
|
||||
CLASS_HACKED_ROLLERMINE,
|
||||
CLASS_COMBINE_HUNTER,
|
||||
//CLASS_HUMAN_GRUNT,
|
||||
|
||||
NUM_AI_CLASSES
|
||||
};
|
||||
|
|
|
@ -86,6 +86,7 @@ struct NavConnect
|
|||
};
|
||||
|
||||
typedef CUtlVectorUltraConservative<NavConnect, CNavVectorAllocator> NavConnectVector;
|
||||
typedef CUtlLinkedList<NavConnect, int> NavConnectList;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -103,6 +104,7 @@ union NavLadderConnect
|
|||
}
|
||||
};
|
||||
typedef CUtlVectorUltraConservative<NavLadderConnect, CNavVectorAllocator> NavLadderConnectVector;
|
||||
typedef CUtlLinkedList<NavLadderConnect, int> NavLadderConnectList;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
|
277
sp/src/game/server/npc_base_human.cpp
Normal file
277
sp/src/game/server/npc_base_human.cpp
Normal file
|
@ -0,0 +1,277 @@
|
|||
#include "cbase.h"
|
||||
#include "ai_default.h"
|
||||
#include "ai_task.h"
|
||||
#include "ai_schedule.h"
|
||||
#include "ai_hull.h"
|
||||
#include "soundent.h"
|
||||
#include "game.h"
|
||||
#include "npcevent.h"
|
||||
#include "entitylist.h"
|
||||
#include "activitylist.h"
|
||||
#include "ai_basenpc.h"
|
||||
|
||||
#include "ai_basehumanoid.h"
|
||||
#include "ai_sentence.h"
|
||||
#include "ai_baseactor.h"
|
||||
|
||||
#include "engine/IEngineSound.h"
|
||||
|
||||
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//=========================================================
|
||||
// Private activities
|
||||
//=========================================================
|
||||
//int ACT_MYCUSTOMACTIVITY = -1;
|
||||
//Activity ACT_RUN_RIFLE;
|
||||
Activity ACT_WALK_UNARMED;
|
||||
|
||||
//=========================================================
|
||||
// Custom schedules
|
||||
//=========================================================
|
||||
enum
|
||||
{
|
||||
//SCHED_MYCUSTOMSCHEDULE = LAST_SHARED_SCHEDULE,
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// Custom tasks
|
||||
//=========================================================
|
||||
enum
|
||||
{
|
||||
//TASK_MYCUSTOMTASK = LAST_SHARED_TASK,
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Custom Conditions
|
||||
//=========================================================
|
||||
enum
|
||||
{
|
||||
//COND_MYCUSTOMCONDITION = LAST_SHARED_CONDITION,
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
class CNPCHuman : public CAI_BaseHumanoid
|
||||
{
|
||||
DECLARE_CLASS( CNPCHuman, CAI_BaseHumanoid );
|
||||
|
||||
public:
|
||||
void Precache( void );
|
||||
void Spawn( void );
|
||||
Class_T Classify( void );
|
||||
int SelectSchedule( void );
|
||||
void StartTask( const Task_t *pTask );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( npc_hn_human, CNPCHuman );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPCHuman::Precache( void )
|
||||
{
|
||||
PrecacheModel( "models/humans/marine.mdl" );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPCHuman::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetModel( "models/humans/marine.mdl" );
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_NOT_STANDABLE );
|
||||
SetMoveType( MOVETYPE_STEP );
|
||||
SetBloodColor( BLOOD_COLOR_RED );
|
||||
SetFlexWeight("cheek_depth",RandomFloat(0,1));
|
||||
SetFlexWeight("cheek_fat_max",RandomFloat(0,1));
|
||||
SetFlexWeight("cheek_fat_min",RandomFloat(0,0.5));
|
||||
SetFlexWeight("chin_butt",RandomFloat(0,1));
|
||||
SetFlexWeight("chin_width",RandomFloat(0,1));
|
||||
SetFlexWeight("face_d_min",RandomFloat(0,1));
|
||||
SetFlexWeight("face_d_max",RandomFloat(0,1));
|
||||
SetFlexWeight("head_height",RandomFloat(0,1));
|
||||
SetFlexWeight("head_w_min",RandomFloat(0,1));
|
||||
SetFlexWeight("head_w_max",RandomFloat(0,1));
|
||||
SetFlexWeight("neck_size",RandomFloat(0,1));
|
||||
SetFlexWeight("ears_angle",RandomFloat(0,1));
|
||||
SetFlexWeight("ears_height",RandomFloat(0,1));
|
||||
SetFlexWeight("eyes_ang_min",RandomFloat(0,1));
|
||||
SetFlexWeight("eyes_ang_max",RandomFloat(0,1));
|
||||
SetFlexWeight("eyes_height",RandomFloat(0,1));
|
||||
SetFlexWeight("jaw_depth",RandomFloat(0,1));
|
||||
SetFlexWeight("lowlip_size",RandomFloat(0,1));
|
||||
SetFlexWeight("uplip_size",RandomFloat(0,1));
|
||||
SetFlexWeight("mouth_w_min",RandomFloat(0,1));
|
||||
SetFlexWeight("mouth_w_max",RandomFloat(0,1));
|
||||
SetFlexWeight("mouth_h_min",RandomFloat(0,1));
|
||||
SetFlexWeight("mouth_h_max",RandomFloat(0,1));
|
||||
SetFlexWeight("mouth_depth",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_w_min",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_w_max",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_h_min",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_h_max",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_angle",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_d_max",RandomFloat(0,1));
|
||||
SetFlexWeight("nost_height",RandomFloat(0,1));
|
||||
SetFlexWeight("nost_width",RandomFloat(0,1));
|
||||
SetFlexWeight("nose_tip",RandomFloat(0,1));
|
||||
SetFlexWeight("hairline_puff",RandomFloat(0,1));
|
||||
|
||||
if (RandomInt(0,5)==4) {
|
||||
SetBodygroup( 2, 1 );
|
||||
SetFlexWeight("cigar_mouth",1);
|
||||
}
|
||||
else {
|
||||
SetBodygroup( 2, 0 );
|
||||
SetFlexWeight("cigar_mouth",0);
|
||||
}
|
||||
m_nSkin=RandomInt(0,14);
|
||||
SetBodygroup( 3, RandomInt(0,1) );
|
||||
//SetBodygroup( 4, RandomInt(0,1) );
|
||||
m_iHealth = 40;
|
||||
m_flFieldOfView = 0.5;
|
||||
m_NPCState = NPC_STATE_NONE;
|
||||
|
||||
CapabilitiesClear();
|
||||
CapabilitiesAdd( bits_CAP_MOVE_GROUND );
|
||||
CapabilitiesAdd( bits_CAP_MOVE_JUMP );
|
||||
CapabilitiesAdd( bits_CAP_MOVE_GROUND );
|
||||
CapabilitiesAdd( bits_CAP_MOVE_CLIMB );
|
||||
CapabilitiesAdd( bits_CAP_MOVE_CRAWL );
|
||||
CapabilitiesAdd( bits_CAP_DUCK );
|
||||
|
||||
CapabilitiesAdd( bits_CAP_USE_WEAPONS );
|
||||
CapabilitiesAdd( bits_CAP_RANGE_ATTACK_GROUP );
|
||||
CapabilitiesAdd( bits_CAP_MELEE_ATTACK_GROUP );
|
||||
CapabilitiesAdd( bits_CAP_INNATE_MELEE_ATTACK1 );
|
||||
CapabilitiesAdd( bits_CAP_MOVE_SHOOT );
|
||||
|
||||
CapabilitiesAdd( bits_CAP_NO_HIT_SQUADMATES );
|
||||
CapabilitiesAdd( bits_CAP_SQUAD );
|
||||
|
||||
CapabilitiesAdd( bits_CAP_USE );
|
||||
CapabilitiesAdd( bits_CAP_DOORS_GROUP );
|
||||
|
||||
CapabilitiesAdd( bits_CAP_TURN_HEAD );
|
||||
CapabilitiesAdd( bits_CAP_ANIMATEDFACE );
|
||||
|
||||
CapabilitiesAdd( bits_CAP_AIM_GUN );
|
||||
CapabilitiesAdd( bits_CAP_MOVE_GROUND );
|
||||
|
||||
CBaseCombatWeapon *pWeapon = Weapon_Create( "weapon_shotgun" );
|
||||
pWeapon->SetName( AllocPooledString(UTIL_VarArgs("%s_weapon", STRING(GetEntityName()))) );
|
||||
pWeapon->AddEffects( EF_NOSHADOW );
|
||||
Weapon_Equip( pWeapon );
|
||||
|
||||
NPCInit();
|
||||
}
|
||||
|
||||
void CNPCHuman::StartTask( const Task_t *pTask )
|
||||
{
|
||||
switch (pTask->iTask) {
|
||||
case TASK_RUN_PATH:
|
||||
GetNavigator()->SetMovementActivity(ACT_RUN_RIFLE);
|
||||
break;
|
||||
case TASK_WALK_PATH:
|
||||
GetNavigator()->SetMovementActivity(ACT_WALK_UNARMED);
|
||||
break;
|
||||
default:
|
||||
BaseClass::StartTask(pTask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//
|
||||
//
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
Class_T CNPCHuman::Classify( void )
|
||||
{
|
||||
return CLASS_MILITARY;
|
||||
}
|
||||
|
||||
int CNPCHuman::SelectSchedule( void )
|
||||
{
|
||||
if ( HasCondition( COND_HEAR_PHYSICS_DANGER ) )
|
||||
{
|
||||
return SCHED_FLINCH_PHYSICS;
|
||||
}
|
||||
|
||||
// grunts place HIGH priority on running away from danger sounds.
|
||||
if ( HasCondition(COND_HEAR_DANGER) )
|
||||
{
|
||||
CSound *pSound;
|
||||
pSound = GetBestSound();
|
||||
|
||||
Assert( pSound != NULL );
|
||||
if ( pSound)
|
||||
{
|
||||
if (pSound->m_iType & SOUND_DANGER)
|
||||
{
|
||||
// I hear something dangerous, probably need to take cover.
|
||||
// dangerous sound nearby!, call it out
|
||||
/*const char *pSentenceName = "COMBINE_DANGER";
|
||||
|
||||
CBaseEntity *pSoundOwner = pSound->m_hOwner;
|
||||
if ( pSoundOwner )
|
||||
{
|
||||
CBaseGrenade *pGrenade = dynamic_cast<CBaseGrenade *>(pSoundOwner);
|
||||
if ( pGrenade && pGrenade->GetThrower() )
|
||||
{
|
||||
if ( IRelationType( pGrenade->GetThrower() ) != D_LI )
|
||||
{
|
||||
// special case call out for enemy grenades
|
||||
pSentenceName = "COMBINE_GREN";
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_NORMAL, SENTENCE_CRITERIA_NORMAL );
|
||||
|
||||
// If the sound is approaching danger, I have no enemy, and I don't see it, turn to face.
|
||||
if( !GetEnemy() && pSound->IsSoundType(SOUND_CONTEXT_DANGER_APPROACH) && pSound->m_hOwner && !FInViewCone(pSound->GetSoundReactOrigin()) )
|
||||
{
|
||||
GetMotor()->SetIdealYawToTarget( pSound->GetSoundReactOrigin() );
|
||||
return SCHED_ALERT_FACE_BESTSOUND;
|
||||
}
|
||||
|
||||
return SCHED_TAKE_COVER_FROM_BEST_SOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( m_NPCState )
|
||||
{
|
||||
case NPC_STATE_IDLE:
|
||||
return SCHED_IDLE_STAND;
|
||||
break;
|
||||
case NPC_STATE_COMBAT:
|
||||
if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) )
|
||||
return SCHED_MELEE_ATTACK1;
|
||||
|
||||
if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) )
|
||||
return SCHED_RANGE_ATTACK1;
|
||||
|
||||
return SCHED_CHASE_ENEMY;
|
||||
break;
|
||||
}
|
||||
return SCHED_FAIL;
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue