Skip to content

Add Summoner Curse Skills and Lightning Shock Skill Fix#738

Draft
ze-dom wants to merge 3 commits intoMUnique:masterfrom
ze-dom:lightning_shock
Draft

Add Summoner Curse Skills and Lightning Shock Skill Fix#738
ze-dom wants to merge 3 commits intoMUnique:masterfrom
ze-dom:lightning_shock

Conversation

@ze-dom
Copy link
Copy Markdown
Contributor

@ze-dom ze-dom commented Mar 26, 2026

To-do

  • UpdatePlugins (after discussion)
  • Comment changes with source references

Developments

  • Summoner's Explosion, Requiem and Pollution skills (book) and their magic effects
  • Summoner's Lightning Shock skill completion
  • Added Skill.SkipElementalModifierto bypass element resistance checks

Comment on lines -284 to -286
var hitChance = attackRound < areaSkillSettings.MinimumNumberOfHitsPerTarget
? 1.0
: Math.Min(areaSkillSettings.HitChancePerDistanceMultiplier, Math.Pow(areaSkillSettings.HitChancePerDistanceMultiplier, player.GetDistanceTo(target)));
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await observable.ForEachWorldObserverAsync<IObjectMovedPlugIn>(p => p.ObjectMovedAsync(walkSupporter, MoveType.Instant), true).ConfigureAwait(false);
}
}
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
return false;
}
var skipModifier = skillEntry.Skill.SkipElementalModifier;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the early seasons skills (S1, S2) use the elemental resistance checks:
emu, zTeamS6.3

return;
}

var multiplier = magicEffectDefinition.Number == ExplosionMagicEffectNumber ? attacker.Attributes[Stats.BleedingDamageMultiplier] : 0.6f;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emu, zTeamS6.3
Because the FireTomeMastery (Explosion skill) is a passive, we need to hardcode 0.6f here, otherwise you can use Requiem skill and also get the FireTomeMastery multiplier bonus.

await this._attackAction.AttackAsync(player, extraTargetId, PollutionSkillId, point, rotation).ConfigureAwait(false);
}
});
}
Copy link
Copy Markdown
Contributor Author

@ze-dom ze-dom Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skill.SkipElementalModifier = true;
skill.MagicEffectDef = this.CreateEffect(ElementalType.Ice, MagicEffectNumber.Iced, Stats.IsIced, 2);
return;
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isStunnedPowerUpDefinition.Boost = this.Context.CreateNew<PowerUpDefinitionValue>();
isStunnedPowerUpDefinition.Boost.ConstantValue.Value = 1;
}
} No newline at end of file
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@ggmammoth
Copy link
Copy Markdown

I want to implement a stun mechanic with a percentage chance and a fixed duration.
When a skill or attack is executed, I generate a random value between 0 and 1 and compare it to a predefined stun chance (for example, 20%). If the random value is within that chance, I apply a stun effect to the target for a specific duration (for example, 3 seconds).

// stun chance (example: 20%)
double stunChance = 0.20;

// generate random number between 0 and 1
double roll = Random.Shared.NextDouble();

// check if stun should be applied
if (roll <= stunChance)
{
// apply stun effect for 3 seconds
target.ApplyMagicEffect(
MagicEffectNumber.Stunned,
TimeSpan.FromSeconds(3));
}

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

magicEffect.Duration = this.Context.CreateNew<PowerUpDefinitionValue>();

// Damage is applied 5 times for every second
magicEffect.Duration.ConstantValue.Value = 5;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

magicEffect.Duration = this.Context.CreateNew<PowerUpDefinitionValue>();

// Damage is applied 5 times for every second
magicEffect.Duration.ConstantValue.Value = 5;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.Attacker = attacker;
this.Owner = owner;
this._damage = damage;
this._damageTimer = new Timer(1000);
Copy link
Copy Markdown
Contributor Author

@ze-dom ze-dom Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

@ze-dom
Copy link
Copy Markdown
Contributor Author

ze-dom commented Mar 27, 2026

I want to implement a stun mechanic with a percentage chance and a fixed duration. When a skill or attack is executed, I generate a random value between 0 and 1 and compare it to a predefined stun chance (for example, 20%). If the random value is within that chance, I apply a stun effect to the target for a specific duration (for example, 3 seconds).

// stun chance (example: 20%) double stunChance = 0.20;

// generate random number between 0 and 1 double roll = Random.Shared.NextDouble();

// check if stun should be applied if (roll <= stunChance) { // apply stun effect for 3 seconds target.ApplyMagicEffect( MagicEffectNumber.Stunned, TimeSpan.FromSeconds(3)); }

Check this file. I do that there:
https://github.com/MUnique/OpenMU/pull/738/changes#diff-48e019d7ab8cfc38baac49d2275d7d992eca9f414cd658ec05c5c71603e242d7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants