-
Notifications
You must be signed in to change notification settings - Fork 98
Sadhu skills #302
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
base: master
Are you sure you want to change the base?
Sadhu skills #302
Conversation
exectails
left a comment
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.
Thanks for the PR. I took a quick glance and I noticed that some of it still seems a bit prototypical, and I also have some questions and concerns before we continue. Please refer to my comments.
src/ZoneServer/World/Actors/CombatEntities/Components/MovementComponent.cs
Outdated
Show resolved
Hide resolved
| if (!ZoneServer.Instance.Data.MapDb.TryFind(mapId, out var map)) | ||
| throw new ArgumentException("Map '" + mapId + "' not found in data."); | ||
|
|
||
| if (this.IsOutOfBody()) |
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 feel like this is a weird place to check for out of body to prevent warps, because what if we do want to warp? This special behavior also isn't documented anywhere, so anyone who might try to warp someone will have to dig deep into the warp code to figure out why it's not working.
Additionally, creating explicit checks for very specific conditions within general purpose functions is not ideal, because it's not extensible. An alternative idea that I'm just going to throw out there might be to add a warp lock, which you can set for these buffs you're checking in IsOutOfBody, which will generalize the whole approach, make it somewhat self-documenting, save you from having to do that manual buff check, and have it be reusable.
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.
You marked this as resolved, but the issues are still there 🤔
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.
warping prevention removed!
src/ZoneServer/World/Actors/CombatEntities/Components/MovementComponent.cs
Outdated
Show resolved
Hide resolved
| { | ||
| LearnSkill(character, SkillId.Hammer_Attack); | ||
| LearnSkill(character, SkillId.Hammer_Attack_TH); | ||
| LearnSkill(character, SkillId.Sadhu_OutofBodyCancel); |
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.
Can you tell me why you removed this? It's part of the official data, which there probably is a reason for.
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.
This skill is not being used anymore and has no purposes. Sadhu has been remake I think.
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.
This is based on official data though, and removing it creates a dissonance between server and client. Unless this causes issues, it should stay this way.
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.
This WAS from the official data, but it got outdated, since the last changes on sadhu, the skill is not being used anymore.
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.
That may be true, but it is in fact still part of the job data as of the last time I checked, which this script is based on.
Removing this makes updating the data more challenging, because you have to remember not to add this skill. Potential automated tools for this purpose would also have to be changed not to re-add it. And if it is actually still used for something without our knowledge, we would rather not remove it. Not to mention that any kind of backwards compatibility we might want to introduce would potentially require this line to be re-added.
For these reasons I asked whether there are any issues with leaving it as is, because that is the simplest solution for my concerns, unless we have to conditionally remove it for some reason.
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.
src/ZoneServer/Skills/Handlers/Clerics/Sadhu/Sadhu_Skill_Base.cs
Outdated
Show resolved
Hide resolved
| if (!ZoneServer.Instance.Data.MapDb.TryFind(mapId, out var map)) | ||
| throw new ArgumentException("Map '" + mapId + "' not found in data."); | ||
|
|
||
| if (this.IsOutOfBody()) |
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.
You marked this as resolved, but the issues are still there 🤔
|
@exectails this PR is ready to be reviewed again. |
exectails
left a comment
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 appreciate your efforts for improving the code, though some concerns have not been cleared yet. Still, I might consider merging the PR soon, assuming you're still around and able to maintain the changes, fixing issues in a timely manner should they arise.
Given the nature of this class, the code is unfortunately not very straightforward to follow in its current form, and I suspect potential changes or improvements to it would be simpler to accomplish if one were to rewrite the skills. As their developer, I assume you would have a better overview of them and their behavior.
src/ZoneServer/Network/Send.cs
Outdated
| /// </summary> | ||
| /// <param name="character"></param> | ||
| /// <param name="targetCharacter"></param> | ||
| public static void ZC_UPDATED_PCAPPEARANCE(Character character, Character targetCharacter) |
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.
You've added a few overloads like this, where you differentiate between a character and target, but several of them don't seem to serve a real purpose. Like this one, where all the information is taken from the target, but the source of the broadcast is a different character. This could lead to confusion over what information the caller is expected to give. It could also lead to visual bugs, because if someone else is in range of the target character, but not the character, they might not receive the packets you're broadcasting. These senders should get reevaluated and cleaned up to only make this distinction if that is actually necessary and desired.
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.
resolved.
src/ZoneServer/Network/Send.cs
Outdated
| /// <param name="propertyList"></param> | ||
| public static void ZC_OBJECT_PROPERTY(IZoneConnection conn, long objectId, PropertyList propertyList) | ||
| { | ||
| // TODO: Find a better way to check this - This was done to avoid sending packets for dummies (while receiving buffs) |
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 don't recall if I mentioned this before, but the idea behind a dummy anything is usually that you can use them like the real thing without thinking twice about it. As such, if you have a dummy character, would it not be easier to also have a dummy connection, to be able to "send" them packets without actually doing so? Or is there a reason I'm missing for why a null check might be preferable?
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 don't think we would need a fake connection for dummies.
A connection means that a client exists behind it, right?
For the other side, we can send packets to the dummy map:
dummy.Map.Broadcast(packet);
If in the future the dummy plays an animation (when the dummy is selling equipament improvements and it needs to play the refinement animation, for example) we can use this without problem.
I have move this check to InitEvents() method on CharacterProperties.cs:
/// <summary>
/// Sets up event subscriptions, to react to actions of the
/// character with property updates.
/// </summary>
private void InitEvents()
{
// This was done to avoid sending packets for dummies (while receiving buffs)
if (this.Character.Connection == null)
return;
[...]
}
| // [i373230] Maybe added earlier | ||
| // [i373230] Maybe added earlier [Updated at 28/07/24] | ||
| { | ||
| packet.PutByte(0); |
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.
Were you able to confirm that this is actually a short and not two bytes? Changing data like this could easily lead to confusion at a later point when we try to figure out what these bytes do.
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.
Changes reverted.
src/ZoneServer/Network/Send.cs
Outdated
| /// </summary> | ||
| /// <param name="entity"></param> | ||
| /// <param name="target"></param> | ||
| public static void ZC_MSPD(ICombatEntity entity, ICombatEntity target) |
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.
Is it possible you're misunderstanding what this sender does? While this overload allows you to treat the two values as distinct entities, the only difference is who gets notified about the change. Generally speaking, you'd want the source entity to also be the target entity, so the other clients in range of the target get informed about the target's new speed--not the clients who are close to the source, who might not even be in visible range of the target.
| /// <param name="creator"></param> | ||
| private async Task MovePad(Pad pad, ICombatEntity creator) | ||
| { | ||
| // Forward and back, hovering a moment in between. |
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.
The comment says forward and back but that's not what's happening here. Could you clarify whether the error is in the code or the comment? If it's the comment that's incorrect, and the pad only moves forward, this comment could safely be removed, as the method appears clear-cut and is commented appropriately.
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.
wrong commentary. Fix applied.
| /// <summary> | ||
| /// Returns true if the DummyCharacter has Owner | ||
| /// </summary> | ||
| public bool hasOwner => Owner != null; |
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.
There are still some convention violations, such as curly braces on the same line as a foreach or this camelCase property. If you're using Visual Studio, auto-formatting should solve some of these issues and the style checker should inform you about the rest.
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.
Done.
| } | ||
|
|
||
| if (this.Entity is Character character) | ||
| if (this.Entity is Character character && character is not DummyCharacter) |
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.
You're mixing conventions of checking for dummy characters before calling senders and inside them, as well as mixing type and null checks. I do understand what led to this, but it would be better to stay consistent. Better yet would be to not need this distinction.
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 have changed to:
if (this.Entity is Character character && this.Entity is not DummyCharacter)
Send.ZC_COOLDOWN_CHANGED(character, cooldown);
But it's essentially the same. It's needed since the dummy casts a skill.
|
|
||
| Send.ZC_MSPD(this.Entity); | ||
| } | ||
| else if (this.Entity is Character character && character is DummyCharacter dummyCharacter) |
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 would presume this check to be either incorrect or redundant. Am I right in that assessment? You're checking whether the entity is a character and a dummy character, which would mean the code applies only to dummy characters, as only they are both. Though in that case it would be enough to check for the dummy character type. And if you wanted it to apply to both, a check for character would be enough, as the dummy inherits character iirc.
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.
fixed.
| { | ||
| foreach (var character in _characters.Values) | ||
| character.Connection.Send(packet); | ||
| character.Connection?.Send(packet); |
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 not a huge fan of this change, as it introduces a new type of character into the system that did not exist prior and might not be handled correctly in all cases: a character without connection. Before this, all characters could be presumed to have a connection during their entire session, from when they connect to when they disconnect. If that's no longer the case, we'd have to make sure that any access to the connection property, as well as information behind that, such as accounts, are properly checked before they're accessed.
While I recognize that this only applies to the Sadhu dummy characters right now, and that everything may very well work as intended for the moment, we will inevitably use the cloning methods you introduced for other purposes and other systems are going to have to work around these dummy characters, regardless of where they came from.
With that in mind, have you made sure that this radical change won't cause any issues in the existing code?
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.
This is a bit confused for me.
Last time we talked you said that it would be better to keep using the on going Characters instead of creating a new dictionary:
private readonly Dictionary<int, Character> _dummiesCharacter = new();
That what I did last time and I have refactored to keep using the current dictionary.
I am not sure if this approach will work still with vending dummies character but it should!
It would require a few changes but mainly it's the same.
| { | ||
| LearnSkill(character, SkillId.Hammer_Attack); | ||
| LearnSkill(character, SkillId.Hammer_Attack_TH); | ||
| LearnSkill(character, SkillId.Sadhu_OutofBodyCancel); |
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.
That may be true, but it is in fact still part of the job data as of the last time I checked, which this script is based on.
Removing this makes updating the data more challenging, because you have to remember not to add this skill. Potential automated tools for this purpose would also have to be changed not to re-add it. And if it is actually still used for something without our knowledge, we would rather not remove it. Not to mention that any kind of backwards compatibility we might want to introduce would potentially require this line to be re-added.
For these reasons I asked whether there are any issues with leaving it as is, because that is the simplest solution for my concerns, unless we have to conditionally remove it for some reason.
|
@exectails I have update this PR with:
|

All Sadhu Skills:
Also there was an implementation of the art Spirit Expert: Wandering Soul which creates a dummy that acts by himself.