bot_exports.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. #include "../g_local.h"
  4. #include "bot_exports.h"
  5. /*
  6. ================
  7. Bot_SetWeapon
  8. ================
  9. */
  10. void Bot_SetWeapon( edict_t * bot, const int weaponIndex, const bool instantSwitch ) {
  11. if ( weaponIndex <= IT_NULL || weaponIndex > IT_TOTAL ) {
  12. return;
  13. }
  14. if ( ( bot->svflags & SVF_BOT ) == 0 ) {
  15. return;
  16. }
  17. gclient_t * client = bot->client;
  18. if ( client == nullptr || !client->pers.inventory[ weaponIndex ] ) {
  19. return;
  20. }
  21. const item_id_t weaponItemID = static_cast<item_id_t>( weaponIndex );
  22. const gitem_t * currentGun = client->pers.weapon;
  23. if ( currentGun != nullptr ) {
  24. if ( currentGun->id == weaponItemID ) {
  25. return;
  26. } // already have the gun in hand.
  27. }
  28. const gitem_t * pendingGun = client->newweapon;
  29. if ( pendingGun != nullptr ) {
  30. if ( pendingGun->id == weaponItemID ) {
  31. return;
  32. } // already in the process of switching to that gun, just be patient!
  33. }
  34. gitem_t * item = &itemlist[ weaponIndex ];
  35. if ( ( item->flags & IF_WEAPON ) == 0 ) {
  36. return;
  37. }
  38. if ( item->use == nullptr ) {
  39. return;
  40. }
  41. bot->client->no_weapon_chains = true;
  42. item->use( bot, item );
  43. if ( instantSwitch ) {
  44. // FIXME: ugly, maybe store in client later
  45. const int temp_instant_weapon = g_instant_weapon_switch->integer;
  46. g_instant_weapon_switch->integer = 1;
  47. ChangeWeapon( bot );
  48. g_instant_weapon_switch->integer = temp_instant_weapon;
  49. }
  50. }
  51. /*
  52. ================
  53. Bot_TriggerEdict
  54. ================
  55. */
  56. void Bot_TriggerEdict( edict_t * bot, edict_t * edict ) {
  57. if ( !bot->inuse || !edict->inuse ) {
  58. return;
  59. }
  60. if ( ( bot->svflags & SVF_BOT ) == 0 ) {
  61. return;
  62. }
  63. if ( edict->use ) {
  64. edict->use( edict, bot, bot );
  65. }
  66. trace_t unUsed;
  67. if ( edict->touch ) {
  68. edict->touch( edict, bot, unUsed, true );
  69. }
  70. }
  71. /*
  72. ================
  73. Bot_UseItem
  74. ================
  75. */
  76. void Bot_UseItem( edict_t * bot, const int32_t itemID ) {
  77. if ( !bot->inuse ) {
  78. return;
  79. }
  80. if ( ( bot->svflags & SVF_BOT ) == 0 ) {
  81. return;
  82. }
  83. const item_id_t desiredItemID = item_id_t( itemID );
  84. bot->client->pers.selected_item = desiredItemID;
  85. ValidateSelectedItem( bot );
  86. if ( bot->client->pers.selected_item == IT_NULL ) {
  87. return;
  88. }
  89. if ( bot->client->pers.selected_item != desiredItemID ) {
  90. return;
  91. } // the itemID changed on us - don't use it!
  92. gitem_t * item = &itemlist[ bot->client->pers.selected_item ];
  93. bot->client->pers.selected_item = IT_NULL;
  94. if ( item->use == nullptr ) {
  95. return;
  96. }
  97. bot->client->no_weapon_chains = true;
  98. item->use( bot, item );
  99. }
  100. /*
  101. ================
  102. Bot_GetItemID
  103. ================
  104. */
  105. int32_t Bot_GetItemID( const char * classname ) {
  106. if ( classname == nullptr || classname[ 0 ] == '\0' ) {
  107. return Item_Invalid;
  108. }
  109. if ( Q_strcasecmp( classname, "none" ) == 0 ) {
  110. return Item_Null;
  111. }
  112. for ( int i = 0; i < IT_TOTAL; ++i ) {
  113. const gitem_t * item = itemlist + i;
  114. if ( item->classname == nullptr || item->classname[ 0 ] == '\0' ) {
  115. continue;
  116. }
  117. if ( Q_strcasecmp( item->classname, classname ) == 0 ) {
  118. return item->id;
  119. }
  120. }
  121. return Item_Invalid;
  122. }
  123. /*
  124. ================
  125. Edict_ForceLookAtPoint
  126. ================
  127. */
  128. void Edict_ForceLookAtPoint( edict_t * edict, gvec3_cref_t point ) {
  129. vec3_t viewOrigin = edict->s.origin;
  130. if ( edict->client != nullptr ) {
  131. viewOrigin += edict->client->ps.viewoffset;
  132. }
  133. const vec3_t ideal = ( point - viewOrigin ).normalized();
  134. vec3_t viewAngles = vectoangles( ideal );
  135. if ( viewAngles.x < -180.0f ) {
  136. viewAngles.x = anglemod( viewAngles.x + 360.0f );
  137. }
  138. if ( edict->client != nullptr ) {
  139. edict->client->ps.pmove.delta_angles = ( viewAngles - edict->client->resp.cmd_angles );
  140. edict->client->ps.viewangles = {};
  141. edict->client->v_angle = {};
  142. edict->s.angles = {};
  143. }
  144. }
  145. /*
  146. ================
  147. Bot_PickedUpItem
  148. Check if the given bot has picked up the given item or not.
  149. ================
  150. */
  151. bool Bot_PickedUpItem( edict_t * bot, edict_t * item ) {
  152. return item->item_picked_up_by[ ( bot->s.number - 1 ) ];
  153. }