Advertisement
ColinStroble

Untitled

Feb 16th, 2019
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.08 KB | None | 0 0
  1. #include "autowall.h"
  2. #include "..\..\csgo sdk\IPhysics.h"
  3. #include "..\..\csgo sdk\ClientClass.h"
  4. #include "..\..\csgo sdk\ICvar.h"
  5. #include "..\..\Settings.h"
  6.  
  7. typedef CGameTrace trace_t;
  8.  
  9. inline bool CGameTrace::DidHitWorld() const
  10. {
  11. return hit_entity->EntIndex() == 0;
  12. }
  13. inline bool CGameTrace::DidHitNonWorldEntity() const
  14. {
  15. return hit_entity != NULL && !DidHitWorld();
  16. }
  17.  
  18. c_autowall* autowall;
  19.  
  20. #define DAMAGE_NO 0
  21. #define DAMAGE_EVENTS_ONLY 1
  22. #define DAMAGE_YES 2
  23. #define DAMAGE_AIM 3
  24. #define CHAR_TEX_ANTLION 'A'
  25. #define CHAR_TEX_BLOODYFLESH 'B'
  26. #define CHAR_TEX_CONCRETE 'C'
  27. #define CHAR_TEX_DIRT 'D'
  28. #define CHAR_TEX_EGGSHELL 'E' ///< the egg sacs in the tunnels in ep2.
  29. #define CHAR_TEX_FLESH 'F'
  30. #define CHAR_TEX_GRATE 'G'
  31. #define CHAR_TEX_ALIENFLESH 'H'
  32. #define CHAR_TEX_CLIP 'I'
  33. #define CHAR_TEX_PLASTIC 'L'
  34. #define CHAR_TEX_METAL 'M'
  35. #define CHAR_TEX_SAND 'N'
  36. #define CHAR_TEX_FOLIAGE 'O'
  37. #define CHAR_TEX_COMPUTER 'P'
  38. #define CHAR_TEX_SLOSH 'S'
  39. #define CHAR_TEX_TILE 'T'
  40. #define CHAR_TEX_CARDBOARD 'U'
  41. #define CHAR_TEX_VENT 'V'
  42. #define CHAR_TEX_WOOD 'W'
  43. #define CHAR_TEX_GLASS 'Y'
  44. #define CHAR_TEX_WARPSHIELD 'Z' ///< weird-looking jello effect for advisor shield.
  45.  
  46. void ScaleDamage_1(int hitgroup, C_BaseEntity* enemy, float weapon_armor_ratio, float& current_damage)
  47. {
  48. int armor = enemy->GetArmor();
  49. float ratio;
  50.  
  51. switch (hitgroup)
  52. {
  53. case HITGROUP_HEAD:
  54. current_damage *= 4.f;
  55. break;
  56. case HITGROUP_STOMACH:
  57. current_damage *= 1.25f;
  58. break;
  59. case HITGROUP_LEFTLEG:
  60. case HITGROUP_RIGHTLEG:
  61. current_damage *= 0.75f;
  62. break;
  63. }
  64.  
  65. if (armor > 0)
  66. {
  67. switch (hitgroup)
  68. {
  69. case HITGROUP_HEAD:
  70. if (enemy->HasHelmet())
  71. {
  72. ratio = (weapon_armor_ratio * 0.5) * current_damage;
  73. if (((current_damage - ratio) * 0.5) > armor)
  74. ratio = current_damage - (armor * 2.0);
  75. current_damage = ratio;
  76. }
  77. break;
  78. case HITGROUP_GENERIC:
  79. case HITGROUP_CHEST:
  80. case HITGROUP_STOMACH:
  81. case HITGROUP_LEFTARM:
  82. case HITGROUP_RIGHTARM:
  83. ratio = (weapon_armor_ratio * 0.5) * current_damage;
  84. if (((current_damage - ratio) * 0.5) > armor)
  85. ratio = current_damage - (armor * 2.0);
  86. current_damage = ratio;
  87. break;
  88. }
  89. }
  90. }
  91.  
  92. void c_autowall::TraceLine(Vector& absStart, Vector& absEnd, unsigned int mask, IClientEntity* ignore, CGameTrace* ptr)
  93. {
  94. Ray_t ray;
  95. ray.Init(absStart, absEnd);
  96. CTraceFilter filter;
  97. filter.pSkip = ignore;
  98.  
  99. g_pEngineTrace->TraceRay(ray, mask, &filter, ptr);
  100. }
  101.  
  102. void c_autowall::ClipTraceToPlayers(const Vector& absStart, const Vector absEnd, unsigned int mask, ITraceFilter* filter, CGameTrace* tr)
  103. {
  104.  
  105. C_BaseEntity *pLocal = g_pEntityList->GetClientEntity(g_pEngine->GetLocalPlayer());
  106. C_BaseCombatWeapon* weapon = (C_BaseCombatWeapon*)pLocal->GetActiveWeapon();
  107.  
  108. static DWORD dwAddress = Utils::FindSignature("client_panorama.dll", "53 8B DC 83 EC 08 83 E4 F0 83 C4 04 55 8B 6B 04 89 6C 24 04 8B EC 81 EC ? ? ? ? 8B 43 10");
  109.  
  110. if (!dwAddress)
  111. return;
  112.  
  113. _asm
  114. {
  115. MOV EAX, filter
  116. LEA ECX, tr
  117. PUSH ECX
  118. PUSH EAX
  119. PUSH mask
  120. LEA EDX, absEnd
  121. LEA ECX, absStart
  122. CALL dwAddress
  123. ADD ESP, 0xC
  124. }
  125. }
  126.  
  127. ////////////////////////////////////// Legacy Functions //////////////////////////////////////
  128. void c_autowall::GetBulletTypeParameters(float& maxRange, float& maxDistance, char* bulletType, bool sv_penetration_type)
  129. {
  130. if (sv_penetration_type)
  131. {
  132. maxRange = 35.0;
  133. maxDistance = 3000.0;
  134. }
  135. else
  136. {
  137. //Play tribune to framerate. Thanks, stringcompare
  138. //Regardless I doubt anyone will use the old penetration system anyway; so it won't matter much.
  139. if (!strcmp(bulletType, ("BULLET_PLAYER_338MAG")))
  140. {
  141. maxRange = 45.0;
  142. maxDistance = 8000.0;
  143. }
  144. if (!strcmp(bulletType, ("BULLET_PLAYER_762MM")))
  145. {
  146. maxRange = 39.0;
  147. maxDistance = 5000.0;
  148. }
  149. if (!strcmp(bulletType, ("BULLET_PLAYER_556MM")) || !strcmp(bulletType, ("BULLET_PLAYER_556MM_SMALL")) || !strcmp(bulletType, ("BULLET_PLAYER_556MM_BOX")))
  150. {
  151. maxRange = 35.0;
  152. maxDistance = 4000.0;
  153. }
  154. if (!strcmp(bulletType, ("BULLET_PLAYER_57MM")))
  155. {
  156. maxRange = 30.0;
  157. maxDistance = 2000.0;
  158. }
  159. if (!strcmp(bulletType, ("BULLET_PLAYER_50AE")))
  160. {
  161. maxRange = 30.0;
  162. maxDistance = 1000.0;
  163. }
  164. if (!strcmp(bulletType, ("BULLET_PLAYER_357SIG")) || !strcmp(bulletType, ("BULLET_PLAYER_357SIG_SMALL")) || !strcmp(bulletType, ("BULLET_PLAYER_357SIG_P250")) || !strcmp(bulletType, ("BULLET_PLAYER_357SIG_MIN")))
  165. {
  166. maxRange = 25.0;
  167. maxDistance = 800.0;
  168. }
  169. if (!strcmp(bulletType, ("BULLET_PLAYER_9MM")))
  170. {
  171. maxRange = 21.0;
  172. maxDistance = 800.0;
  173. }
  174. if (!strcmp(bulletType, ("BULLET_PLAYER_45ACP")))
  175. {
  176. maxRange = 15.0;
  177. maxDistance = 500.0;
  178. }
  179. if (!strcmp(bulletType, ("BULLET_PLAYER_BUCKSHOT")))
  180. {
  181. maxRange = 0.0;
  182. maxDistance = 0.0;
  183. }
  184. }
  185. }
  186.  
  187. ////////////////////////////////////// Misc Functions //////////////////////////////////////
  188. bool c_autowall::BreakableEntity(IClientEntity* entity)
  189. {
  190.  
  191. ClientClass* pClass = (ClientClass*)entity->GetClientClass();
  192.  
  193. if (!pClass)
  194. return false;
  195.  
  196. if (pClass == nullptr)
  197. return false;
  198.  
  199. return pClass->ClassID == EClassIds::CBreakableProp || pClass->ClassID == EClassIds::CBreakableSurface;
  200.  
  201. }
  202.  
  203. void c_autowall::ScaleDamage(CGameTrace &enterTrace, WeaponInfo_t *weaponData, float& currentDamage)
  204. {
  205.  
  206. C_BaseEntity *pLocal = g_pEntityList->GetClientEntity(g_pEngine->GetLocalPlayer());
  207. C_BaseCombatWeapon* weapon = (C_BaseCombatWeapon*)pLocal->GetActiveWeapon();
  208. bool hasHeavyArmor = false;
  209. int armorValue = ((C_BaseEntity*)enterTrace.hit_entity)->GetArmor();
  210. int hitGroup = enterTrace.hitgroup;
  211.  
  212. if (!pLocal)
  213. return;
  214.  
  215. auto IsArmored = [&enterTrace]()->bool
  216. {
  217. C_BaseEntity* targetEntity = (C_BaseEntity*)enterTrace.hit_entity;
  218. switch (enterTrace.hitgroup)
  219. {
  220. case HITGROUP_HEAD:
  221. return !!(C_BaseEntity*)targetEntity->HasHelmet();
  222. case HITGROUP_GENERIC:
  223. case HITGROUP_CHEST:
  224. case HITGROUP_STOMACH:
  225. case HITGROUP_LEFTARM:
  226. case HITGROUP_RIGHTARM:
  227. return true;
  228. default:
  229. return false;
  230. }
  231. };
  232.  
  233. switch (hitGroup)
  234. {
  235. case HITGROUP_HEAD:
  236. currentDamage *= 2.f;
  237. break;
  238. case HITGROUP_STOMACH:
  239. currentDamage *= 1.25f;
  240. break;
  241. case HITGROUP_LEFTLEG:
  242. case HITGROUP_RIGHTLEG:
  243. currentDamage *= 0.75f;
  244. break;
  245. default:
  246. break;
  247. }
  248.  
  249. if (armorValue > 0 && IsArmored())
  250. {
  251. float bonusValue = 1.f, armorBonusRatio = 0.5f, armorRatio = weaponData->flArmorRatio / 2.f;
  252.  
  253. if (hasHeavyArmor)
  254. {
  255. armorBonusRatio = 0.33f;
  256. armorRatio *= 0.5f;
  257. bonusValue = 0.33f;
  258. }
  259.  
  260. auto NewDamage = currentDamage * armorRatio;
  261.  
  262. if (((currentDamage - (currentDamage * armorRatio)) * (bonusValue * armorBonusRatio)) > armorValue)
  263. NewDamage = currentDamage - (armorValue / armorBonusRatio);
  264.  
  265. currentDamage = NewDamage;
  266. }
  267. }
  268.  
  269. ////////////////////////////////////// Main Autowall Functions //////////////////////////////////////
  270. bool c_autowall::trace_to_exit(CGameTrace& enterTrace, CGameTrace& exitTrace, Vector startPosition, Vector direction)
  271. {
  272. Vector start, end;
  273. float maxDistance = 90.f, rayExtension = 4.f, currentDistance = 0;
  274. int firstContents = 0;
  275.  
  276. while (currentDistance <= maxDistance)
  277. {
  278. currentDistance += rayExtension;
  279.  
  280. start = startPosition + direction * currentDistance;
  281.  
  282. if (!firstContents)
  283. firstContents = g_pEngineTrace->GetPointContents(start, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr);
  284.  
  285. int pointContents = g_pEngineTrace->GetPointContents(start, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr);
  286.  
  287. if (!(pointContents & MASK_SHOT_HULL) || pointContents & CONTENTS_HITBOX && pointContents != firstContents)
  288. {
  289. end = start - (direction * rayExtension);
  290.  
  291. TraceLine(start, end, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr, &exitTrace);
  292.  
  293. if (exitTrace.startsolid && exitTrace.surface.flags & SURF_HITBOX)
  294. {
  295. TraceLine(start, startPosition, MASK_SHOT_HULL, (IClientEntity*)exitTrace.hit_entity, &exitTrace);
  296.  
  297. if (exitTrace.DidHit() && !exitTrace.startsolid)
  298. {
  299. start = exitTrace.endpos;
  300. return true;
  301. }
  302. continue;
  303. }
  304.  
  305. if (exitTrace.DidHit() && !exitTrace.startsolid)
  306. {
  307.  
  308. if (BreakableEntity((IClientEntity*)enterTrace.hit_entity) && BreakableEntity((IClientEntity*)exitTrace.hit_entity))
  309. return true;
  310.  
  311. if (enterTrace.surface.flags & SURF_NODRAW || !(exitTrace.surface.flags & SURF_NODRAW) && (exitTrace.plane.normal.Dot(direction) <= 1.f))
  312. {
  313. float multAmount = exitTrace.fraction * 4.f;
  314. start -= direction * multAmount;
  315. return true;
  316. }
  317.  
  318. continue;
  319. }
  320.  
  321. if (!exitTrace.DidHit() || exitTrace.startsolid)
  322. {
  323. if (enterTrace.DidHitNonWorldEntity() && BreakableEntity((IClientEntity*)enterTrace.hit_entity))
  324. {
  325. exitTrace = enterTrace;
  326. exitTrace.endpos = start + direction;
  327. return true;
  328. }
  329.  
  330. continue;
  331. }
  332. }
  333. }
  334. return false;
  335. }
  336.  
  337. bool c_autowall::HandleBulletPenetration(WeaponInfo_t* weaponData, CGameTrace& enterTrace, Vector& eyePosition, Vector direction, int& possibleHitsRemaining, float& currentDamage, float penetrationPower, bool sv_penetration_type, float ff_damage_reduction_bullets, float ff_damage_bullet_penetration)
  338. {
  339. //Because there's been issues regarding this- putting this here.
  340. if (&currentDamage == nullptr)
  341. {
  342. return false;
  343. }
  344.  
  345. C_BaseEntity* local = (C_BaseEntity*)g_pEntityList->GetClientEntity(g_pEngine->GetLocalPlayer());
  346.  
  347. auto data = FireBulletData(local->GetEyePosition());
  348. data.filter = CTraceFilter();
  349. data.filter.pSkip = local;
  350. CGameTrace exitTrace;
  351. C_BaseEntity* pEnemy = (C_BaseEntity*)enterTrace.hit_entity;
  352.  
  353. surfacedata_t *enterSurfaceData = g_PhysSurface->GetSurfaceData(enterTrace.surface.surfaceProps);
  354. int enterMaterial = enterSurfaceData->game.material;
  355.  
  356. float enterSurfPenetrationModifier = enterSurfaceData->game.flPenetrationModifier;
  357. float enterDamageModifier = enterSurfaceData->game.flDamageModifier;
  358. float thickness, modifier, lostDamage, finalDamageModifier, combinedPenetrationModifier;
  359. bool isSolidSurf = ((enterTrace.contents >> 3) & CONTENTS_SOLID);
  360. bool isLightSurf = ((enterTrace.surface.flags >> 7) & SURF_LIGHT);
  361.  
  362. if (possibleHitsRemaining <= 0
  363. || (enterTrace.surface.name == (const char*)0x2227c261 && exitTrace.surface.name == (const char*)0x2227c868)
  364. || (!possibleHitsRemaining && !isLightSurf && !isSolidSurf && enterMaterial != CHAR_TEX_GRATE && enterMaterial != CHAR_TEX_GLASS)
  365. || weaponData->flPenetration <= 0.f
  366. || !trace_to_exit(enterTrace, exitTrace, enterTrace.endpos, direction)
  367. && !(g_pEngineTrace->GetPointContents(enterTrace.endpos, MASK_SHOT_HULL, nullptr) & MASK_SHOT_HULL))
  368. {
  369. return false;
  370. }
  371.  
  372. surfacedata_t *exitSurfaceData = g_PhysSurface->GetSurfaceData(exitTrace.surface.surfaceProps);
  373. int exitMaterial = exitSurfaceData->game.material;
  374. float exitSurfPenetrationModifier = exitSurfaceData->game.flPenetrationModifier;
  375. float exitDamageModifier = exitSurfaceData->game.flDamageModifier;
  376.  
  377. if (sv_penetration_type)
  378. {
  379. if (enterMaterial == CHAR_TEX_GRATE || enterMaterial == CHAR_TEX_GLASS)
  380. {
  381. combinedPenetrationModifier = 3.f;
  382. finalDamageModifier = 0.05f;
  383. }
  384. else if (isSolidSurf || isLightSurf)
  385. {
  386. combinedPenetrationModifier = 1.f;
  387. finalDamageModifier = 0.16f;
  388. }
  389. else if (enterMaterial == CHAR_TEX_FLESH && (local->GetTeam() == pEnemy->GetTeam() && ff_damage_reduction_bullets == 0.f))
  390. {
  391. if (ff_damage_bullet_penetration == 0.f)
  392. {
  393. return false;
  394. }
  395. combinedPenetrationModifier = ff_damage_bullet_penetration;
  396. finalDamageModifier = 0.16f;
  397. }
  398. else
  399. {
  400. combinedPenetrationModifier = (enterSurfPenetrationModifier + exitSurfPenetrationModifier) / 2.f;
  401. finalDamageModifier = 0.16f;
  402. }
  403.  
  404. if (enterMaterial == exitMaterial)
  405. {
  406. if (exitMaterial == CHAR_TEX_CARDBOARD || exitMaterial == CHAR_TEX_WOOD)
  407. combinedPenetrationModifier = 3.f;
  408. else if (exitMaterial == CHAR_TEX_PLASTIC)
  409. combinedPenetrationModifier = 2.f;
  410. }
  411.  
  412. thickness = (exitTrace.endpos - enterTrace.endpos).LengthSqr();
  413. modifier = fmaxf(1.f / combinedPenetrationModifier, 0.f);
  414.  
  415. lostDamage = fmaxf(
  416. ((modifier * thickness) / 24.f)
  417. + ((currentDamage * finalDamageModifier)
  418. + (fmaxf(3.75f / penetrationPower, 0.f) * 3.f * modifier)), 0.f);
  419.  
  420. if (lostDamage > currentDamage)
  421. {
  422. return false;
  423. }
  424.  
  425. if (lostDamage > 0.f)
  426. currentDamage -= lostDamage;
  427.  
  428. if (currentDamage < 1.f)
  429. {
  430. return false;
  431. }
  432.  
  433. eyePosition = exitTrace.endpos;
  434. --possibleHitsRemaining;
  435.  
  436. return true;
  437. }
  438. else
  439. {
  440. combinedPenetrationModifier = 1.f;
  441.  
  442. if (isSolidSurf || isLightSurf)
  443. finalDamageModifier = 0.99f;
  444. else
  445. {
  446. finalDamageModifier = fminf(enterDamageModifier, exitDamageModifier);
  447. combinedPenetrationModifier = fminf(enterSurfPenetrationModifier, exitSurfPenetrationModifier);
  448. }
  449.  
  450. if (enterMaterial == exitMaterial && (exitMaterial == CHAR_TEX_METAL || exitMaterial == CHAR_TEX_WOOD))
  451. combinedPenetrationModifier += combinedPenetrationModifier;
  452.  
  453. thickness = (exitTrace.endpos - enterTrace.endpos).LengthSqr();
  454.  
  455. if (sqrt(thickness) <= combinedPenetrationModifier * penetrationPower)
  456. {
  457. currentDamage *= finalDamageModifier;
  458. eyePosition = exitTrace.endpos;
  459. --possibleHitsRemaining;
  460. return true;
  461. }
  462. return false;
  463. }
  464. }
  465.  
  466. bool c_autowall::FireBullet(C_BaseCombatWeapon* pWeapon, Vector& direction, float& currentDamage)
  467. {
  468. if (!pWeapon)
  469. return false;
  470.  
  471. C_BaseEntity* local = (C_BaseEntity*)g_pEntityList->GetClientEntity(g_pEngine->GetLocalPlayer());
  472.  
  473. auto data = FireBulletData(local->GetEyePosition());
  474.  
  475. data.filter = CTraceFilter();
  476. data.filter.pSkip = local;
  477.  
  478. bool sv_penetration_type;
  479.  
  480. float currentDistance = 0.f, penetrationPower, penetrationDistance, maxRange, ff_damage_reduction_bullets, ff_damage_bullet_penetration, rayExtension = 40.f;
  481. Vector eyePosition = local->GetEyePosition();
  482.  
  483. static ConVar* penetrationSystem = g_pCVar->FindVar(("sv_penetration_type"));
  484. static ConVar* damageReductionBullets = g_pCVar->FindVar(("ff_damage_reduction_bullets"));
  485. static ConVar* damageBulletPenetration = g_pCVar->FindVar(("ff_damage_bullet_penetration"));
  486.  
  487. sv_penetration_type = penetrationSystem->GetBool();
  488. ff_damage_reduction_bullets = damageReductionBullets->GetFloat();
  489. ff_damage_bullet_penetration = damageBulletPenetration->GetFloat();
  490.  
  491. WeaponInfo_t* weaponData = pWeapon->GetCSWpnData();
  492. CGameTrace enterTrace;
  493. CTraceFilter filter;
  494.  
  495. filter.pSkip = local;
  496.  
  497. if (!weaponData)
  498. return false;
  499.  
  500. maxRange = weaponData->flRange;
  501.  
  502. GetBulletTypeParameters(penetrationPower, penetrationDistance, weaponData->szBulletType, sv_penetration_type);
  503.  
  504. if (sv_penetration_type)
  505. penetrationPower = weaponData->flPenetration;
  506.  
  507. int possibleHitsRemaining = 4;
  508.  
  509. currentDamage = weaponData->iDamage;
  510.  
  511. while (possibleHitsRemaining > 0 && currentDamage >= 1.f)
  512. {
  513. maxRange -= currentDistance;
  514.  
  515. Vector end = eyePosition + direction * maxRange;
  516.  
  517. TraceLine(eyePosition, end, MASK_SHOT_HULL | CONTENTS_HITBOX, (IClientEntity*)local, &enterTrace);
  518. ClipTraceToPlayers(eyePosition, end + direction * rayExtension, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &enterTrace); // | CONTENTS_HITBOX
  519.  
  520. surfacedata_t *enterSurfaceData = g_PhysSurface->GetSurfaceData(enterTrace.surface.surfaceProps);
  521.  
  522. float enterSurfPenetrationModifier = enterSurfaceData->game.flPenetrationModifier;
  523.  
  524. int enterMaterial = enterSurfaceData->game.material;
  525.  
  526. if (enterTrace.fraction == 1.f)
  527. break;
  528.  
  529. currentDistance += enterTrace.fraction * maxRange;
  530.  
  531. currentDamage *= pow(weaponData->flRangeModifier, (currentDistance / 500.f));
  532.  
  533. if (currentDistance > penetrationDistance && weaponData->flPenetration > 0.f || enterSurfPenetrationModifier < 0.1f)
  534. break;
  535.  
  536. bool canDoDamage = (enterTrace.hitgroup != HITGROUP_GEAR && enterTrace.hitgroup != HITGROUP_GENERIC);
  537. bool isEnemy = (((C_BaseEntity*)local)->GetTeam() != ((C_BaseEntity*)enterTrace.hit_entity)->GetTeam());
  538.  
  539. if ((canDoDamage && isEnemy))
  540. {
  541. ScaleDamage(enterTrace, weaponData, currentDamage);
  542. return true;
  543. }
  544.  
  545. if (!HandleBulletPenetration(weaponData, enterTrace, eyePosition, direction, possibleHitsRemaining, currentDamage, penetrationPower, sv_penetration_type, ff_damage_reduction_bullets, ff_damage_bullet_penetration))
  546. break;
  547. }
  548. return false;
  549. }
  550.  
  551. ////////////////////////////////////// Usage Calls //////////////////////////////////////
  552. float c_autowall::CanHit(Vector &point)
  553. {
  554. C_BaseEntity* local = (C_BaseEntity*)g_pEntityList->GetClientEntity(g_pEngine->GetLocalPlayer());
  555.  
  556. if (!local || !local->IsAlive())
  557. return -1;
  558.  
  559. auto data = FireBulletData(local->GetEyePosition());
  560. data.filter = CTraceFilter();
  561. data.filter.pSkip = local;
  562. Vector angles;
  563. Vector direction;
  564. Vector tmp = point - local->GetEyePosition();
  565. float currentDamage = 0;
  566.  
  567. MATH::VectorAngles234(tmp, angles);
  568. MATH::AngleVectors234(angles, &direction);
  569. direction.NormalizeInPlace();
  570.  
  571. if (FireBullet(local->GetActiveWeapon(), direction, currentDamage))
  572. return currentDamage;
  573. return -1;
  574. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement