From 1ceb22e15121a7355b3c5ef6986d1d85f2e4308f Mon Sep 17 00:00:00 2001 From: Night Owl Date: Mon, 10 Apr 2017 23:07:03 +0500 Subject: [PATCH] Cut nodes. --- dlls/CMakeLists.txt | 4 +- dlls/mpstubb.cpp | 217 --------------------------- dlls/nodes.h | 346 ++------------------------------------------ 3 files changed, 16 insertions(+), 551 deletions(-) diff --git a/dlls/CMakeLists.txt b/dlls/CMakeLists.txt index 695b002b..975cfd08 100644 --- a/dlls/CMakeLists.txt +++ b/dlls/CMakeLists.txt @@ -96,13 +96,13 @@ set (SVDLL_SOURCES lights.cpp maprules.cpp # monstermaker.cpp -# monsters.cpp + monsters.cpp # monsterstate.cpp # mortar.cpp # mp5.cpp multiplay_gamerules.cpp # nihilanth.cpp - nodes.cpp +# nodes.cpp # osprey.cpp pathcorner.cpp plane.cpp diff --git a/dlls/mpstubb.cpp b/dlls/mpstubb.cpp index 703a4dba..17c337b5 100644 --- a/dlls/mpstubb.cpp +++ b/dlls/mpstubb.cpp @@ -36,221 +36,4 @@ int CGraph::FindNearestNode( const Vector &vecOrigin, int afNodeTypes ) { return /*********************************************************/ -void CBaseMonster::ReportAIState( void ) { } -float CBaseMonster::ChangeYaw( int speed ) { return 0; } -void CBaseMonster::MakeIdealYaw( Vector vecTarget ) { } -void CBaseMonster::CorpseFallThink( void ) -{ - if( pev->flags & FL_ONGROUND ) - { - SetThink( NULL ); - - SetSequenceBox(); - UTIL_SetOrigin( pev, pev->origin );// link into world. - } - else - pev->nextthink = gpGlobals->time + 0.1; -} - -// Call after animation/pose is set up -void CBaseMonster::MonsterInitDead( void ) -{ - InitBoneControllers(); - - pev->solid = SOLID_BBOX; - pev->movetype = MOVETYPE_TOSS;// so he'll fall to ground - - pev->frame = 0; - ResetSequenceInfo(); - pev->framerate = 0; - - // Copy health - pev->max_health = pev->health; - pev->deadflag = DEAD_DEAD; - - UTIL_SetSize( pev, g_vecZero, g_vecZero ); - UTIL_SetOrigin( pev, pev->origin ); - - // Setup health counters, etc. - BecomeDead(); - SetThink( &CBaseMonster::CorpseFallThink ); - pev->nextthink = gpGlobals->time + 0.5; -} - -BOOL CBaseMonster::ShouldFadeOnDeath( void ) -{ - return FALSE; -} - -BOOL CBaseMonster::FCheckAITrigger( void ) -{ - return FALSE; -} - -void CBaseMonster::KeyValue( KeyValueData *pkvd ) -{ - CBaseToggle::KeyValue( pkvd ); -} - -int CBaseMonster::IRelationship( CBaseEntity *pTarget ) -{ - static int iEnemy[14][14] = - { // NONE MACH PLYR HPASS HMIL AMIL APASS AMONST APREY APRED INSECT PLRALY PBWPN ABWPN - /*NONE*/ { R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO }, - /*MACHINE*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_DL, R_DL }, - /*PLAYER*/ { R_NO ,R_DL ,R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_DL, R_DL }, - /*HUMANPASSIVE*/{ R_NO ,R_NO ,R_AL ,R_AL ,R_HT ,R_FR ,R_NO ,R_HT ,R_DL ,R_FR ,R_NO ,R_AL, R_NO, R_NO }, - /*HUMANMILITAR*/{ R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_HT ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_HT, R_NO, R_NO }, - /*ALIENMILITAR*/{ R_NO ,R_DL ,R_HT ,R_DL ,R_HT ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO }, - /*ALIENPASSIVE*/{ R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO }, - /*ALIENMONSTER*/{ R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO }, - /*ALIENPREY */{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_FR ,R_NO ,R_DL, R_NO, R_NO }, - /*ALIENPREDATO*/{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_DL, R_NO, R_NO }, - /*INSECT*/ { R_FR ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR, R_NO, R_NO }, - /*PLAYERALLY*/ { R_NO ,R_DL ,R_AL ,R_AL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_NO, R_NO }, - /*PBIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_NO, R_DL }, - /*ABIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_AL ,R_NO ,R_DL ,R_DL ,R_NO ,R_NO ,R_DL, R_DL, R_NO } - }; - - return iEnemy[Classify()][pTarget->Classify()]; -} - -//========================================================= -// Look - Base class monster function to find enemies or -// food by sight. iDistance is distance ( in units ) that the -// monster can see. -// -// Sets the sight bits of the m_afConditions mask to indicate -// which types of entities were sighted. -// Function also sets the Looker's m_pLink -// to the head of a link list that contains all visible ents. -// (linked via each ent's m_pLink field) -// -//========================================================= -void CBaseMonster::Look( int iDistance ) -{ - int iSighted = 0; - - // DON'T let visibility information from last frame sit around! - ClearConditions( bits_COND_SEE_HATE | bits_COND_SEE_DISLIKE | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR | bits_COND_SEE_NEMESIS | bits_COND_SEE_CLIENT ); - - m_pLink = NULL; - - CBaseEntity *pSightEnt = NULL;// the current visible entity that we're dealing with - - CBaseEntity *pList[100]; - - Vector delta = Vector( iDistance, iDistance, iDistance ); - - // Find only monsters/clients in box, NOT limited to PVS - int count = UTIL_EntitiesInBox( pList, 100, pev->origin - delta, pev->origin + delta, FL_CLIENT | FL_MONSTER ); - for( int i = 0; i < count; i++ ) - { - pSightEnt = pList[i]; - if( pSightEnt != this && pSightEnt->pev->health > 0 ) - { - // the looker will want to consider this entity - // don't check anything else about an entity that can't be seen, or an entity that you don't care about. - if( IRelationship( pSightEnt ) != R_NO && FInViewCone( pSightEnt ) && !FBitSet( pSightEnt->pev->flags, FL_NOTARGET ) && FVisible( pSightEnt ) ) - { - if( pSightEnt->IsPlayer() ) - { - // if we see a client, remember that (mostly for scripted AI) - iSighted |= bits_COND_SEE_CLIENT; - } - - pSightEnt->m_pLink = m_pLink; - m_pLink = pSightEnt; - - if( pSightEnt == m_hEnemy ) - { - // we know this ent is visible, so if it also happens to be our enemy, store that now. - iSighted |= bits_COND_SEE_ENEMY; - } - - // don't add the Enemy's relationship to the conditions. We only want to worry about conditions when - // we see monsters other than the Enemy. - switch( IRelationship( pSightEnt ) ) - { - case R_NM: - iSighted |= bits_COND_SEE_NEMESIS; - break; - case R_HT: - iSighted |= bits_COND_SEE_HATE; - break; - case R_DL: - iSighted |= bits_COND_SEE_DISLIKE; - break; - case R_FR: - iSighted |= bits_COND_SEE_FEAR; - break; - case R_AL: - break; - default: - ALERT( at_aiconsole, "%s can't assess %s\n", STRING( pev->classname ), STRING(pSightEnt->pev->classname ) ); - break; - } - } - } - } - - SetConditions( iSighted ); -} - -//========================================================= -// BestVisibleEnemy - this functions searches the link -// list whose head is the caller's m_pLink field, and returns -// a pointer to the enemy entity in that list that is nearest the -// caller. -// -// !!!UNDONE - currently, this only returns the closest enemy. -// we'll want to consider distance, relationship, attack types, back turned, etc. -//========================================================= -CBaseEntity *CBaseMonster::BestVisibleEnemy( void ) -{ - CBaseEntity *pReturn; - CBaseEntity *pNextEnt; - int iNearest; - int iDist; - int iBestRelationship; - - iNearest = 8192;// so first visible entity will become the closest. - pNextEnt = m_pLink; - pReturn = NULL; - iBestRelationship = R_NO; - - while( pNextEnt != NULL ) - { - if( pNextEnt->IsAlive() ) - { - if( IRelationship( pNextEnt ) > iBestRelationship ) - { - // this entity is disliked MORE than the entity that we - // currently think is the best visible enemy. No need to do - // a distance check, just get mad at this one for now. - iBestRelationship = IRelationship( pNextEnt ); - iNearest = ( pNextEnt->pev->origin - pev->origin ).Length(); - pReturn = pNextEnt; - } - else if( IRelationship( pNextEnt ) == iBestRelationship ) - { - // this entity is disliked just as much as the entity that - // we currently think is the best visible enemy, so we only - // get mad at it if it is closer. - iDist = ( pNextEnt->pev->origin - pev->origin ).Length(); - - if( iDist <= iNearest ) - { - iNearest = iDist; - iBestRelationship = IRelationship( pNextEnt ); - pReturn = pNextEnt; - } - } - } - - pNextEnt = pNextEnt->m_pLink; - } - - return pReturn; -} diff --git a/dlls/nodes.h b/dlls/nodes.h index 27b890ed..406f4577 100644 --- a/dlls/nodes.h +++ b/dlls/nodes.h @@ -6,367 +6,49 @@ * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * -* This source code contains proprietary and confidential information of -* Valve LLC and its suppliers. Access to this code is restricted to -* persons who have executed a written SDK license with Valve. Any access, -* use or distribution of this code by or to any unlicensed person is illegal. +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. * ****/ //========================================================= // nodes.h //========================================================= -//========================================================= -// DEFINE -//========================================================= -#define MAX_STACK_NODES 100 -#define NO_NODE -1 -#define MAX_NODE_HULLS 4 - -#define bits_NODE_LAND ( 1 << 0 ) // Land node, so nudge if necessary. -#define bits_NODE_AIR ( 1 << 1 ) // Air node, don't nudge. -#define bits_NODE_WATER ( 1 << 2 ) // Water node, don't nudge. -#define bits_NODE_GROUP_REALM (bits_NODE_LAND | bits_NODE_AIR | bits_NODE_WATER) - -//========================================================= -// Instance of a node. -//========================================================= -class CNode -{ -public: - Vector m_vecOrigin;// location of this node in space - Vector m_vecOriginPeek; // location of this node (LAND nodes are NODE_HEIGHT higher). - BYTE m_Region[3]; // Which of 256 regions do each of the coordinate belong? - int m_afNodeInfo;// bits that tell us more about this location - - int m_cNumLinks; // how many links this node has - int m_iFirstLink;// index of this node's first link in the link pool. - - // Where to start looking in the compressed routing table (offset into m_pRouteInfo). - // (4 hull sizes -- smallest to largest + fly/swim), and secondly, door capability. - // - int m_pNextBestNode[MAX_NODE_HULLS][2]; - - // Used in finding the shortest path. m_fClosestSoFar is -1 if not visited. - // Then it is the distance to the source. If another path uses this node - // and has a closer distance, then m_iPreviousNode is also updated. - // - float m_flClosestSoFar; // Used in finding the shortest path. - int m_iPreviousNode; - - short m_sHintType;// there is something interesting in the world at this node's position - short m_sHintActivity;// there is something interesting in the world at this node's position - float m_flHintYaw;// monster on this node should face this yaw to face the hint. -}; - -//========================================================= -// CLink - A link between 2 nodes -//========================================================= -#define bits_LINK_SMALL_HULL ( 1 << 0 )// headcrab box can fit through this connection -#define bits_LINK_HUMAN_HULL ( 1 << 1 )// player box can fit through this connection -#define bits_LINK_LARGE_HULL ( 1 << 2 )// big box can fit through this connection -#define bits_LINK_FLY_HULL ( 1 << 3 )// a flying big box can fit through this connection -#define bits_LINK_DISABLED ( 1 << 4 )// link is not valid when the set - -#define NODE_SMALL_HULL 0 -#define NODE_HUMAN_HULL 1 -#define NODE_LARGE_HULL 2 -#define NODE_FLY_HULL 3 +#ifndef NODES_H +#define NODES_H +#define NO_NODE -1 +#define bits_NODE_GROUP_REALM 1 class CLink { public: - int m_iSrcNode;// the node that 'owns' this link ( keeps us from having to make reverse lookups ) - int m_iDestNode;// the node on the other end of the link. - entvars_t *m_pLinkEnt;// the entity that blocks this connection (doors, etc) - - // m_szLinkEntModelname is not necessarily NULL terminated (so we can store it in a more alignment-friendly 4 bytes) - char m_szLinkEntModelname[ 4 ];// the unique name of the brush model that blocks the connection (this is kept for save/restore) - - int m_afLinkInfo;// information about this link - float m_flWeight;// length of the link line segment }; -typedef struct -{ - int m_SortedBy[3]; - int m_CheckedEvent; -} DIST_INFO; - -typedef struct -{ - Vector v; - short n; // Nearest node or -1 if no node found. -} CACHE_ENTRY; - -//========================================================= -// CGraph -//========================================================= -#define GRAPH_VERSION (int)16// !!!increment this whever graph/node/link classes change, to obsolesce older disk files. class CGraph { public: - -// the graph has two flags, and should not be accessed unless both flags are TRUE! BOOL m_fGraphPresent;// is the graph in memory? BOOL m_fGraphPointersSet;// are the entity pointers for the graph all set? - BOOL m_fRoutingComplete; // are the optimal routes computed, yet? - CNode *m_pNodes;// pointer to the memory block that contains all node info - CLink *m_pLinkPool;// big list of all node connections - signed char *m_pRouteInfo; // compressed routing information the nodes use. - - int m_cNodes;// total number of nodes int m_cLinks;// total number of links - int m_nRouteInfo; // size of m_pRouteInfo in bytes. - - // Tables for making nearest node lookup faster. SortedBy provided nodes in a - // order of a particular coordinate. Instead of doing a binary search, RangeStart - // and RangeEnd let you get to the part of SortedBy that you are interested in. - // - // Once you have a point of interest, the only way you'll find a closer point is - // if at least one of the coordinates is closer than the ones you have now. So we - // search each range. After the search is exhausted, we know we have the closest - // node. - // -#define CACHE_SIZE 128 -#define NUM_RANGES 256 - DIST_INFO *m_di; // This is m_cNodes long, but the entries don't correspond to CNode entries. - int m_RangeStart[3][NUM_RANGES]; - int m_RangeEnd[3][NUM_RANGES]; - float m_flShortest; - int m_iNearest; - int m_minX, m_minY, m_minZ, m_maxX, m_maxY, m_maxZ; - int m_minBoxX, m_minBoxY, m_minBoxZ, m_maxBoxX, m_maxBoxY, m_maxBoxZ; - int m_CheckedCounter; - float m_RegionMin[3], m_RegionMax[3]; // The range of nodes. - CACHE_ENTRY m_Cache[CACHE_SIZE]; - - - int m_HashPrimes[16]; - short *m_pHashLinks; - int m_nHashLinks; - - - // kinda sleazy. In order to allow variety in active idles for monster groups in a room with more than one node, - // we keep track of the last node we searched from and store it here. Subsequent searches by other monsters will pick - // up where the last search stopped. - int m_iLastActiveIdleSearch; - - // another such system used to track the search for cover nodes, helps greatly with two monsters trying to get to the same node. - int m_iLastCoverSearch; - - // functions to create the graph - int LinkVisibleNodes ( CLink *pLinkPool, FILE *file, int *piBadNode ); - int RejectInlineLinks ( CLink *pLinkPool, FILE *file ); - int FindShortestPath ( int *piPath, int iStart, int iDest, int iHull, int afCapMask); - int FindNearestNode ( const Vector &vecOrigin, CBaseEntity *pEntity ); - int FindNearestNode ( const Vector &vecOrigin, int afNodeTypes ); - //int FindNearestLink ( const Vector &vecTestPoint, int *piNearestLink, BOOL *pfAlongLine ); - float PathLength( int iStart, int iDest, int iHull, int afCapMask ); - int NextNodeInRoute( int iCurrentNode, int iDest, int iHull, int iCap ); + CLink *m_pLinkPool;// big list of all node connections - enum NODEQUERY { NODEGRAPH_DYNAMIC, NODEGRAPH_STATIC }; - // A static query means we're asking about the possiblity of handling this entity at ANY time - // A dynamic query means we're asking about it RIGHT NOW. So we should query the current state - int HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, NODEQUERY queryType ); - entvars_t* LinkEntForLink ( CLink *pLink, CNode *pNode ); - void ShowNodeConnections ( int iNode ); void InitGraph( void ); int AllocNodes ( void ); int CheckNODFile(char *szMapName); int FLoadGraph(char *szMapName); - int FSaveGraph(char *szMapName); int FSetGraphPointers(void); - void CheckNode(Vector vecOrigin, int iNode); - - void BuildRegionTables(void); - void ComputeStaticRoutingTables(void); - void TestRoutingTables(void); - - void HashInsert(int iSrcNode, int iDestNode, int iKey); - void HashSearch(int iSrcNode, int iDestNode, int &iKey); - void HashChoosePrimes(int TableSize); - void BuildLinkLookups(void); - - void SortNodes(void); - - int HullIndex( const CBaseEntity *pEntity ); // what hull the monster uses - int NodeType( const CBaseEntity *pEntity ); // what node type the monster uses - inline int CapIndex( int afCapMask ) - { - if (afCapMask & (bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE)) - return 1; - return 0; - } - - - inline CNode &Node( int i ) - { -#ifdef _DEBUG - if ( !m_pNodes || i < 0 || i > m_cNodes ) - ALERT( at_error, "Bad Node!\n" ); -#endif - return m_pNodes[i]; - } - - inline CLink &Link( int i ) - { -#ifdef _DEBUG - if ( !m_pLinkPool || i < 0 || i > m_cLinks ) - ALERT( at_error, "Bad link!\n" ); -#endif - return m_pLinkPool[i]; - } - - inline CLink &NodeLink( int iNode, int iLink ) - { - return Link( Node( iNode ).m_iFirstLink + iLink ); - } - - inline CLink &NodeLink( const CNode &node, int iLink ) - { - return Link( node.m_iFirstLink + iLink ); - } - - inline int INodeLink ( int iNode, int iLink ) - { - return NodeLink( iNode, iLink ).m_iDestNode; - } - -#if 0 - inline CNode &SourceNode( int iNode, int iLink ) - { - return Node( NodeLink( iNode, iLink ).m_iSrcNode ); - } - - inline CNode &DestNode( int iNode, int iLink ) - { - return Node( NodeLink( iNode, iLink ).m_iDestNode ); - } - - inline CNode *PNodeLink ( int iNode, int iLink ) - { - return &DestNode( iNode, iLink ); - } -#endif -}; - -//========================================================= -// Nodes start out as ents in the level. The node graph -// is built, then these ents are discarded. -//========================================================= -class CNodeEnt : public CBaseEntity -{ - void Spawn( void ); - void KeyValue( KeyValueData *pkvd ); - virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - short m_sHintType; - short m_sHintActivity; -}; - -//========================================================= -// CStack - last in, first out. -//========================================================= -class CStack -{ -public: - CStack( void ); - void Push( int value ); - int Pop( void ); - int Top( void ); - int Empty( void ) { return m_level==0; } - int Size( void ) { return m_level; } - void CopyToArray ( int *piArray ); - -private: - int m_stack[ MAX_STACK_NODES ]; - int m_level; -}; - -//========================================================= -// CQueue - first in, first out. -//========================================================= -class CQueue -{ -public: - - CQueue( void );// constructor - inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); } - inline int Empty ( void ) { return ( m_cSize == 0 ); } - //inline int Tail ( void ) { return ( m_queue[ m_tail ] ); } - inline int Size ( void ) { return ( m_cSize ); } - void Insert( int, float ); - int Remove( float & ); - -private: - int m_cSize; - struct tag_QUEUE_NODE - { - int Id; - float Priority; - } m_queue[ MAX_STACK_NODES ]; - int m_head; - int m_tail; -}; - -//========================================================= -// CQueuePriority - Priority queue (smallest item out first). -// -//========================================================= -class CQueuePriority -{ -public: - - CQueuePriority( void );// constructor - inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); } - inline int Empty ( void ) { return ( m_cSize == 0 ); } - //inline int Tail ( float & ) { return ( m_queue[ m_tail ].Id ); } - inline int Size ( void ) { return ( m_cSize ); } - void Insert( int, float ); - int Remove( float &); - -private: - int m_cSize; - struct tag_HEAP_NODE - { - int Id; - float Priority; - } m_heap[ MAX_STACK_NODES ]; - void Heap_SiftDown(int); - void Heap_SiftUp(void); - -}; - -//========================================================= -// hints - these MUST coincide with the HINTS listed under -// info_node in the FGD file! -//========================================================= -enum -{ - HINT_NONE = 0, - HINT_WORLD_DOOR, - HINT_WORLD_WINDOW, - HINT_WORLD_BUTTON, - HINT_WORLD_MACHINERY, - HINT_WORLD_LEDGE, - HINT_WORLD_LIGHT_SOURCE, - HINT_WORLD_HEAT_SOURCE, - HINT_WORLD_BLINKING_LIGHT, - HINT_WORLD_BRIGHT_COLORS, - HINT_WORLD_HUMAN_BLOOD, - HINT_WORLD_ALIEN_BLOOD, - - HINT_TACTICAL_EXIT = 100, - HINT_TACTICAL_VANTAGE, - HINT_TACTICAL_AMBUSH, + void ShowNodeConnections ( int iNode ); + int FindNearestNode ( const Vector &vecOrigin, CBaseEntity *pEntity ); + int FindNearestNode ( const Vector &vecOrigin, int afNodeTypes ); - HINT_STUKA_PERCH = 300, - HINT_STUKA_LANDING }; extern CGraph WorldGraph; + +#endif // NODES_H