Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
7.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Base combat character with no AI
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. //
  8. //-----------------------------------------------------------------------------
  9. // $Log: $
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================//
  13. #include "cbase.h"
  14. #include "ai_hull.h"
  15. #include "ai_node.h"
  16. #include "ai_link.h"
  17. #include "ai_network.h"
  18. #include "ai_initutils.h"
  19. #include "bitstring.h"
  20. #include "ai_basenpc.h"
  21. #include "ai_navigator.h"
  22. #include "ai_moveprobe.h"
  23. #include "fmtstr.h"
  24. #include "game.h"
  25. #include "ai_networkmanager.h"
  26. // memdbgon must be the last include file in a .cpp file!!!
  27. #include "tier0/memdbgon.h"
  28. //-----------------------------------------------------------------------------
  29. CAI_Link *CAI_Node::GetLink( int destNodeId )
  30. {
  31. // Now make sure this node still has a link to the destID
  32. for ( int link = 0; link < NumLinks(); link++ )
  33. {
  34. // If we find the link the dynamic link is valid
  35. if ( m_Links[link]->DestNodeID(m_iID) == destNodeId )
  36. {
  37. return m_Links[link];
  38. }
  39. }
  40. return NULL;
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Purpose: Add a link to this node
  44. // Input :
  45. // Output :
  46. //-----------------------------------------------------------------------------
  47. void CAI_Node::AddLink(CAI_Link *newLink)
  48. {
  49. if ( NumLinks() == AI_MAX_NODE_LINKS )
  50. {
  51. DevMsg( "Node %d has too many links\n", m_iID );
  52. return;
  53. }
  54. #ifdef _DEBUG
  55. for (int link=0;link<NumLinks();link++)
  56. {
  57. if (m_Links[link] == newLink)
  58. {
  59. AssertMsgOnce( 0, "Link added to node multiple times!" );
  60. return;
  61. }
  62. }
  63. AssertMsg( newLink->m_iDestID == m_iID || newLink->m_iSrcID == m_iID, "Added link to node that doesn't reference the node" );
  64. #endif
  65. m_Links.AddToTail( newLink );
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose: Returns link if node has a link to node of the given nNodeID.
  69. // Otherwise returns NULL
  70. // Input :
  71. // Output :
  72. //-----------------------------------------------------------------------------
  73. CAI_Link* CAI_Node::HasLink(int nNodeID)
  74. {
  75. for (int link=0;link<NumLinks();link++)
  76. {
  77. // If node has link to myself, than add link to my list of links
  78. if (m_Links[link]->DestNodeID(m_iID) == nNodeID)
  79. {
  80. return m_Links[link];
  81. }
  82. }
  83. return NULL;
  84. }
  85. //------------------------------------------------------------------------------
  86. // Purpose : Called before GetShuffeledLinks to change the order in which
  87. // links are returned
  88. // Input :
  89. // Output :
  90. //------------------------------------------------------------------------------
  91. void CAI_Node::ShuffleLinks(void)
  92. {
  93. m_iFirstShuffledLink++;
  94. if (m_iFirstShuffledLink >= NumLinks())
  95. {
  96. m_iFirstShuffledLink = 0;
  97. }
  98. }
  99. //------------------------------------------------------------------------------
  100. // Purpose : Used to get links in different order each time.
  101. // Call ShuffleLinks() first
  102. // Input :
  103. // Output :
  104. //------------------------------------------------------------------------------
  105. CAI_Link* CAI_Node::GetShuffeledLink(int nNum)
  106. {
  107. int nLinkID = m_iFirstShuffledLink + nNum;
  108. if (nLinkID >= NumLinks())
  109. {
  110. nLinkID -= NumLinks();
  111. }
  112. return m_Links[nLinkID];
  113. }
  114. //----------------------------------------------------------------------------------
  115. // Purpose: Returns z value of floor below given point (up to fMaxDrop inches below)
  116. // Input :
  117. // Output :
  118. //----------------------------------------------------------------------------------
  119. float GetFloorZ(const Vector &origin, float fMaxDrop)
  120. {
  121. // trace to the ground, then pop up 8 units and place node there to make it
  122. // easier for them to connect (think stairs, chairs, and bumps in the floor).
  123. // After the routing is done, push them back down.
  124. //
  125. trace_t tr;
  126. AI_TraceLine ( origin,
  127. origin - Vector ( 0, 0, fMaxDrop ),
  128. MASK_NPCSOLID_BRUSHONLY,
  129. NULL,
  130. COLLISION_GROUP_NONE,
  131. &tr );
  132. // This trace is ONLY used if we hit an entity flagged with FL_WORLDBRUSH
  133. trace_t trEnt;
  134. AI_TraceLine ( origin,
  135. origin - Vector ( 0, 0, fMaxDrop ),
  136. MASK_NPCSOLID,
  137. NULL,
  138. COLLISION_GROUP_NONE,
  139. &trEnt );
  140. // Did we hit something closer than the floor?
  141. if ( trEnt.fraction < tr.fraction )
  142. {
  143. // If it was a world brush entity, copy the node location
  144. if ( trEnt.m_pEnt )
  145. {
  146. CBaseEntity *e = trEnt.m_pEnt;
  147. if ( e && ( e->GetFlags() & FL_WORLDBRUSH ) )
  148. {
  149. tr.endpos = trEnt.endpos;
  150. }
  151. }
  152. }
  153. return tr.endpos.z;
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose: Returns z value of floor below given point (up to 384 inches below)
  157. // Input :
  158. // Output :
  159. //-----------------------------------------------------------------------------
  160. float GetFloorZ(const Vector &origin)
  161. {
  162. return GetFloorZ(origin, 384);
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Purpose: Returns distance of floor from the origin (up to 384 inches)
  166. // Input :
  167. // Output :
  168. //-----------------------------------------------------------------------------
  169. float GetFloorDistance(const Vector &origin)
  170. {
  171. return (origin.z - GetFloorZ(origin));
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose: Climb nodes are centered over the climb surface, the must be
  175. // shifted away from the climb surface according to the hull size
  176. // of the NPC using the climb
  177. // Input :
  178. // Output :
  179. //-----------------------------------------------------------------------------
  180. Vector CAI_Node::GetPosition(int hull)
  181. {
  182. if (m_eNodeType == NODE_CLIMB)
  183. {
  184. // Shift by the length of the hull and some small fudge
  185. float shift = (0.5*NAI_Hull::Length(hull)) + (NODE_CLIMB_OFFSET);
  186. Vector offsetDir = Vector(cos(DEG2RAD(m_flYaw)),sin(DEG2RAD(m_flYaw)),0);
  187. Vector origin;
  188. if (m_eNodeInfo & bits_NODE_CLIMB_OFF_FORWARD)
  189. {
  190. origin = m_vOrigin + (shift * offsetDir);
  191. }
  192. else if (m_eNodeInfo & bits_NODE_CLIMB_OFF_LEFT)
  193. {
  194. Vector upDir(0,0,1);
  195. Vector leftDir;
  196. CrossProduct( offsetDir, upDir, leftDir);
  197. origin = m_vOrigin - (2 * shift * leftDir) - (shift * offsetDir);
  198. }
  199. else if (m_eNodeInfo & bits_NODE_CLIMB_OFF_RIGHT)
  200. {
  201. Vector upDir(0,0,1);
  202. Vector leftDir;
  203. CrossProduct( offsetDir, upDir, leftDir);
  204. origin = m_vOrigin + (2 * shift * leftDir) - (shift * offsetDir);
  205. }
  206. else
  207. {
  208. origin = m_vOrigin - (shift * offsetDir);
  209. }
  210. return Vector( origin.x, origin.y, origin.z + m_flVOffset[hull] );
  211. }
  212. else if (m_eNodeType == NODE_GROUND)
  213. {
  214. // this is the floor resting position of this hull, adjusted to account for mins.z
  215. return Vector( m_vOrigin.x, m_vOrigin.y, m_vOrigin.z + m_flVOffset[hull] );
  216. }
  217. else
  218. {
  219. return m_vOrigin;
  220. }
  221. }
  222. //-----------------------------------------------------------------------------
  223. // Purpose: Constructor
  224. // Input :
  225. // Output :
  226. //-----------------------------------------------------------------------------
  227. CAI_Node::CAI_Node( int id, const Vector &origin, float yaw )
  228. : m_Links( 0, 4 )
  229. {
  230. m_vOrigin = origin;
  231. m_iID = id;
  232. for (int i = 0; i < NUM_HULLS; i++)
  233. {
  234. m_flVOffset[i] = 0.0;
  235. }
  236. m_eNodeType = NODE_GROUND;
  237. m_eNodeInfo = 0;
  238. m_iFirstShuffledLink = 0;
  239. m_pHint = NULL;
  240. m_flYaw = yaw;
  241. m_flNextUseTime = 0;
  242. m_zone = AI_NODE_ZONE_UNKNOWN;
  243. };