-
Notifications
You must be signed in to change notification settings - Fork 624
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
Conversation
b848181
to
f29715e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I plan to follow up this PR with making mob mod adjustments to all of the relevant mob luas, unless you'd like me to include it all in this one PR.
The problem with this is that it leaves things in base
in an incomplete state, no? I'm only skimming and leaving this to others to also review
src/map/utils/battleutils.cpp
Outdated
} | ||
|
||
std::function<void(CBattleEntity*)> drawInFunc = [PMob, drawInDistance, &nearEntity, &success](CBattleEntity* PMember) | ||
std::function<void(CBattleEntity*)> drawInFunc = [PMob, drawInRange, &nearEntity, &success](CBattleEntity* PMember) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call this const auto drawInFunc = [&](CBattleEntity* PMember)
src/map/utils/battleutils.cpp
Outdated
@@ -5595,8 +5595,14 @@ namespace battleutils | |||
} | |||
} | |||
|
|||
bool DrawIn(CBattleEntity* PTarget, CMobEntity* PMob, float offset) | |||
bool DrawIn(CBattleEntity* PTarget, CMobEntity* PMob, float offset, uint8 drawInRange) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should drawInRange be a float?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted that to a float
src/map/utils/battleutils.cpp
Outdated
{ | ||
// Check if time to draw in again, if not then exit | ||
if (std::chrono::time_point_cast<std::chrono::seconds>(server_clock::now()).time_since_epoch().count() - PMob->GetLocalVar("DrawInTime") < 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fairly sure we have defines that allow you to make std::chrono::time_point_cast<std::chrono::seconds>(server_clock::now()).time_since_epoch().count()
much shorter than this? Or you can define it on the line before as const auto and then use it in the if statement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't able to find a define like this for seconds, so I made a variable and called it like you mentioned.
src/map/lua/lua_baseentity.cpp
Outdated
@@ -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); | |||
uint8 drawInRange = mobObj->GetMeleeRange() * 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does this come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it from the existing code for the draw in range, in battleutils.cpp on line 5626
This will correct most of the mobs to at least draw in to the correct location, although digging deeper in to draw ins I'm actually finding that drawing in as written in the core is quite rare. A vast majority of the mobs that do draw in will only do it if you try to drag them out of their spawn area, rather than if you move away from the mob itself too far. I was going to change that on a per mob basis in their lua unless there's a better solution. I was just concerned about making too big of a PR. |
As you noted, retail has a lot of different draw in results and triggers. Some (not all) of the different distances are caused by the mobs melee radius/sizing on retail. Def needed a distance control to handle some of them. Long ago I tried to handle draw in by taking it out of where it was (battelutils at the time, iirc its in the mob controller now) and moving it to its own function that can be bound. But repeated rebases from other work in the same area at the time lead to me breaking my branch and leaving it to rot. Been years now, never had time or energy to make a second attempt at it. I started on that way back in Darkstar - that's how long ago that was. Way later, someone did make a binding for it, but it just forces a draw in of a specified player target. There's no control over what actually happens within lua, just a force-trigger of it. ( Maybe not soon, but it might be worthwhile to transition away from mobmods and into parameters passed to a function, a handler for a decision at run time so you can do conditional logic in lua and pass the result back etc. Related and possibly abandoned 2 months ago: #6007 that one attempted to make a bitmask that could be added to. Actually found that from looking for an issue/discussion about draw in that tried to detail the triggers and results of different mobs draw-ins. I think what I was looking for was in a former iterations issues, I can't find it. No issues with the intent here in the pr, just had one of those "oh hey I remember knowing stuff and things related to this subject, I wanna share that" moments. |
Those captures are interesting. Here's some things I noticed: Roc looks like it draws its target in if it has been out of melee range for 10-15 seconds. It also seems to place the target behind it, and pretty far away at that. This seems like what the mimic does as well, except it places the target close in front of it and triggers every 1-2 seconds. Tiamat and King Vinegarroon looks like they only draws in if the target leaves the arena area, every 5-10 seconds, draws in to center. Something like Abyssea. They both stop chasing and stand still at a certain point, and start drawing in about every 10 seconds. May be something like the target has been out of bounds for 5 seconds. I think the draw in that deals with melee distance needs to be able to set angle and distance to place the target, a cooldown, an optional maximum range. Maybe a mixin would work for this? The other kind of draw in that Tiamat and KV use seem like something entirely different and should maybe be called something else to prevent confusion. This one seems like it's more tied to the area of the fight rather than the mob itself. I haven't really looked at how Abyssea is implemented, but this seems a lot like how you get drawn in if you try leaving the base without visitant status. I'm working on some stuff dealing with melee distance and model sizes, waiting for login campaign to start for some research, but I'll try looking more into this too. |
This could be some path node jank where SE has pre selected locations that are "good" and Shiva's size is "too big" to be teleported by the wall when a better node exists, at least this reminds me of node-based "can it fit" spawn detection I did for unreal engine 1 (1998) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a pretty clear improvement over what we have
That was just the clearest/closest example, but it appears the go to the sameish relative position every time. At ~0:40 it does it even in the open. KV and Tiamat draw in to the center, but only if you leave a defined area, not their melee range (they stop following at the edge of this area). In both cases there is a cooldown. The only thing I can think of that has this behavior of instantly drawing in if you leave melee range are mimics. And even those differ in how they do it. SW Apollyon mimics draw you in to their center, facing the same way as them (so positioned behind with 0 distance), while Odyssey mimics draw you in front of them, facing them. |
classic SE |
Apollyon mimics also don't draw in if you're over 20' away, but I don't think Odyssey mimics have a limit (probably same with AMAN). So yeah, classic SE. |
KV also randomly draws either its main target or the entire alliance when it uses a TP move. Trying to code that behavior actually is what led me down this entire draw in rabbit hole when Tiberon and I originally wrote this like two years ago. I did originally have a maximum reach for draw in mobmod but it never ended up being used so I scrapped it for this PR. Watching the Roc video (there's also another with Simurgh too that acts the same), I was wondering if it was delay due to Siknoz kiting the birds when the draw in happens and Shiva gets drawn in to where Roc was at the time the server processed the draw in vs where he actually was on the player's screen. Looking through captures though, most of the RoZ and CoP NMs that do draw in only do it when you try to leave their "arena" or spawn area, and when they do its not to their hitbox its actually to what looks like a set spot on the map. ToAU HNMs do the same thing except they draw you into a random spot in a box where they spawn. I definitely like the mixin idea for the arena draw in, we used a utils called "arenaDrawIn" to implement this for ASB awhile back that I could rework for LSB when I make the changes to all of the individual mobs. |
Yeah KV appears to also use draw in on demand before a TP move (didn't notice if its before a specific move or what). I wonder if the draw in that happens when leaving the spawn area also draws in the whole party, or if it's only the one before a TP move.
IDK it gets bound then draws in several times while still in the same position. The logs show about 10 seconds between the last melee hit and the draw in, though I think there is some variance on a few. Might just be due to melee swing timing though. I think what you're describing can be seen here with Proto-Omega. That position the player gets drawn in to is where Ultima ends up when it stops moving, likely due to latency it was already actually there when the draw in happened and the client was just catching up with movement. We can see earlier in the video that Ultima draws in to the center, facing the same direction, similar to Apollyon mimics. Ultima also seems to have an arena draw in seen here. Actually, since we don't have the draw in PoV, it might only be the arena draw in.
Which RoZ and CoP NMs draw in? I'd like to check it out more. Ultima, KV, and Tiamat look pretty straight forward if you imagine an invisible wall acting like the Abyssea gate (iirc it just draws you back to the gate after like 5 seconds but it's been a while and I can't find a video). I think a generalized system could be made that could be used for Abyssea and this arena draw in (or the current implementation expanded). I also don't know if there's a way to handle that mechanic where Tiamat and KV stop chasing you at the edge of their area. |
All three of the kings have a draw in leaving their spawn area. Voluptuous Vivian, Capricious Cassie, Bune, and Ash Dragon also have the same kind of thing. There's likely more, that's just off the top of my head. |
Vivian, Cassie, and Ash Dragon all seem to have the arena type draw in that draws in to the center of the hitbox.
This is what I'm interested in. I see that ToAU HNMS (Cerberus and Hydra at least) draw in to what looks like a few different set spots in their spawn area. So it seems the arena type draw in can pull to the boss or to a set spot(s). Then the distance from mob type draw in seems to draw in to a variable position relative to the boss. |
I was seeing it happen on Tiamat, I think I saw it on KV but not finding it now. Might be running into the same thing we're seeing on Roc/Sim where it's intending to bring it to the middle of hit box but it snaps to the closest safe location. I'll be honest, I don't know if I can figure out how to code that kind of logic in! The capture for Vivian really makes it obvious to me that the mob isn't allowed to path past the "arena" boundaries too. Not quite sure how to implement that portion. I'm going to edit this PR later today with the changes Zach listed, and also add in to have the player's rotation set to match the mob's too as you've noted. |
I don't think that's happening with Roc. It stills draws in pretty far away even when it's bound and not moving. I don't think it ever draws in to center. It does look like that's what's happening with Tiamat though. You can actually catch a frame where the character is moved before the camera, and you can see it's just outside Tiamat's hitbox, which is likely due to latency and movement (like how you have to run in front of a mob to hit it while moving). That ASB arena draw in looks like the right direction for that type of mechanic though. |
Here's a crappy drawing of the 4 different types of draw in I'm seeing, where the red circles are the mob, blue is the player, green square is arena, green circle is some distance from mob, and the red lines show potential draw in locations (center of boss, somewhere around boss or inside arena). Lines marked 2 and 4 could be anywhere inside the green and are just examples. I guess the biggest difference is if the end position is boss relative or arena relative. With the arena type though, the mob stops chasing at the edge of the arena so that has to be more than just a draw in box like the ASB implementation I think. |
This capture of KV is interesting. Both players are in melee range most of the time, well within the spawn area boundary, and the draw ins seem completely random. Starting here it draws in both players, uses Earthbreaker, then Venom String, then draws in just 1 player and uses Earthbreaker again. Towards the end when they start walking past the boundary (pretty sure this is the same spot the draw in happens in the other capture), only the forward-most character is drawn in (presumably the one following never actually leaves the fight area and doesn't get drawn in). Note for the first draw in after that time stamp, KV hasn't reached its range limit and is still moving, likely the reason the players appears to have been drawn in behind KV (latency because of movement). Shortly after that it stops chasing so there's no ambiguity where it's drawing in to. |
What im taking back from this discussion is draw in is consistently inconsistent and is far from SE's usual "for every rule, an exception" |
To try to boil down my observations and theories as much as possible: Draw in is triggered by one or more of:
When triggered, can be moved to:
There seems to be some cooldown in most cases. There can be a max range.
This is just my best guess based on what I've seen. In the cases where the mob is moving while the draw in happens, the player will likely not appear where it seems like they should because the position update packets needs to make a full round trip from Japan, during which the mob is still moving, so by the time your new position is confirmed the mob has moved and it looks like you're just inside melee range or something instead of centered on their hitbox. Edit: With a closer look it seems like ASB arenaDrawIn could do all of this. For normal range based draw in you can just use the mob pos as the arena pos. |
Co-authored-by: Tiberon <[email protected]>
f29715e
to
f782fb6
Compare
Well I think this PR should be good to go for at least a portion of the mobs that do draw in in this fashion. I've already got another PR ready to go with the mob adjustments and adding in the arenaDrawIn util. I made an issue though I'm seeing with draw in where mobs constantly reposition themselves everytime you get drawn in (#6561). |
So, I ported the arenaDrawIn stuff and expanded it to handle every case I've seen I think, while also removing all mob mods and core draw-in stuff, so it exists pretty much all in Lua (except the Navmesh safe position finding stuff). Here's some examples of how you would use it: Tiamat: local drawInTable = {
conditions = {
target:getXPos() < -515 and target:getZPos() > 8,
target:getXPos() > -480 and target:getZPos() > -50,
},
position = mob:getPos(),
wait = 3,
}
if drawInTable.conditions[1] then
mob:setMobMod(xi.mobMod.NO_MOVE, 1)
utils.drawIn(target, drawInTable)
else
mob:setMobMod(xi.mobMod.NO_MOVE, 0)
end Roc: entity.onMobFight = function(mob, target)
local drawInTable = {
conditions = {
target:checkDistance(mob) > 4,
},
position = mob:getPos(),
offset = 10,
radian = 180,
wait = 15,
}
if drawInTable.conditions[1] then
utils.drawIn(target, drawInTable)
end
end Cassie/Ultima: entity.onMobFight = function(mob, target)
local spawnPos = mob:getSpawnPos()
local drawInTable = {
conditions = {
target:checkDistance(spawnPos.x, spawnPos.y, spawnPos.z) > 25,
},
position = mob:getPos(),
wait = 3,
}
if drawInTable.conditions[1] then
mob:setMobMod(xi.mobMod.NO_MOVE, 1)
utils.drawIn(target, drawInTable)
else
mob:setMobMod(xi.mobMod.NO_MOVE, 0)
end
end For more basic draw in with no grace period/wait time: entity.onMobFight = function(mob, target)
if mob:checkDistance(target) >= mob:getMeleeRange() * 2 then
mob:drawIn(target) -- radian and offset optional args, otherwise dead center
end
end The only think I really have left to do is rip out the pool mods in the db and convert it into a mixin or something. This also decouples draw-in from the mob, so it can be used for other things too. Still testing though. |
I can go ahead and close this out, looks like coco is taking care of all of it in #6566 |
I affirm:
What does this pull request do?
While working on mechanics for certain HNMs, I noted that draw in appears to work differently all over the game. This PR adjusts the default draw in behavior, along with adding mob mods to customize draw in on a per mob basis as needed.
I plan to follow up this PR with making mob mod adjustments to all of the relevant mob luas, unless you'd like me to include it all in this one PR.
Captures used for this:
Steps to test these changes
Default behavior:
Mobmods: