diff --git a/SWLOR.Game.Server/Feature/AbilityDefinition/OneHanded/ForceLeapAbilityDefinition.cs b/SWLOR.Game.Server/Feature/AbilityDefinition/Force/ForceLeapAbilityDefinition.cs similarity index 90% rename from SWLOR.Game.Server/Feature/AbilityDefinition/OneHanded/ForceLeapAbilityDefinition.cs rename to SWLOR.Game.Server/Feature/AbilityDefinition/Force/ForceLeapAbilityDefinition.cs index 3441463a1b..2c0308b7a1 100644 --- a/SWLOR.Game.Server/Feature/AbilityDefinition/OneHanded/ForceLeapAbilityDefinition.cs +++ b/SWLOR.Game.Server/Feature/AbilityDefinition/Force/ForceLeapAbilityDefinition.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using SWLOR.Game.Server.Service; using SWLOR.Game.Server.Service.AbilityService; using SWLOR.Game.Server.Service.CombatService; @@ -7,7 +7,7 @@ using SWLOR.NWN.API.Engine; using SWLOR.NWN.API.NWScript.Enum; -namespace SWLOR.Game.Server.Feature.AbilityDefinition.OneHanded +namespace SWLOR.Game.Server.Feature.AbilityDefinition.Force { public class ForceLeapAbilityDefinition : IAbilityListDefinition { @@ -26,9 +26,10 @@ private static string Validation(uint activator, uint target, int level, Locatio var weapon = GetItemInSlot(InventorySlot.RightHand, activator); var rightHandType = GetBaseItemType(weapon); - if (!Item.LightsaberBaseItemTypes.Contains(rightHandType)) + if (!Item.OneHandedMeleeItemTypes.Contains(rightHandType) && + !Item.TwoHandedMeleeItemTypes.Contains(rightHandType)) { - return "A lightsaber must be equipped in your right hand to use this ability."; + return "A melee weapon must be equipped in your right hand to use this ability."; } if (GetDistanceBetween(activator, target) < 8) @@ -59,7 +60,7 @@ private static void ImpactAction(uint activator, uint target, int level, Locatio break; } - dmg += Combat.GetAbilityDamageBonus(activator, SkillType.OneHanded); + dmg += Combat.GetAbilityDamageBonus(activator, SkillType.Force); const float Delay = 1.2f; ClearAllActions(); @@ -69,8 +70,8 @@ private static void ImpactAction(uint activator, uint target, int level, Locatio ActionPlayAnimation(Animation.ForceLeap, 2.0f, 1.0f); SetCommandable(false, activator); }); - - CombatPoint.AddCombatPoint(activator, target, SkillType.OneHanded, 3); + + CombatPoint.AddCombatPoint(activator, target, SkillType.Force, 3); var stat = AbilityType.Perception; if (Ability.IsAbilityToggled(activator, AbilityToggleType.StrongStyleLightsaber)) @@ -79,19 +80,19 @@ private static void ImpactAction(uint activator, uint target, int level, Locatio } var attackerStat = Combat.GetPerkAdjustedAbilityScore(activator); - var attack = Stat.GetAttack(activator, stat, SkillType.OneHanded); + var attack = Stat.GetAttack(activator, stat, SkillType.Force); var defense = Stat.GetDefense(target, CombatDamageType.Physical, AbilityType.Vitality); var defenderStat = GetAbilityScore(target, AbilityType.Vitality); var damage = Combat.CalculateDamage( attack, - dmg, - attackerStat, - defense, - defenderStat, + dmg, + attackerStat, + defense, + defenderStat, 0); var weapon = GetItemInSlot(InventorySlot.RightHand, activator); var rightHandBaseItemType = GetBaseItemType(weapon); - + DelayCommand(Delay, () => { const float Duration = 2f; @@ -122,7 +123,7 @@ private static void ForceLeap1(AbilityBuilder builder) .Level(1) .HasRecastDelay(RecastGroup.ForceLeap, 30f) .HasActivationDelay(0.5f) - .RequirementStamina(3) + .RequirementFP(3) .HasMaxRange(20f) .IsCastedAbility() .IsHostileAbility() @@ -137,7 +138,7 @@ private static void ForceLeap2(AbilityBuilder builder) .Name("Force Leap II") .Level(2) .HasRecastDelay(RecastGroup.ForceLeap, 30f) - .RequirementStamina(4) + .RequirementFP(4) .HasActivationDelay(0.5f) .HasMaxRange(20f) .IsCastedAbility() @@ -153,7 +154,7 @@ private static void ForceLeap3(AbilityBuilder builder) .Name("Force Leap III") .Level(3) .HasRecastDelay(RecastGroup.ForceLeap, 30f) - .RequirementStamina(5) + .RequirementFP(5) .HasActivationDelay(0.5f) .HasMaxRange(20f) .IsCastedAbility() @@ -164,4 +165,4 @@ private static void ForceLeap3(AbilityBuilder builder) .HasImpactAction(ImpactAction); } } -} \ No newline at end of file +} diff --git a/SWLOR.Game.Server/Feature/AbilityDefinition/OneHanded/PommelStrikeAbilityDefinition.cs b/SWLOR.Game.Server/Feature/AbilityDefinition/OneHanded/PommelStrikeAbilityDefinition.cs new file mode 100644 index 0000000000..c36b3ef843 --- /dev/null +++ b/SWLOR.Game.Server/Feature/AbilityDefinition/OneHanded/PommelStrikeAbilityDefinition.cs @@ -0,0 +1,135 @@ +using System.Collections.Generic; +using SWLOR.Game.Server.Service; +using SWLOR.Game.Server.Service.AbilityService; +using SWLOR.Game.Server.Service.CombatService; +using SWLOR.Game.Server.Service.PerkService; +using SWLOR.Game.Server.Service.SkillService; +using SWLOR.NWN.API.Engine; +using SWLOR.NWN.API.NWScript.Enum; + +namespace SWLOR.Game.Server.Feature.AbilityDefinition.OneHanded +{ + public class PommelStrikeAbilityDefinition : IAbilityListDefinition + { + public Dictionary BuildAbilities() + { + var builder = new AbilityBuilder(); + PommelStrike1(builder); + PommelStrike2(builder); + PommelStrike3(builder); + + return builder.Build(); + } + + private static string Validation(uint activator, uint target, int level, Location targetLocation) + { + var weapon = GetItemInSlot(InventorySlot.RightHand, activator); + var rightHandType = GetBaseItemType(weapon); + + if (Item.LightsaberBaseItemTypes.Contains(rightHandType)) + { + return string.Empty; + } + else + return "A lightsaber must be equipped in your right hand to use this ability."; + } + + private static void ImpactAction(uint activator, uint target, int level, Location targetLocation) + { + int dmg; + const float Duration = 6f; + + switch (level) + { + default: + case 1: + dmg = 6; + break; + case 2: + dmg = 12; + break; + case 3: + dmg = 24; + break; + } + + dmg += Combat.GetAbilityDamageBonus(activator, SkillType.OneHanded); + + CombatPoint.AddCombatPoint(activator, target, SkillType.OneHanded, 3); + + var stat = AbilityType.Perception; + if (Ability.IsAbilityToggled(activator, AbilityToggleType.StrongStyleLightsaber)) + { + stat = AbilityType.Might; + } + + var attackerStat = Combat.GetPerkAdjustedAbilityScore(activator); + var attack = Stat.GetAttack(activator, stat, SkillType.OneHanded); + var defense = Stat.GetDefense(target, CombatDamageType.Physical, AbilityType.Vitality); + var defenderStat = GetAbilityScore(target, AbilityType.Vitality); + var damage = Combat.CalculateDamage(attack, dmg, attackerStat, defense, defenderStat, 0); + + ApplyEffectToObject(DurationType.Instant, EffectDamage(damage, DamageType.Slashing), target); + + // DC calculation: 15 + PER/2 for daze + var dc = 15 + (GetAbilityModifier(AbilityType.Perception, activator) / 2); + dc = Combat.CalculateSavingThrowDC(activator, SavingThrow.Will, dc); + var checkResult = WillSave(target, dc, SavingThrowType.None, activator); + if (checkResult == SavingThrowResultType.Failed) + { + ApplyEffectToObject(DurationType.Temporary, EffectDazed(), target, Duration); + Ability.ApplyTemporaryImmunity(target, Duration, ImmunityType.Dazed); + } + + AssignCommand(activator, () => ActionPlayAnimation(Animation.RiotBlade)); + + Enmity.ModifyEnmity(activator, target, 100 * level + damage); + } + + private static void PommelStrike1(AbilityBuilder builder) + { + builder.Create(FeatType.PommelStrike1, PerkType.PommelStrike) + .Name("Pommel Strike I") + .Level(1) + .HasRecastDelay(RecastGroup.PommelStrike, 20f) + .RequirementStamina(4) + .HasActivationDelay(0.5f) + .IsCastedAbility() + .IsHostileAbility() + .UnaffectedByHeavyArmor() + .BreaksStealth() + .HasCustomValidation(Validation) + .HasImpactAction(ImpactAction); + } + private static void PommelStrike2(AbilityBuilder builder) + { + builder.Create(FeatType.PommelStrike2, PerkType.PommelStrike) + .Name("Pommel Strike II") + .Level(2) + .HasRecastDelay(RecastGroup.PommelStrike, 20f) + .RequirementStamina(6) + .HasActivationDelay(0.5f) + .IsCastedAbility() + .IsHostileAbility() + .UnaffectedByHeavyArmor() + .BreaksStealth() + .HasCustomValidation(Validation) + .HasImpactAction(ImpactAction); + } + private static void PommelStrike3(AbilityBuilder builder) + { + builder.Create(FeatType.PommelStrike3, PerkType.PommelStrike) + .Name("Pommel Strike III") + .Level(3) + .HasRecastDelay(RecastGroup.PommelStrike, 20f) + .RequirementStamina(8) + .HasActivationDelay(0.5f) + .IsCastedAbility() + .IsHostileAbility() + .UnaffectedByHeavyArmor() + .BreaksStealth() + .HasCustomValidation(Validation) + .HasImpactAction(ImpactAction); + } + } +} diff --git a/SWLOR.Game.Server/Feature/AbilityDefinition/TwoHanded/HardSlashAbilityDefinition.cs b/SWLOR.Game.Server/Feature/AbilityDefinition/TwoHanded/HardSlashAbilityDefinition.cs index a743ec9a05..b85927494b 100644 --- a/SWLOR.Game.Server/Feature/AbilityDefinition/TwoHanded/HardSlashAbilityDefinition.cs +++ b/SWLOR.Game.Server/Feature/AbilityDefinition/TwoHanded/HardSlashAbilityDefinition.cs @@ -121,4 +121,4 @@ private static void HardSlash3(AbilityBuilder builder) .HasImpactAction(ImpactAction); } } -} \ No newline at end of file +} diff --git a/SWLOR.Game.Server/Feature/PerkDefinition/ForcePerkDefinition.cs b/SWLOR.Game.Server/Feature/PerkDefinition/ForcePerkDefinition.cs index 901708b017..78ceb17761 100644 --- a/SWLOR.Game.Server/Feature/PerkDefinition/ForcePerkDefinition.cs +++ b/SWLOR.Game.Server/Feature/PerkDefinition/ForcePerkDefinition.cs @@ -33,6 +33,7 @@ public Dictionary BuildPerks() CreepingTerror(); ForceRage(); ThrowRock(); + ForceLeap(); ForceInspiration(); return _builder.Build(); @@ -112,6 +113,33 @@ private void ThrowRock() .GrantsFeat(FeatType.ThrowRock5); } + private void ForceLeap() + { + _builder.Create(PerkCategoryType.ForceUniversal, PerkType.ForceLeap) + .Name("Force Leap") + + .AddPerkLevel() + .Description("Leap to a distant target instantly, inflicting 8 DMG and stunning for 2 seconds.") + .Price(3) + .RequirementSkill(SkillType.Force, 15) + .RequirementCharacterType(CharacterType.ForceSensitive) + .GrantsFeat(FeatType.ForceLeap1) + + .AddPerkLevel() + .Description("Leap to a distant target instantly, inflicting 15 DMG and stunning for 2 seconds.") + .Price(3) + .RequirementSkill(SkillType.Force, 30) + .RequirementCharacterType(CharacterType.ForceSensitive) + .GrantsFeat(FeatType.ForceLeap2) + + .AddPerkLevel() + .Description("Leap to a distant target instantly, inflicting 23 DMG and stunning for 2 seconds.") + .Price(3) + .RequirementSkill(SkillType.Force, 45) + .RequirementCharacterType(CharacterType.ForceSensitive) + .GrantsFeat(FeatType.ForceLeap3); + } + private void BurstOfSpeed() { _builder.Create(PerkCategoryType.ForceUniversal, PerkType.BurstOfSpeed) diff --git a/SWLOR.Game.Server/Feature/PerkDefinition/OneHandedPerkDefinition.cs b/SWLOR.Game.Server/Feature/PerkDefinition/OneHandedPerkDefinition.cs index d982a511ac..cf481b89cc 100644 --- a/SWLOR.Game.Server/Feature/PerkDefinition/OneHandedPerkDefinition.cs +++ b/SWLOR.Game.Server/Feature/PerkDefinition/OneHandedPerkDefinition.cs @@ -34,7 +34,6 @@ public Dictionary BuildPerks() ImprovedCriticalLightsabers(); LightsaberProficiency(); LightsaberMastery(); - ForceLeap(); SaberStrike(); ImprovedTwoWeaponFighting(); StrongStyleLightsaber(); @@ -46,6 +45,7 @@ public Dictionary BuildPerks() ShieldResistance(); Alacrity(); Clarity(); + PommelStrike(); return _builder.Build(); } @@ -808,32 +808,7 @@ private void LightsaberMastery() .GrantsFeat(FeatType.LightsaberMastery2); } - private void ForceLeap() - { - _builder.Create(PerkCategoryType.OneHandedLightsaber, PerkType.ForceLeap) - .Name("Force Leap") - - .AddPerkLevel() - .Description("Leap to a distant target instantly, inflicting 8 DMG and stunning for 2 seconds.") - .Price(3) - .RequirementSkill(SkillType.OneHanded, 15) - .RequirementCharacterType(CharacterType.ForceSensitive) - .GrantsFeat(FeatType.ForceLeap1) - .AddPerkLevel() - .Description("Leap to a distant target instantly, inflicting 15 DMG and stunning for 2 seconds.") - .Price(3) - .RequirementSkill(SkillType.OneHanded, 30) - .RequirementCharacterType(CharacterType.ForceSensitive) - .GrantsFeat(FeatType.ForceLeap2) - - .AddPerkLevel() - .Description("Leap to a distant target instantly, inflicting 23 DMG and stunning for 2 seconds.") - .Price(3) - .RequirementSkill(SkillType.OneHanded, 45) - .RequirementCharacterType(CharacterType.ForceSensitive) - .GrantsFeat(FeatType.ForceLeap3); - } private void SaberStrike() { @@ -894,5 +869,37 @@ private void StrongStyleLightsaber() .Price(1) .GrantsFeat(FeatType.StrongStyleLightsaber); } + + private void PommelStrike() + { + _builder.Create(PerkCategoryType.OneHandedLightsaber, PerkType.PommelStrike) + .Name("Pommel Strike") + + .AddPerkLevel() + .Description("Strike your enemy with the pommel of your saber, doing damage and dazing them.") + .Price(2) + .DroidAISlots(1) + .RequirementSkill(SkillType.OneHanded, 5) + .RequirementCharacterType(CharacterType.ForceSensitive) + .GrantsFeat(FeatType.PommelStrike1) + + .AddPerkLevel() + .Description("Strike your enemy with the pommel of your saber, doing damage and dazing them.") + .Price(3) + .DroidAISlots(2) + .RequirementSkill(SkillType.OneHanded, 20) + .RequirementCharacterType(CharacterType.ForceSensitive) + .GrantsFeat(FeatType.PommelStrike2) + + .AddPerkLevel() + .Description("Strike your enemy with the pommel of your saber, doing damage and dazing them.") + .Price(3) + .DroidAISlots(3) + .RequirementSkill(SkillType.OneHanded, 35) + .RequirementCharacterType(CharacterType.ForceSensitive) + .GrantsFeat(FeatType.PommelStrike3); + } + } } + diff --git a/SWLOR.Game.Server/Service/AbilityService/RecastGroup.cs b/SWLOR.Game.Server/Service/AbilityService/RecastGroup.cs index 6ec71cfdcc..665a4f8b9d 100644 --- a/SWLOR.Game.Server/Service/AbilityService/RecastGroup.cs +++ b/SWLOR.Game.Server/Service/AbilityService/RecastGroup.cs @@ -257,6 +257,8 @@ public enum RecastGroup ForceRestore = 124, [RecastGroup("Adrenal Stim", "Adr. Stim", true)] AdrenalStim = 125, + [RecastGroup("Pommel Strike", "Pom. Strike", true)] + PommelStrike = 126, } public class RecastGroupAttribute: Attribute diff --git a/SWLOR.Game.Server/Service/PerkService/PerkType.cs b/SWLOR.Game.Server/Service/PerkService/PerkType.cs index 2c7902bd0b..2adfef01ac 100644 --- a/SWLOR.Game.Server/Service/PerkService/PerkType.cs +++ b/SWLOR.Game.Server/Service/PerkService/PerkType.cs @@ -304,5 +304,6 @@ public enum PerkType Research = 297, AdrenalStim = 298, ResearchProjects = 299, + PommelStrike = 300, } } diff --git a/SWLOR.Game.Server/Service/Stat.cs b/SWLOR.Game.Server/Service/Stat.cs index c1e5f82bb9..79564e2da6 100644 --- a/SWLOR.Game.Server/Service/Stat.cs +++ b/SWLOR.Game.Server/Service/Stat.cs @@ -1929,5 +1929,7 @@ public static void RestoreNPCStats(bool outOfCombatRegen) } } } + } } + diff --git a/SWLOR.NWN.API/NWScript/Enum/FeatType.cs b/SWLOR.NWN.API/NWScript/Enum/FeatType.cs index 1315e41baf..b1ba0d9209 100644 --- a/SWLOR.NWN.API/NWScript/Enum/FeatType.cs +++ b/SWLOR.NWN.API/NWScript/Enum/FeatType.cs @@ -1963,5 +1963,8 @@ public enum FeatType ForceLink3 = 1994, ZenMarksmanship = 1995, IntuitivePiloting = 1996, + PommelStrike1 = 1997, + PommelStrike2 = 1998, + PommelStrike3 = 1999, } } diff --git a/SWLOR_Haks b/SWLOR_Haks index 3628b22653..b7f3554ad4 160000 --- a/SWLOR_Haks +++ b/SWLOR_Haks @@ -1 +1 @@ -Subproject commit 3628b22653fa7df8419b12a3b1c7205298c58a16 +Subproject commit b7f3554ad48fe2d29f632bde39ed0c5260ae1907