AI_AssassinDroid.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // leave this line at the top of all AI_xxxx.cpp files for PCH reasons...
  2. #include "g_headers.h"
  3. //custom anims:
  4. //both_attack1 - running attack
  5. //both_attack2 - crouched attack
  6. //both_attack3 - standing attack
  7. //both_stand1idle1 - idle
  8. //both_crouch2stand1 - uncrouch
  9. //both_death4 - running death
  10. #define ASSASSIN_SHIELD_SIZE 75
  11. #define TURN_ON 0x00000000
  12. #define TURN_OFF 0x00000100
  13. ////////////////////////////////////////////////////////////////////////////////////////
  14. //
  15. ////////////////////////////////////////////////////////////////////////////////////////
  16. bool BubbleShield_IsOn()
  17. {
  18. return (NPC->flags&FL_SHIELDED);
  19. }
  20. ////////////////////////////////////////////////////////////////////////////////////////
  21. //
  22. ////////////////////////////////////////////////////////////////////////////////////////
  23. void BubbleShield_TurnOn()
  24. {
  25. if (!BubbleShield_IsOn())
  26. {
  27. NPC->flags |= FL_SHIELDED;
  28. NPC->client->ps.powerups[PW_GALAK_SHIELD] = Q3_INFINITE;
  29. gi.G2API_SetSurfaceOnOff( &NPC->ghoul2[NPC->playerModel], "force_shield", TURN_ON );
  30. }
  31. }
  32. ////////////////////////////////////////////////////////////////////////////////////////
  33. //
  34. ////////////////////////////////////////////////////////////////////////////////////////
  35. void BubbleShield_TurnOff()
  36. {
  37. if ( BubbleShield_IsOn())
  38. {
  39. NPC->flags &= ~FL_SHIELDED;
  40. NPC->client->ps.powerups[PW_GALAK_SHIELD] = 0;
  41. gi.G2API_SetSurfaceOnOff( &NPC->ghoul2[NPC->playerModel], "force_shield", TURN_OFF );
  42. }
  43. }
  44. ////////////////////////////////////////////////////////////////////////////////////////
  45. // Push A Particular Ent
  46. ////////////////////////////////////////////////////////////////////////////////////////
  47. void BubbleShield_PushEnt(gentity_t* pushed, vec3_t smackDir)
  48. {
  49. G_Damage(pushed, NPC, NPC, smackDir, NPC->currentOrigin, (g_spskill->integer+1)*Q_irand( 5, 10), DAMAGE_NO_KNOCKBACK, MOD_ELECTROCUTE);
  50. G_Throw(pushed, smackDir, 10);
  51. // Make Em Electric
  52. //------------------
  53. pushed->s.powerups |= (1 << PW_SHOCKED);
  54. if (pushed->client)
  55. {
  56. pushed->client->ps.powerups[PW_SHOCKED] = level.time + 1000;
  57. }
  58. }
  59. ////////////////////////////////////////////////////////////////////////////////////////
  60. // Go Through All The Ents Within The Radius Of The Shield And Push Them
  61. ////////////////////////////////////////////////////////////////////////////////////////
  62. void BubbleShield_PushRadiusEnts()
  63. {
  64. int numEnts;
  65. gentity_t* radiusEnts[128];
  66. const float radius = ASSASSIN_SHIELD_SIZE;
  67. vec3_t mins, maxs;
  68. vec3_t smackDir;
  69. float smackDist;
  70. for (int i = 0; i < 3; i++ )
  71. {
  72. mins[i] = NPC->currentOrigin[i] - radius;
  73. maxs[i] = NPC->currentOrigin[i] + radius;
  74. }
  75. numEnts = gi.EntitiesInBox(mins, maxs, radiusEnts, 128);
  76. for (int entIndex=0; entIndex<numEnts; entIndex++)
  77. {
  78. // Only Clients
  79. //--------------
  80. if (!radiusEnts[entIndex] || !radiusEnts[entIndex]->client)
  81. {
  82. continue;
  83. }
  84. // Don't Push Away Other Assassin Droids
  85. //---------------------------------------
  86. if (radiusEnts[entIndex]->client->NPC_class==NPC->client->NPC_class)
  87. {
  88. continue;
  89. }
  90. // Should Have Already Pushed The Enemy If He Touched Us
  91. //-------------------------------------------------------
  92. if (NPC->enemy && NPCInfo->touchedByPlayer==NPC->enemy && radiusEnts[entIndex]==NPC->enemy)
  93. {
  94. continue;
  95. }
  96. // Do The Vector Distance Test
  97. //-----------------------------
  98. VectorSubtract(radiusEnts[entIndex]->currentOrigin, NPC->currentOrigin, smackDir);
  99. smackDist = VectorNormalize(smackDir);
  100. if (smackDist<radius)
  101. {
  102. BubbleShield_PushEnt(radiusEnts[entIndex], smackDir);
  103. }
  104. }
  105. }
  106. ////////////////////////////////////////////////////////////////////////////////////////
  107. //
  108. ////////////////////////////////////////////////////////////////////////////////////////
  109. void BubbleShield_Update()
  110. {
  111. // Shields Go When You Die
  112. //-------------------------
  113. if (NPC->health<=0)
  114. {
  115. if (BubbleShield_IsOn())
  116. {
  117. BubbleShield_TurnOff();
  118. }
  119. return;
  120. }
  121. // Recharge Shields
  122. //------------------
  123. NPC->client->ps.stats[STAT_ARMOR] += 1;
  124. if (NPC->client->ps.stats[STAT_ARMOR]>250)
  125. {
  126. NPC->client->ps.stats[STAT_ARMOR] = 250;
  127. }
  128. // If We Have Enough Armor And Are Not Shooting Right Now, Kick The Shield On
  129. //----------------------------------------------------------------------------
  130. if (NPC->client->ps.stats[STAT_ARMOR]>100 && TIMER_Done(NPC, "ShieldsDown"))
  131. {
  132. // Check On Timers To Raise And Lower Shields
  133. //--------------------------------------------
  134. if ((level.time - NPCInfo->enemyLastSeenTime)<1000 && TIMER_Done(NPC, "ShieldsUp"))
  135. {
  136. TIMER_Set(NPC, "ShieldsDown", 2000); // Drop Shields
  137. TIMER_Set(NPC, "ShieldsUp", Q_irand(4000, 5000)); // Then Bring Them Back Up For At Least 3 sec
  138. }
  139. BubbleShield_TurnOn();
  140. if (BubbleShield_IsOn())
  141. {
  142. // Update Our Shader Value
  143. //-------------------------
  144. NPC->client->renderInfo.customRGBA[0] =
  145. NPC->client->renderInfo.customRGBA[1] =
  146. NPC->client->renderInfo.customRGBA[2] =
  147. NPC->client->renderInfo.customRGBA[3] = (NPC->client->ps.stats[STAT_ARMOR] - 100);
  148. // If Touched By An Enemy, ALWAYS Shove Them
  149. //-------------------------------------------
  150. if (NPC->enemy && NPCInfo->touchedByPlayer==NPC->enemy)
  151. {
  152. vec3_t dir;
  153. VectorSubtract(NPC->enemy->currentOrigin, NPC->currentOrigin, dir);
  154. VectorNormalize(dir);
  155. BubbleShield_PushEnt(NPC->enemy, dir);
  156. }
  157. // Push Anybody Else Near
  158. //------------------------
  159. BubbleShield_PushRadiusEnts();
  160. }
  161. }
  162. // Shields Gone
  163. //--------------
  164. else
  165. {
  166. BubbleShield_TurnOff();
  167. }
  168. }