├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── MicroscopicContentExpansion.sln ├── MicroscopicContentExpansion ├── .editorconfig ├── Assets │ ├── FeintingFlurry.png │ ├── FlyingKick.png │ ├── Ravener.png │ ├── Snake.png │ ├── StartossComet.png │ └── StartossStyle.png ├── BlueprintInitLoader.cs ├── Config │ ├── AddedContent.cs │ ├── AddedContent.json │ ├── Blueprints.json │ ├── Homebrew.cs │ └── Homebrew.json ├── Globals.cs ├── Info.json ├── Localization │ └── LocalizationPack.json ├── Main.cs ├── MicroscopicContentExpansion.csproj ├── ModLogic │ └── ModContextMCEBase.cs ├── NewComponents │ ├── AbilityCasterHasChosenWeaponFromGroup.cs │ ├── AbilityCasterHasSwiftAction.cs │ ├── AbilityCustomDimensionalAssault.cs │ ├── AbilityCustomDimensionalDervish.cs │ ├── AbilityCustomFlyingKick.cs │ ├── AbilityCustomStartossComet.cs │ ├── AddUnitFactDependingOnClassLevel.cs │ ├── AuraFeatureComponentWithWiden.cs │ ├── ContextActionArmorEnchantPoolMCE.cs │ ├── CriticalConfirmationUnarmed.cs │ ├── CrusadersFlurryUnlock.cs │ ├── HarmonyPatchActivator.cs │ ├── LegionBlessingApplySpell.cs │ ├── LegionBlessingSacrificeSpellAbility.cs │ ├── MasterClassLevelGetter.cs │ ├── RuleAttackWithWeaponChaining.cs │ ├── SnakeFangOnMissHandler.cs │ ├── SpecialAnimationMonkKick.cs │ └── StartossStyleComponent.cs ├── NewContent │ ├── AnimalCompanions │ │ ├── NightmareAnimalCompanion.cs │ │ └── NightmareMountOffsetPatch.cs │ ├── AntipaladinFeatures │ │ ├── AntipaladinAlignmentRestriction.cs │ │ ├── AntipaladinSpellbook.cs │ │ ├── AuraofCowardice.cs │ │ ├── AuraofDepravity.cs │ │ ├── AuraofDespair.cs │ │ ├── AuraofSin.cs │ │ ├── AuraofVengeance.cs │ │ ├── ChannelNegativeEnergy.cs │ │ ├── Cruelties.cs │ │ ├── FiendishBoon.cs │ │ ├── PlagueBringer.cs │ │ ├── SmiteGood.cs │ │ ├── TipoftheSpear.cs │ │ ├── TouchofCorruption.cs │ │ ├── UnholyChampion.cs │ │ └── UnholyResilience.cs │ ├── Archetypes │ │ ├── DreadVanguard.cs │ │ ├── DreadVanguardFeatures │ │ │ ├── BeaconOfEvil.cs │ │ │ ├── BeaconOfEvil12.cs │ │ │ ├── BeaconOfEvil16.cs │ │ │ ├── BeaconOfEvil20.cs │ │ │ └── BeaconOfEvil8.cs │ │ ├── IronTyrant.cs │ │ ├── IronTyrantFeatures │ │ │ └── IronTyrantArmorBond.cs │ │ ├── KnightoftheSepulcher.cs │ │ ├── KnightoftheSepulcherFeatures │ │ │ ├── CloakoftheCrypt.cs │ │ │ ├── CryptLord.cs │ │ │ ├── FortitudeoftheCrypt.cs │ │ │ ├── SoulOftheCrypt.cs │ │ │ ├── TouchoftheCrypt.cs │ │ │ ├── UndyingChampion.cs │ │ │ ├── WeaponsofSin.cs │ │ │ └── WilloftheCrypt.cs │ │ ├── Tyrant.cs │ │ └── TyrantFeatures │ │ │ ├── DiabolicBoon.cs │ │ │ ├── TyrantAlignmentRestriction.cs │ │ │ └── TyrantSpellbook.cs │ ├── Classes │ │ ├── AntipaladinAdder.cs │ │ ├── CrusaderLegionBlessing.cs │ │ ├── DruidicHerbalism.cs │ │ ├── MonkDiamondResilience.cs │ │ ├── MonkFlawlessMind.cs │ │ ├── MonkStyleStrikeFlyingKick.cs │ │ └── MonkTimelessBody.cs │ ├── Feats │ │ ├── CrusadersFlurry.cs │ │ ├── DimenshionalDervish.cs │ │ ├── FeintingFlurry.cs │ │ ├── SnakeStyleChain.cs │ │ ├── StartossStyleChain.cs │ │ └── UnsanctionedKnowledge.cs │ └── Spells │ │ ├── BladeofDarkTriumph.cs │ │ ├── DeadlyJuggernaut.cs │ │ ├── KiLeech.cs │ │ ├── ProtectionFromChaosGood.cs │ │ ├── ProtectionFromLawGood.cs │ │ └── WidenAuras.cs ├── RebalancedContent │ ├── DragonbloodShifterArchetype │ │ ├── DragonbloodWingController.cs │ │ └── Dragonblooded.cs │ ├── MythicArmor │ │ ├── ArmorACAsDamage.cs │ │ └── MythicArmorFeatTweaks.cs │ └── MythicFeats │ │ └── MythicDodge.cs ├── UMMSettingsUI.cs └── Utils │ ├── ActionFlow.cs │ └── AuraUtils.cs ├── README.md └── Repository.json /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # Asset files 7 | #*.png 8 | 9 | # User-specific files 10 | *.rsuser 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Mono auto generated files 20 | mono_crash.* 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | [Ww][Ii][Nn]32/ 30 | [Aa][Rr][Mm]/ 31 | [Aa][Rr][Mm]64/ 32 | bld/ 33 | [Bb]in/ 34 | [Oo]bj/ 35 | [Ll]og/ 36 | [Ll]ogs/ 37 | [Ll]ib/ 38 | PublishOutput/ 39 | 40 | # Visual Studio 2015/2017 cache/options directory 41 | .vs/ 42 | # Uncomment if you have tasks that create the project's static files in wwwroot 43 | #wwwroot/ 44 | 45 | # Visual Studio 2017 auto generated files 46 | Generated\ Files/ 47 | 48 | # MSTest test Results 49 | [Tt]est[Rr]esult*/ 50 | [Bb]uild[Ll]og.* 51 | 52 | # NUnit 53 | *.VisualState.xml 54 | TestResult.xml 55 | nunit-*.xml 56 | 57 | # Build Results of an ATL Project 58 | [Dd]ebugPS/ 59 | [Rr]eleasePS/ 60 | dlldata.c 61 | 62 | # Benchmark Results 63 | BenchmarkDotNet.Artifacts/ 64 | 65 | # .NET Core 66 | project.lock.json 67 | project.fragment.lock.json 68 | artifacts/ 69 | 70 | # ASP.NET Scaffolding 71 | ScaffoldingReadMe.txt 72 | 73 | # StyleCop 74 | StyleCopReport.xml 75 | 76 | # Files built by Visual Studio 77 | *_i.c 78 | *_p.c 79 | *_h.h 80 | *.ilk 81 | *.meta 82 | *.obj 83 | *.iobj 84 | *.pch 85 | *.pdb 86 | *.ipdb 87 | *.pgc 88 | *.pgd 89 | *.rsp 90 | *.sbr 91 | *.tlb 92 | *.tli 93 | *.tlh 94 | *.tmp 95 | *.tmp_proj 96 | *_wpftmp.csproj 97 | *.log 98 | *.vspscc 99 | *.vssscc 100 | .builds 101 | *.pidb 102 | *.svclog 103 | *.scc 104 | 105 | # Chutzpah Test files 106 | _Chutzpah* 107 | 108 | # Visual C++ cache files 109 | ipch/ 110 | *.aps 111 | *.ncb 112 | *.opendb 113 | *.opensdf 114 | *.sdf 115 | *.cachefile 116 | *.VC.db 117 | *.VC.VC.opendb 118 | 119 | # Visual Studio profiler 120 | *.psess 121 | *.vsp 122 | *.vspx 123 | *.sap 124 | 125 | # Visual Studio Trace Files 126 | *.e2e 127 | 128 | # TFS 2012 Local Workspace 129 | $tf/ 130 | 131 | # Guidance Automation Toolkit 132 | *.gpState 133 | 134 | # ReSharper is a .NET coding add-in 135 | _ReSharper*/ 136 | *.[Rr]e[Ss]harper 137 | *.DotSettings.user 138 | 139 | # TeamCity is a build add-in 140 | _TeamCity* 141 | 142 | # DotCover is a Code Coverage Tool 143 | *.dotCover 144 | 145 | # AxoCover is a Code Coverage Tool 146 | .axoCover/* 147 | !.axoCover/settings.json 148 | 149 | # Coverlet is a free, cross platform Code Coverage Tool 150 | coverage*.json 151 | coverage*.xml 152 | coverage*.info 153 | 154 | # Visual Studio code coverage results 155 | *.coverage 156 | *.coveragexml 157 | 158 | # NCrunch 159 | _NCrunch_* 160 | .*crunch*.local.xml 161 | nCrunchTemp_* 162 | 163 | # MightyMoose 164 | *.mm.* 165 | AutoTest.Net/ 166 | 167 | # Web workbench (sass) 168 | .sass-cache/ 169 | 170 | # Installshield output folder 171 | [Ee]xpress/ 172 | 173 | # DocProject is a documentation generator add-in 174 | DocProject/buildhelp/ 175 | DocProject/Help/*.HxT 176 | DocProject/Help/*.HxC 177 | DocProject/Help/*.hhc 178 | DocProject/Help/*.hhk 179 | DocProject/Help/*.hhp 180 | DocProject/Help/Html2 181 | DocProject/Help/html 182 | 183 | # Click-Once directory 184 | publish/ 185 | 186 | # Publish Web Output 187 | *.[Pp]ublish.xml 188 | *.azurePubxml 189 | # Note: Comment the next line if you want to checkin your web deploy settings, 190 | # but database connection strings (with potential passwords) will be unencrypted 191 | *.pubxml 192 | *.publishproj 193 | 194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 195 | # checkin your Azure Web App publish settings, but sensitive information contained 196 | # in these scripts will be unencrypted 197 | PublishScripts/ 198 | 199 | # NuGet Packages 200 | *.nupkg 201 | # NuGet Symbol Packages 202 | *.snupkg 203 | # The packages folder can be ignored because of Package Restore 204 | **/[Pp]ackages/* 205 | # except build/, which is used as an MSBuild target. 206 | !**/[Pp]ackages/build/ 207 | # Uncomment if necessary however generally it will be regenerated when needed 208 | #!**/[Pp]ackages/repositories.config 209 | # NuGet v3's project.json files produces more ignorable files 210 | *.nuget.props 211 | *.nuget.targets 212 | 213 | # Microsoft Azure Build Output 214 | csx/ 215 | *.build.csdef 216 | 217 | # Microsoft Azure Emulator 218 | ecf/ 219 | rcf/ 220 | 221 | # Windows Store app package directories and files 222 | AppPackages/ 223 | BundleArtifacts/ 224 | Package.StoreAssociation.xml 225 | _pkginfo.txt 226 | *.appx 227 | *.appxbundle 228 | *.appxupload 229 | 230 | # Visual Studio cache files 231 | # files ending in .cache can be ignored 232 | *.[Cc]ache 233 | # but keep track of directories ending in .cache 234 | !?*.[Cc]ache/ 235 | 236 | # Others 237 | ClientBin/ 238 | ~$* 239 | *~ 240 | *.dbmdl 241 | *.dbproj.schemaview 242 | *.jfm 243 | *.pfx 244 | *.publishsettings 245 | orleans.codegen.cs 246 | 247 | # Including strong name files can present a security risk 248 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 249 | #*.snk 250 | 251 | # Since there are multiple workflows, uncomment next line to ignore bower_components 252 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 253 | #bower_components/ 254 | 255 | # RIA/Silverlight projects 256 | Generated_Code/ 257 | 258 | # Backup & report files from converting an old project file 259 | # to a newer Visual Studio version. Backup files are not needed, 260 | # because we have git ;-) 261 | _UpgradeReport_Files/ 262 | Backup*/ 263 | UpgradeLog*.XML 264 | UpgradeLog*.htm 265 | ServiceFabricBackup/ 266 | *.rptproj.bak 267 | 268 | # SQL Server files 269 | *.mdf 270 | *.ldf 271 | *.ndf 272 | 273 | # Business Intelligence projects 274 | *.rdl.data 275 | *.bim.layout 276 | *.bim_*.settings 277 | *.rptproj.rsuser 278 | *- [Bb]ackup.rdl 279 | *- [Bb]ackup ([0-9]).rdl 280 | *- [Bb]ackup ([0-9][0-9]).rdl 281 | 282 | # Microsoft Fakes 283 | FakesAssemblies/ 284 | 285 | # GhostDoc plugin setting file 286 | *.GhostDoc.xml 287 | 288 | # Node.js Tools for Visual Studio 289 | .ntvs_analysis.dat 290 | node_modules/ 291 | 292 | # Visual Studio 6 build log 293 | *.plg 294 | 295 | # Visual Studio 6 workspace options file 296 | *.opt 297 | 298 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 299 | *.vbw 300 | 301 | # Visual Studio LightSwitch build output 302 | **/*.HTMLClient/GeneratedArtifacts 303 | **/*.DesktopClient/GeneratedArtifacts 304 | **/*.DesktopClient/ModelManifest.xml 305 | **/*.Server/GeneratedArtifacts 306 | **/*.Server/ModelManifest.xml 307 | _Pvt_Extensions 308 | 309 | # Paket dependency manager 310 | .paket/paket.exe 311 | paket-files/ 312 | 313 | # FAKE - F# Make 314 | .fake/ 315 | 316 | # CodeRush personal settings 317 | .cr/personal 318 | 319 | # Python Tools for Visual Studio (PTVS) 320 | __pycache__/ 321 | *.pyc 322 | 323 | # Cake - Uncomment if you are using it 324 | # tools/** 325 | # !tools/packages.config 326 | 327 | # Tabs Studio 328 | *.tss 329 | 330 | # Telerik's JustMock configuration file 331 | *.jmconfig 332 | 333 | # BizTalk build output 334 | *.btp.cs 335 | *.btm.cs 336 | *.odx.cs 337 | *.xsd.cs 338 | 339 | # OpenCover UI analysis results 340 | OpenCover/ 341 | 342 | # Azure Stream Analytics local run output 343 | ASALocalRun/ 344 | 345 | # MSBuild Binary and Structured Log 346 | *.binlog 347 | 348 | # NVidia Nsight GPU debugger configuration file 349 | *.nvuser 350 | 351 | # MFractors (Xamarin productivity tool) working folder 352 | .mfractor/ 353 | 354 | # Local History for Visual Studio 355 | .localhistory/ 356 | 357 | # BeatPulse healthcheck temp database 358 | healthchecksdb 359 | 360 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 361 | MigrationBackup/ 362 | 363 | # Ionide (cross platform F# VS Code tools) working folder 364 | .ionide/ 365 | 366 | # Fody - auto-generated XML schema 367 | FodyWeavers.xsd 368 | 369 | /GamePath.props -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Version 1.0.0 2 | 3 | - Added alternative monk capstone Old Master -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 AlterAsc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31903.59 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroscopicContentExpansion", "MicroscopicContentExpansion\MicroscopicContentExpansion.csproj", "{54A8EF4B-704E-475B-8E4C-0DC2FD58CE72}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{868C0EDF-8A0E-4070-AC7D-0EB5A616FF05}" 9 | ProjectSection(SolutionItems) = preProject 10 | .gitignore = .gitignore 11 | CHANGELOG.md = CHANGELOG.md 12 | LICENSE = LICENSE 13 | README.md = README.md 14 | Repository.json = Repository.json 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {54A8EF4B-704E-475B-8E4C-0DC2FD58CE72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {54A8EF4B-704E-475B-8E4C-0DC2FD58CE72}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {54A8EF4B-704E-475B-8E4C-0DC2FD58CE72}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {54A8EF4B-704E-475B-8E4C-0DC2FD58CE72}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {97256292-0E50-4DF7-945F-EF41CA474409} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | [*.{cs,vb}] 3 | #### Naming styles #### 4 | 5 | # Naming rules 6 | 7 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion 8 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface 9 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i 10 | 11 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion 12 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types 13 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case 14 | 15 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion 16 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members 17 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case 18 | 19 | # Symbol specifications 20 | 21 | dotnet_naming_symbols.interface.applicable_kinds = interface 22 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 23 | dotnet_naming_symbols.interface.required_modifiers = 24 | 25 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum 26 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 27 | dotnet_naming_symbols.types.required_modifiers = 28 | 29 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method 30 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 31 | dotnet_naming_symbols.non_field_members.required_modifiers = 32 | 33 | # Naming styles 34 | 35 | dotnet_naming_style.begins_with_i.required_prefix = I 36 | dotnet_naming_style.begins_with_i.required_suffix = 37 | dotnet_naming_style.begins_with_i.word_separator = 38 | dotnet_naming_style.begins_with_i.capitalization = pascal_case 39 | 40 | dotnet_naming_style.pascal_case.required_prefix = 41 | dotnet_naming_style.pascal_case.required_suffix = 42 | dotnet_naming_style.pascal_case.word_separator = 43 | dotnet_naming_style.pascal_case.capitalization = pascal_case 44 | 45 | dotnet_naming_style.pascal_case.required_prefix = 46 | dotnet_naming_style.pascal_case.required_suffix = 47 | dotnet_naming_style.pascal_case.word_separator = 48 | dotnet_naming_style.pascal_case.capitalization = pascal_case 49 | dotnet_style_operator_placement_when_wrapping = beginning_of_line 50 | tab_width = 4 51 | indent_size = 4 52 | end_of_line = crlf 53 | dotnet_style_coalesce_expression = true:suggestion 54 | dotnet_style_null_propagation = true:suggestion 55 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion 56 | dotnet_style_prefer_auto_properties = true:silent 57 | dotnet_style_object_initializer = true:suggestion 58 | dotnet_style_collection_initializer = true:suggestion 59 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion 60 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent 61 | dotnet_style_prefer_conditional_expression_over_return = true:silent 62 | dotnet_style_explicit_tuple_names = true:suggestion 63 | dotnet_style_prefer_inferred_tuple_names = true:suggestion 64 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion 65 | dotnet_style_prefer_compound_assignment = true:suggestion 66 | dotnet_style_namespace_match_folder = true:warning 67 | 68 | [*.cs] 69 | csharp_indent_labels = one_less_than_current 70 | csharp_using_directive_placement = outside_namespace:silent 71 | csharp_prefer_simple_using_statement = true:suggestion 72 | csharp_prefer_braces = true:silent 73 | csharp_style_namespace_declarations = file_scoped:warning 74 | csharp_style_prefer_method_group_conversion = true:silent 75 | csharp_style_prefer_top_level_statements = true:silent 76 | csharp_style_prefer_primary_constructors = true:suggestion 77 | csharp_style_expression_bodied_methods = false:silent 78 | csharp_style_expression_bodied_constructors = false:silent 79 | csharp_style_expression_bodied_operators = false:silent 80 | csharp_style_expression_bodied_properties = true:silent 81 | csharp_style_expression_bodied_indexers = true:silent 82 | csharp_style_expression_bodied_accessors = true:silent 83 | csharp_style_expression_bodied_lambdas = true:silent 84 | csharp_style_expression_bodied_local_functions = false:silent -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Assets/FeintingFlurry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/b398a6677164413fed2b9c0a2dc8187f022565f8/MicroscopicContentExpansion/Assets/FeintingFlurry.png -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Assets/FlyingKick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/b398a6677164413fed2b9c0a2dc8187f022565f8/MicroscopicContentExpansion/Assets/FlyingKick.png -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Assets/Ravener.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/b398a6677164413fed2b9c0a2dc8187f022565f8/MicroscopicContentExpansion/Assets/Ravener.png -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Assets/Snake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/b398a6677164413fed2b9c0a2dc8187f022565f8/MicroscopicContentExpansion/Assets/Snake.png -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Assets/StartossComet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/b398a6677164413fed2b9c0a2dc8187f022565f8/MicroscopicContentExpansion/Assets/StartossComet.png -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Assets/StartossStyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/b398a6677164413fed2b9c0a2dc8187f022565f8/MicroscopicContentExpansion/Assets/StartossStyle.png -------------------------------------------------------------------------------- /MicroscopicContentExpansion/BlueprintInitLoader.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using MicroscopicContentExpansion.NewContent.Classes; 4 | using MicroscopicContentExpansion.NewContent.Feats; 5 | using MicroscopicContentExpansion.NewContent.Spells; 6 | using MicroscopicContentExpansion.RebalancedContent.DragonbloodShifterArchetype; 7 | using MicroscopicContentExpansion.RebalancedContent.MythicArmor; 8 | using MicroscopicContentExpansion.RebalancedContent.MythicFeats; 9 | 10 | namespace MicroscopicContentExpansion; 11 | [HarmonyPatch(typeof(BlueprintsCache), nameof(BlueprintsCache.Init))] 12 | internal class BlueprintInitLoader 13 | { 14 | static bool Initialized; 15 | 16 | [HarmonyPostfix] 17 | static void AddModBlueprints() 18 | { 19 | if (Initialized) return; 20 | Initialized = true; 21 | AntipaladinAdder.AddAntipaladin(); 22 | CrusadersFlurry.Add(); 23 | SnakeStyleChain.AddSnakeStyle(); 24 | StartossStyleChain.AddStartossChain(); 25 | DimenshionalDervish.AddDimenshionalSavantFeatChain(); 26 | KiLeech.AddKiLeech(); 27 | DruidicHerbalism.Add(); 28 | CrusaderLegionBlessing.Add(); 29 | MonkStyleStrikeFlyingKick.AddFlyingKick(); 30 | MonkTimelessBody.AddTimelessBody(); 31 | MonkFlawlessMind.AddFlawlessMind(); 32 | MonkDiamondResilience.AddDiamondResilience(); 33 | FeintingFlurry.Add(); 34 | 35 | Dragonblooded.Change(); 36 | MythicArmorFeatTweaks.Change(); 37 | MythicDodge.Rework(); 38 | } 39 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Config/AddedContent.cs: -------------------------------------------------------------------------------- 1 | using TabletopTweaks.Core.Config; 2 | 3 | namespace MicroscopicContentExpansion.Config; 4 | public class AddedContent : IUpdatableSettings 5 | { 6 | public bool NewSettingsOffByDefault = false; 7 | public SettingGroup Spells = new(); 8 | public SettingGroup NewClasses = new(); 9 | public SettingGroup Feats = new(); 10 | 11 | public void Init() 12 | { 13 | } 14 | 15 | public void OverrideSettings(IUpdatableSettings userSettings) 16 | { 17 | var loadedSettings = userSettings as AddedContent; 18 | NewSettingsOffByDefault = loadedSettings.NewSettingsOffByDefault; 19 | Spells.LoadSettingGroup(loadedSettings.Spells, NewSettingsOffByDefault); 20 | NewClasses.LoadSettingGroup(loadedSettings.NewClasses, NewSettingsOffByDefault); 21 | Feats.LoadSettingGroup(loadedSettings.Feats, NewSettingsOffByDefault); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Config/AddedContent.json: -------------------------------------------------------------------------------- 1 | { 2 | "NewSettingsOffByDefault": false, 3 | "Spells": { 4 | "DisableAll": false, 5 | "Settings": { 6 | "DeadlyJuggernaut": { 7 | "Enabled": true, 8 | "Homebrew": false, 9 | "Description": "Adds Deadly Juggernaut spell to Cleric, Inquisitor and Paladin spell lists. And as ki power to monks (excl. Drunken Master)." 10 | }, 11 | "BladeofBrightVictory": { 12 | "Enabled": true, 13 | "Homebrew": false, 14 | "Description": "Adds Blade of Bright Victory spell to Paladin spell list" 15 | } 16 | }, 17 | "IsExpanded": true 18 | }, 19 | "NewClasses": { 20 | "DisableAll": false, 21 | "Settings": { 22 | "AntipaladinClass": { 23 | "Enabled": true, 24 | "Homebrew": false, 25 | "Description": "Adds Antipaladin class" 26 | }, 27 | "DruidicHerbalism": { 28 | "Enabled": true, 29 | "Homebrew": false, 30 | "Description": "Adds Druidic Herbalism" 31 | }, 32 | "CrusaderLegionBlessing": { 33 | "Enabled": true, 34 | "Homebrew": false, 35 | "Description": "Adds Crusader Legion's Blessing" 36 | } 37 | }, 38 | "IsExpanded": true 39 | }, 40 | "Feats": { 41 | "DisableAll": false, 42 | "Settings": { 43 | "PaladinUnsanctionedKnowdledge": { 44 | "Enabled": true, 45 | "Homebrew": false, 46 | "Description": "Adds Unsanctioned Knowledge feat for Paladins" 47 | }, 48 | "SnakeStyleFeatChain": { 49 | "Enabled": true, 50 | "Homebrew": false, 51 | "Description": "Adds Snake Style feat chain" 52 | }, 53 | "StartossStyleFeatChain": { 54 | "Enabled": true, 55 | "Homebrew": false, 56 | "Description": "Adds Startoss Style feat chain" 57 | }, 58 | "CrusadersFlurry": { 59 | "Enabled": true, 60 | "Homebrew": false, 61 | "Description": "Adds Crusader's Flurry'" 62 | }, 63 | "CrusadersFlurryNoGodCheck": { 64 | "Enabled": false, 65 | "Homebrew": false, 66 | "Description": "Disables check for wielding deity's favored weapon (if your deity is modded and normal check fails, or you're RPing deity that's not in the game)." 67 | }, 68 | "DimensionalDervishFeatChain": { 69 | "Enabled": true, 70 | "Homebrew": false, 71 | "Description": "Adds Flickering Step and Dimensional Dervish feat chain." 72 | }, 73 | "FlyingKickStyleStrike": { 74 | "Enabled": true, 75 | "Homebrew": false, 76 | "Description": "Adds Flying Kick style strike." 77 | }, 78 | "MonkTimelessBody": { 79 | "Enabled": true, 80 | "Homebrew": false, 81 | "Description": "Adds Timeless Body to monks." 82 | }, 83 | "MonkFlawlessMind": { 84 | "Enabled": true, 85 | "Homebrew": false, 86 | "Description": "Adds Flawless Mind to monks." 87 | }, 88 | "MonkDiamondResilience": { 89 | "Enabled": true, 90 | "Homebrew": false, 91 | "Description": "Adds Diamond Resilience Ki Power to monks (excl. Drunken Master)." 92 | }, 93 | "FeintingFlurry": { 94 | "Enabled": true, 95 | "Homebrew": false, 96 | "Description": "Adds Feinting Flurry (requires DLC6!)." 97 | } 98 | }, 99 | "IsExpanded": true 100 | } 101 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Config/Homebrew.cs: -------------------------------------------------------------------------------- 1 | using TabletopTweaks.Core.Config; 2 | 3 | namespace MicroscopicContentExpansion.Config; 4 | public class Homebrew : IUpdatableSettings 5 | { 6 | public bool NewSettingsOffByDefault = false; 7 | public SettingGroup DragonbloodShifter = new(); 8 | public SettingGroup MythicArmorFeats = new(); 9 | public SettingGroup MythicFeats = new(); 10 | 11 | public void Init() 12 | { 13 | } 14 | 15 | public void OverrideSettings(IUpdatableSettings userSettings) 16 | { 17 | var loadedSettings = userSettings as Homebrew; 18 | NewSettingsOffByDefault = loadedSettings.NewSettingsOffByDefault; 19 | DragonbloodShifter.LoadSettingGroup(loadedSettings.DragonbloodShifter, NewSettingsOffByDefault); 20 | MythicArmorFeats.LoadSettingGroup(loadedSettings.MythicArmorFeats, NewSettingsOffByDefault); 21 | MythicFeats.LoadSettingGroup(loadedSettings.MythicFeats, NewSettingsOffByDefault); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Config/Homebrew.json: -------------------------------------------------------------------------------- 1 | { 2 | "NewSettingsOffByDefault": true, 3 | "DragonbloodShifter": { 4 | "DisableAll": true, 5 | "Settings": { 6 | "EverlastingAspect": { 7 | "Enabled": false, 8 | "Homebrew": false, 9 | "Description": "Make Draconic Aspect last indefinitely." 10 | }, 11 | "MultipleAspectsAtOnce": { 12 | "Enabled": false, 13 | "Homebrew": false, 14 | "Description": "At levels 9, 14 and 20 allow 2, 3, 4 aspects enabled at the same time." 15 | }, 16 | "AddAirborneToForms": { 17 | "Enabled": false, 18 | "Homebrew": false, 19 | "Description": "Add Airborne property to dragon forms given by class." 20 | }, 21 | "IncreaseFormStatBonuses": { 22 | "Enabled": false, 23 | "Homebrew": false, 24 | "Description": "Increase STR/CON bonuses provided by dragon forms given by class by 0/2/4." 25 | }, 26 | "AddBiteAttack": { 27 | "Enabled": false, 28 | "Homebrew": false, 29 | "Description": "Add at lvl 4 bite attack with 1.5 STR bonus." 30 | }, 31 | "IncreaseFormBiteStrBonus": { 32 | "Enabled": false, 33 | "Homebrew": false, 34 | "Description": "Make class dragon form bite attack use 1.5 STR bonus." 35 | }, 36 | "AddWings": { 37 | "Enabled": false, 38 | "Homebrew": false, 39 | "Description": "Add at lvl 5 wings that are active when dragon aspect is active and match the color of last activated aspect." 40 | }, 41 | "ApplyGDBonuses": { 42 | "Enabled": false, 43 | "Homebrew": false, 44 | "Description": "Make Thousand Bites spell affect Gold and Black dragon forms of lvl 20 shifter." 45 | }, 46 | "FixGDSpellMetamagicTags": { 47 | "Enabled": false, 48 | "Homebrew": false, 49 | "Description": "Allows applying metamagic to mythic GD spells where tags were missing." 50 | }, 51 | "AddRavenerForm": { 52 | "Enabled": false, 53 | "Homebrew": false, 54 | "Description": "Creates Ravener form option at lvl 20 available to undead characters (so Lich 9+)." 55 | } 56 | }, 57 | "IsExpanded": true 58 | }, 59 | "MythicArmorFeats": { 60 | "DisableAll": true, 61 | "Settings": { 62 | "ArmorEnhancementBonusToBypassDR": { 63 | "Enabled": false, 64 | "Homebrew": false, 65 | "Description": "Use armor enhancement bonus for DR penetration in Heavy and Medium mythic offense feats. I.e. bonus damage from +5 heavy armor counts as if it came from +5 weapon." 66 | } 67 | }, 68 | "IsExpanded": true 69 | }, 70 | "MythicFeats": { 71 | "DisableAll": true, 72 | "Settings": { 73 | "MythicDodgeRework": { 74 | "Enabled": false, 75 | "Homebrew": false, 76 | "Description": "Enemies that attack you reroll the die once if they roll nat 20 on attack roll." 77 | } 78 | }, 79 | "IsExpanded": true 80 | } 81 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Globals.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using TabletopTweaks.Core.Utilities; 3 | 4 | namespace MicroscopicContentExpansion; 5 | internal static class Globals 6 | { 7 | internal static T GetBP(string id) where T : SimpleBlueprint 8 | { 9 | return BlueprintTools.GetBlueprint(id); 10 | } 11 | 12 | internal static T GetBPRef(string id) where T : BlueprintReferenceBase 13 | { 14 | return BlueprintTools.GetBlueprintReference(id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Info.json: -------------------------------------------------------------------------------- 1 | { 2 | "AssemblyName": "MicroscopicContentExpansion.dll", 3 | "Author": "AlterAsc", 4 | "DisplayName": "Microscopic Content Expansion", 5 | "EntryMethod": "MicroscopicContentExpansion.Main.Load", 6 | "GameVersion": "2.7.0", 7 | "HomePage": "https://www.nexusmods.com/pathfinderwrathoftherighteous/mods/506", 8 | "Id": "MicroscopicContentExpansion", 9 | "ManagerVersion": "0.23.0", 10 | "Repository": "https://raw.githubusercontent.com/alterasc/MicroscopicContentExpansion/master/Repository.json", 11 | "Requirements": [ "TabletopTweaks-Core-0.7.11" ], 12 | "LoadAfter": [ "TabletopTweaks-Core", "TabletopTweaks-Base", "MewsiferConsole.Mod" ], 13 | "Version": "1.20.0" 14 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Main.cs: -------------------------------------------------------------------------------- 1 | global using static MicroscopicContentExpansion.Globals; 2 | global using static MicroscopicContentExpansion.Main; 3 | using HarmonyLib; 4 | using MicroscopicContentExpansion.ModLogic; 5 | using MicroscopicContentExpansion.NewContent.AnimalCompanions; 6 | using TabletopTweaks.Core.Utilities; 7 | using UnityModManagerNet; 8 | 9 | namespace MicroscopicContentExpansion; 10 | public static class Main 11 | { 12 | public static ModContextMCEBase MCEContext; 13 | public static Harmony HarmonyInstance; 14 | public static bool Load(UnityModManager.ModEntry modEntry) 15 | { 16 | HarmonyInstance = new Harmony(modEntry.Info.Id); 17 | MCEContext = new ModContextMCEBase(modEntry); 18 | MCEContext.LoadAllSettings(); 19 | MCEContext.ModEntry.OnSaveGUI = OnSaveGUI; 20 | MCEContext.ModEntry.OnGUI = UMMSettingsUI.OnGUI; 21 | HarmonyInstance.CreateClassProcessor(typeof(BlueprintInitLoader)).Patch(); 22 | HarmonyInstance.CreateClassProcessor(typeof(NightmareMountOffsetPatch)).Patch(); 23 | PostPatchInitializer.Initialize(MCEContext); 24 | return true; 25 | } 26 | 27 | static void OnSaveGUI(UnityModManager.ModEntry modEntry) 28 | { 29 | MCEContext.SaveAllSettings(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/MicroscopicContentExpansion.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net481 6 | MicroscopicContentExpansion 7 | MicroscopicContentExpansion 8 | 1.0.0 9 | true 10 | latest 11 | MicroscopicContentExpansion 12 | false 13 | https://api.nuget.org/v3/index.json 14 | $(LocalAppData)Low\Owlcat Games\Pathfinder Wrath Of The Righteous 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | PreserveNewest 52 | 53 | 54 | PreserveNewest 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | ^Mono path\[0\] = '(.*?)/Wrath_Data/Managed'$ 65 | 66 | 67 | 68 | $([System.Text.RegularExpressions.Regex]::Match($(MonoPathLine), $(MonoPathRegex)).Groups[1].Value) 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/ModLogic/ModContextMCEBase.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using MicroscopicContentExpansion.Config; 3 | using TabletopTweaks.Core.ModLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | using static UnityModManagerNet.UnityModManager; 6 | 7 | namespace MicroscopicContentExpansion.ModLogic; 8 | public class ModContextMCEBase : ModContextBase 9 | { 10 | public AddedContent AddedContent; 11 | public Homebrew Homebrew; 12 | 13 | public ModContextMCEBase(ModEntry ModEntry) : base(ModEntry) 14 | { 15 | #if DEBUG 16 | Debug = true; 17 | #endif 18 | } 19 | public override void LoadAllSettings() 20 | { 21 | LoadSettings("AddedContent.json", "MicroscopicContentExpansion.Config", ref AddedContent); 22 | LoadSettings("Homebrew.json", "MicroscopicContentExpansion.Config", ref Homebrew); 23 | LoadBlueprints("MicroscopicContentExpansion.Config", this); 24 | LoadLocalization("MicroscopicContentExpansion.Localization"); 25 | } 26 | 27 | public override void AfterBlueprintCachePatches() 28 | { 29 | base.AfterBlueprintCachePatches(); 30 | } 31 | 32 | public override void SaveAllSettings() 33 | { 34 | base.SaveAllSettings(); 35 | SaveSettings("AddedContent.json", AddedContent); 36 | SaveSettings("Homebrew.json", Homebrew); 37 | } 38 | 39 | public T GetModBlueprintReference(string name) where T : BlueprintReferenceBase 40 | => BlueprintTools.GetModBlueprintReference(this, name); 41 | } 42 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AbilityCasterHasChosenWeaponFromGroup.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes.Selection; 3 | using Kingmaker.Blueprints.Items.Weapons; 4 | using Kingmaker.Blueprints.JsonSystem; 5 | using Kingmaker.Blueprints.Root; 6 | using Kingmaker.EntitySystem.Entities; 7 | using Kingmaker.Items.Slots; 8 | using Kingmaker.UnitLogic; 9 | using Kingmaker.UnitLogic.Abilities.Blueprints; 10 | using Kingmaker.UnitLogic.Abilities.Components.Base; 11 | using System.Linq; 12 | 13 | namespace MicroscopicContentExpansion.NewComponents; 14 | [AllowedOn(typeof(BlueprintAbility), false)] 15 | [AllowMultipleComponents] 16 | [TypeId("3eee2cfa0d254f78b495be783a635f4e")] 17 | public class AbilityCasterHasChosenWeaponFromGroup : BlueprintComponent, IAbilityCasterRestriction 18 | { 19 | public BlueprintParametrizedFeatureReference ChosenWeaponFeature; 20 | public WeaponFighterGroup WeaponGroup; 21 | public BlueprintFeatureReference WeaponGroupReference; 22 | 23 | public bool IsCasterRestrictionPassed(UnitEntityData caster) 24 | { 25 | if (this.HasSuitableWeapon(caster.Body.PrimaryHand)) 26 | return true; 27 | return false; 28 | } 29 | 30 | private bool HasSuitableWeapon(WeaponSlot slot) 31 | { 32 | return slot.MaybeWeapon != null 33 | && slot.MaybeWeapon.Blueprint.FighterGroup.Contains(WeaponGroup) 34 | && (slot.Owner.GetFeature(ChosenWeaponFeature, (FeatureParam)slot.MaybeWeapon.Blueprint.Category) != null 35 | || slot.Owner.HasFact(WeaponGroupReference)) 36 | ; 37 | } 38 | public string GetAbilityCasterRestrictionUIText() => (string)LocalizedTexts.Instance.Reasons.ChosenWeaponRequired; 39 | } 40 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AbilityCasterHasSwiftAction.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.EntitySystem.Entities; 4 | using Kingmaker.UnitLogic.Abilities.Blueprints; 5 | using Kingmaker.UnitLogic.Abilities.Components.Base; 6 | 7 | namespace MicroscopicContentExpansion.NewComponents; 8 | [AllowedOn(typeof(BlueprintAbility), false)] 9 | [AllowMultipleComponents] 10 | [TypeId("08a2ac736acf45fa82b484593d88cab9")] 11 | internal class AbilityCasterHasSwiftAction : BlueprintComponent, IAbilityCasterRestriction 12 | { 13 | public string GetAbilityCasterRestrictionUIText() => "Caster doesn't have swift action available"; 14 | 15 | public bool IsCasterRestrictionPassed(UnitEntityData caster) => caster.HasSwiftAction(); 16 | } 17 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AbilityCustomDimensionalAssault.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.Blueprints.Root; 4 | using Kingmaker.UnitLogic; 5 | using Kingmaker.UnitLogic.Abilities; 6 | using Kingmaker.UnitLogic.Abilities.Components.Base; 7 | using Kingmaker.UnitLogic.Commands; 8 | using Kingmaker.Utility; 9 | using System; 10 | using System.Collections.Generic; 11 | using UnityEngine; 12 | 13 | namespace MicroscopicContentExpansion.NewComponents; 14 | [TypeId("29cfc39737054920bdef50529a521699")] 15 | internal class AbilityCustomDimensionalAssault : AbilityCustomLogic 16 | { 17 | 18 | public override bool IsEngageUnit => true; 19 | public override IEnumerator Deliver(AbilityExecutionContext context, TargetWrapper target) 20 | { 21 | var caster = context.MaybeCaster; 22 | 23 | if (caster == null) 24 | { 25 | PFLog.Default.Error(this, "Caster is missing", Array.Empty()); 26 | yield break; 27 | } 28 | var threatHand = caster.GetThreatHandMelee(); 29 | if (threatHand == null) 30 | { 31 | PFLog.Default.Error("Caster can't attack", Array.Empty()); 32 | yield break; 33 | } 34 | var originalTarget = target.Unit; 35 | if (originalTarget == null) 36 | { 37 | PFLog.Default.Error("Can't be applied to point", Array.Empty()); 38 | yield break; 39 | } 40 | if (!caster.IsReach(originalTarget, threatHand)) 41 | { 42 | Vector3 target1 = originalTarget.Position; 43 | var casterPos = caster.Position; 44 | 45 | var handRange = caster.GetThreatHandMelee().Weapon.AttackRange.Meters; 46 | 47 | var dist = Vector3.Distance(casterPos, target1) - handRange / 2; 48 | 49 | var tpTarget = Vector3.MoveTowards(casterPos, target1, dist); 50 | 51 | caster.ForceLookAt(target1); 52 | caster.CombatState.PreventAttacksOfOpporunityNextFrame = true; 53 | caster.Position = tpTarget; 54 | } 55 | caster.Descriptor.AddBuff(BlueprintRoot.Instance.SystemMechanics.ChargeBuff, context, new TimeSpan?(1.Rounds().Seconds)); 56 | caster.Descriptor.State.IsCharging = true; 57 | 58 | UnitAttack attack = new UnitAttack(target.Unit) 59 | { 60 | IsCharge = true 61 | }; 62 | attack.IgnoreCooldown(); 63 | attack.Init(caster); 64 | caster.Commands.AddToQueueFirst(attack); 65 | } 66 | 67 | public override void Cleanup(AbilityExecutionContext context) 68 | { 69 | context.Caster.Descriptor.State.IsCharging = false; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AbilityCustomDimensionalDervish.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.EntitySystem.Entities; 4 | using Kingmaker.Items.Slots; 5 | using Kingmaker.PubSubSystem; 6 | using Kingmaker.RuleSystem.Rules; 7 | using Kingmaker.UnitLogic; 8 | using Kingmaker.UnitLogic.Abilities; 9 | using Kingmaker.UnitLogic.Abilities.Components.Base; 10 | using Kingmaker.UnitLogic.Commands; 11 | using Kingmaker.Utility; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | using UnityEngine; 16 | 17 | namespace MicroscopicContentExpansion.NewComponents; 18 | [TypeId("3eda209f2af8431ab8093f6ceb4e73e8")] 19 | internal class AbilityCustomDimensionalDervish : AbilityCustomLogic 20 | { 21 | public override IEnumerator Deliver(AbilityExecutionContext context, TargetWrapper target) 22 | { 23 | var caster = context.MaybeCaster; 24 | 25 | if (caster == null) 26 | { 27 | PFLog.Default.Error(this, "Caster is missing", Array.Empty()); 28 | yield break; 29 | } 30 | var threatHand = caster.GetThreatHandMelee(); 31 | if (threatHand == null) 32 | { 33 | PFLog.Default.Error("Caster can't attack", Array.Empty()); 34 | yield break; 35 | } 36 | var originalTarget = target.Unit; 37 | if (originalTarget == null) 38 | { 39 | PFLog.Default.Error("Can't be applied to point", Array.Empty()); 40 | yield break; 41 | } 42 | caster.SpendAction(Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Swift, true, 0); 43 | //first we attack our main target 44 | var totalRange = caster.CombatSpeedMps * 6f; 45 | UnitEntityData maybeCaster = context.MaybeCaster; 46 | if (!maybeCaster.IsReach(originalTarget, threatHand)) 47 | { 48 | Vector3 target1 = originalTarget.Position; 49 | var casterPos = caster.Position; 50 | 51 | var handRange = caster.GetThreatHandMelee().Weapon.AttackRange.Meters; 52 | 53 | var dist = Vector3.Distance(casterPos, target1) - handRange / 2; 54 | totalRange -= dist; 55 | var tpTarget = Vector3.MoveTowards(casterPos, target1, dist); 56 | 57 | caster.ForceLookAt(target1); 58 | caster.CombatState.PreventAttacksOfOpporunityNextFrame = true; 59 | caster.Position = tpTarget; 60 | } 61 | // then setup TeleportAfterAttackToNextTarget handler that will teleport to closest enemy if no targets in reach 62 | // and perform full attack 63 | var eventHandlers = new EventHandlers(); 64 | eventHandlers.Add(new TeleportAfterAttackToNextTarget(caster, totalRange)); 65 | 66 | using (eventHandlers.Activate()) 67 | { 68 | UnitAttack cmd = new UnitAttack(target.Unit) 69 | { 70 | ForceFullAttack = true 71 | }; 72 | cmd.Init(context.Caster); 73 | cmd.Start(); 74 | 75 | while (!cmd.IsFinished) 76 | { 77 | bool wasActed = cmd.IsActed; 78 | if (!cmd.IsFinished) 79 | cmd.Tick(); 80 | if ((wasActed ? 0 : (cmd.IsActed ? 1 : 0)) != 0) 81 | { 82 | yield return new AbilityDeliveryTarget(target); 83 | } 84 | yield return null; 85 | } 86 | } 87 | } 88 | 89 | public override void Cleanup(AbilityExecutionContext context) 90 | { 91 | } 92 | 93 | private class EventHandlers : IDisposable 94 | { 95 | private readonly List m_Handlers = new List(); 96 | 97 | public void Add(object handler) => this.m_Handlers.Add(handler); 98 | 99 | public EventHandlers Activate() 100 | { 101 | foreach (object handler in this.m_Handlers) 102 | EventBus.Subscribe(handler); 103 | return this; 104 | } 105 | 106 | public void Dispose() 107 | { 108 | foreach (object handler in this.m_Handlers) 109 | EventBus.Unsubscribe(handler); 110 | } 111 | } 112 | 113 | internal static void TeleportToTarget(UnitEntityData caster, UnitEntityData target) 114 | { 115 | Vector3 target1 = target.Position; 116 | var casterPos = caster.Position; 117 | 118 | var handRange = caster.GetThreatHandMelee().Weapon.AttackRange.Meters; 119 | 120 | var dist = Vector3.Distance(casterPos, target1) - handRange / 2; 121 | var tpTarget = Vector3.MoveTowards(casterPos, target1, dist); 122 | 123 | caster.ForceLookAt(target1); 124 | caster.CombatState.PreventAttacksOfOpporunityNextFrame = true; 125 | caster.Position = tpTarget; 126 | } 127 | 128 | public override bool IsEngageUnit => true; 129 | } 130 | 131 | 132 | 133 | 134 | [TypeId("461bb5f8eb0b418da9a4b1bd4003c92c")] 135 | public class TeleportAfterAttackToNextTarget : 136 | IInitiatorRulebookHandler, 137 | IRulebookHandler, 138 | ISubscriber, 139 | IInitiatorRulebookSubscriber 140 | { 141 | public UnitEntityData GetSubscribingUnit() 142 | { 143 | return this.m_Unit; 144 | } 145 | 146 | private readonly UnitEntityData m_Unit; 147 | private float distance; 148 | 149 | public TeleportAfterAttackToNextTarget(UnitEntityData unit, float distance) 150 | { 151 | m_Unit = unit; 152 | this.distance = distance; 153 | } 154 | 155 | public void OnEventAboutToTrigger(RuleAttackWithWeaponResolve evt) 156 | { 157 | 158 | } 159 | 160 | 161 | public void OnEventDidTrigger(RuleAttackWithWeaponResolve evt) 162 | { 163 | WeaponSlot threatHand = evt.Initiator.GetThreatHandMelee(); 164 | var list = new List { }; 165 | foreach (UnitGroupMemory.UnitInfo enemy in evt.Initiator.Memory.Enemies) 166 | { 167 | UnitEntityData unit = enemy.Unit; 168 | if (unit.HPLeft > 0 && evt.Initiator.IsReach(unit, threatHand)) return; 169 | } 170 | foreach (UnitGroupMemory.UnitInfo unitInfo in evt.Initiator.Memory.Enemies) 171 | { 172 | if (unitInfo.Unit.HPLeft > 0 && unitInfo.Unit.Descriptor.State.IsConscious) 173 | list.Add(unitInfo.Unit); 174 | } 175 | list.Sort((u1, u2) => evt.Initiator.DistanceTo(u1).CompareTo(evt.Initiator.DistanceTo(u2))); 176 | if (list.Count == 0) 177 | return; 178 | var closest = list.First(); 179 | 180 | Vector3 target1 = closest.Position; 181 | var casterPos = evt.Initiator.Position; 182 | 183 | var handRange = evt.Initiator.GetThreatHandMelee().Weapon.AttackRange.Meters; 184 | 185 | var dist = Vector3.Distance(casterPos, target1) - handRange / 2; 186 | if (dist < this.distance) 187 | { 188 | this.distance -= dist; 189 | var tpTarget = Vector3.MoveTowards(casterPos, target1, dist); 190 | 191 | evt.Initiator.ForceLookAt(target1); 192 | evt.Initiator.CombatState.PreventAttacksOfOpporunityNextFrame = true; 193 | evt.Initiator.Position = tpTarget; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AbilityCustomFlyingKick.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | using Kingmaker; 3 | using Kingmaker.Blueprints; 4 | using Kingmaker.Blueprints.JsonSystem; 5 | using Kingmaker.Blueprints.Root; 6 | using Kingmaker.Controllers.Units; 7 | using Kingmaker.EntitySystem.Entities; 8 | using Kingmaker.Localization; 9 | using Kingmaker.RuleSystem.Rules; 10 | using Kingmaker.UnitLogic; 11 | using Kingmaker.UnitLogic.Abilities; 12 | using Kingmaker.UnitLogic.Abilities.Components; 13 | using Kingmaker.UnitLogic.Abilities.Components.Base; 14 | using Kingmaker.UnitLogic.Buffs.Blueprints; 15 | using Kingmaker.UnitLogic.Commands; 16 | using Kingmaker.Utility; 17 | using Kingmaker.View; 18 | using Kingmaker.Visual.Animation.Kingmaker; 19 | using System; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | 24 | namespace MicroscopicContentExpansion.NewComponents; 25 | 26 | [TypeId("7d967f2e6e4043c2a490963bb6d40027")] 27 | public class AbilityCustomFlyingKick : AbilityCustomLogic, 28 | IAbilityTargetRestriction, 29 | IAbilityMinRangeProvider 30 | { 31 | 32 | [SerializeField] 33 | public BlueprintBuffReference m_AddBuffWhileRunning; 34 | 35 | public BlueprintBuffReference m_FlurrySuppressionBuff; 36 | 37 | public BlueprintBuff AddBuffWhileRunning => this.m_AddBuffWhileRunning?.Get(); 38 | 39 | public override IEnumerator Deliver( 40 | AbilityExecutionContext context, 41 | TargetWrapper target) 42 | { 43 | UnitEntityData caster = context.Caster; 44 | Vector3 startPoint = caster.Position; 45 | var originalTarget = target.Unit; 46 | 47 | if (originalTarget == null) 48 | { 49 | PFLog.Default.Error("Can't be applied to point", []); 50 | yield break; 51 | } 52 | Vector3 originalTargetPosition = originalTarget.Position; 53 | 54 | var handRange = caster.GetThreatHandMelee().Weapon.AttackRange.Meters; 55 | 56 | var endPoint = GetLandingEndpoint(caster, originalTarget, handRange); 57 | 58 | caster.View.StopMoving(); 59 | 60 | if (caster.View.AnimationManager?.CurrentAction is UnitAnimationActionHandle currentAction) 61 | currentAction.DoesNotPreventMovement = true; 62 | else 63 | PFLog.Default.Error("No animation handle found"); 64 | 65 | caster.Descriptor.AddBuff(this.AddBuffWhileRunning, context); 66 | 67 | var startTime = Game.Instance.TimeController.GameTime; 68 | float duration = 0.75f; 69 | float d = 0.0f; 70 | 71 | while (d <= duration) 72 | { 73 | if (Game.Instance.TurnBasedCombatController.WaitingForUI) 74 | { 75 | yield return null; 76 | } 77 | else 78 | { 79 | d = (float)(Game.Instance.TimeController.GameTime - startTime).TotalSeconds; 80 | var passed = d / duration; 81 | 82 | if (originalTarget.Position != originalTargetPosition) 83 | { 84 | endPoint = GetLandingEndpoint(caster, originalTarget, handRange); 85 | } 86 | 87 | var position = Vector3.Lerp(startPoint, endPoint, passed); 88 | caster.Position = position; 89 | caster.FlyHeight = (passed - passed * passed) * 4f; 90 | yield return null; 91 | } 92 | } 93 | caster.FlyHeight = 0f; 94 | caster.Position = endPoint; 95 | 96 | context.Caster.Descriptor.RemoveFact(AddBuffWhileRunning); 97 | 98 | caster.FlyHeight = 0f; 99 | UnitPlaceOnGroundController.ForcedTick(caster); 100 | 101 | if (!originalTarget.State.IsDead) 102 | { 103 | RuleAttackWithWeapon attackWithWeapon = new RuleAttackWithWeapon(caster, originalTarget, caster.GetThreatHandMelee().Weapon, 0); 104 | context.TriggerRule(attackWithWeapon); 105 | } 106 | caster.Descriptor.AddBuff(m_FlurrySuppressionBuff, context, TimeSpan.FromSeconds(1)); 107 | var flurryTarget = originalTarget; 108 | if (!flurryTarget.State.IsDead) 109 | { 110 | var threatHand = caster.GetThreatHandMelee(); 111 | var list = new List { }; 112 | 113 | foreach (UnitGroupMemory.UnitInfo enemy in caster.Memory.Enemies) 114 | { 115 | UnitEntityData unit = enemy.Unit; 116 | if (unit.HPLeft > 0 && caster.IsReach(unit, threatHand)) 117 | { 118 | flurryTarget = unit; 119 | break; 120 | } 121 | } 122 | } 123 | if (flurryTarget != null) 124 | { 125 | UnitAttack cmd = new UnitAttack(target.Unit) 126 | { 127 | ForceFullAttack = true 128 | }; 129 | cmd.IgnoreCooldown(); 130 | cmd.Init(caster); 131 | caster.Commands.AddToQueueFirst(cmd); 132 | } 133 | } 134 | 135 | public override void Cleanup(AbilityExecutionContext context) 136 | { 137 | context.Caster.Descriptor.RemoveFact(AddBuffWhileRunning); 138 | } 139 | 140 | private static Vector3 GetLandingEndpoint(UnitEntityData caster, UnitEntityData target, float handRange) 141 | { 142 | 143 | Vector3 startPoint = caster.Position; 144 | Vector3 targetP = target.Position; 145 | var dist = Vector3.Distance(startPoint, targetP) - handRange - caster.Corpulence - target.Corpulence; 146 | return Vector3.MoveTowards(startPoint, targetP, dist); 147 | } 148 | 149 | public float GetMinRangeMeters(UnitEntityData caster) => 5.Feet().Meters + caster.View.Corpulence; 150 | 151 | public bool IsTargetRestrictionPassed(UnitEntityData caster, TargetWrapper targetWrapper) => this.CheckTargetRestriction(caster, targetWrapper, out LocalizedString _); 152 | 153 | public string GetAbilityTargetRestrictionUIText(UnitEntityData caster, TargetWrapper target) 154 | { 155 | CheckTargetRestriction(caster, target, out LocalizedString failReason); 156 | return failReason == null ? string.Empty : (string)failReason; 157 | } 158 | 159 | private bool CheckTargetRestriction( 160 | UnitEntityData caster, 161 | TargetWrapper targetWrapper, 162 | [CanBeNull] out LocalizedString failReason) 163 | { 164 | 165 | float magnitude = (targetWrapper.Point - caster.Position).magnitude; 166 | if ((double)magnitude > (double)AbilityCustomOverrun.GetMaxRangeMeters(caster)) 167 | { 168 | failReason = BlueprintRoot.Instance.LocalizedTexts.Reasons.TargetIsTooFar; 169 | return false; 170 | } 171 | if (magnitude < GetMinRangeMeters(caster)) 172 | { 173 | failReason = BlueprintRoot.Instance.LocalizedTexts.Reasons.TargetIsTooClose; 174 | return false; 175 | } 176 | 177 | if (ObstacleAnalyzer.TraceAlongNavmesh(caster.Position, targetWrapper.Point) != targetWrapper.Point) 178 | { 179 | failReason = BlueprintRoot.Instance.LocalizedTexts.Reasons.ObstacleBetweenCasterAndTarget; 180 | return false; 181 | } 182 | failReason = null; 183 | return true; 184 | } 185 | 186 | public override bool IsEngageUnit => true; 187 | } 188 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AddUnitFactDependingOnClassLevel.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Facts; 4 | using Kingmaker.Blueprints.JsonSystem; 5 | using Kingmaker.Designers.Mechanics.Facts; 6 | using Kingmaker.EntitySystem; 7 | using Kingmaker.PubSubSystem; 8 | using Kingmaker.UnitLogic; 9 | using Newtonsoft.Json; 10 | using System; 11 | using System.Linq; 12 | using UnityEngine; 13 | 14 | namespace MicroscopicContentExpansion.NewComponents; 15 | 16 | [ComponentName("Add feature depending on class level")] 17 | [AllowMultipleComponents] 18 | [AllowedOn(typeof(BlueprintUnitFact), false)] 19 | [TypeId("1981eee498aa42ce92459d460b9681b9")] 20 | public class AddUnitFactDependingOnClassLevel : 21 | UnitFactComponentDelegate, 22 | IOwnerGainLevelHandler, 23 | IUnitSubscriber, 24 | ISubscriber 25 | { 26 | 27 | [SerializeField] 28 | public BlueprintCharacterClassReference m_Class; 29 | 30 | [SerializeField] 31 | public BlueprintUnitFactReference[] unitFactArray; 32 | 33 | [SerializeField] 34 | public BlueprintCharacterClassReference[] m_AdditionalClasses; 35 | 36 | [SerializeField] 37 | public BlueprintArchetypeReference[] m_Archetypes; 38 | 39 | public BlueprintCharacterClass Class => this.m_Class?.Get(); 40 | 41 | public ReferenceArrayProxy AdditionalClasses => (ReferenceArrayProxy)this.m_AdditionalClasses; 42 | 43 | public ReferenceArrayProxy Archetypes => (ReferenceArrayProxy)this.m_Archetypes; 44 | 45 | public override void OnActivate() => this.Apply(); 46 | 47 | public override void OnDeactivate() 48 | { 49 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Fact not null {this.Data.AppliedFact != null}"); 50 | this.Owner.RemoveFact(this.Data.AppliedFact); 51 | this.Data.AppliedFact = null; 52 | this.Data.AppliedFactReference = null; 53 | } 54 | 55 | public void HandleUnitGainLevel() => this.Apply(); 56 | 57 | private void Apply() 58 | { 59 | var featureToApply = IsFeatureShouldBeApplied(); 60 | 61 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Will add guid {featureToApply.Guid}"); 62 | if (this.Data.AppliedFact != null) 63 | { 64 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Applied Fact present"); 65 | if (this.Data.AppliedFactReference.Equals(featureToApply)) 66 | { 67 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Applied Fact match"); 68 | return; 69 | } 70 | else 71 | { 72 | this.Owner.RemoveFact(this.Data.AppliedFact); 73 | this.Data.AppliedFact = null; 74 | this.Data.AppliedFactReference = null; 75 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Removed Fact"); 76 | } 77 | } 78 | var feature = featureToApply.Get(); 79 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Feature not null {feature != null}"); 80 | UnitFact fact2 = feature.CreateFact(null, this.Owner.Descriptor, new TimeSpan?()); 81 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: fact2 not null {fact2 != null}"); 82 | UnitFact fact3 = this.Owner.Facts.Add(fact2); 83 | this.Data.AppliedFact = fact3; 84 | 85 | this.Data.AppliedFactReference = featureToApply; 86 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: Added new Fact {this.Data.AppliedFact != null}"); 87 | } 88 | 89 | private BlueprintUnitFactReference IsFeatureShouldBeApplied() 90 | { 91 | int classLevel = ReplaceCasterLevelOfAbility.CalculateClassLevel(this.Class, this.AdditionalClasses.ToArray(), (UnitDescriptor)this.Owner, this.Archetypes.ToArray()); 92 | var idx = classLevel / 3; 93 | Main.MCEContext.Logger.Log($"IsFeatureShouldBeApplied: {idx}"); 94 | if (idx > unitFactArray.Length) 95 | { 96 | return unitFactArray[unitFactArray.Length - 1]; 97 | } 98 | return unitFactArray[idx - 1]; 99 | 100 | } 101 | } 102 | 103 | public class AddFeatureDependingOnClassLevelData 104 | { 105 | [JsonProperty] 106 | public EntityFact AppliedFact; 107 | [JsonProperty] 108 | public BlueprintUnitFactReference AppliedFactReference; 109 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/AuraFeatureComponentWithWiden.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Facts; 3 | using Kingmaker.Blueprints.JsonSystem; 4 | using Kingmaker.Designers.Mechanics.Facts; 5 | using Kingmaker.EntitySystem; 6 | using Kingmaker.EntitySystem.Entities; 7 | using Kingmaker.PubSubSystem; 8 | using Kingmaker.UnitLogic; 9 | using Kingmaker.UnitLogic.Buffs.Blueprints; 10 | 11 | namespace MicroscopicContentExpansion.NewComponents; 12 | [TypeId("42a0a56bec4a47df89aa6e8b7ddd8157")] 13 | [AllowedOn(typeof(BlueprintUnitFact), false)] 14 | [AllowMultipleComponents] 15 | public class AuraFeatureComponentWithWiden : 16 | UnitFactComponentDelegate, 17 | IUnitLifeStateChanged, 18 | IGlobalSubscriber, 19 | ISubscriber, 20 | IUnitGainFactHandler, 21 | IUnitLostFactHandler 22 | { 23 | 24 | public BlueprintBuffReference DefaultBuff; 25 | public BlueprintUnitFactReference WidenFact; 26 | public BlueprintBuffReference WidenBuff; 27 | public BlueprintBuff BuffToApply => Owner.HasFact(WidenFact) ? WidenBuff?.Get() : DefaultBuff?.Get(); 28 | 29 | public override void OnActivate() => Data.AppliedBuff = Owner.AddBuff(BuffToApply, Fact.MaybeContext); 30 | 31 | public override void OnDeactivate() 32 | { 33 | Data.AppliedBuff?.Remove(); 34 | Data.AppliedBuff = null; 35 | } 36 | 37 | public void HandleUnitLifeStateChanged(UnitEntityData unit, UnitLifeState prevLifeState) 38 | { 39 | if (unit == (UnitDescriptor)Owner && (prevLifeState == UnitLifeState.Dead || prevLifeState == UnitLifeState.Unconscious) && prevLifeState != UnitLifeState.Conscious && Data.AppliedBuff == null) 40 | Data.AppliedBuff = Owner.AddBuff(BuffToApply, Fact.MaybeContext); 41 | if (!(unit == (UnitDescriptor)Owner) || prevLifeState == UnitLifeState.Dead || prevLifeState == UnitLifeState.Unconscious || prevLifeState != UnitLifeState.Conscious) 42 | return; 43 | Data.AppliedBuff?.Remove(); 44 | Data.AppliedBuff = null; 45 | } 46 | 47 | public void HandleUnitGainFact(EntityFact fact) 48 | { 49 | if (!WidenFact.Is(fact.Blueprint as BlueprintUnitFact)) return; 50 | if (Data.AppliedBuff != null) 51 | { 52 | Data.AppliedBuff?.Remove(); 53 | Data.AppliedBuff = Owner.AddBuff(BuffToApply, Fact.MaybeContext); 54 | } 55 | } 56 | 57 | public void HandleUnitLostFact(EntityFact fact) 58 | { 59 | if (!WidenFact.Is(fact.Blueprint as BlueprintUnitFact)) return; 60 | if (Data.AppliedBuff != null) 61 | { 62 | Data.AppliedBuff?.Remove(); 63 | Data.AppliedBuff = Owner.AddBuff(BuffToApply, Fact.MaybeContext); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/ContextActionArmorEnchantPoolMCE.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Items.Ecnchantments; 3 | using Kingmaker.Blueprints.JsonSystem; 4 | using Kingmaker.EntitySystem.Entities; 5 | using Kingmaker.Items; 6 | using Kingmaker.UnitLogic.ActivatableAbilities; 7 | using Kingmaker.UnitLogic.FactLogic; 8 | using Kingmaker.UnitLogic.Mechanics; 9 | using Kingmaker.UnitLogic.Mechanics.Actions; 10 | using Kingmaker.UnitLogic.Parts; 11 | using Kingmaker.Utility; 12 | using Owlcat.Runtime.Core.Logging; 13 | using System; 14 | using System.Linq; 15 | using UnityEngine; 16 | using UnityEngine.Serialization; 17 | 18 | namespace MicroscopicContentExpansion.NewComponents; 19 | [TypeId("b0880fc55e33413db74fe74d0f4ef3aa")] 20 | public class ContextActionArmorEnchantPoolMCE : ContextAction 21 | { 22 | public EnchantPoolType EnchantPool; 23 | public ActivatableAbilityGroup Group; 24 | [SerializeField] 25 | [FormerlySerializedAs("DefaultEnchantments")] 26 | public BlueprintItemEnchantmentReference[] m_DefaultEnchantments = new BlueprintItemEnchantmentReference[5]; 27 | public ContextDurationValue DurationValue; 28 | 29 | public override string GetCaption() => string.Format("Add enchants from pool to caster's armor (for {0})", DurationValue); 30 | 31 | public override void RunAction() 32 | { 33 | UnitEntityData maybeCaster = this.Context.MaybeCaster; 34 | if (maybeCaster == null) 35 | { 36 | LogChannel.Default.Error(this, "ContextActionArmorEnchantPool: target is null"); 37 | } 38 | else 39 | { 40 | UnitPartEnchantPoolData partEnchantPoolData = maybeCaster.Ensure(); 41 | partEnchantPoolData.ClearEnchantPool(this.EnchantPool); 42 | ItemEntityArmor maybeArmor = maybeCaster.Body.Armor.MaybeArmor; 43 | if (maybeArmor == null) 44 | return; 45 | int num1 = 0; 46 | int groupSize = maybeCaster.Ensure().GetGroupSize(this.Group); 47 | if (maybeArmor.Enchantments.Any()) 48 | { 49 | num1 = maybeArmor.Enchantments.SelectMany(e => e.SelectComponents()) 50 | .Select(e => e.EnhancementValue) 51 | .DefaultIfEmpty(0) 52 | .Max(); 53 | } 54 | Rounds duration = this.DurationValue.Calculate(this.Context); 55 | foreach (AddBondProperty selectFactComponent in maybeCaster.Buffs.SelectFactComponents()) 56 | { 57 | if (selectFactComponent.EnchantPool == this.EnchantPool && !maybeArmor.HasEnchantment(selectFactComponent.Enchant)) 58 | { 59 | groupSize -= selectFactComponent.Enchant.EnchantmentCost; 60 | partEnchantPoolData.AddEnchant(maybeArmor, this.EnchantPool, selectFactComponent.Enchant, this.Context, duration); 61 | } 62 | } 63 | int num2 = Math.Min(Math.Max(groupSize, 0) + num1, 5); 64 | if (num2 <= 0) 65 | return; 66 | BlueprintItemEnchantment defaultEnchantment = this.m_DefaultEnchantments[num2 - 1]; 67 | partEnchantPoolData.AddEnchant(maybeArmor, this.EnchantPool, defaultEnchantment, this.Context, duration); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/CriticalConfirmationUnarmed.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Facts; 3 | using Kingmaker.Blueprints.JsonSystem; 4 | using Kingmaker.PubSubSystem; 5 | using Kingmaker.RuleSystem.Rules; 6 | using Kingmaker.UnitLogic; 7 | 8 | namespace MicroscopicContentExpansion.NewComponents; 9 | [AllowedOn(typeof(BlueprintUnitFact))] 10 | [TypeId("001209d9eeeb4484a5fc8652010c2d60")] 11 | public class CriticalConfirmationUnarmed : 12 | UnitFactComponentDelegate, 13 | IInitiatorRulebookHandler, 14 | IRulebookHandler, 15 | ISubscriber, 16 | IInitiatorRulebookSubscriber 17 | { 18 | public int Bonus; 19 | 20 | public void OnEventAboutToTrigger(RuleAttackRoll evt) 21 | { 22 | if (!evt.Weapon.IsMonkUnarmedStrike) 23 | return; 24 | evt.CriticalConfirmationBonus += Bonus; 25 | } 26 | 27 | public void OnEventDidTrigger(RuleAttackRoll evt) 28 | { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/CrusadersFlurryUnlock.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Selection; 4 | using Kingmaker.Blueprints.Facts; 5 | using Kingmaker.Blueprints.Items.Armors; 6 | using Kingmaker.Blueprints.Items.Weapons; 7 | using Kingmaker.Blueprints.JsonSystem; 8 | using Kingmaker.EntitySystem; 9 | using Kingmaker.EntitySystem.Entities; 10 | using Kingmaker.Items; 11 | using Kingmaker.Items.Slots; 12 | using Kingmaker.PubSubSystem; 13 | using Kingmaker.UnitLogic; 14 | using Kingmaker.UnitLogic.FactLogic; 15 | using Kingmaker.UnitLogic.Parts; 16 | using Newtonsoft.Json; 17 | using System.Linq; 18 | 19 | namespace MicroscopicContentExpansion.NewComponents; 20 | [ComponentName("Crusaders Flurry")] 21 | [AllowedOn(typeof(BlueprintUnitFact), false)] 22 | [AllowMultipleComponents] 23 | [TypeId("c934325c5cbb494f914507761f531ac3")] 24 | public class CrusadersFlurryUnlock : 25 | UnitFactComponentDelegate, 26 | IUnitActiveEquipmentSetHandler, 27 | IGlobalSubscriber, 28 | ISubscriber, 29 | IUnitEquipmentHandler 30 | { 31 | 32 | public BlueprintUnitFactReference _flurryFact1; 33 | public BlueprintUnitFactReference _flurryFact11; 34 | public BlueprintUnitFactReference _flurryFact20; 35 | public BlueprintArchetypeReference _soheiArchetype; 36 | public BlueprintCharacterClassReference _monkClass; 37 | public BlueprintFeatureReference[] _flurry2ndfacts; 38 | public BlueprintFeatureReference _oldMaster; 39 | public BlueprintFeatureSelectionReference _deitySelection; 40 | public BlueprintParametrizedFeatureReference _weaponFocus; 41 | 42 | public BlueprintUnitFact Flurry1 => _flurryFact1?.Get(); 43 | public BlueprintUnitFact Flurry11 => _flurryFact11?.Get(); 44 | public BlueprintUnitFact Flurry20 => _flurryFact20?.Get(); 45 | 46 | public override void OnActivate() => CheckEligibility(); 47 | 48 | public override void OnDeactivate() => RemoveFact(); 49 | 50 | public void HandleUnitChangeActiveEquipmentSet(UnitDescriptor unit) => this.CheckEligibility(); 51 | 52 | private bool IsDeityMeleeFavoredWeaponWithWeaponFocus() 53 | { 54 | if (Owner.Body.PrimaryHand.MaybeWeapon == null) 55 | return false; 56 | var primaryWeapon = Owner.Body.PrimaryHand.Weapon.Blueprint; 57 | if (primaryWeapon.m_Type.Get().m_AttackType != Kingmaker.RuleSystem.AttackType.Melee) 58 | return false; 59 | if (Owner.GetFeature((BlueprintFeature)_weaponFocus, (FeatureParam)primaryWeapon.Category) == null) 60 | return false; 61 | 62 | if (MCEContext.AddedContent.Feats.IsEnabled("CrusadersFlurryNoGodCheck")) 63 | return true; 64 | 65 | Owner.Progression.Selections.TryGetValue(_deitySelection?.Get(), out var selection); 66 | if (selection == null) 67 | return false; 68 | if (!selection.m_SelectionsByLevel.TryGetValue(1, out var selectedAtLvl1)) return false; 69 | if (selectedAtLvl1.Count == 0) return false; 70 | var selectedDeity = selectedAtLvl1.First(); 71 | var comp = selectedDeity.GetComponent(); 72 | if (comp == null || comp.m_BasicItems == null || comp.m_BasicItems.Count() == 0) 73 | return false; 74 | var favoredWeaponType = ((BlueprintItemWeapon)comp.m_BasicItems[0].Get()).m_Type; 75 | if (primaryWeapon.m_Type.Equals(favoredWeaponType)) 76 | { 77 | return true; 78 | } 79 | 80 | return false; 81 | } 82 | 83 | private void CheckEligibility() 84 | { 85 | var isSoheiArchetype = Owner.Progression.IsArchetype(_soheiArchetype.Get()); 86 | 87 | var hasShield = Owner.Body.SecondaryHand.HasShield; 88 | if (!isSoheiArchetype) 89 | { 90 | //not Sohei 91 | var noArmor = !Owner.Body.Armor.HasArmor || !Owner.Body.Armor.Armor.Blueprint.IsArmor; 92 | var isMonkWeapon = Owner.Body.PrimaryHand.Weapon.Blueprint.IsMonk; 93 | if (!hasShield && noArmor && !isMonkWeapon && IsDeityMeleeFavoredWeaponWithWeaponFocus()) 94 | { 95 | AddFact(); 96 | } 97 | else 98 | RemoveFact(); 99 | } 100 | else 101 | { 102 | //Sohei 103 | bool noArmorOrLightArmor = false; 104 | if (!Owner.Body.Armor.HasArmor) 105 | noArmorOrLightArmor = true; 106 | else if (Owner.Body.Armor.MaybeArmor != null) 107 | noArmorOrLightArmor = !Owner.Body.Armor.MaybeArmor.Blueprint.IsArmor 108 | || Owner.Body.Armor.MaybeArmor.Blueprint.ProficiencyGroup == ArmorProficiencyGroup.Light; 109 | 110 | bool wieldingWeaponWithWTOrMonkWeapon = Owner.Get() != null 111 | ? Owner.Body.PrimaryHand.MaybeWeapon.Blueprint.IsMonk || 112 | Owner.Get().IsSuitableWeapon(Owner.Body.PrimaryHand.MaybeWeapon) 113 | : Owner.Body.PrimaryHand.MaybeWeapon.Blueprint.IsMonk; 114 | 115 | if (!hasShield && noArmorOrLightArmor 116 | && !wieldingWeaponWithWTOrMonkWeapon && IsDeityMeleeFavoredWeaponWithWeaponFocus()) 117 | AddFact(); 118 | else 119 | RemoveFact(); 120 | } 121 | } 122 | 123 | private void AddFact() 124 | { 125 | if (Data.Flurry1 == null) 126 | { 127 | Data.Flurry1 = Owner.AddFact(Flurry1); 128 | } 129 | if (Data.Flurry11 == null) 130 | { 131 | if (_flurry2ndfacts.Any(x => Owner.HasFact(x))) 132 | { 133 | Data.Flurry11 = Owner.AddFact(Flurry11); 134 | } 135 | } 136 | if (Data.Flurry20 == null) 137 | { 138 | if (Owner.HasFact(_oldMaster)) 139 | { 140 | Data.Flurry20 = Owner.AddFact(Flurry20); 141 | } 142 | } 143 | } 144 | 145 | private void RemoveFact() 146 | { 147 | if (Data.Flurry1 != null) 148 | { 149 | Owner.RemoveFact(Data.Flurry1); 150 | Data.Flurry1 = null; 151 | } 152 | if (Data.Flurry11 != null) 153 | { 154 | Owner.RemoveFact(Data.Flurry11); 155 | Data.Flurry11 = null; 156 | } 157 | if (Data.Flurry20 != null) 158 | { 159 | Owner.RemoveFact(Data.Flurry20); 160 | Data.Flurry20 = null; 161 | } 162 | } 163 | 164 | public void HandleEquipmentSlotUpdated(ItemSlot slot, ItemEntity previousItem) 165 | { 166 | if ((UnitEntityData)slot.Owner != (UnitDescriptor)Owner || !slot.Active) 167 | return; 168 | CheckEligibility(); 169 | } 170 | } 171 | 172 | public class CrusadersFlurryUnlockData 173 | { 174 | [JsonProperty] 175 | public EntityFact Flurry1; 176 | [JsonProperty] 177 | public EntityFact Flurry11; 178 | [JsonProperty] 179 | public EntityFact Flurry20; 180 | } 181 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/HarmonyPatchActivator.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.UnitLogic; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace MicroscopicContentExpansion.NewComponents; 6 | 7 | /// 8 | /// Activates patches under specified type on component initialization 9 | /// 10 | public class HarmonyPatchActivator : UnitFactComponentDelegate 11 | { 12 | private static readonly HashSet ActivatedPatches = []; 13 | 14 | public Type PatchType; 15 | 16 | public override void OnTurnOn() 17 | { 18 | base.OnTurnOn(); 19 | if (ActivatedPatches.Contains(PatchType)) 20 | { 21 | return; 22 | } 23 | try 24 | { 25 | HarmonyInstance.CreateClassProcessor(PatchType).Patch(); 26 | MCEContext.Logger.Log($"Enabled {PatchType.Name} patches"); 27 | } 28 | catch (Exception ex) 29 | { 30 | MCEContext.Logger.LogError(ex, $"Error when enabling {PatchType.Name} patches: {ex.Message}"); 31 | } 32 | ActivatedPatches.Add(PatchType); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/LegionBlessingApplySpell.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.Controllers.Optimization; 4 | using Kingmaker.EntitySystem.Entities; 5 | using Kingmaker.PubSubSystem; 6 | using Kingmaker.RuleSystem; 7 | using Kingmaker.RuleSystem.Rules.Abilities; 8 | using Kingmaker.UnitLogic; 9 | using Kingmaker.UnitLogic.Abilities; 10 | using Kingmaker.UnitLogic.Abilities.Blueprints; 11 | using Kingmaker.UnitLogic.Abilities.Components; 12 | using Kingmaker.Utility; 13 | using System.Collections.Generic; 14 | 15 | namespace MicroscopicContentExpansion.NewComponents; 16 | [TypeId("c184044ab8934085bc7ed8eded0ddb4c")] 17 | public class LegionBlessingApplySpell : 18 | UnitFactComponentDelegate, 19 | IInitiatorRulebookHandler, 20 | IRulebookHandler, 21 | ISubscriber, 22 | IInitiatorRulebookSubscriber 23 | { 24 | 25 | public int SpellLevel; 26 | public BlueprintSpellbookReference SpellbookReference; 27 | 28 | void IRulebookHandler.OnEventAboutToTrigger( 29 | RuleCastSpell evt) 30 | { 31 | } 32 | 33 | void IRulebookHandler.OnEventDidTrigger(RuleCastSpell evt) 34 | { 35 | if (evt.IsDuplicateSpellApplied 36 | || !evt.Success 37 | || evt.Spell.Blueprint.Type != AbilityType.Spell 38 | || evt.Spell.Range != AbilityRange.Touch 39 | || evt.Spell.SpellLevel != SpellLevel 40 | || evt.Spell.SpellbookBlueprint != SpellbookReference.Get() 41 | || !evt.SpellTarget.Unit.IsAlly(Owner)) 42 | return; 43 | AbilityData spell = evt.Spell; 44 | List alliesAround = GetTargetsAroundYou(spell, evt.SpellTarget.Unit); 45 | var touchAbility = spell.Blueprint.GetComponent(); 46 | if (touchAbility != null) 47 | { 48 | spell = new AbilityData(evt.Spell, touchAbility.TouchDeliveryAbility); 49 | } 50 | foreach (var target in alliesAround) 51 | { 52 | Rulebook.Trigger(new RuleCastSpell(spell, target) 53 | { 54 | IsDuplicateSpellApplied = true 55 | }); 56 | } 57 | Owner.RemoveFact(Fact); 58 | } 59 | 60 | private List GetTargetsAroundYou(AbilityData data, UnitEntityData baseTarget) 61 | { 62 | List unitsInRange = EntityBoundsHelper.FindUnitsInRange(Owner.Position, 13.Feet().Meters); 63 | unitsInRange.Remove(baseTarget); 64 | unitsInRange.RemoveAll(x => x.Faction != baseTarget.Faction || !data.CanTarget((TargetWrapper)x)); 65 | return unitsInRange; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/LegionBlessingSacrificeSpellAbility.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.UnitLogic; 4 | using Kingmaker.UnitLogic.Abilities; 5 | using Kingmaker.UnitLogic.Abilities.Components.Base; 6 | using Kingmaker.Utility; 7 | 8 | namespace MicroscopicContentExpansion.NewComponents; 9 | [TypeId("e626812134a646d2bbd1be80b7fad21d")] 10 | public class LegionBlessingSacrificeSpellAbility : AbilityApplyEffect 11 | { 12 | 13 | public BlueprintBuffReference[] LegionBlessingBuffs; 14 | public override void Apply(AbilityExecutionContext context, TargetWrapper target) 15 | { 16 | var spellLevel = context.Ability.SpellLevel; 17 | if (spellLevel >= 4 && spellLevel <= 9) 18 | { 19 | var buff = LegionBlessingBuffs[spellLevel - 4]; 20 | context.MaybeCaster?.AddBuff(buff, null, null); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/MasterClassLevelGetter.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints.Classes; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.EntitySystem.Entities; 4 | using Kingmaker.UnitLogic.Mechanics.Properties; 5 | 6 | namespace MicroscopicContentExpansion.NewComponents; 7 | [TypeId("378aa84e70d44cceb01e884e690e623c")] 8 | public class MasterClassLevelGetter : PropertyValueGetter 9 | { 10 | 11 | public BlueprintCharacterClass CharacterClass; 12 | 13 | public override int GetBaseValue(UnitEntityData unit) 14 | { 15 | if (!unit.IsPet || unit.Master == null) 16 | { 17 | return 0; 18 | } 19 | return unit.Master.Progression.GetClassLevel(CharacterClass); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/RuleAttackWithWeaponChaining.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | using Kingmaker; 3 | using Kingmaker.Armies.TacticalCombat; 4 | using Kingmaker.Blueprints; 5 | using Kingmaker.Blueprints.Items.Weapons; 6 | using Kingmaker.Blueprints.JsonSystem; 7 | using Kingmaker.Controllers.Projectiles; 8 | using Kingmaker.EntitySystem.Entities; 9 | using Kingmaker.Items; 10 | using Kingmaker.RuleSystem; 11 | using Kingmaker.RuleSystem.Rules; 12 | using Kingmaker.RuleSystem.Rules.Abilities; 13 | using Kingmaker.RuleSystem.Rules.Damage; 14 | using Kingmaker.UnitLogic.Parts; 15 | using Kingmaker.Utility; 16 | using System.Linq; 17 | 18 | namespace MicroscopicContentExpansion.NewComponents; 19 | [TypeId("a3477f19abb04c9ab98337f9e31d0392")] 20 | class RuleAttackWithWeaponChaining : RuleAttackWithWeapon 21 | { 22 | 23 | public UnitEntityData Source { get; set; } 24 | public RuleAttackWithWeaponChaining([NotNull] UnitEntityData attacker, UnitEntityData source, [NotNull] UnitEntityData target, [NotNull] ItemEntityWeapon weapon, int attackBonusPenalty) : base(attacker, target, weapon, attackBonusPenalty) 25 | { 26 | this.Source = source; 27 | } 28 | 29 | public override void OnTrigger(RulebookEventContext context) 30 | { 31 | Rulebook.Trigger(this.WeaponStats); 32 | this.AttackRoll = new RuleAttackRoll(this.Initiator, this.Target, this.WeaponStats, this.AttackBonusPenalty) 33 | { 34 | AutoHit = this.AutoHit, 35 | AutoCriticalThreat = this.AutoCriticalThreat, 36 | AutoCriticalConfirmation = TacticalCombatHelper.IsActive || this.AutoCriticalConfirmation, 37 | SuspendCombatLog = this.Weapon.Blueprint.IsRanged, 38 | RuleAttackWithWeapon = this, 39 | DoNotProvokeAttacksOfOpportunity = this.IsAttackOfOpportunity, 40 | ForceFlatFooted = this.ForceFlatFooted 41 | }; 42 | Rulebook.Trigger(this.AttackRoll); 43 | BlueprintProjectileReference[] projectiles = this.Weapon.Blueprint.VisualParameters.Projectiles; 44 | if (projectiles.Length != 0) 45 | { 46 | this.LaunchProjectilesChain(projectiles); 47 | } 48 | else 49 | { 50 | RuleAttackWithWeaponResolve evt = new RuleAttackWithWeaponResolve(this, this.Weapon.Blueprint.HasNoDamage ? null : this.CreateRuleDealDamage(true)); 51 | this.MeleeDamage = evt.Damage; 52 | this.ResolveRules.Add(evt); 53 | context.Trigger(evt); 54 | } 55 | } 56 | 57 | private void LaunchProjectilesChain(BlueprintProjectileReference[] projectiles) 58 | { 59 | foreach (BlueprintProjectileReference projectile in projectiles) 60 | { 61 | if (projectile.Get() != null) 62 | { 63 | this.LaunchProjectileChain(projectile.Get(), true); 64 | if (this.Weapon.Blueprint.FighterGroup.Contains(WeaponFighterGroup.Bows) && (bool)this.Initiator.Descriptor.State.Features.Manyshot && this.IsFirstAttack && this.IsFullAttack && !(bool)this.Initiator.Descriptor.State.Features.SuppressedManyshot) 65 | this.LaunchProjectileChain(projectile.Get(), false); 66 | } 67 | } 68 | } 69 | 70 | private void LaunchProjectileChain(BlueprintProjectile blueprint, bool first) 71 | { 72 | Projectile projectile; 73 | var ssrc = this.Source != null ? this.Source : this.Initiator; 74 | if (this.AttackRoll.IsHit) 75 | { 76 | RuleDealDamage damage = this.Weapon.Blueprint.HasNoDamage ? null : this.CreateRuleDealDamage(TacticalCombatHelper.IsActive | first); 77 | RuleAttackWithWeaponResolve ruleOnHit = new RuleAttackWithWeaponResolve(this, damage); 78 | this.ResolveRules.Add(ruleOnHit); 79 | projectile = Game.Instance.ProjectileController.Launch(ssrc, (TargetWrapper)this.Target, blueprint, this.AttackRoll, ruleOnHit); 80 | if (damage != null) 81 | damage.Projectile = projectile; 82 | } 83 | else 84 | { 85 | RuleAttackWithWeaponResolve ruleOnHit = new RuleAttackWithWeaponResolve(this, null); 86 | this.ResolveRules.Add(ruleOnHit); 87 | projectile = Game.Instance.ProjectileController.Launch(ssrc, (TargetWrapper)this.Target, blueprint, this.AttackRoll, ruleOnHit); 88 | projectile.CalculateMissTarget(); 89 | } 90 | projectile.IsFromWeapon = true; 91 | this.LaunchedProjectiles.Add(projectile); 92 | UnitPartMagus unitPartMagus = this.Initiator.Get(); 93 | if (!(bool)unitPartMagus || !(unitPartMagus.EldritchArcherSpell != null)) 94 | return; 95 | RuleCastSpell ruleCastSpell = Rulebook.Trigger(new RuleCastSpell(unitPartMagus.EldritchArcherSpell, (TargetWrapper)this.Target)); 96 | ruleCastSpell.Context.AttackRoll = this.AttackRoll; 97 | ruleCastSpell.Context.MissTarget = projectile?.MissTarget; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/SnakeFangOnMissHandler.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker; 2 | using Kingmaker.Blueprints; 3 | using Kingmaker.Blueprints.Facts; 4 | using Kingmaker.Blueprints.JsonSystem; 5 | using Kingmaker.Items.Slots; 6 | using Kingmaker.PubSubSystem; 7 | using Kingmaker.RuleSystem.Rules; 8 | using Kingmaker.UnitLogic; 9 | using Kingmaker.UnitLogic.Mechanics.Components; 10 | using Kingmaker.Utility; 11 | 12 | namespace MicroscopicContentExpansion.NewComponents; 13 | [AllowedOn(typeof(BlueprintUnitFact), false)] 14 | [AllowMultipleComponents] 15 | [TypeId("ac67128448634c5b88bfc44d3009bb8d")] 16 | public class SnakeFangOnMissHandler : 17 | UnitFactComponentDelegate, 18 | ITargetRulebookHandler, 19 | IRulebookHandler, 20 | ISubscriber, 21 | ITargetRulebookSubscriber 22 | { 23 | 24 | public BlueprintUnitFactReference m_Fact; 25 | public void OnEventAboutToTrigger(RuleAttackWithWeapon evt) 26 | { 27 | } 28 | 29 | public void OnEventDidTrigger(RuleAttackWithWeapon evt) 30 | { 31 | if (evt.AttackRoll.IsHit || !evt.Target.HasFact(m_Fact) || IsNotUnarmedWeapon(evt.Target.Body.PrimaryHand)) 32 | return; 33 | if (this.Fact is IFactContextOwner) 34 | { 35 | Game.Instance.CombatEngagementController.ForceAttackOfOpportunity(evt.Target, evt.Initiator); 36 | } 37 | } 38 | 39 | private static bool IsNotUnarmedWeapon(WeaponSlot hand) 40 | { 41 | if (!hand.HasWeapon) 42 | return false; 43 | return !hand.Weapon.Blueprint.IsUnarmed; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/SpecialAnimationMonkKick.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.UnitLogic.Buffs.Blueprints; 4 | using Kingmaker.UnitLogic.Buffs.Components; 5 | using Kingmaker.View.Animation; 6 | using Kingmaker.Visual.Animation.Kingmaker; 7 | using Kingmaker.Visual.Animation.Kingmaker.Actions; 8 | 9 | namespace MicroscopicContentExpansion.NewComponents; 10 | 11 | [ComponentName("SpecialAnimationStateAny")] 12 | [AllowedOn(typeof(BlueprintBuff), false)] 13 | [TypeId("494e9bf94233487f9284c94ba51d94f3")] 14 | public class SpecialAnimationMonkKick : UnitBuffComponentDelegate, 15 | IBuffFxComponent 16 | { 17 | 18 | public UnitAnimationActionHandAttack Animation; 19 | 20 | public override void OnDeactivate() 21 | { 22 | base.OnDeactivate(); 23 | if (this.Data.Handle == null) 24 | return; 25 | this.Data.Handle.Release(); 26 | this.Data.Handle = null; 27 | } 28 | 29 | void IBuffFxComponent.OnSpawnFx() => this.StartAnimation(); 30 | 31 | public void StartAnimation() 32 | { 33 | UnitAnimationManager animationManager = this.Owner.View.AnimationManager; 34 | if (animationManager == null) 35 | return; 36 | 37 | var handle = animationManager.CreateHandle(UnitAnimationType.MainHandAttack, true); 38 | handle.AttackWeaponStyle = WeaponAnimationStyle.MartialArts; 39 | handle.Variant = 2; 40 | handle.m_SpeedScale = 0.66f; 41 | this.Data.Handle = handle; 42 | animationManager.Execute(Data.Handle); 43 | } 44 | } 45 | 46 | public class SpecialAnimationStateAnyData 47 | { 48 | public UnitAnimationActionHandle Handle; 49 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewComponents/StartossStyleComponent.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Selection; 4 | using Kingmaker.Blueprints.Facts; 5 | using Kingmaker.Blueprints.Items.Armors; 6 | using Kingmaker.Blueprints.Items.Weapons; 7 | using Kingmaker.Blueprints.JsonSystem; 8 | using Kingmaker.Enums; 9 | using Kingmaker.Items.Slots; 10 | using Kingmaker.PubSubSystem; 11 | using Kingmaker.RuleSystem; 12 | using Kingmaker.RuleSystem.Rules; 13 | using Kingmaker.UnitLogic; 14 | 15 | namespace MicroscopicContentExpansion.NewComponents; 16 | 17 | 18 | [AllowMultipleComponents] 19 | [AllowedOn(typeof(BlueprintUnitFact))] 20 | [TypeId("8b13837d88a24b63bd3ce04b76b2664e")] 21 | public class StartossStyleComponent : UnitFactComponentDelegate, 22 | IInitiatorRulebookHandler, 23 | IRulebookHandler, 24 | ISubscriber, 25 | IInitiatorRulebookSubscriber 26 | { 27 | 28 | public BlueprintParametrizedFeatureReference ChosenWeaponFeature; 29 | public BlueprintFeatureReference StartossComet; 30 | public BlueprintFeatureReference StartossShower; 31 | public WeaponFighterGroup WeaponGroup; 32 | public BlueprintFeatureReference WeaponGroupReference; 33 | 34 | public void OnEventAboutToTrigger(RuleCalculateWeaponStats evt) 35 | { 36 | if (IsSuitable(evt)) 37 | { 38 | var addDmg = 2; 39 | if (Owner.HasFact(StartossComet)) 40 | { 41 | addDmg += 2; 42 | } 43 | if (Owner.HasFact(StartossShower)) 44 | { 45 | addDmg += 2; 46 | } 47 | evt.AddDamageModifier(addDmg, base.Fact, ModifierDescriptor.UntypedStackable); 48 | } 49 | } 50 | 51 | public void OnEventDidTrigger(RuleCalculateWeaponStats evt) 52 | { 53 | } 54 | 55 | private bool HasSuitableWeapon(WeaponSlot slot) 56 | { 57 | return slot.MaybeWeapon != null 58 | && slot.Owner.GetFeature((BlueprintFeature)this.ChosenWeaponFeature, (FeatureParam)slot.MaybeWeapon.Blueprint.Category) != null; 59 | } 60 | 61 | private bool IsSuitable(RuleCalculateWeaponStats evt) 62 | { 63 | var weapon = evt.Weapon; 64 | var ruleCalculateAttackBonus = new RuleCalculateAttackBonusWithoutTarget(evt.Initiator, weapon, 0); 65 | ruleCalculateAttackBonus.WeaponStats.m_Triggered = true; 66 | Rulebook.Trigger(ruleCalculateAttackBonus); 67 | 68 | return weapon.Blueprint.IsRanged 69 | && weapon.Blueprint.FighterGroup.Contains(WeaponGroup) 70 | && (HasSuitableWeapon(Owner.Body.PrimaryHand) || Owner.HasFact(WeaponGroupReference)) 71 | && IsOffHandNotHoldingAnotherWeapon(); 72 | } 73 | 74 | private bool IsOffHandNotHoldingAnotherWeapon() 75 | { 76 | var secondaryHand = Owner.Body.CurrentHandsEquipmentSet.SecondaryHand; 77 | bool hasFreeHand = true; 78 | if (secondaryHand.HasShield) 79 | { 80 | var maybeShield = secondaryHand.MaybeShield; 81 | hasFreeHand = maybeShield.Blueprint.Type.ProficiencyGroup == ArmorProficiencyGroup.Buckler; 82 | } 83 | else if (secondaryHand.HasWeapon && secondaryHand.MaybeWeapon != Owner.Body.EmptyHandWeapon) 84 | { 85 | hasFreeHand = false; 86 | } 87 | return hasFreeHand; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AnimalCompanions/NightmareMountOffsetPatch.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Kingmaker.Blueprints.Root; 3 | using Kingmaker.Modding; 4 | using Kingmaker.View; 5 | using Kingmaker.Visual.Mounts; 6 | using Owlcat.Runtime.Core.Utils; 7 | using System.Linq; 8 | using UnityEngine; 9 | 10 | namespace MicroscopicContentExpansion.NewContent.AnimalCompanions; 11 | 12 | [HarmonyPatch(typeof(OwlcatModificationsManager), nameof(OwlcatModificationsManager.OnResourceLoaded))] 13 | public static class NightmareMountOffsetPatch 14 | { 15 | 16 | [HarmonyPrefix] 17 | public static void Prefix(object resource, string guid) 18 | { 19 | if (guid != "ac628c52d113f9c47a923c51d25f605e") //nightmare asset id 20 | return; 21 | if (resource is UnitEntityView view) 22 | { 23 | PatchNightmareAsset(view); 24 | } 25 | } 26 | 27 | public static Transform CreateMountBone(Transform parent, string type, Vector3 posOffset, Vector3? rotOffset = null) 28 | { 29 | var offsetBone = new GameObject($"Saddle_{type}_parent"); 30 | offsetBone.transform.SetParent(parent); 31 | offsetBone.transform.localPosition = posOffset; 32 | if (rotOffset.HasValue) 33 | offsetBone.transform.localEulerAngles = rotOffset.Value; 34 | 35 | var target = new GameObject($"Saddle_{type}"); 36 | target.transform.SetParent(offsetBone.transform); 37 | 38 | return target.transform; 39 | } 40 | 41 | public static void PatchNightmareAsset(UnitEntityView view) 42 | { 43 | var offsets = view.gameObject.AddComponent(); 44 | 45 | offsets.Root = view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"); 46 | offsets.RootBattle = view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"); 47 | 48 | offsets.PelvisIkTarget = CreateMountBone(view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"), 49 | "Pelvis", 50 | new Vector3(0f, 0.361f, 0.065f), 51 | new Vector3(0.7602f, 180f, 0f)); 52 | offsets.LeftFootIkTarget = CreateMountBone(view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"), 53 | "LeftFoot", 54 | new Vector3(0.425f, -0.3506f, -0.1074f), 55 | new Vector3(334.9193f, 94.9215f, 322.0144f)); 56 | offsets.RightFootIkTarget = CreateMountBone(view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"), 57 | "RightFoot", 58 | new Vector3(-0.425f, -0.3506f, -0.1074f), 59 | new Vector3(11.3555f, 92.1214f, 144.7181f)); 60 | offsets.LeftKneeIkTarget = CreateMountBone(view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"), 61 | "LeftKnee", 62 | new Vector3(0.386f, 0.0652f, -0.275f), 63 | new Vector3(359.9774f, 0f, 149.1742f)); 64 | offsets.RightKneeIkTarget = CreateMountBone(view.Pelvis.FindChildRecursive("Locator_Torso_Upper_02"), 65 | "RightKnee", 66 | new Vector3(-0.386f, 0.0652f, -0.275f), 67 | new Vector3(359.9774f, 0f, 337.0312f)); 68 | 69 | offsets.Hands = CreateMountBone(view.Pelvis.FindChildRecursive("Locator_Head_00"), 70 | "Hands", 71 | new Vector3(0f, 0.5108f, -0.5856f), 72 | new Vector3(359.9774f, 0f, 337.0312f)); 73 | 74 | var offsetConfig = ScriptableObject.CreateInstance(); 75 | offsetConfig.name = "Nightmare_MountConfig"; 76 | 77 | offsetConfig.offsets = [ 78 | new RaceMountOffsetsConfig.MountOffsetData() { 79 | Races = BlueprintRoot.Instance.Progression.m_CharacterRaces.ToList(), 80 | RootPosition = new Vector3(0f, 0f, 0.5f), 81 | RootBattlePosition = new Vector3(0f, 0f, 0.5f), 82 | 83 | SaddleRootPosition = Vector3.zero, 84 | SaddleRootScale = Vector3.one, 85 | SaddleRootRotation = new Vector4(0, 0, 0, 1), 86 | 87 | PelvisPosition = Vector3.zero, 88 | PelvisRotation = new Vector4(0, 0, 0, 1), 89 | 90 | LeftFootPosition = Vector3.zero, 91 | LeftFootRotation = new Vector4(0, 0, 0, 1), 92 | 93 | RightFootPosition = Vector3.zero, 94 | RightFootRotation = new Vector4(0, 0, 0, 1), 95 | 96 | LeftKneePosition = Vector3.zero, 97 | 98 | RightKneePosition = Vector3.zero, 99 | 100 | HandsPosition = new Vector3(0.15f, -0.4f, 1.2f), 101 | 102 | PelvisPositionWeight = 0.9f, 103 | PelvisRotationWeight = 1.0f, 104 | FootsPositionWeight = 1.0f, 105 | FootsRotationWeight = 1.0f, 106 | KneesBendWeight = 1.0f, 107 | HandsPositionWeight = 1.0f, 108 | HandsMappingWeight = 0.7f, 109 | } 110 | ]; 111 | offsets.OffsetsConfig = offsetConfig; 112 | } 113 | 114 | 115 | } 116 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/AntipaladinAlignmentRestriction.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 8 | internal class AntipaladinAlignmentRestriction 9 | { 10 | internal static void AddAntipaladinAlignmentRestriction() 11 | { 12 | var SpellbookRef = MCEContext.GetModBlueprintReference("AntipaladinSpellbook"); 13 | 14 | Helpers.CreateBlueprint(MCEContext, "AntipaladinAlignmentRestriction", bp => 15 | { 16 | bp.SetName(MCEContext, "Alignment Restriction"); 17 | bp.SetDescription(MCEContext, "An antipaladin who ceases to be evil loses all antipaladin {g|Encyclopedia:Spell}spells{/g} " + 18 | "and class features. He cannot thereafter gain levels as an antipaladin until he " + 19 | "changes the {g|Encyclopedia:Alignment}alignment{/g} back."); 20 | bp.AddComponent(c => 21 | { 22 | c.m_Spellbooks = [ 23 | SpellbookRef 24 | ]; 25 | c.Alignment = Kingmaker.UnitLogic.Alignments.AlignmentMaskType.Evil; 26 | c.m_IgnoreFact = GetBPRef("24e78475f0a243e1a810452d14d0a1bd"); 27 | }); 28 | bp.IsClassFeature = true; 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/AuraofCowardice.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Spells; 4 | using Kingmaker.Designers.Mechanics.Facts; 5 | using Kingmaker.Enums; 6 | using Kingmaker.UnitLogic.Abilities.Blueprints; 7 | using Kingmaker.UnitLogic.Buffs.Blueprints; 8 | using Kingmaker.UnitLogic.Buffs.Components; 9 | using Kingmaker.UnitLogic.Mechanics; 10 | using Kingmaker.UnitLogic.Mechanics.Components; 11 | using MicroscopicContentExpansion.NewComponents; 12 | using MicroscopicContentExpansion.Utils; 13 | using TabletopTweaks.Core.NewComponents; 14 | using TabletopTweaks.Core.Utilities; 15 | 16 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 17 | internal class AuraofCowardice 18 | { 19 | private const string NAME = "Aura of Cowardice"; 20 | private const string DESCRIPTION = "At 3rd level, an antipaladin radiates a palpably daunting aura that causes all enemies" + 21 | " within 10 feet to take a –4 penalty on saving throws against fear effects. Creatures that are normally immune to" + 22 | " fear lose that immunity while within 10 feet of an antipaladin with this ability. This ability functions only" + 23 | " while the antipaladin remains conscious, not if he is unconscious or dead."; 24 | 25 | public static void AddAuraOfCowardiceFeature() 26 | { 27 | var AOCIcon = GetBP("d2aeac47450c76347aebbc02e4f463e0").Icon; 28 | var AntipaladinClassRef = MCEContext.GetModBlueprintReference("AntipaladinClass"); 29 | 30 | var AuraOfCowardiceEffectBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfCowardiceEffectBuff", bp => 31 | { 32 | bp.SetName(MCEContext, NAME); 33 | bp.SetDescription(MCEContext, DESCRIPTION); 34 | bp.m_Icon = AOCIcon; 35 | 36 | bp.AddComponent(c => 37 | { 38 | c.SpellDescriptor = SpellDescriptor.Fear; 39 | c.ModifierDescriptor = ModifierDescriptor.Penalty; 40 | c.Value = new ContextValue() 41 | { 42 | ValueType = ContextValueType.Rank 43 | }; 44 | }); 45 | 46 | bp.AddComponent(c => 47 | { 48 | c.m_BaseValueType = ContextRankBaseValueType.ClassLevel; 49 | c.m_Progression = ContextRankProgression.Custom; 50 | c.m_Class = [AntipaladinClassRef]; 51 | c.m_CustomProgression = [ 52 | new ContextRankConfig.CustomProgressionItem() { 53 | BaseValue = 7, 54 | ProgressionValue = -4 55 | }, 56 | new ContextRankConfig.CustomProgressionItem() { 57 | BaseValue = 100, 58 | ProgressionValue = -2 59 | } 60 | ]; 61 | }); 62 | 63 | bp.AddComponent(c => 64 | { 65 | c.Descriptor = SpellDescriptor.Fear | SpellDescriptor.Shaken | SpellDescriptor.Frightened; 66 | }); 67 | 68 | bp.AddComponent(c => 69 | { 70 | c.Descriptor = SpellDescriptor.Fear | SpellDescriptor.Shaken | SpellDescriptor.Frightened; 71 | }); 72 | }); 73 | 74 | 75 | var AuraOfCowardiceArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 76 | modContext: MCEContext, 77 | bpName: "AntipaladinAuraOfCowardiceArea", 78 | size: 13, 79 | buff: AuraOfCowardiceEffectBuff.ToReference() 80 | ); 81 | 82 | var AuraOfCowardiceWidenArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 83 | modContext: MCEContext, 84 | bpName: "AntipaladinAuraOfCowardiceWidenArea", 85 | size: 22, 86 | buff: AuraOfCowardiceEffectBuff.ToReference() 87 | ); 88 | 89 | var AuraOfCowardiceBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfCowardiceBuff", bp => 90 | { 91 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 92 | bp.AddComponent(c => 93 | { 94 | c.m_AreaEffect = AuraOfCowardiceArea.ToReference(); 95 | }); 96 | }); 97 | 98 | var AuraOfCowardiceWidenBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfCowardiceWidenBuff", bp => 99 | { 100 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 101 | bp.AddComponent(c => 102 | { 103 | c.m_AreaEffect = AuraOfCowardiceWidenArea.ToReference(); 104 | }); 105 | }); 106 | 107 | var AuraOfCowardiceFeature = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfCowardiceFeature", bp => 108 | { 109 | bp.SetName(MCEContext, NAME); 110 | bp.SetDescription(MCEContext, DESCRIPTION); 111 | bp.m_Icon = AOCIcon; 112 | bp.AddComponent(c => 113 | { 114 | c.DefaultBuff = AuraOfCowardiceBuff.ToReference(); 115 | c.WidenFact = MCEContext.GetModBlueprintReference("WidenAurasBuff"); 116 | c.WidenBuff = AuraOfCowardiceWidenBuff.ToReference(); 117 | }); 118 | }); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/AuraofDepravity.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Spells; 4 | using Kingmaker.Designers.Mechanics.Facts; 5 | using Kingmaker.Enums; 6 | using Kingmaker.UnitLogic.Buffs.Blueprints; 7 | using Kingmaker.UnitLogic.Buffs.Components; 8 | using Kingmaker.UnitLogic.FactLogic; 9 | using MicroscopicContentExpansion.NewComponents; 10 | using MicroscopicContentExpansion.Utils; 11 | using TabletopTweaks.Core.Utilities; 12 | 13 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 14 | internal class AuraofDepravity 15 | { 16 | private const string NAME = "Aura of Depravity"; 17 | private const string DESCRIPTION = "At 17th level, an antipaladin gains DR 5/good. Each enemy within 10 feet takes a –4 penalty" + 18 | " on saving throws against compulsion effects. This ability functions only while the antipaladin is conscious, not if he is" + 19 | " unconscious or dead."; 20 | 21 | public static void AddAuraOfDepravityFeature() 22 | { 23 | var AOCIcon = GetBP("d673c30720e8e7c4bb0903dc3c9ab649").Icon; 24 | 25 | var AntipaladinClassRef = MCEContext.GetModBlueprintReference("AntipaladinClass"); 26 | 27 | var AuraOfDepravityEffectBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDepravityEffectBuff", bp => 28 | { 29 | bp.SetName(MCEContext, NAME); 30 | bp.SetDescription(MCEContext, DESCRIPTION); 31 | bp.m_Icon = AOCIcon; 32 | bp.AddComponent(c => 33 | { 34 | c.SpellDescriptor = SpellDescriptor.Compulsion; 35 | c.ModifierDescriptor = ModifierDescriptor.Penalty; 36 | c.Value = -4; 37 | c.Bonus = 0; 38 | }); 39 | }); 40 | 41 | var AuraOfDepravityArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 42 | modContext: MCEContext, 43 | bpName: "AntipaladinAuraOfDepravityArea", 44 | size: 13, 45 | buff: AuraOfDepravityEffectBuff.ToReference() 46 | ); 47 | 48 | var AuraOfDepravityWidenArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 49 | modContext: MCEContext, 50 | bpName: "AntipaladinAuraOfDepravityWidenArea", 51 | size: 22, 52 | buff: AuraOfDepravityEffectBuff.ToReference() 53 | ); 54 | 55 | var AuraOfDepravityBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDepravityBuff", bp => 56 | { 57 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 58 | bp.AddComponent(c => 59 | { 60 | c.m_AreaEffect = AuraOfDepravityArea.ToReference(); 61 | }); 62 | }); 63 | 64 | var AuraOfDepravityWidenBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDepravityWidenBuff", bp => 65 | { 66 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 67 | bp.AddComponent(c => 68 | { 69 | c.m_AreaEffect = AuraOfDepravityWidenArea.ToReference(); 70 | }); 71 | }); 72 | 73 | var AuraOfDepravityFeature = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDepravityFeature", bp => 74 | { 75 | bp.SetName(MCEContext, NAME); 76 | bp.SetDescription(MCEContext, DESCRIPTION); 77 | bp.m_Icon = AOCIcon; 78 | bp.AddComponent(c => 79 | { 80 | c.DefaultBuff = AuraOfDepravityBuff.ToReference(); 81 | c.WidenFact = MCEContext.GetModBlueprintReference("WidenAurasBuff"); 82 | c.WidenBuff = AuraOfDepravityWidenBuff.ToReference(); 83 | }); 84 | bp.AddComponent(c => 85 | { 86 | c.BypassedByAlignment = true; 87 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Good; 88 | c.Value = 5; 89 | }); 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/AuraofDespair.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using Kingmaker.UnitLogic.Buffs.Blueprints; 5 | using Kingmaker.UnitLogic.Buffs.Components; 6 | using Kingmaker.UnitLogic.FactLogic; 7 | using MicroscopicContentExpansion.NewComponents; 8 | using MicroscopicContentExpansion.Utils; 9 | using TabletopTweaks.Core.Utilities; 10 | 11 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 12 | internal class AuraofDespair 13 | { 14 | private const string NAME = "Aura of Despair"; 15 | private const string DESCRIPTION = "At 8th level, enemies within 10 feet of an antipaladin take a –2 penalty on all saving throws." + 16 | " This penalty does not stack with the penalty from aura of cowardice.\nThis ability functions only while the antipaladin is" + 17 | " conscious, not if he is unconscious or dead."; 18 | 19 | public static void AddAuraOfDespairFeature() 20 | { 21 | 22 | var CrushingDespairIcon = GetBP("4baf4109145de4345861fe0f2209d903").Icon; 23 | var AuraOfDespairEffectBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDespairEffectBuff", bp => 24 | { 25 | bp.SetName(MCEContext, NAME); 26 | bp.SetDescription(MCEContext, DESCRIPTION); 27 | bp.m_Icon = CrushingDespairIcon; 28 | bp.AddComponent(c => 29 | { 30 | c.Descriptor = Kingmaker.Enums.ModifierDescriptor.Penalty; 31 | c.Value = -2; 32 | c.Stat = Kingmaker.EntitySystem.Stats.StatType.SaveFortitude; 33 | }); 34 | bp.AddComponent(c => 35 | { 36 | c.Descriptor = Kingmaker.Enums.ModifierDescriptor.Penalty; 37 | c.Value = -2; 38 | c.Stat = Kingmaker.EntitySystem.Stats.StatType.SaveReflex; 39 | }); 40 | bp.AddComponent(c => 41 | { 42 | c.Descriptor = Kingmaker.Enums.ModifierDescriptor.Penalty; 43 | c.Value = -2; 44 | c.Stat = Kingmaker.EntitySystem.Stats.StatType.SaveWill; 45 | }); 46 | }); 47 | 48 | var AuraOfDespairArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 49 | modContext: MCEContext, 50 | bpName: "AntipaladinAuraOfDespairArea", 51 | size: 13, 52 | buff: AuraOfDespairEffectBuff.ToReference() 53 | ); 54 | 55 | var AuraOfDespairWidenArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 56 | modContext: MCEContext, 57 | bpName: "AntipaladinAuraOfDespairWidenArea", 58 | size: 22, 59 | buff: AuraOfDespairEffectBuff.ToReference() 60 | ); 61 | 62 | var AuraOfDespairBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDespairBuff", bp => 63 | { 64 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 65 | bp.AddComponent(c => 66 | { 67 | c.m_AreaEffect = AuraOfDespairArea.ToReference(); 68 | }); 69 | }); 70 | 71 | var AuraOfDespairWidenBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDespairWidenBuff", bp => 72 | { 73 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 74 | bp.AddComponent(c => 75 | { 76 | c.m_AreaEffect = AuraOfDespairWidenArea.ToReference(); 77 | }); 78 | }); 79 | 80 | var AuraOfDespairFeature = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfDespairFeature", bp => 81 | { 82 | bp.SetName(MCEContext, NAME); 83 | bp.SetDescription(MCEContext, DESCRIPTION); 84 | bp.m_Icon = CrushingDespairIcon; 85 | bp.AddComponent(c => 86 | { 87 | c.DefaultBuff = AuraOfDespairBuff.ToReference(); 88 | c.WidenFact = MCEContext.GetModBlueprintReference("WidenAurasBuff"); 89 | c.WidenBuff = AuraOfDespairWidenBuff.ToReference(); 90 | }); 91 | }); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/AuraofSin.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using Kingmaker.UnitLogic.Buffs.Blueprints; 5 | using Kingmaker.UnitLogic.Buffs.Components; 6 | using Kingmaker.UnitLogic.FactLogic; 7 | using MicroscopicContentExpansion.NewComponents; 8 | using MicroscopicContentExpansion.Utils; 9 | using TabletopTweaks.Core.Utilities; 10 | 11 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 12 | internal class AuraofSin 13 | { 14 | private const string NAME = "Aura of Sin"; 15 | private const string DESCRIPTION = "At 14th level, an antipaladin’s weapons are treated as evil-aligned for the purposes" + 16 | " of overcoming damage reduction. Any attack made against an enemy within 10 feet of him is treated as evil-aligned" + 17 | " for the purposes of overcoming damage reduction. This ability functions only while the antipaladin is conscious," + 18 | " not if he is unconscious or dead."; 19 | 20 | public static void AddAuraOfSinFeature() 21 | { 22 | var AOSIcon = GetBP("8bc64d869456b004b9db255cdd1ea734").Icon; 23 | 24 | var AuraOfSinEffectBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfSinEffectBuff", bp => 25 | { 26 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 27 | bp.AddComponent(c => 28 | { 29 | c.AddAlignment = true; 30 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Evil; 31 | }); 32 | }); 33 | 34 | var AuraOfSinArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 35 | modContext: MCEContext, 36 | bpName: "AntipaladinAuraOfSinArea", 37 | size: 13, 38 | buff: AuraOfSinEffectBuff.ToReference() 39 | ); 40 | 41 | var AuraOfSinWidenArea = AuraUtils.CreateUnconditionalHostileAuraEffect( 42 | modContext: MCEContext, 43 | bpName: "AntipaladinAuraOfSinWidenArea", 44 | size: 22, 45 | buff: AuraOfSinEffectBuff.ToReference() 46 | ); 47 | 48 | var AuraOfSinBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfSinBuff", bp => 49 | { 50 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 51 | bp.AddComponent(c => 52 | { 53 | c.m_AreaEffect = AuraOfSinArea.ToReference(); 54 | }); 55 | }); 56 | 57 | var AuraOfSinWidenBuff = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfSinWidenBuff", bp => 58 | { 59 | bp.m_Flags = BlueprintBuff.Flags.HiddenInUi; 60 | bp.AddComponent(c => 61 | { 62 | c.m_AreaEffect = AuraOfSinWidenArea.ToReference(); 63 | }); 64 | }); 65 | 66 | var AuraOfSinFeature = Helpers.CreateBlueprint(MCEContext, "AntipaladinAuraOfSinFeature", bp => 67 | { 68 | bp.SetName(MCEContext, NAME); 69 | bp.SetDescription(MCEContext, DESCRIPTION); 70 | bp.m_Icon = AOSIcon; 71 | bp.AddComponent(c => 72 | { 73 | c.DefaultBuff = AuraOfSinBuff.ToReference(); 74 | c.WidenFact = MCEContext.GetModBlueprintReference("WidenAurasBuff"); 75 | c.WidenBuff = AuraOfSinWidenBuff.ToReference(); 76 | }); 77 | bp.AddComponent(c => 78 | { 79 | c.AddAlignment = true; 80 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Evil; 81 | }); 82 | }); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/PlagueBringer.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints.Classes; 2 | using Kingmaker.Blueprints.Classes.Spells; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 7 | internal class PlagueBringer 8 | { 9 | public static void AddPlagueBringer() 10 | { 11 | var PlagueBringer = Helpers.CreateBlueprint(MCEContext, "AntipaladinPlagueBringer", bp => 12 | { 13 | bp.SetName(MCEContext, "Plague Bringer"); 14 | bp.SetDescription(MCEContext, "At 3rd level, the powers of darkness make an antipaladin a beacon of " + 15 | "corruption and disease. An antipaladin does not take any damage or take any penalty from diseases."); 16 | bp.Ranks = 1; 17 | bp.IsClassFeature = true; 18 | bp.AddComponent(c => { c.Descriptor = SpellDescriptor.Disease; }); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/TipoftheSpear.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 7 | internal class TipoftheSpear 8 | { 9 | private const string NAME = "Tip of the Spear"; 10 | private const string DESCRIPTION = "At 11th level, the antipaladin tears through heroes and " + 11 | "rival villains alike. The antipaladin can smite foes regardless of their alignment."; 12 | 13 | public static void AddTipoftheSpear() 14 | { 15 | var AntipaladinClassRef = MCEContext.GetModBlueprintReference("AntipaladinClass"); 16 | var SmiteGoodResource = MCEContext.GetModBlueprintReference("AntipaladinSmiteGoodResource"); 17 | 18 | var TipoftheSpear = Helpers.CreateBlueprint(MCEContext, "AntipaladinTipoftheSpear", bp => 19 | { 20 | bp.SetName(MCEContext, NAME); 21 | bp.SetDescription(MCEContext, DESCRIPTION); 22 | bp.IsClassFeature = true; 23 | bp.AddComponent(c => 24 | { 25 | c.m_Resource = SmiteGoodResource; 26 | c.Value = 3; 27 | }); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/UnholyChampion.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Selection; 4 | using Kingmaker.Designers.Mechanics.Facts; 5 | using Kingmaker.UnitLogic.FactLogic; 6 | using TabletopTweaks.Core.Utilities; 7 | 8 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 9 | internal class UnholyChampion 10 | { 11 | private const string NAME = "Unholy Champion"; 12 | private const string DESCRIPTION = "At 20th level, an antipaladin becomes a conduit for the might of the dark " + 13 | "powers. His DR increases to 10/good. In addition, whenever he channels negative energy or uses touch of " + 14 | "corruption to damage a creature, he deals the maximum possible amount."; 15 | 16 | public static void AddUnholyChampion() 17 | { 18 | var UnholyChampion = Helpers.CreateBlueprint(MCEContext, "AntipaladinUnholyChampion", bp => 19 | { 20 | bp.SetName(MCEContext, NAME); 21 | bp.SetDescription(MCEContext, DESCRIPTION); 22 | bp.Ranks = 1; 23 | bp.IsClassFeature = true; 24 | bp.AddComponent(c => 25 | { 26 | c.Material = Kingmaker.Enums.Damage.PhysicalDamageMaterial.Adamantite; 27 | c.BypassedByAlignment = true; 28 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Good; 29 | c.Reality = Kingmaker.Enums.Damage.DamageRealityType.Ghost; 30 | c.Value = 10; 31 | c.Pool = 12; 32 | }); 33 | bp.AddComponent(c => 34 | { 35 | c.m_AllowedAbilities = AutoMetamagic.AllowedType.Any; 36 | c.Metamagic = Kingmaker.UnitLogic.Abilities.Metamagic.Maximize; 37 | c.Abilities = [ 38 | MCEContext.GetModBlueprintReference("AntipaladinChannelEnergyHarm"), 39 | MCEContext.GetModBlueprintReference("AntipaladinChannelEnergyHeal"), 40 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionUnmodified"), 41 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionBlinded"), 42 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionCursed"), 43 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionDazed"), 44 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionDiseased"), 45 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionExhausted"), 46 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionFatigued"), 47 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionFrightened"), 48 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionNauseated"), 49 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionParalyzed"), 50 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionPoisoned"), 51 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionShaken"), 52 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionSickened"), 53 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionStaggered"), 54 | MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionStunned") 55 | ]; 56 | }); 57 | }); 58 | 59 | var perfectBodyFlawlessMind = GetBPRef("cb61beef-4f35-4992-a09e-821d170a6582"); 60 | 61 | var markOfVengeance = BlueprintTools.GetModBlueprintReference(MCEContext, "AntipaladinAuraOfVengeanceFeature"); 62 | 63 | Helpers.CreateBlueprint(MCEContext, "AntipaladinCapstone", bp => 64 | { 65 | bp.SetName(MCEContext, "Antipaladin Capstone"); 66 | bp.SetDescription(MCEContext, "At 20th level, antipaladin gains a powerful class feature"); 67 | bp.m_AllFeatures = [ 68 | UnholyChampion.ToReference(), 69 | perfectBodyFlawlessMind, 70 | markOfVengeance 71 | ]; 72 | bp.Mode = SelectionMode.Default; 73 | bp.Groups = [FeatureGroup.None]; 74 | bp.IsClassFeature = true; 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/AntipaladinFeatures/UnholyResilience.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints.Classes; 2 | using Kingmaker.Designers.Mechanics.Facts; 3 | using Kingmaker.EntitySystem.Stats; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | namespace MicroscopicContentExpansion.NewContent.AntipaladinFeatures; 7 | internal class UnholyResilience 8 | { 9 | public static void AddUnholyResilience() 10 | { 11 | var UnholyResilience = Helpers.CreateBlueprint(MCEContext, "AntipaladinUnholyResilience", bp => 12 | { 13 | bp.SetName(MCEContext, "Unholy Resilience"); 14 | bp.SetDescription(MCEContext, "At 2nd level, an antipaladin gains a bonus equal to his Charisma bonus (if any) on all saving throws."); 15 | bp.Ranks = 1; 16 | bp.IsClassFeature = true; 17 | bp.AddComponent(c => 18 | { 19 | c.BaseStat = StatType.Charisma; 20 | c.DerivativeStat = StatType.SaveFortitude; 21 | }); 22 | bp.AddComponent(c => 23 | { 24 | c.BaseStat = StatType.Charisma; 25 | c.DerivativeStat = StatType.SaveWill; 26 | }); 27 | bp.AddComponent(c => 28 | { 29 | c.BaseStat = StatType.Charisma; 30 | c.DerivativeStat = StatType.SaveReflex; 31 | }); 32 | bp.AddComponent(c => 33 | { 34 | c.Stat = StatType.Charisma; 35 | }); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/DreadVanguard.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using MicroscopicContentExpansion.NewContent.Archetypes.DreadVanguardFeatures; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | namespace MicroscopicContentExpansion.NewContent.Archetypes; 7 | internal class DreadVanguard 8 | { 9 | private const string NAME = "Dread Vanguard"; 10 | private const string DESCRIPTION = "Some antipaladins serve or ally themselves with villains who are bent on " + 11 | "earthly conquest. They care nothing for the intricacies of divine spellcasting, but malevolent energy " + 12 | "still surrounds them. Whether alone or at the head of a marauding host, these cruel warriors bring suffering" + 13 | " and death—but their presence also heralds the coming of a greater evil."; 14 | 15 | public static void AddDreadVanguard() 16 | { 17 | var antipaladinClass = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinClass"); 18 | var touchOfCorruptionUse = MCEContext.GetModBlueprintReference("AntipaladinTouchOfCorruptionAdditionalUse"); 19 | 20 | var beacon5 = BeaconOfEvil20.AddBeaconOfEvil(); 21 | var beacon1 = BeaconOfEvil.AddBeaconOfEvil(); 22 | var beacon2 = BeaconOfEvil8.AddBeaconOfEvil(); 23 | var beacon3 = BeaconOfEvil12.AddBeaconOfEvil(); 24 | var beacon4 = BeaconOfEvil16.AddBeaconOfEvil(); 25 | 26 | 27 | 28 | var DreadVanguard = Helpers.CreateBlueprint(MCEContext, "DreadVanguardArchetype", bp => 29 | { 30 | bp.LocalizedName = Helpers.CreateString(MCEContext, $"{bp.name}.Name", NAME); 31 | bp.LocalizedDescription = Helpers.CreateString(MCEContext, $"{bp.name}.Description", DESCRIPTION); 32 | bp.LocalizedDescriptionShort = Helpers.CreateString(MCEContext, $"{bp.name}.Description", DESCRIPTION); 33 | bp.RemoveFeatures = []; 34 | bp.RemoveSpellbook = true; 35 | bp.AddFeatures = [ 36 | Helpers.CreateLevelEntry(4, touchOfCorruptionUse, beacon1), 37 | Helpers.CreateLevelEntry(8, touchOfCorruptionUse, beacon2), 38 | Helpers.CreateLevelEntry(12, touchOfCorruptionUse, beacon3), 39 | Helpers.CreateLevelEntry(16, touchOfCorruptionUse, beacon4), 40 | Helpers.CreateLevelEntry(20, touchOfCorruptionUse, beacon5) 41 | ]; 42 | }); 43 | 44 | var Archetypes = antipaladinClass.m_Archetypes.AppendToArray(DreadVanguard.ToReference()); 45 | antipaladinClass.m_Archetypes = Archetypes; 46 | 47 | var DVBeaconUIGroup = Helpers.CreateUIGroup(beacon1, beacon2, beacon3, beacon4, beacon5); 48 | var antipaladinProgression = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinProgression"); 49 | antipaladinProgression.UIGroups = antipaladinProgression.UIGroups.AppendToArray(DVBeaconUIGroup); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/DreadVanguardFeatures/BeaconOfEvil12.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.DreadVanguardFeatures; 8 | internal class BeaconOfEvil12 9 | { 10 | const string NAME = "Beacon of Evil"; 11 | 12 | const string DESCRIPTION = "At 12th level, when he activates this ability, a dread vanguard can choose to increase " + 13 | "the radius of one antipaladin aura he possesses to 30 feet. Also, the morale bonus granted to AC and on attack" + 14 | " rolls, damage rolls, and saving throws against fear increases to +2."; 15 | 16 | public static BlueprintFeatureReference AddBeaconOfEvil() 17 | { 18 | var AntipaladinClass = MCEContext.GetModBlueprintReference("AntipaladinClass"); 19 | 20 | var icon = GetBP("a02cf51787df937489ef5d4cf5970335").Icon; 21 | 22 | return Helpers.CreateBlueprint(MCEContext, "DreadVanguardBeaconOfEvilFeature12", bp => 23 | { 24 | bp.SetName(MCEContext, $"{NAME}"); 25 | bp.SetDescription(MCEContext, DESCRIPTION); 26 | bp.IsClassFeature = true; 27 | bp.m_Icon = icon; 28 | }).ToReference(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/DreadVanguardFeatures/BeaconOfEvil16.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.DreadVanguardFeatures; 8 | internal class BeaconOfEvil16 9 | { 10 | const string NAME = "Beacon of Evil"; 11 | 12 | const string DESCRIPTION = "At 16th level, the fast healing granted by this ability increases to 5." + 13 | " Additionally, the antipaladin’s weapons and those of his allies within the aura’s radius are" + 14 | " considered evil for the purpose of overcoming damage reduction."; 15 | 16 | public static BlueprintFeatureReference AddBeaconOfEvil() 17 | { 18 | var AntipaladinClass = MCEContext.GetModBlueprintReference("AntipaladinClass"); 19 | 20 | var icon = GetBP("a02cf51787df937489ef5d4cf5970335").Icon; 21 | 22 | return Helpers.CreateBlueprint(MCEContext, "DreadVanguardBeaconOfEvilFeature16", bp => 23 | { 24 | bp.SetName(MCEContext, $"{NAME}"); 25 | bp.SetDescription(MCEContext, DESCRIPTION); 26 | bp.IsClassFeature = true; 27 | bp.m_Icon = icon; 28 | }).ToReference(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/DreadVanguardFeatures/BeaconOfEvil20.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.DreadVanguardFeatures; 8 | internal class BeaconOfEvil20 9 | { 10 | const string NAME = "Beacon of Evil"; 11 | 12 | const string DESCRIPTION = "At 20th level, the beacon of evil’s radius increases to 50 feet, " + 13 | "and the morale bonus granted to AC and on attack rolls, damage rolls, and saving throws " + 14 | "against fear increases to +4. Lastly, attacks made by the dread vanguard and his allies " + 15 | "within the aura’s radius are infused with pure unholy power, and deal an additional 1d6 " + 16 | "points of damage."; 17 | 18 | public static BlueprintFeatureReference AddBeaconOfEvil() 19 | { 20 | var AntipaladinClass = MCEContext.GetModBlueprintReference("AntipaladinClass"); 21 | 22 | var icon = GetBP("a02cf51787df937489ef5d4cf5970335").Icon; 23 | 24 | return Helpers.CreateBlueprint(MCEContext, "DreadVanguardBeaconOfEvilFeature20", bp => 25 | { 26 | bp.SetName(MCEContext, $"{NAME}"); 27 | bp.SetDescription(MCEContext, DESCRIPTION); 28 | bp.IsClassFeature = true; 29 | bp.m_Icon = icon; 30 | }).ToReference(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/DreadVanguardFeatures/BeaconOfEvil8.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.DreadVanguardFeatures; 8 | internal class BeaconOfEvil8 9 | { 10 | const string NAME = "Beacon of Evil"; 11 | 12 | const string DESCRIPTION = "At 8th level, the aura grants fast healing 3 to the dread vanguard" + 13 | " as well as to his allies while they remain within it."; 14 | 15 | public static BlueprintFeatureReference AddBeaconOfEvil() 16 | { 17 | var AntipaladinClass = MCEContext.GetModBlueprintReference("AntipaladinClass"); 18 | 19 | var icon = GetBP("a02cf51787df937489ef5d4cf5970335").Icon; 20 | 21 | return Helpers.CreateBlueprint(MCEContext, "DreadVanguardBeaconOfEvilFeature8", bp => 22 | { 23 | bp.SetName(MCEContext, $"{NAME}"); 24 | bp.SetDescription(MCEContext, DESCRIPTION); 25 | bp.IsClassFeature = true; 26 | bp.m_Icon = icon; 27 | }).ToReference(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcher.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | namespace MicroscopicContentExpansion.NewContent.Archetypes; 7 | internal class KnightoftheSepulcher 8 | { 9 | private const string NAME = "Knight of the Sepulcher"; 10 | private const string DESCRIPTION = "Not content with the antipaladin’s mere corruption of the soul, the knight of the sepulcher sacrifices mortality along with morality."; 11 | 12 | public static void AddKnightoftheSepulcher() 13 | { 14 | var antipaladinClass = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinClass"); 15 | 16 | var fiendishBoon = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinFiendishBoonSelection"); 17 | var auraOfDespair = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinAuraOfDespairFeature"); 18 | var smiteGoodAdditionalUse = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinSmiteGoodAdditionalUse"); 19 | var auraOfSin = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinAuraOfSinFeature"); 20 | var crueltySelection = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinCrueltySelection"); 21 | var auraOfDepravity = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinAuraOfDepravityFeature"); 22 | var capstone = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinCapstone"); 23 | 24 | 25 | var touchoftheCrypt = TouchoftheCrypt.AddTouchoftheCrypt(); 26 | var fortitudeoftheCrypt = FortitudeoftheCrypt.AddFortitudeoftheCrypt(); 27 | var cloakoftheCrypt = CloakoftheCrypt.AddCloakoftheCrypt(); 28 | var willoftheCrypt = WilloftheCrypt.AddWilloftheCrypt(); 29 | var weaponsofSin = WeaponsofSin.AddWeaponsofSin(); 30 | var cryptLord = CryptLord.AddCryptLord(); 31 | var souloftheCrypt = SouloftheCrypt.AddSouloftheCrypt(); 32 | var undyingChampion = UndyingChampion.AddUndyingChampion(); 33 | 34 | var knightoftheSepulcher = Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherArchetype", bp => 35 | { 36 | bp.LocalizedName = Helpers.CreateString(MCEContext, $"{bp.name}.Name", NAME); 37 | bp.LocalizedDescription = Helpers.CreateString(MCEContext, $"{bp.name}.Description", DESCRIPTION); 38 | bp.LocalizedDescriptionShort = Helpers.CreateString(MCEContext, $"{bp.name}.Description", DESCRIPTION); 39 | bp.RemoveFeatures = [ 40 | Helpers.CreateLevelEntry(5, fiendishBoon), 41 | Helpers.CreateLevelEntry(8, auraOfDespair), 42 | Helpers.CreateLevelEntry(10, smiteGoodAdditionalUse), 43 | Helpers.CreateLevelEntry(14, auraOfSin), 44 | Helpers.CreateLevelEntry(15, crueltySelection), 45 | Helpers.CreateLevelEntry(17, auraOfDepravity), 46 | Helpers.CreateLevelEntry(20, capstone) 47 | ]; 48 | bp.AddFeatures = [ 49 | Helpers.CreateLevelEntry(5, touchoftheCrypt), 50 | Helpers.CreateLevelEntry(8, fortitudeoftheCrypt), 51 | Helpers.CreateLevelEntry(10, cloakoftheCrypt), 52 | Helpers.CreateLevelEntry(14, weaponsofSin), 53 | Helpers.CreateLevelEntry(15, cryptLord), 54 | Helpers.CreateLevelEntry(17, souloftheCrypt), 55 | Helpers.CreateLevelEntry(20, undyingChampion) 56 | ]; 57 | }); 58 | 59 | var archetypes = antipaladinClass.m_Archetypes.AppendToArray(knightoftheSepulcher.ToReference()); 60 | antipaladinClass.m_Archetypes = archetypes; 61 | 62 | var KotSUIGroup = Helpers.CreateUIGroup(touchoftheCrypt, fortitudeoftheCrypt, cloakoftheCrypt, 63 | willoftheCrypt, weaponsofSin, cryptLord, souloftheCrypt, undyingChampion); 64 | var antipaladinProgression = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinProgression"); 65 | antipaladinProgression.UIGroups = antipaladinProgression.UIGroups.AppendToArray(KotSUIGroup); 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/CloakoftheCrypt.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 8 | internal class CloakoftheCrypt 9 | { 10 | 11 | public static BlueprintFeatureReference AddCloakoftheCrypt() 12 | { 13 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherCloakoftheCrypt", bp => 14 | { 15 | bp.SetName(MCEContext, "Cloak of the Crypt"); 16 | bp.SetDescription(MCEContext, "At 10th level, the knight of the sepulcher gains immunity to energy drain " + 17 | "and harmful negative energy effects. His chance of ignoring critical hits and sneak attacks increases" + 18 | " to 50%, as though he were wearing armor of moderate fortification."); 19 | bp.AddComponent(); 20 | bp.AddComponent(c => 21 | { 22 | c.Bonus = 50; 23 | }); 24 | bp.IsClassFeature = true; 25 | }).ToReference(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/CryptLord.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Spells; 4 | using Kingmaker.UnitLogic.FactLogic; 5 | using TabletopTweaks.Core.Utilities; 6 | 7 | 8 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 9 | internal class CryptLord 10 | { 11 | 12 | public static BlueprintFeatureReference AddCryptLord() 13 | { 14 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherCryptLord", bp => 15 | { 16 | bp.SetName(MCEContext, "Crypt Lord"); 17 | bp.SetDescription(MCEContext, "At 15th level, a knight of the sepulcher’s chance of ignoring critical hits " + 18 | "and sneak attacks increases to 75%, as though he were wearing armor of heavy fortification. " + 19 | "He gains immunity to death effects, paralysis, sleep effects, and stunning. He no longer sleeps. " + 20 | "The knight of the sepulcher also gains immunity to fatigue."); 21 | bp.AddComponent(c => 22 | { 23 | c.Bonus = 75; 24 | }); 25 | bp.AddComponent(c => 26 | { 27 | c.Descriptor = SpellDescriptor.Sleep | SpellDescriptor.Paralysis | SpellDescriptor.Death | SpellDescriptor.Fatigue | SpellDescriptor.Stun; 28 | }); 29 | bp.IsClassFeature = true; 30 | }).ToReference(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/FortitudeoftheCrypt.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Spells; 4 | using Kingmaker.UnitLogic.FactLogic; 5 | using TabletopTweaks.Core.Utilities; 6 | 7 | 8 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 9 | internal class FortitudeoftheCrypt 10 | { 11 | 12 | public static BlueprintFeatureReference AddFortitudeoftheCrypt() 13 | { 14 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherFortitudeoftheCrypt", bp => 15 | { 16 | bp.SetName(MCEContext, "Fortitude of the Crypt"); 17 | bp.SetDescription(MCEContext, "At 8th level, a knight of the sepulcher gains immunity to poison."); 18 | bp.AddComponent(c => 19 | { 20 | c.Descriptor = SpellDescriptor.Poison; 21 | }); 22 | bp.IsClassFeature = true; 23 | }).ToReference(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/SoulOftheCrypt.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 8 | internal class SouloftheCrypt 9 | { 10 | 11 | public static BlueprintFeatureReference AddSouloftheCrypt() 12 | { 13 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherSouloftheCrypt", bp => 14 | { 15 | bp.SetName(MCEContext, "Soul of the Crypt"); 16 | bp.SetDescription(MCEContext, "At 17th level, a knight of the sepulcher gains DR 5/bludgeoning and good."); 17 | bp.IsClassFeature = true; 18 | bp.AddComponent(c => 19 | { 20 | c.Material = Kingmaker.Enums.Damage.PhysicalDamageMaterial.Adamantite; 21 | c.BypassedByAlignment = true; 22 | c.BypassedByForm = true; 23 | c.Form = Kingmaker.Enums.Damage.PhysicalDamageForm.Bludgeoning; 24 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Good; 25 | c.Reality = Kingmaker.Enums.Damage.DamageRealityType.Ghost; 26 | c.Value = 5; 27 | c.Pool = 12; 28 | }); 29 | }).ToReference(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/TouchoftheCrypt.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Spells; 4 | using Kingmaker.Designers.Mechanics.Facts; 5 | using Kingmaker.Enums; 6 | using Kingmaker.UnitLogic.FactLogic; 7 | using TabletopTweaks.Core.Utilities; 8 | 9 | 10 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 11 | internal class TouchoftheCrypt 12 | { 13 | internal static BlueprintFeatureReference AddTouchoftheCrypt() 14 | { 15 | var AntipaladinClassRef = MCEContext.GetModBlueprintReference("AntipaladinClass"); 16 | 17 | var negativeEnergyAffinity = GetBP("d5ee498e19722854198439629c1841a5"); 18 | 19 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherTouchoftheCrypt", bp => 20 | { 21 | bp.SetName(MCEContext, "Touch of the Crypt"); 22 | bp.SetDescription(MCEContext, "At 5th level, a knight of the sepulcher gains a +2 bonus on saving throws against " + 23 | "mind-affecting effects, death effects, and poison. He is harmed by positive energy effects and healed by negative" + 24 | " energy effects as though he were undead, although negative energy effects that don’t heal undead (such as " + 25 | "enervation) affect him normally. The knight of the sepulcher has a 25% chance of ignoring critical hits and the " + 26 | "bonus damage from sneak attacks as though he were wearing armor of light fortification."); 27 | bp.AddComponent(c => 28 | { 29 | c.m_Facts = [ 30 | negativeEnergyAffinity.ToReference() 31 | ]; 32 | }); 33 | bp.AddComponent(c => 34 | { 35 | c.Bonus = 25; 36 | }); 37 | bp.AddComponent(c => 38 | { 39 | c.SpellDescriptor = SpellDescriptor.MindAffecting | SpellDescriptor.Death | SpellDescriptor.Poison; 40 | c.ModifierDescriptor = ModifierDescriptor.UntypedStackable; 41 | c.Value = 2; 42 | }); 43 | bp.IsClassFeature = true; 44 | }).ToReference(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/UndyingChampion.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 8 | internal class UndyingChampion 9 | { 10 | 11 | public static BlueprintFeatureReference AddUndyingChampion() 12 | { 13 | var undeadType = GetBP("734a29b693e9ec346ba2951b27987e33"); 14 | 15 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherUndyingChampion", bp => 16 | { 17 | bp.SetName(MCEContext, "Undying Champion"); 18 | bp.SetDescription(MCEContext, "At 20th level, a knight of the sepulcher joins the ranks of the " + 19 | "undead. His DR increases to 10/bludgeoning and good. His type changes to undead, and he " + 20 | "acquires all undead traits. Although immune to disease, he can still carry and spread " + 21 | "diseases with the antipaladin’s plague bringer ability. The undying champion no longer has " + 22 | "a Constitution score. He uses his Charisma score for calculating hit points, Fortitude saves," + 23 | " and any special abilities that rely on Constitution. "); 24 | bp.IsClassFeature = true; 25 | bp.AddComponent(c => 26 | { 27 | c.m_Facts = [undeadType.ToReference()]; 28 | }); 29 | bp.AddComponent(c => 30 | { 31 | c.Material = Kingmaker.Enums.Damage.PhysicalDamageMaterial.Adamantite; 32 | c.BypassedByAlignment = true; 33 | c.BypassedByForm = true; 34 | c.Form = Kingmaker.Enums.Damage.PhysicalDamageForm.Bludgeoning; 35 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Good; 36 | c.Reality = Kingmaker.Enums.Damage.DamageRealityType.Ghost; 37 | c.Value = 10; 38 | c.Pool = 12; 39 | }); 40 | }).ToReference(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/WeaponsofSin.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 7 | internal class WeaponsofSin 8 | { 9 | private const string NAME = "Weapons of Sin"; 10 | private const string DESCRIPTION = "At 14th level, a knight of the sepulcher’s" + 11 | " weapons are treated as evil-aligned for the purposes of overcoming damage reduction."; 12 | 13 | public static BlueprintFeatureReference AddWeaponsofSin() 14 | { 15 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherWeaponsofSin", bp => 16 | { 17 | bp.SetName(MCEContext, NAME); 18 | bp.SetDescription(MCEContext, DESCRIPTION); 19 | bp.IsClassFeature = true; 20 | bp.AddComponent(c => 21 | { 22 | c.Material = Kingmaker.Enums.Damage.PhysicalDamageMaterial.Adamantite; 23 | c.AddAlignment = true; 24 | c.Alignment = Kingmaker.Enums.Damage.DamageAlignment.Evil; 25 | c.Reality = Kingmaker.Enums.Damage.DamageRealityType.Ghost; 26 | }); 27 | }).ToReference(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/KnightoftheSepulcherFeatures/WilloftheCrypt.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using TabletopTweaks.Core.Utilities; 4 | 5 | namespace MicroscopicContentExpansion.NewContent.Archetypes.KnightoftheSepulcherFeatures; 6 | internal class WilloftheCrypt 7 | { 8 | 9 | public static BlueprintFeatureReference AddWilloftheCrypt() 10 | { 11 | //nothing done here as increase is coded in TouchoftheCrypt.cs 12 | return Helpers.CreateBlueprint(MCEContext, "KnightoftheSepulcherWilloftheCrypt", bp => 13 | { 14 | bp.SetName(MCEContext, "Will of the Crypt"); 15 | bp.SetDescription(MCEContext, "At 11th level, a knight of the sepulcher’s bonus on saving" + 16 | " throws against mind-affecting effects and death effects increases to +4."); 17 | bp.IsClassFeature = true; 18 | }).ToReference(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/Tyrant.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Prerequisites; 4 | using Kingmaker.EntitySystem.Stats; 5 | using MicroscopicContentExpansion.NewContent.Archetypes.TyrantFeatures; 6 | using TabletopTweaks.Core.Utilities; 7 | 8 | namespace MicroscopicContentExpansion.NewContent.Archetypes; 9 | internal class Tyrant 10 | { 11 | private const string NAME = "Tyrant"; 12 | private const string DESCRIPTION = "Evil arises in every form imaginable, not just in hearts full of destruction and chaos" + 13 | ". Tyrants are manipulative and lawful antipaladins, chess masters who arrange things behind the scenes to ensure that" + 14 | " whatever happens, evil always wins, and the tyrant along with it. Unlike other antipaladins, tyrants are all too" + 15 | " happy to associate with good creatures, the better to manipulate them into performing evil acts."; 16 | 17 | public static void AddTyrant() 18 | { 19 | var AntipaladinClass = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinClass"); 20 | var crueltySelection = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinCrueltySelection"); 21 | 22 | var antipaladinAlignmentRestriction = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinAlignmentRestriction"); 23 | var fiendishBoon = BlueprintTools.GetModBlueprint(MCEContext, "AntipaladinFiendishBoonSelection"); 24 | 25 | var tyrantAlignmentRestriction = TyrantAlignmentRestriction.AddAntipaladinAlignmentRestriction(); 26 | var tyrantSpellbook = TyrantSpellbook.AddTyrantSpellbook(); 27 | var diabolicBoon = DiabolicBoon.AddDiabolicBoon(); 28 | 29 | var Tyrant = Helpers.CreateBlueprint(MCEContext, "TyrantArchetype", bp => 30 | { 31 | bp.LocalizedName = Helpers.CreateString(MCEContext, $"{bp.name}.Name", NAME); 32 | bp.LocalizedDescription = Helpers.CreateString(MCEContext, $"{bp.name}.Description", DESCRIPTION); 33 | bp.LocalizedDescriptionShort = Helpers.CreateString(MCEContext, $"{bp.name}.Description", DESCRIPTION); 34 | bp.AddComponent(c => { c.Alignment = Kingmaker.UnitLogic.Alignments.AlignmentMaskType.LawfulEvil; }); 35 | bp.m_ReplaceSpellbook = tyrantSpellbook.ToReference(); 36 | bp.RemoveFeatures = [ 37 | Helpers.CreateLevelEntry(1, antipaladinAlignmentRestriction), 38 | Helpers.CreateLevelEntry(5, fiendishBoon) 39 | ]; 40 | bp.ReplaceClassSkills = true; 41 | bp.ClassSkills = [ 42 | StatType.SkillStealth, StatType.SkillPersuasion, StatType.SkillAthletics, StatType.SkillLoreReligion 43 | ]; 44 | bp.AddFeatures = [ 45 | Helpers.CreateLevelEntry(1, tyrantAlignmentRestriction), 46 | Helpers.CreateLevelEntry(5, diabolicBoon) 47 | ]; 48 | }); 49 | 50 | var Archetypes = AntipaladinClass.m_Archetypes.AppendToArray(Tyrant.ToReference()); 51 | AntipaladinClass.m_Archetypes = Archetypes; 52 | 53 | TyrantSpellbook.AddPrestigeProgression(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Archetypes/TyrantFeatures/TyrantAlignmentRestriction.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using TabletopTweaks.Core.Utilities; 5 | 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Archetypes.TyrantFeatures; 8 | internal class TyrantAlignmentRestriction 9 | { 10 | 11 | public static BlueprintFeatureReference AddAntipaladinAlignmentRestriction() 12 | { 13 | var SpellbookRef = MCEContext.GetModBlueprintReference("AntipaladinSpellbook"); 14 | 15 | return Helpers.CreateBlueprint(MCEContext, "TyrantAlignmentRestriction", bp => 16 | { 17 | bp.SetName(MCEContext, "Alignment Restriction"); 18 | bp.SetDescription(MCEContext, "A tyrant who ceases to be lawful evil loses all antipaladin {g|Encyclopedia:Spell}spells{/g} " + 19 | "and class features. He cannot thereafter gain levels as an antipaladin until he " + 20 | "changes the {g|Encyclopedia:Alignment}alignment{/g} back."); 21 | bp.AddComponent(c => 22 | { 23 | c.m_Spellbooks = [ 24 | SpellbookRef 25 | ]; 26 | c.Alignment = Kingmaker.UnitLogic.Alignments.AlignmentMaskType.LawfulEvil; 27 | }); 28 | bp.IsClassFeature = true; 29 | }).ToReference(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Classes/CrusaderLegionBlessing.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Kingmaker.Blueprints; 3 | using Kingmaker.Blueprints.Classes; 4 | using Kingmaker.Localization.Shared; 5 | using Kingmaker.UnitLogic.Abilities.Blueprints; 6 | using Kingmaker.UnitLogic.Buffs.Blueprints; 7 | using Kingmaker.UnitLogic.FactLogic; 8 | using MicroscopicContentExpansion.NewComponents; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using TabletopTweaks.Core.Utilities; 12 | 13 | namespace MicroscopicContentExpansion.NewContent.Classes; 14 | internal class CrusaderLegionBlessing 15 | { 16 | internal static void Add() 17 | { 18 | var clericClass = GetBPRef("67819271767a9dd4fbfd4ae700befea0"); 19 | var crusaderArchetype = GetBP("6bfb7e74b530f3749b590286dd2b9b30"); 20 | 21 | var icon = GetBP("2427f2e3ca22ae54ea7337bbab555b16").m_Icon; 22 | 23 | 24 | List buffs = new(); 25 | var buffDescription = Helpers.CreateString(MCEContext, "LegionBlessingBuff.Description", 26 | "Next time you cast on ally spell of this level, it also gets applied on all allies around you in 10 ft radius.", Locale.enGB); 27 | for (int i = 1; i <= 6; i++) 28 | { 29 | var buff = Helpers.CreateBlueprint(MCEContext, $"LegionBlessingBuff{i}", bp => 30 | { 31 | bp.SetName(MCEContext, $"Legion's Blessing - Spell Level {i}"); 32 | bp.m_Description = buffDescription; 33 | bp.m_Icon = icon; 34 | bp.m_Flags = BlueprintBuff.Flags.RemoveOnRest; 35 | bp.AddComponent(c => 36 | { 37 | c.SpellbookReference = crusaderArchetype.m_ReplaceSpellbook; 38 | c.SpellLevel = i; 39 | }); 40 | }); 41 | buffs.Add(buff.ToReference()); 42 | }; 43 | 44 | 45 | var sacrificeSpellAbility = Helpers.CreateBlueprint(MCEContext, "LegionBlessingSacrificeSpellAbility", bp => 46 | { 47 | bp.SetName(MCEContext, "Legion's Blessing - Sacrifice Spell"); 48 | bp.SetDescription(MCEContext, "You sacrifice prepared spell. Next beneficial spell with " + 49 | "a range of touch prepared in a slot 3 spell levels lower will be applied not only to target, " + 50 | "but also to all allies around in 10 ft radius."); 51 | bp.m_Icon = icon; 52 | bp.AddComponent(c => 53 | { 54 | c.LegionBlessingBuffs = buffs.ToArray(); 55 | }); 56 | bp.Type = AbilityType.Supernatural; 57 | bp.Range = AbilityRange.Personal; 58 | bp.CanTargetSelf = true; 59 | bp.LocalizedSavingThrow = new(); 60 | bp.LocalizedDuration = new(); 61 | bp.Animation = Kingmaker.Visual.Animation.Kingmaker.Actions.UnitAnimationActionCastSpell.CastAnimationStyle.Omni; 62 | bp.ActionType = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Free; 63 | }); 64 | 65 | 66 | 67 | var legionBlessing = Helpers.CreateBlueprint(MCEContext, "LegionBlessingFeature", bp => 68 | { 69 | bp.SetName(MCEContext, "Legion's Blessing"); 70 | bp.SetDescription(MCEContext, "At 8th level, a crusader gains the ability to confer beneficial " + 71 | "spells quickly to a large group of allies. The crusader may confer " + 72 | "the effects of a single harmless spell with a range of touch to all allies around in 10 ft radius. " + 73 | "Using the legion’s blessing expends the prepared spell, but it also requires the crusader to " + 74 | "sacrifice another prepared spell three levels higher, as when spontaneously using a cure " + 75 | "or inflict spell. The higher-level spell is not cast but is simply lost, its magical " + 76 | "energy used to power the legion’s blessing."); 77 | bp.m_Icon = icon; 78 | bp.AddComponent(c => 79 | { 80 | c.m_CharacterClass = clericClass; 81 | var nullRef = new BlueprintAbilityReference() { deserializedGuid = BlueprintGuid.Empty }; 82 | var abilityRef = sacrificeSpellAbility.ToReference(); 83 | c.m_SpellsByLevel = [ 84 | nullRef, //0 85 | nullRef, //1 86 | nullRef, //2 87 | nullRef, //3 88 | abilityRef, //4 89 | abilityRef, //5 90 | abilityRef, //6 91 | abilityRef, //7 92 | abilityRef, //8 93 | abilityRef //9 94 | ]; 95 | }); 96 | }); 97 | 98 | if (MCEContext.AddedContent.NewClasses.IsDisabled("CrusaderLegionBlessing")) return; 99 | 100 | var features = crusaderArchetype.AddFeatures; 101 | var lvl8Feature = features.Where(x => x.Level == 8).FirstOrDefault(); 102 | if (lvl8Feature != null) 103 | { 104 | lvl8Feature.m_Features.Add(legionBlessing.ToReference()); 105 | } 106 | else 107 | { 108 | lvl8Feature = Helpers.CreateLevelEntry(8, legionBlessing); 109 | crusaderArchetype.AddFeatures = features.AddToArray(lvl8Feature); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Classes/DruidicHerbalism.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Kingmaker.Blueprints; 3 | using Kingmaker.Blueprints.Classes; 4 | using Kingmaker.Blueprints.Classes.Selection; 5 | using Kingmaker.Blueprints.Items.Equipment; 6 | using Kingmaker.Craft; 7 | using Kingmaker.EntitySystem.Entities; 8 | using Kingmaker.UnitLogic; 9 | using Kingmaker.UnitLogic.Abilities; 10 | using Kingmaker.UnitLogic.Abilities.Blueprints; 11 | using MicroscopicContentExpansion.NewComponents; 12 | using System; 13 | using System.Linq; 14 | using TabletopTweaks.Core.Utilities; 15 | 16 | namespace MicroscopicContentExpansion.NewContent.Classes; 17 | internal class DruidicHerbalism 18 | { 19 | internal static void Add() 20 | { 21 | var druidBondSelection = GetBP("3830f3630a33eba49b60f511b4c8f2a8"); 22 | var featureInternalName = "DruidicHerbalism"; 23 | var description = "A druid who chooses to learn druidic herbalism can create herbal concoctions that function like potions." + 24 | "\n\nAt 1st level druid receives Brew Potions feat, and can make any potion without spending ingredients." + 25 | "\n\nAt 7th level druid can craft herbal concoctions in no time. She can create a special concoction of any spell that she can cast, but to do so, she must expend a spell slot of the same level. These special concoctions do not cost her anything to create and function like extracts created by an alchemist with the infusion discovery."; 26 | 27 | var brewPotions = GetBPRef("c0f8c4e513eb493408b8070a1de93fc0"); 28 | 29 | var freePotions = Helpers.CreateBlueprint(MCEContext, "DruidicConcoctions", a => 30 | { 31 | a.SetName(MCEContext, "Druidic Concoctions"); 32 | a.SetDescription(MCEContext, "Druid can brew any potion without spending ingredients."); 33 | a.AddComponent(c => 34 | { 35 | c.PatchType = typeof(DruidicHerbalismPatches); 36 | }); 37 | }); 38 | 39 | var infusion = Helpers.CreateBlueprint(MCEContext, "DruidicHerbalismInfusion", a => 40 | { 41 | a.SetName(MCEContext, "Druidic Herbalism - Infusion"); 42 | a.SetDescription(MCEContext, "At 7th level druid can craft herbal concoctions in no time. She can create a special concoction of any spell that she can cast, but to do so, she must expend a spell slot of the same level. These special concoctions do not cost her anything to create and function like extracts created by an alchemist with the infusion discovery."); 43 | }); 44 | 45 | var druidicHerbalismProgression = Helpers.CreateBlueprint(MCEContext, featureInternalName, a => 46 | { 47 | a.SetName(MCEContext, "Druidic Herbalism"); 48 | a.SetDescription(MCEContext, description); 49 | a.m_Classes = [ 50 | new BlueprintProgression.ClassWithLevel() { 51 | m_Class = ClassTools.ClassReferences.DruidClass 52 | } 53 | ]; 54 | a.Groups = [ 55 | FeatureGroup.DruidBond 56 | ]; 57 | a.LevelEntries = [ 58 | Helpers.CreateLevelEntry(1, brewPotions, freePotions), 59 | Helpers.CreateLevelEntry(7, infusion), 60 | ]; 61 | }); 62 | 63 | if (MCEContext.AddedContent.NewClasses.IsDisabled("DruidicHerbalism")) return; 64 | 65 | druidBondSelection.m_AllFeatures = druidBondSelection.m_AllFeatures.AddToArray(druidicHerbalismProgression.ToReference()).ToArray(); 66 | } 67 | } 68 | 69 | [HarmonyPatch] 70 | internal class DruidicHerbalismPatches 71 | { 72 | private static bool Enabled; 73 | 74 | private static BlueprintGuid DruidClassGuid; 75 | private static BlueprintFeatureReference DruidicConcoctions; 76 | private static BlueprintFeatureReference DruidicHerbalismInfusion; 77 | 78 | [HarmonyPrepare] 79 | internal static void Init() 80 | { 81 | if (Enabled) { return; } 82 | 83 | DruidClassGuid = new(new Guid("610d836f3a3a9ed42a4349b62f002e96")); 84 | DruidicConcoctions = GetBPRef("1758c2df-11f7-449f-a4fc-2762f9b68ae5"); 85 | DruidicHerbalismInfusion = GetBPRef("5ddf6390-09f3-44ea-8cac-63b3f44d6e10"); 86 | Enabled = true; 87 | MCEContext.Logger.Log($"Finished DruidicHerbalismPatches.Init"); 88 | } 89 | 90 | [HarmonyPatch(typeof(CraftRoot), nameof(CraftRoot.CreateCraftInfo))] 91 | [HarmonyPostfix] 92 | internal static void CraftRoot_CreateCraftInfo_Patch(CraftRoot __instance, ref CraftAvailInfo __result, UnitEntityData crafter, BlueprintItemEquipmentUsable item, Spellbook spellbook, BlueprintAbility abillity, CraftRequirements[] list, CraftInfoComponent craftComp, MetamagicData metamagic, int metamagicBorder, int metamagicBorderColor) 93 | { 94 | if (item.Type == UsableItemType.Potion && crafter.HasFact(DruidicConcoctions)) 95 | { 96 | CraftItemInfo craftItemInfo = new CraftItemInfo 97 | { 98 | Item = __result.Info.Item, 99 | CastingModifierBonus = __result.Info.CastingModifierBonus, 100 | SpellLevel = __result.Info.SpellLevel, 101 | IsArcane = __result.Info.IsArcane, 102 | CasterLevel = __result.Info.CasterLevel, 103 | CraftCost = [], 104 | Metamagic = __result.Info.Metamagic, 105 | MetamagicBorder = __result.Info.MetamagicBorder, 106 | MetamagicBorderColor = __result.Info.MetamagicBorderColor 107 | }; 108 | __result = new CraftAvailInfo 109 | { 110 | Info = craftItemInfo, 111 | Requirements = new CraftRequirements() { RequiredFeature = __result.Requirements.RequiredFeature }, 112 | IsHaveFeature = __result.IsHaveFeature, 113 | IsHaveItem = __result.IsHaveItem, 114 | IsHaveResources = true, 115 | MaxCasterLevel = spellbook.EffectiveCasterLevel 116 | }; 117 | } 118 | } 119 | 120 | [HarmonyPostfix] 121 | [HarmonyPatch(typeof(AbilityData), nameof(AbilityData.AlchemistInfusion), MethodType.Getter)] 122 | internal static void AbilityData_AlchemistInfusion_Patch(AbilityData __instance, ref bool __result) 123 | { 124 | if (__result) return; 125 | 126 | if (__instance.Caster != null && __instance?.Spellbook?.Blueprint?.m_CharacterClass != null 127 | && __instance.Spellbook.Blueprint.m_CharacterClass.Guid == DruidClassGuid 128 | && __instance.Caster.HasFact(DruidicHerbalismInfusion)) 129 | { 130 | __result = true; 131 | } 132 | } 133 | 134 | [HarmonyPostfix] 135 | [HarmonyPatch(typeof(AbilityData), nameof(AbilityData.TargetAnchor), MethodType.Getter)] 136 | internal static void AbilityData_TargetAnchor_Patch(AbilityData __instance, ref AbilityTargetAnchor __result) 137 | { 138 | if (__result == AbilityTargetAnchor.Unit) return; 139 | 140 | if (__instance.Range == AbilityRange.Personal && __result == AbilityTargetAnchor.Owner 141 | && __instance.Caster != null && __instance?.Spellbook?.Blueprint?.m_CharacterClass != null 142 | && __instance.Spellbook.Blueprint.m_CharacterClass.Guid == DruidClassGuid 143 | && __instance.Caster.HasFact(DruidicHerbalismInfusion)) 144 | { 145 | __result = AbilityTargetAnchor.Unit; 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Classes/MonkDiamondResilience.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Prerequisites; 4 | using Kingmaker.Blueprints.Classes.Selection; 5 | using Kingmaker.UnitLogic.FactLogic; 6 | using Kingmaker.UnitLogic.Mechanics.Components; 7 | using TabletopTweaks.Core.NewComponents.OwlcatReplacements.DamageResistance; 8 | using TabletopTweaks.Core.Utilities; 9 | 10 | namespace MicroscopicContentExpansion.NewContent.Classes; 11 | internal class MonkDiamondResilience 12 | { 13 | internal static void AddDiamondResilience() 14 | { 15 | var monkClassRef = GetBPRef("e8f21e5b58e0569468e420ebea456124"); 16 | 17 | var damageReductionIcon = GetBP("cffb5cddefab30140ac133699d52a8f8").m_Icon; 18 | 19 | var diamondResilience = Helpers.CreateBlueprint(MCEContext, "MonkDiamondResilience", a => 20 | { 21 | a.SetName(MCEContext, "Ki Power: Diamond Resilience"); 22 | a.SetDescription(MCEContext, "A monk gains DR 2/—. At 16th level, the damage reduction increases to 4/—. At 19th level, it increases to DR 6/—."); 23 | a.m_Icon = damageReductionIcon; 24 | a.AddComponent(c => 25 | { 26 | c.m_Buff = GetBPRef("a1aecb0c003a49b9ae385035875f1b92"); // DLC3_HasteIslandStacks 27 | }); 28 | a.AddPrerequisite(c => 29 | { 30 | c.m_CharacterClass = monkClassRef; 31 | c.Level = 14; 32 | }); 33 | a.AddComponent(c => 34 | { 35 | c.Value = new Kingmaker.UnitLogic.Mechanics.ContextValue() 36 | { 37 | ValueType = Kingmaker.UnitLogic.Mechanics.ContextValueType.Rank, 38 | }; 39 | c.Pool = new(); 40 | c.BypassedByMaterial = false; 41 | c.BypassedByForm = false; 42 | c.BypassedByMagic = false; 43 | c.BypassedByAlignment = false; 44 | c.BypassedByReality = false; 45 | c.BypassedByWeaponType = false; 46 | c.BypassedByMeleeWeapon = false; 47 | c.BypassedByEpic = false; 48 | c.SourceIsClassFeature = true; 49 | }); 50 | a.AddComponent(c => 51 | { 52 | c.m_BaseValueType = ContextRankBaseValueType.ClassLevel; 53 | c.m_Progression = ContextRankProgression.Custom; 54 | c.m_Class = [monkClassRef]; 55 | c.m_CustomProgression = [ 56 | new ContextRankConfig.CustomProgressionItem() { 57 | BaseValue = 15, 58 | ProgressionValue = 2 59 | }, 60 | new ContextRankConfig.CustomProgressionItem() { 61 | BaseValue = 18, 62 | ProgressionValue = 4 63 | }, 64 | new ContextRankConfig.CustomProgressionItem() { 65 | BaseValue = 100, 66 | ProgressionValue = 6 67 | } 68 | ]; 69 | }); 70 | 71 | }); 72 | if (MCEContext.AddedContent.Feats.IsEnabled("MonkDiamondResilience")) 73 | { 74 | var diamondResilienceRef = diamondResilience.ToReference(); 75 | var monkKiPowerSelection = GetBP("3049386713ff04245a38b32483362551"); 76 | var scaledFistKiPowerSelection = GetBP("4694f6ac27eaed34abb7d09ab67b4541"); 77 | 78 | monkKiPowerSelection.m_AllFeatures = monkKiPowerSelection.m_AllFeatures.AppendToArray(diamondResilienceRef); 79 | scaledFistKiPowerSelection.m_AllFeatures = scaledFistKiPowerSelection.m_AllFeatures.AppendToArray(diamondResilienceRef); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Classes/MonkFlawlessMind.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Designers.Mechanics.Facts; 4 | using System.Linq; 5 | using TabletopTweaks.Core.Utilities; 6 | 7 | 8 | namespace MicroscopicContentExpansion.NewContent.Classes; 9 | internal class MonkFlawlessMind 10 | { 11 | internal static void AddFlawlessMind() 12 | { 13 | var flawlessMind = Helpers.CreateBlueprint(MCEContext, "MonkFlawlessMind", a => 14 | { 15 | a.SetName(MCEContext, "Flawless Mind"); 16 | a.SetDescription(MCEContext, "At 19th level, a monk gains total control over his mental faculties. Whenever he attempts a Will save, he can roll twice and take the better result."); 17 | a.AddComponent(c => 18 | { 19 | c.Rule = RuleType.SavingThrow; 20 | c.RollsAmount = 1; 21 | c.TakeBest = true; 22 | c.m_SavingThrowType = Kingmaker.RuleSystem.Rules.FlaggedSavingThrowType.Will; 23 | }); 24 | }); 25 | if (MCEContext.AddedContent.Feats.IsEnabled("MonkFlawlessMind")) 26 | { 27 | var monkProgression = GetBP("8a91753b978e3b34b9425419179aafd6"); 28 | var lvlEntries = monkProgression.LevelEntries; 29 | var lvl19Entry = lvlEntries.FirstOrDefault(x => x.Level == 19); 30 | if (lvl19Entry != null) 31 | { 32 | lvl19Entry.m_Features.Add(flawlessMind.ToReference()); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Classes/MonkTimelessBody.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.UnitLogic.FactLogic; 4 | using System.Linq; 5 | using TabletopTweaks.Core.Utilities; 6 | 7 | namespace MicroscopicContentExpansion.NewContent.Classes; 8 | internal class MonkTimelessBody 9 | { 10 | internal static void AddTimelessBody() 11 | { 12 | var flawlessMind = Helpers.CreateBlueprint(MCEContext, "MonkTimelessBody", a => 13 | { 14 | a.SetName(MCEContext, "Timeless Body"); 15 | a.SetDescription(MCEContext, "At 17th level, a monk no longer takes penalties to his ability scores for aging and cannot be magically aged."); 16 | a.AddComponent(c => 17 | { 18 | c.m_Buff = GetBPRef("a1aecb0c003a49b9ae385035875f1b92"); // DLC3_HasteIslandStacks 19 | }); 20 | a.AddComponent(c => 21 | { 22 | c.m_Buff = GetBPRef("6ed8dfef694e4189bbe2fea3e8e70216"); // BythosAgeBuff3 23 | }); 24 | a.AddComponent(c => 25 | { 26 | c.m_Buff = GetBPRef("280882479c3e4e6c8c287237d6269f65"); // BythosAgeBuff2 27 | }); 28 | a.AddComponent(c => 29 | { 30 | c.m_Buff = GetBPRef("e7227f04b30d4eba9c186a7be747d5bf"); // BythosAgeBuff1 31 | }); 32 | }); 33 | if (MCEContext.AddedContent.Feats.IsEnabled("MonkTimelessBody")) 34 | { 35 | var monkProgression = GetBP("8a91753b978e3b34b9425419179aafd6"); 36 | var lvlEntries = monkProgression.LevelEntries; 37 | var lvl17Entry = lvlEntries.FirstOrDefault(x => x.Level == 17); 38 | if (lvl17Entry != null) 39 | { 40 | lvl17Entry.m_Features.Add(flawlessMind.ToReference()); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Feats/CrusadersFlurry.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Prerequisites; 4 | using Kingmaker.Modding; 5 | using Kingmaker.Utility; 6 | using MicroscopicContentExpansion.NewComponents; 7 | using System.Collections.Generic; 8 | using TabletopTweaks.Core.Utilities; 9 | 10 | namespace MicroscopicContentExpansion.NewContent.Feats; 11 | internal class CrusadersFlurry 12 | { 13 | 14 | internal static void Add() 15 | { 16 | MCEContext.Logger.LogHeader("Adding Crusader's Flurry"); 17 | 18 | var cflurryUnlock = Helpers.CreateBlueprint(MCEContext, "CrusadersFlurryUnlock", bp => 19 | { 20 | 21 | var hasHomeBrewArchetypes = OwlcatModificationsManager.Instance.AppliedModifications.Any(x => x.Manifest.UniqueName == "HomebrewArchetypes"); 22 | List flurry2ndFacts = [ 23 | GetBPRef("a34b8a9fcc9024b42bacfd5e6b614bfa"), 24 | GetBPRef("dfc54683a9b7b2d4294ad1fd2acd5877") 25 | ]; 26 | if (hasHomeBrewArchetypes) 27 | { 28 | flurry2ndFacts.Add(GetBPRef("885ad943c0c3f0445aef3813f869921f")); //SacredFistFlurry15Unlock 29 | } 30 | bp.AddComponent(c => 31 | { 32 | c._deitySelection = GetBPRef("59e7a76987fe3b547b9cce045f4db3e4"); 33 | c._soheiArchetype = GetBPRef("fad7c56737ed12e42aacc330acc86428"); 34 | c._flurryFact1 = GetBPRef("332362f3bd39ebe46a740a36960fdcb4"); 35 | c._flurryFact11 = GetBPRef("de25523acc24b1448aa90f74d6512a08"); 36 | c._flurryFact20 = GetBPRef("98319382db0542ef91e0523392d49757"); 37 | c._weaponFocus = GetBPRef("1e1f627d26ad36f43bbd26cc2bf8ac7e"); 38 | c._flurry2ndfacts = flurry2ndFacts.ToArray(); 39 | c._oldMaster = GetBPRef("0e6eea0e813f44489835b8940264b7af"); 40 | }); 41 | bp.SetName(MCEContext, "Crusader's Flurry"); 42 | bp.SetDescription(MCEContext, "You can use your deity’s favored weapon as if it were a monk weapon."); 43 | bp.IsClassFeature = true; 44 | bp.Groups = [ 45 | FeatureGroup.Feat 46 | ]; 47 | bp.AddPrerequisiteFeature(GetBPRef("1e1f627d26ad36f43bbd26cc2bf8ac7e")); 48 | 49 | List flurryPrereqs = new List() { 50 | GetBPRef("fd99770e6bd240a4aab70f7af103e56a"), 51 | GetBPRef("cd4381b73b6709146bbcc0a528a6f471") 52 | }; 53 | if (hasHomeBrewArchetypes) 54 | { 55 | flurryPrereqs.Add(GetBPRef("a86e13b03d0d50e4a91a8d8bf9d7d2b1")); //SacredFistFlurryUnlock 56 | } 57 | bp.AddComponent(c => 58 | { 59 | c.m_Features = flurryPrereqs.ToArray(); 60 | }); 61 | 62 | bp.AddComponent(c => 63 | { 64 | c.m_Features = [ 65 | GetBPRef("d332c1748445e8f4f9e92763123e31bd"), //ChannelEnergySelection 66 | GetBPRef("a9ab1bbc79ecb174d9a04699986ce8d5"), //ChannelEnergyHospitalerFeature 67 | GetBPRef("7d49d7f590dc9a948b3bd1c8b7979854"), //ChannelEnergyEmpyrealFeature 68 | GetBPRef("cb6d55dda5ab906459d18a435994a760"), //ChannelEnergyPaladinFeature 69 | GetBPRef("b8ec9dccc0e7ef74fb4072b0679c2aec"), //ShamanLifeSpiritChannelEnergyFeature 70 | GetBPRef("4bf9a9afadca5304e89bf52f2ac2d236"), //OracleRevelationChannelFeature 71 | GetBPRef("bd588bc544d2f8547a02bb82ad9f466a"), //WarpriestChannelEnergyFeature 72 | GetBPRef("e02c8a7336a542f4baffa116b6506950"), //WarpriestChannelNegativeFeature 73 | GetBPRef("b40316f05d4772e4894688e6743602bd"), //HexChannelerChannelFeature 74 | GetBPRef("a79013ff4bcd4864cb669622a29ddafb"), //ChannelEnergyFeature 75 | GetBPRef("295dff380fb8ed743bd5c76a30a49a46"), //LichChannelNegativeFeature 76 | GetBPRef("927707dce06627d4f880c90b5575125f"), //NecromancySchoolBaseFeature 77 | GetBPRef("06d824227f664c5fbb0e88901339ca91") //AntipaladinChannelNegativeEnergyFeature 78 | ]; 79 | }); 80 | }); 81 | 82 | if (MCEContext.AddedContent.Feats.IsDisabled("CrusadersFlurry")) { return; } 83 | 84 | FeatTools.AddAsFeat(cflurryUnlock); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Feats/FeintingFlurry.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Prerequisites; 4 | using Kingmaker.Designers.Mechanics.Buffs; 5 | using Kingmaker.DLC; 6 | using Kingmaker.EntitySystem.Stats; 7 | using Kingmaker.Localization.Shared; 8 | using Kingmaker.UnitLogic.ActivatableAbilities; 9 | using Kingmaker.UnitLogic.Buffs.Blueprints; 10 | using Kingmaker.UnitLogic.FactLogic; 11 | using Kingmaker.UnitLogic.Mechanics.Actions; 12 | using Kingmaker.UnitLogic.Mechanics.Components; 13 | using TabletopTweaks.Core.Utilities; 14 | 15 | namespace MicroscopicContentExpansion.NewContent.Feats; 16 | internal class FeintingFlurry 17 | { 18 | internal static void Add() 19 | { 20 | 21 | var feintingFlurryIcon = AssetLoader.LoadInternal(MCEContext, folder: "", file: "FeintingFlurry.png"); 22 | 23 | var feint = GetBP("c610310d31414edabcedf0c8a6fe32c4"); 24 | if (feint == null) return; 25 | 26 | var feintAbility = GetBPRef("1bb6f0b196aa457ba80bdb312dc64952"); 27 | 28 | var monkFlurry = GetBP("fd99770e6bd240a4aab70f7af103e56a"); 29 | var qmFlurry = GetBP("44b0f313ec56481eb447019fbe714330"); 30 | var soheiFlurry = GetBP("cd4381b73b6709146bbcc0a528a6f471"); 31 | 32 | var dlc6Reward = GetBPRef("b94f823171a84e30ad7a1b892433ab5d"); 33 | 34 | var description = Helpers.CreateString(MCEContext, "FeintingFlurry.Description", "While using flurry of blows to make {g|Encyclopedia:MeleeAttack}melee attacks{/g}, you can forgo your melee attack to make a {g|Encyclopedia:Persuasion}Persuasion{/g} (bluff) {g|Encyclopedia:Check}check{/g} to feint an opponent.", Locale.enGB, shouldProcess: true); 35 | 36 | var buff = Helpers.CreateBlueprint(MCEContext, "FeintingFlurryBuff", a => 37 | { 38 | a.SetName(MCEContext, "Feinting Flurry"); 39 | a.m_Description = description; 40 | a.m_Icon = feintingFlurryIcon; 41 | a.AddComponent(c => 42 | { 43 | c.ReduceCount = 1; 44 | c.OnlyFromPrimaryHand = true; 45 | c.Condition = new(); 46 | }); 47 | a.AddComponent(c => 48 | { 49 | c.TriggerBeforeAttack = true; 50 | c.OnlyHit = true; 51 | c.OnMiss = false; 52 | c.OnlyOnFullAttack = true; 53 | c.OnlyOnFirstAttack = true; 54 | c.OnlyOnFirstHit = false; 55 | c.CriticalHit = false; 56 | c.OnlyNatural20 = false; 57 | c.OnAttackOfOpportunity = false; 58 | c.NotCriticalHit = false; 59 | c.OnlySneakAttack = false; 60 | c.NotSneakAttack = false; 61 | c.CheckWeaponBlueprint = false; 62 | c.CheckWeaponCategory = false; 63 | c.CheckWeaponGroup = false; 64 | c.CheckWeaponRangeType = true; 65 | c.RangeType = Kingmaker.Enums.WeaponRangeType.Melee; 66 | c.CheckPhysicalDamageForm = false; 67 | c.ReduceHPToZero = false; 68 | c.DamageMoreTargetMaxHP = false; 69 | c.CheckDistance = false; 70 | c.AllNaturalAndUnarmed = false; 71 | c.DuelistWeapon = false; 72 | c.NotExtraAttack = false; 73 | c.OnCharge = false; 74 | c.IgnoreAutoHit = false; 75 | c.ActionsOnInitiator = false; 76 | c.Action = new() 77 | { 78 | Actions = [ 79 | new ContextActionCastSpell() { 80 | m_Spell = feintAbility, 81 | OverrideSpellbook = false, 82 | OverrideDC = false, 83 | DC = 0, 84 | OverrideSpellLevel = false, 85 | SpellLevel = 0, 86 | CastByTarget = false, 87 | LogIfCanNotTarget = false, 88 | MarkAsChild = false 89 | } 90 | ] 91 | }; 92 | }); 93 | }); 94 | 95 | var ability = Helpers.CreateBlueprint(MCEContext, "FeintingFlurryActivatableAbility", a => 96 | { 97 | a.SetName(MCEContext, "Feinting Flurry"); 98 | a.m_Description = description; 99 | a.m_Icon = feintingFlurryIcon; 100 | a.DeactivateImmediately = true; 101 | a.ActivationType = AbilityActivationType.WithUnitCommand; 102 | a.m_ActivateWithUnitCommand = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Free; 103 | a.m_ActivateOnUnitAction = AbilityActivateOnUnitActionType.Attack; 104 | a.m_Buff = buff.ToReference(); 105 | }); 106 | 107 | var feintingFlurry = Helpers.CreateBlueprint(MCEContext, "FeintingFlurry", a => 108 | { 109 | a.SetName(MCEContext, "Feinting Flurry"); 110 | a.m_Description = description; 111 | a.m_Icon = feintingFlurryIcon; 112 | a.AddComponent(c => 113 | { 114 | c.m_Facts = [ability.ToReference()]; 115 | }); 116 | a.AddPrerequisiteFeature(feint); 117 | a.AddPrerequisite(c => 118 | { 119 | c.Stat = StatType.Dexterity; 120 | c.Value = 15; 121 | }); 122 | a.AddPrerequisite(c => 123 | { 124 | c.Stat = StatType.Intelligence; 125 | c.Value = 13; 126 | }); 127 | a.AddPrerequisiteFeaturesFromList(1, monkFlurry, qmFlurry, soheiFlurry); 128 | a.AddComponent(c => 129 | { 130 | c.m_DlcReward = dlc6Reward; 131 | }); 132 | a.Groups = [ 133 | FeatureGroup.CombatFeat, 134 | FeatureGroup.Feat 135 | ]; 136 | }); 137 | 138 | if (MCEContext.AddedContent.Feats.IsDisabled("FeintingFlurry")) { return; } 139 | FeatTools.AddAsFeat(feintingFlurry); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Spells/ProtectionFromChaosGood.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes.Spells; 3 | using Kingmaker.Craft; 4 | using Kingmaker.UnitLogic.Abilities; 5 | using Kingmaker.UnitLogic.Abilities.Blueprints; 6 | using Kingmaker.UnitLogic.Abilities.Components; 7 | using Kingmaker.Utility; 8 | using TabletopTweaks.Core.Utilities; 9 | 10 | namespace MicroscopicContentExpansion.NewContent.Spells; 11 | internal class ProtectionFromChaosGood 12 | { 13 | public static BlueprintAbilityReference AddProtectionFromChaosGood() 14 | { 15 | var protectionFromChaos = GetBPRef("1eaf1020e82028d4db55e6e464269e00"); 16 | var protectionFromGood = GetBP("2ac7637daeb2aa143a3bae860095b63e"); 17 | 18 | return Helpers.CreateBlueprint(MCEContext, "ProtectionFromChaosGood", bp => 19 | { 20 | bp.SetName(MCEContext, "Protection from Chaos/Good"); 21 | bp.SetDescription(MCEContext, "The subject gains a +2 deflection {g|Encyclopedia:Bonus}bonus{/g}" + 22 | " to {g|Encyclopedia:Armor_Class}AC{/g} and a +2 resistance bonus on {g|Encyclopedia:Saving_Throw" + 23 | "}saves{/g}. Both these bonuses apply against {g|Encyclopedia:Attack}attacks{/g} made or effects" + 24 | " created by creatures with the corresponding {g|Encyclopedia:Alignment}alignment{/g}."); 25 | bp.m_Icon = protectionFromGood.Icon; 26 | bp.CanTargetFriends = true; 27 | bp.EffectOnAlly = AbilityEffectOnUnit.None; 28 | bp.EffectOnEnemy = AbilityEffectOnUnit.None; 29 | bp.Animation = Kingmaker.Visual.Animation.Kingmaker.Actions.UnitAnimationActionCastSpell.CastAnimationStyle.Touch; 30 | bp.ActionType = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Standard; 31 | bp.AvailableMetamagic = Metamagic.Quicken | Metamagic.Extend | Metamagic.Heighten | Metamagic.Reach | Metamagic.CompletelyNormal; 32 | bp.LocalizedDuration = Helpers.CreateString(MCEContext, $"{bp.name}.Duration", "1 minute/level"); 33 | bp.LocalizedSavingThrow = new Kingmaker.Localization.LocalizedString(); 34 | bp.AddComponent(c => 35 | { 36 | c.School = SpellSchool.Abjuration; 37 | }); 38 | bp.AddComponent(c => 39 | { 40 | c.m_Variants = [ 41 | protectionFromChaos, 42 | protectionFromGood.ToReference() 43 | ]; 44 | }); 45 | }).ToReference(); 46 | } 47 | 48 | public static BlueprintAbilityReference AddProtectionFromChaosGoodCommunal() 49 | { 50 | var protectionFromChaosCommunal = GetBPRef("0ec75ec95d9e39d47a23610123ba1bad"); 51 | var protectionFromGoodCommunal = GetBP("5bfd4cce1557d5744914f8f6d85959a4"); 52 | 53 | return Helpers.CreateBlueprint(MCEContext, "ProtectionFromChaosGoodCommunal", bp => 54 | { 55 | bp.SetName(MCEContext, "Protection from Chaos/Good - Communal"); 56 | bp.SetDescription(MCEContext, "All allies within 30 feet gain a +2 deflection {g|Encyclopedia:Bonus}bonus{/g} " + 57 | "to {g|Encyclopedia:Armor_Class}AC{/g} and a +2 resistance bonus on {g|Encyclopedia:Saving_Throw}saves{/g}." + 58 | " Both these bonuses apply against {g|Encyclopedia:Attack}attacks{/g} made or effects created by creatures" + 59 | " with corresponding {g|Encyclopedia:Alignment}alignments{/g}."); 60 | bp.m_Icon = protectionFromGoodCommunal.Icon; 61 | bp.CanTargetFriends = true; 62 | bp.EffectOnAlly = AbilityEffectOnUnit.None; 63 | bp.EffectOnEnemy = AbilityEffectOnUnit.None; 64 | bp.Animation = Kingmaker.Visual.Animation.Kingmaker.Actions.UnitAnimationActionCastSpell.CastAnimationStyle.Touch; 65 | bp.ActionType = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Standard; 66 | bp.AvailableMetamagic = Metamagic.Quicken | Metamagic.Extend | Metamagic.Heighten | Metamagic.Reach | Metamagic.CompletelyNormal; 67 | bp.LocalizedDuration = Helpers.CreateString(MCEContext, $"{bp.name}.Duration", "1 minute"); 68 | bp.LocalizedSavingThrow = new Kingmaker.Localization.LocalizedString(); 69 | bp.AddComponent(c => 70 | { 71 | c.School = SpellSchool.Abjuration; 72 | }); 73 | bp.AddComponent(c => 74 | { 75 | c.m_Variants = [ 76 | protectionFromChaosCommunal, 77 | protectionFromGoodCommunal.ToReference() 78 | ]; 79 | }); 80 | bp.AddComponent(c => 81 | { 82 | c.m_Radius = 30.Feet(); 83 | c.m_TargetType = TargetType.Ally; 84 | }); 85 | bp.AddComponent(c => 86 | { 87 | c.SpellType = CraftSpellType.Other; 88 | c.SavingThrow = CraftSavingThrow.None; 89 | c.AOEType = CraftAOE.AOE; 90 | }); 91 | }).ToReference(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Spells/ProtectionFromLawGood.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes.Spells; 3 | using Kingmaker.Craft; 4 | using Kingmaker.UnitLogic.Abilities; 5 | using Kingmaker.UnitLogic.Abilities.Blueprints; 6 | using Kingmaker.UnitLogic.Abilities.Components; 7 | using Kingmaker.Utility; 8 | using TabletopTweaks.Core.Utilities; 9 | 10 | namespace MicroscopicContentExpansion.NewContent.Spells; 11 | internal class ProtectionFromLawGood 12 | { 13 | public static BlueprintAbilityReference AddProtectionFromLawGood() 14 | { 15 | var protectionFromLaw = GetBPRef("c3aafbbb6e8fc754fb8c82ede3280051"); 16 | var protectionFromGood = GetBP("2ac7637daeb2aa143a3bae860095b63e"); 17 | 18 | return Helpers.CreateBlueprint(MCEContext, "ProtectionFromLawGood", bp => 19 | { 20 | bp.SetName(MCEContext, "Protection from Law/Good"); 21 | bp.SetDescription(MCEContext, "The subject gains a +2 deflection {g|Encyclopedia:Bonus}bonus{/g}" + 22 | " to {g|Encyclopedia:Armor_Class}AC{/g} and a +2 resistance bonus on {g|Encyclopedia:Saving_Throw" + 23 | "}saves{/g}. Both these bonuses apply against {g|Encyclopedia:Attack}attacks{/g} made or effects" + 24 | " created by creatures with the corresponding {g|Encyclopedia:Alignment}alignment{/g}."); 25 | bp.m_Icon = protectionFromGood.Icon; 26 | bp.CanTargetFriends = true; 27 | bp.EffectOnAlly = AbilityEffectOnUnit.None; 28 | bp.EffectOnEnemy = AbilityEffectOnUnit.None; 29 | bp.Animation = Kingmaker.Visual.Animation.Kingmaker.Actions.UnitAnimationActionCastSpell.CastAnimationStyle.Touch; 30 | bp.ActionType = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Standard; 31 | bp.AvailableMetamagic = Metamagic.Quicken | Metamagic.Extend | Metamagic.Heighten | Metamagic.Reach | Metamagic.CompletelyNormal; 32 | bp.LocalizedDuration = Helpers.CreateString(MCEContext, $"{bp.name}.Duration", "1 minute/level"); 33 | bp.LocalizedSavingThrow = new Kingmaker.Localization.LocalizedString(); 34 | bp.AddComponent(c => 35 | { 36 | c.School = SpellSchool.Abjuration; 37 | }); 38 | bp.AddComponent(c => 39 | { 40 | c.m_Variants = [ 41 | protectionFromLaw, 42 | protectionFromGood.ToReference() 43 | ]; 44 | }); 45 | }).ToReference(); 46 | } 47 | 48 | public static BlueprintAbilityReference AddProtectionFromLawGoodCommunal() 49 | { 50 | var protectionFromLawCommunal = GetBPRef("8b8ccc9763e3cc74bbf5acc9c98557b9"); 51 | var protectionFromGoodCommunal = GetBP("5bfd4cce1557d5744914f8f6d85959a4"); 52 | 53 | return Helpers.CreateBlueprint(MCEContext, "ProtectionFromLawGoodCommunal", bp => 54 | { 55 | bp.SetName(MCEContext, "Protection from Law/Good - Communal"); 56 | bp.SetDescription(MCEContext, "All allies within 30 feet gain a +2 deflection {g|Encyclopedia:Bonus}bonus{/g} " + 57 | "to {g|Encyclopedia:Armor_Class}AC{/g} and a +2 resistance bonus on {g|Encyclopedia:Saving_Throw}saves{/g}." + 58 | " Both these bonuses apply against {g|Encyclopedia:Attack}attacks{/g} made or effects created by creatures" + 59 | " with corresponding {g|Encyclopedia:Alignment}alignments{/g}."); 60 | bp.m_Icon = protectionFromGoodCommunal.Icon; 61 | bp.CanTargetFriends = true; 62 | bp.EffectOnAlly = AbilityEffectOnUnit.None; 63 | bp.EffectOnEnemy = AbilityEffectOnUnit.None; 64 | bp.Animation = Kingmaker.Visual.Animation.Kingmaker.Actions.UnitAnimationActionCastSpell.CastAnimationStyle.Touch; 65 | bp.ActionType = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Standard; 66 | bp.AvailableMetamagic = Metamagic.Quicken | Metamagic.Extend | Metamagic.Heighten | Metamagic.Reach | Metamagic.CompletelyNormal; 67 | bp.LocalizedDuration = Helpers.CreateString(MCEContext, $"{bp.name}.Duration", "1 minute"); 68 | bp.LocalizedSavingThrow = new Kingmaker.Localization.LocalizedString(); 69 | bp.AddComponent(c => 70 | { 71 | c.School = SpellSchool.Abjuration; 72 | }); 73 | bp.AddComponent(c => 74 | { 75 | c.m_Variants = [ 76 | protectionFromLawCommunal, 77 | protectionFromGoodCommunal.ToReference() 78 | ]; 79 | }); 80 | bp.AddComponent(c => 81 | { 82 | c.m_Radius = 30.Feet(); 83 | c.m_TargetType = TargetType.Ally; 84 | }); 85 | bp.AddComponent(c => 86 | { 87 | c.SpellType = CraftSpellType.Other; 88 | c.SavingThrow = CraftSavingThrow.None; 89 | c.AOEType = CraftAOE.AOE; 90 | }); 91 | }).ToReference(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/NewContent/Spells/WidenAuras.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Spells; 4 | using Kingmaker.UnitLogic.Abilities; 5 | using Kingmaker.UnitLogic.Abilities.Blueprints; 6 | using Kingmaker.UnitLogic.Abilities.Components; 7 | using Kingmaker.UnitLogic.Buffs.Blueprints; 8 | using Kingmaker.UnitLogic.Mechanics; 9 | using Kingmaker.UnitLogic.Mechanics.Actions; 10 | using TabletopTweaks.Core.Utilities; 11 | 12 | namespace MicroscopicContentExpansion.NewContent.Spells; 13 | public class WidenAuras 14 | { 15 | 16 | public static BlueprintAbilityReference AddWidenAuras() 17 | { 18 | var icon = GetBP("b73bc1b252994e6582a644dd6a7f31dc").Icon; 19 | 20 | const string widenAurasName = "Widen Auras"; 21 | const string widenAurasDesc = "The range of your antipaladin auras doubles."; 22 | 23 | var buff = Helpers.CreateBlueprint(MCEContext, "WidenAurasBuff", bp => 24 | { 25 | bp.SetName(MCEContext, widenAurasName); 26 | bp.SetDescription(MCEContext, widenAurasDesc); 27 | bp.m_Icon = icon; 28 | bp.Frequency = DurationRate.Minutes; 29 | bp.m_Flags = BlueprintBuff.Flags.IsFromSpell; 30 | }); 31 | 32 | var spell = Helpers.CreateBlueprint(MCEContext, "WidenAurasAbility", bp => 33 | { 34 | bp.SetName(MCEContext, widenAurasName); 35 | bp.SetDescription(MCEContext, widenAurasDesc); 36 | bp.m_Icon = icon; 37 | bp.AvailableMetamagic = Metamagic.Quicken | Metamagic.Extend | Metamagic.Heighten | Metamagic.CompletelyNormal; 38 | bp.LocalizedDuration = Helpers.CreateString(MCEContext, $"{bp.name}.Duration", "1 minute/level"); 39 | bp.LocalizedSavingThrow = new Kingmaker.Localization.LocalizedString(); 40 | bp.AddComponent(c => 41 | { 42 | c.School = SpellSchool.Transmutation; 43 | }); 44 | bp.AddComponent(c => 45 | { 46 | c.AddAction(b => 47 | { 48 | b.m_Buff = buff.ToReference(); 49 | b.DurationValue = new ContextDurationValue() 50 | { 51 | Rate = DurationRate.Minutes, 52 | DiceCountValue = 0, 53 | BonusValue = new ContextValue() 54 | { 55 | ValueType = ContextValueType.Rank 56 | } 57 | }; 58 | b.AsChild = false; 59 | b.IsFromSpell = true; 60 | }); 61 | }); 62 | bp.Type = AbilityType.Spell; 63 | bp.Range = AbilityRange.Personal; 64 | bp.CanTargetFriends = true; 65 | bp.CanTargetSelf = true; 66 | bp.EffectOnAlly = AbilityEffectOnUnit.None; 67 | bp.EffectOnEnemy = AbilityEffectOnUnit.None; 68 | bp.Animation = Kingmaker.Visual.Animation.Kingmaker.Actions.UnitAnimationActionCastSpell.CastAnimationStyle.Omni; 69 | bp.ActionType = Kingmaker.UnitLogic.Commands.Base.UnitCommand.CommandType.Standard; 70 | }).ToReference(); 71 | 72 | return spell; 73 | } 74 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/RebalancedContent/DragonbloodShifterArchetype/DragonbloodWingController.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.JsonSystem; 3 | using Kingmaker.PubSubSystem; 4 | using Kingmaker.UnitLogic; 5 | using Kingmaker.UnitLogic.ActivatableAbilities; 6 | using Kingmaker.UnitLogic.Buffs; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | namespace MicroscopicContentExpansion.RebalancedContent.DragonbloodShifterArchetype; 11 | 12 | [TypeId("268eb90086c44966b5eae821e050c555")] 13 | public class DragonbloodWingController : UnitFactComponentDelegate, IActivatableAbilityWillStopHandler, IGlobalSubscriber, ISubscriber, IActivatableAbilityStartHandler 14 | { 15 | public Dictionary MatchingWingsDictionary; 16 | 17 | public override void OnActivate() 18 | { 19 | UpdateWings(); 20 | } 21 | 22 | public override void OnTurnOn() 23 | { 24 | UpdateWings(); 25 | } 26 | 27 | public override void OnDeactivate() 28 | { 29 | if (this.Data.WingBuff != null) 30 | { 31 | this.Owner.RemoveFact(this.Data.WingBuff); 32 | this.Data.WingBuff = null; 33 | } 34 | } 35 | 36 | public override void OnTurnOff() 37 | { 38 | if (this.Data.WingBuff != null) 39 | { 40 | this.Owner.RemoveFact(this.Data.WingBuff); 41 | this.Data.WingBuff = null; 42 | } 43 | } 44 | 45 | public void HandleActivatableAbilityStart(ActivatableAbility ability) 46 | { 47 | this.TryRunActions(ability); 48 | } 49 | 50 | public void HandleActivatableAbilityWillStop(ActivatableAbility ability) 51 | { 52 | this.TryRunActions(ability); 53 | } 54 | 55 | private void TryRunActions(ActivatableAbility ability) 56 | { 57 | if (ability.Blueprint.Group != ActivatableAbilityGroup.ShifterAspect) 58 | { 59 | return; 60 | } 61 | if (ability.Owner != base.Owner) 62 | { 63 | return; 64 | } 65 | 66 | UpdateWings(); 67 | } 68 | 69 | private void UpdateWings() 70 | { 71 | ActivatableAbility lastActivatedAspect = base.Owner.ActivatableAbilities.Enumerable 72 | .Where(a => a.Blueprint.Group == ActivatableAbilityGroup.ShifterAspect && a.IsOn) 73 | .OrderByDescending(x => x.m_TurnOnTime) 74 | .FirstOrDefault(); 75 | 76 | if (lastActivatedAspect == default) 77 | { 78 | if (this.Data.WingBuff != null) 79 | { 80 | Owner.RemoveFact(this.Data.WingBuff); 81 | this.Data.WingBuff = null; 82 | } 83 | } 84 | else 85 | { 86 | var abilityBlueprintGuid = lastActivatedAspect.Blueprint.AssetGuid; 87 | var matchingBuff = MatchingWingsDictionary[abilityBlueprintGuid]; 88 | if (this.Data.WingBuff != null) 89 | { 90 | if (this.Data.WingBuff.Blueprint.AssetGuid != matchingBuff.Guid) 91 | { 92 | Owner.RemoveFact(this.Data.WingBuff); 93 | this.Data.WingBuff = null; 94 | } 95 | else 96 | { 97 | return; 98 | } 99 | } 100 | this.Data.WingBuff = Owner.AddBuff(matchingBuff.Get(), Context); 101 | } 102 | } 103 | } 104 | 105 | public class WingData 106 | { 107 | public Buff WingBuff; 108 | } -------------------------------------------------------------------------------- /MicroscopicContentExpansion/RebalancedContent/MythicArmor/ArmorACAsDamage.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Items.Ecnchantments; 3 | using Kingmaker.Blueprints.JsonSystem; 4 | using Kingmaker.Designers; 5 | using Kingmaker.EntitySystem; 6 | using Kingmaker.Enums; 7 | using Kingmaker.Items; 8 | using Kingmaker.PubSubSystem; 9 | using Kingmaker.RuleSystem; 10 | using Kingmaker.RuleSystem.Rules; 11 | using Kingmaker.RuleSystem.Rules.Damage; 12 | using Kingmaker.UnitLogic.Mechanics; 13 | using Kingmaker.UnitLogic.Parts; 14 | 15 | namespace MicroscopicContentExpansion.RebalancedContent.MythicArmor; 16 | 17 | /// 18 | /// Replacer component for heavy and medium mythic armor offence feats. 19 | /// Uses armor enhancement value as enhancement value of damage 20 | /// 21 | [AllowMultipleComponents] 22 | [TypeId("5d9f3651218e44cc91f5d7a0092abed7")] 23 | public class ArmorACAsDamage : 24 | EntityFactComponentDelegate, 25 | IInitiatorRulebookHandler, 26 | IRulebookHandler, 27 | ISubscriber, 28 | IInitiatorRulebookSubscriber 29 | { 30 | public WeaponRangeType RangeType; 31 | 32 | public ContextDiceValue Value; 33 | 34 | public void OnEventAboutToTrigger(RulePrepareDamage evt) 35 | { 36 | if (!CheckCondition(evt)) 37 | return; 38 | UnitPartDisableBonusForDamage disableBonusForDamage = evt.Initiator.Parts.Get(); 39 | if (disableBonusForDamage != null && disableBonusForDamage.DisableAdditionalDice) 40 | return; 41 | DamageTypeDescription damageTypeDescription = evt.DamageBundle.First.CreateTypeDescription(); 42 | var enhancementBonus = GameHelper.GetItemEnhancementBonus(evt.Initiator.Body.Armor.Armor); 43 | damageTypeDescription.Physical.Enhancement = enhancementBonus; 44 | damageTypeDescription.Physical.EnhancementTotal = enhancementBonus; 45 | int rollsCount = this.Value.DiceCountValue.Calculate(this.Context); 46 | DamageDescription damageDescription = new() 47 | { 48 | TypeDescription = damageTypeDescription, 49 | Dice = new DiceFormula(rollsCount, this.Value.DiceType), 50 | Bonus = this.Value.BonusValue.Calculate(this.Context), 51 | SourceFact = this.Fact 52 | }; 53 | BaseDamage damage = damageDescription.CreateDamage(); 54 | evt.Add(damage); 55 | } 56 | 57 | 58 | public void OnEventDidTrigger(RulePrepareDamage evt) 59 | { 60 | } 61 | 62 | private bool CheckCondition(RulePrepareDamage evt) 63 | { 64 | RuleAttackWithWeapon attackWithWeapon = evt.ParentRule.AttackRoll?.RuleAttackWithWeapon; 65 | if (attackWithWeapon != null && CheckCondition(attackWithWeapon)) 66 | return true; 67 | return false; 68 | } 69 | 70 | private bool CheckCondition(RuleAttackWithWeapon evt) 71 | { 72 | ItemEntity itemEntity = this.Fact is ItemEnchantment fact ? fact.Owner : null; 73 | if (itemEntity != null && itemEntity != evt.Weapon 74 | || !evt.AttackRoll.IsHit 75 | || !this.RangeType.IsSuitableWeapon(evt.Weapon)) 76 | return false; 77 | return true; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/RebalancedContent/MythicArmor/MythicArmorFeatTweaks.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.UnitLogic.Buffs.Blueprints; 3 | using Kingmaker.UnitLogic.Mechanics.Components; 4 | using System.Linq; 5 | using TabletopTweaks.Core.Utilities; 6 | 7 | namespace MicroscopicContentExpansion.RebalancedContent.MythicArmor; 8 | internal static class MythicArmorFeatTweaks 9 | { 10 | internal static void Change() 11 | { 12 | AddEnhancementToOffense(); 13 | } 14 | 15 | private static void AddEnhancementToOffense() 16 | { 17 | if (MCEContext.Homebrew.MythicArmorFeats.IsDisabled("ArmorEnhancementBonusToBypassDR")) 18 | { 19 | return; 20 | } 21 | var heavyOffenseBuff = GetBP("5ec6fdb6fa4741798e3264c09e91c949"); 22 | var comp = heavyOffenseBuff.GetComponents().ToList(); 23 | if (comp.Count > 0) 24 | { 25 | var diceComp = comp[0]; 26 | heavyOffenseBuff.AddComponent(c => 27 | { 28 | c.Value = diceComp.Value; 29 | c.RangeType = Kingmaker.Enums.WeaponRangeType.Melee; 30 | }); 31 | heavyOffenseBuff.RemoveComponents(); 32 | } 33 | 34 | var mediumOffenseBuff = GetBP("8ddbd82754ac44c1990c212a3ed1f1c8"); 35 | var compM = mediumOffenseBuff.GetComponents().ToList(); 36 | if (compM.Count > 0) 37 | { 38 | var diceComp = compM[0]; 39 | mediumOffenseBuff.AddComponent(c => 40 | { 41 | c.Value = diceComp.Value; 42 | c.RangeType = Kingmaker.Enums.WeaponRangeType.Melee; 43 | }); 44 | mediumOffenseBuff.RemoveComponents(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/RebalancedContent/MythicFeats/MythicDodge.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.Blueprints.Classes; 3 | using Kingmaker.Blueprints.Classes.Prerequisites; 4 | using Kingmaker.Designers.EventConditionActionSystem.Actions; 5 | using Kingmaker.Designers.Mechanics.Facts; 6 | using Kingmaker.Localization.Shared; 7 | using Kingmaker.UnitLogic.Buffs.Blueprints; 8 | using Kingmaker.UnitLogic.FactLogic; 9 | using Kingmaker.UnitLogic.Mechanics.Actions; 10 | using Kingmaker.UnitLogic.Mechanics.Components; 11 | using Kingmaker.UnitLogic.Mechanics.Conditions; 12 | using MicroscopicContentExpansion.Utils; 13 | using TabletopTweaks.Core.Utilities; 14 | 15 | namespace MicroscopicContentExpansion.RebalancedContent.MythicFeats; 16 | internal class MythicDodge 17 | { 18 | internal static void Rework() 19 | { 20 | var mythicDodgeFeat = GetBP("3812d9ca1377c014c97fb3ac421ba9e6"); 21 | 22 | var mythicDodgeEffectBuff = Helpers.CreateBlueprint(MCEContext, "DodgeMythicEffectBuff", a => 23 | { 24 | a.m_DisplayName = mythicDodgeFeat.m_DisplayName; 25 | a.m_Icon = mythicDodgeFeat.m_Icon; 26 | a.m_Description = new(); 27 | a.AddComponent(x => 28 | { 29 | x.Rule = RuleType.AttackRoll; 30 | x.RollsAmount = 1; 31 | x.RollCondition = ModifyD20.RollConditionType.Equal; 32 | x.ValueToCompareRoll = 20; 33 | }); 34 | a.AddComponent(x => 35 | { 36 | x.TriggerBeforeAttack = true; 37 | x.OnlyHit = true; 38 | x.Action = ActionFlow.DoSingle(x => 39 | { 40 | x.ConditionsChecker = ActionFlow.IfSingle(c => 41 | { 42 | c.Not = true; 43 | c.m_Fact = mythicDodgeFeat.ToReference(); 44 | }); 45 | x.IfTrue = ActionFlow.DoSingle(); 46 | x.IfFalse = new(); 47 | }); 48 | }); 49 | a.AddComponent(x => 50 | { 51 | x.Actions = ActionFlow.DoSingle(); 52 | }); 53 | a.m_Flags = BlueprintBuff.Flags.HiddenInUi; 54 | }).ToReference(); 55 | 56 | var reworkDesc = Helpers.CreateString(MCEContext, "MythicDodgeRework.Description", "When focused, you become nearly impossible to strike.\r\nBenefit: Whenever you are targeted by an effect that requires an {g|Encyclopedia:Attack}attack roll{/g}, including weapon attacks, if attacker {g|Encyclopedia:Dice}rolls{/g} a natural 20 on an {g|Encyclopedia:Attack}attack roll{/g}, they must reroll the die once.", Locale.enGB, shouldProcess: true); 57 | 58 | if (MCEContext.Homebrew.MythicFeats.IsDisabled("MythicDodgeRework")) 59 | { 60 | return; 61 | } 62 | 63 | mythicDodgeFeat.RemoveComponents(x => x is not PrerequisiteFeature); 64 | mythicDodgeFeat.AddComponent(x => 65 | { 66 | x.ActionsOnAttacker = ActionFlow.DoSingle(x => 67 | { 68 | x.m_Buff = mythicDodgeEffectBuff; 69 | x.DurationValue = new() 70 | { 71 | Rate = Kingmaker.UnitLogic.Mechanics.DurationRate.Rounds, 72 | DiceCountValue = 0, 73 | BonusValue = 1, 74 | m_IsExtendable = true 75 | }; 76 | }); 77 | x.ActionOnSelf = new(); 78 | }); 79 | mythicDodgeFeat.AddComponent(x => 80 | { 81 | x.DontCheckType = true; 82 | x.ToCaster = true; 83 | x.Action = ActionFlow.DoSingle(c => 84 | { 85 | c.ConditionsChecker = ActionFlow.IfSingle(); 86 | c.IfTrue = ActionFlow.DoSingle(x => 87 | { 88 | x.m_Buff = mythicDodgeEffectBuff; 89 | x.DurationValue = new() 90 | { 91 | Rate = Kingmaker.UnitLogic.Mechanics.DurationRate.Rounds, 92 | DiceCountValue = 0, 93 | BonusValue = 1, 94 | m_IsExtendable = true 95 | }; 96 | }); 97 | }); 98 | }); 99 | mythicDodgeFeat.m_Description = reworkDesc; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/UMMSettingsUI.cs: -------------------------------------------------------------------------------- 1 | using TabletopTweaks.Core.UMMTools; 2 | using UnityModManagerNet; 3 | 4 | namespace MicroscopicContentExpansion; 5 | internal static class UMMSettingsUI 6 | { 7 | private static int selectedTab; 8 | public static void OnGUI(UnityModManager.ModEntry modEntry) 9 | { 10 | UI.AutoWidth(); 11 | UI.TabBar(ref selectedTab, 12 | () => UI.Label("SETTINGS WILL NOT BE UPDATED UNTIL YOU RESTART YOUR GAME.".yellow().bold()), 13 | new NamedAction("Added Content", () => SettingsTabs.AddedContent()), 14 | new NamedAction("Homebrew", () => SettingsTabs.Homebrew()) 15 | ); 16 | } 17 | } 18 | 19 | internal static class SettingsTabs 20 | { 21 | 22 | public static void AddedContent() 23 | { 24 | var TabLevel = SetttingUI.TabLevel.Zero; 25 | var AddedContent = Main.MCEContext.AddedContent; 26 | UI.Div(0, 15); 27 | using (UI.VerticalScope()) 28 | { 29 | UI.Toggle("New Settings Off By Default".bold(), ref AddedContent.NewSettingsOffByDefault); 30 | UI.Space(25); 31 | 32 | SetttingUI.SettingGroup("Spells", TabLevel, AddedContent.Spells); 33 | SetttingUI.SettingGroup("NewClasses", TabLevel, AddedContent.NewClasses); 34 | SetttingUI.SettingGroup("Feats", TabLevel, AddedContent.Feats); 35 | } 36 | } 37 | 38 | public static void Homebrew() 39 | { 40 | var TabLevel = SetttingUI.TabLevel.Zero; 41 | var Homebrew = Main.MCEContext.Homebrew; 42 | UI.Div(0, 15); 43 | using (UI.VerticalScope()) 44 | { 45 | UI.Toggle("New Settings Off By Default".bold(), ref Homebrew.NewSettingsOffByDefault); 46 | UI.Space(25); 47 | 48 | SetttingUI.SettingGroup("Dragonblood Shifter", TabLevel, Homebrew.DragonbloodShifter); 49 | SetttingUI.SettingGroup("Mythic armor feats", TabLevel, Homebrew.MythicArmorFeats); 50 | SetttingUI.SettingGroup("Mythic feats", TabLevel, Homebrew.MythicFeats); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Utils/ActionFlow.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.ElementsSystem; 2 | using TabletopTweaks.Core.Utilities; 3 | 4 | namespace MicroscopicContentExpansion.Utils; 5 | public static class ActionFlow 6 | { 7 | 8 | public static ActionList DoNothing() => Helpers.CreateActionList(); 9 | 10 | public static ActionList DoSingle(System.Action init = null) where T : GameAction, new() 11 | { 12 | var t = new T(); 13 | init?.Invoke(t); 14 | return Helpers.CreateActionList(t); 15 | } 16 | 17 | public static ConditionsChecker IfSingle(System.Action init = null) where T : Condition, new() 18 | { 19 | var t = new T(); 20 | init?.Invoke(t); 21 | return new ConditionsChecker() 22 | { 23 | Conditions = [t] 24 | }; 25 | } 26 | 27 | public static ConditionsChecker IfAll(params Condition[] conditions) 28 | { 29 | return new ConditionsChecker() 30 | { 31 | Conditions = conditions, 32 | Operation = Operation.And 33 | }; 34 | } 35 | 36 | public static ConditionsChecker IfAny(params Condition[] conditions) 37 | { 38 | return new ConditionsChecker() 39 | { 40 | Conditions = conditions, 41 | Operation = Operation.Or 42 | }; 43 | } 44 | 45 | public static ConditionsChecker EmptyCondition() 46 | { 47 | return new ConditionsChecker() 48 | { 49 | Conditions = [] 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MicroscopicContentExpansion/Utils/AuraUtils.cs: -------------------------------------------------------------------------------- 1 | using Kingmaker.Blueprints; 2 | using Kingmaker.ResourceLinks; 3 | using Kingmaker.UnitLogic.Abilities.Blueprints; 4 | using Kingmaker.UnitLogic.Abilities.Components.AreaEffects; 5 | using Kingmaker.UnitLogic.Mechanics; 6 | using Kingmaker.UnitLogic.Mechanics.Actions; 7 | using Kingmaker.Utility; 8 | using TabletopTweaks.Core.Utilities; 9 | 10 | namespace MicroscopicContentExpansion.Utils; 11 | internal class AuraUtils 12 | { 13 | 14 | public static AbilityAreaEffectRunAction CreateUnconditionalAuraEffect(BlueprintBuffReference buff) 15 | { 16 | return new AbilityAreaEffectRunAction() 17 | { 18 | UnitEnter = ActionFlow.DoSingle(b => 19 | { 20 | b.m_Buff = buff; 21 | b.Permanent = true; 22 | b.DurationValue = new ContextDurationValue(); 23 | }), 24 | UnitExit = ActionFlow.DoSingle(b => 25 | { 26 | b.m_Buff = buff; 27 | b.RemoveRank = false; 28 | b.ToCaster = false; 29 | }), 30 | UnitMove = ActionFlow.DoNothing(), 31 | Round = ActionFlow.DoNothing() 32 | }; 33 | } 34 | 35 | public static BlueprintAbilityAreaEffect CreateUnconditionalHostileAuraEffect(TabletopTweaks.Core.ModLogic.ModContextBase modContext, string bpName, int size, BlueprintBuffReference buff) 36 | { 37 | return Helpers.CreateBlueprint(modContext, bpName, bp => 38 | { 39 | bp.AggroEnemies = true; 40 | bp.AffectEnemies = true; 41 | bp.m_TargetType = BlueprintAbilityAreaEffect.TargetType.Enemy; 42 | bp.Shape = AreaEffectShape.Cylinder; 43 | bp.Size = size.Feet(); 44 | bp.Fx = new PrefabLink(); 45 | bp.AddComponent(c => 46 | { 47 | c.Condition = new(); 48 | c.m_Buff = buff; 49 | }); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Repository.json: -------------------------------------------------------------------------------- 1 | { 2 | "Releases": [ 3 | { 4 | "Id": "MicroscopicContentExpansion", 5 | "Version": "1.20.0" 6 | } 7 | ] 8 | } --------------------------------------------------------------------------------