#include "simpleHitboxComponent.h"
IMPLEMENT_CO_NETOBJECT_V1(SimpleHitboxComponent);
SimpleHitboxComponent::SimpleHitboxComponent() :
// location of head, torso, legs
mBoxHeadPercentage(0.85f),
mBoxTorsoPercentage(0.55f),
mBoxLeftPercentage(0),
mBoxRightPercentage(1),
mBoxBackPercentage(0),
mBoxFrontPercentage(1),
mIsProne(false)
{
}
SimpleHitboxComponent::~SimpleHitboxComponent()
{
}
void SimpleHitboxComponent::initPersistFields()
{
addGroup("Hitbox");
addField("headPercentage", TypeF32, Offset(mBoxHeadPercentage, SimpleHitboxComponent), "");
addField("torsoPercentage", TypeF32, Offset(mBoxTorsoPercentage, SimpleHitboxComponent), "");
addField("leftPercentage", TypeF32, Offset(mBoxLeftPercentage, SimpleHitboxComponent), "");
addField("rightPercentage", TypeF32, Offset(mBoxRightPercentage, SimpleHitboxComponent), "");
addField("backPercentage", TypeF32, Offset(mBoxBackPercentage, SimpleHitboxComponent), "");
addField("frontPercentage", TypeF32, Offset(mBoxFrontPercentage, SimpleHitboxComponent), "");
addField("isProne", TypeF32, Offset(mIsProne, SimpleHitboxComponent), "");
endGroup("Hitbox");
Parent::initPersistFields();
}
void SimpleHitboxComponent::onComponentAdd()
{
Parent::onComponentAdd();
}
void SimpleHitboxComponent::componentAddedToOwner(Component *comp)
{
Parent::componentAddedToOwner(comp);
}
void SimpleHitboxComponent::componentRemovedFromOwner(Component *comp)
{
Parent::componentRemovedFromOwner(comp);
}
void SimpleHitboxComponent::processTick()
{
Parent::processTick();
}
void SimpleHitboxComponent::interpolateTick(F32 dt)
{
Parent::interpolateTick(dt);
}
void SimpleHitboxComponent::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
}
void SimpleHitboxComponent::getDamageLocation(const Point3F& in_rPos, const char *&out_rpVert, const char *&out_rpQuad)
{
Point3F newPoint;
mOwner->getWorldToObj().mulP(in_rPos, &newPoint);
Point3F boxSize = mOwner->getObjBox().getExtents();
F32 boxHeight = boxSize.z;
F32 pointHeight = newPoint.z;
if (mIsProne)
pointHeight = newPoint.y; //this assumes we're y-forward
F32 zTorso = mBoxTorsoPercentage;
F32 zHead = mBoxHeadPercentage;
zTorso *= boxHeight;
zHead *= boxHeight;
if (pointHeight <= zTorso)
out_rpVert = "legs";
else if (pointHeight <= zHead)
out_rpVert = "torso";
else
out_rpVert = "head";
if (dStrcmp(out_rpVert, "head") != 0)
{
if (newPoint.y >= 0.0f)
{
if (newPoint.x <= 0.0f)
out_rpQuad = "front_left";
else
out_rpQuad = "front_right";
}
else
{
if (newPoint.x <= 0.0f)
out_rpQuad = "back_left";
else
out_rpQuad = "back_right";
}
}
else
{
F32 backToFront = boxSize.x;
F32 leftToRight = boxSize.y;
F32 backPoint = backToFront * mBoxBackPercentage;
F32 frontPoint = backToFront * mBoxFrontPercentage;
F32 leftPoint = leftToRight * mBoxLeftPercentage;
F32 rightPoint = leftToRight * mBoxRightPercentage;
S32 index = 0;
if (newPoint.y < backPoint)
index += 0;
else if (newPoint.y >= frontPoint)
index += 3;
else
index += 6;
if (newPoint.x < leftPoint)
index += 0;
else if (newPoint.x >= rightPoint)
index += 1;
else
index += 2;
switch (index)
{
case 0: out_rpQuad = "left_back"; break;
case 1: out_rpQuad = "middle_back"; break;
case 2: out_rpQuad = "right_back"; break;
case 3: out_rpQuad = "left_middle"; break;
case 4: out_rpQuad = "middle_middle"; break;
case 5: out_rpQuad = "right_middle"; break;
case 6: out_rpQuad = "left_front"; break;
case 7: out_rpQuad = "middle_front"; break;
case 8: out_rpQuad = "right_front"; break;
default:
AssertFatal(0, "Bad non-tant index");
};
}
}
DefineEngineMethod(SimpleHitboxComponent, getDamageLocation, const char*, (Point3F pos), ,
"@brief Get the named damage location and modifier for a given world position.\n\n"
"the Player object can simulate different hit locations based on a pre-defined set "
"of PlayerData defined percentages. These hit percentages divide up the Player's "
"bounding box into different regions. The diagram below demonstrates how the various "
"PlayerData properties split up the bounding volume:\n\n"
"
\n\n"
"While you may pass in any world position and getDamageLocation() will provide a best-fit "
"location, you should be aware that this can produce some interesting results. For example, "
"any position that is above PlayerData::boxHeadPercentage will be considered a 'head' hit, even "
"if the world position is high in the sky. Therefore it may be wise to keep the passed in point "
"to somewhere on the surface of, or within, the Player's bounding volume.\n\n"
"@note This method will not return an accurate location when the player is "
"prone or swimming.\n\n"
"@param pos A world position for which to retrieve a body region on this player.\n"
"@return a string containing two words (space separated strings), where the "
"first is a location and the second is a modifier.\n\n"
"Posible locations: