Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Adjust draw-in behavior and add additional functionality #6532

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions scripts/enum/mob_mod.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,7 @@ xi.mobMod =
SKIP_ALLEGIANCE_CHECK = 80, -- Skip the allegiance check for valid target (allows for example a mob to cast a TARGET_ENEMY spell on itself)
ABILITY_RESPONSE = 81, -- Mob can respond to player ability use with onPlayerAbilityUse()
SPEED_BOOST_MULT = 82, -- Multiplier for the base speed of a mob when the mob's target is out of range (range between 100 and 500, 250 means 2.5x, mechanism is from retail)
DRAW_IN_FRONT = 83, -- Mob will draw in slightly in front of them instead of the center of their hitbox (HNMs such as Tiamat)
DRAW_IN_CUSTOM_RANGE = 84, -- Override the default range of MeleeRange*2 of when players start to get drawn-in
DRAW_IN_BIND = 85, -- Forces mob to draw in the moment you leave melee range (ex. Mimics)
}
14 changes: 12 additions & 2 deletions src/map/ai/controllers/mob_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,9 +708,19 @@ void CMobController::Move()
if (((currentDistance > closeDistance) || move) && PMob->PAI->CanFollowPath())
{
// TODO: can this be moved to scripts entirely?
if (PMob->getMobMod(MOBMOD_DRAW_IN) > 0)
if (PMob->getMobMod(MOBMOD_DRAW_IN))
{
if (currentDistance >= PMob->GetMeleeRange() * 2 && battleutils::DrawIn(PTarget, PMob, PMob->GetMeleeRange() - 0.2f))
uint8 drawInRange = PMob->getMobMod(MOBMOD_DRAW_IN_CUSTOM_RANGE) > 0 ? PMob->getMobMod(MOBMOD_DRAW_IN_CUSTOM_RANGE) : PMob->GetMeleeRange() * 2;

// Draw in when target is farther than 2x melee range
if (currentDistance > drawInRange && battleutils::DrawIn(PTarget, PMob, PMob->GetMeleeRange() - 0.2f, drawInRange))
{
FaceTarget();
return;
}
// If i'm bound/can't move, draw in the moment they leave my melee range
else if (PMob->getMobMod(MOBMOD_DRAW_IN_BIND) && (PMob->speed == 0 || PMob->getMobMod(MOBMOD_NO_MOVE)) &&
currentDistance > PMob->GetMeleeRange() && battleutils::DrawIn(PTarget, PMob, PMob->GetMeleeRange() - 1.2f, PMob->GetMeleeRange()))
{
FaceTarget();
return;
Expand Down
7 changes: 4 additions & 3 deletions src/map/lua/lua_baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17172,7 +17172,8 @@ void CLuaBaseEntity::drawIn(sol::variadic_args va)
return;
}

auto mobObj = dynamic_cast<CMobEntity*>(m_PBaseEntity);
auto mobObj = dynamic_cast<CMobEntity*>(m_PBaseEntity);
float drawInRange = mobObj->GetMeleeRange() * 2;

if (va.size() == 0)
{
Expand All @@ -17182,7 +17183,7 @@ void CLuaBaseEntity::drawIn(sol::variadic_args va)
{
return;
}
battleutils::DrawIn(defaultTarget, mobObj, mobObj->GetMeleeRange() - 0.2f);
battleutils::DrawIn(defaultTarget, mobObj, mobObj->GetMeleeRange() - 0.2f, drawInRange);
return;
}

Expand All @@ -17204,7 +17205,7 @@ void CLuaBaseEntity::drawIn(sol::variadic_args va)

if (PTarget)
{
battleutils::DrawIn(PTarget, mobObj, mobObj->GetMeleeRange() - 0.2f);
battleutils::DrawIn(PTarget, mobObj, mobObj->GetMeleeRange() - 0.2f, drawInRange);
}

return;
Expand Down
3 changes: 3 additions & 0 deletions src/map/mob_modifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ enum MOBMODIFIER : int
MOBMOD_SKIP_ALLEGIANCE_CHECK = 80, // Skip the allegiance check for valid target (allows for example a mob to cast a TARGET_ENEMY spell on itself)
MOBMOD_ABILITY_RESPONSE = 81, // Mob can respond to player ability use with onPlayerAbilityUse()
MOBMOD_SPEED_BOOST_MULT = 82, // Multiplier for the base speed of a mob when the mob's target is out of range (range between 100 and 25500, 250 means 2.5x, mechanism is from retail)
MOBMOD_DRAW_IN_FRONT = 83, // Mob will draw in slightly in front of them instead of the center of their hitbox (HNMs such as Tiamat)
MOBMOD_DRAW_IN_CUSTOM_RANGE = 84, // Override the default range of MeleeRange*2 of when players start to get drawn-in
MOBMOD_DRAW_IN_BIND = 85, // Forces mob to draw in the moment you leave melee range (ex. Mimics)
};

#endif
40 changes: 27 additions & 13 deletions src/map/utils/battleutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5595,8 +5595,16 @@ namespace battleutils
}
}

bool DrawIn(CBattleEntity* PTarget, CMobEntity* PMob, float offset)
bool DrawIn(CBattleEntity* PTarget, CMobEntity* PMob, float offset, float drawInRange)
{
// Check if time to draw in again, if not then exit
uint64 timeStamp = std::chrono::time_point_cast<std::chrono::seconds>(server_clock::now()).time_since_epoch().count();

if (timeStamp - PMob->GetLocalVar("DrawInTime") < 2)
{
return false;
}

position_t& pos = PMob->loc.p;
position_t nearEntity = nearPosition(pos, offset, (float)0);

Expand All @@ -5622,19 +5630,13 @@ namespace battleutils
// Move the target a little higher, just in case
nearEntity.y -= 1.0f;

bool success = false;
float drawInDistance = (float)(PMob->getMobMod(MOBMOD_DRAW_IN) > 1 ? PMob->getMobMod(MOBMOD_DRAW_IN) : PMob->GetMeleeRange() * 2);

if (std::chrono::time_point_cast<std::chrono::seconds>(server_clock::now()).time_since_epoch().count() - PMob->GetLocalVar("DrawInTime") < 2)
{
return false;
}
bool success = false;

std::function<void(CBattleEntity*)> drawInFunc = [PMob, drawInDistance, &nearEntity, &success](CBattleEntity* PMember)
const auto drawInFunc = [PMob, drawInRange, &nearEntity, &success](CBattleEntity* PMember)
{
float pDistance = distance(PMob->loc.p, PMember->loc.p);

if (PMob->loc.zone == PMember->loc.zone && pDistance > drawInDistance && PMember->status != STATUS_TYPE::CUTSCENE_ONLY)
if (PMob->loc.zone == PMember->loc.zone && pDistance > drawInRange && PMember->status != STATUS_TYPE::CUTSCENE_ONLY)
{
// don't draw in dead players for now!
// see tractor
Expand All @@ -5645,9 +5647,21 @@ namespace battleutils
else
{
// draw in!
PMember->loc.p.x = nearEntity.x;
PMember->loc.p.y = nearEntity.y;
PMember->loc.p.z = nearEntity.z;
// Certain families (such as Wyrms) draw in in front of where they are looking
if (PMob->getMobMod(MOBMOD_DRAW_IN_FRONT))
{
PMember->loc.p.x = nearEntity.x;
PMember->loc.p.y = nearEntity.y;
PMember->loc.p.z = nearEntity.z;
}
// Default behavior is to draw in to middle of hit box.
else
{
PMember->loc.p.x = PMob->loc.p.x;
PMember->loc.p.y = nearEntity.y;
PMember->loc.p.z = PMob->loc.p.z;
PMember->loc.p.rotation = PMob->loc.p.rotation;
}

if (PMember->objtype == TYPE_PC)
{
Expand Down
2 changes: 1 addition & 1 deletion src/map/utils/battleutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ namespace battleutils
WEATHER GetWeather(CBattleEntity* PEntity, bool ignoreScholar);
WEATHER GetWeather(CBattleEntity* PEntity, bool ignoreScholar, uint16 zoneWeather);
bool WeatherMatchesElement(WEATHER weather, uint8 element);
bool DrawIn(CBattleEntity* PEntity, CMobEntity* PMob, float offset);
bool DrawIn(CBattleEntity* PEntity, CMobEntity* PMob, float offset, float drawInRange);
void DoWildCardToEntity(CCharEntity* PCaster, CCharEntity* PTarget, uint8 roll);
bool DoRandomDealToEntity(CCharEntity* PChar, CBattleEntity* PTarget);

Expand Down
Loading