-
Notifications
You must be signed in to change notification settings - Fork 344
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
Add dark horse options & major dmg calcs refactoring #586
base: master
Are you sure you want to change the base?
Conversation
|| masterSkillTargetAttribute == powerUpDef.TargetAttribute) | ||
{ | ||
var additionalValue = new SimpleElement(skillEntry.CalculateValue(), skillEntry.Skill.MasterDefinition?.Aggregation ?? powerUp.AggregateType); | ||
var additionalValue = new SimpleElement(masterSkillEntry.CalculateValue(), masterSkillEntry.Skill.MasterDefinition?.Aggregation ?? powerUp.AggregateType); |
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.
Before, it would always calculate the value from the formula of the skillEntry
and not of the one associated with the current master skill definition. I believe the idea initially was to traverse the related master skill definitions and apply each formula. I have tested it this way with Soul Barrier Strengthener/Soul Barrier Proficiency and works.
.Append(new PowerUpWrapper( | ||
new SimpleElement(1, AggregateType.AddRaw), | ||
pet.IsDarkRaven() ? Stats.RavenLevel : Stats.HorseLevel, | ||
this.Attributes)).ToList(); |
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.
To trigger the related attributes upon level up. Before, you had to unequip-equip the item.
@@ -85,7 +85,7 @@ int Write() | |||
packet.Rotation = newPlayer.Rotation.ToPacketByte(); | |||
packet.HeroState = selectedCharacter.State.Convert(); | |||
packet.AttackSpeed = (ushort)(newPlayer.Attributes?[Stats.AttackSpeed] ?? 0); | |||
packet.MagicSpeed = (ushort)(newPlayer.Attributes?[Stats.AttackSpeed] ?? 0); // TODO: Implement MagicSpeed | |||
packet.MagicSpeed = (ushort)(newPlayer.Attributes?[Stats.MagicSpeed] ?? 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.
Leftover?
definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.MaximumCurseBaseDmg, Stats.Level, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentCurse)); | ||
definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeedAny, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentCurse)); | ||
definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.ExcellentWizTwoPercentInc, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentCurse)); | ||
definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.ExcellentWizBaseDmg, Stats.TotalLevel, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentCurse)); |
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 not used. Just to keep up to date.
@@ -253,7 +264,7 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber | |||
item.MaximumItemLevel = isAmmunition ? (byte)0 : Constants.MaximumItemLevel; | |||
item.DropsFromMonsters = dropsFromMonsters; | |||
item.SetGuid(item.Group, item.Number); | |||
if (slot == 0 && knightClass > 0 && width == 1) | |||
if (slot == 0 && (knightClass > 0 || magicGladiatorClass > 0) && width == 1) |
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.
MG can wield a staff on RH too! 😃
item.BasePowerUpAttributes.Add(maxDamagePowerUp); | ||
|
||
var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeed, attackSpeed, AggregateType.AddRaw); | ||
var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeedByWeapon, attackSpeed, AggregateType.AddRaw); |
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 this OK for 0.95d?
{ | ||
if (ragefighterClass == 0 || number < 3) | ||
if (ragefighterClass == 0 || number < 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.
Not relevant. Just for accuracy (only numbers 0 and 1 can be equipped by RF).
@@ -60,12 +60,13 @@ internal class SkillsInitializer : SkillsInitializerBase | |||
{ SkillNumber.Heal, MagicEffectNumber.Heal }, | |||
{ SkillNumber.Recovery, MagicEffectNumber.ShieldRecover }, | |||
{ SkillNumber.InfinityArrow, MagicEffectNumber.InfiniteArrow }, | |||
{ SkillNumber.InfinityArrowStr, MagicEffectNumber.InfiniteArrow }, |
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 removed because it was unnecessary, as the magic effect is inherited from the replaced skill.
@@ -758,24 +762,25 @@ private void InitializeMasterSkillData() | |||
// DL | |||
this.AddMasterSkillDefinition(SkillNumber.FireBurstStreng, SkillNumber.FireBurst, SkillNumber.Undefined, 2, 2, SkillNumber.FireBurst, 20, Formula502); | |||
this.AddMasterSkillDefinition(SkillNumber.ForceWaveStreng, SkillNumber.Force, SkillNumber.Undefined, 2, 2, SkillNumber.Force, 20, Formula632); | |||
this.AddMasterSkillDefinition((SkillNumber)5090, SkillNumber.Force, SkillNumber.Undefined, 2, 2, SkillNumber.ForceWave, 20, Formula632); |
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 one gets the damage from ForceWave. The one above gets it from Force.
if (isExcellentHit) | ||
if (damageType == DamageType.Physical) | ||
{ | ||
if (isExcellentHit) |
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.
For physical damage, an excellent hit is also a critical hit:
https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/ObjAttack.cpp#L3679
// double wield => 110% dmg (55% + 55%) | ||
dmg += dmg; | ||
/* There is an ancient set option critical damage subtraction here*/ | ||
} |
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.
{ | ||
dmg = (int)(dmg / 1.5); | ||
} | ||
} |
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.
classicPvpDuelDmgDec = 1; | ||
} | ||
|
||
if (isExcellentHit) |
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.
if (attacker.Attributes[Stats.IsTwoHandedWeaponEquipped] > 0) | ||
{ | ||
dmg += (int)(dmg * attacker.Attributes[Stats.TwoHandedWeaponDamageIncrease]); | ||
} |
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.
} | ||
else if (isCriticalHit) | ||
|
||
dmg += (int)attacker.Attributes[Stats.GreaterDamageBonus]; |
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.
Physical: https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/ObjAttack.cpp#L3814
Wizardry: https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/ObjAttack.cpp#L4202
Summoner: https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/ObjAttack.cpp#L4511
{ | ||
dmg = baseMinDamage; | ||
dmg -= (int)(dmg * attacker.Attributes[Stats.WeaknessPhysDmgDecrement]); // check if it's a mob attacking | ||
dmg += GetMasterSkillTreePhysicalPassiveDamageBonus(attacker, false); |
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.
bonusDamage = (int)(bonusDamage == 0 | ||
? attacker.Attributes[Stats.MaceBonusDamage] | ||
: (bonusDamage + attacker.Attributes[Stats.MaceBonusDamage]) / 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.
if (damageType == DamageType.Fenrir) | ||
{ | ||
classicPvpDuelDmgDec = 1; | ||
} |
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.
var defenseAttribute = defender.GetDefenseAttribute(attacker); | ||
var defense = (int)defender.Attributes[defenseAttribute]; | ||
dmg -= defense; | ||
dmg = (int)(dmg * 0.3); | ||
} |
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.
} | ||
|
||
dmg = Math.Max(dmg, 0); | ||
dmg -= (int)(dmg * defender.Attributes[Stats.ShieldSkillReceiveDecrement]); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 6, Stats.TotalStrength)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); |
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.
|
||
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsGloveWeaponEquipped, Stats.GloveWeaponBonusBaseDamage)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.SkillMultiplier, 0.001f, Stats.TotalEnergy)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.VitalitySkillMultiplier, 0.001f, Stats.TotalVitality)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseEnergy)); |
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.
|
||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(57, Stats.MaximumHealth)); | ||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(7, Stats.MaximumMana)); | ||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); | ||
|
||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.5f, Stats.SkillMultiplier)); |
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.
@@ -44,25 +57,27 @@ private CharacterClass CreateSummoner(CharacterClassNumber number, string name, | |||
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 18, true)); | |||
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 23, true)); | |||
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 70, false)); | |||
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 20, false)); | |||
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 40, false)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 10, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.TotalStrengthAndAgility, Stats.TotalAgility, Stats.TotalStrength, InputOperator.Add)); | ||
|
||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 3, Stats.TotalAgility)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 0.25f, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.1f, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.TotalAgility)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 0.6f, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.5f, Stats.BaseAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1.0f / 9, Stats.TotalEnergy)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1.0f / 4, Stats.TotalEnergy)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 7, Stats.TotalStrengthAndAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrengthAndAgility)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 7, Stats.TotalStrengthAndAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrengthAndAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(statsMinWizAndCurseBaseDmg, 1.0f / 9, Stats.TotalEnergy)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(statsMaxWizAndCurseBaseDmg, 1.0f / 4, Stats.TotalEnergy)); |
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.
result.AttributeCombinations.Add(this.CreateAttributeRelationship(berserkerHealthMultiplierDecrement, -0.1f, Stats.BerserkerHealthMultiplierFactor, InputOperator.Minimum)); // At least -10% HP | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(isBerserkerBuffed, 1, Stats.BerserkerMinPhysDmgBonus, InputOperator.Minimum)); | ||
result.AttributeCombinations.Add(this.CreateConditionalRelationship(berserkerHealthMultiplier, isBerserkerBuffed, berserkerHealthMultiplierDecrement)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, berserkerHealthMultiplier, aggregateType: AggregateType.Multiplicate)); |
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.
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, finalBerserkerManaMultiplier)); | ||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, berserkerHealthMultiplier)); | ||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerManaMultiplier)); | ||
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerHealthMultiplierFactor)); |
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.
These 0 values I found were necessary because otherwise the magic effect power ups would conflict and not always update.
|
||
this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); | ||
|
||
return result; |
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.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.MaximumPhysBaseDmg, ItemOptionDefinitionNumbers.PhysicalAttack)); | ||
this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.MaximumWizBaseDmg, ItemOptionDefinitionNumbers.WizardryAttack)); | ||
this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.PhysicalBaseDmg, ItemOptionDefinitionNumbers.PhysicalAttack)); | ||
this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.WizardryBaseDmg, ItemOptionDefinitionNumbers.WizardryAttack)); |
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.
: base((byte)CharacterClassNumber.DarkLord, (ushort)SkillNumber.FireBlast) | ||
{ | ||
} | ||
} |
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.
: base((byte)CharacterClassNumber.MagicGladiator, (ushort)SkillNumber.ManaRays) | ||
{ | ||
} | ||
} |
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.
: base((byte)CharacterClassNumber.DarkLord, (byte)ItemGroups.Swords, 1, 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.
: base((byte)CharacterClassNumber.MagicGladiator, (byte)ItemGroups.Swords, 1, 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.
maxDmgPerStrengthAndAgility.InputAttribute = Stats.TotalStrengthAndAgility.GetPersistent(this.GameConfiguration); | ||
maxDmgPerStrengthAndAgility.InputOperator = InputOperator.Multiply; | ||
maxDmgPerStrengthAndAgility.InputOperand = 1.0f / 30; | ||
maxPhysPowerUpDefinition.Boost.RelatedValues.Add(maxDmgPerStrengthAndAgility); |
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 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 split this into smaller, independent PRs, please? I have only looked at a very small part of the changes and can hardly process them all at once in my head 😂
So far, some changes are very good and some make the code very complicated (damage calc). I'm not sure if that's all neccessary. In the past I tried to keep it all as clean and simple as possible. For example, my goal wasn't to replicate the original code by 100 % if that blows up complexity to another level.
Also, the referenced sources are not original and of a higher season, so we cannot trust on formulas etc. of that alone.
/// <summary> | ||
/// Gets or sets the aggregate type with which the relationship should effect the target attribute. | ||
/// </summary> | ||
public AggregateType AggregateType { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the calculation stage at which the relationship should effect the target attribute. | ||
/// </summary> | ||
public byte Stage { get; set; } | ||
|
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.
Why are these needed? Which use cases do you try to solve with them?
|
||
/// <summary> | ||
/// The electric spike (DL) skill damage type. | ||
/// </summary> | ||
ElectricSpike = 6, | ||
|
||
/// <summary> | ||
/// The dark horse's earthshake skill damage type. | ||
/// </summary> | ||
Earthshake = 7, | ||
|
||
/// <summary> | ||
/// The chaotic diseier (DL) skill damage type. | ||
/// </summary> | ||
ChaoticDiseier = 8, | ||
|
||
/// <summary> | ||
/// The generic dark lord offensive skill damage type. | ||
/// </summary> | ||
/// <remarks>Any DL skill other than electric spike, chaotic diseier, and earthshake.</remarks> | ||
DarkLordGenericSkill = 9, | ||
|
||
/// <summary> | ||
/// The multishot (Elf) skill damage type. | ||
/// </summary> | ||
MultiShot = 10, |
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.
No sorry, these are not damage types
/// <summary> | ||
/// Gets the total strength and agility attribute definition. | ||
/// </summary> | ||
public static AttributeDefinition TotalStrengthAndAgility { get; } = new(new Guid("4DFA4E4A-D185-4BCE-952C-5E78A92DC4AF"), "Total Strength and Agility", string.Empty); |
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.
Unneeded Stat. You can add an AttributeRelationship for each Strength and Agility
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.
It is used on the src/Persistence/Initialization/Skills/BerserkerEffectInitializer.cs
|
||
// Not all character's skills get multiplied (e.g., elf's TripleShot and MultiShot), so default case should be empty. | ||
// Switch cases ordering kept close to source's for reference, with new season (NS) skills included. | ||
switch (skill.Skill?.Number) |
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.
Sorry, cannot accept that. I tried to prevent references to specific skills in the code as much as possible.
{ | ||
dmg = (int)(dmg * attacker.Attributes[Stats.TwoHandedWeaponDamageIncrease]); | ||
defender.Attributes[Stats.CurrentMana] -= soulBarrierManaToll; |
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 method shouldn't modify any attributes
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.HarmonyPhysBaseDmg, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.HarmonyPhysBaseDmg, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.SocketBaseMinDmgBonus, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.SocketBaseMaxDmgBonus, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.ExcellentPhysBaseDmg, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.ExcellentPhysBaseDmg, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.ExcellentPhysTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.ExcellentPhysTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 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.
Why all these new Stats?
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.
Refer to this comment and the Stat code docs near it. Because originally these are all added and multiplied on different stages.
In other words, (((A + B) * C) + D) * E)
will produce a different result than (A + B + D) * (C * E)
. (For reference, I documented this on src/AttributeSystem/IElement.cs.)
I wanted to emulate the original calculations, so this was the rationale for the introduction of stages. Another approach would be to add Stats add infinitum, but that would be even more confusing 😅. But I understand if this may not be acceptable to you.
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); | ||
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); |
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.
Why stage 4 and not 1?
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.
In the sources, the damage bonus from special item consumables is the last thing added (Stats.BaseDamageBonus here contains JackO'lanternWrath and CherryBlossomFlowerPetal power ups - I left it documented on the Stat docs).
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.0f / 6, Stats.TotalStrength)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 3, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); |
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 sure if your linked source is using the original formula here...
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalStrength)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalVitality)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalEnergy)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalLeadership)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseEnergy)); | ||
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseLeadership)); |
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.
Are you sure this is not based on the total values?
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.
/// <summary> | ||
/// Gets the mini robot transformation ring option number. | ||
/// </summary> | ||
public static short MiniRobotTransformationRing => 0x76; |
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.
Never seen this before in season 6
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 very well be so, I only added because there was already code in src/Persistence/Initialization/VersionSeasonSix/Items/Jewelery.cs for these.
manaMultiplier.InputAttribute = Stats.BaseEnergy.GetPersistent(this.GameConfiguration); // BaseEnergy and not TotalEnergy | ||
manaMultiplier.InputOperator = InputOperator.Multiply; | ||
manaMultiplier.InputOperand = 1f / 3000f; | ||
manaPowerUpDefinition.Boost.RelatedValues.Add(manaMultiplier); |
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.
https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/Template/zGameServer/Data/Skill/BuffSkillEffect.xml#L93
https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/BuffEffect.cpp#L84
https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/ObjUseSkill.cpp#L5160
healthMultiplier.InputAttribute = Stats.BaseEnergy.GetPersistent(this.GameConfiguration); // BaseEnergy and not TotalEnergy | ||
healthMultiplier.InputOperator = InputOperator.Multiply; | ||
healthMultiplier.InputOperand = 1f / 6000f; | ||
healthPowerUpDefinition.Boost.RelatedValues.Add(healthMultiplier); |
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.
|
||
// Always a 50 % damage reduction | ||
powerUpDefinition.Boost = this.Context.CreateNew<PowerUpDefinitionValue>(); | ||
powerUpDefinition.Boost.ConstantValue.Value = 0.50f; | ||
powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; | ||
powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; | ||
} |
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.
powerUpDefinition.Boost = this.Context.CreateNew<PowerUpDefinitionValue>(); | ||
powerUpDefinition.Boost.ConstantValue.Value = 2f; | ||
powerUpDefinition.Boost.ConstantValue.Value = 1f; |
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.
@@ -35,7 +35,7 @@ public override void Initialize() | |||
magicEffect.SendDuration = true; | |||
magicEffect.StopByDeath = true; | |||
magicEffect.Duration = this.Context.CreateNew<PowerUpDefinitionValue>(); | |||
magicEffect.Duration.ConstantValue.Value = (float)TimeSpan.FromHours(8).TotalSeconds; | |||
magicEffect.Duration.ConstantValue.Value = 600; |
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.
decDmgPowerUpDefinition.Boost.ConstantValue.Value = 0.05f; | ||
decDmgPowerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; | ||
} | ||
} |
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.
https://github.com/kyleruss/emu-server/blob/202856a74c905c203b9b2795fd161f564ca8b257/GameServer/Source/ObjUseSkill.cpp#L6214
However, this depends on a chance (10%). I have noticed more RF and Summoner skills also have effects that depend on a chance rate. To be addressed later!
/// The weakness effect, which decreases inflicted damage. | ||
/// </summary> | ||
Weakness = 0x4C, | ||
|
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 berserker buff effect. | ||
/// </summary> | ||
Berserker = 0x51, | ||
|
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.
To do:
Dev changes:
Stage
property to allow for more flexibility and better mimic original calculations. The idea is to group elements by stages within the sameComposableAttribute
, thereby allowing sum and multiplication on different levels, whereas before, all sum/multiplication values were bundled together (a single stage). See here and here.InputOperator.Min
andInputOperator.Max
forAttributeRelationshipElement
.MasterSkillDefinition.ExtendsDuration
to flag master skills which formula applies to a duration increase (there are several such skills, like Soul Barrier Proficiency).Stats.AttackSpeedAny
as a bucket to feed bothStats.AttackSpeed
andStats.MagicSpeed
for simplification.Features:
Fixes: