Add Summoner Curse Skills and Lightning Shock Skill Fix#738
Add Summoner Curse Skills and Lightning Shock Skill Fix#738ze-dom wants to merge 7 commits intoMUnique:masterfrom
Conversation
| var hitChance = attackRound < areaSkillSettings.MinimumNumberOfHitsPerTarget | ||
| ? 1.0 | ||
| : Math.Min(areaSkillSettings.HitChancePerDistanceMultiplier, Math.Pow(areaSkillSettings.HitChancePerDistanceMultiplier, player.GetDistanceTo(target))); |
There was a problem hiding this comment.
Pretty sure this is not accurate for Flame and Twister. Those may sometimes not hit at all. Will check it another time. For now I've kept it as it was.
There was a problem hiding this comment.
Yea, it's hard to replicate the exact same logic on server side. Flame and Twisters hits were originally calculated on the client side, when rendering each frame(!), depending on the actual (random) animation. So, increasing the frame rate from 25 to 60 fps led to a higher chance of hits 😄
| currentTarget = nextTarget; | ||
| } | ||
|
|
||
| await movableTarget.MoveAsync(currentTarget).ConfigureAwait(false); |
| await observable.ForEachWorldObserverAsync<IObjectMovedPlugIn>(p => p.ObjectMovedAsync(walkSupporter, MoveType.Instant), true).ConfigureAwait(false); | ||
| } | ||
| } | ||
| } |
| { | ||
| return false; | ||
| } | ||
| var skipModifier = skillEntry.Skill.SkipElementalModifier; |
| return; | ||
| } | ||
|
|
||
| var multiplier = magicEffectDefinition.Number == ExplosionMagicEffectNumber ? attacker.Attributes[Stats.BleedingDamageMultiplier] : 0.6f; |
| await this._attackAction.AttackAsync(player, extraTargetId, PollutionSkillId, point, rotation).ConfigureAwait(false); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
emu: ObjUseSkill.cpp, user.cpp, zTeamS6.3: ObjectUseSkill.cpp, user.cpp
64-59 = 5
Video of skill display:
https://www.youtube.com/watch?v=Gpmxlw3kjsc
| skill.SkipElementalModifier = true; | ||
| skill.MagicEffectDef = this.CreateEffect(ElementalType.Ice, MagicEffectNumber.Iced, Stats.IsIced, 2); | ||
| return; | ||
| } |
| isStunnedPowerUpDefinition.Boost = this.Context.CreateNew<PowerUpDefinitionValue>(); | ||
| isStunnedPowerUpDefinition.Boost.ConstantValue.Value = 1; | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
Didn't add any duration because from what I've seen so far the effect is not default to any skill, so it's more called in an ad hoc fashion.
|
I want to implement a stun mechanic with a percentage chance and a fixed duration. // stun chance (example: 20%) // generate random number between 0 and 1 // check if stun should be applied |
| this.CreateSkill(SkillNumber.Pollution, "Pollution", CharacterClasses.AllSummoners, DamageType.Curse, 80, 6, 15, 120, energyRequirement: 115, elementalModifier: ElementalType.Lightning); // Book of Lagle's skill | ||
| this.CreateSkill(SkillNumber.LightningShock, "Lightning Shock", CharacterClasses.AllSummoners, DamageType.Wizardry, 95, 6, 7, 115, energyRequirement: 823, elementalModifier: ElementalType.Lightning); | ||
| this.CreateSkill(SkillNumber.Explosion223, "Explosion", CharacterClasses.AllSummoners, DamageType.Curse, 40, 6, 5, 90, energyRequirement: 100, elementalModifier: ElementalType.Fire, skillType: SkillType.AreaSkillAutomaticHits); // Book of Samut's skill | ||
| this.AddAreaSkillSettings(SkillNumber.Explosion223, false, 0, 0, 0, effectRange: 2); |
| this.CreateSkill(SkillNumber.Requiem, "Requiem", CharacterClasses.AllSummoners, DamageType.Curse, 65, 6, 10, 110, energyRequirement: 99, elementalModifier: ElementalType.Wind, skillType: SkillType.AreaSkillAutomaticHits); // Book of Neil's skill | ||
| this.AddAreaSkillSettings(SkillNumber.Requiem, false, 0, 0, 0, effectRange: 2); | ||
| this.CreateSkill(SkillNumber.Pollution, "Pollution", CharacterClasses.AllSummoners, DamageType.Curse, 80, 6, 15, 120, energyRequirement: 115, elementalModifier: ElementalType.Lightning, skillType: SkillType.AreaSkillAutomaticHits); // Book of Lagle's skill | ||
| this.AddAreaSkillSettings(SkillNumber.Pollution, false, 0, 0, 0, minimumHitsPerAttack: 4, maximumHitsPerAttack: 8, effectRange: 3); |
| this.CreateSkill(SkillNumber.Pollution, "Pollution", CharacterClasses.AllSummoners, DamageType.Curse, 80, 6, 15, 120, energyRequirement: 115, elementalModifier: ElementalType.Lightning, skillType: SkillType.AreaSkillAutomaticHits); // Book of Lagle's skill | ||
| this.AddAreaSkillSettings(SkillNumber.Pollution, false, 0, 0, 0, minimumHitsPerAttack: 4, maximumHitsPerAttack: 8, effectRange: 3); | ||
| this.CreateSkill(SkillNumber.LightningShock, "Lightning Shock", CharacterClasses.AllSummoners, DamageType.Wizardry, 95, 6, 7, 115, energyRequirement: 823, elementalModifier: ElementalType.Lightning, skillType: SkillType.AreaSkillAutomaticHits); | ||
| this.AddAreaSkillSettings(SkillNumber.LightningShock, false, 0, 0, 0, minimumHitsPerAttack: 5, maximumHitsPerAttack: 12, useTargetAreaFilter: true, targetAreaDiameter: 14); |
| this.AddMasterSkillDefinition(SkillNumber.LightningTomeMastery, SkillNumber.LightningTomeStren, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula181); | ||
| this.AddPassiveMasterSkillDefinition(SkillNumber.FireTomeMastery, Stats.BleedingDamageMultiplier, AggregateType.AddRaw, $"{Formula181} / 100", 3, 2, SkillNumber.FireTomeStrengthener); | ||
| this.AddPassiveMasterSkillDefinition(SkillNumber.WindTomeMastery, Stats.StunChance, AggregateType.AddRaw, $"{Formula120} / 100", 3, 2, SkillNumber.WindTomeStrengthener); | ||
| this.AddPassiveMasterSkillDefinition(SkillNumber.LightningTomeMastery, Stats.PollutionMoveTargetChance, AggregateType.AddRaw, $"{Formula181} / 100", 3, 2, SkillNumber.LightningTomeStren); |
There was a problem hiding this comment.
| this.AddMasterSkillDefinition(SkillNumber.WindTomeMastery, SkillNumber.WindTomeStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula120); | ||
| this.AddMasterSkillDefinition(SkillNumber.LightningTomeMastery, SkillNumber.LightningTomeStren, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula181); | ||
| this.AddPassiveMasterSkillDefinition(SkillNumber.FireTomeMastery, Stats.BleedingDamageMultiplier, AggregateType.AddRaw, $"{Formula181} / 100", 3, 2, SkillNumber.FireTomeStrengthener); | ||
| this.AddPassiveMasterSkillDefinition(SkillNumber.WindTomeMastery, Stats.StunChance, AggregateType.AddRaw, $"{Formula120} / 100", 3, 2, SkillNumber.WindTomeStrengthener); |
There was a problem hiding this comment.
| this.AddMasterSkillDefinition(SkillNumber.FireTomeMastery, SkillNumber.FireTomeStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula181); | ||
| this.AddMasterSkillDefinition(SkillNumber.WindTomeMastery, SkillNumber.WindTomeStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula120); | ||
| this.AddMasterSkillDefinition(SkillNumber.LightningTomeMastery, SkillNumber.LightningTomeStren, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula181); | ||
| this.AddPassiveMasterSkillDefinition(SkillNumber.FireTomeMastery, Stats.BleedingDamageMultiplier, AggregateType.AddRaw, $"{Formula181} / 100", 3, 2, SkillNumber.FireTomeStrengthener); |
There was a problem hiding this comment.
| magicEffect.Duration = this.Context.CreateNew<PowerUpDefinitionValue>(); | ||
|
|
||
| // Damage is applied 5 times for every second | ||
| magicEffect.Duration.ConstantValue.Value = 5; |
| magicEffect.Duration = this.Context.CreateNew<PowerUpDefinitionValue>(); | ||
|
|
||
| // Damage is applied 5 times for every second | ||
| magicEffect.Duration.ConstantValue.Value = 5; |
| this.Attacker = attacker; | ||
| this.Owner = owner; | ||
| this._damage = damage; | ||
| this._damageTimer = new Timer(1000); |
There was a problem hiding this comment.
emu, zTeamS6.3
While poison is every 3s, this one seems to be every second. Check the skill videos at muonlinefanz.com (they are cut short, but you can see the 2nd dmg coming up).
Check this file. I do that there: |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces significant enhancements to the Summoner class by implementing several key skills and refining existing mechanics. It adds new functionality for handling elemental modifiers, introduces a bleeding damage system, and updates skill configurations to ensure proper behavior and balance. These changes aim to improve the gameplay experience for the Summoner class by providing more robust and accurate skill mechanics. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request implements the Summoner's book skills (Explosion, Requiem, Pollution) and introduces a bleeding effect mechanic. It extends AreaSkillSettings with new properties, adds corresponding attributes to the Stats class, and implements stun and push-back logic through new skill plugins. Feedback highlights the need to wrap a fire-and-forget task in a try-catch block to ensure application stability, replace placeholder GUIDs in the new plugins, and define magic numbers as named constants to improve code maintainability.
| _ = Task.Run(async () => | ||
| { | ||
| for (int i = 1; i <= 5; i++) | ||
| { | ||
| await Task.Delay(1000).ConfigureAwait(false); | ||
| await this._attackAction.AttackAsync(player, extraTargetId, PollutionSkillId, point, rotation).ConfigureAwait(false); | ||
| } | ||
| }); |
There was a problem hiding this comment.
This fire-and-forget task (_ = Task.Run(...)) can be dangerous. Any unhandled exception within the async lambda will be swallowed and could crash the application. It's crucial to wrap the content of the task in a try-catch block to handle potential exceptions and log them.
_ = Task.Run(async () =>
{
try
{
for (int i = 1; i <= 5; i++)
{
await Task.Delay(1000).ConfigureAwait(false);
await this._attackAction.AttackAsync(player, extraTargetId, PollutionSkillId, point, rotation).ConfigureAwait(false);
}
}
catch (Exception ex)
{
player.Logger.LogError(ex, "Error during pollution skill execution.");
}
});| /// </summary> | ||
| [PlugIn] | ||
| [Display(Name = nameof(PlugInResources.PollutionSkillPlugIn_Name), Description = nameof(PlugInResources.PollutionSkillPlugIn_Description), ResourceType = typeof(PlugInResources))] | ||
| [Guid("A2B3C4D5-E6F7-4812-3456-7890ABCDEF12")] |
| /// </summary> | ||
| [PlugIn] | ||
| [Display(Name = nameof(PlugInResources.RequiemSkillPlugIn_Name), Description = nameof(PlugInResources.RequiemSkillPlugIn_Description), ResourceType = typeof(PlugInResources))] | ||
| [Guid("A1B2C3D4-E5F6-7890-ABCD-EF1234567890")] |
| return; | ||
| } | ||
|
|
||
| var multiplier = magicEffectDefinition.Number == ExplosionMagicEffectNumber ? attacker.Attributes[Stats.BleedingDamageMultiplier] : 0.6f; |
There was a problem hiding this comment.
The magic number 0.6f for the bleeding damage multiplier should be defined as a named constant to improve readability and maintainability. For example, you could add private const float RequiemBleedingDamageMultiplier = 0.6f; at the top of the AttackableExtensions class and use it here. This would make it clear what this value represents.
| } | ||
| else if (attackCount >= minAttacks) | ||
| { | ||
| hitChance = 0.5; |
| } | ||
| else if (attackCount >= minAttacks) | ||
| { | ||
| hitChance = 0.5; |
To-do
Developments
Skill.SkipElementalModifierto bypass element resistance checks