diff --git a/HouseRules.Essentials/FreeActionPointsOnCritRule.cs b/HouseRules.Essentials/FreeActionPointsOnCritRule.cs new file mode 100644 index 00000000..12a2b805 --- /dev/null +++ b/HouseRules.Essentials/FreeActionPointsOnCritRule.cs @@ -0,0 +1,69 @@ +namespace HouseRules.Essentials.Rules +{ + using System.Collections.Generic; + using Boardgame.BoardEntities; + using Boardgame.BoardEntities.Abilities; + using DataKeys; + using HarmonyLib; + using HouseRules.Core.Types; + + public sealed class FreeActionPointsOnCritRule : Rule, IConfigWritable>, IPatchable, IMultiplayerSafe + { + public override string Description => "Some Heroes restore an Action Point by getting critical hits."; + + private static List _globalAdjustments; + private static bool _isActivated; + + private readonly List _adjustments; + + public FreeActionPointsOnCritRule(List adjustments) + { + _adjustments = adjustments; + } + + public List GetConfigObject() => _adjustments; + + protected override void OnActivate(Context context) + { + _globalAdjustments = _adjustments; + _isActivated = true; + } + + protected override void OnDeactivate(Context context) => _isActivated = false; + + private static void Patch(Harmony harmony) + { + harmony.Patch( + original: AccessTools.Method(typeof(Ability), "GenerateAttackDamage"), + postfix: new HarmonyMethod( + typeof(FreeActionPointsOnCritRule), + nameof(Ability_GenerateAttackDamage_Postfix))); + } + + private static void Ability_GenerateAttackDamage_Postfix(Piece source, Dice.Outcome diceResult) + { + if (!_isActivated) + { + return; + } + + if (!source.IsPlayer()) + { + return; + } + + if (diceResult != Dice.Outcome.Crit) + { + return; + } + + if (!_globalAdjustments.Contains(source.boardPieceId)) + { + return; + } + + source.effectSink.TryGetStat(Stats.Type.ActionPoints, out int currentAP); + source.effectSink.TrySetStatBaseValue(Stats.Type.ActionPoints, currentAP + 1); + } + } +} diff --git a/HouseRules.Essentials/HouseRulesEssentialsBase.cs b/HouseRules.Essentials/HouseRulesEssentialsBase.cs index b88dce9e..d0916e7d 100644 --- a/HouseRules.Essentials/HouseRulesEssentialsBase.cs +++ b/HouseRules.Essentials/HouseRulesEssentialsBase.cs @@ -77,6 +77,7 @@ private static void RegisterRuleTypes() HR.Rulebook.Register(typeof(EnemyHealthScaledRule)); HR.Rulebook.Register(typeof(EnemyRespawnDisabledRule)); HR.Rulebook.Register(typeof(FreeAbilityOnCritRule)); + HR.Rulebook.Register(typeof(FreeActionPointsOnCritRule)); HR.Rulebook.Register(typeof(GoldPickedUpMultipliedRule)); HR.Rulebook.Register(typeof(LampTypesOverriddenRule)); HR.Rulebook.Register(typeof(LevelExitLockedUntilAllEnemiesDefeatedRule)); diff --git a/HouseRules.Essentials/README.md b/HouseRules.Essentials/README.md index 56518225..9dfb2446 100644 --- a/HouseRules.Essentials/README.md +++ b/HouseRules.Essentials/README.md @@ -461,10 +461,27 @@ The [Settings Reference](../docs/SettingsReference.md) contains lists of all dif "HeroSorcerer": "Fireball", "HeroGuardian": "Bone", "HeroRogue": "PoisonGasGrenade" - } - }, + } ``` +#### __FreeActionPointsOnCrit__: A Critical Hit rewards you with a free action point. + - Whenever you score a critical hit, the listed player pieces will gain one action point. + - Allows configuration of different abilities on a per-hero basis. + - To configure: + - Specify a Dictionary of [BoardPieceIds](../docs/SettingsReference.md#boardpieceids). + + ###### _Example JSON config for FreeActionPointsOnCrit_ + + ```json + { + "Rule": "FreeActionPointsOnCrit", + "Config": [ + "HeroGuardian", + "HeroRogue" + ] + }, +``` + #### __GoldPickedUpMultiplied__: 💰Gold💰 picked up is multiplied - To configure: - Specify a decimal number representing how gold is multiplied.