simpleHitboxComponent.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "simpleHitboxComponent.h"
  2. IMPLEMENT_CO_NETOBJECT_V1(SimpleHitboxComponent);
  3. SimpleHitboxComponent::SimpleHitboxComponent() :
  4. // location of head, torso, legs
  5. mBoxHeadPercentage(0.85f),
  6. mBoxTorsoPercentage(0.55f),
  7. mBoxLeftPercentage(0),
  8. mBoxRightPercentage(1),
  9. mBoxBackPercentage(0),
  10. mBoxFrontPercentage(1),
  11. mIsProne(false)
  12. {
  13. }
  14. SimpleHitboxComponent::~SimpleHitboxComponent()
  15. {
  16. }
  17. void SimpleHitboxComponent::initPersistFields()
  18. {
  19. addGroup("Hitbox");
  20. addField("headPercentage", TypeF32, Offset(mBoxHeadPercentage, SimpleHitboxComponent), "");
  21. addField("torsoPercentage", TypeF32, Offset(mBoxTorsoPercentage, SimpleHitboxComponent), "");
  22. addField("leftPercentage", TypeF32, Offset(mBoxLeftPercentage, SimpleHitboxComponent), "");
  23. addField("rightPercentage", TypeF32, Offset(mBoxRightPercentage, SimpleHitboxComponent), "");
  24. addField("backPercentage", TypeF32, Offset(mBoxBackPercentage, SimpleHitboxComponent), "");
  25. addField("frontPercentage", TypeF32, Offset(mBoxFrontPercentage, SimpleHitboxComponent), "");
  26. addField("isProne", TypeF32, Offset(mIsProne, SimpleHitboxComponent), "");
  27. endGroup("Hitbox");
  28. Parent::initPersistFields();
  29. }
  30. void SimpleHitboxComponent::onComponentAdd()
  31. {
  32. Parent::onComponentAdd();
  33. }
  34. void SimpleHitboxComponent::componentAddedToOwner(Component *comp)
  35. {
  36. Parent::componentAddedToOwner(comp);
  37. }
  38. void SimpleHitboxComponent::componentRemovedFromOwner(Component *comp)
  39. {
  40. Parent::componentRemovedFromOwner(comp);
  41. }
  42. void SimpleHitboxComponent::processTick()
  43. {
  44. Parent::processTick();
  45. }
  46. void SimpleHitboxComponent::interpolateTick(F32 dt)
  47. {
  48. Parent::interpolateTick(dt);
  49. }
  50. void SimpleHitboxComponent::advanceTime(F32 dt)
  51. {
  52. Parent::advanceTime(dt);
  53. }
  54. void SimpleHitboxComponent::getDamageLocation(const Point3F& in_rPos, const char *&out_rpVert, const char *&out_rpQuad)
  55. {
  56. Point3F newPoint;
  57. mOwner->getWorldToObj().mulP(in_rPos, &newPoint);
  58. Point3F boxSize = mOwner->getObjBox().getExtents();
  59. F32 boxHeight = boxSize.z;
  60. F32 pointHeight = newPoint.z;
  61. if (mIsProne)
  62. pointHeight = newPoint.y; //this assumes we're y-forward
  63. F32 zTorso = mBoxTorsoPercentage;
  64. F32 zHead = mBoxHeadPercentage;
  65. zTorso *= boxHeight;
  66. zHead *= boxHeight;
  67. if (pointHeight <= zTorso)
  68. out_rpVert = "legs";
  69. else if (pointHeight <= zHead)
  70. out_rpVert = "torso";
  71. else
  72. out_rpVert = "head";
  73. if (dStrcmp(out_rpVert, "head") != 0)
  74. {
  75. if (newPoint.y >= 0.0f)
  76. {
  77. if (newPoint.x <= 0.0f)
  78. out_rpQuad = "front_left";
  79. else
  80. out_rpQuad = "front_right";
  81. }
  82. else
  83. {
  84. if (newPoint.x <= 0.0f)
  85. out_rpQuad = "back_left";
  86. else
  87. out_rpQuad = "back_right";
  88. }
  89. }
  90. else
  91. {
  92. F32 backToFront = boxSize.x;
  93. F32 leftToRight = boxSize.y;
  94. F32 backPoint = backToFront * mBoxBackPercentage;
  95. F32 frontPoint = backToFront * mBoxFrontPercentage;
  96. F32 leftPoint = leftToRight * mBoxLeftPercentage;
  97. F32 rightPoint = leftToRight * mBoxRightPercentage;
  98. S32 index = 0;
  99. if (newPoint.y < backPoint)
  100. index += 0;
  101. else if (newPoint.y >= frontPoint)
  102. index += 3;
  103. else
  104. index += 6;
  105. if (newPoint.x < leftPoint)
  106. index += 0;
  107. else if (newPoint.x >= rightPoint)
  108. index += 1;
  109. else
  110. index += 2;
  111. switch (index)
  112. {
  113. case 0: out_rpQuad = "left_back"; break;
  114. case 1: out_rpQuad = "middle_back"; break;
  115. case 2: out_rpQuad = "right_back"; break;
  116. case 3: out_rpQuad = "left_middle"; break;
  117. case 4: out_rpQuad = "middle_middle"; break;
  118. case 5: out_rpQuad = "right_middle"; break;
  119. case 6: out_rpQuad = "left_front"; break;
  120. case 7: out_rpQuad = "middle_front"; break;
  121. case 8: out_rpQuad = "right_front"; break;
  122. default:
  123. AssertFatal(0, "Bad non-tant index");
  124. };
  125. }
  126. }
  127. DefineEngineMethod(SimpleHitboxComponent, getDamageLocation, const char*, (Point3F pos), ,
  128. "@brief Get the named damage location and modifier for a given world position.\n\n"
  129. "the Player object can simulate different hit locations based on a pre-defined set "
  130. "of PlayerData defined percentages. These hit percentages divide up the Player's "
  131. "bounding box into different regions. The diagram below demonstrates how the various "
  132. "PlayerData properties split up the bounding volume:\n\n"
  133. "<img src=\"images/player_damageloc.png\">\n\n"
  134. "While you may pass in any world position and getDamageLocation() will provide a best-fit "
  135. "location, you should be aware that this can produce some interesting results. For example, "
  136. "any position that is above PlayerData::boxHeadPercentage will be considered a 'head' hit, even "
  137. "if the world position is high in the sky. Therefore it may be wise to keep the passed in point "
  138. "to somewhere on the surface of, or within, the Player's bounding volume.\n\n"
  139. "@note This method will not return an accurate location when the player is "
  140. "prone or swimming.\n\n"
  141. "@param pos A world position for which to retrieve a body region on this player.\n"
  142. "@return a string containing two words (space separated strings), where the "
  143. "first is a location and the second is a modifier.\n\n"
  144. "Posible locations:<ul>"
  145. "<li>head</li>"
  146. "<li>torso</li>"
  147. "<li>legs</li></ul>\n"
  148. "Head modifiers:<ul>"
  149. "<li>left_back</li>"
  150. "<li>middle_back</li>"
  151. "<li>right_back</li>"
  152. "<li>left_middle</li>"
  153. "<li>middle_middle</li>"
  154. "<li>right_middle</li>"
  155. "<li>left_front</li>"
  156. "<li>middle_front</li>"
  157. "<li>right_front</li></ul>\n"
  158. "Legs/Torso modifiers:<ul>"
  159. "<li>front_left</li>"
  160. "<li>front_right</li>"
  161. "<li>back_left</li>"
  162. "<li>back_right</li></ul>\n"
  163. "@see PlayerData::boxHeadPercentage\n"
  164. "@see PlayerData::boxHeadFrontPercentage\n"
  165. "@see PlayerData::boxHeadBackPercentage\n"
  166. "@see PlayerData::boxHeadLeftPercentage\n"
  167. "@see PlayerData::boxHeadRightPercentage\n"
  168. "@see PlayerData::boxTorsoPercentage\n"
  169. )
  170. {
  171. const char *buffer1;
  172. const char *buffer2;
  173. object->getDamageLocation(pos, buffer1, buffer2);
  174. static const U32 bufSize = 128;
  175. char *buff = Con::getReturnBuffer(bufSize);
  176. dSprintf(buff, bufSize, "%s %s", buffer1, buffer2);
  177. return buff;
  178. }