-
-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4615 from SolastaMods/dev
1.5.97.9
- Loading branch information
Showing
385 changed files
with
2,845 additions
and
5,062 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Condition/&ConditionPathOfTheWildMagicBolsteringMagicRollDescription=You roll a d3 whenever making an attack roll or an ability check and add the number rolled to the d20 roll. | ||
Condition/&ConditionPathOfTheWildMagicBolsteringMagicRollTitle=Bolstering Magic: Roll | ||
Condition/&ConditionPathOfTheWildMagicBolsteringMagicSlotDescription=You gained one random spell slot between levels 1 and 3. | ||
Condition/&ConditionPathOfTheWildMagicBolsteringMagicSlotTitle=Bolstering Magic: Slot | ||
Feature/&FeaturePathOfTheWildMagicControlledSurgeDescription=Whenever you roll on the Wild Magic table, you can roll the die twice and choose which of the two effects to unleash. If you roll the same number on both dice, you can ignore the number and choose any effect on the table. | ||
Feature/&FeaturePathOfTheWildMagicControlledSurgeTitle=Controlled Surge | ||
Feature/&FeaturePathOfTheWildMagicUnstableBackslashDescription=Immediately after you take damage or fail a saving throw while raging, you can use your reaction to roll on the Wild Magic table and immediately produce the effect rolled. This effect replaces your current Wild Magic effect. | ||
Feature/&FeaturePathOfTheWildMagicUnstableBackslashTitle=Unstable Backslash | ||
Feature/&FeatureSetPathOfTheWildMagicWildSurgeDescription=When you enter your rage, roll on the Wild Magic table to determine the magical effect produced. If the effect requires a saving throw, the DC equals 8 + your proficiency bonus + your Constitution modifier. | ||
Feature/&FeatureSetPathOfTheWildMagicWildSurgeTitle=Wild Surge | ||
Feature/&PowerPathOfTheWildMagicBolsteringMagicDescription=As an action, you can touch one ally and confer one of the following benefits of your choice:\n• For 10 minutes, the creature can roll a d3 whenever making an attack roll or an ability check and add the number rolled to the d20 roll.\n• Roll a d3. The creature regains one expended spell slot, the level of which equals the number rolled. Once a creature receives this benefit, that creature can’t receive it again until after a long rest.\nYou can take this action a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest. | ||
Feature/&PowerPathOfTheWildMagicBolsteringMagicRollDescription=As an action, you can touch one ally and for 10 minutes, they can roll a d3 whenever making an attack roll or an ability check and add the number rolled to the d20 roll. | ||
Feature/&PowerPathOfTheWildMagicBolsteringMagicRollTitle=Bolstering Magic: Roll | ||
Feature/&PowerPathOfTheWildMagicBolsteringMagicSpellDescription=As an action, you can touch one ally and roll a d3. The creature regains one expended spell slot, the level of which equals the number rolled. Once a creature receives this benefit, that creature can’t receive it again until after a long rest. | ||
Feature/&PowerPathOfTheWildMagicBolsteringMagicSpellTitle=Bolstering Magic: Spell | ||
Feature/&PowerPathOfTheWildMagicBolsteringMagicTitle=Bolstering Magic | ||
Feature/&PowerPathOfTheWildMagicMagicAwarenessDescription=As an action, you can open your awareness to the presence of concentrated magic. Over the next minute, you know the location of any spell or magic item within 60 feet of you. | ||
Feature/&PowerPathOfTheWildMagicMagicAwarenessTitle=Magic Awareness | ||
Subclass/&PathOfTheWildMagicDescription=Many places in the multiverse abound with beauty, intense emotion, and rampant magic. the Feywild, the Upper Planes, and other realms of supernatural power radiate with such forces and can profoundly influence people. As folk of deep feeling, barbarians are especially susceptible to these wild influences, with some barbarians being transformed by the magic. These magic-suffused barbarians walk the Path of Wild Magic. Elf, tiefling, and aasimars often seek this path, eager to manifest the otherworldly magic of their ancestors. | ||
Subclass/&PathOfTheWildMagicTitle=Path of the Wild Magic | ||
Tooltip/&MustNotHaveBolsteringMagicSpell=Must not have Bolstering Magic slots |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
using System.Collections; | ||
using System.Linq; | ||
using JetBrains.Annotations; | ||
using SolastaUnfinishedBusiness.Api.GameExtensions; | ||
using SolastaUnfinishedBusiness.Behaviors.Specific; | ||
using SolastaUnfinishedBusiness.Builders; | ||
using SolastaUnfinishedBusiness.Builders.Features; | ||
using SolastaUnfinishedBusiness.Interfaces; | ||
using static RuleDefinitions; | ||
using static SolastaUnfinishedBusiness.Api.DatabaseHelper; | ||
|
||
namespace SolastaUnfinishedBusiness.Subclasses; | ||
|
||
[UsedImplicitly] | ||
public sealed class PathOfTheWildMagic //: AbstractSubclass | ||
{ | ||
private const string Name = "PathOfTheWildMagic"; | ||
|
||
public PathOfTheWildMagic() | ||
{ | ||
// Magic Awareness | ||
|
||
var powerMagicAwareness = FeatureDefinitionPowerBuilder | ||
.Create($"Power{Name}MagicAwareness") | ||
.SetGuiPresentation(Category.Feature, SpellDefinitions.DetectMagic) | ||
.SetUsesProficiencyBonus(ActivationTime.Action) | ||
.SetEffectDescription( | ||
EffectDescriptionBuilder | ||
.Create(SpellDefinitions.DetectMagic) | ||
.SetDurationData(DurationType.Minute, 1) | ||
.SetTargetingData(Side.Ally, RangeType.Self, 0, TargetType.Self, 0) | ||
.SetEffectForms( | ||
EffectFormBuilder | ||
.Create() | ||
.SetDivinationForm( | ||
DivinationForm.Type.RevealEntitiesBearingTags, | ||
[], [TagsDefinitions.Magical], 12) | ||
.Build(), | ||
EffectFormBuilder.ConditionForm(ConditionDefinitions.ConditionDetectMagicSight)) | ||
.Build()) | ||
.AddToDB(); | ||
|
||
// Wild Surge | ||
|
||
var featureSetWildSurge = FeatureDefinitionFeatureSetBuilder | ||
.Create($"FeatureSet{Name}WildSurge") | ||
.SetGuiPresentation(Category.Feature) | ||
.SetFeatureSet() | ||
.AddToDB(); | ||
|
||
// Bolstering Magic | ||
|
||
var powerBolsteringMagic = FeatureDefinitionPowerBuilder | ||
.Create($"Power{Name}BolsteringMagic") | ||
.SetGuiPresentation(Category.Feature) | ||
.SetUsesProficiencyBonus(ActivationTime.Action) | ||
.SetEffectDescription( | ||
EffectDescriptionBuilder | ||
.Create() | ||
.SetTargetingData(Side.Ally, RangeType.Touch, 0, TargetType.IndividualsUnique) | ||
.Build()) | ||
.AddToDB(); | ||
|
||
var conditionBolsteringMagicRoll = ConditionDefinitionBuilder | ||
.Create($"Condition{Name}BolsteringMagicRoll") | ||
.SetGuiPresentation(Category.Condition) | ||
.AddToDB(); | ||
|
||
conditionBolsteringMagicRoll.AddCustomSubFeatures( | ||
new CustomBehaviorBolsteringMagicRoll(conditionBolsteringMagicRoll)); | ||
|
||
var powerBolsteringMagicRoll = FeatureDefinitionPowerSharedPoolBuilder | ||
.Create($"Power{Name}BolsteringMagicRoll") | ||
.SetGuiPresentation(Category.Feature, hidden: true) | ||
.SetSharedPool(ActivationTime.Action, powerBolsteringMagic) | ||
.SetEffectDescription( | ||
EffectDescriptionBuilder | ||
.Create() | ||
.SetDurationData(DurationType.Minute, 10) | ||
.SetTargetingData(Side.Ally, RangeType.Touch, 0, TargetType.IndividualsUnique) | ||
.SetEffectForms(EffectFormBuilder.ConditionForm(conditionBolsteringMagicRoll)) | ||
.Build()) | ||
.AddToDB(); | ||
|
||
var db = DatabaseRepository.GetDatabase<FeatureDefinitionMagicAffinity>(); | ||
var conditions = new ConditionDefinition[3]; | ||
|
||
for (var i = 1; i <= 3; i++) | ||
{ | ||
conditions[i - 1] = ConditionDefinitionBuilder | ||
.Create($"Condition{Name}BolsteringMagicSlot{i}") | ||
.SetGuiPresentation($"Condition{Name}BolsteringMagicSlot", Category.Condition) | ||
.SetSilent(Silent.WhenRemoved) | ||
.SetFeatures(db.GetElement($"MagicAffinityAdditionalSpellSlot{i}")) | ||
.AddToDB(); | ||
} | ||
|
||
var powerBolsteringMagicSpell = FeatureDefinitionPowerSharedPoolBuilder | ||
.Create($"Power{Name}BolsteringMagicSpell") | ||
.SetGuiPresentation(Category.Feature, hidden: true) | ||
.SetSharedPool(ActivationTime.Action, powerBolsteringMagic) | ||
.SetEffectDescription( | ||
EffectDescriptionBuilder | ||
.Create() | ||
.SetDurationData(DurationType.UntilLongRest) | ||
.SetTargetingData(Side.Ally, RangeType.Touch, 0, TargetType.IndividualsUnique) | ||
.SetEffectForms( | ||
EffectFormBuilder | ||
.Create() | ||
.SetConditionForm( | ||
conditions[0], | ||
ConditionForm.ConditionOperation.AddRandom, | ||
false, false, conditions) | ||
.Build()) | ||
.Build()) | ||
.AddCustomSubFeatures(new FilterTargetingCharacterBolsteringMagicSpell(conditions)) | ||
.AddToDB(); | ||
|
||
PowerBundle.RegisterPowerBundle(powerBolsteringMagic, false, | ||
powerBolsteringMagicRoll, powerBolsteringMagicSpell); | ||
|
||
var featureSetBolsteringMagic = FeatureDefinitionFeatureSetBuilder | ||
.Create($"FeatureSet{Name}BolsteringMagic") | ||
.SetGuiPresentation($"Power{Name}BolsteringMagic", Category.Feature) | ||
.SetFeatureSet(powerBolsteringMagic, powerBolsteringMagicRoll, powerBolsteringMagicSpell) | ||
.AddToDB(); | ||
|
||
// Unstable Backslash | ||
|
||
var featureUnstableBackslash = FeatureDefinitionBuilder | ||
.Create($"Feature{Name}UnstableBackslash") | ||
.SetGuiPresentation(Category.Feature) | ||
.AddToDB(); | ||
|
||
// Controlled Surge | ||
|
||
var featureControlledSurge = FeatureDefinitionBuilder | ||
.Create($"Feature{Name}ControlledSurge") | ||
.SetGuiPresentation(Category.Feature) | ||
.AddToDB(); | ||
|
||
// MAIN | ||
|
||
Subclass = CharacterSubclassDefinitionBuilder | ||
.Create(Name) | ||
.SetGuiPresentation(Category.Subclass, CharacterSubclassDefinitions.PathBerserker) | ||
.AddFeaturesAtLevel(3, powerMagicAwareness, featureSetWildSurge) | ||
.AddFeaturesAtLevel(6, featureSetBolsteringMagic) | ||
.AddFeaturesAtLevel(10, featureUnstableBackslash) | ||
.AddFeaturesAtLevel(14, featureControlledSurge) | ||
.AddToDB(); | ||
} | ||
|
||
internal CharacterClassDefinition Klass => CharacterClassDefinitions.Barbarian; | ||
|
||
internal CharacterSubclassDefinition Subclass { get; } | ||
|
||
internal FeatureDefinitionSubclassChoice SubclassChoice => | ||
FeatureDefinitionSubclassChoices.SubclassChoiceBarbarianPrimalPath; | ||
|
||
// ReSharper disable once UnassignedGetOnlyAutoProperty | ||
internal DeityDefinition DeityDefinition { get; } | ||
|
||
private sealed class CustomBehaviorBolsteringMagicRoll( | ||
ConditionDefinition conditionBolsteringMagicRoll) : ITryAlterOutcomeAttack, ITryAlterOutcomeAttributeCheck | ||
{ | ||
public IEnumerator OnTryAlterOutcomeAttack( | ||
GameLocationBattleManager instance, | ||
CharacterAction action, | ||
GameLocationCharacter attacker, | ||
GameLocationCharacter defender, | ||
GameLocationCharacter helper, | ||
ActionModifier actionModifier) | ||
{ | ||
if (helper != defender) | ||
{ | ||
yield break; | ||
} | ||
|
||
var advantageType = actionModifier.AttackAdvantageTrend switch | ||
{ | ||
> 0 => AdvantageType.Advantage, | ||
< 0 => AdvantageType.Disadvantage, | ||
_ => AdvantageType.None | ||
}; | ||
|
||
var roll = RollDie(DieType.D3, advantageType, out _, out _); | ||
|
||
actionModifier.AttacktoHitTrends.Add( | ||
new TrendInfo(roll, FeatureSourceType.CharacterFeature, conditionBolsteringMagicRoll.Name, | ||
conditionBolsteringMagicRoll)); | ||
} | ||
|
||
public IEnumerator OnTryAlterAttributeCheck( | ||
GameLocationBattleManager battleManager, | ||
AbilityCheckData abilityCheckData, | ||
GameLocationCharacter defender, | ||
GameLocationCharacter helper, | ||
ActionModifier abilityCheckModifier) | ||
{ | ||
if (helper != defender || | ||
abilityCheckData.AbilityCheckRollOutcome != RollOutcome.Failure) | ||
{ | ||
yield break; | ||
} | ||
} | ||
} | ||
|
||
private sealed class FilterTargetingCharacterBolsteringMagicSpell( | ||
params ConditionDefinition[] conditions) : IFilterTargetingCharacter | ||
{ | ||
private readonly string[] _conditionNames = conditions.Select(x => x.Name).ToArray(); | ||
|
||
public bool EnforceFullSelection => false; | ||
|
||
public bool IsValid(CursorLocationSelectTarget __instance, GameLocationCharacter target) | ||
{ | ||
var isValid = !target.RulesetActor.HasAnyConditionOfType(_conditionNames); | ||
|
||
if (isValid) | ||
{ | ||
return true; | ||
} | ||
|
||
__instance.actionModifier.FailureFlags.Add("Tooltip/&MustNotHaveBolsteringMagicSpell"); | ||
|
||
return false; | ||
} | ||
} | ||
} |
Oops, something went wrong.