From 27e61dd0a79e50d6620b6608907655932bbfb128 Mon Sep 17 00:00:00 2001 From: Andre White Date: Thu, 7 Sep 2023 00:37:12 -0600 Subject: [PATCH 01/19] :construction: Linting Markdown in Concordian Testing markdown lint exclusions in Acceptance test markdown (Concordian) --- .../io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md b/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md index c751375a..7cf3cedd 100644 --- a/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md +++ b/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md @@ -49,9 +49,10 @@ These feats are not recommended for characters with actual levels of the class. | [Half-Elf Dilettante: Sorcerer](http://ddowiki.com/page/Half-Elf_Dilettante:_Sorcerer "Half-Elf Dilettante: Sorcerer") | Passive | Able to use wands and scrolls as if you were a level one sorcerer. |* Half-Elf* 13 Charisma | | [Half-Elf Dilettante: Warlock](http://ddowiki.com/page/Half-Elf_Dilettante:_Warlock "Half-Elf Dilettante: Warlock") | Passive | Able to use wands and scrolls as if you were a level one warlock. Toggle: You deal 1D4 extra Fire damage with attacks and spells. This trigger at most once every two seconds. This toggle is exclusive with Warlock Pact toggles. |* Half-Elf* 13 Charisma | | [Half-Elf Dilettante: Wizard](http://ddowiki.com/page/Half-Elf_Dilettante:_Wizard "Half-Elf Dilettante: Wizard") | Passive | Able to use wands and scrolls as if you were a level one wizard. |* Half-Elf* 13 Intelligence | - + [existingDilettanteFeat]: - "c:verify-rows=#feat:verifyDilettante()" [_matchStrategy_]: - "c:matchStrategy=KeyMatch" -[result]: - "?=#feat" \ No newline at end of file +[result]: - "?=#feat" + From 8ca85ed4657213c1497ef4d193cd7193fd65abb0 Mon Sep 17 00:00:00 2001 From: Andre White Date: Fri, 8 Sep 2023 17:11:07 -0600 Subject: [PATCH 02/19] upstream version sync --- .trunk/.gitignore | 2 +- .trunk/trunk.yaml | 24 ++-- README.md | 15 ++- ...axonomy.kotlin-test-conventions.gradle.kts | 29 ++--- .../djaxonomy.test-conventions.gradle.kts | 2 +- .../kotlin/io/truthencode/TestExtensions.kt | 2 +- .../main/kotlin/node-conventions.gradle.kts | 2 +- build.gradle.kts | 25 ++--- docs/developers_guide/EffectBuilder.md | 8 +- docs/developers_guide/Project_Layout.md | 2 +- docs/index.md | 12 +- docs/resources/integration.md | 2 +- docs/resources/otherapps.md | 1 - mkdocs.yml | 104 ++++++++---------- project-dependencies.dot | 13 --- .../ddo/model/feats/races/HalfElfFeatSpec.md | 54 +++++---- .../common/ddo-test-results/build.gradle.kts | 1 + 17 files changed, 130 insertions(+), 168 deletions(-) delete mode 100644 project-dependencies.dot diff --git a/.trunk/.gitignore b/.trunk/.gitignore index 8130ba6d..1e246529 100644 --- a/.trunk/.gitignore +++ b/.trunk/.gitignore @@ -2,7 +2,7 @@ *logs *actions *notifications +*tools plugins user_trunk.yaml user.yaml -shims diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 4f1c7cf1..a2082aa5 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,26 +1,28 @@ version: 0.1 cli: - version: 1.13.0 +version: 1.15.0 + plugins: sources: - id: trunk - ref: v0.0.17 + ref: v1.2.1 uri: https://github.com/trunk-io/plugins lint: enabled: - - actionlint@1.6.24 + - taplo@0.8.1 + - actionlint@1.6.25 - dotenv-linter@3.3.0 - git-diff-check - - gitleaks@8.16.3 - - ktlint@0.49.0 - - markdownlint@0.34.0 + - gitleaks@8.18.0 + - ktlint@0.50.0 + - markdownlint@0.36.0 - oxipng@8.0.0 - - prettier@2.8.8 - - renovate@35.71.6 - - scalafmt@3.7.3 + - prettier@3.0.3 + - renovate@36.83.0 + - scalafmt@3.7.14 - shellcheck@0.9.0 - - shfmt@3.5.0 - - yamllint@1.31.0 + - shfmt@3.6.0 + - yamllint@1.32.0 runtimes: enabled: - go@1.19.5 diff --git a/README.md b/README.md index 8fbb16ad..7ad045cf 100644 --- a/README.md +++ b/README.md @@ -2,27 +2,26 @@ ## DDO Calculations, Planner and Plotting - DDO-Calc is a set of programs that I am creating to become more familiar with alternative JVM languages and multiple platforms. I am also a fan of [DDO Online](http://www.ddo.com). -At the end, I would like to create a Character planner that includes the ability to discover / analyze equipment and support a database. Target clients may include Android, Desktop via JavaFx and web (possible Google Web App). +At the end, I would like to create a Character planner that includes the ability to discover / analyze equipment and support a database. Target clients may include Android, Desktop via JavaFx and web (possible Google Web App). The bulk of the codebase is targeted for Scala, with R providing some analytics / graphing of power curves etc. The transport will eventually be an interconnected RESTful API over Websockets where possible using JSoN with optional Xml outputs utilizing Firebase and / or MongoDB as a potential backend. -One of the final additional goals is extensibility. The intention is to provide an Open API and to be both Swagger 2.0 and RAML 0.8 compliant. +One of the final additional goals is extensibility. The intention is to provide an Open API and to be both Swagger 2.0 and RAML 0.8 compliant. This API will should feature Semantic Versioning once considered stable enough to promote out of Alpha status. -- - - -[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg?style=plastic)](https://raw.githubusercontent.com/adarro/ddo-calc/master/LICENSE) [![Project Stats](https://www.openhub.net/p/ddo-calc/widgets/project_thin_badge?format=gif&ref=Thin+badge)](https://www.openhub.net/p/ddo-calc) [![GitHub forks](https://img.shields.io/github/forks/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/network) [![GitHub stars](https://img.shields.io/github/stars/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/stargazers) -![Travis CI](https://travis-ci.org/adarro/ddo-calc.svg?branch=master) [![Build status](https://ci.appveyor.com/api/projects/status/pnp0ghiwcu2lpkft?svg=true)](https://ci.appveyor.com/project/adarro/ddo-calc) [![Dependency Status](https://www.versioneye.com/user/projects/58c90554d01cb20045124875/badge.svg?style=plastic)](https://www.versioneye.com/user/projects/58c90554d01cb20045124875) +--- + +[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg?style=plastic)](https://raw.githubusercontent.com/adarro/ddo-calc/master/LICENSE) [![Project Stats](https://www.openhub.net/p/ddo-calc/widgets/project_thin_badge?format=gif&ref=Thin+badge)](https://www.openhub.net/p/ddo-calc) [![GitHub forks](https://img.shields.io/github/forks/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/network) [![GitHub stars](https://img.shields.io/github/stars/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/stargazers) +![Travis CI](https://travis-ci.org/adarro/ddo-calc.svg?branch=master) [![Build status](https://ci.appveyor.com/api/projects/status/pnp0ghiwcu2lpkft?svg=true)](https://ci.appveyor.com/project/adarro/ddo-calc) [![Dependency Status](https://www.versioneye.com/user/projects/58c90554d01cb20045124875/badge.svg?style=plastic)](https://www.versioneye.com/user/projects/58c90554d01cb20045124875) -[![Codacy Badge](https://api.codacy.com/project/badge/grade/2a569860b46048d3b84f2f6ecd0eaf2b)](https://www.codacy.com/app/adarro/ddo-calc) [![GitHub issues](https://img.shields.io/github/issues/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/issues) +[![Codacy Badge](https://api.codacy.com/project/badge/grade/2a569860b46048d3b84f2f6ecd0eaf2b)](https://www.codacy.com/app/adarro/ddo-calc) [![GitHub issues](https://img.shields.io/github/issues/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/issues) API Compliance ![Swagger 2.0](http://online.swagger.io/validator?url=https://raw.githubusercontent.com/adarro/ddo-calc/master/swagger.yaml) [![Java SDK](https://apimatic.io/apiarydocs/image?template=java)](https://apimatic.io/apiarydocs/sdk?template=java&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![Windows SDK](https://apimatic.io/apiarydocs/image?template=windows)](https://apimatic.io/apiarydocs/sdk?template=windows&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![Android SDK](https://apimatic.io/apiarydocs/image?template=android)](https://apimatic.io/apiarydocs/sdk?template=android&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![iOS SDK](https://apimatic.io/apiarydocs/image?template=ios)](https://apimatic.io/apiarydocs/sdk?template=ios&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![PHP SDK](https://apimatic.io/apiarydocs/image?template=php)](https://apimatic.io/apiarydocs/sdk?template=php&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![Python SDK](https://apimatic.io/apiarydocs/image?template=python)](https://apimatic.io/apiarydocs/sdk?template=python&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![Ruby SDK](https://apimatic.io/apiarydocs/image?template=ruby)](https://apimatic.io/apiarydocs/sdk?template=ruby&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![GOLang SDK](https://apimatic.io/apiarydocs/image?template=golang)](https://apimatic.io/apiarydocs/sdk?template=golang&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![AngularJS SDK](https://apimatic.io/apiarydocs/image?template=angularjs)](https://apimatic.io/apiarydocs/sdk?template=angularjs&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode)[![NodeJS SDK](https://apimatic.io/apiarydocs/image?template=nodejs)](https://apimatic.io/apiarydocs/sdk?template=nodejs&token=NTc2Nzc0NDVhMDE5ZTExY2E4MzQ1ZWY1&apiid=truthencode) - diff --git a/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts index 71e30521..7ee142a5 100644 --- a/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts @@ -61,38 +61,35 @@ afterEvaluate { } } } - } -// Extensions are just plain objects, there is no interface/type -class MyExtension(foo: String) { - -} +// Extensions are just plain objects, there is no interface/type +class MyExtension(foo: String) // Add new extensions via the extension container -//val myExt = project.extensions.create("custom", MyExtension::class, "bar") +// val myExt = project.extensions.create("custom", MyExtension::class, "bar") // («name», «type», «constructor args», …) -//myExt { +// myExt { // -//} +// } -//val theRealState = +// val theRealState = // theState() // project.extensions.create("theState", TheStateExtension::class) // TheStateExtension.theState() // -//theRealState { +// theRealState { // theDeepState {} // -//} +// } // -//// 1: DSL-like -//theState { +// // 1: DSL-like +// theState { // theDeepState { // theDeepestState { // undermine "the will of the people" // } // } -//} +// } // extensions appear as properties on the target object by the given name @@ -105,8 +102,6 @@ afterEvaluate { val ts = TestBuildSupport(project) - - suites { val test = when (testMode) { @@ -150,4 +145,4 @@ afterEvaluate { // } } } -} +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts index ce670891..3dd2afc7 100644 --- a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts @@ -77,4 +77,4 @@ project.testing { */ } } -} +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt index ba447280..1dc0a005 100644 --- a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt +++ b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt @@ -42,4 +42,4 @@ class TestBuildSupport(proj: Project) { implementation("io.kotest:kotest-property:$koTestVersion") } } -} +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/node-conventions.gradle.kts b/build-logic/src/main/kotlin/node-conventions.gradle.kts index edaaede4..a219e638 100644 --- a/build-logic/src/main/kotlin/node-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/node-conventions.gradle.kts @@ -147,7 +147,7 @@ tasks.register("package") { from(buildTaskUsingNpm) { into("npm") } - from (buildTaskUsingYarn) { + from(buildTaskUsingYarn) { into("yarn") } } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 603eb4c8..86f3c59c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,14 +41,13 @@ plugins { // id ("be.vbgn.ci-detect") version "0.1.0" } - // general project information val projectName = project.name val gitHubAccountName = "truthencode" val gitHubBaseSite = "https://github.com/$gitHubAccountName/${project.name}" -val siteIssueTracker = "${gitHubBaseSite}/issues" +val siteIssueTracker = "$gitHubBaseSite/issues" val gitExtension = "${project.name}.git" -val siteScm = "${gitHubBaseSite}/$gitExtension" +val siteScm = "$gitHubBaseSite/$gitExtension" // Used for versioned documentation val mkDocsLatestAlias: String? by project @@ -64,8 +63,6 @@ mkdocs { with(publish) { this.generateVersionsFile = true } - - } val devRequirementsIn = listOf( @@ -89,17 +86,16 @@ val requirementsIn = listOf( tasks.register("generateRequirementsIn") { val rIn = layout.projectDirectory.file("requirements.in") this.outputs.files(rIn) - val rTxt = requirementsIn.joinToString("\n") { it.replace(":","==") } + val rTxt = requirementsIn.joinToString("\n") { it.replace(":", "==") } logger.error("rText : \n$rTxt") rIn.asFile.writeText(rTxt) } python { this.pip( - requirementsIn.concat(devRequirementsIn) + requirementsIn.concat(devRequirementsIn), ) installVirtualenv = true - } tasks.register("dumpSomeDiagnostics") { @@ -113,7 +109,6 @@ tasks.register("dumpSomeDiagnostics") { println(SimpleDateFormat("HH:mm:ss dd/MM/yyyy", Locale.US).format(Date(nyxState.timestamp))) println(nyxState.version) } - } } @@ -131,7 +126,6 @@ tasks.register("syncDocVersion", PythonTask::class) { } } - tasks.register("syncRequirements", PythonTask::class) { dependsOn(tasks.named("nyxInfer"), tasks.named("generateRequirementsIn")) module = "piptools" @@ -232,7 +226,6 @@ class VersionInfo { return readOptionalProperty(props, key, defaultValue) } - val props = versionProperties() val major = optionalProperty("version.major", "0")?.toInt() val minor = optionalProperty("version.minor", "0")?.toInt() @@ -255,7 +248,9 @@ class VersionInfo { fun readOptionalProperty(prop: Properties, key: String, defaultValue: String? = null): String? { val oKey = if (prop.containsKey(key)) { prop.getProperty(key) - } else null + } else { + null + } val pKey = when { oKey.isNullOrBlank() -> null else -> prop.getProperty(key) @@ -273,11 +268,9 @@ class VersionInfo { val foo = project.rootProject.layout.files("version.properties") - val syncVersionFilesFromRoot by tasks.registering(Copy::class) { if (rootProject != project) { logger.warn("This task should only be run from the root project") - } else { logger.warn("in root project, propagating properties") rootProject.allprojects.forEach { @@ -287,8 +280,6 @@ val syncVersionFilesFromRoot by tasks.registering(Copy::class) { into(it.layout.buildDirectory) } } - - } } @@ -315,4 +306,4 @@ allprojects { // tasks.withType { // mustRunAfter(syncVersionFiles) // } -} +} \ No newline at end of file diff --git a/docs/developers_guide/EffectBuilder.md b/docs/developers_guide/EffectBuilder.md index 53267b8f..1ee31aaa 100644 --- a/docs/developers_guide/EffectBuilder.md +++ b/docs/developers_guide/EffectBuilder.md @@ -39,14 +39,15 @@ mindmapDiagram { +++ Named Items ++++ Augments <> ++++ Filigrees <> -+++ Random Loot ++++ Random Loot +++ Crafted Items -+++ Set bonus ++++ Set bonus @endmindmap ``` + ### Entity effects Entities in this context include All feats, enhancements, destinies, skills, attributes etc. These are represented by @@ -122,7 +123,7 @@ Even if this and random loot are not fully comprehensive, simply having the abil slot available, and I'm trying to increase my 'Y'" could now return a list of effects that let you know there are craft-able, named items or random loot effects available (or unavailable) even if it doesn't have a specific item. I.e. it will be aware that an Insight Bonus to 'Y' can be Cannith crafted to that 'X' slot, but random loot only has that -effect on a different slot. +effect on a different slot. ### Augments / Filigrees @@ -133,7 +134,6 @@ These will follow the same principles as the Named items. Set bonuses will be handled in the same way as any other named enchantments, with a triggerOn condition of 'X' equipped items / augments. Required Modules: ddo-etl, ddo-dao - ### Temporary effects These will be named effects with a triggerOff condition of some time duration, on Death, on dispel etc. diff --git a/docs/developers_guide/Project_Layout.md b/docs/developers_guide/Project_Layout.md index 95004d06..d2520909 100644 --- a/docs/developers_guide/Project_Layout.md +++ b/docs/developers_guide/Project_Layout.md @@ -4,6 +4,6 @@ Current Inter-project layout ```dot {! - include "./project-dependencies.dot" + include "./project-dependencies.dot" !} ``` diff --git a/docs/index.md b/docs/index.md index 7a180048..824a5673 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,26 +2,24 @@ ## DDO Calculations, Planner and Plotting - DDO-Calc is a set of programs that I am creating to become more familiar with alternative JVM languages and multiple platforms. I am also a fan of [DDO Online](http://www.ddo.com). -At the end, I would like to create a Character planner that includes the ability to discover / analyze equipment and support a database. Target clients may include Android, Desktop via JavaFx and web (possible Google Web App). +At the end, I would like to create a Character planner that includes the ability to discover / analyze equipment and support a database. Target clients may include Android, Desktop via JavaFx and web (possible Google Web App). The bulk of the codebase is targeted for Scala, with R providing some analytics / graphing of power curves etc. The transport will eventually be an interconnected RESTful API over Websockets where possible using JSoN with optional Xml outputs utilizing Firebase and / or MongoDB as a potential backend. -One of the final additional goals is extensibility. The intention is to provide an Open API and to be both Swagger 2.0 and RAML 0.8 compliant. +One of the final additional goals is extensibility. The intention is to provide an Open API and to be both Swagger 2.0 and RAML 0.8 compliant. This API will should feature Semantic Versioning once considered stable enough to promote out of Alpha status. +--- -- - - -[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg?style=plastic)](https://raw.githubusercontent.com/adarro/ddo-calc/master/LICENSE) [![Project Stats](https://www.openhub.net/p/ddo-calc/widgets/project_thin_badge?format=gif&ref=Thin+badge)](https://www.openhub.net/p/ddo-calc) [![GitHub forks](https://img.shields.io/github/forks/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/network) [![GitHub stars](https://img.shields.io/github/stars/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/stargazers) [![GitHub issues](https://img.shields.io/github/issues/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/issues) +[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg?style=plastic)](https://raw.githubusercontent.com/adarro/ddo-calc/master/LICENSE) [![Project Stats](https://www.openhub.net/p/ddo-calc/widgets/project_thin_badge?format=gif&ref=Thin+badge)](https://www.openhub.net/p/ddo-calc) [![GitHub forks](https://img.shields.io/github/forks/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/network) [![GitHub stars](https://img.shields.io/github/stars/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/stargazers) [![GitHub issues](https://img.shields.io/github/issues/adarro/ddo-calc.svg?style=plastic)](https://github.com/adarro/ddo-calc/issues) [![Build status](https://ci.appveyor.com/api/projects/status/pnp0ghiwcu2lpkft?svg=true)](https://ci.appveyor.com/project/adarro/ddo-calc) [![Dependency Status](https://www.versioneye.com/user/projects/58c90554d01cb20045124875/badge.svg?style=plastic)](https://www.versioneye.com/user/projects/58c90554d01cb20045124875) [![CircleCI](https://circleci.com/gh/truthencode/ddo-calc/tree/master.svg?style=shield)](https://circleci.com/gh/truthencode/ddo-calc/?branch=master) - -[![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=truthencode_ddo-calc)](https://sonarcloud.io/summary/new_code?id=truthencode_ddo-calc) [![Codecov](https://img.shields.io/codecov/c/github/adarro/ddo-calc.svg?maxAge=2592000?style=plastic)](https://codecov.io/github/adarro/ddo-calc) \ No newline at end of file +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/a32019b5ef2f4fe6a58a348a61184c3a)](https://app.codacy.com/gh/truthencode/ddo-calc/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)[![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=truthencode_ddo-calc)](https://sonarcloud.io/summary/new_code?id=truthencode_ddo-calc) [![Codecov](https://img.shields.io/codecov/c/github/adarro/ddo-calc.svg?maxAge=2592000?style=plastic)](https://codecov.io/github/adarro/ddo-calc) diff --git a/docs/resources/integration.md b/docs/resources/integration.md index 8cec5214..a8574c4a 100644 --- a/docs/resources/integration.md +++ b/docs/resources/integration.md @@ -4,4 +4,4 @@ At some point this page might show direct or indirect integration with other sit Ideally, I would like to fill the gaps of existing solutions as opposed to duplicating all their existing hard work. -examples include importing data from the undisputed Character Planner's forum export. \ No newline at end of file +examples include importing data from the undisputed Character Planner's forum export. diff --git a/docs/resources/otherapps.md b/docs/resources/otherapps.md index aba799fc..89b09005 100644 --- a/docs/resources/otherapps.md +++ b/docs/resources/otherapps.md @@ -1,4 +1,3 @@ # Third Party Applications Here are some of the existing 3rd party applications and sites that can already do many things to help you get the most out of DDO! - diff --git a/mkdocs.yml b/mkdocs.yml index f2a0d67c..b284d011 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,18 +17,18 @@ copyright: > # Material theme theme: - name: 'material' + name: material palette: - - media: "(prefers-color-scheme: light)" - scheme: default - toggle: - icon: material/toggle-switch-off-outline - name: Switch to dark mode - - media: "(prefers-color-scheme: dark)" - scheme: slate - toggle: - icon: material/toggle-switch - name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/toggle-switch-off-outline + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/toggle-switch + name: Switch to light mode features: #- navigation.tabs #- navigation.tabs.sticky @@ -44,13 +44,12 @@ plugins: # Required for variables support (https://github.com/rosscdh/mkdocs-markdownextradata-plugin) - markdownextradata - embed_file: - callouts: true - # custom-attribute: 'assets/css/custom_attributes.css' //need to be the same as in the config! - language_message: 'file does not currently exists.' + callouts: true + # custom-attribute: 'assets/css/custom_attributes.css' //need to be the same as in the config! + language_message: file does not currently exists. - include-markdown: - opening_tag: "{!" - closing_tag: "!}" - + opening_tag: "{!" + closing_tag: "!}" extra: version: @@ -64,7 +63,6 @@ extra: find what they're searching for. With your consent, you're helping us to make our documentation better. - # palette: # primary: 'indigo' # accent: 'indigo' @@ -92,60 +90,54 @@ markdown_extensions: - footnotes - meta - md_in_html - - toc: - permalink: true + - toc: + permalink: true # Python Markdown Extensions - - pymdownx.arithmatex: - generic: true - - pymdownx.betterem: - smart_enable: all + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all - pymdownx.caret - pymdownx.details - - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg - pymdownx.highlight - pymdownx.inlinehilite - pymdownx.keys - pymdownx.mark - pymdownx.smartsymbols - pymdownx.superfences - - pymdownx.tabbed: - alternate_style: true - - pymdownx.tasklist: - custom_checkbox: true + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true - pymdownx.tilde # plantuml - - plantuml_markdown: - server: http://www.plantuml.com/plantuml # PlantUML server, for remote rendering - # other global options - insecure: False # set to True if the server uses self-signed certificates - cachedir: /tmp # set a non-empty value to enable caching - base_dir: . # where to search for diagrams to include - config: # PlantUML config file, relative to base_dir (a PlantUML file included in every diagram) - format: png # default diagram image format - classes: class1,class2 # default diagram classes - encoding: utf-8 # character encoding for external files (default utf-8) - title: UML diagram # default title (tooltip) for diagram images - alt: UML diagram image # default `alt` attribute for diagram images - image_maps: True # generate image maps when the format is png and there are hyperlinks - priority: 30 # plugin priority; the higher, the sooner will be applied (default 30) - http_method: GET # GET or POST - note that plantuml.com only supports GET (default GET) - fallback_to_get: True # When using POST, should GET be used as fallback (POST will fail if @startuml/@enduml tags not used) (default True) - theme: bluegray # theme to be set, can be overridden inside puml files, (default none) - puml_notheme_cmdlist: [ - 'version', - 'listfonts', - 'stdlib', - 'license' - ] # theme will not be set if listed commands present (default as listed) + - plantuml_markdown: + server: http://www.plantuml.com/plantuml # PlantUML server, for remote rendering + # other global options + insecure: False # set to True if the server uses self-signed certificates + cachedir: /tmp # set a non-empty value to enable caching + base_dir: . # where to search for diagrams to include + config: # PlantUML config file, relative to base_dir (a PlantUML file included in every diagram) + format: png # default diagram image format + classes: class1,class2 # default diagram classes + encoding: utf-8 # character encoding for external files (default utf-8) + title: UML diagram # default title (tooltip) for diagram images + alt: UML diagram image # default `alt` attribute for diagram images + image_maps: True # generate image maps when the format is png and there are hyperlinks + priority: 30 # plugin priority; the higher, the sooner will be applied (default 30) + http_method: GET # GET or POST - note that plantuml.com only supports GET (default GET) + fallback_to_get: True # When using POST, should GET be used as fallback (POST will fail if @startuml/@enduml tags not used) (default True) + theme: bluegray # theme to be set, can be overridden inside puml files, (default none) + puml_notheme_cmdlist: ["version", "listfonts", "stdlib", "license"] # theme will not be set if listed commands present (default as listed) - mkdocs_graphviz - nl2br extra_javascript: - https://cdn.jsdelivr.net/gh/rod2ik/cdn@main/mkdocs/javascripts/mkdocs-graphviz.js - #nav: # - Home: index.md # - User guide: @@ -156,4 +148,4 @@ extra_javascript: # - Release notes: about/history.md # - Roadmap: # - Tasks: about/Tasks.md -# - Components: '*include components/*/mkdocs.yml' \ No newline at end of file +# - Components: '*include components/*/mkdocs.yml' diff --git a/project-dependencies.dot b/project-dependencies.dot deleted file mode 100644 index 201472ac..00000000 --- a/project-dependencies.dot +++ /dev/null @@ -1,13 +0,0 @@ -strict digraph { -splines=ortho -"ddo-modeling" -> "ddo-platform-scala" -"ddo-testing-util" -> "ddo-platform-scala" -"ddo-test-results" -> "ddo-core" -"ddo-core" -> "ddo-platform-scala" -"ddo-core" -> "ddo-util" -"ddo-core" -> "ddo-modeling" -"ddo-core" -> "ddo-core" -"ddo-core" -> "ddo-testing-util" -"ddo-etl" -> "ddo-platform-scala" -"ddo-util" -> "ddo-platform-scala" -} diff --git a/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md b/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md index 7cf3cedd..4dbe0ba8 100644 --- a/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md +++ b/subprojects/common/ddo-core/src/specs/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md @@ -2,17 +2,15 @@ ## [Half Elf Feats](http://ddowiki.com/page/Category:Half-Elf_feats) -| [ ][existingFeat] [Feats][result]| Type | Description | Prerequisites | -|----------------------------------------|--------|----|----| -| [Half-Elf Keen Senses](http://ddowiki.com/edit/Half-Elf_Keen_Senses?redlink=1 "Half-Elf Keen Senses (page does not exist)") | Passive | +1 racial bonus to Listen, Search, and Spot checks. |* Half-Elf | -| [Half-Elf Mixed Heritage](http://ddowiki.com/edit/Half-Elf_Mixed_Heritage?redlink=1 "Half-Elf Mixed Heritage (page does not exist)") | Passive | Half-elves are treated as both an Elf and a Human by magical items and effects if one would be beneficial. Negative effects treat Half-Elves as if they were Elves. |* Half-Elf| -| [Half-Elf Social Graces](http://ddowiki.com/edit/Half-Elf_Social_Graces?redlink=1 "Half-Elf Social Graces (page does not exist)") | Passive | Half-Elves get an additional roll for each use of the skills Intimidate, Diplomacy, and Bluff. | Half-Elf | -| [Immunity to Sleep](http://ddowiki.com/page/Immunity_to_Sleep "Immunity to Sleep") | Passive | Half Elves are naturally immune to magical sleep effects. | Drow Elf, Elf, Half-Elf, Sun Elf | +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | +| ------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| [Half-Elf Keen Senses](http://ddowiki.com/edit/Half-Elf_Keen_Senses?redlink=1 "Half-Elf Keen Senses (page does not exist)") | Passive | +1 racial bonus to Listen, Search, and Spot checks. | \* Half-Elf | +| [Half-Elf Mixed Heritage](http://ddowiki.com/edit/Half-Elf_Mixed_Heritage?redlink=1 "Half-Elf Mixed Heritage (page does not exist)") | Passive | Half-elves are treated as both an Elf and a Human by magical items and effects if one would be beneficial. Negative effects treat Half-Elves as if they were Elves. | \* Half-Elf | +| [Half-Elf Social Graces](http://ddowiki.com/edit/Half-Elf_Social_Graces?redlink=1 "Half-Elf Social Graces (page does not exist)") | Passive | Half-Elves get an additional roll for each use of the skills Intimidate, Diplomacy, and Bluff. | Half-Elf | +| [Immunity to Sleep](http://ddowiki.com/page/Immunity_to_Sleep "Immunity to Sleep") | Passive | Half Elves are naturally immune to magical sleep effects. | Drow Elf, Elf, Half-Elf, Sun Elf | [existingFeat]: - "c:verify-rows=#feat:verifyNonDilettante()" - [_matchStrategy_]: - "c:matchStrategy=KeyMatch" - [result]: - "?=#feat" ## Dilettante feats @@ -26,33 +24,33 @@ When retraining feats by talking to [Fred](http://ddowiki.com/page/Fred "Fred"), increase [tome](http://ddowiki.com/page/Tome "Tome") bonuses are NOT counted for prerequisites, however, ability increases from [level-up](http://ddowiki.com/page/Ability "Ability") -Characters can increase an [ability](http://ddowiki.com/page/Ability "Ability") by one at levels: 4, 8, 12, 16, 20, and -24. ARE counted. [(Nov 2012 forum post)](http://forums.ddo.com/showthread.php?t=399599) +Characters can increase an [ability](http://ddowiki.com/page/Ability "Ability") by one at levels: 4, 8, 12, 16, 20, and 24. ARE counted. [(Nov 2012 forum post)](http://forums.ddo.com/showthread.php?t=399599) Along with various bonuses, you, with these feats, count as a level one of the class for item use purposes (class restricted items, [scrolls](http://ddowiki.com/page/Scroll "Scroll") and [wands](http://ddowiki.com/page/Wand "Wand")). These feats are not recommended for characters with actual levels of the class. -| [ ][existingDilettanteFeat] [Feats][result]| Type | Description | Prerequisites | -|---|---|----|---| -| [Half-Elf Dilettante: Artificer](http://ddowiki.com/edit/Half-Elf_Dilettante:_Artificer?redlink=1 "Half-Elf Dilettante: Artificer (page does not exist)") | Passive | You have watched the artificers of House Cannith work their trade. You gain proficiency with all crossbows, and Artificer Knowledge: Scrolls (You gain a +2 bonus to Use Magical Device checks when using scrolls, and their Caster Level is increased by one - this Caster Level increase is capped by your Intelligence modifier.) You are able to use wands and scrolls as if you are a level one artificer. For item use purposes you count as a level one artificer in addition to any other classes you possess (though this does not grant the ability to use Rune Arms). | Half-Elf 13 Intelligence | -| [Half-Elf Dilettante: Barbarian](http://ddowiki.com/page/Half-Elf_Dilettante:_Barbarian "Half-Elf Dilettante: Barbarian") | Passive | [Damage Reduction](http://ddowiki.com/page/Damage_Reduction "Damage Reduction") 1/- (does not stack with Barbarian Damage Reduction). |* Half-Elf * 13 Constitution | -| [Half-Elf Dilettante: Bard](http://ddowiki.com/page/Half-Elf_Dilettante:_Bard "Half-Elf Dilettante: Bard") | Active | Can produce a Bardic [Fascinate](http://ddowiki.com/page/Fascinate "Fascinate") effect three times per rest that mesmerizes nearby enemies, with a Will DC based on a Perform check (or 1d20 + Charisma Modifier if untrained) to negate. Able to use wands and scrolls as if you were a level one bard. |* Half-Elf* 13 Charisma | -| [Half-Elf Dilettante: Cleric](http://ddowiki.com/pagepage/Half-Elf_Dilettante:_Cleric "Half-Elf Dilettante: Cleric") | Passive | Able to use wands and scrolls as if you were a level one cleric. |* Half-Elf * 13 Wisdom | -| [Half-Elf Dilettante: Druid](http://ddowiki.com/page/Half-Elf_Dilettante:_Druid?redlink=1 "Half-Elf Dilettante: Druid (page does not exist)") | Passive | Able to use wands and scrolls as if you were a level one druid. |* Half-Elf * 13 Wisdom | -| [Half-Elf Dilettante: Favored Soul](http://ddowiki.com/page/Half-Elf_Dilettante:_Favored_Soul "Half-Elf Dilettante: Favored Soul") | Passive | Able to use wands and scrolls as if you were a level one favored soul. |* Half-Elf * 13 Charisma | -| [Half-Elf Dilettante: Fighter](http://ddowiki.com/page/Half-Elf_Dilettante:_Fighter "Half-Elf Dilettante: Fighter") | Passive | Proficiency with all martial melee weapons. |* Half-Elf* 13 Strength | -| [Half-Elf Dilettante: Monk](http://ddowiki.com/page/Half-Elf_Dilettante:_Monk "Half-Elf Dilettante: Monk") | Passive | Proficiency with the [quarterstaff](http://ddowiki.com/page/Quarterstaff "Quarterstaff"), [kama](http://ddowiki.com/page/Kama "Kama"), and [shuriken](http://ddowiki.com/page/Shuriken "Shuriken"), and can add up to 2 points of your Wisdom bonus to your Armor Class as long as you are Defensively [Centered](http://ddowiki.com/page/Centered "Centered") (unarmored and unencumbered, does not stack with the similar monk class ability). |* Half-Elf * 13 Wisdom | -| [Half-Elf Dilettante: Paladin](http://ddowiki.com/page/Half-Elf_Dilettante:_Paladin "Half-Elf Dilettante: Paladin") | Passive | Can add up to 2 points of your Charisma bonus to all saves (does not stack with the [Divine Grace](http://ddowiki.com/page/Divine_Grace "Divine Grace") ability). Able to use wands and scrolls as if you were a level one paladin. |* Half-Elf,* 13 Charisma | -| [Half-Elf Dilettante: Ranger](http://ddowiki.com/page/Half-Elf_Dilettante:_Ranger "Half-Elf Dilettante: Ranger") | Passive | Proficiency with all martial ranged weapons, and can add up to 2 points of your Strength bonus to bow damage. Able to use wands and scrolls as if you were a level one ranger. |* Half-Elf * 13 Dexterity | -| [Half-Elf Dilettante: Rogue](http://ddowiki.com/page/Half-Elf_Dilettante:_Rogue "Half-Elf Dilettante: Rogue") | Passive | You deal +1d6 Sneak Attack damage (does not stack with the Rogue [Sneak Attack](http://ddowiki.com/page/Sneak_Attack "Sneak Attack") ability). |* Half-Elf,* 13 Dexterity | -| [Half-Elf Dilettante: Sorcerer](http://ddowiki.com/page/Half-Elf_Dilettante:_Sorcerer "Half-Elf Dilettante: Sorcerer") | Passive | Able to use wands and scrolls as if you were a level one sorcerer. |* Half-Elf* 13 Charisma | -| [Half-Elf Dilettante: Warlock](http://ddowiki.com/page/Half-Elf_Dilettante:_Warlock "Half-Elf Dilettante: Warlock") | Passive | Able to use wands and scrolls as if you were a level one warlock. Toggle: You deal 1D4 extra Fire damage with attacks and spells. This trigger at most once every two seconds. This toggle is exclusive with Warlock Pact toggles. |* Half-Elf* 13 Charisma | -| [Half-Elf Dilettante: Wizard](http://ddowiki.com/page/Half-Elf_Dilettante:_Wizard "Half-Elf Dilettante: Wizard") | Passive | Able to use wands and scrolls as if you were a level one wizard. |* Half-Elf* 13 Intelligence | +| [ ][existingDilettanteFeat] [Feats][result] | Type | Description | Prerequisites | +| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| [Half-Elf Dilettante: Artificer](http://ddowiki.com/edit/Half-Elf_Dilettante:_Artificer?redlink=1 "Half-Elf Dilettante: Artificer (page does not exist)") | Passive | You have watched the artificers of House Cannith work their trade. You gain proficiency with all crossbows, and Artificer Knowledge: Scrolls (You gain a +2 bonus to Use Magical Device checks when using scrolls, and their Caster Level is increased by one - this Caster Level increase is capped by your Intelligence modifier.) You are able to use wands and scrolls as if you are a level one artificer. For item use purposes you count as a level one artificer in addition to any other classes you possess (though this does not grant the ability to use Rune Arms). | Half-Elf 13 Intelligence | +| [Half-Elf Dilettante: Barbarian](http://ddowiki.com/page/Half-Elf_Dilettante:_Barbarian "Half-Elf Dilettante: Barbarian") | Passive | [Damage Reduction](http://ddowiki.com/page/Damage_Reduction "Damage Reduction") 1/- (does not stack with Barbarian Damage Reduction). | _ Half-Elf _ 13 Constitution | +| [Half-Elf Dilettante: Bard](http://ddowiki.com/page/Half-Elf_Dilettante:_Bard "Half-Elf Dilettante: Bard") | Active | Can produce a Bardic [Fascinate](http://ddowiki.com/page/Fascinate "Fascinate") effect three times per rest that mesmerizes nearby enemies, with a Will DC based on a Perform check (or 1d20 + Charisma Modifier if untrained) to negate. Able to use wands and scrolls as if you were a level one bard. | _ Half-Elf_ 13 Charisma | +| [Half-Elf Dilettante: Cleric](http://ddowiki.com/pagepage/Half-Elf_Dilettante:_Cleric "Half-Elf Dilettante: Cleric") | Passive | Able to use wands and scrolls as if you were a level one cleric. | _ Half-Elf _ 13 Wisdom | +| [Half-Elf Dilettante: Druid](http://ddowiki.com/page/Half-Elf_Dilettante:_Druid?redlink=1 "Half-Elf Dilettante: Druid (page does not exist)") | Passive | Able to use wands and scrolls as if you were a level one druid. | _ Half-Elf _ 13 Wisdom | +| [Half-Elf Dilettante: Favored Soul](http://ddowiki.com/page/Half-Elf_Dilettante:_Favored_Soul "Half-Elf Dilettante: Favored Soul") | Passive | Able to use wands and scrolls as if you were a level one favored soul. | _ Half-Elf _ 13 Charisma | +| [Half-Elf Dilettante: Fighter](http://ddowiki.com/page/Half-Elf_Dilettante:_Fighter "Half-Elf Dilettante: Fighter") | Passive | Proficiency with all martial melee weapons. | _ Half-Elf_ 13 Strength | +| [Half-Elf Dilettante: Monk](http://ddowiki.com/page/Half-Elf_Dilettante:_Monk "Half-Elf Dilettante: Monk") | Passive | Proficiency with the [quarterstaff](http://ddowiki.com/page/Quarterstaff "Quarterstaff"), [kama](http://ddowiki.com/page/Kama "Kama"), and [shuriken](http://ddowiki.com/page/Shuriken "Shuriken"), and can add up to 2 points of your Wisdom bonus to your Armor Class as long as you are Defensively [Centered](http://ddowiki.com/page/Centered "Centered") (unarmored and unencumbered, does not stack with the similar monk class ability). | _ Half-Elf _ 13 Wisdom | +| [Half-Elf Dilettante: Paladin](http://ddowiki.com/page/Half-Elf_Dilettante:_Paladin "Half-Elf Dilettante: Paladin") | Passive | Can add up to 2 points of your Charisma bonus to all saves (does not stack with the [Divine Grace](http://ddowiki.com/page/Divine_Grace "Divine Grace") ability). Able to use wands and scrolls as if you were a level one paladin. | _ Half-Elf,_ 13 Charisma | +| [Half-Elf Dilettante: Ranger](http://ddowiki.com/page/Half-Elf_Dilettante:_Ranger "Half-Elf Dilettante: Ranger") | Passive | Proficiency with all martial ranged weapons, and can add up to 2 points of your Strength bonus to bow damage. Able to use wands and scrolls as if you were a level one ranger. | _ Half-Elf _ 13 Dexterity | +| [Half-Elf Dilettante: Rogue](http://ddowiki.com/page/Half-Elf_Dilettante:_Rogue "Half-Elf Dilettante: Rogue") | Passive | You deal +1d6 Sneak Attack damage (does not stack with the Rogue [Sneak Attack](http://ddowiki.com/page/Sneak_Attack "Sneak Attack") ability). | _ Half-Elf,_ 13 Dexterity | +| [Half-Elf Dilettante: Sorcerer](http://ddowiki.com/page/Half-Elf_Dilettante:_Sorcerer "Half-Elf Dilettante: Sorcerer") | Passive | Able to use wands and scrolls as if you were a level one sorcerer. | _ Half-Elf_ 13 Charisma | +| [Half-Elf Dilettante: Warlock](http://ddowiki.com/page/Half-Elf_Dilettante:_Warlock "Half-Elf Dilettante: Warlock") | Passive | Able to use wands and scrolls as if you were a level one warlock. Toggle: You deal 1D4 extra Fire damage with attacks and spells. This trigger at most once every two seconds. This toggle is exclusive with Warlock Pact toggles. | _ Half-Elf_ 13 Charisma | +| [Half-Elf Dilettante: Wizard](http://ddowiki.com/page/Half-Elf_Dilettante:_Wizard "Half-Elf Dilettante: Wizard") | Passive | Able to use wands and scrolls as if you were a level one wizard. | _ Half-Elf_ 13 Intelligence | + -[existingDilettanteFeat]: - "c:verify-rows=#feat:verifyDilettante()" +[existingDilettanteFeat]: - "c:verify-rows=#feat:verifyDilettante()" [_matchStrategy_]: - "c:matchStrategy=KeyMatch" - [result]: - "?=#feat" + diff --git a/subprojects/common/ddo-test-results/build.gradle.kts b/subprojects/common/ddo-test-results/build.gradle.kts index 0e61fb67..160db89e 100644 --- a/subprojects/common/ddo-test-results/build.gradle.kts +++ b/subprojects/common/ddo-test-results/build.gradle.kts @@ -17,6 +17,7 @@ reporting { } } +description = "Utility class for aggregating Reports" // Transliterated Groovy -> Kotlin from // https://gist.githubusercontent.com/nikialeksey/7cefae6b3104ce9a2c765197343bc436/raw/fb61c7d35480f9ae16650aefbb31c9c11420bec4/dependency-report.gradle // Inspired by https://gist.github.com/tzachz/419478fc8b009e953f5e5dc39f3f3a2a From 5f26554b52c0f3e1830249f5952e68100e00b49e Mon Sep 17 00:00:00 2001 From: Andre White Date: Fri, 8 Sep 2023 19:49:48 -0600 Subject: [PATCH 03/19] Syncing trunk version --- .trunk/trunk.yaml | 2 +- docs/resources/integration.md | 6 +++++- mkdocs.yml | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index a2082aa5..9b9da57b 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,6 +1,6 @@ version: 0.1 cli: -version: 1.15.0 + version: 1.15.0 plugins: sources: diff --git a/docs/resources/integration.md b/docs/resources/integration.md index a8574c4a..6be6cda9 100644 --- a/docs/resources/integration.md +++ b/docs/resources/integration.md @@ -2,6 +2,10 @@ At some point this page might show direct or indirect integration with other sites / applications. -Ideally, I would like to fill the gaps of existing solutions as opposed to duplicating all their existing hard work. +Ideally, I would like to fill the gaps with existing solutions as opposed to duplicating all their existing hard work. examples include importing data from the undisputed Character Planner's forum export. + +[DDO wiki](https://www.ddowiki.com) + + diff --git a/mkdocs.yml b/mkdocs.yml index b284d011..9937eb59 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -138,6 +138,7 @@ markdown_extensions: extra_javascript: - https://cdn.jsdelivr.net/gh/rod2ik/cdn@main/mkdocs/javascripts/mkdocs-graphviz.js + - https://cdn.jsdelivr.net/gh/eddymens/markdown-external-link-script@v2.0.0/main.min.js #nav: # - Home: index.md # - User guide: From b61df2c2f627f59f66783e28f1b1660b9713817f Mon Sep 17 00:00:00 2001 From: Andre White Date: Thu, 7 Sep 2023 02:10:11 -0600 Subject: [PATCH 04/19] :construction: :green_heart: codacy coverage attempt to apply bash for individual coverage reports. --- gradle/codacy_upload.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 gradle/codacy_upload.sh diff --git a/gradle/codacy_upload.sh b/gradle/codacy_upload.sh new file mode 100755 index 00000000..445ffa11 --- /dev/null +++ b/gradle/codacy_upload.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Exit script if you try to use an uninitialized variable. +set -o nounset + +# Exit script if a statement returns a non-true return value. +set -o errexit + +# Use the error status of the first failure, +# rather than that of the last item in a pipeline. +set -o pipefail + +find . -iname "cobertura.xml" | + xargs bash <(curl -Ls https://coverage.codacy.com/get.sh) report \ + --partial -l Scala -r + +bash <(curl -Ls https://coverage.codacy.com/get.sh) final From dac124381defa9d62401f0abf0d60a02f1109fb9 Mon Sep 17 00:00:00 2001 From: Andre White Date: Thu, 7 Sep 2023 06:32:37 -0600 Subject: [PATCH 05/19] :construction: Coverage data to Codacy Aggregate Scoverage via root scoverage gradle plugin task --- build-logic/settings.gradle.kts | 1 + build.gradle.kts | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts index af410770..a5c2529a 100644 --- a/build-logic/settings.gradle.kts +++ b/build-logic/settings.gradle.kts @@ -39,6 +39,7 @@ pluginManagement { id("com.palantir.baseline") version palantirPluginVersion id("com.palantir.baseline-config") version palantirPluginVersion id("org.inferred.processors") version "3.7.0" + id("org.scoverage") version "8.0.3" // id("ru.vyarus.mkdocs") version "3.0.0" } } diff --git a/build.gradle.kts b/build.gradle.kts index 86f3c59c..c5987723 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,6 @@ * limitations under the License. */ import com.mooltiverse.oss.nyx.state.State -import org.jetbrains.kotlin.util.collectionUtils.concat import ru.vyarus.gradle.plugin.python.task.PythonTask import java.text.SimpleDateFormat import java.util.* @@ -24,8 +23,10 @@ import java.util.* plugins { // id("code-quality") // id("org.kordamp.gradle.project") +// scala apply (false) + id("org.scoverage") apply (false) // may need node support - id("node-conventions") +// id("node-conventions") idea // id("net.thauvin.erik.gradle.semver") @@ -37,10 +38,12 @@ plugins { id("com.github.ben-manes.versions") version "0.41.0" id("nl.littlerobots.version-catalog-update") version "0.8.1" id("ru.vyarus.mkdocs") + // id("ru.vyarus.mkdocs") version "3.0.0" apply (false) // id ("be.vbgn.ci-detect") version "0.1.0" } +apply(plugin = "org.scoverage") // general project information val projectName = project.name val gitHubAccountName = "truthencode" @@ -93,7 +96,7 @@ tasks.register("generateRequirementsIn") { python { this.pip( - requirementsIn.concat(devRequirementsIn), + requirementsIn.plus(devRequirementsIn), ) installVirtualenv = true } From f85518c1eacacd803a4950fd2edc4ff148ae84c6 Mon Sep 17 00:00:00 2001 From: Andre White Date: Thu, 7 Sep 2023 23:24:32 -0600 Subject: [PATCH 06/19] :construction: Coverage data to Codacy Implementing JVMTestSuite logicf or Java / Scala / Kotlin TODO: Add integration / functional / acceptance --- build-logic/build.gradle.kts | 6 + build-logic/gradle.properties | 9 +- ...axonomy.kotlin-test-conventions.gradle.kts | 2 +- .../djaxonomy.test-conventions.gradle.kts | 141 +++++++++++++---- .../kotlin/io/truthencode/TestExtensions.kt | 86 +++++++++++ gradle.properties | 3 +- gradle/libs.versions.toml | 142 ++++-------------- subprojects/common/ddo-core/build.gradle.kts | 23 +-- subprojects/common/ddo-etl/build.gradle.kts | 30 ++-- .../io/truthencode/ddo/etl/LibrarySuite.scala | 1 + .../common/ddo-modeling/build.gradle.kts | 22 +-- 11 files changed, 267 insertions(+), 198 deletions(-) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index d7cb8a40..6f953ea2 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -34,6 +34,7 @@ val kotlinVersion: String by project val quarkusPlatformVersion: String by project val jandexPluginVersion: String by project val defaultJavaToolChainVersion: String? by project +val kasechangeVersion: String by project dependencies { // tool languages @@ -77,6 +78,11 @@ dependencies { // Database implementation("app.cash.sqldelight:gradle-plugin:2.0.0-alpha05") + // String utils + // camel / snake etc + // universal dependency for Gradle 5.3 and above + // in case of multiplatform project, just specify the dependency for commonMain/commonTest source set + implementation("net.pearx.kasechange:kasechange:$kasechangeVersion") /* to here */ // implementation("com.diffplug.spotless-changelog:spotless-changelog-plugin-gradle:2.4.0") // implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinPluginVersion") diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties index 9843b6b3..9e9d39a4 100644 --- a/build-logic/gradle.properties +++ b/build-logic/gradle.properties @@ -22,6 +22,8 @@ kotlinVersion=1.9.10 koTestVersion=5.5.5 +scalaVersions=2.12.18,2.11.12,2.13.12 + # Quarkus quarkusPluginId=io.quarkus quarkusPluginVersion=3.2.0.Final @@ -33,11 +35,14 @@ jandexPluginVersion=0.11.0 testSetsPluginVersion=2.1.1 kordampGradlePluginVersion=0.51.1 scalaTestPluginVersion=0.31 -scoveragePluginVersion=3.1.5 +scoveragePluginVersion=8.0.3 semVerPluginVersion=1.2.0 editorConfigVersion=0.0.3 # foojay foojayResolverPluginVersionversion=0.4.0 -palantirPluginVersion=5.17.0 \ No newline at end of file +palantirPluginVersion=5.17.0 + +# kotlin string util lib +kasechangeVersion=1.4.1 \ No newline at end of file diff --git a/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts index 7ee142a5..c25f7510 100644 --- a/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts @@ -64,7 +64,7 @@ afterEvaluate { } // Extensions are just plain objects, there is no interface/type -class MyExtension(foo: String) +// class MyExtension(foo: String) // Add new extensions via the extension container // val myExt = project.extensions.create("custom", MyExtension::class, "bar") diff --git a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts index 3dd2afc7..061957fe 100644 --- a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts @@ -1,6 +1,6 @@ import io.truthencode.djaxonomy.etc.KotlinTestKitExtension import io.truthencode.djaxonomy.etc.KotlinTestKits -import io.truthencode.djaxonomy.etc.TestBuildSupport +import io.truthencode.djaxonomy.etc.TestTypes /* * SPDX-License-Identifier: Apache-2.0 @@ -29,52 +29,129 @@ extension.useKotlinTestKit.convention( KotlinTestKits.KoTest, ) +fun JvmTestSuite.applyKoTest() { + val koTestVersion: String = (findProperty("koTestVersion") ?: embeddedKotlinVersion).toString() + + + dependencies { + implementation("io.kotest:kotest-runner-junit5:$koTestVersion") + implementation("io.kotest:kotest-assertions-core:$koTestVersion") + implementation("io.kotest:kotest-property:$koTestVersion") + } + + +} + +fun JvmTestSuite.applyKotlinTest() { + + + useKotlinTest() + + +} + +val junitScalaTestVersion: String by project +val junitPlatformVersion: String by project + +fun JvmTestSuite.applyScalaTest() { + dependencies { + runtimeOnly("co.helmethair:scalatest-junit-runner:$junitScalaTestVersion") + runtimeOnly("org.junit.vintage:junit-vintage-engine:$junitPlatformVersion") + } + + targets.all { + testTask.configure { + useJUnitPlatform { + includeEngines = setOf("scalatest", "vintage") + testLogging { + events("passed", "skipped", "failed") + } + } + } + } +} + project.testing { suites { - apply { - if (plugins.hasPlugin("org.jetbrains.kotlin.jvm")) { - val ts = TestBuildSupport(project) - when (extension.useKotlinTestKit.get()) { - KotlinTestKits.KoTest -> { - logger.warn("configuring KoTest for Unit testing") - - val test: JvmTestSuite by getting(JvmTestSuite::class, ts.applyKoTest) - } + val integrationTest by registering(JvmTestSuite::class) + + val functionalTest by registering(JvmTestSuite::class) + val performanceTest by registering(JvmTestSuite::class) + val test by getting(JvmTestSuite::class) + val acceptanceTest = register("acceptanceTest") + configureEach { + if (this is JvmTestSuite) { + val tt: TestTypes = TestTypes.fromNamingConvention(name) - KotlinTestKits.KotlinTest -> { - logger.warn("configuring KotlinTest for Unit testing") - val test by getting(JvmTestSuite::class) { - useKotlinTest() + +// Kotlin specific + if (project.plugins.hasPlugin("org.jetbrains.kotlin.jvm")) { + logger.error("Configuring Kotlin Testing for ${project.name}") + when (extension.useKotlinTestKit.get()) { + KotlinTestKits.KoTest -> { + logger.warn("configuring KoTest for Unit testing") + test.applyKoTest() + } + + KotlinTestKits.KotlinTest -> { + logger.warn("configuring KotlinTest for Unit testing") + + test.applyKotlinTest() } + + else -> {} } + } + + // Scala Specific + if (project.plugins.hasPlugin("scala")) { + + logger.error("Configuring ${project.name} for Scala ${tt.name} Testing : ${this.name} ") + + when (tt) { + TestTypes.Unit -> { + logger.error(("Configuring standard Unit Test for scala")) + test.applyScalaTest() + } + + TestTypes.Acceptance -> { + useJUnitJupiter() + logger.error("adding scala acceptance stuff") + } + + else -> { + logger.error("no config ATM (applying Jupiter as default") + useJUnitJupiter() + } - else -> { - val test by getting(JvmTestSuite::class) } + + } } /* - val functionalTest by registering(JvmTestSuite::class) { + val functionalTest by registering(JvmTestSuite::class) { - dependencies { - implementation(project()) - } + dependencies { + implementation(project()) } - register("integrationTest") { - dependencies { - implementation(project()) - } - - targets { - all { - testTask.configure { - shouldRunAfter(t) - } + } + register("integrationTest") { + dependencies { + implementation(project()) + } + + targets { + all { + testTask.configure { + shouldRunAfter(t) } } } + } - */ - } + */ + + } // config } } \ No newline at end of file diff --git a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt index 1dc0a005..f1e67994 100644 --- a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt +++ b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt @@ -1,6 +1,8 @@ package io.truthencode.djaxonomy.etc +import net.pearx.kasechange.toCamelCase import org.gradle.api.Project +import org.gradle.api.attributes.TestSuiteType import org.gradle.api.plugins.jvm.JvmTestSuite import org.gradle.api.provider.Property import org.gradle.kotlin.dsl.invoke @@ -25,6 +27,90 @@ interface KotlinAnnotationProcessingExtension { val kotlinTestMode: Property } +enum class Day { + MONDAY(1, "Monday"), + TUESDAY(2, "Tuesday"), + WEDNESDAY(3, "Wednesday"), + THURSDAY(4, "Thursday"), + FRIDAY(5, "Friday"), + SATURDAY(6, "Saturday"), + SUNDAY(7, "Sunday"); // end of the constants + + // custom properties with default values + var dayOfWeek: Int? = null + var printableName: String? = null + + constructor() + + // custom constructors + constructor( + dayOfWeek: Int, + printableName: String + ) { + this.dayOfWeek = dayOfWeek + this.printableName = printableName + } + + // custom method + fun customToString(): String { + return "[${dayOfWeek}] -> $printableName" + } +} + +enum class TestTypes { + Unit(TestSuiteType.UNIT_TEST), + Integration(TestSuiteType.INTEGRATION_TEST), + Functional(TestSuiteType.FUNCTIONAL_TEST), + Performance(TestSuiteType.PERFORMANCE_TEST), + Acceptance("acceptance-test"), + Custom("custom-test"); + + var id: String? = null + var defaultName: String? = null + var testSuiteType: String? = null + val knownSuiteNames = listOf( + TestSuiteType.UNIT_TEST, + TestSuiteType.FUNCTIONAL_TEST, + TestSuiteType.INTEGRATION_TEST, + TestSuiteType.PERFORMANCE_TEST + ) + + constructor() + + constructor(id: String) { + this.id = id + this.defaultName = when (id) { + TestSuiteType.UNIT_TEST -> "test" + else -> id.toCamelCase() + } + if (knownSuiteNames.contains(id)) { + this.testSuiteType = id + } + } + + companion object { + + fun fromTestSuiteType(id: String): TestTypes { + return when (id) { + TestSuiteType.UNIT_TEST -> Unit + TestSuiteType.INTEGRATION_TEST -> Integration + TestSuiteType.FUNCTIONAL_TEST -> Functional + TestSuiteType.PERFORMANCE_TEST -> Performance + "acceptance-test" -> Acceptance // Static Duck-typing ATM + else -> Custom + } + } + + + fun fromNamingConvention(key: String): TestTypes { + return TestTypes.values().find { it.defaultName == key } ?: TestTypes.Custom + } + } + +} + + + class TestBuildSupport(proj: Project) { private val koTestVersion: String by proj val applyMockito = { suite: JvmTestSuite -> diff --git a/gradle.properties b/gradle.properties index 1091fa61..735430d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -37,7 +37,7 @@ logbackVersion=1.2.3 jetBrainsAnnotationVersion=17.0.0 # scala -scalaLibraryVersion=2.13.7 +scalaLibraryVersion=2.13.10 scalaMajorVersion=2.13 scalaScraperVersion=2.2.1 @@ -126,6 +126,7 @@ verticesVersion=0.1.2 # scala # scalaVersion +scalaVersions=2.12.18,2.11.12,2.13.12 scoveragePluginVersion=8.0.3 # TODO: re-evaluate if we need versions Plugin since we've shapped to shipKit versionsPluginVersion=0.39.0 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e490cec5..7809c3e6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,133 +1,55 @@ [versions] -ch-qos-logback = "1.2.11" -com-clever-cloud-pulsar4s = "2.8.1" +ch-qos-logback = "1.4.11" com-wix = "0.7.6" -io-getquill = "3.11.0" -io-vertx = "4.2.3" -org-apache-camel = "3.13.0" -org-jacoco = "0.8.9" -org-junit-jupiter = "5.8.2" -org-scoverage = "1.4.10" -org-testcontainers = "1.16.2" -org-wvlet-airframe = "21.12.1" +io-getquill = "4.6.1" +io-monix = "3.4.1" +org-jetbrains-kotlin = "1.9.0" +org-junit-jupiter = "5.10.0" +org-scoverage = "2.0.10" [libraries] ch-qos-logback-logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "ch-qos-logback" } -ch-qos-logback-logback-core = { module = "ch.qos.logback:logback-core", version.ref = "ch-qos-logback" } -co-helmethair-scalatest-junit-runner = "co.helmethair:scalatest-junit-runner:0.1.10" -com-beachape-enumeratum_2-13 = "com.beachape:enumeratum_2.13:1.7.0" -com-clever-cloud-pulsar4s-pulsar4s-avro_2-13 = { module = "com.clever-cloud.pulsar4s:pulsar4s-avro_2.13", version.ref = "com-clever-cloud-pulsar4s" } -com-clever-cloud-pulsar4s-pulsar4s-core_2-13 = { module = "com.clever-cloud.pulsar4s:pulsar4s-core_2.13", version.ref = "com-clever-cloud-pulsar4s" } -com-clever-cloud-pulsar4s-pulsar4s-monix_2-13 = { module = "com.clever-cloud.pulsar4s:pulsar4s-monix_2.13", version.ref = "com-clever-cloud-pulsar4s" } +co-helmethair-scalatest-junit-runner = "co.helmethair:scalatest-junit-runner:0.2.0" +com-beachape-enumeratum_2-13 = "com.beachape:enumeratum_2.13:1.7.3" com-geirsson-scalafmt-core_2-13 = "com.geirsson:scalafmt-core_2.13:3.1.1" com-github-kxbmap-configs_2-13 = "com.github.kxbmap:configs_2.13:0.6.1" -com-h2database-h2 = "com.h2database:h2:1.4.200" -com-hazelcast = "com.hazelcast:hazelcast:5.0" -com-tersesystems-blindsight-blindsight-logstash_2-13 = "com.tersesystems.blindsight:blindsight-logstash_2.13:1.5.2" -com-tersesystems-logback-logback-structured-config = "com.tersesystems.logback:logback-structured-config:1.0.1" -com-typesafe-akka-akka-actor_2-13 = "com.typesafe.akka:akka-actor_2.13:2.6.16" com-typesafe-config = "com.typesafe:config:1.4.2" -com-typesafe-genjavadoc-genjavadoc-plugin_2-13-7 = "com.typesafe.genjavadoc:genjavadoc-plugin_2.13.7:0.18" -com-typesafe-scala-logging-scala-logging_2-13 = "com.typesafe.scala-logging:scala-logging_2.13:3.9.2" -com-vladsch-flexmark-flexmark-all = "com.vladsch.flexmark:flexmark-all:0.62.2" +com-typesafe-scala-logging-scala-logging_2-13 = "com.typesafe.scala-logging:scala-logging_2.13:3.9.5" com-wix-accord-core_2-13 = { module = "com.wix:accord-core_2.13", version.ref = "com-wix" } com-wix-accord-scalatest_2-13 = { module = "com.wix:accord-scalatest_2.13", version.ref = "com-wix" } -de-neuland-bfi-jade4j = "de.neuland-bfi:jade4j:1.2.7" -dev-zio-zio_2-13 = "dev.zio:zio_2.13:1.0.12" -io-gatling-highcharts-gatling-charts-highcharts = "io.gatling.highcharts:gatling-charts-highcharts:3.2.1" +de-neuland-bfi-jade4j = "de.neuland-bfi:jade4j:1.3.2" io-getquill-quill-core_2-13 = { module = "io.getquill:quill-core_2.13", version.ref = "io-getquill" } -io-getquill-quill-jdbc-monix_2-13 = { module = "io.getquill:quill-jdbc-monix_2.13", version.ref = "io-getquill" } io-getquill-quill-monix_2-13 = { module = "io.getquill:quill-monix_2.13", version.ref = "io-getquill" } io-getquill-quill-sql_2-13 = { module = "io.getquill:quill-sql_2.13", version.ref = "io-getquill" } -io-github-davidgregory084-vertices-core_2-13 = "io.github.davidgregory084:vertices-core_2.13:0.1.2" -io-lemonlabs-scala-uri_2-13 = "io.lemonlabs:scala-uri_2.13:4.0.0-M3" -io-monix-monix-bio_2-13 = "io.monix:monix-bio_2.13:1.2.0" -io-monix-monix-eval_2-13 = "io.monix:monix-eval_2.13:3.4.0" -io-monix-monix-execution_2-13 = "io.monix:monix-execution_2.13:3.4.0" -io-monix-monix-reactive_2-13 = "io.monix:monix-reactive_2.13:3.4.0" -io-swagger-core-v3-swagger-jaxrs2 = "io.swagger.core.v3:swagger-jaxrs2:2.1.11" -io-vertx-vertx-auth-shiro = { module = "io.vertx:vertx-auth-shiro", version.ref = "io-vertx" } -io-vertx-vertx-codegen = { module = "io.vertx:vertx-codegen", version.ref = "io-vertx" } -io-vertx-vertx-core = { module = "io.vertx:vertx-core", version.ref = "io-vertx" } -io-vertx-vertx-ignite = { module = "io.vertx:vertx-ignite", version.ref = "io-vertx" } -io-vertx-vertx-junit5 = { module = "io.vertx:vertx-junit5", version.ref = "io-vertx" } -io-vertx-vertx-mongo-client = { module = "io.vertx:vertx-mongo-client", version.ref = "io-vertx" } -io-vertx-vertx-web = { module = "io.vertx:vertx-web", version.ref = "io-vertx" } -io-vertx-vertx-web-client = { module = "io.vertx:vertx-web-client", version.ref = "io-vertx" } -javax-servlet-javax-servlet-api = "javax.servlet:javax.servlet-api:3.1.0" -javax-ws-rs-javax-ws-rs-api = "javax.ws.rs:javax.ws.rs-api:2.1" -net-ruippeixotog-scala-scraper_2-13 = "net.ruippeixotog:scala-scraper_2.13:2.2.1" -net-sourceforge-plantuml = "net.sourceforge.plantuml:plantuml:1.2023.10" -net-thauvin-erik-semver = "net.thauvin.erik:semver:1.2.0" -org-antlr-antlr4 = "org.antlr:antlr4:4.10.1" -org-apache-camel-camel-componentdsl = { module = "org.apache.camel:camel-componentdsl", version.ref = "org-apache-camel" } -org-apache-camel-camel-core = { module = "org.apache.camel:camel-core", version.ref = "org-apache-camel" } -org-apache-camel-camel-main = { module = "org.apache.camel:camel-main", version.ref = "org-apache-camel" } -org-apache-camel-camel-pulsar = { module = "org.apache.camel:camel-pulsar", version.ref = "org-apache-camel" } -org-apache-camel-camel-test-junit5 = { module = "org.apache.camel:camel-test-junit5", version.ref = "org-apache-camel" } -org-apache-camel-camel-testcontainers-junit5 = { module = "org.apache.camel:camel-testcontainers-junit5", version.ref = "org-apache-camel" } -org-apache-camel-camel-vertx = { module = "org.apache.camel:camel-vertx", version.ref = "org-apache-camel" } -org-apache-commons-commons-lang3 = "org.apache.commons:commons-lang3:3.7" -org-apache-httpcomponents-httpclient = "org.apache.httpcomponents:httpclient:4.5.13" -org-apache-logging-log4j-log4j-core = "org.apache.logging.log4j:log4j-core:2.17.1" -org-apache-pulsar-pulsar-client-all = "org.apache.pulsar:pulsar-client-all:2.9.1" -org-apache-shiro-shiro-core = "org.apache.shiro:shiro-core:1.8.0" -org-concordion = "org.concordion:concordion:3.1.3" +io-monix-monix-eval_2-13 = { module = "io.monix:monix-eval_2.13", version.ref = "io-monix" } +io-monix-monix-reactive_2-13 = { module = "io.monix:monix-reactive_2.13", version.ref = "io-monix" } +net-ruippeixotog-scala-scraper_2-13 = "net.ruippeixotog:scala-scraper_2.13:3.1.0" +org-apache-logging-log4j-log4j-core = "org.apache.logging.log4j:log4j-core:3.0.0-alpha1" +org-concordion = "org.concordion:concordion:4.0.1" org-concordion-concordion-collapse-output-extension = "org.concordion:concordion-collapse-output-extension:1.0.0" org-concordion-concordion-embed-extension = "org.concordion:concordion-embed-extension:1.2.0" -org-eclipse-jetty-jetty-server = "org.eclipse.jetty:jetty-server:11.0.7" -org-evosuite-evosuite-standalone-runtime = "org.evosuite:evosuite-standalone-runtime:1.0.5" -org-jacoco-org-jacoco-agent = { module = "org.jacoco:org.jacoco.agent", version.ref = "org-jacoco" } -org-jacoco-org-jacoco-ant = { module = "org.jacoco:org.jacoco.ant", version.ref = "org-jacoco" } -org-javassist = "org.javassist:javassist:3.20.0-GA" -org-jetbrains-annotations = "org.jetbrains:annotations:13.0" -org-jetbrains-kotlin-kotlin-build-tools-impl = "org.jetbrains.kotlin:kotlin-build-tools-impl:1.9.10" -org-jetbrains-kotlin-kotlin-compiler-embeddable = "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.10" -org-jetbrains-kotlin-kotlin-klib-commonizer-embeddable = "org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.9.10" -org-jetbrains-kotlin-kotlin-reflect = "org.jetbrains.kotlin:kotlin-reflect:1.9.0" -org-jetbrains-kotlin-kotlin-scripting-compiler-embeddable = "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.10" -org-jetbrains-kotlin-kotlin-stdlib = "org.jetbrains.kotlin:kotlin-stdlib:1.9.0" -org-jetbrains-kotlin-kotlin-stdlib-common = "org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0" -org-jetbrains-kotlin-kotlin-stdlib-jdk7 = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0" -org-jetbrains-kotlin-kotlin-stdlib-jdk8 = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0" -org-json4s-json4s-native_2-13 = "org.json4s:json4s-native_2.13:4.0.3" -org-junit-junit-bom = "org.junit:junit-bom:5.8.2" +org-jetbrains-annotations = "org.jetbrains:annotations:24.0.1" +org-jetbrains-kotlin-kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "org-jetbrains-kotlin" } +org-jetbrains-kotlin-kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "org-jetbrains-kotlin" } +org-jetbrains-kotlin-kotlin-stdlib-common = { module = "org.jetbrains.kotlin:kotlin-stdlib-common", version.ref = "org-jetbrains-kotlin" } +org-jetbrains-kotlin-kotlin-stdlib-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "org-jetbrains-kotlin" } +org-jetbrains-kotlin-kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "org-jetbrains-kotlin" } +org-json4s-json4s-native_2-13 = "org.json4s:json4s-native_2.13:4.1.0-M3" org-junit-jupiter-junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "org-junit-jupiter" } -org-junit-jupiter-junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "org-junit-jupiter" } -org-junit-jupiter-junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "org-junit-jupiter" } -org-junit-platform-junit-platform-engine = "org.junit.platform:junit-platform-engine:1.8.1" -org-junit-platform-junit-platform-launcher = "org.junit.platform:junit-platform-launcher:1.8.1" -org-junit-platform-junit-platform-runner = "org.junit.platform:junit-platform-runner:1.8.2" -org-junit-vintage-junit-vintage-engine = "org.junit.vintage:junit-vintage-engine:5.8.2" -org-mockito-mockito-core = "org.mockito:mockito-core:3.4.6" -org-mockito-mockito-scala-scalatest_2-13 = "org.mockito:mockito-scala-scalatest_2.13:1.16.49" -org-scala-lang-scala-compiler = "org.scala-lang:scala-compiler:2.13.7" -org-scala-lang-scala-library = "org.scala-lang:scala-library:2.12.8" -org-scala-lang-scala-reflect = "org.scala-lang:scala-reflect:2.13.7" -org-scala-stm-scala-stm_2-13 = "org.scala-stm:scala-stm_2.13:0.11.1" -org-scalacheck-scalacheck_2-13 = "org.scalacheck:scalacheck_2.13:1.15.4" -org-scalatest-scalatest_2-13 = "org.scalatest:scalatest_2.13:3.3.0-SNAP3" +org-junit-platform-junit-platform-engine = "org.junit.platform:junit-platform-engine:1.10.0" +org-junit-platform-junit-platform-launcher = "org.junit.platform:junit-platform-launcher:1.10.0" +org-junit-platform-junit-platform-runner = "org.junit.platform:junit-platform-runner:5.8.2" +org-junit-vintage-junit-vintage-engine = "org.junit.vintage:junit-vintage-engine:5.10.0" +org-mockito-mockito-core = "org.mockito:mockito-core:5.5.0" +org-scalacheck-scalacheck_2-13 = "org.scalacheck:scalacheck_2.13:1.17.0" +org-scalatest-scalatest_2-13 = "org.scalatest:scalatest_2.13:3.3.0-SNAP4" org-scalatestplus-mockito-3-4_2-13 = "org.scalatestplus:mockito-3-4_2.13:3.3.0.0-SNAP3" -org-scalatra-scalate-scalate-core_2-13 = "org.scalatra.scalate:scalate-core_2.13:1.9.7" -org-scoverage-scalac-scoverage-plugin_2-13-7 = { module = "org.scoverage:scalac-scoverage-plugin_2.13.7", version.ref = "org-scoverage" } org-scoverage-scalac-scoverage-runtime_2-13 = { module = "org.scoverage:scalac-scoverage-runtime_2.13", version.ref = "org-scoverage" } -org-slf4j-jul-to-slf4j = "org.slf4j:jul-to-slf4j:1.8.0-beta4" -org-slf4j-slf4j-api = "org.slf4j:slf4j-api:1.7.36" -org-testcontainers-junit-jupiter = { module = "org.testcontainers:junit-jupiter", version.ref = "org-testcontainers" } -org-testcontainers-mongodb = { module = "org.testcontainers:mongodb", version.ref = "org-testcontainers" } -org-testcontainers-pulsar = { module = "org.testcontainers:pulsar", version.ref = "org-testcontainers" } -org-wvlet-airframe-airframe-config_2-13 = { module = "org.wvlet.airframe:airframe-config_2.13", version.ref = "org-wvlet-airframe" } -org-wvlet-airframe-airframe-http-finagle_2-13 = { module = "org.wvlet.airframe:airframe-http-finagle_2.13", version.ref = "org-wvlet-airframe" } -org-wvlet-airframe-airframe_2-13 = { module = "org.wvlet.airframe:airframe_2.13", version.ref = "org-wvlet-airframe" } [plugins] -com-dorongold-task-tree = "com.dorongold.task-tree:2.1.0" +com-dorongold-task-tree = "com.dorongold.task-tree:2.1.1" com-github-ManifestClasspath = "com.github.ManifestClasspath:0.1.0-RELEASE" -com-github-ben-manes-versions = "com.github.ben-manes.versions:0.41.0" -com-github-lkishalmi-gatling = "com.github.lkishalmi.gatling:3.2.9" +com-github-ben-manes-versions = "com.github.ben-manes.versions:0.48.0" com-zlad-gradle-avrohugger = "com.zlad.gradle.avrohugger:0.7.0" -net-thauvin-erik-gradle-semver = "net.thauvin.erik.gradle.semver:1.0.4" nl-littlerobots-version-catalog-update = "nl.littlerobots.version-catalog-update:0.8.1" -org-jetbrains-kotlin-jvm = "org.jetbrains.kotlin.jvm:1.9.10" -org-kordamp-gradle-project = "org.kordamp.gradle.project:0.51.0" -org-openapi-generator = "org.openapi.generator:4.2.2" +org-openapi-generator = "org.openapi.generator:7.0.0" diff --git a/subprojects/common/ddo-core/build.gradle.kts b/subprojects/common/ddo-core/build.gradle.kts index 331bfbbf..a5723db6 100644 --- a/subprojects/common/ddo-core/build.gradle.kts +++ b/subprojects/common/ddo-core/build.gradle.kts @@ -20,31 +20,10 @@ plugins { id("scala-library-profile") // id("ru.vyarus.mkdocs") // version "3.0.0" -// id("acceptance-test-conventions") + id("djaxonomy.test-conventions") // id("doc-uml") } -testing { - suites { - val test by getting(JvmTestSuite::class) { - useJUnitJupiter() - } - - register("integrationTest") { - dependencies { - implementation(project()) - } - - targets { - all { - testTask.configure { - shouldRunAfter(test) - } - } - } - } - } -} tasks.named("check") { dependsOn(testing.suites.named("integrationTest")) diff --git a/subprojects/common/ddo-etl/build.gradle.kts b/subprojects/common/ddo-etl/build.gradle.kts index 8239a49c..e97192dc 100644 --- a/subprojects/common/ddo-etl/build.gradle.kts +++ b/subprojects/common/ddo-etl/build.gradle.kts @@ -26,6 +26,7 @@ plugins { id("scala-conventions") // id("acceptance-test-conventions") + id("djaxonomy.test-conventions") } description = "Common ETL module for storing / loading data from web / user etc" @@ -65,25 +66,14 @@ dependencies { implementation(group = "com.wix", name = "accord-core_$scalaMajorVersion") implementation(group = "ch.qos.logback", name = "logback-classic") implementation(group = "com.typesafe.scala-logging", name = "scala-logging_$scalaMajorVersion") - testImplementation(group = "org.scalatest", name = "scalatest_$scalaMajorVersion") - testImplementation(group = "org.scalacheck", name = "scalacheck_$scalaMajorVersion", version = "1.14.0") - testImplementation(group = "org.mockito", name = "mockito-core") - - // JUnit 5 - testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-engine") - testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") - testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") - testRuntimeOnly(group = "org.junit.vintage", name = "junit-vintage-engine") +// testImplementation(group = "org.scalatest", name = "scalatest_$scalaMajorVersion") +// testImplementation(group = "org.scalacheck", name = "scalacheck_$scalaMajorVersion", version = "1.14.0") +// testImplementation(group = "org.mockito", name = "mockito-core") +// +// // JUnit 5 +// testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-engine") +// testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") +// testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") +// testRuntimeOnly(group = "org.junit.vintage", name = "junit-vintage-engine") } -tasks { - // Use the built-in JUnit support of Gradle. - "test"(Test::class) { - useJUnitPlatform { - includeEngines = setOf("scalatest", "vintage") - testLogging { - events("passed", "skipped", "failed") - } - } - } -} diff --git a/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala b/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala index ade77c88..a3de5c35 100644 --- a/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala +++ b/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala @@ -27,5 +27,6 @@ class LibrarySuite extends AnyFunSuite { test("someLibraryMethod is always true") { def library: Library = new Library() assert(library.someLibraryMethod()) + assert(false) } } diff --git a/subprojects/common/ddo-modeling/build.gradle.kts b/subprojects/common/ddo-modeling/build.gradle.kts index 39083de5..37cd4c2d 100644 --- a/subprojects/common/ddo-modeling/build.gradle.kts +++ b/subprojects/common/ddo-modeling/build.gradle.kts @@ -18,9 +18,12 @@ plugins { id("scala-library-profile") + id("djaxonomy.test-conventions") id("com.zlad.gradle.avrohugger") - id("com.github.lkishalmi.gatling") version "3.2.9" +// id("com.github.lkishalmi.gatling") version "3.2.9" + // id("io.gatling.gradle") version "3.9.5.5" replaces above id("org.openapi.generator") + } dependencies { @@ -45,13 +48,13 @@ dependencies { implementation(group = "com.wix", name = "accord-core_$scalaMajorVersion") implementation(group = "ch.qos.logback", name = "logback-classic") implementation(group = "com.typesafe.scala-logging", name = "scala-logging_$scalaMajorVersion") - testImplementation(group = "org.scalatest", name = "scalatest_$scalaMajorVersion") - testImplementation(group = "org.mockito", name = "mockito-core") - - // JUnit 5 - testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-engine") - testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") - testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") +// testImplementation(group = "org.scalatest", name = "scalatest_$scalaMajorVersion") +// testImplementation(group = "org.mockito", name = "mockito-core") +// +// // JUnit 5 +// testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-engine") +// testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") +// testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") } // OpenApi code / schema generation @@ -228,5 +231,4 @@ tasks { // withType { // mustRunAfter(gas) // } -} - +} \ No newline at end of file From 03b35f4ac2aeea80f121f1c3a13198957f7e944a Mon Sep 17 00:00:00 2001 From: Andre White Date: Fri, 8 Sep 2023 14:37:45 -0600 Subject: [PATCH 07/19] :construction: :wrench: JvmTestSuite Configured basic Scala / JUnit JvmSuite, Adding Acceptance concordion testing TODO: Kotlin, Integration, Functional --- .../djaxonomy.test-conventions.gradle.kts | 19 ++++++++++++ .../kotlin/io/truthencode/TestExtensions.kt | 31 +------------------ subprojects/common/ddo-core/build.gradle.kts | 20 ++++++------ .../io/truthencode/ddo/DamageDiceTest.scala | 2 +- .../io/truthencode/ddo/etl/LibrarySuite.scala | 3 +- 5 files changed, 32 insertions(+), 43 deletions(-) diff --git a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts index 061957fe..046e362b 100644 --- a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts @@ -53,10 +53,29 @@ fun JvmTestSuite.applyKotlinTest() { val junitScalaTestVersion: String by project val junitPlatformVersion: String by project +val scalaTestPlusMockitoVersion: String by project +val scalaCheckVersion: String by project +val scalaTestVersion: String by project +val accordVersion: String by project +val scalaMajorVersion: String by project + +val mockitoVersion: String by project + fun JvmTestSuite.applyScalaTest() { dependencies { runtimeOnly("co.helmethair:scalatest-junit-runner:$junitScalaTestVersion") runtimeOnly("org.junit.vintage:junit-vintage-engine:$junitPlatformVersion") + implementation("org.scalatest:scalatest_$scalaMajorVersion:$scalaTestVersion") + implementation("org.scalacheck:scalacheck_$scalaMajorVersion:$scalaCheckVersion") + implementation("org.scalatestplus:mockito-3-4_$scalaMajorVersion:$scalaTestPlusMockitoVersion") + implementation("org.mockito:mockito-core:$mockitoVersion") + implementation("com.wix:accord-core_${scalaMajorVersion}:${accordVersion}") + implementation("com.wix:accord-scalatest_${scalaMajorVersion}:$accordVersion") + // JUnit + + + + } targets.all { diff --git a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt index f1e67994..0230694f 100644 --- a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt +++ b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt @@ -27,35 +27,6 @@ interface KotlinAnnotationProcessingExtension { val kotlinTestMode: Property } -enum class Day { - MONDAY(1, "Monday"), - TUESDAY(2, "Tuesday"), - WEDNESDAY(3, "Wednesday"), - THURSDAY(4, "Thursday"), - FRIDAY(5, "Friday"), - SATURDAY(6, "Saturday"), - SUNDAY(7, "Sunday"); // end of the constants - - // custom properties with default values - var dayOfWeek: Int? = null - var printableName: String? = null - - constructor() - - // custom constructors - constructor( - dayOfWeek: Int, - printableName: String - ) { - this.dayOfWeek = dayOfWeek - this.printableName = printableName - } - - // custom method - fun customToString(): String { - return "[${dayOfWeek}] -> $printableName" - } -} enum class TestTypes { Unit(TestSuiteType.UNIT_TEST), @@ -103,7 +74,7 @@ enum class TestTypes { fun fromNamingConvention(key: String): TestTypes { - return TestTypes.values().find { it.defaultName == key } ?: TestTypes.Custom + return TestTypes.values().find { it.defaultName == key } ?: Custom } } diff --git a/subprojects/common/ddo-core/build.gradle.kts b/subprojects/common/ddo-core/build.gradle.kts index a5723db6..c445e30c 100644 --- a/subprojects/common/ddo-core/build.gradle.kts +++ b/subprojects/common/ddo-core/build.gradle.kts @@ -58,16 +58,16 @@ dependencies { implementation(group = "ch.qos.logback", name = "logback-classic") implementation(group = "com.typesafe.scala-logging", name = "scala-logging_$scalaMajorVersion") testImplementation(project(":ddo-testing-util")) - testImplementation(group = "org.scalatest", name = "scalatest_$scalaMajorVersion") - testImplementation(group = "org.scalacheck", name = "scalacheck_$scalaMajorVersion") - testImplementation(group = "org.scalatestplus", "mockito-3-4_$scalaMajorVersion") - testImplementation(group = "com.wix", name = "accord-scalatest_$scalaMajorVersion") - - // JUnit 5 - testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-engine") - testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") - testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") - testRuntimeOnly(group = "org.junit.vintage", name = "junit-vintage-engine") + // testImplementation(group = "org.scalatest", name = "scalatest_$scalaMajorVersion") + // testImplementation(group = "org.scalacheck", name = "scalacheck_$scalaMajorVersion") + // testImplementation(group = "org.scalatestplus", "mockito-3-4_$scalaMajorVersion") + // testImplementation(group = "com.wix", name = "accord-scalatest_$scalaMajorVersion") + + // // JUnit 5 + // testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-engine") + // testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") + // testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") + // testRuntimeOnly(group = "org.junit.vintage", name = "junit-vintage-engine") // Concordion BDD // val acceptanceTestImplementation by configurations.getting diff --git a/subprojects/common/ddo-core/src/test/scala/io/truthencode/ddo/DamageDiceTest.scala b/subprojects/common/ddo-core/src/test/scala/io/truthencode/ddo/DamageDiceTest.scala index ba61be33..3bfd6c66 100644 --- a/subprojects/common/ddo-core/src/test/scala/io/truthencode/ddo/DamageDiceTest.scala +++ b/subprojects/common/ddo-core/src/test/scala/io/truthencode/ddo/DamageDiceTest.scala @@ -77,7 +77,7 @@ class DamageDiceTest for { x <- diceSet.cross(tpl) } yield s"${x._1} ${x._2}" } describe("DnD Dice") { - they("should support 3[2D4 + 3] flags syntax") { + they("should support W[nDn + n] flags syntax") { randomDiceSets.foreach { d => noException shouldBe thrownBy(DamageInfo.apply(d)) } diff --git a/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala b/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala index a3de5c35..adf86084 100644 --- a/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala +++ b/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala @@ -26,7 +26,6 @@ import org.scalatest.funsuite.AnyFunSuite class LibrarySuite extends AnyFunSuite { test("someLibraryMethod is always true") { def library: Library = new Library() - assert(library.someLibraryMethod()) - assert(false) + assert(library.someLibraryMethod()) } } From 7d1db27a6cad833f8f72719a5ad726deb39573ce Mon Sep 17 00:00:00 2001 From: Andre White Date: Fri, 8 Sep 2023 14:38:31 -0600 Subject: [PATCH 08/19] trunk fmt --- build-logic/build.gradle.kts | 5 +---- .../djaxonomy.test-conventions.gradle.kts | 22 +++---------------- .../kotlin/io/truthencode/TestExtensions.kt | 10 +++------ subprojects/common/ddo-core/build.gradle.kts | 7 +++--- subprojects/common/ddo-etl/build.gradle.kts | 3 +-- .../common/ddo-modeling/build.gradle.kts | 1 - 6 files changed, 11 insertions(+), 37 deletions(-) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 6f953ea2..cdf0ce3b 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -46,11 +46,9 @@ dependencies { // doc generation (requires python) // implementation("com.palantir.baseline:gradle-baseline-java:$palantirPluginVersion") - // CI build support implementation("be.vbgn.gradle:ci-detect-plugin:0.5.0") - // implementation("org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:4.0.0") // scala implementation("org.scoverage:gradle-scoverage:8.0.3") @@ -98,7 +96,6 @@ dependencies { // // implementation("app.cash.sqldelight:runtime-jvm:2.0.0-alpha05") // implementation("ru.vyarus:gradle-mkdocs-plugin:3.0.0") - } kotlin { @@ -107,4 +104,4 @@ kotlin { // GraalvmToolchain support doesn't work for CI systems. Circle CI requires custom image since deprecating cicrleci/graal in favor of cimg/openjdk // (this as JavaToolchainSpec).vendor.set(JvmVendorSpec.GRAAL_VM) } -} +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts index 046e362b..b8f85975 100644 --- a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts @@ -32,22 +32,15 @@ extension.useKotlinTestKit.convention( fun JvmTestSuite.applyKoTest() { val koTestVersion: String = (findProperty("koTestVersion") ?: embeddedKotlinVersion).toString() - dependencies { implementation("io.kotest:kotest-runner-junit5:$koTestVersion") implementation("io.kotest:kotest-assertions-core:$koTestVersion") implementation("io.kotest:kotest-property:$koTestVersion") } - - } fun JvmTestSuite.applyKotlinTest() { - - useKotlinTest() - - } val junitScalaTestVersion: String by project @@ -69,13 +62,9 @@ fun JvmTestSuite.applyScalaTest() { implementation("org.scalacheck:scalacheck_$scalaMajorVersion:$scalaCheckVersion") implementation("org.scalatestplus:mockito-3-4_$scalaMajorVersion:$scalaTestPlusMockitoVersion") implementation("org.mockito:mockito-core:$mockitoVersion") - implementation("com.wix:accord-core_${scalaMajorVersion}:${accordVersion}") - implementation("com.wix:accord-scalatest_${scalaMajorVersion}:$accordVersion") + implementation("com.wix:accord-core_$scalaMajorVersion:$accordVersion") + implementation("com.wix:accord-scalatest_$scalaMajorVersion:$accordVersion") // JUnit - - - - } targets.all { @@ -102,7 +91,6 @@ project.testing { if (this is JvmTestSuite) { val tt: TestTypes = TestTypes.fromNamingConvention(name) - // Kotlin specific if (project.plugins.hasPlugin("org.jetbrains.kotlin.jvm")) { logger.error("Configuring Kotlin Testing for ${project.name}") @@ -142,10 +130,7 @@ project.testing { logger.error("no config ATM (applying Jupiter as default") useJUnitJupiter() } - } - - } } /* @@ -169,8 +154,7 @@ project.testing { } } - */ - + */ } // config } } \ No newline at end of file diff --git a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt index 0230694f..17ffc450 100644 --- a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt +++ b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt @@ -27,14 +27,14 @@ interface KotlinAnnotationProcessingExtension { val kotlinTestMode: Property } - enum class TestTypes { Unit(TestSuiteType.UNIT_TEST), Integration(TestSuiteType.INTEGRATION_TEST), Functional(TestSuiteType.FUNCTIONAL_TEST), Performance(TestSuiteType.PERFORMANCE_TEST), Acceptance("acceptance-test"), - Custom("custom-test"); + Custom("custom-test"), + ; var id: String? = null var defaultName: String? = null @@ -43,7 +43,7 @@ enum class TestTypes { TestSuiteType.UNIT_TEST, TestSuiteType.FUNCTIONAL_TEST, TestSuiteType.INTEGRATION_TEST, - TestSuiteType.PERFORMANCE_TEST + TestSuiteType.PERFORMANCE_TEST, ) constructor() @@ -72,16 +72,12 @@ enum class TestTypes { } } - fun fromNamingConvention(key: String): TestTypes { return TestTypes.values().find { it.defaultName == key } ?: Custom } } - } - - class TestBuildSupport(proj: Project) { private val koTestVersion: String by proj val applyMockito = { suite: JvmTestSuite -> diff --git a/subprojects/common/ddo-core/build.gradle.kts b/subprojects/common/ddo-core/build.gradle.kts index c445e30c..4fb8c140 100644 --- a/subprojects/common/ddo-core/build.gradle.kts +++ b/subprojects/common/ddo-core/build.gradle.kts @@ -16,7 +16,7 @@ * limitations under the License. */ - // ddo-core +// ddo-core plugins { id("scala-library-profile") // id("ru.vyarus.mkdocs") // version "3.0.0" @@ -24,7 +24,6 @@ plugins { // id("doc-uml") } - tasks.named("check") { dependsOn(testing.suites.named("integrationTest")) } @@ -98,7 +97,7 @@ dependencies { } } -//sourceSets { +// sourceSets { // this.getByName("acceptanceTest") { // java { // setSrcDirs(listOf()) @@ -107,4 +106,4 @@ dependencies { // setSrcDirs(listOf("test/scala")) // } // } -//} \ No newline at end of file +// } \ No newline at end of file diff --git a/subprojects/common/ddo-etl/build.gradle.kts b/subprojects/common/ddo-etl/build.gradle.kts index e97192dc..bb887eaa 100644 --- a/subprojects/common/ddo-etl/build.gradle.kts +++ b/subprojects/common/ddo-etl/build.gradle.kts @@ -75,5 +75,4 @@ dependencies { // testRuntimeOnly(group = "org.junit.platform", name = "junit-platform-launcher") // testRuntimeOnly(group = "co.helmethair", name = "scalatest-junit-runner") // testRuntimeOnly(group = "org.junit.vintage", name = "junit-vintage-engine") -} - +} \ No newline at end of file diff --git a/subprojects/common/ddo-modeling/build.gradle.kts b/subprojects/common/ddo-modeling/build.gradle.kts index 37cd4c2d..49adf911 100644 --- a/subprojects/common/ddo-modeling/build.gradle.kts +++ b/subprojects/common/ddo-modeling/build.gradle.kts @@ -23,7 +23,6 @@ plugins { // id("com.github.lkishalmi.gatling") version "3.2.9" // id("io.gatling.gradle") version "3.9.5.5" replaces above id("org.openapi.generator") - } dependencies { From 87c973bebf051bcd0c30c25705eb0e4f531e0dc0 Mon Sep 17 00:00:00 2001 From: Andre White Date: Fri, 8 Sep 2023 14:39:44 -0600 Subject: [PATCH 09/19] gitlog ignore mem dumps archive html --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 12957a46..44fd0498 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml # hs_err_pid* *.hprof +hs*.log + +docsold/ #Maven exclusions target/ From f497f23ac065a3d42bd0ef59f04e04527efcce37 Mon Sep 17 00:00:00 2001 From: Andre White Date: Fri, 8 Sep 2023 16:08:29 -0600 Subject: [PATCH 10/19] trunk fmt and clean run check --- .scalafmt.conf | 4 +- .trunk/trunk.yaml | 14 +- build-logic/build.gradle.kts | 2 +- ...axonomy.kotlin-test-conventions.gradle.kts | 47 +++--- .../kotlin/io/truthencode/TestExtensions.kt | 32 ++-- .../main/kotlin/node-conventions.gradle.kts | 150 +++++++++--------- build.gradle.kts | 82 ++++++---- gradle/codacy_upload.sh | 2 +- subprojects/common/ddo-core/build.gradle.kts | 2 +- .../io/truthencode/ddo/etl/LibrarySuite.scala | 5 +- .../common/ddo-modeling/build.gradle.kts | 9 +- .../common/ddo-test-results/build.gradle.kts | 5 +- 12 files changed, 199 insertions(+), 155 deletions(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index 15dba801..3297e4b2 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = "3.1.1" +version = "3.7.14" preset = Intellij maxColumn = 100 @@ -58,7 +58,7 @@ optIn { breaksInsideChains = false breakChainOnFirstMethodDot = true configStyleArguments = true - blankLineBeforeDocstring = true + forceBlankLineBeforeDocstring = true } runner.dialect = Scala213Source3 diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 9b9da57b..e2bed55d 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -5,28 +5,32 @@ cli: plugins: sources: - id: trunk - ref: v1.2.1 + ref: v1.2.3 uri: https://github.com/trunk-io/plugins lint: enabled: + - checkov@2.4.9 + - osv-scanner@1.3.6 + - trivy@0.45.0 + - trufflehog@3.54.3 - taplo@0.8.1 - actionlint@1.6.25 - dotenv-linter@3.3.0 - git-diff-check - gitleaks@8.18.0 - - ktlint@0.50.0 + - ktlint@1.0.0 - markdownlint@0.36.0 - oxipng@8.0.0 - prettier@3.0.3 - - renovate@36.83.0 + - renovate@36.88.0 - scalafmt@3.7.14 - shellcheck@0.9.0 - shfmt@3.6.0 - yamllint@1.32.0 runtimes: enabled: - - go@1.19.5 - - java@11.0.13 + - go@1.21.0 + - java@13.0.11 - node@18.12.1 - python@3.10.8 actions: diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index cdf0ce3b..16442a1a 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -81,7 +81,7 @@ dependencies { // universal dependency for Gradle 5.3 and above // in case of multiplatform project, just specify the dependency for commonMain/commonTest source set implementation("net.pearx.kasechange:kasechange:$kasechangeVersion") - /* to here */ + // to here // implementation("com.diffplug.spotless-changelog:spotless-changelog-plugin-gradle:2.4.0") // implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinPluginVersion") // implementation("com.palantir.baseline:com.palantir.gradle-baseline-config:$palantirPluginVersion") diff --git a/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts index c25f7510..ef089237 100644 --- a/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.kotlin-test-conventions.gradle.kts @@ -33,9 +33,10 @@ val kte = project.extensions.create("KotlinTestKitExtens kte.useKotlinTestKit.convention(KotlinTestKits.KoTest) afterEvaluate { - val testMode = findProperty("kotlinTestMode")?.toString() - ?.let(io.truthencode.djaxonomy.etc.TestMode::valueOf) - ?: io.truthencode.djaxonomy.etc.TestMode.REFLECT + val testMode = + findProperty("kotlinTestMode")?.toString() + ?.let(io.truthencode.djaxonomy.etc.TestMode::valueOf) + ?: io.truthencode.djaxonomy.etc.TestMode.REFLECT logger.warn("${project.name} kotlinTestMode: $testMode (dependencies)") when (testMode) { io.truthencode.djaxonomy.etc.TestMode.REFLECT -> { @@ -94,9 +95,10 @@ afterEvaluate { // extensions appear as properties on the target object by the given name afterEvaluate { - val testMode = findProperty("kotlinTestSuite")?.toString() - ?.let(KotlinTestKits::valueOf) - ?: KotlinTestKits.KoTest + val testMode = + findProperty("kotlinTestSuite")?.toString() + ?.let(KotlinTestKits::valueOf) + ?: KotlinTestKits.KoTest logger.warn("${project.name} kotlinTestMode: $testMode (JvmTestSuite)") testing { @@ -104,26 +106,27 @@ afterEvaluate { suites { - val test = when (testMode) { - KotlinTestKits.KoTest -> { - logger.warn("configuring KoTest for Unit testing (from kts)") - val test: JvmTestSuite by getting(JvmTestSuite::class, ts.applyKoTest) - test - } + val test = + when (testMode) { + KotlinTestKits.KoTest -> { + logger.warn("configuring KoTest for Unit testing (from kts)") + val test: JvmTestSuite by getting(JvmTestSuite::class, ts.applyKoTest) + test + } - KotlinTestKits.KotlinTest -> { - logger.warn("configuring KotlinTest for Unit testing (from kts)") - val test by getting(JvmTestSuite::class) { - useKotlinTest() + KotlinTestKits.KotlinTest -> { + logger.warn("configuring KotlinTest for Unit testing (from kts)") + val test by getting(JvmTestSuite::class) { + useKotlinTest() + } + test } - test - } - else -> { - val test by getting(JvmTestSuite::class) - test + else -> { + val test by getting(JvmTestSuite::class) + test + } } - } // val functionalTest by registering(JvmTestSuite::class) { // dependencies { diff --git a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt index 17ffc450..a78be6c0 100644 --- a/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt +++ b/build-logic/src/main/kotlin/io/truthencode/TestExtensions.kt @@ -9,11 +9,15 @@ import org.gradle.kotlin.dsl.invoke import org.gradle.kotlin.dsl.provideDelegate enum class KotlinTestKits { - KoTest, KotlinTest, None + KoTest, + KotlinTest, + None, } enum class TestMode { - REFLECT, KAPT, KSP + REFLECT, + KAPT, + KSP, } interface KotlinTestKitExtension { @@ -23,7 +27,6 @@ interface KotlinTestKitExtension { class KotlinTestKitClassExtension(val useKotlinTestKit: Property) interface KotlinAnnotationProcessingExtension { - val kotlinTestMode: Property } @@ -39,28 +42,29 @@ enum class TestTypes { var id: String? = null var defaultName: String? = null var testSuiteType: String? = null - val knownSuiteNames = listOf( - TestSuiteType.UNIT_TEST, - TestSuiteType.FUNCTIONAL_TEST, - TestSuiteType.INTEGRATION_TEST, - TestSuiteType.PERFORMANCE_TEST, - ) + val knownSuiteNames = + listOf( + TestSuiteType.UNIT_TEST, + TestSuiteType.FUNCTIONAL_TEST, + TestSuiteType.INTEGRATION_TEST, + TestSuiteType.PERFORMANCE_TEST, + ) constructor() constructor(id: String) { this.id = id - this.defaultName = when (id) { - TestSuiteType.UNIT_TEST -> "test" - else -> id.toCamelCase() - } + this.defaultName = + when (id) { + TestSuiteType.UNIT_TEST -> "test" + else -> id.toCamelCase() + } if (knownSuiteNames.contains(id)) { this.testSuiteType = id } } companion object { - fun fromTestSuiteType(id: String): TestTypes { return when (id) { TestSuiteType.UNIT_TEST -> Unit diff --git a/build-logic/src/main/kotlin/node-conventions.gradle.kts b/build-logic/src/main/kotlin/node-conventions.gradle.kts index a219e638..53bb3292 100644 --- a/build-logic/src/main/kotlin/node-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/node-conventions.gradle.kts @@ -41,62 +41,65 @@ tasks.yarn { } } -val testTaskUsingNpx = tasks.register("testNpx") { - dependsOn(tasks.npmInstall) - command.set("mocha") - args.set(listOf("test", "--grep", "should say hello")) - ignoreExitValue.set(false) - environment.set(mapOf("MY_CUSTOM_VARIABLE" to "hello")) - workingDir.set(projectDir) - execOverrides { - standardOutput = System.out +val testTaskUsingNpx = + tasks.register("testNpx") { + dependsOn(tasks.npmInstall) + command.set("mocha") + args.set(listOf("test", "--grep", "should say hello")) + ignoreExitValue.set(false) + environment.set(mapOf("MY_CUSTOM_VARIABLE" to "hello")) + workingDir.set(projectDir) + execOverrides { + standardOutput = System.out + } + inputs.dir("node_modules") + inputs.file("package.json") + inputs.dir("src") + inputs.dir("test") + outputs.upToDateWhen { + true + } } - inputs.dir("node_modules") - inputs.file("package.json") - inputs.dir("src") - inputs.dir("test") - outputs.upToDateWhen { - true - } -} -val testTaskUsingNpm = tasks.register("testNpm") { - dependsOn(tasks.npmInstall) - npmCommand.set(listOf("run", "test")) - args.set(listOf("test")) - ignoreExitValue.set(false) - environment.set(mapOf("MY_CUSTOM_VARIABLE" to "hello")) - workingDir.set(projectDir) - execOverrides { - standardOutput = System.out +val testTaskUsingNpm = + tasks.register("testNpm") { + dependsOn(tasks.npmInstall) + npmCommand.set(listOf("run", "test")) + args.set(listOf("test")) + ignoreExitValue.set(false) + environment.set(mapOf("MY_CUSTOM_VARIABLE" to "hello")) + workingDir.set(projectDir) + execOverrides { + standardOutput = System.out + } + inputs.dir("node_modules") + inputs.file("package.json") + inputs.dir("src") + inputs.dir("test") + outputs.upToDateWhen { + true + } } - inputs.dir("node_modules") - inputs.file("package.json") - inputs.dir("src") - inputs.dir("test") - outputs.upToDateWhen { - true - } -} -val testTaskUsingYarn = tasks.register("testYarn") { - dependsOn(tasks.npmInstall) - yarnCommand.set(listOf("run", "test")) - args.set(listOf("test")) - ignoreExitValue.set(false) - environment.set(mapOf("MY_CUSTOM_VARIABLE" to "hello")) - workingDir.set(projectDir) - execOverrides { - standardOutput = System.out +val testTaskUsingYarn = + tasks.register("testYarn") { + dependsOn(tasks.npmInstall) + yarnCommand.set(listOf("run", "test")) + args.set(listOf("test")) + ignoreExitValue.set(false) + environment.set(mapOf("MY_CUSTOM_VARIABLE" to "hello")) + workingDir.set(projectDir) + execOverrides { + standardOutput = System.out + } + inputs.dir("node_modules") + inputs.file("package.json") + inputs.dir("src") + inputs.dir("test") + outputs.upToDateWhen { + true + } } - inputs.dir("node_modules") - inputs.file("package.json") - inputs.dir("src") - inputs.dir("test") - outputs.upToDateWhen { - true - } -} tasks.register("run") { dependsOn(testTaskUsingNpx, testTaskUsingNpm, testTaskUsingYarn) @@ -114,29 +117,32 @@ tasks.register("run") { } } -val buildTaskUsingNpx = tasks.register("buildNpx") { - dependsOn(tasks.npmInstall) - command.set("babel") - args.set(listOf("src", "--out-dir", "${layout.buildDirectory}/npx-output")) - inputs.dir("src") - outputs.dir("${layout.buildDirectory}/npx-output") -} +val buildTaskUsingNpx = + tasks.register("buildNpx") { + dependsOn(tasks.npmInstall) + command.set("babel") + args.set(listOf("src", "--out-dir", "${layout.buildDirectory}/npx-output")) + inputs.dir("src") + outputs.dir("${layout.buildDirectory}/npx-output") + } -val buildTaskUsingNpm = tasks.register("buildNpm") { - dependsOn(tasks.npmInstall) - npmCommand.set(listOf("run", "build")) - args.set(listOf("--", "--out-dir", "${layout.buildDirectory}/npm-output")) - inputs.dir("src") - outputs.dir("${layout.buildDirectory}/npm-output") -} +val buildTaskUsingNpm = + tasks.register("buildNpm") { + dependsOn(tasks.npmInstall) + npmCommand.set(listOf("run", "build")) + args.set(listOf("--", "--out-dir", "${layout.buildDirectory}/npm-output")) + inputs.dir("src") + outputs.dir("${layout.buildDirectory}/npm-output") + } -val buildTaskUsingYarn = tasks.register("buildYarn") { - dependsOn(tasks.npmInstall) - yarnCommand.set(listOf("run", "build")) - args.set(listOf("--out-dir", "${layout.buildDirectory}/yarn-output")) - inputs.dir("src") - outputs.dir("${layout.buildDirectory}/yarn-output") -} +val buildTaskUsingYarn = + tasks.register("buildYarn") { + dependsOn(tasks.npmInstall) + yarnCommand.set(listOf("run", "build")) + args.set(listOf("--out-dir", "${layout.buildDirectory}/yarn-output")) + inputs.dir("src") + outputs.dir("${layout.buildDirectory}/yarn-output") + } tasks.register("package") { archiveFileName.set("app.zip") diff --git a/build.gradle.kts b/build.gradle.kts index c5987723..24fce21d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,6 +54,7 @@ val siteScm = "$gitHubBaseSite/$gitExtension" // Used for versioned documentation val mkDocsLatestAlias: String? by project + fun mkDocAlias(): String { return mkDocsLatestAlias ?: "Latest" } @@ -68,23 +69,25 @@ mkdocs { } } -val devRequirementsIn = listOf( - "pip-tools:7.3.0", -) - -val requirementsIn = listOf( - "mkdocs:1.5.2", - "mkdocs-material:9.2.8", // trans req: regex which may require cc (gcc et all) - "mkdocs-monorepo-plugin:1.0.5", - "mkdocs-markdownextradata-plugin:0.2.5", - "mkdocs-graphviz:1.5.3", - "mike:1.1.2", - "plantuml-markdown:3.9.2", - "mkdocs-embed-file-plugins:2.0.6", - "mkdocs-callouts:1.9.0", - "mkdocs-awesome-pages-plugin:2.9.2", - "mkdocs-include-markdown-plugin:6.0.1", -) +val devRequirementsIn = + listOf( + "pip-tools:7.3.0", + ) + +val requirementsIn = + listOf( + "mkdocs:1.5.2", + "mkdocs-material:9.2.8", // trans req: regex which may require cc (gcc et all) + "mkdocs-monorepo-plugin:1.0.5", + "mkdocs-markdownextradata-plugin:0.2.5", + "mkdocs-graphviz:1.5.3", + "mike:1.1.2", + "plantuml-markdown:3.9.2", + "mkdocs-embed-file-plugins:2.0.6", + "mkdocs-callouts:1.9.0", + "mkdocs-awesome-pages-plugin:2.9.2", + "mkdocs-include-markdown-plugin:6.0.1", + ) tasks.register("generateRequirementsIn") { val rIn = layout.projectDirectory.file("requirements.in") @@ -138,6 +141,20 @@ tasks.register("syncRequirements", PythonTask::class) { } } +/* + +Reporting tasks +// coverage +reportScoverage + + +// aggregate +aggregateScoverage +testAggregateTestReport +buildDashboard + + */ + // val releaseActive: Boolean? = rootProject.findProperty("release") as Boolean? // config { @@ -225,7 +242,10 @@ class VersionInfo { return prop } - private fun optionalProperty(key: String, defaultValue: String? = null): String? { + private fun optionalProperty( + key: String, + defaultValue: String? = null, + ): String? { return readOptionalProperty(props, key, defaultValue) } @@ -248,16 +268,22 @@ class VersionInfo { val version = "$major$separator$minor$separator$patch$prerelease$buildMeta" companion object { - fun readOptionalProperty(prop: Properties, key: String, defaultValue: String? = null): String? { - val oKey = if (prop.containsKey(key)) { - prop.getProperty(key) - } else { - null - } - val pKey = when { - oKey.isNullOrBlank() -> null - else -> prop.getProperty(key) - } + fun readOptionalProperty( + prop: Properties, + key: String, + defaultValue: String? = null, + ): String? { + val oKey = + if (prop.containsKey(key)) { + prop.getProperty(key) + } else { + null + } + val pKey = + when { + oKey.isNullOrBlank() -> null + else -> prop.getProperty(key) + } return pKey ?: defaultValue } diff --git a/gradle/codacy_upload.sh b/gradle/codacy_upload.sh index 445ffa11..ab4373ec 100755 --- a/gradle/codacy_upload.sh +++ b/gradle/codacy_upload.sh @@ -10,7 +10,7 @@ set -o errexit # rather than that of the last item in a pipeline. set -o pipefail -find . -iname "cobertura.xml" | +find . -iname "cobertura.xml" -print0 | xargs bash <(curl -Ls https://coverage.codacy.com/get.sh) report \ --partial -l Scala -r diff --git a/subprojects/common/ddo-core/build.gradle.kts b/subprojects/common/ddo-core/build.gradle.kts index 4fb8c140..12d4d726 100644 --- a/subprojects/common/ddo-core/build.gradle.kts +++ b/subprojects/common/ddo-core/build.gradle.kts @@ -40,7 +40,7 @@ dependencies { val scalaLibraryVersion: String by project val scalaMajorVersion: String by project - /* Platform dependent */ + // Platform dependent // https://mvnrepository.com/artifact/org.json4s/json4s-native implementation(group = "org.json4s", name = "json4s-native_$scalaMajorVersion") diff --git a/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala b/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala index adf86084..8029a289 100644 --- a/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala +++ b/subprojects/common/ddo-etl/src/test/scala/io/truthencode/ddo/etl/LibrarySuite.scala @@ -15,9 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * This Scala Testsuite was generated by the Gradle 'init' task. - */ package io.truthencode.ddo.etl import org.scalatest.funsuite.AnyFunSuite @@ -26,6 +23,6 @@ import org.scalatest.funsuite.AnyFunSuite class LibrarySuite extends AnyFunSuite { test("someLibraryMethod is always true") { def library: Library = new Library() - assert(library.someLibraryMethod()) + assert(library.someLibraryMethod()) } } diff --git a/subprojects/common/ddo-modeling/build.gradle.kts b/subprojects/common/ddo-modeling/build.gradle.kts index 49adf911..d710a2e5 100644 --- a/subprojects/common/ddo-modeling/build.gradle.kts +++ b/subprojects/common/ddo-modeling/build.gradle.kts @@ -145,10 +145,11 @@ val schemaList = listOf("parseHub") // Create Tasks to generate Avro Schemas for our OpenAPI specs -val genAvroSchemaTask = task("genAvroSchema") { - this.group = "OpenAPI Tools" - dependsOn("openApiValidate") -} +val genAvroSchemaTask = + task("genAvroSchema") { + this.group = "OpenAPI Tools" + dependsOn("openApiValidate") + } run { @Suppress("IDENTIFIER_LENGTH") diff --git a/subprojects/common/ddo-test-results/build.gradle.kts b/subprojects/common/ddo-test-results/build.gradle.kts index 160db89e..1b9f0e0c 100644 --- a/subprojects/common/ddo-test-results/build.gradle.kts +++ b/subprojects/common/ddo-test-results/build.gradle.kts @@ -40,7 +40,10 @@ tasks.register("moduleDependencyReport") { } // recursively print dependencies to file and move on to child projects -fun printDeps(writer: Writer, project: Project) { +fun printDeps( + writer: Writer, + project: Project, +) { if (!project.name .contains("test") ) { From 8c87884db8f9fe9a04707f11dc03335d18acdb54 Mon Sep 17 00:00:00 2001 From: Andre White Date: Sat, 9 Sep 2023 01:35:52 -0600 Subject: [PATCH 11/19] :construction: Acceptance Testing :arrow_up: concordion 3.x - > 4.0.1 :building_construction: Added extension functions to apply dependencies / engines to tests based on type / Lang (Unit/Integration, Scala/Kotlin) Still require some project specific config. --- .../djaxonomy.test-conventions.gradle.kts | 92 ++++++++++++++----- gradle.properties | 8 +- subprojects/common/ddo-core/build.gradle.kts | 17 +++- 3 files changed, 89 insertions(+), 28 deletions(-) diff --git a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts index b8f85975..aab3a2b6 100644 --- a/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/djaxonomy.test-conventions.gradle.kts @@ -46,18 +46,63 @@ fun JvmTestSuite.applyKotlinTest() { val junitScalaTestVersion: String by project val junitPlatformVersion: String by project +val scalaLibraryVersion: String by project +val enumeratumVersion: String by project +val logbackVersion: String by project + val scalaTestPlusMockitoVersion: String by project val scalaCheckVersion: String by project val scalaTestVersion: String by project val accordVersion: String by project val scalaMajorVersion: String by project +val scalaLoggingVersion: String by project val mockitoVersion: String by project +val concordionVersion: String by project +val flexmarkVersion: String by project +val typeSafeConfigVersion: String by project + +fun JvmTestSuite.applyConcordionAcceptanceTest() { + dependencies { + implementation(project()) + implementation("org.concordion:concordion:$concordionVersion") + // flexmark (mostly for concordion / markdown) + implementation("com.vladsch.flexmark:flexmark-all:$flexmarkVersion") // 0.62.2 -> 0.64.8 +// implementation("com.vladsch.flexmark:ext-gfm-strikethrough:$flexmarkVersion") +// implementation("com.vladsch.flexmark:flexmark-ext-emoji:$flexmarkVersion") +// implementation("com.vladsch.flexmark:flexmark-ext-yaml-front-matter:$flexmarkVersion") +// implementation("com.vladsch.flexmark:flexmark-ext-gfm-tasklist:$flexmarkVersion") + } +} + +fun JvmTestSuite.applyScalaDepends() { + dependencies { + implementation("org.scala-lang:scala-library:$scalaLibraryVersion") + implementation("ch.qos.logback:logback-classic:$logbackVersion") + implementation("com.typesafe.scala-logging:scala-logging_$scalaMajorVersion:$scalaLoggingVersion") + implementation("com.beachape:enumeratum_$scalaMajorVersion:$enumeratumVersion") + implementation("com.typesafe:config:$typeSafeConfigVersion") + } +} + +fun JvmTestSuite.applyVintageEngine() { + dependencies { + runtimeOnly("org.junit.vintage:junit-vintage-engine:$junitPlatformVersion") + } +} + +fun JvmTestSuite.applyJupiterEngine() { + dependencies { + runtimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitPlatformVersion") + } +} fun JvmTestSuite.applyScalaTest() { dependencies { runtimeOnly("co.helmethair:scalatest-junit-runner:$junitScalaTestVersion") - runtimeOnly("org.junit.vintage:junit-vintage-engine:$junitPlatformVersion") + + // runtimeOnly("org.junit.vintage:junit-vintage-engine:5.10.0") + implementation("org.scalatest:scalatest_$scalaMajorVersion:$scalaTestVersion") implementation("org.scalacheck:scalacheck_$scalaMajorVersion:$scalaCheckVersion") implementation("org.scalatestplus:mockito-3-4_$scalaMajorVersion:$scalaTestPlusMockitoVersion") @@ -118,12 +163,29 @@ project.testing { when (tt) { TestTypes.Unit -> { logger.error(("Configuring standard Unit Test for scala")) - test.applyScalaTest() + this.applyScalaTest() } TestTypes.Acceptance -> { useJUnitJupiter() + this.applyScalaDepends() + this.applyJupiterEngine() + this.applyVintageEngine() logger.error("adding scala acceptance stuff") + dependencies { + implementation("de.neuland-bfi:jade4j:1.2.7") + } + targets.all { + testTask.configure { + useJUnitPlatform { + // includeEngines = setOf("vintage") + // includeEngines("junit-jupiter", "junit-vintage") + testLogging { + events("passed", "skipped", "failed") + } + } + } + } } else -> { @@ -132,29 +194,15 @@ project.testing { } } } - } - /* - val functionalTest by registering(JvmTestSuite::class) { - dependencies { - implementation(project()) - } - } - register("integrationTest") { - dependencies { - implementation(project()) - } - - targets { - all { - testTask.configure { - shouldRunAfter(t) + // Concordian BDD Acceptance + if (tt == TestTypes.Acceptance) { + logger.error("applying Concordion Acceptance") + this.applyConcordionAcceptanceTest() + this.applyVintageEngine() + this.applyJupiterEngine() } } } - } - - */ - } // config } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 735430d7..670b8732 100644 --- a/gradle.properties +++ b/gradle.properties @@ -83,11 +83,12 @@ quillVersion=3.11.0 monixVersion=3.4.0 #BDD Testing -concordionVersion=3.1.3 +concordionVersion=4.0.1 concordionExtEmbedVersion=1.2.0 concordionExtCollapseOutputVersion=1.0.0 - +// flexmark markdown extensions for concordion specs +flexmarkVersion=0.64.8 # system properties # concordion @@ -103,7 +104,8 @@ junitScalaTestVersion=0.1.10 # Test Configuration / Version Management # engines (base platform / jupiter / vintage) -junitPlatformVersion=5.8.2 +junitPlatformVersion=5.10.0 +# 5.8.2 # launcher etc junitLauncherVersion=1.8.1 diff --git a/subprojects/common/ddo-core/build.gradle.kts b/subprojects/common/ddo-core/build.gradle.kts index 12d4d726..4ad96c8f 100644 --- a/subprojects/common/ddo-core/build.gradle.kts +++ b/subprojects/common/ddo-core/build.gradle.kts @@ -89,14 +89,25 @@ dependencies { // version = "0.62.2" // ) - testImplementation(group = "de.neuland-bfi", name = "jade4j", version = "1.2.7") - testImplementation(group = "net.ruippeixotog", name = "scala-scraper_$scalaMajorVersion", version = "2.2.1") - testCompileOnly(group = "org.jetbrains", name = "annotations", version = "17.0.0") + // testImplementation(group = "de.neuland-bfi", name = "jade4j", version = "1.2.7") + // testImplementation(group = "net.ruippeixotog", name = "scala-scraper_$scalaMajorVersion", version = "2.2.1") + // testCompileOnly(group = "org.jetbrains", name = "annotations", version = "17.0.0") implementation(group = "org.jetbrains", name = "annotations", version = "17.0.0") } } +testing { + suites { + withType(JvmTestSuite::class).matching { it.name in listOf("acceptanceTest") }.configureEach { + + dependencies { + implementation(project(":ddo-modeling")) + } + } + } +} + // sourceSets { // this.getByName("acceptanceTest") { // java { From 46e81b7e9927c08e6c24685513b027788ac73aa9 Mon Sep 17 00:00:00 2001 From: Andre White Date: Sat, 9 Sep 2023 01:39:36 -0600 Subject: [PATCH 12/19] Acceptance Testing :truck: Moved (copied) Concordion specs to more standard layout. May shift again. TODO: remove dups. :memo: minor documentation. --- docs/developers_guide/Tech_Concepts.md | 17 +- docs/resources/integration.md | 2 - .../ddo/model/destiny/EpicDestinies.java | 39 + .../ddo/model/feats/DodgeSpec.java | 25 + .../acceptanceTests/AcceptanceTests.md | 3 + .../resources/acceptanceTests/keepme.html | 27 + .../acceptanceTest/resources/css/ddostyle.css | 1043 +++++++++++++++++ ...px-Icon_Feat_Exotic_Weapon_Proficiency.png | Bin 0 -> 2746 bytes ...x-Icon_Feat_Martial_Weapon_Proficiency.png | Bin 0 -> 2896 bytes .../images/ApothecaryDetermination.png | Bin 0 -> 2667 bytes .../images/DragonmarkofFinding (1).png | Bin 0 -> 2727 bytes .../resources/images/DragonmarkofFinding.png | Bin 0 -> 2727 bytes .../resources/images/HalfOrcOrcBlood.png | Bin 0 -> 2044 bytes .../resources/images/Icon_Arcane_Insight.png | Bin 0 -> 3576 bytes .../resources/images/Icon_Blinding_Speed.png | Bin 0 -> 2652 bytes .../images/Icon_Burst_of_Glacial_Wrath.png | Bin 0 -> 3174 bytes .../resources/images/Icon_Class_feats (1).png | Bin 0 -> 2142 bytes .../resources/images/Icon_Class_feats.png | Bin 0 -> 2142 bytes .../images/Icon_Construct_Essence.png | Bin 0 -> 3210 bytes .../resources/images/Icon_Embolden_Spell.png | Bin 0 -> 3138 bytes .../images/Icon_Enhancement_Shadow_Phase.png | Bin 0 -> 2798 bytes .../images/Icon_Epic_Damage_Reduction.png | Bin 0 -> 2562 bytes .../images/Icon_Epic_Destiny_feats.png | Bin 0 -> 2757 bytes .../images/Icon_Epic_Eldritch_Blast.png | Bin 0 -> 2528 bytes .../resources/images/Icon_Epic_Fortitude.png | Bin 0 -> 2584 bytes .../resources/images/Icon_Epic_Life_feats.png | Bin 0 -> 2840 bytes .../resources/images/Icon_Epic_Power.png | Bin 0 -> 3327 bytes .../resources/images/Icon_Epic_Reflexes.png | Bin 0 -> 2530 bytes .../resources/images/Icon_Epic_Reputation.png | Bin 0 -> 2608 bytes .../resources/images/Icon_Epic_Will.png | Bin 0 -> 2530 bytes .../resources/images/Icon_Epic_feats.png | Bin 0 -> 2848 bytes .../images/Icon_Feat_Bladeforged.png | Bin 0 -> 2769 bytes .../images/Icon_Feat_Bulwark_Of_Defense.png | Bin 0 -> 2116 bytes .../images/Icon_Feat_Combat_Archery.png | Bin 0 -> 2490 bytes .../images/Icon_Feat_Composite_Plating.png | Bin 0 -> 2539 bytes .../resources/images/Icon_Feat_Dwarven.png | Bin 0 -> 2192 bytes .../resources/images/Icon_Feat_Elf.png | Bin 0 -> 2145 bytes .../Icon_Feat_Empower_Healing_Spell.png | Bin 0 -> 2037 bytes .../images/Icon_Feat_Empower_Spell.png | Bin 0 -> 2118 bytes .../images/Icon_Feat_Enlarge_Spell.png | Bin 0 -> 1773 bytes .../Icon_Feat_Epic_Mental_Toughness.png | Bin 0 -> 2972 bytes .../resources/images/Icon_Feat_Epic_Skill.png | Bin 0 -> 2610 bytes .../images/Icon_Feat_Epic_Spell_Focus.png | Bin 0 -> 2982 bytes .../Icon_Feat_Epic_Spell_Penetration.png | Bin 0 -> 2906 bytes .../images/Icon_Feat_Epic_Toughness.png | Bin 0 -> 2623 bytes .../images/Icon_Feat_Eschew_Materials.png | Bin 0 -> 1746 bytes .../images/Icon_Feat_Extend_Spell.png | Bin 0 -> 1247 bytes .../images/Icon_Feat_Halfling_Agility.png | Bin 0 -> 2164 bytes .../images/Icon_Feat_Heighten_Spell.png | Bin 0 -> 1706 bytes .../resources/images/Icon_Feat_Human.png | Bin 0 -> 2079 bytes .../Icon_Feat_Improved_Martial_Arts.png | Bin 0 -> 3053 bytes .../Icon_Feat_Improved_Sneak_Attack.png | Bin 0 -> 2663 bytes .../images/Icon_Feat_Inspire_Excellence.png | Bin 0 -> 2782 bytes .../images/Icon_Feat_Maximize_Spell.png | Bin 0 -> 2254 bytes .../Icon_Feat_Overwhelming_Critical.png | Bin 0 -> 2959 bytes .../images/Icon_Feat_Quicken_Spell.png | Bin 0 -> 1691 bytes .../images/Icon_Feat_Vorpal_Strikes.png | Bin 0 -> 2868 bytes .../resources/images/Icon_General_feats.png | Bin 0 -> 2324 bytes .../resources/images/Icon_Greater_Ruin.png | Bin 0 -> 3041 bytes .../images/Icon_Iconic_Past_Life_feats.png | Bin 0 -> 2887 bytes .../Icon_Improved_Augment_Summoning.png | Bin 0 -> 3238 bytes .../resources/images/Icon_Intensify_Spell.png | Bin 0 -> 3663 bytes .../resources/images/Icon_Master_of_Air.png | Bin 0 -> 3572 bytes .../images/Icon_Master_of_Alignment.png | Bin 0 -> 3669 bytes .../images/Icon_Master_of_Artifice.png | Bin 0 -> 3803 bytes .../resources/images/Icon_Master_of_Earth.png | Bin 0 -> 3369 bytes .../resources/images/Icon_Master_of_Fire.png | Bin 0 -> 3065 bytes .../images/Icon_Master_of_Knowledge.png | Bin 0 -> 3092 bytes .../resources/images/Icon_Master_of_Light.png | Bin 0 -> 3068 bytes .../resources/images/Icon_Master_of_Music.png | Bin 0 -> 3063 bytes .../resources/images/Icon_Master_of_Water.png | Bin 0 -> 3241 bytes .../images/Icon_Master_of_the_Dead.png | Bin 0 -> 3092 bytes .../images/Icon_Master_of_the_Wilds.png | Bin 0 -> 3179 bytes .../resources/images/Icon_Past_Life_feats.png | Bin 0 -> 2625 bytes .../resources/images/Icon_Racial_feats.png | Bin 0 -> 2306 bytes .../resources/images/Icon_Ruin.png | Bin 0 -> 2557 bytes .../resources/images/Icon_Watchful_Eye.png | Bin 0 -> 2618 bytes .../images/Icon_Wellspring_of_Power.png | Bin 0 -> 3232 bytes .../resources/images/Question_icon.png | Bin 0 -> 1658 bytes .../resources/images/somerights20.png | Bin 0 -> 854 bytes .../images/thumb/36px-Icon_Feat_Elf.png | Bin 0 -> 2145 bytes .../images/thumb/36px-Icon_Feat_Elven.png | Bin 0 -> 2824 bytes ...x-Icon_Feat_Martial_Weapon_Proficiency.png | Bin 0 -> 2896 bytes .../resources/images/thumb/Icon_Feat_Elf.png | Bin 0 -> 2145 bytes .../src/acceptanceTest/resources/io/Index.md | 8 + .../acceptanceTest/resources/io/IndexSpec.md | 3 + .../io/truthencode/ddo/model/Model.md | 23 + .../ddo/model/alignment/AlignmentsSpec.html | 35 + .../ddo/model/alignment/LawAxisSpec.html | 109 ++ .../ddo/model/alignment/MoralAxisSpec.html | 104 ++ .../ddo/model/destiny/EpicDestinies.md | 1 + .../enhancements/ApothecaryEnhancementSpec.md | 99 ++ .../enhancements/ArcanotechnicianSpec.md | 65 + .../model/enhancements/BattleEngineerSpec.md | 65 + .../ddo/model/enhancements/BombardierSpec.md | 98 ++ .../model/enhancements/EnhancementTree.html | 678 +++++++++++ .../ddo/model/enhancements/Enhancements.md | 6 + .../enhancements/FrenziedBerserkerSpec.md | 65 + .../model/enhancements/OccultSlayerSpec.md | 1 + .../ddo/model/enhancements/RavagerSpec.md | 1 + .../enhancements/RenegadeMastermakerSpec.md | 1 + .../ddo/model/enhancements/VileChemistSpec.md | 96 ++ .../truthencode/ddo/model/feats/DodgeSpec.md | 1 + .../ddo/model/feats/FeatEffectSpec.md | 17 + .../io/truthencode/ddo/model/feats/Feats.html | 267 +++++ .../io/truthencode/ddo/model/feats/FeatsMd.md | 109 ++ .../ddo/model/feats/GeneralFeatsSpec.md | 162 +++ .../ddo/model/feats/ManyShotSpec.md | 57 + .../ddo/model/feats/MartialArtsFeatSpec.html | 32 + .../ddo/model/feats/RacialFeatList.md | 4 + .../ddo/model/feats/TacticalFeatSpec.md | 18 + .../feats/classes/AlchemistClassFeatSpec.md | 240 ++++ .../feats/classes/ArtificerClassFeatSpec.md | 273 +++++ .../feats/classes/BarbarianClassFeatSpec.md | 202 ++++ .../model/feats/classes/BardClassFeatSpec.md | 213 ++++ .../ddo/model/feats/classes/Classes.md | 21 + .../feats/classes/ClericClassFeatSpec.md | 39 + .../model/feats/classes/DruidClassFeatSpec.md | 164 +++ .../feats/classes/FavoredSoulClassFeatSpec.md | 191 +++ .../feats/classes/FighterClassFeatSpec.md | 224 ++++ .../model/feats/classes/MonkClassFeatSpec.md | 257 ++++ .../feats/classes/PaladinClassFeatSpec.md | 240 ++++ .../feats/classes/RangerClassFeatSpec.md | 219 ++++ .../model/feats/classes/RogueClassFeatSpec.md | 207 ++++ .../feats/classes/SorcererClassFeatSpec.md | 170 +++ .../feats/classes/WarlockClassFeatSpec.md | 221 ++++ .../feats/classes/WizardClassFeatSpec.md | 170 +++ .../ddo/model/feats/deity/DeityFeatSpec.md | 37 + .../feats/dragonmarks/DragonmarksFeatSpec.md | 23 + .../truthencode/ddo/model/feats/epic/Epic.md | 12 + .../feats/epic/EpicActiveSpellFeatSpec.md | 17 + .../ddo/model/feats/epic/EpicClassFeatSpec.md | 50 + .../model/feats/epic/EpicGeneralFeatSpec.md | 30 + .../model/feats/epic/EpicMetamagicFeatSpec.md | 16 + .../feats/epic/EpicRangedCombatFeatSpec.md | 15 + .../feats/epic/EpicSpellCastingFeatSpec.md | 29 + .../ddo/model/feats/favor/FavorFeatSpec.md | 1 + .../ddo/model/feats/metamagic/MetaMagic.md | 24 + .../model/feats/races/BladeforgedFeatSpec.md | 31 + .../model/feats/races/DeepGnomeFeatSpec.md | 26 + .../ddo/model/feats/races/DrowFeatSpec.md | 26 + .../ddo/model/feats/races/DwarfFeatSpec.md | 25 + .../ddo/model/feats/races/ElfFeatSpec.md | 26 + .../ddo/model/feats/races/GnomeFeatSpec.md | 25 + .../ddo/model/feats/races/HalfElfFeatSpec.md | 56 + .../ddo/model/feats/races/HalfOrcFeatSpec.md | 19 + .../ddo/model/feats/races/HalflingFeatSpec.md | 25 + .../races/PurpleDragonKnightsFeatSpec.md | 20 + .../ddo/model/feats/races/Races.md | 22 + .../model/feats/races/ShardarkaiFeatSpec.md | 20 + .../ddo/model/feats/races/SunElfFeatSpec.md | 26 + .../model/feats/races/WarforgedFeatSpec.md | 34 + .../io/truthencode/ddo/model/races/Races.md | 3 + .../truthencode/ddo/model/skill/SkillSpec.md | 30 + .../acceptanceTests/AcceptanceTests.scala | 33 + .../src/acceptanceTest/scala/io/Index.scala | 24 + .../truthencode/ddo/model/DisplayHelper.scala | 28 + .../io/truthencode/ddo/model/Model.scala | 27 + .../ddo/model/alignment/AlignmentsSpec.scala | 24 + .../ddo/model/alignment/LawAxisSpec.scala | 47 + .../ddo/model/alignment/MoralAxisSpec.scala | 47 + .../ApothecaryEnhancementSpec.java | 44 + .../enhancements/ArcanotechnicianSpec.java | 39 + .../enhancements/BattleEngineerSpec.java | 44 + .../model/enhancements/BombardierSpec.java | 39 + .../ClassEnhancementDisplayHelper.scala | 52 + ...hancementDisplayHelperTest.scala.scalatest | 113 ++ .../enhancements/ClassEnhancementInfo.scala | 174 +++ .../EnhancementDisplayHelper.scala | 27 + .../model/enhancements/EnhancementTree.java | 27 + .../ddo/model/enhancements/Enhancements.scala | 25 + .../enhancements/FrenziedBerserkerSpec.java | 39 + .../JEnhancementDisplayHelper.scala | 123 ++ .../model/enhancements/OccultSlayerSpec.java | 39 + .../ddo/model/enhancements/RavagerSpec.java | 39 + .../enhancements/RenegadeMastermakerSpec.java | 39 + .../model/enhancements/VileChemistSpec.java | 41 + .../model/feats/BonusFeatTest.scala.scalatest | 39 + .../feats/ClassDisplayBonusFeatTest.scala | 20 + .../model/feats/ClassFeatDisplayHelper.scala | 162 +++ .../feats/ConcordionResourcesBundleSpec.scala | 29 + .../feats/DragonmarkFeatDisplayHelper.scala | 25 + .../feats/EpicFeatFeatDisplayHelper.scala | 37 + .../ddo/model/feats/FeatDisplayHelper.scala | 76 ++ .../truthencode/ddo/model/feats/Feats.scala | 24 + .../feats/GeneralFeatRelatedFixture.scala | 40 + .../ddo/model/feats/GeneralFeatsSpec.java | 36 + .../model/feats/IndividualFeatFixture.scala | 83 ++ .../ddo/model/feats/ManyShotSpec.java | 29 + .../ddo/model/feats/MartialArtsFeatSpec.java | 26 + .../ddo/model/feats/RaceSupport.scala | 59 + .../feats/TacticalFeatFeatDisplayHelper.scala | 39 + .../ddo/model/feats/TacticalFeatSpec.java | 26 + .../classes/AlchemistClassFeatSpec.scala | 33 + .../classes/ArtificerClassFeatSpec.scala | 33 + .../classes/BarbarianClassFeatSpec.scala | 32 + .../feats/classes/BardClassFeatSpec.scala | 32 + .../model/feats/classes/ChargeSupport.scala | 68 ++ .../ddo/model/feats/classes/ClassFeats.scala | 28 + .../feats/classes/ClericClassFeatSpec.scala | 29 + .../feats/classes/DruidClassFeatSpec.scala | 31 + .../classes/FavoredSoulClassFeatSpec.scala | 32 + .../feats/classes/FighterClassFeatSpec.scala | 32 + .../feats/classes/MonkClassFeatSpec.java | 46 + .../feats/classes/MonkJavaHelperFeat.scala | 31 + .../feats/classes/PaladinClassFeatSpec.scala | 32 + .../feats/classes/RangerClassFeatSpec.scala | 32 + .../feats/classes/RogueClassFeatSpec.scala | 32 + .../feats/classes/SorcererClassFeatSpec.scala | 32 + .../feats/classes/WarlockClassFeatSpec.scala | 32 + .../feats/classes/WizardClassFeatSpec.scala | 32 + .../ddo/model/feats/deity/DeityFeatSpec.scala | 155 +++ .../dragonmarks/DragonmarksFeatSpec.scala | 25 + .../ddo/model/feats/epic/Epic.scala | 30 + .../feats/epic/EpicActiveSpellFeatSpec.scala | 31 + .../model/feats/epic/EpicClassFeatSpec.scala | 97 ++ .../feats/epic/EpicGeneralFeatSpec.scala | 31 + .../feats/epic/EpicMetamagicFeatSpec.scala | 31 + .../feats/epic/EpicRangedCombatFeatSpec.scala | 30 + .../feats/epic/EpicSpellCastingFeatSpec.scala | 31 + .../ddo/model/feats/favor/FavorFeatSpec.scala | 44 + .../ddo/model/feats/metamagic/MetaMagic.scala | 35 + .../feats/races/BladeforgedFeatSpec.scala | 28 + .../model/feats/races/DeepGnomeFeatSpec.scala | 28 + .../ddo/model/feats/races/DrowFeatSpec.scala | 28 + .../ddo/model/feats/races/DwarfFeatSpec.scala | 29 + .../ddo/model/feats/races/ElfFeatSpec.scala | 30 + .../ddo/model/feats/races/GnomeFeatSpec.scala | 28 + .../model/feats/races/HalfElfFeatSpec.scala | 49 + .../model/feats/races/HalfOrcFeatSpec.scala | 28 + .../model/feats/races/HalflingFeatSpec.scala | 28 + .../races/PurpleDragonKnightsFeatSpec.scala | 28 + .../ddo/model/feats/races/Races.scala | 40 + .../feats/races/ShardarkaiFeatSpec.scala | 28 + .../model/feats/races/SunElfFeatSpec.scala | 28 + .../model/feats/races/WarforgedFeatSpec.scala | 28 + .../truthencode/ddo/model/races/Races.scala | 24 + .../ddo/model/skill/SkillSpec.scala | 65 + .../support/ConcordionEnumBuilderHelper.scala | 47 + .../ConcordionEnumBuilderSupport.scala | 78 ++ .../ConcordionEnumHelperTest.scala.scalatest | 46 + .../support/ConcordionTemplateBuilder.scala | 115 ++ ...cordionTemplateBuilderTest.scala.scalatest | 41 + .../ddo/support/requisite/Requisite.md | 3 + .../ddo/testoptions/DefaultFlexmark.scala | 22 + .../truthencode/ddo/testoptions/Emoji.scala | 52 + .../ddo/testoptions/Flexmark.scala | 87 ++ .../ddo/testoptions/FlexmarkImpl.scala | 27 + .../GfmStrikethroughSubscript.scala | 48 + .../ddo/testoptions/GfmTaskListOptions.scala | 51 + .../ddo/testoptions/WikiLink.scala | 52 + 251 files changed, 11224 insertions(+), 5 deletions(-) create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/destiny/EpicDestinies.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/feats/DodgeSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/AcceptanceTests.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/keepme.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/css/ddostyle.css create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/36px-Icon_Feat_Exotic_Weapon_Proficiency.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/36px-Icon_Feat_Martial_Weapon_Proficiency.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/ApothecaryDetermination.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/DragonmarkofFinding (1).png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/DragonmarkofFinding.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/HalfOrcOrcBlood.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Arcane_Insight.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Blinding_Speed.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Burst_of_Glacial_Wrath.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Class_feats (1).png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Class_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Construct_Essence.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Embolden_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Enhancement_Shadow_Phase.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Damage_Reduction.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Destiny_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Eldritch_Blast.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Fortitude.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Life_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Power.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Reflexes.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Reputation.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Will.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Bladeforged.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Bulwark_Of_Defense.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Combat_Archery.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Composite_Plating.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Dwarven.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Elf.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Empower_Healing_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Empower_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Enlarge_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Mental_Toughness.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Skill.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Spell_Focus.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Spell_Penetration.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Toughness.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Eschew_Materials.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Extend_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Halfling_Agility.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Heighten_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Human.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Improved_Martial_Arts.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Improved_Sneak_Attack.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Inspire_Excellence.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Maximize_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Overwhelming_Critical.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Quicken_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Vorpal_Strikes.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_General_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Greater_Ruin.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Iconic_Past_Life_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Improved_Augment_Summoning.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Intensify_Spell.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Air.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Alignment.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Artifice.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Earth.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Fire.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Knowledge.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Light.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Music.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Water.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_the_Dead.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_the_Wilds.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Past_Life_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Racial_feats.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Ruin.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Watchful_Eye.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Wellspring_of_Power.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/Question_icon.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/somerights20.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/36px-Icon_Feat_Elf.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/36px-Icon_Feat_Elven.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/Icon_Feat_Elf.png create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/Index.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/IndexSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/Model.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/AlignmentsSpec.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/destiny/EpicDestinies.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BombardierSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/EnhancementTree.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/Enhancements.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RavagerSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/VileChemistSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/DodgeSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatEffectSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/Feats.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatsMd.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/GeneralFeatsSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/ManyShotSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.html create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/RacialFeatList.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/TacticalFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/Classes.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/Epic.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/metamagic/MetaMagic.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DrowFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ElfFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/Races.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/races/Races.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/skill/SkillSpec.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/acceptanceTests/AcceptanceTests.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/Index.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/DisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/Model.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/AlignmentsSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/LawAxisSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/MoralAxisSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BombardierSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelperTest.scala.scalatest create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementInfo.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementTree.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/Enhancements.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/JEnhancementDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RavagerSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/VileChemistSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/BonusFeatTest.scala.scalatest create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassDisplayBonusFeatTest.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassFeatDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ConcordionResourcesBundleSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/DragonmarkFeatDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/EpicFeatFeatDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/FeatDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/Feats.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatRelatedFixture.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatsSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/IndividualFeatFixture.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ManyShotSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/RaceSupport.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatFeatDisplayHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ChargeSupport.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClassFeats.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.java create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkJavaHelperFeat.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/Epic.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/metamagic/MetaMagic.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DrowFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ElfFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/Races.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/races/Races.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/skill/SkillSpec.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderHelper.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderSupport.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumHelperTest.scala.scalatest create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilder.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilderTest.scala.scalatest create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/requisite/Requisite.md create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/DefaultFlexmark.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Emoji.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Flexmark.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/FlexmarkImpl.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmStrikethroughSubscript.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmTaskListOptions.scala create mode 100644 subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/WikiLink.scala diff --git a/docs/developers_guide/Tech_Concepts.md b/docs/developers_guide/Tech_Concepts.md index df9a3bb0..6adcbe70 100644 --- a/docs/developers_guide/Tech_Concepts.md +++ b/docs/developers_guide/Tech_Concepts.md @@ -1,4 +1,4 @@ -# List of technologies used or considered for use. +# List of technologies used or considered for use Build quality / development tools These are generally implemented via gradle plugins or triggered of CI/CD builds to improve code quality / security and or mind map or visualize concepts. @@ -37,16 +37,23 @@ result comparison. Scala3 has integrated features similar to docusaurus, so like Scala3 upgrade. Possible alternatives are [Znai](https://testingisdocumenting.org/znai/introduction/getting-started/) or Docusaurus. We can go aDoc if needed but would prefer Markdown. +### Allure + +[Allue](https://github.com/allure-framework) is a reporting aggregation service that works with Junit4 , Junit5, Scalatest, Cucumber and more. + ### OpenAPI + Embedding a Swagger UI for the OpenAPI spec in the docs ### Jupyter + Would eventually like to integrate a Jupyter notebook in the doc site. This would be useful for a living calculator, quick web checks and possibly even spark integration. -The default is very Python focused, but R / Scala kernels exist. Ideally embedding a Graal Scala Jupyter. +The default is very Python focused, but R / Scala kernels exist. Ideally embedding a Graal Scala Jupyter. There are also a handful of Proof of concept polygot notebooks out there, mostly built in Smalltalk. ## Front End + Front End Using Kafka streams, we can update running totals and properties in an event-driven manner for character builders such as feats possessed, stances / abilities toggled, items equipped to dynamically show average damage, DR breaking, crit profiles, hit-points etc. without having to re-evaluate every effect in place. @@ -57,6 +64,10 @@ filtering by requirements as they are discovered. Camel - camel can route these topics in the background to update the databases, run further more process intensive operations etc without affecting the flow of the builder. -Vert.x Vert.x can expose the API as a RESTful service and react via the event bus with Camel. +Vert.x Vert.x can expose the API as a RESTful service and react via the event bus with Camel. +## Apache Isis +Rapid prototyping where Domain Objects become the UI. +[Apache ~~Isis~~ Causeway](https://causeway.apache.org) +May have potential direct-integration issues as a JPMS Java app, but as a RESTful DTO Front-end it could be extremely useful. diff --git a/docs/resources/integration.md b/docs/resources/integration.md index 6be6cda9..9a238e15 100644 --- a/docs/resources/integration.md +++ b/docs/resources/integration.md @@ -7,5 +7,3 @@ Ideally, I would like to fill the gaps with existing solutions as opposed to dup examples include importing data from the undisputed Character Planner's forum export. [DDO wiki](https://www.ddowiki.com) - - diff --git a/subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/destiny/EpicDestinies.java b/subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/destiny/EpicDestinies.java new file mode 100644 index 00000000..098930a8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/destiny/EpicDestinies.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.destiny; + +import com.vladsch.flexmark.ext.emoji.EmojiExtension; +import com.vladsch.flexmark.parser.Parser; +import com.vladsch.flexmark.util.data.DataSet; +import com.vladsch.flexmark.util.data.MutableDataSet; +import com.vladsch.flexmark.util.misc.Extension; +import org.concordion.api.option.FlexmarkOptions; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +import java.util.List; + +@RunWith(ConcordionRunner.class) +public class EpicDestinies { + private final transient List e = List.of(EmojiExtension.create()); + @FlexmarkOptions + DataSet flexmarkOptions = new MutableDataSet() + .set(EmojiExtension.ATTR_IMAGE_SIZE, "24") + .set(Parser.EXTENSIONS, e); + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/feats/DodgeSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/feats/DodgeSpec.java new file mode 100644 index 00000000..421160c5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/java/io/truthencode/ddo/model/feats/DodgeSpec.java @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats; + +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@RunWith(ConcordionRunner.class) +public class DodgeSpec { +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/AcceptanceTests.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/AcceptanceTests.md new file mode 100644 index 00000000..6cf21563 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/AcceptanceTests.md @@ -0,0 +1,3 @@ +# AcceptanceTests + +- [Model](../io/truthencode/ddo/model/Model.html "c:run") diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/keepme.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/keepme.html new file mode 100644 index 00000000..14c4016d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/acceptanceTests/keepme.html @@ -0,0 +1,27 @@ + + + + + + File here to prevent auto-delete of directory + + + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/css/ddostyle.css b/subprojects/common/ddo-core/src/acceptanceTest/resources/css/ddostyle.css new file mode 100644 index 00000000..888e9176 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/css/ddostyle.css @@ -0,0 +1,1043 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +body.page-Main_Page h1.firstHeading { + display: none; +} + +#p-logo, +#p-logo a { + height: 65px !important; +} + +tr.mw-table-row-done { + font-size: smaller; + text-decoration: line-through; + text-decoration: line-through wavy #dd0000; + background-color: #feeded; +} + +tr.sticky-header { + position: -webkit-sticky !important; + position: sticky !important; + top: 0px !important; + z-index: 1 !important; +} + +div.scrollBox table.wikitable { + margin-top: 0px !important; +} + +td.diff-context, +td.diff-deletedline, +td.diff-addedline { + font-size: larger !important; + font-family: monospace; +} + +span.redlink > a.external.text { + background: none !important; + color: #ba0000 !important; + padding: 0px !important; +} + +.tall-header > th { + max-width: 1px; + white-space: pre-wrap; + word-wrap: break-word; +} + +.emailLink { + display: none; +} + +.boxCell { + background-color: #ffffff; + border: 1px solid #aaaaaa; + border-radius: 5px; + padding: 5px; + vertical-align: top; + width: 33%; +} + +.homeCell { + padding: 5px; + font-weight: bold; + margin: 3px; + text-align: center; +} + +.boxCellIcon { + float: right !important; +} + +#whatsNew, +.whatsNew { + overflow: auto !important; +} + +div.whatsNewSection { + background-color: #fa8072; + margin: 3px; + text-align: center; +} + +div.whatsNewLamannia { + background-color: #d9d9ff !important; +} + +@media (min-width: 2048px) { + #whatsNew, + .whatsNew { + width: 1591px; + } + + div.whatsNewSection { + width: 510px; + } +} + +@media (max-width: 1920px) { + #whatsNew, + .whatsNew { + width: 1326px; + } + + div.whatsNewSection { + width: 422px; + } +} + +@media (max-width: 1600px) { + #whatsNew, + .whatsNew { + width: 11194px; + } + + div.whatsNewSection { + width: 378px; + } +} + +@media (max-width: 1440px) { + #whatsNew, + .whatsNew { + width: 1061px; + } + + div.whatsNewSection { + width: 334px; + } +} + +@media (max-width: 1280px) { + #whatsNew, + .whatsNew { + width: 849px; + } + + div.whatsNewSection { + width: 263px; + } +} + +@media (max-width: 1024px) { + #whatsNew, + .whatsNew { + width: 663px; + } + + div.whatsNewSection { + width: 201px; + } +} + +@media (max-width: 800px) { + #whatsNew, + .whatsNew { + width: 530px; + } + + div.whatsNewSection { + width: 157px; + } +} + +@media (max-width: 640px) { + #whatsNew, + .whatsNew { + width: 398px; + } + + div.whatsNewSection { + width: 112px; + } +} + +@media (max-width: 480px) { + #whatsNew, + .whatsNew { + width: 346px; + } + + div.whatsNewSection { + width: 97px; + } +} + +td.homeWhatsNewCell { + background-color: #ffffff; + border: 1px solid #aaaaaa; + border-radius: 5px; + vertical-align: top; +} + +.whatsNewSectionContent { + background-color: #ffffff; + align: left; +} + +.homeSiteMapCell { + background-color: palegoldenrod; +} + +.homeAboutCell { + background-color: lightskyblue; +} + +.IPA { + font-family: + Chrysanthi Unicode, + Doulos SIL, + Gentium, + GentiumAlt, + Code2000, + TITUS Cyberbit Basic, + DejaVu Sans, + Bitstream Vera Sans, + Bitstream Cyberbit, + Arial Unicode MS, + Lucida Sans Unicode, + Hiragino Kaku Gothic Pro, + Matrix Unicode; +} + +.Unicode { + font-family: + TITUS Cyberbit Basic, + Code2000, + Doulos SIL, + Chrysanthi Unicode, + Bitstream Cyberbit, + Bitstream CyberBase, + Bitstream Vera, + Thryomanes, + Gentium, + GentiumAlt, + Visual Geez Unicode, + Lucida Grande, + Arial Unicode MS, + Microsoft Sans Serif, + Lucida Sans Unicode; +} + +.polytonic { + font-family: + Athena, + Gentium, + Palatino Linotype, + Arial Unicode MS, + Lucida Sans Unicode, + Lucida Grande, + Code2000; +} + +.developer-show, +.widgeteditor-show, +.steward-show, +.bureaucrat-show, +.sysop-show, +.superuser-show, +.ddowikivip-show, +.user-show, +.self-show { + display: none; +} + +.mw-charinsert-buttons { + border: 1px solid #aaaaaa; + font-size: 110%; + margin-top: 10px; + padding: 1px; + text-align: center; +} + +.mw-charinsert-buttons a { + background-color: #ccddee !important; + border: thin #006699 outset; + color: #000000; + font-size: 0.9em; + font-weight: bold; + padding: 0em 0.1em 0.1em; + text-decoration: none; +} + +.mw-charinsert-buttons a:hover, +.mw-charinsert-buttons a:active { + background-color: #bbccdd; + border-style: inset; +} + +.client-js .mw-edittools-section { + display: inline; +} + +.client-js .mw-edittools-section input[type="button"] { + font-size: 0.9em; + margin-left: 1px; + padding: 0px 1px; +} + +span.has_tooltip { + position: relative; +} + +span.has_tooltip span.tooltip { + display: none; +} + +span.has_tooltip:hover span.tooltip { + display: block; + left: 13px; + position: absolute; + top: 9px; + width: 200%; +} + +pre { + max-width: 1200px; + min-width: 300px; + overflow: auto; + white-space: pre-wrap !important; + word-wrap: break-word; +} + +.navbox { + border: 1px solid #aaaaaa; + clear: both; + font-size: 88%; + margin: auto; + padding: 1px; + text-align: center; + width: 100%; +} + +.navbox-inner, +.navbox-subgroup { + width: 100%; +} + +.navbox-group, +.navbox-title, +.navbox-abovebelow { + padding: 0.25em 1em; + line-height: 1.5em; + text-align: center; +} + +th.navbox-group { + white-space: nowrap; + text-align: right; +} + +.navbox, +.navbox-subgroup { + background-color: #fdfdfd; +} + +.navbox-list { + line-height: 1.8em; + border-color: #fdfdfd; +} + +.navbox th, +.navbox-title { + background-color: #ccccff; +} + +.navbox-abovebelow, +th.navbox-group, +.navbox-subgroup .navbox-title { + background-color: #ddddff; +} + +.navbox-subgroup .navbox-group, +.navbox-subgroup .navbox-abovebelow { + background-color: #e6e6ff; +} + +.navbox-even { + background-color: #f7f7f7; +} + +.navbox-odd { + background: transparent; +} + +table.navbox + table.navbox { + margin-top: -1px; +} + +.navbox .hlist td dl, +.navbox .hlist td ol, +.navbox .hlist td ul, +.navbox td.hlist dl, +.navbox td.hlist ol, +.navbox td.hlist ul { + padding: 0.125em 0em; +} + +ol + table.navbox, +ul + table.navbox { + margin-top: 0.5em; +} + +.collapseButton { + float: right; + font-weight: normal; + margin-left: 0.5em; + text-align: right; + width: auto; +} + +.mw-collapsible-toggle { + font-weight: normal; + text-align: right; +} + +.navbox .mw-collapsible-toggle { + width: 6em; +} + +.hidden { + display: none; +} + +table.ItemDisplayTemplateOuterTable { + background-color: #cceeff; + border-collapse: collapse; +} + +table.ItemDisplayTemplateOuterTable tr { + vertical-align: top; +} + +table.ItemDisplayTemplateOuterTable th { + background-color: #aaccff; + padding: 2px 10px; + vertical-align: middle; + white-space: nowrap; +} + +table.ItemDisplayTemplateOuterTable td.ItemDisplayTemplateExampleValue { + background-color: #ffffff; + padding-top: 15px; +} + +table.ItemDisplayTemplateOuterTable td { + background-color: #cceeff; + padding: 2px 10px; +} + +table.ItemDisplayAmmunitionOuterTable { + width: 100%; + background-color: #f0d1e0; + border-collapse: collapse; +} + +table.ItemDisplayAmmunitionOuterTable tr { + vertical-align: top; +} + +table.ItemDisplayAmmunitionOuterTable td { + width: 100%; +} + +table.ItemDisplayAmmunitionDetailsTable { + background-color: #f0d1e0; + width: 100%; +} + +table.ItemDisplayAmmunitionDetailsTable th { + background-color: #e6b2cc; + padding: 2px 10px; + vertical-align: middle; + white-space: nowrap; +} + +table.ItemDisplayAmmunitionDetailsTable td { + background-color: #ebc2d6; + padding: 2px 10px; +} + +table.ItemDisplayAmmunitionImagesTable { + background-color: #f0d1e0; + padding: 10px 0px; + width: 100%; +} + +table.ItemDisplayAmmunitionImagesTable tr { +} + +table.ItemDisplayAmmunitionImagesTable td { + padding: 15px 10px; +} + +table.ItemDisplayArmorOuterTable { + background-color: #e0d1b2; + border-collapse: collapse; + width: 100%; +} + +table.ItemDisplayArmorOuterTable tr { + vertical-align: top; +} + +table.ItemDisplayArmorOuterTable td { + width: 100%; +} + +table.ItemDisplayArmorDetailsTable { + background-color: #e0d1b2; + width: 100%; +} + +table.ItemDisplayArmorDetailsTable th { + background-color: #ccb280; + padding: 2px 10px; + vertical-align: middle; + white-space: nowrap; +} + +table.ItemDisplayArmorDetailsTable td { + background-color: #d6c299; + padding: 2px 10px; +} + +table.ItemDisplayArmorImagesTable { + background-color: #e0d1b2; + padding: 10px 0px; + width: 100%; +} + +table.ItemDisplayArmorImagesTable tr { +} + +table.ItemDisplayArmorImagesTable td { + padding: 15px 10px; +} + +table.ItemDisplayComponentOuterTable { + background-color: #cceeff; + border-collapse: collapse; + width: 100%; +} + +table.ItemDisplayComponentOuterTable tr { + vertical-align: top; +} + +table.ItemDisplayComponentOuterTable td { + width: 100%; +} + +table.ItemDisplayComponentDetailsTable { + background-color: #cceeff; + width: 100%; +} + +table.ItemDisplayComponentDetailsTable th { + background-color: #a3becc; + padding: 2px 10px; + vertical-align: middle; + white-space: nowrap; +} + +table.ItemDisplayComponentDetailsTable td { + background-color: #b8d6e6; + padding: 2px 10px; +} + +table.ItemDisplayComponentImagesTable { + background-color: #cceeff; + padding: 10px 0px; + width: 100%; +} + +table.ItemDisplayComponentImagesTable tr { +} + +table.ItemDisplayComponentImagesTable td { + padding: 15px 10px; +} + +div.mw-warning-with-logexcerpt, +div.mw-lag-warn-high, +div.mw-cascadeprotectedwarning, +div#mw-protect-cascadeon { + background: none repeat scroll 0% 0% #ffdbdb; + border: 1px solid #bb7070; + clear: both; + margin: 0.2em 0px; + padding: 0.25em 0.9em; +} + +.center { + text-align: center !important; + width: inherit !important; +} + +.middle { + vertical-align: middle; +} + +.citation::before { + content: "[ "; +} + +.citation::after { + content: " ]"; +} + +.citation { + font-size: smaller; + font-variant-position: super; + vertical-align: super; + font-weight: bold; +} + +.hlist dl, +.hlist ol, +.hlist ul { + margin: 0; + padding: 0; +} + +.hlist dd, +.hlist dt, +.hlist li { + margin: 0; + display: inline; +} + +.hlist.inline, +.hlist.inline dl, +.hlist.inline ol, +.hlist.inline ul, +.hlist dl dl, +.hlist dl ol, +.hlist dl ul, +.hlist ol dl, +.hlist ol ol, +.hlist ol ul, +.hlist ul dl, +.hlist ul ol, +.hlist ul ul { + display: inline; +} + +.hlist .mw-empty-li { + display: none; +} + +.hlist dt:after { + content: ":"; +} + +.hlist dd:after, +.hlist li:after { + content: " · "; + font-weight: bold; +} + +.hlist dd:last-child:after, +.hlist dt:last-child:after, +.hlist li:last-child:after { + content: none; +} + +.hlist dd dd:first-child:before, +.hlist dd dt:first-child:before, +.hlist dd li:first-child:before, +.hlist dt dd:first-child:before, +.hlist dt dt:first-child:before, +.hlist dt li:first-child:before, +.hlist li dd:first-child:before, +.hlist li dt:first-child:before, +.hlist li li:first-child:before { + content: " ("; + font-weight: normal; +} + +.hlist dd dd:last-child:after, +.hlist dd dt:last-child:after, +.hlist dd li:last-child:after, +.hlist dt dd:last-child:after, +.hlist dt dt:last-child:after, +.hlist dt li:last-child:after, +.hlist li dd:last-child:after, +.hlist li dt:last-child:after, +.hlist li li:last-child:after { + content: ")"; + font-weight: normal; +} + +.hlist ol { + counter-reset: listitem; +} + +.hlist ol > li { + counter-increment: listitem; +} + +.hlist ol > li:before { + content: " " counter(listitem) "\a0"; +} + +.hlist dd ol > li:first-child:before, +.hlist dt ol > li:first-child:before, +.hlist li ol > li:first-child:before { + content: " (" counter(listitem) "\a0"; +} + +.plainlist ol, +.plainlist ul { + line-height: inherit; + list-style: none none; + margin: 0; +} + +.plainlist ol li, +.plainlist ul li { + margin-bottom: 0; +} + +.toclimit-2 .toclevel-1 ul, +.toclimit-3 .toclevel-2 ul, +.toclimit-4 .toclevel-3 ul, +.toclimit-5 .toclevel-4 ul, +.toclimit-6 .toclevel-5 ul, +.toclimit-7 .toclevel-6 ul { + display: none; +} + +span.snip { + font-size: smaller; + font-weight: bold; + font-style: italic; +} + +span.calc_xp_bonus { + font-style: italic !important; +} + +span.calc_xp_bonus:before { + content: " ("; +} + +span.calc_xp_bonus:after { + content: ")"; +} + +table.padone > tbody > tr > td { + padding: 0em 1em !important; +} + +th.Fephead, +td.Fephead { + background-color: #ccff99; + border: 2px solid #aadd77; + border-bottom-width: 0; +} + +th.fEphead, +td.fEphead { + background-color: #f0e68c; + border: 2px solid #db9200; + border-bottom-width: 0; +} + +th.fePhead, +td.fePhead { + background-color: #ffa07a; + border: 2px solid #ff8058; + border-bottom-width: 0; +} + +th.Fepcell, +td.Fepcell { + background-color: #eeffcc; + border: 2px solid #aadd77; + border-top-width: 0; +} + +th.fEpcell, +td.fEpcell { + background-color: #fafad2; + border: 2px solid #db9200; + border-top-width: 0; +} + +th.fePcell, +td.fePcell { + background-color: #ffdab9; + border: 2px solid #ff8058; + border-top-width: 0; +} + +span.has_tooltip { + position: relative; +} + +span.has_tooltip span.tooltip { + display: none; +} + +span.has_tooltip:hover span.tooltip { + display: block; + width: 200%; + position: absolute; + top: 9px; + left: 13px; +} + +div.post { + margin: 0px; + margin-right: 5px; + margin-top: 5px; + padding: 9px; + border-top: 4px solid #658296; + border-bottom: 4px solid #658296; + border-left: 1px dashed #658296; + border-right: 1px dashed #658296; + background: #f9f9f9; +} + +div.post .sig { + margin: 0px; + margin-left: 10px; + margin-top: 5px; + padding: 4px; + font-size: 80%; + font-weight: bold; + border-top: 1px dashed #999999; + border-left: 4px solid #999999; +} + +div.post:hover .sig { + border-top: 1px dashed #666666; + border-left: 4px solid #666666; +} + +.usermessage { + margin: 6px 0px; +} + +.inlineunhider .inlineunhide { + display: none; +} + +.inlineunhider:hover .inlineunhide { + display: inline; +} + +small.inlineunhide { + clear: both; + float: right; + font-style: italic; + font-weight: normal; +} + +table.itemTable { + clear: right; + border: 1px solid #ffff00; + border-bottom-width: 3px; + border-right-width: 2px; + margin: 4px auto; + width: 98%; +} + +table.itemTable.jewelry { + background-color: #ffbbbb; +} + +table.itemTable.clothing { + background-color: #ddaaff; +} + +table.itemTable.weapon, +table.itemTable.wand, +table.itemTable.runearm, +table.itemTable.cosmetic { + background-color: #ccff99; +} + +table.itemTable.ammunition { + background-color: #ff9999; +} + +table.itemTable.armor { + background-color: #f0dc82; +} + +table.itemTable.shield { + background-color: #aaccff; +} + +table.itemTable.quiver { + background-color: #eebbee; +} + +table.itemTable tr { + text-align: center; +} + +table.itemTable td { + vertical-align: middle; +} + +table.itemTable td.frame { + font-weight: bold; +} + +table.itemTable td.desc { + text-align: left; + padding-left: 3px; +} + +table.itemTable td.frame.undefinedSlot { + background-color: #ffff00; +} + +table.itemTable td.frame.jewelry { + background-color: #ffbbbb; +} + +table.itemTable td.frame.clothing { + background-color: #ddaaff; +} + +table.itemTable td.frame.weapon, +table.itemTable td.frame.wand, +table.itemTable td.frame.runearm, +table.itemTable td.frame.cosmetic { + background-color: #ccff99; +} + +table.itemTable td.frame.ammunition { + background-color: #ff9999; +} + +table.itemTable td.frame.armor { + background-color: #f0dc82; +} + +table.itemTable td.frame.shield { + background-color: #aaccff; +} + +table.itemTable td.frame.quiver { + background-color: #eebbee; +} + +td.desc.undefinedSlot { + background-color: #e6d8ad; +} + +td.desc.jewelry { + background-color: #ffe4e1; +} + +td.desc.clothing { + background-color: #eeddff; +} + +table.itemTable td.desc.weapon, +table.itemTable td.desc.wand, +table.itemTable td.desc.runearm, +table.itemTable td.desc.cosmetic { + background-color: #eeffcc; +} + +table.itemTable td.desc.ammunition { + background-color: #ffcccc; +} + +table.itemTable td.desc.armor { + background-color: #fffacd; +} + +table.itemTable td.desc.shield { + background-color: #cceeff; +} + +table.itemTable td.desc.quiver { + background-color: #f0e4f0; +} + +table.itemTable td.image { + vertical-align: top; + min-width: 426px; + max-width: 426px; +} + +table.itemTable.mount { + background-color: #bbffbb; +} + +table.itemTable td.frame.mount { + background-color: #bbffbb; +} + +table.itemTable td.desc.mount { + background-color: #aaeeaa; +} + +table > thead > tr.sticky { + position: -webkit-sticky; + position: sticky; + top: 0px; + z-index: 1; +} + +div.clickable a { + display: flex; + align-items: center; + width: 100%; + height: 100%; + background-color: #f7f7f7; + padding-right: 5px; +} + +div.clickable a img { + padding: 1em; +} + +div.clickable a.external.text { + background-image: none; + padding-right: 5px; +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/36px-Icon_Feat_Exotic_Weapon_Proficiency.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/36px-Icon_Feat_Exotic_Weapon_Proficiency.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e70fd03474c3cd85f96b614f4212b36287d82a GIT binary patch literal 2746 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/ApothecaryDetermination.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/ApothecaryDetermination.png new file mode 100644 index 0000000000000000000000000000000000000000..1b910f3eb37efc051bd79a1f200bf469ca8ef878 GIT binary patch literal 2667 zcmV-x3Y7JUP)Olvf&nzrRfRr}qjoR4EEr z04a(hU_-1RC>9Xx*kX(zx>yo5tCB=b*0p8Ls%v($iP^ZOY_dj^7-Pf;DhN_TX9gIi zm%r>>c=DhDY-?=!zyqFIz9IM{H;mXvcfvi`5}ZpMHDC#dr5zx^VEFlY5vKgTo8Bdf{ko&7H8YK)a=H$UI=NSOCCeG9i8db2uC_ zrBbIiHa4|5-6We~m6Yv)=kff&=_BRMjrC6+-|KuzXp{mJ0f9h(BN#$3Y#hfhjuU4n zpR?`J{ox@i;KX+~Z}@!Fx@~*mS(s#E}9ivwsz5>SGPZFL*du_^Fl?<-CGTh zY65lg=VHkzEZ*qG3bH=b)?(b*4o_qwE6s* zqws5f75Ll5%5T2C(c9Z2mvHnNLMWmYNs> z<-u`Wrk0O5okI=>gQF6;1Ys!akU1?WLBPRpe^=Am^rWut&cCm{`rAi7|9(|dTT^RK z!>r6mb4L$~d!=G2ANO)tfa7TYK$p~y*njMihQ`Nk9~%&q&+t_$RZY!J|57Z#MSK(k z__?zwI6D4|FTQMQFmK!O<}WvR>vZMQ_Qo6Ef2IxTsCW6-CfI2KT0EC{^#4S&R&MW`uj};LC_3EQXUM0fIz*$7+Q0$w)tt}l?&AX zfS!5xpqHeseRhoz(>9iwt)XQ`q1iq#Y#m|Y{NA3y*4B2GKSJTOo775GVZou!5g*%s ze7T|SK_g$JRA}_w17;7+kPIj^n)|i&Km2HU{P@wMM>Qv^%Tb|-bK}-m4$6gzffB$7 zV;L16PI4HlbI|3c>*?#2$rUN7X z=sYBJ4fUApmdjVJe)s)7t8EZxkr<11dYn!#+0x!^_W*+mDId{L+pCp9YC;qXr35@S z!DZu4*NBI5(kMcr%&-e=KDyUpN}rS5`O`qd7rmcBH4ZoyYC_ zxu@r+$B(r^pSM9lsDCI3xI8Y? zAU$MtU@B6gVPit@VT>1Hw{#5)2o+- zHk$(nhE0As9zFJnXVqtw3W03uezuzE^WYt<-dOnt$#w8^T=}%0fvW<#yT;ie%9=hXElA z=OVmY|FuL!r2gsr$-PHk+W5*O9|t%BkgITQfYgV$XtvWv4YhQ4+guilZAhh5uuzUt z!8e-+yrl2mPY=5K%rpfY|8TfGcc$9yM(Z)R^!VYE_inc5F37ub`4a-? zY1No{up?Qj(P=bx^Wc+~?jcXNHZ)AjHKGiSQa+l?1&5un+bNT2ki)`~663jSSXLN* z|9(Yt_XZy`)X`TzXl?g0gFw4Z9Y1&JT-&silv8j1Lm`xoiHN{3Ph>=3fL=p-yegH3 zqF}%b!y}fV5eq7lDF6_M6@UhY1e6Ak+YzAC(3U;@BR#x5X1ry$N|*w)st}+X7;c<=i+-2p=vn1Eh|ZfmS&7Sy|ZL> zM#RSK@U4rY*5`z$g<<)Vf>&q9CxwcV#_HFU%&*$L5g3M9yLnDl-Y8uHgk?g(F8K4+ zNh_B7MIhxtOblRBxK*3$CO2HZ5FD<6lY15|Oi<<}sxKWVD$k2sI#FDaA6;1(Sv*Z1 zuY-g@WYz@3ytLSY1ygocZ1Br}`Sh2q&6-^_J}MKLQ4B}UrX8;?)(YX^zCe?yQl^5o z_T!&_lrte1Dpw^JP7Y5sz_G0}kCja+o+8bOgrn<{t{hr$VD-4dbi=e*WzOVLrAua1 zY+voy{y*TSuxx71Dr05=_HxyPHx3m=1wrpX-jH>gHPn8!Y3wACF{a5v}+m|=(E{a_42Ot%X3OHVi!-+&rXyUElk+EyW}@QV4k6HMcn*(;!`JQZ`)`Tb6{oO z_#LGSGomyp1|m)k*@^1ZNbcAGEHzA#VpJsR#PJ$loEBM-9et4aM`Hs{-Z) z6fMih&K#eUIUzbkJY!Pi+WeXMGbgNE7`Jk9+|s%6v!}#NPl--X49l4wJuTH(zHQ}; zJixq|T|3vjws*skgKM^z&8ym3x_NbO#Y+X1FBk0JRZ{u#(#lr~D$AD~`D5AP!&`qx Z@;~I;pIO#sqniK#002ovPDHLkV1k5sBn|)o literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/DragonmarkofFinding (1).png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/DragonmarkofFinding (1).png new file mode 100644 index 0000000000000000000000000000000000000000..fb7049cd4038aab7b73a55b8493e41e211c133c1 GIT binary patch literal 2727 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Arcane_Insight.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Arcane_Insight.png new file mode 100644 index 0000000000000000000000000000000000000000..9ee32c603231665f3d1971f1ea77be7fbbe1e443 GIT binary patch literal 3576 zcmV@Wz1O~<%gmWGbIy$Iv9ZVa0@&EZ-~vhl zBm@ddL`xb_D$*vcD2XDfN=?*ARh1|giHbx`(?V3Ds!5wFYM`Vc1WHOm5=_j+F$H3K z#*FQ;=X&nfecx;K$BdDG=4aQR{bx)2-QTyq_kF)t@Y^281x+F>4b#vOx`~t-mIHBGrTnD5C zr33mpAWMLzfd)tgQd0;Ml!7U>@ty(;@O01=*d|!6Mv{O5kV(bO2M(+4TXr()RnV1z z>v&kENwZ#O*z02$22x54!@$kwux%UH$(Cas`yomYb1)lxsOB!qd5(apd!}-~BEDT%7z``<2vN)sY772zS zmgNw~F_{F0BSSY0M5+jr zI=Rx2iJ1zn4Pm+g$k3r&p5Vmkvv|=KJXJ+#7FK59s1jx($c7pgHcIMffrVk2(35zM ziD76Af&nt<63PLilVx;e;0J9?17sXvC=DwKupE(yTTs0s0tcZ9#@x*a%SI(OWEQqnq}l3WVUuMUqfVYU3COZ0DznK^rfO73 zQD}M|OBlpK6I1CFbjSipltt(w!y`gdHFBbW&Lw~}4g6t<<2bm|K^YcP6IHZKQZD52 zyAiggqf)_CwZa7h27ZJxOp1<&7|A152uZ-0E!bV%%uvf%wsgWUCemz#ve7ayJsU(! zlyvYlle}BNN;F&pf{QJ4EYNkGyjLJ?OA3yQVJa$9CGw77`m#y-odDM?P;dp#=q8pH zYlLw|lJyuZROt0g0+o?B9X6NCv}M51?~?gGrCfo$If9S|nMyHT=nfN9Vj+Zy&~$YD zk_shhk$k>DVnv`7Q=6x7bKvV8I>CUP?$V2gY@ghNIX1$WTg9ztG;0GAKVf{##WX9B zb}8fw*u^~b13cFxuyqQSM^O~fQv<`ch*bqn2KGJbcI~b!!9YTRA~}?-u`|xH|0Wafs+?bGP-4qoqI1wv<<3No8LV2-*kc{MsiT=Zvc`C zgrVVBf}AFa;y$*WN3&phViS#CoA12*U7mjH84m4w7r%GYT^xMZL1wmY!5VI7ZGMek zy!kv%KF8K;_VV7FZf7Jnf-V*3=H?h1D>I#+CXgYC88h^|w2}qRG=5FjoM)h04EmS0 z%v|Ro9gVfs74#_+VSp4FdcmMvsW7s$OtW6+=VxBv=!qj-JM%7XyY2%V-g^TR?8k8oV@gNxE3 zL8**XW?-6h2R?;?k5$PLgaJ_&kuQ6cCrgZ$a%6*qpU?iBWAm@Gy}FapT$Qn66%`nC z7WxeQKF(%~zUZ*ne4E~&jbT{0hJ!UJC}?@?zKbwYd>Ij`JXyF=Axm5LCsIn%G$zdw zY|p{>edJIe^BTf%i3gCSl3t_5$jAuW_RWA2%rBouwU#M6lPtZt!kvfi;K5Hnz@4AE zgXx1?@k*oUr94VY@hp>~=FnYekR*autw}Di7%OfSROsO^L-*|nZBZv!3<;AAZPaCK>lot`Bb<5d6bB~v@DE>nm>)m>1bP^7Sz$BU znIdyftWY~1Lp{gff=^HnSUI;s+>gm89=X`Ty(k?54NX_Xag3px7@AEQDNJnAZbll% zL>-OJQUlo^^3AV3!~>uGGm73csTdG9hWKZ@c*BJ6ee<7q=u2Pb>tFwSuD*3YN1ix> zY~}dIL*HP0?-(Dy|6aCj9Y+rYc4m-sY$|320*y%9sE`l>DItmyY|BGM2B~imcPv!T zLaS#C=IXE%F`gFL=1sB5nxHvb!);jva{-OlS9t2%|BNLEJo)s0GFG1E#7`I4VeV%B zm1Den-%g%<X zZrrzrLYVQHKY5UTV?eJNV)}V@ly@=aO`t0f&PK~J1*QdQnu5&0(uuSb1BZUQgK2;v z75#35a-qn=*#@<95ka8QjhpP>I>X<5`mcHP(SPKrr+$g+z!TqngyxdZr|!R(=YIHo zK63l}I5e}DC!TzkC`?eP$#(5BW^()Jbv!+tXHWhYdN}0OBfsMCHTyVu>=oKe=XmOS-{FOy z{D_CY`Xz3<^?f||+;bc|`YL)R$T7;+k*hGHar|yb6ousNjS3k8q6jR@AqqmaIg|LR zi$7?h*$IJ4v80A0U}mbswt~i!kNqtJOJ{29CR%H6F+VrU^tj0*4?oKD&-{cVFTBM3 zuTS#WHy&Xr?(+Gse1+z6hv_Ys(G6lI@)fpM4-)$!y09_qnCPOGNd=m|u4OWkY%k5= zYB^qAIEs`KO$VtYLcy7nCwarkbKt70n3>tm+=bKp;JIg6UR>nv4}O?${oPmTG>15u z;G_54OJ~sMGhg@|0U7yGk1R_W_a>OiZDu?_$^60_NKeOfEn)#kFoGC#4J^yRz`==2 zT)*oe6Qeu$(b1<+UWnysG>1#9tadPzpxanuc)CZo*QUN)<0Busm*cO#Mtf4}TziPx@(PXBI=9|@6I-T6 zaqNV@`rKz(t<}gmIv>3C7XJ7n_i_BiV{9*M#|>SA{(vM4Y4`e=mb<=pzay?TfTTYh z;^+|tOQW}tFg-cLJ%|60@BiXo8Ct7oo=!9Fv89w_ad8R9u<&$^VpS(>G;bO zb16rT9^-ee-out%SJO|2jE#)*#J@aES#9F_=^IIU4i`ENTG5bhkRg@5zI&^StF&5I z`!tm_8y$>(8_TlkhCPge%^lZ$kRKfTHgmr@OXEE?wpC{6wF6|Lv2^Y{yJvPV|MqDv z-?fMF35Uw&-PBtKr{Avg`iVJ6O|H1?03ZJF&G_dG&YxbO74>O{9i#?+7_6rZ@}fbD zLDLoCFhoxvNhDb@X3+0rh&&?AaofQ=dEuph!;BPT`B4@x)EFyGVHIIzX_@_3?qRjj z=9#Bo!w+>cJH`~Fz7Kf5;7a= z{RWod61fqku!uSXlr5y%Y(4yfu_1!3lpvBt#c7UCepb~FlQmqFBH z(62)hpj1FNs3U~HkQT!zr9+CaJzV8s<6ves!=aDmSV*#Up35>^-Nv(B!c-Bf5NUO3 z^|~BA_LdfA7XfMO!O=#RglRyMu0N$*pGe)@_=yc>7YaNF!f-v#K|q>i) yaUKQ%m}uy!LaBGMEl?Z7r9*;PcdY;4&i?`BzMadw=@WDS0000w|QRt;f|Y2qs=BOqKyNr(Wz&$W1PAwrn0vQ z^O2UB>Cx%{C0FdD_ z%jxWLIwi>@m&KW+lu8t`F@9fL$Io6lxR_Y}NsU1ult27v)6*|@MV9-w=-r93HOuzK&4X?c36IkIWEqC-^jf9&0ckcCV+~yC~dPhEw+~|pDOW=-` zE6r|oMh}^IAw8dsafOQ$^8pWOE30q^)r)*?dNR3leSM(9oXnAlu^BAMjcfdGyw~;8 zqr2!IKe_RPQ~j0I4!hGn*th7bvzr_=$D#Tf$Hq1FoPv6Lr|m&~o2P=cLEffHM}_Pn z&o2oBi%V4@eT&Uc+|<>{g%hW4-qo?{_BMZ7ft(=PZHC$CTy2A&-m}&5QSYq3#^rL@ zFLsYnh)pE$#op=B+2v5Z@$UB3mxkuA4J=eQl{P!<7P}-mG|LNlNmPmgo>9`?3cA_s zcURf2N9I5L;3BZgwLv|rGa`ya=i_VZD(Q9Wn>ufd`9rQUpL1|xk}L9DAx~>4k>J@( zVOvL)PG`R|Fdb)b$Y*P^SnRgE;Ls)`qR2~pLKG~L*_K~#36%w{!M@oz z>b*+ML{Togc`BMq@O_TIP$2orBzq=Ma8fp`^UORV?&vN8oQcJ+N^z>P0eFl`6ADb zzSD>0Vw#m0M$0h_Q(GTo^pGoxm_?vwC@qV$Dx_mUO$l;Q!UQW=Z`J9|T8b3rqzMOI zD-n`Ua>cA@tF&s2018WpBPACy1(`K#C>8)nR#VNW_?0yJ#2YaC8d-x`t2LMiP02tN z2|X9jvLnTvZ7U}Hm zOok7QL6I;FrgxClI~Ra#HDDsbCK4t-X>3V30Z3m3bN|JSl5livDnpkFz6|F+6OO9@G3o%Tc9a` zEGIDlyGj`#YKON}Io)%^;dgq1x=rPVN|pC)V&devsi`Xoil$3z zU7PC6>q^QwIe&1VtM{!bIa%EEKzl=tePMBaA%e7Go>A;`vWyEn7%hxSrS^K=rV3>6 zlvn!7j0Sw*$Y=Qivu17S?UfcAV>>nxK5=|xX(Edd!=VH35Coa{T-VtS{#)FiR8OS&o6$F@|U_FyZ<(ZE*yBXZ{*rkeVa?l z5wG3OTu7ZaDvtpGu!X1TgVcPRhk-2 z7IQeCmt>s=8?>$4gX`++(mCevCzmI#M$6j*Wlf%va?{Q&)y-u!r$Hhb%S_s1UQ=<)F5_xL;7{KL6^Km-Uf`posao4iir z27jPGnm+OIh4@I!w;^Enn0KwP<|QUCtABsI`}(ONiIXdQB^}Kczti)ZKc7lRIjc$U zG+Vh$s#+cR?4zsmQGq6eTpt^EdmXhV)#c$iDNoEHdtICFzJ@^GV&drAJ@Mff0AjVY zE8tWyD3VsroxC}4dPvGCq^PKA_1&ADlhLR~C0VUBAVeelV5sbaBSWL%>3{xYLSVRm zy0W?co+fwq)mb?&@AyWrNXbWz^+hhv0ss)mB?LanN0RyQwb_{~(^yi7gh^51Q`}&G zHlO7)$#i^l0;pNkLvNB6IEQ-sjoz3ZI@>h&|% zfT3vy0Yw8Kpa20708j|Q1Q9|M42nV|c=n;@kB`RtzTExm>>44oYtPEtt2evbHA-%B zLDV!TOnNjuS6gC*fB#{bBMx84}AwUA{9vTRWnO_36sYBrl)J=I*9kr^4&o4m+sx|dq|0fE>A z5a-@|-aY4D#qWCZ0z^bvfzc8r4KW664myJ<00CNo(jX;7KpRC2>39B(0#HhjNw5-f z10sUfU=7F!7*N8aRU%UfnG&Qxkwc7-Bp|ndtO6lG05L%n31uK9cp=?PAOr`}x7_cU%9FI6TIiqQNVvJa8i7{e~VSj%gr4-lK*DO{Q zAq284!x+P&UJ_JdcfQB&&WuSpqAV;*Df%D?KC!9RwCe?>jyyd%;a~pgX98{jDGiYL z(ZBtW^NSXfZ=;Y3Or}6;jLDE%k=dNyJCwE{6+VL0iikiNjngY*BPlZI{0$&2VKNzUa?&CM1P8;g=a_qPuO(v|HmOgq8_g_R>%X-t$TEnKZ_|-sP)$D4|q>oJO zgl4nl&^9*#iZUb5!AIzNnD33bx~gecj<#NrPi81>&^kxw1*#|rQX`5nWF7vBe;g>Gjb;A(TGeJL_H9EVhEmmcZw{bFeNc1jvqh5 z$AHZZ^YI?b&2n3^W}8G}YbZ3d&q|hCkWwNgsHB06@BiQ(-hKD4_?y4|JMP~7 zm=8bv761Cff9CY!9G4tzh%DNU<)(sE;#7u0v#Kj}-!sVsBChFzW0V(+%M#~Xb`HiU zqq$tQSP4~A^Wta^DWA)b^HV015m^SllXP9rd++^{KYQmd*qcxIgKvG4KmPVN`OCk4 z7at=hR~OuQaG#%j@GI^-e!?aymP26Gb%@Z>H9d7*qmn>rfehf*j&)aa-CVOX-=Wwk z7#B18$4?og!1?C@`Oso)PTPajIW8oA^3$JERTVqaoTljz3i9!oAQDGqMt*q2!Rx=r zcSC|~#PP`)zrOohj!&MjSS)C(HEHmKuAysMf>Ri4K}1${$9z7ajh;eSC+D>69LrPDV`qjOndI=6idLP>9~~ z=)noU{OBV-Ie&r<9$|70`=M=x;e;E?NT#V1c5qemq}SF)_vgkG`gTXH0~<_Em`_8UxIdzJl1_o@1x zBs2$d;Fanr_x|I@_~AJY4IQ8)!fILq<06L;_|ISbH@|u3A&2`1xG1PQ$9ixyKo_sD0e1kTe5EgyVtO4J9b8J zzP zF(KlRT)BZXD(KcN%YMa0-*MgcG+kiP)LdF;NeW zGR!Ft5AiNi*EOfEW!zm7QY0^+X`e|)gor>WjrS3g6=<2!Wtu0OnieSMd#p~+c(Ayp z_8#pM+T{2lv01gWF)##2>?6u0T-PIVOI~IW0`>Kh)_F`ZMg`DW#?W^3Z9{1@LdOk< z#a7uPiI6~`2vHD}CT2PJF3)-I$wO8tF*!QK&Sq?U;Hs*L5hmprEe-2U%c^du7E8SA ziCsruRSZ?lP&dS;N4vE6`Gr+YFVSl`KKdf+sW$LMo(ye!U?nfzX!bVu4>) zB8NFah#2!sS>H1nfdy!7gAnm#bynNxR;r&m{e{P39TuHoL3$DE#@ zkrg9smUDi6&Dq5zeeW22r0)kj+s^A#B*jQf9+AKxF#=44=DOnQ{DR;-F-F?9p%*tL zQ%Vsd)LoA%3Y?V8Z{1?(J>znM^8rud!@GB=hmLmB(AN#?O-v3UV@Q(HwpqM;9!K&ThrR1t!vuHM3Q!NCy4vuKo zHMz|=obMrGqHZ=c$zvxIOkU7?&#G%#HVsZ0oK{4wK^u}WU<^@8f{+Ly$g+&07%>b3 zL-4rhQ27mqLIPtUN`c98GBe}oa7MSh=BlpPJ)H8%`ycRHvB&Sf{#CTr=rU(o95G0V zSZ=ma7de}=r{FyjjY1)mLTX8rf+#f!N$WhS%qS;gl868d!|=Idlqj}S0TO95_Fs9C zx4-i(%xJ{^?mnV(Spyg+=a+Xhoz6fnqu)&q}P#QPMz?#3V>agw!OZF*ZjjL)*59C`m3d(mDO` zIfp<(1yVU ztSPZYi82{UX*>d#z_Ar?g~Gd@F!ZdiuIW}4&2mX;ErYt@P&-C=Qd&5wTk6Y?*AiOJCcWz%4@8I@@XtDa%mQwo8}3sM$vE|5ZCXg7q; zkr_y?Wugsjvmk1XGoG+nv71TC2{zVsE0P`v)tuaOzU{fEbFu9i$@ z6`y|k8IR9SDGkha=Umh^KDVS%!S2x^_4y_Hw+q9Op4GAjAuJk*9+cy<4rz!aG%0xa;@;2iX;QY*fJiMbgd)P8k=Qk zt?@}wU0s5AjLn2hNve|unG)Uwl!}l7b=}gDZ?_EbnL!&sC4m7<-?OToVx}W(ax5>N zA~q}h$u;BYjQO-A7m+W2;U$JgpHWveT~{$bD3N~aI8%gjRuGu7sTX8f&hFtDTShJ) zJRmC#MN!~`V70g)nSK28B~uE9uA{rYqKOTIOH8v{jD1UK3>Wu*%NsARONZv|` zRAwwM&e;te!)8TXRP^mY@_|$>7={kY64g6iY-*xU6hbq#3OU-LJ3ogT`|fCE5?fCp zgg{$`caDk8L0X&|LFm~_4eesV&;R`wq6^OeiS6R(W|xG~;QaO-GRzdq?^knw?5s+!2i4RzX6hn&ll!fk^lez M07*qoM6N<$g66XC^Z)<= literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Class_feats (1).png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Class_feats (1).png new file mode 100644 index 0000000000000000000000000000000000000000..e1793967ad919923819ef5c009965195aab62297 GIT binary patch literal 2142 zcmV-k2%-0hP)g1R6opb)@ zd;p(RL;LRK7a#3*E@U~aRIYQJI^z{UTq_A6lDOONZ?<=usTkC243pVmJeB9HUa!y0 zOy^l|<-f0jN;Ny>RTNZ+_!jD{rqp{nI~v`+K#03fXsG{?cuiPXFtM8apy&&CORQ4^K>>+)Rch zCyr;jCEJ@QNR~bI$GuaF`A%D}YzoBE&waL7bgDD+bEUcYVsWCt3kLH{$D@Qan;Y-0 zoO|G_4@}M0HLM^1`|A6dX-JM8;*CjXYPRUzP`8RU&jxA1%(Oy|Wt3f`lx;Sn?LC#} z002R#S2q-9YW`EEIek4U%xGy%Sh?fLLxZ%{>1=LnoLxTmi>ID^_~A#+yyovyF2fwt zn6JBs8s*Y_jn^w?o)Jcr#Wg5WunfsE@nusWhhD&FcZag|S28+VD+NfEL8uc8i zH06dw8gWJoHY<5{twcR~>}cuusbLW5_Z|ZuyJ?QPbr1|AgtcN66N_tZVS55fD+vJGp##)>v0glY|OB(e;9j#Vx3336`zd~0{*jyv7P6gkN3<^|*M zkp&G7Agx8JlaZDQf*3()(A0Bq&0|%ImMr5S*25X)?CcDx&-C=u;G zW|-H?xK?d;QJPeNF3QI1*u!Bf=0ukmr7<*V-FMDNF`YB*!vS2(jrho~>)g9VJP(A1QThyNX~$ zn1K*QfOCJ?+wBS|IYTx>ms+E-%m~rASOSwHgczj-hY}1zUM)#$2xA>Z86pHJnGT1! z5C$V4FhK}ctg*}(vA{9`A<)_@Rd2twW}E1mGVAok_Qf590HhLmMk(e7<_vodk7F?g zt4!S^5CW|c0)%OjAgT6;9UYygR|5`0_4Yd(aXJ7X2x)^eZZgYc)gj4UT947D=`=aZU91n5pXIHga{!*3FFK#nB!W`p_+WJ{+D4% z+{y*y5(&*UP(n09zz8fHsoj3>-L(nxO0c;pxa&qB1eAtWH{UsTM#~}PHsc024X;w6 zleP9h-s{YjVr79M`PZq3G3X&KPVo9LCyAr8$U#7ykVEtBaA4;Mye1!XG~I#_RvNB5Y|5 z-d)p28VCUVP@jA)JALMDYDU~~t;z(hRVAjj&BkCFS)tGgSpB}gyz1{ivQ!`xK^T8T zU&M(%`I;nH?;nLq!G-lu>y+6REtRG1$TW>U)Qtev@e^-#I$J@|@AQ<`006cHrGmux zW5&B+!)>48o^yHNw%R&O2{A4078EAJAC-&d7;HEqzj^NBGfyA)_f~BiBLoP6W6G8D z{%-qYRB{x-gI_uPg}YsZKm+Wyg&#{~If~mdlW9LN82Zpz-~^F+`QO2>eto__NC5yL zsMnl{YVqJ|zLGU}VXueoyLYl+gVwM&(ESi;wKIR#fhSiI~Y{RQp2||#haxls@<3i&kQ==3PHZ^|lE_+|)_Pc{oAP`;H zh_b8LHO=k#rW+AcT+)#akwn3Mz~gz6y<8--veB z)+UQtqmG1-{-7Tv(I^x>KiduD&TcTK`fKa`|JNaa7im@!5Ru7MB;p^_wTZVwHEluH(+_y<2a0iR_1A6^1d U&%2Vc`2YX_07*qoM6N<$g8bwJ!2kdN literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Class_feats.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Class_feats.png new file mode 100644 index 0000000000000000000000000000000000000000..e1793967ad919923819ef5c009965195aab62297 GIT binary patch literal 2142 zcmV-k2%-0hP)g1R6opb)@ zd;p(RL;LRK7a#3*E@U~aRIYQJI^z{UTq_A6lDOONZ?<=usTkC243pVmJeB9HUa!y0 zOy^l|<-f0jN;Ny>RTNZ+_!jD{rqp{nI~v`+K#03fXsG{?cuiPXFtM8apy&&CORQ4^K>>+)Rch zCyr;jCEJ@QNR~bI$GuaF`A%D}YzoBE&waL7bgDD+bEUcYVsWCt3kLH{$D@Qan;Y-0 zoO|G_4@}M0HLM^1`|A6dX-JM8;*CjXYPRUzP`8RU&jxA1%(Oy|Wt3f`lx;Sn?LC#} z002R#S2q-9YW`EEIek4U%xGy%Sh?fLLxZ%{>1=LnoLxTmi>ID^_~A#+yyovyF2fwt zn6JBs8s*Y_jn^w?o)Jcr#Wg5WunfsE@nusWhhD&FcZag|S28+VD+NfEL8uc8i zH06dw8gWJoHY<5{twcR~>}cuusbLW5_Z|ZuyJ?QPbr1|AgtcN66N_tZVS55fD+vJGp##)>v0glY|OB(e;9j#Vx3336`zd~0{*jyv7P6gkN3<^|*M zkp&G7Agx8JlaZDQf*3()(A0Bq&0|%ImMr5S*25X)?CcDx&-C=u;G zW|-H?xK?d;QJPeNF3QI1*u!Bf=0ukmr7<*V-FMDNF`YB*!vS2(jrho~>)g9VJP(A1QThyNX~$ zn1K*QfOCJ?+wBS|IYTx>ms+E-%m~rASOSwHgczj-hY}1zUM)#$2xA>Z86pHJnGT1! z5C$V4FhK}ctg*}(vA{9`A<)_@Rd2twW}E1mGVAok_Qf590HhLmMk(e7<_vodk7F?g zt4!S^5CW|c0)%OjAgT6;9UYygR|5`0_4Yd(aXJ7X2x)^eZZgYc)gj4UT947D=`=aZU91n5pXIHga{!*3FFK#nB!W`p_+WJ{+D4% z+{y*y5(&*UP(n09zz8fHsoj3>-L(nxO0c;pxa&qB1eAtWH{UsTM#~}PHsc024X;w6 zleP9h-s{YjVr79M`PZq3G3X&KPVo9LCyAr8$U#7ykVEtBaA4;Mye1!XG~I#_RvNB5Y|5 z-d)p28VCUVP@jA)JALMDYDU~~t;z(hRVAjj&BkCFS)tGgSpB}gyz1{ivQ!`xK^T8T zU&M(%`I;nH?;nLq!G-lu>y+6REtRG1$TW>U)Qtev@e^-#I$J@|@AQ<`006cHrGmux zW5&B+!)>48o^yHNw%R&O2{A4078EAJAC-&d7;HEqzj^NBGfyA)_f~BiBLoP6W6G8D z{%-qYRB{x-gI_uPg}YsZKm+Wyg&#{~If~mdlW9LN82Zpz-~^F+`QO2>eto__NC5yL zsMnl{YVqJ|zLGU}VXueoyLYl+gVwM&(ESi;wKIR#fhSiI~Y{RQp2||#haxls@<3i&kQ==3PHZ^|lE_+|)_Pc{oAP`;H zh_b8LHO=k#rW+AcT+)#akwn3Mz~gz6y<8--veB z)+UQtqmG1-{-7Tv(I^x>KiduD&TcTK`fKa`|JNaa7im@!5Ru7MB;p^_wTZVwHEluH(+_y<2a0iR_1A6^1d U&%2Vc`2YX_07*qoM6N<$g8bwJ!2kdN literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Construct_Essence.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Construct_Essence.png new file mode 100644 index 0000000000000000000000000000000000000000..347a2919a4c43ad46bb824dd2ee004fd63a6653a GIT binary patch literal 3210 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Embolden_Spell.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Embolden_Spell.png new file mode 100644 index 0000000000000000000000000000000000000000..85cbad4e8bd418f3daed27c8470773aa46b8d941 GIT binary patch literal 3138 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Destiny_feats.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Destiny_feats.png new file mode 100644 index 0000000000000000000000000000000000000000..f334e0d36498b5813187d650b90dd2c09c39d059 GIT binary patch literal 2757 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 JPDHLkV1h7kMF#)? literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Reflexes.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Reflexes.png new file mode 100644 index 0000000000000000000000000000000000000000..420361556f6c595fb1592e67bbd5a66e3366a4bc GIT binary patch literal 2530 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Reputation.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_Reputation.png new file mode 100644 index 0000000000000000000000000000000000000000..465f4030a1a147e241204089ae620a1657828bd7 GIT binary patch literal 2608 zcmV-03eWY4P)ScaZ0SvObaccEcqtl)22esmmOzqCNJ0{l&2F-{bIzXI z`@a3q={P#r@%i%1^L+UIKK}m@e8VhVQu>>pZ8#erXjc3Xdn3Fzv^5$8s3T zA;bXouL1x;!~-M(08bw8ICt^mUp@5ERDAYpH2k%DQFGny?-jP;NT5=2*W4uf>kye> zxh{knoRzp7Ir8J|N2ed@)o9 zMG@$|6kD8kF`vJUTElkoP0WS(f(NNJLemEX|4x8pVD&I_VEh6RTzp^e)WT-yD!dUu zuA+8DqW9(NHmpB-ydT|r-@+>fPJ4=xAajCSM!e`4Q&f#Y-pl(|BDsdB-S*sJB-dkQ zJYr^MUnn@^M$$4H8e$ zaNG+e%)2Gd>*Bn5-ljXh7|hJ@-o0AqdpV4$9$00SK6ki>It#oc)4@!sL>cRhdp z{2(;+JYIO|h4!qtqT_#H6NbCEj(FZq7)xNKhN?#Ehe-sF}U8K0G_8 zQ3ek8Pp+>FZmcQj>z0OO>=xz(i~1vOCi~e;)1K&7IdEI=Md_iNQM=@_1bFx9G6WceF`MhLlEEb z$=kZa1_xqy-o8ok`fZB$Jp9HO&r=zC5oDNSb{yhDMqo1Xx+=IieF|ejEz8Elv8GPH z`q!T}EPW)KRX-VywdA|CgJ&{8`Qf%gfb*XI-ILvCSKrh)!Wk}$;biRU(Mbhpyu0P+7fY0M%v}`#N=X#Kr4`LdKVKvfnXOjIpDuvNy%M zES^#=Lw>xv=>9#wz`%A!-*p^=8N{*dM1SU8qwycFp6ria!~lR(1JS(lqPEtG87(|I zJcf&kO6OHy==~Hy$z}n`TgGvc+vRlyiWOhT)N^J=#lQhM`>A`IckFxs4cF@EZZ;Py#MzRMe=mce0Jl6;H;z{x(P&?CB13GL>Vg6c(Uje!H^M8BQNT3OXj zW#fIR{yb&hdzS_xBbV<*k=|(i71c|Y%cHS;NtA%D5`;NU0+8vMICQLZ{6cIxYTM?< zC7zbHh1tkaN7KxVZfA}7IpaO9_{G;UeP{dsU$Z+M8Ln(@sW11848{o-981g0jb)Ql zb}p-`34pOXFQ9l~Y9h9IYZFN))5DW?#+)0oB69Wq4^wBqO23Q%0MOSJZCDU$sg^oA zyE1c^3@yV6K9?_F@rET{fSeF?(a1>Zwl+-)H_m;2CKIPam5uuj#v_sbZ`-Z`0Jr?$ ziZyjtm$$kcZE`jTE3p_KimUTNUPKC1GRg6ZFQBIhE(bFcsTcOX9T`Ypmh&I`A1Qmu S2Y3en0000*bb z&pF2zzA#A9-yiV#y!-w>2*KrV%jVXnAKiUEKXzp}hKMmN8_A$l&D7M@StYThzA(RO zW_oOGH?S4t)*t)U2ic|aWjW}wg6&(@JoMnFU&mA&fx? ztx4LmS-?>8U$+2V5X<0$fR!Qj<>yKn0`Xdln{bv-PHV)BlS>$dl%XR0%L z2nVAi5W!lQ^sGxLs)RJ=NGvlt{K&mKPaj{d)vf;{7#K`{{m#_e(zqRCk%$tBYLT$q z-?nN~`=+t-nLrR3QEV6_7FNErdH1Aw2`M~a$SeuxCg#6!%^fGsP1G&>69ofTulwR7 z>9J(CZ7|G$h9gSMz_A!+P}$M3s}ARpWJSX$s6%5+-qNutQyr0Xq3c);VbVfQ&yRff zwjJ+%m^Z7|WdvKdcHFgR-BIt9=;Yf{J-)CsnHm~IRiVpnf8&P6uvPQsHOV(r(HK^H z8`6{I4>b)G84(52$@WmYw*TrnGof`#kYI$}>s$IA zo)0NBrtyddZ4osj#e`UpiK9zA-PGKqZ(Xb(3rL`;V5rK@mTMR3gw^aFd}sWJPi*+- zfs$!D0Du8t%a+bvU+H^0I;{6AfdGjFFy}QxC!bw?)7GcVuT%P%*tZm0*cLMBRu`5n-D#mNGUHq^?-Q1f+>S@@^jQMuXE^`5{ zE9@3HF*5b+-FF^2F;1TO!8Q9Ur=2JmI*JF?zF1RO!Zan{sN4|?1nYEK0FS86 z80kRDoU^!gg)b^KZ!WAwdLy6b!aZ9&A{a0(ESGT=SK{#I(a~o=bF0+Tnkr>QjANBx z#5nb9+gk_b%R>Zv6)V@Q6~g4!_3^7bF%!VoA<)C5kdkvUTIa)JcZ}({2ZTCr?K32a zYs6wS8ibld-6g6f#G>v>R(2MHz(U9%;tGkXa#(6iH*5w`OUQR&r20IUrN4ElZ73rW zN-kC32f)q74o6IBs3{=r@?oh-Psfy1KKFB>(n&EryX>kOl2xS1T)LDuxGxA28j-pa z(QBKpQ1Au-*J2|x=C8)*Mqhg|cX+?;d*IXeJO?BlaVmoG_X&n=yY#OQ>$3sj z>ew)_CSwNX+NS>9yV6;6?%4jinHL}dMhHuoGi=ucHHGg9jF3|iAb`1G=0vhz{`S)Y z4}R`GLlrNM9U7i4*d_|wcry=6G@E1~I2GIzHCHTF%z$*hBii-T@BRJ@_dfOJfvLSu zE?6bb83F-8hfgwd^!H{7_p_2$9b1Intg!fPk8vu4#nR0t**fwD{`Nv{bH zdsO%gF)Avizl7?7&*6qY?&x`b{r!JGaqzj5e=Spo0RTb>K>T|H1Q*SH^5YNR(BHCW z$=Y{%<}X>(a&69hA*c`(q!6xZYq4VX3lPA7a_}fn21Sc66zdn4N9XNVBJ!?=77bw} zhlqp_00$fJUDP6!YQhzgPd7=h2kKMrNqwVi4Xq>J_8jt0Dtr;JkW zA!nISbWBQ}T7+{!eeSv-m>dZxP2p(Kc|(%mu}8Nt?osAzYA6+5o3D%)s@YUL71RQ` z(i|bECB8vL?S=Z0Sg=z?8&-wPqBTaigfvtNZtM+Rm@qvbm=KymJmxxX zDI83v^fh&wtJ1?wp*wWkXv9Ai551Mr_HgV5ls^d&QF4>ZCq1N;?0G{mJg%RcE-jaA zYJ*RK1#xwJg=k)7u&qn&sxOx)LV^ievMVd~l~g!3QTX6U=B@ccR@LWxGI?g|_2JnI zvG_{Gd3R{yc&;=TkK(L(_RRFe*zy9#oQc56@tOIY>DZ#BJ-DUV|DzutC8OgjYxQ(n zOIq#9EoB|be1c*7>b|9F>Dbt4u3DD}>P$8|wl#EV#_^#k5~hMqF0OD;qDI&g@bECA%pt<%u3aA7)KD+QjRaCmdm-SGheh93$<0Ng4Y#Szxcw% zOlJB&KY8TLWaq%fO>!jCuar&i#Q1Ef?Ak8(1q^nza_~=ITCUq%aLEX$Ma#^VoKlUN zwnzjLliB>}Qn^s^OEtbKrKU42dtaZ(T%7#xsyKUMJf7_BUJOh(&Rw`zw;b-+OjqS? zy`6viaI{dNo`*Ri$(Wum+VeT9V)1gFm0TA<9~#T96xo{Y;0`PLyO#^2=Q5Y?qT#cd zj;_^>1o1Wg>?PNBd0$WCLcMxsxa_*z_Q9tR3ahi(`a+ggEmp4j%S9K1y0Bd8+89b? zlKWn$jtr0fud*8&zSPolWkWTo^p)o(z25GIw~o!%s;urJ%i@(PM+TXlcb9T*wa&^W zFIB1OntgqZ8_qQxI8ZwOQTpZEbmVj<-I+>@q_ojFb$-PvFzy4T$aaNoixTr!^1fwp zmxAL9*Ma6Hq)$ literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_feats.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Epic_feats.png new file mode 100644 index 0000000000000000000000000000000000000000..c747fbe8b3e79c3d46a965039fd2725defa18750 GIT binary patch literal 2848 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Bladeforged.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Bladeforged.png new file mode 100644 index 0000000000000000000000000000000000000000..d1284a58e93c91aa7df3551e13a9ceeaa5f28dad GIT binary patch literal 2769 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 XyV&1|!zD~E00000NkvXXu0mjfz~e$` literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Bulwark_Of_Defense.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Bulwark_Of_Defense.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc647c2b05211d690615e72dd4515910c749d70 GIT binary patch literal 2116 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 Ef<~I7*8l(j literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Composite_Plating.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Composite_Plating.png new file mode 100644 index 0000000000000000000000000000000000000000..f357ef7ef1e18f7a93f0dabe3cd605472dac1f92 GIT binary patch literal 2539 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 S0VjU|0000 z6YzLAT9DcLY;}2lxn5ti?VO^pm6|qByW7p~E~0<(_ke%={SW{Ar~j1d4gl`p-~b`U zFh6CcnnwgIQv&qMch1`;_QNr9n6Kx^!Oc`{8uKuv-F8T4aU7PbC0I?V=2WVxxv5(%)zw1a z#k$*WjsSo}#Ms7}AR-g0xtcXi6GH%Eb@Q4{;q2n{{BogVKc-aG8KLAf^clc&RxQ;D zV+esz0nIHSEKl10SZb+E+=Wg!k~;u^#3(Vkfi!_wYSnqiZS;QoRC9J_&6?eyOr{>2 zrnrr@MuZ@Qh=7OyfG!AKgM9(h3N%W)3=Y6d^VJFv-GI;yA%@V+;+Xbr5GG#4u*v1U z_53hStFCQhyjag&_0!wUo9AOIL`aC_>SoS_O+zW0n~N|BQ|LMospjTTt0Evbe7SCa z^`nnw;+xHO+0eG1P8TgRH6eyTfkn-~b$|JW?e(ko zZa3RnD186PFb@#hp{``AiKPlV$axu%LXjL;nApmedbuX!&pUi*KHoM~_$bb9d z775(}(U^$QL%Wc1svmst@@_jIhd5tg=n(NZq>n!Q&i8-tJ>Oj`xDl`jAvmG|Qk+RU zR|lyEW6?fE9$$W)ulu^$ZV^?1AV}8)B9v*=cD`zsD{dAadkwG4bSI`(9EkUlbM>k?)G=GTJZCpixRp! zU`+{`+_V+1)8K#{q7`-k16Ke;;?S@(qFBs5YK=AZS@JY*+pcL3<3Sh=iCo8V6ba;r zNT?;v7AF!qVDzRe&#q9S)#S(qP|Y0xNkThEZp<;~ei(+svG0dzn9QLSrbXNJ=){zY zx)%eKQozlu)KVdjyWwyore1k-`}t-$n%BS#;O5|Nh7hSS=V6?lHc$Qj*pGQgIh$yV zgs^CvJ2O)SE&EAN)~%%E*Vi{GC%{mum6EAKaIQJuJnVzOY}Pda+|<;KRHri4^1R*O z-E8llw}*Z-&8D@O2~9*%jN_e-J6 zwVo|x9?Sq7H4RTUyZpt&{&~AUjuV@Qh+Y9fvl$|_p?P?C`tEz@uh;W7tYn(>_U1aY zi?BT75Zk7uAQLyY+w$$J_U8Wa&2@hFwENDx>$VBS>~1rBd~+OCuy}+{(e}F|(KKIE zbvD%~Bt&8WM7gS1EpA?>o(V(Of-7W*X4ju@aX$;4Sjv0I&n;bDu1d}i_fNVXahkTO z$1Zk2b$8rtp08f)jiUjfX$)Mo6r|_vtsM3vfTNq0-lzsZ1atG6v|YElh>2`-|9IBP zt9MUQ#&IaD_1O297w1jOo%-Tx?eDCW=wV-TQ352EVz5gUh~zL9cXt3V=c+D*h{HI% zeE-GIKKjPf?vQ|!`l5;RZm~TiA$@*luA0?`toxyiB~^7W zSNB|N69m`T;17N9nDwFDN z%)?X=+`vmNjMBAjN||LTh;Vwc>~M;$SWz;4acC$Tdt9s22TO#6P?52e%!07O))X12mOn>8fTzW?%45Xmcn3p2O^ zF^BNaPp`L!Y3Nf<6_5kt<*Ms~Ok*CWGEQ|E@-XEomsDyliVlQc-43}XGbVH-GL$G3 zgwY)l(UISp);53rIC2hzW=U z0fCUT8VMIf4@~R^>aJ!$rp{ow>c^kmB?WZICEwlc(p1itvy-!xzO~P+sHIZV+xY_) zhk`5;B6HJ9$yqEXhB<}StpK2d8Z~OgKxQ5M<BP(TB4CT0|21Sq9Q8bBDQtP1GHAQ6h1ffIvy8pnV9_vY0*t1myh-#+h; zsis`i!4V}gGN)X%>i>Ty03ZcMGiPB02M5U>c2B!96?HTw6mbX7t~onV*EMhMH(xy- zhwF#q<1R#+iuPG6kt~|fbyKlwZt7~_ZioyHA##XpRdtx-uYd9Co3CF-k6z1SH3Q;i zHa}U;Qrd5}chhv3a!SeE1Vx5nbQ_R8Ms5RWEkja5YGP*&)qUQCPG;;a8KweXefj)9 X7?A>0x%n^e00000NkvXXu0mjfj};-z literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Empower_Healing_Spell.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Empower_Healing_Spell.png new file mode 100644 index 0000000000000000000000000000000000000000..60458e72679babd4c3b8295a540c6fd8b2e697eb GIT binary patch literal 2037 zcmV%x~+WO{hG|N6GJ_^}fO6{ut~WST~~;yV@3b%S_J7eEVtb-^WOsPV*!;cPZ* znr?Bp**q^0PQVc@bA}o z@<|RHP`Uj7HMi}`^hBE;j-5EOZYsgPewmz-`}Y#~^!<`mYgu-qTDnr*avQxnL2>_H zCZ}XyzoZgphAAp_>vd}{{=Cw4D@0XADYEBMZ3e0>4UO{5ac z>t^d_QA(66*R7Dx@AK&X+v~0|l?=_&xaV%!zKfTi=Lf4*c7hw0bNQu+!gC1%1QzsQ znp9nmd`jPLwSPa49+0R0#+Hq;W4Ahet4vze!8$vVr@!91QF{B>xrKXnDB#K~IJcX5 z?Lt7{K>!Lsgiw@@Cg#mizki(XEmhm^k?p(CM7Hgk;gv1B4tBaM`>yo%(broe0Ztju zCgh_B`0i;i9n+;+pqyu37at6Fwi<*X6kvYv$2ds1D{he(gnsXP@Vl7udY* zw5#w@6_iD>M5zR-2Gew!)2K44idU`aZr-LYyI7umo>+ouH%vDzsDqVlcX~3gN6=Y% zL*1o26~v{KNl2RWNllorxU%_pyEhKfRk` z3CkLT4 z;DSk@F*ZRYV18Ue37T4v1mQIE=do?CI`}d_yoLTjhK{^b2Qv)ObrvsT@OLPME;OaE zTx^F$-E^LZ8l{k>N5Lo*zy%#W#F7}Qfp9Zkfm9fiob#U}k za7iUubV0rAk7P@+7}+sCI-=4Ir~rTfU9fG)K_2p8fdeHdpE3=D2{Bv^0ld2~9e@F9QzeDFX{&DBhp*OUV^4Z~oXqU)+I>)WpgE?)#__O5^nSbf!Td20DJ2Ll&M+NW(87I?*U*m{5e# zan79&Ciw!59gE@U49pJ#-{;_)eEU)c9>VdkZ0st!&fCMhmP2!xDsWR9oh_h)2L`^u zOUKFCm_@W0>1MP5%fa<3o02Mo12WxAI1Aq9F8W@zD zmdl+R)mP5JfWSq3QX$&o_+g^Wa1Nxv2NOe~S0+#>^4orHThFSW@UK@vYCd-HLV7w#CK+K&eoemGx^4&-xAOwjay0Pso+a6sJ;uphK8Mh9QeX*;)t!nn80Kqk>eY zAJpW9rv#sMzo^+OiPpJ(rXg~w&0_gdmMmrG)|qa?3_%DtMQGmo~QTQh}1~ySVfcS+z!eIKd$1yZguFeJoOijkH{l~yz~$C-Vr>X z#taQflwxX%$&>g#9qp`LE9>q8m+P

1Wietv)N_HJDXCLr47dGpeDHJ@?9w?qJPY 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≠Xej z!Jh3jP~=h`u8W;z4CX1HM>oN1I9!E-km zOce(?6G;F+f@2|!UG?H=P}Pol8x{#?YxaR6CN*XZ&jzjuX(`e@&N zKDeJBJBTBn;Jdlo1wx?BofZ@cOC{0(3)u1R3gZVOc>FE;?OASn*tbW?V2UDYHR^OQ zH_y{^{JS$$Dxy%}o*v#YLc2z&x5|zJrwnL7iC{962NRy^(=>6Bue{HzZS<6R-(HY{ zD9C+a&*b$RY#C{}L{34d8iIfq7BO`L6PL)gC}j#FaFUu9mCM92Gf}aCcAMQUY#WL| zZ!eDwv!>A_2Pg{p)@@#HBA;h@?=Rpk=6Z3b!!n|BNhC4igcHe@$vKPi4i}0L3S>ki zK*YAqc^jqL82Bv{R0lEcU0}>=L*19k)3Vi4~m-29Z#1Tg! zIzD*;ns>O-NHxKhqgvKl1{)qK_V*oHYxz->3=bAeQ&UyJj7~R_GS27pFiL!1x}GeT ztZp|f70oo|rDa#s#7a8~JY7|VAkr;SHF;OXHVw7a3W89&o(#hnAM*Auglj-+yDOC~ P00000NkvXXu0mjfB8x?e literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Mental_Toughness.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Mental_Toughness.png new file mode 100644 index 0000000000000000000000000000000000000000..ec79bebe9a3fcbd9bf8ccd06643ac060c86a9ed1 GIT binary patch literal 2972 zcmV;N3uE+&P)pF0drDELIK&yEPnt13qeUlK~#9!l~;LGRQDA|5MmZ<;$YlZ1lfh) z7BomqXtOk0*9NsQ(WIKRB&pd<^+b&eL=@TAVI3G4m|asEUq8S7PGVL4kprXZz3gyIY+9`q0nM@26=IVc&9@$SKq84~57(DMillCRANe zqOn*9A+7wAE$D1=pfXQ^vU6R?KP7=oV8yv(LKJ4SKpYo`@|b7@@py;)0|I9KAOMv4 zs_o%n-*P|hOh^Dfy9*^5ZOA<#Mrl?X8Y|W4lo}zHbfdbm32LPUlEz-hT6@q?qlCQ9 zirnK8G?wX6o3CUb>SAMW1qUwJN#DMolKVFx{}J3jVs~`p&35W}&m)hZ^ehD|?}MOB zf$DM@nq^%u+KsTeEpU0QbTwgk+zIzE{p~Wr;<7+*9z?T13%O_zf?_4=3RH|YRWULD z2wSvhKY@7I*VlK}_W=0%`UPzb51HnI_a-Kyu1JmQLIp%MY8b48Fgwi{u$W*UvZJ$0 z2dm2pgUw6Y0k3Y>tXcQ?Yz+(fJNK}gN+jW% zh|Qg75vi%HcDP5K=xEcSwbqIJ4?56TXo99=6iT_1%5SAoJLnxR40byPwIeY0Poln{ zAMMpcXeu$Gt;q0CxUq6~_HK@*~N@U5HsR`p(z=vadb(tKU^=|Y^$Iz$n!r`@} zPj5iG*o3OHT55}uvbE#WFF&S$S6N`T{&bbr^d0xp>>Z2C4Q=N*TFM=eR$GaX7Dm{% zW+NKPbf_)p0mrxE=qUJb7Fv?sg6fQ#B^=2`#F`cOdBb6fEvB0$`)I8K7w63X_|W3as^7^Md*4)DB~&W{UvnuNRgJd9cRuQC8^b+t+gI9X)TJ2vhc?12XNrv zJ`N}YadC<&AQ&W7Xdtf9lRvl^uUaL85SI2qO8}(tw*ge<(s0RBLsZ{`i7O+-Y8S-i zM({ILBqcZNtI4K8It3Bb7NN2t52YpNarnJAuw(mX{A$lm96fRf2M@l4dQk-f@cCC) zq18H3k)=dwW+!pVh_Oj8RJ~?4zy?>XLJiFcAC8R$ABjJ%RM}S5Q=V7PU2nc>nO5*sx(8)~|n*t<=;Myz};NaVGQF3^|QJbYcJ1DQSE;y0#viUQ-WY6dvQ6p>Nc97JvpG`c}ZNo~E~ae$LU*##L2PD|0+t|HHOQw!*a zLI;}3T6;QNa1NQVY4bC9`Q<%$?6I|&KmQ?wg@xdWCz25r6@j^P=OQ#T7)eR1v2WiV zYNHoZpG`rl7$z>6(bqLh74X99ra{)uY#9dP0ILA!f_Y~|U^Adj4+r`8$fXe|);&gn&Cff?0#I%xY`u({nB zusWfXx*@AGF%n)N4`No_EYP5{!GV?vE98v>OnL@8^-f{~n{c_^c;~%$apd>E!@F;% zv*4>&Co;$4woHO*8R{#Ps4wnAcZUV;5f`ap4EkPbg~W-h_r*wm^C;8#rcF;%(6v;BP*(cD zKpuBLQ-K4o{RaH}R^%O*le87+>vJ**>Ma(uiUuL8r778H0+;x?NUFfj;3aHJ?Mh05 zq;il=KN>#J{>MbgGNg;7(3P6JHOd%*kBL zHS8f-juJ13&Gj0j?Ro*v|8gtWb815z;^Lw?4$Nf#?9Vr$_#+7y# z+=`gb+xERp={Fi*Kg87o%nK^{Vr<*Kh0B-)zW3fapgkR13l~1jl=0lAXOUk}LA~!shuF*|!4561 zb?ZpF0drDELIK&yEPnt13D-$PK~#9!l~-v{lvfsQMV$P}SQBR|Y8hw7 zEk;pMP(c=zMMRcvgl4B{*%3q#6fpr26;MFgk)^T4Zs=~BT^89vU|7W^u83RIaf!>s zA2T(hIdl6}byp}PiCuN-ecyW&_q=oOJ@0*-88fsD0B}AAEiJ78zSAnSmIWg1lquRp zTy%&%ktq#ES@mw@rwAdgutsTT915jA7)dlksnQ>%atD;2wZ!Z{e?ByA+O&lLI8$ND zh3V6$+ql}T{m@kti;R;oa1`3YEno+neYx-ma)NuHBO6`)9oRgLY)$>1l^Y6qRV==o z{rS;PCO|tkw&xqX6BP&`%0GgTeZGi@-Gzfmk%>j&GBr*z|Uh87pq`E0qb+C~Y(U3w6MLso{j3>FB+*b7@iA}S7pYoW)Bo^M z0@^dRy_|R}er{@{+(}d5xPBGfjP>AdtWVH`z5YsUTD};59z3-4)?)DHMTSdb|G@C= zUNzYJE3lSae&w^ZgFpOJIuCVdO52Gru_v?=?G2DE7Su_9r!x5B- z;?dY=j`?$EDYUg`%why6c!qIlPE~fFLwC#E~!o z0vxU2Xuc5@)nbglxPkjW-kN|1uWmD_pC7)y!*KWcbw)&IB71jz~e@Wb1? zc>J&NUt+@Clb`OX!ARVGdX=R^QuHmVOTsW`&Yw^$6Ok^N@3R4;3IIz*10OdJ?0(atO8>!J6tJ z@lYfNu5_>fwDT#+JbiaxO@I|CbqBS00@8AX;Iv7saWpXs0vl8GwVb8hZNt@p3Ji5h zvB%jOECqyJTysb=V-XGo>FxPE_F6>I{C1XEz_+4mX+WHm{UUGxN}Je3a-IaXF?JZz~0Z1tAI zM)zwtZCDK#!!=9+Z<3z^v-wcxZ5Y4agib0*Z%Tz7sbH_K0~;D$sBM$tBT-%>bsQ4&rJk(qb@9$FN7`a%we4lcC1?ot||x-ON{ct zovY_rjl6v^h*U}kPj3a0UByW94RzsSx*oB6{ZW{I0?i$jnpz+ti~#uuOF^qL3Fq^6 zfFsNEW1d~puD~d<>*+s_8uItJP)}ItEC%0b4bl&VqKmrX(O4S`u7>hVG8{=6zQJmi zD&ZDG*0SCfM)0Io-5=tO?2IEg-&m&d1x8@>Za=y%HKSg69MU2?N`cr#r2r#9i|h{{ zzom+OIEt(>KIuh_AD^k@X|fK1)|=oY`3Xp|KkWdVPBH9Uz#86DSr zN}HR}S_Et}MWB@_cG+w}04bm%;!cVMo+Q&Aj+LRmIT0afTP2{5#DR3YI&Fb2EJrX*2SastjqYnW^L zlV$I9+(xj*uI*dkZ)pqxDd9wcoh^(J7U+o+sj+BpN8i%6vSak|MiU6(|Q^ALJ9LBT6Zd-GNkkphCrp!J+S4hYw+WO8jD{hn@N4ne$ zoPp**O&3rNFap%G6MVd>Rf(LmSl0hj5MZ^y)7PQhZa|2=nW_$0DguarszXknI;1{~ zm=V>K9z#W&GdOv&2vn74Fa^ja838)ECU`k3#+2_+E6ZfTra}mr6rb`N!m}U}76{%> zHDGDPQV{H7hwi~96#;gGk|~ekOr9k;E)Kd-mU^JAA)giDy_Yvt3aEXZ5qR+9ZIqN` zAu~A|Pw#h5Nuak`3@#ayCslip?G^-)3PLkOc#tZ5B2ivh%v3HT50Dk_rsMdJ>;^m( zwA~c4ia2z)i&O+ADWH1p9d1T68Ow#LykAp+S#>Ze;I(N3J3)mO8{tZXc;pjBMQLbI zq$2%v7#1&>{U5sedvj*cj~-;sZibMOHTHI&n?OKakYi7;A?a`=Qscv!0Zm1qxiSa- zwEG0IA^x`D%MTPYL~|$9q91+1R0)DNp}SIuo-V28 zibaZO#)=v-{P;HLY?$DT?0gvNE@ii<*U$TLfZXvws1R8v;~`fRU?;U?XLC9fSsqxp zIGG-Zj%G1CKGjOpw#c#5)ebo+F?jW22$_kIIF)`_ zwZ_oYU4?Use57X{K|@_GDpR@mddd9vv~&MY`Z%Sp=1_O1)&G-I-Y%TaXGbVqBp8Y% zS;)&ggv!bSBq#2Nth!hgT)obWrn34J8Wm1hzG$v$=TV>db*xb$(a}>MnekyzH0?)O zC0$(0JkcrpF0drDELIK&yEPnt13rk5vK~#9!l~;L8ly@2)IRxZB1i6plhT$9- zZg4mT28a8;hD#{Y8DK$0K&qgOh#(?}+{k^ZNCl*50b8x<*6z{m?shk6HrYQmX*T<3 z)1>LM@Au2PNz>G{ll<~c=KFr{`@GNdKJV`v9su6YElo|$%(ACq$%-nh08%U!9biSl}f}a9l z)T`afO7q0dHfcBCgXPUx$SaFrWn;+&Aqn(ZP)#jO4g^~QUk~IJrXsH>6`tO%&^)Ti zswWT(v;_e$F*OF?#Q`2}j>yUOg|_z5fAe^}vL68;&FbSMzBrt&z{*@VE?hnf8#`-O ziHjQ_PR@?7vbKgHfjCM@xI|i7TF}$e1E21>c{p>;$(|<(p`)WsjOkH77{cAt6`le& z95*+`%)}*Zzlep6r6I@SoSNDZQ_@_$I_;F#_xCpIu{76%^X-kS0@9m;8nXb=;&9kI z+Q7)zkN_Oz7Gs0-X8oW|328A_=yxWUfq?;x2!JRo0Me9rV#tl2)yDG3IZOw zuM2C^-N49zfv`AXhS>N>l%6g?R&ELbviN_O>rhh~P_-llt6Yy*vnAJv>)}#`PH>$z=J+r*laR!1&@2ocNA7VP!!ZZ5Uz~S3c|=Y-s2Np+KI6;<6k>Mum_R_AKCWN@#6s z2_vGN8k9L9=~OHM@MlukJJ}L|7`C6DB}q(SOoegxR%hBVG%5#gq&FL5OM|$4y$uF* z!+~!PJ9`^A&}M<3Cna-$ufHb^9U0QIk`WRX2oG-;I6B$EiR|S_&r@X#D9r%^?TCnI z5topCC;Dl>H?d?yO=&;?jF@ao8!9Y4F9L7%Mm9zk22fmCfTPqzb`*$)4AW5<><2dr z>fz;rG)hhYST)WR*xl0wLXkh+ccvcDWyxIWdw|dfENOrM@e(m>USB_N&Oxj|YHY^V z)}t%foO|bc-r9py^o?Fa2x&|HrEaySYHZ=<>yF?MfAX+9V<9Fsf(0W@slqTQ8fs8d zQNRu&D{Bk55}<%!UxY>mLmVH4oPtbL)s$1;RL~wV#|Q(;01%M9H5J|;&iIbEG+c=b zolRWFlkbfxg}-5T@Q-M#-e;@z^gilx zcOg$$M`Ph0ru%=7waGuD`|Jx8%kw!KQVwQsCd1>kZp@F%NP_8Hr;P0PxDK*2pCJ&T=t9s9qoRNufO^a zHs=0{L}@JePWEu7<|UaJ8(a5PxHH!X-lM?|NYfIy(a7xNNX-{cG$yAcAT2YAoqApZ zcLpFe>?W(aJaGeOOP;dIYcqGC$a=yp2Jp?gQ2rraKK&<_$G&8Z>+D2@1^OT&CIpTI z=D~J5w(nMex4qKAjjmj9vd65^6$eY66tMsYXe8E<~Y$c(&7n%{#=v%A-625CcQTcJ@6z;x-3{Nf0Thha&X`4xen}i$CsR0jGZ?Qq)#J59@q5`)^dvSZD7ad*gNGI>V`rQHc zU+y3`UWL?f6=b13ND97+l(1e_X?FA|lO-*DfIwbBi?SK3i+Az*ix+tH`T&3W`)_eT zK-xRcqpjl{B*`bSv~~qk!|~wdru$)Sp%72EMo@L8lvVxS)mG%>rNf1WQk}94o7+>g z;Vvd-?_g-`273ECAWyF%AazXZ;`k+w6{7wMg4{|W6BnV7re+S=xTRS^$sgmhFP>v& zX%rU;#3IdrrAY-H$A*94-h!Lnkw*QnwBC-xXA{WCJcZi2YB+J{0Uf7xb){H)Foc`8 z+E6CXKvh*P`uf{3K0APmZAzlN9j8w{=A>Xu1h^Ez*;))|D*?__6<}v?1uN^rm|g6} zyA*3{7c-^bI@noc|LC2NUNAHX&00xKG!E~V;-iCk*qkr}pKKXM_DfBUKwNYXk|hx+ z%uU9bntWXAK8vpIbC8CWGwS05+iA5S+P4y_Yv(aF(?icR(Q1IIOM(5}eyrRsq!aY` zxu1J2*F19M$ZURYBzAjFwH-wlC2>^3Nh({HI-OJ$PlnEcc2)lcO zP~A#`yQ9_Mo8)f;@CHOkwmkB?zW!=_xH}DJTWge;XF?XEKvakjey$$iTX`VRwHO%@ zL&%C6;jU~Ji2a-4WuF3}a|E_F@8JH8RJgg=tgz(2=FcgCC@jeG{b8AOd-DDW&M3>7 z_i6eO%}PXgE12&qrH`2vX&$hnxF~KB<+4uPf7p-hl`MGjEypRA#;^T%{Kg&inMFbj zTvB3X=NuOAXQ6Mg2zzs6&5LQcIbV(Gc{vUS3o$)bh6gK+m>+Gx^wWAYFE`L+wY#Q9 cpSR`sFJgKFbqoj7I{*Lx07*qoM6N<$f`#yP-2eap literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Spell_Penetration.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Spell_Penetration.png new file mode 100644 index 0000000000000000000000000000000000000000..2400f11a2ae7b1bb05831601d74d4dddcfb2c504 GIT binary patch literal 2906 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 Ef&x=f^8f$< literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Toughness.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Epic_Toughness.png new file mode 100644 index 0000000000000000000000000000000000000000..1523abdb20ea214b070b42eb23df0252646ebd7b GIT binary patch literal 2623 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Extend_Spell.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Extend_Spell.png new file mode 100644 index 0000000000000000000000000000000000000000..82f74341dc384c36aa91561585c599b07063eb48 GIT binary patch literal 1247 zcmV<51R(o~P)b4^BM#?;T@(=p47Le_aT{#FaHyLG#zi0z22{tuaz|*p0=+RP zFfNXb;)WyQ+y#U&TZ|ivA)=YaIE_=o54cOCA~B&p>I&5iL|Wnzc%qfVV1lTY31zBo{?Q50xf z^9H(;&UXejH~6*6UcT6WZ0t&zeq62}R~T-p4HNR4*UGO9Wu5Dc8te@p`y`VvQ=dKn zHbVi>uma9%PY_yG7XvF{J*)tYBA3twc_Cmkid1^;2JZ{DqE@66IzKxIY@;fI!aoZz z7XIGDZFL4)=x)y;bZPN!uz}PyfG@H5TZjMjJigC={~9eouq>B#*@RZg;=l%cg&=W; zzfLmvF8}#dqC1uh6|lxpXjIDJ2Lfp( zZKK=x4H==U%OhYpf?q_MM%JKX?_J{`7#x0_gl91(B;3sN#ki==Z^dVg4V;Gk2z5kRpE~^d_X{fqh%2Wz=eijcc>4A zqD^4vVq2;iPk>wiT*csT`1p0^q36_V2{ZA@Z~$-x__Be;e>&n>0lvWEW)@HK|NbDD zD`TcosFV%!F_E|-s188)lF`>{7T*_qcZ$J1EFS0aPXc3l6z?%b-KX&&=CnvmN$n0W zqvY^Ej`*$s4{;Cc*x&lNKV}7Y(y8e*I@AT2MG3x12$Gl3TsrgjFo%C}z%88V5wCLi zp#Xp7kQ-t$>u)0?YpB`}7Ib;EaTBh4q5yzroZ*YhY*R8-xzn_bUIK7h*hU0S6nHs9 zeGt6jiAK(FZS{;dKoS6cm%)=bqrcd*_71!(Hufch{&v!tE0~&LyD~7 zO2P>Jfi~HG4Nr$En$Ycv1pBpe3MpyU)DUaGCRN@*nu!X-?ALy`NaF~dlMx7ZVsUR@ zD~_x@6=A%Zo4K>TB2xZ-tU?;!B8jgRM^%)DOKYQz1Ik2u3-fnXmF*K1gw=^7Ys&ZK zX9pXvWTgifze@_j-YMK&TC%sac#pI$MkzZ`Q*NGOToayf{s)<#pqZe5P+kB4002ov JPDHLkV1lnsM>GHc literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Halfling_Agility.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Halfling_Agility.png new file mode 100644 index 0000000000000000000000000000000000000000..ff99a2eb0a099e806dca5d4295cf98100132b431 GIT binary patch literal 2164 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 Ae*gdg literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Human.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Human.png new file mode 100644 index 0000000000000000000000000000000000000000..38e08fb6600ae227f403652de98b8dc536b4adab GIT binary patch literal 2079 zcmV+)2;ldLP)M`+f|ZTT0 z$0BwS`W5;={ege{!`m-@cfFW*LUEWgu} z9MH`j!NI`+z!9mNb^S2R=N$s1R5pyCe|o#_<8i8oDK8>_vKg+1pz06D{J$N)AItOD z9*()FsslMl49FnC04`hIFX{4{K%vzqFcKd8tt91lW zOLi=(ximBr!cK_M$=h{gR~gkxt$pZ)BY^_|00IYIZ#EL7syEdT_~+Ndr^{ezoKgu0 z)pbU2GlY4-s_y2sSye@MM4SbdRL54Af!(dR0ZlYp26r&`5W{>v?-v6x6A}||JNaY? zSQEM~I-UhF_omv^5D*cWXdW5Sb29{Bq%H`7H?50+;_l`oOb$*&uRho!;%R@(IZxwA z+J3o;Hvt)3h?;p)4_&uh4#+ZAQ*#Gk#&sY1z)h{06Hy-o+-s{nXbfxdX5i5G-Dkgg z`?r65&7mV<#Po3=e!2_+%^a#4h4|`j-LK}3H11F1(=MlM?(T?)edM9ZsTMUSz(8C} zLug^PkSR4JynA)M-CoU?3pGdKmB-I-=T|+0tGbbd_1$*+@v9g`RnLooL$HU(@iaCw zcXR+|=mQ;-saYTrMpY+5Nt4DXSDU4ps#&WVh&NI01|o2CK$gwx?e@)wp^JddN&_-~ zc*{ZTyNA>Mq}I&A9T>3}KIaAqQ7E};Jqio1mIDhr05iKIn9n*Ef@(&9i>uYuPwr&V zy91yjAv&<}@_J)PE|2=W4{C(upiI<h=E10ss>1vz&>q<+1; ze*0m!o*MuVBA~m&g&czUYT?XEl;-^hy*5KbO%BLcGfCON!O|_}2SJi3Er{i=y=hKu^RS&U-Xt@P$gh0q4AQQ`MhOO%H zcm_u^)60d`ssSjB`(v9<6uFxZ%xtQ)X|8rUr>Do=>72~5Ipk)gnsO{u9Saiz01?f? zN>WmHKO9dF4^QN7fbMXty3aOLeLjrm-J!PDFXxM8FG98H{*)gck1sFB+7t=Zyqc>) zZC-$i3!)+-n3twvt%7^WL?jLt!DvN%6b+fu&_vU{8 ze*f+LK25oTj;6I5Dln3SV2+KWdI11Hf7!j0<6*j_!R~o)(y;`0pQ?X<%$r4;wEk;< zm|ESOrigI6>O){RjSSN9*>O~33ZW5!N#Ldgh7db%>IOh4$EgBm>}Il9g^SCH z$dEuAG73`F_BiD)wyR%%@KG5j4xyj-fvJq+YCf9}vsc??7bG`JRd-{4*iGem z!V<)NJSPcJE{T78yL~z&Bx0sZARMX{;;Yx!-ijfE2hipziI5O;5Q-w==xA7*xw-=Z zq5}XT03geZ5P=DYq5JF?ZvrzB5j{$b3Tman95-+ z$FZEJTuOrr=x&5?wOPw7MnG6Chkocy8zG|uIGCE7oyMt7l?Z^GxB;rFmC{nRW-eW9 zj^|XL_v7xA4(FUobv09KO&MtzIuV&gk@a%Pj06S_fk>DEp_KOh!~S_UE;~9McjJ@{ z{oVWhf4+ao)js-QbG^apa2)e#%%`c0S!=rpb9V@l9Z3vjG4F_w2qH5Qb^!&|tCdFrYY41Seb-D<6pM;NDMpn~YuzyQfY>`awf2_*MVyC0qoUi$sRIh}N>I+j{VDMIMN)O^fU zo1p^|prN^&!BqTen1O>74^6F>#v-U&2q^3@VvWE>6l8+ z+1vz0#&L2Rkv&G91<+Q@zaV6~6oS<^P(dl=-N6Q;7fo002ov JPDHLkV1ffz?-Bq2 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Improved_Martial_Arts.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Improved_Martial_Arts.png new file mode 100644 index 0000000000000000000000000000000000000000..88c6e746d3716fe164659bcb90d0acb2d76cd699 GIT binary patch literal 3053 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Maximize_Spell.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Maximize_Spell.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0f7c1689f16343249a66bc15633ee5cd47b380 GIT binary patch literal 2254 zcmV;<2r>7GP)&Fl?d%4@Pz( zV2I1O5SJkMARZKPiAIxXGN?@4BGE&Pqn@KZ)x3v~Hk{;t>eT5|ef!?~)xA}9tHGbW z6=cmgTot6t^vlWcE!#D-vUqM`?krtqz>ZYEg6tWEyzAzDS(kbCbm{)8t+`o|1$hxw zrL*=FIqgUpm6zeMzj9&SvDij^W}`mqOoQ%BeP+WKamW6>w4!M0-cKgi9bKY=>9+Zs zy`^Q0Qr;;cyc3LHcZvXJq*DOjz7WhDE6KWd}jgKL)yRr$2AlIE3@ z{kv(>I^yAi&>tD*W`(QXBO{zCqur_s07S18?tU-IviSI}SaXv8(7>KtU9~k=i=7YWMId5j6K>K zOCR5r*?)9 z#8<1p%mDBQped9**g{tkMS>t0L%{ce!kta*KnTenkAAr+-n}Jug&nL4dt*0xbE#n* zwm^_&?N~c_Bmm3xqP$nEcNThdY7VAgUkKrm{lg9#B)tJBvW0RHlWWDcHPnuPm$Ih3 zfV_t3PiClKTjD$oFeU(5meSHOAK!~7ob)_PJQpbVSsGmr>jh6NCfB1#=xAh+*b`Xd zE<8%_SW6u<2Vmp`$P?rE9x}krHx{d4(UB7ku#aOghw*_82ETqt8r^Z-d~$0iyS;(@ zeTZTlVvj2QQC%=zKS>Y(oHh`a&%xKy*zMK$)L7IWM&`e*OzZM__RV=_fYsNes$dB* zN@QG1ekSVDu(H|&1oZ%e0Pxa+Ba3iTB(3=;uJjRVr^5;lw96HppM_5Np_1w7c$n}Y zk!~17nmJNfJx4JyozG-QPIO)d_M9+X3K>7BUR!e1u#tp}`Mb z@PQL8fsYlapA3&of!VI8I#5_YuA4IQ{AV#E5p%b3Yu;9U;Ki3qH?7AHT9sr@)55f& zrjyA>RX(u51x~U6qs%}r46GUGkHH8Dlsls{^MyWUCRfRW;FiBC>;nhz)eDTfUGu($ z3YND$K$KX`AzD>UC;(5A>8&8_3czqJbm|9Z4uwqtsBs$XM}W{}2JaAX&<$Ll30IGS z69>RS8o*7CP7vf$(Ln^WLxlUcMV`hAT^|)Je*I)Vg?&fq<>RDbCYJZGpEl7O%W+FA zJsVE+A-KX*SZNDvn98a*216Lw?g;mK3x^lr&%<#2QrsF(UKX-P(L|p@u6)HfYFXFPa5zxdHpgEj0MBrjy zq@RTz1_}kvD1is$4=>F{Cl``KA-Fn}cv&i#5dfGIsFYA^rDC}`LGHG(R(+qPbws8d zjxzG=BV)O0o+0E6fX97=d%5(>56DLo&d=nP3!F)w~^RTpmGX(?e6WvgCWJ#tgCVeyEs^%i7 zo`vN)Q7#v&N29-VYC2iMn{njATI%tRX`Qy2LphttC&Xu4sTly@wXmzrMsJcNmgSC8 z!3wgK+W7kQ=5=MTfZ{A)P*I*u;DMu`ms7pEh62f33#_Pe03 zK2t8a1wdcMNm~06rl2`2JIz%ED=(P+8fKW1RS$6PqS*RCa-M2B#~%%Z zas~JW<^jirSf4*4O+^52DDj($%o-Dbu_D@N}J;qXVotOyy^q z=MTl^b96%@ZrV=%TS}v>}Ao@jX#~C0)D70=$vY5UM;gk!7Z+VbQBx!SA;IePP66 zq2?fIxhmE-vf2iA;~Hx|MK?y_QN!Tx+wM&FRlP4?>|}1ygD<9}ku-*`?d+OvpN6jC z<1XD~!u{}6QAQ=L#Q*J8u%vjeO&dJ9GdxG5`^P2iHHp^p5yHqv$7Dz})m?lDo5(vy9%GyD_dj3(SC c_>;H)18l#;R literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Overwhelming_Critical.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Overwhelming_Critical.png new file mode 100644 index 0000000000000000000000000000000000000000..04c5e821db87c0f9fcf0def26b4130ba72a82c1c GIT binary patch literal 2959 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 FV1j%8n}q-X literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Quicken_Spell.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Quicken_Spell.png new file mode 100644 index 0000000000000000000000000000000000000000..096f48aae0e9e0ee543acaab0a4b3bcb407d29ad GIT binary patch literal 1691 zcmV;M24wk(P)EEVX5bI$AU^J_ytEfS6W$0xsY^1D3m z@A=;E^1d&=?Pv{E{BHjbn}cOL8%p;*UHQVZ_w8z#*BqR)V_R8kQ^hW^<{unC8hrgP zdtciBSWBp;^{Hk1_s)B9cixVzfu|b2`_c;!9zC@FL|gDgTj*qa^T}hu_CMAhIxf6q?CjpwCkZcRPBhDFP?;zBm|)e8G~W(GfN!ty46$h1^oH2M=AgMM@-@dARsg$%Mg44 zul#DUBW`La9TW_c{F@p*f@T~^Tu(H z?H@b5&35|4eR5$y<}F%YzP@5rFQAePq?#OSQddM6n*!LF$zCwtjjVXwp2*Z;)TGpd zO{=ltenz59if39fJXR+>w5oSPz9tO;oc-4yFc7<&=K^ThYQA&YYiR@7CQAG)iQ&>j zM)Il3sqW{K<5_kSm*sNhB;I=m7w0qlG}UWVCmDK(lkViyyLoFm4FiIAPI())nE+~k zlI)n7VGuyk4E^Bm!vNewSfNM3r(vWC66giOSdoLOanN-P_aHM75ch9gQk#1i7YUM~zC7cM|x z6-7xw2Mn93fd2VOHjs+Zv08$EKuH5S0T1r0ROw?dVgw=)8ZO=MhpsD!SXWoLs|(?X zs6r4?ung!?s#oC}#P=fFjYFsL-pBap6M$9^D<1_C5j}@3J8=4p`u{o6h$Towjm^@=G2zccw|yEw~_X#!gD^FCbm)X()p2Vw zaz{bnGGH2#9DLQ^*Aj4^8=K~$A1!_R8NZ?ZOvIe0seM1IbnevNZ*Zq>+FsxwJ>UBM zp*w@@+F9)2JrkNUbf>FOy;JPTt+R*j+!);I6kEHpVCYW7jrFCDc*&3QXul5xuVc4m zYV)g%$Lq|!yWC>pNGQoc$slZy{QTLzZo|w+A1RdV(uETr+c-1$`0P-9S>yJyx(%~7 zuA5O`S1g3}Yp1VVp1)~*(b}4VEgNQTt}R-=c(P;`RZo!rH8lkfubjGW&GdDvr`2yM lX=*6nT-!H9dg5D-PXUXqVwOacNYwxU002ovPDHLkV1nRKI0OIy literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Vorpal_Strikes.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Feat_Vorpal_Strikes.png new file mode 100644 index 0000000000000000000000000000000000000000..622b247eb6485d6375cc3a565ee4cdffa2a46151 GIT binary patch literal 2868 zcmV-43(NG0P)pF0drDELIK&yEPnt13fW0SK~#9!9aVX78`T-#`_LYeRT!X=(YRFfeTyplPRNfKrAdKq!Hb#t_nw zI}S;(V@t7RDYA8Iwc6{w-PdQnoq79a=iBf1z3=z??UFm6zAqjR&E+cy5sEC(46V29 zYPB`-`q7(w{#dKEJP;5l%JF@?mRy%0h*gqw!L}Ka#CyZ@9FmybvS!tK=|@$ zk|wFe4MoueLU)Pz7{@=HH&t;7MN*!R6A|8E_y>M}E&2Fk-`e|JOA|W?lJJpNwDVDL zcB>%9SoWV_$U{DfC=4J41T8kj21E=2O}kR+vrHF}Bu$efiEgLHYtVbH!D~_%!i6yc z?uejnd1Q#0D^xwi5ELo1a?902=H%DIN`R)14)g}k#YBeh>>BSF=!=c?2DFXP1dDUw zX{({v&g9BxGcy-fIMCZGT(`}7_XiqyMlZ#bODF=5kAw&!Y8zGg&ZO6fD1MaM}7huU|DPg^B4} zE>#qUdf}M?);?}}F{PWQ1>DKtm0|K{4}b0SE{365s&(>PVG8&D+h#nXMQ+)#e^2QdLiQN+<3i|MO2R3@kP{skI_bD6%g0=yTjB}=u{ zj%VNe>kg`;Lxl*qjl;M)*2zw=J{|6itu)@+Q$IC!q(7C|e#h!~?*UTqqjET?D2gO$ zK{X!LLaK@p|NDZr`;j?GmhXCcAkh&zqTCy1s5`{@>FRNaV5@1+8!lVEaQO5+QC_5| zG4)QCC5G;j3ClS(o;x>bFO9&#)ysQ^FENRUg*>KM6yyM7`Yol|MI(e9{Q8-2@xTgZRDPN zA#?1*BO;=2ylMNDw|h)_k4w9pFX9n%3{TT6%Wz>?QDu486I}J|^v#b&vFgsoz87bi zheG?^ka^fEnJBO>P?A|3sB#covUXR3@v_W1q}e7bl%sePqq5m7CUD zLY6T5k1qXpS#KNCGNUXU%E;HxO9b*d0V5ohfr>s-`qWBhnHH0V}lvm%j zwYd8eV3Cp_sA5E=l$4UPDfifU_4POHe?0f1ej&4YbXoWI&53nK7?A`H@*sg}$JGNO zXF1;Z&exZH^^4Jnj0@tvo32aEyDs)6cHitJlu&ANL`liJBy;CcRfnG8;!P9a=r8^!0z^M-N_krT5a_%C0>J=Zo`< z-R??;mTtT1x}U1+Z^=8zCIN*B@jN24`(XDq>+$fgYT_KXD16UHg3L>?NaK7az$!&2 zuaoaY;@ZfnWxajf&^7Js1hU<`fB4;NMyXfcEABgZ%5iPqv4V=sam>*5+c(|gxs(F| z!SQTmVoH>ha73aA!Y2s463F*csS}jtm1l2gGgY1aAQB5Dv`{3bNs3ZgsANAqW6l>i zQGD=``+Gw@uk9VB?En-J0g*b{7T(Bf9S~R&KT(KjC-~f>4>ad zH)I=@ZdlXV+}Y_16hig6xtJuxHf%~u#rOBwjp~GBwM3TWdDd>}o&!4jyJao+*$HCB zW}-4%6enh|g6RiRsogec*`>kW?qp0W6$AnLROWq&1?y ztCM5d?oAs(_JgC7ArX}!aPX)-g0O5rxFFTn$%vC|vSa?!2_aK(5n^oLm(}9%ic1t( zn46t}HlP`%TB*%uFI08cGA+k}4YQFg9B!K%e0pqfYI^16qw#q3WM)sU8XGOat6VrZ zyc~&4LvI0uR;?c?1IwwKSVc96=$kt_3h`(%8P}`Tc2k!nEGz6|#;6-4# zW3FB^IJzPv3FNs?Prv;47D>;o8%ncO{Zs~ye`XTxEChg{IhJFEpvLerQ?EYCR+cu%sl8mT@9Ubq_A>>P@Pu!gHLYNMcAMwP;~B_ov_eamTIq^snl7 zEO#!KpE;lLY|{c>tx{4X!Dm?L(po%HMrh7)$ajZ^rmp|u{LGB28esor>ftX#3{3a4}kMjOPojfi*LxJ6L~k3^A? zD~j3aT5(Q@cV!>=MHPU*N^SC{uUr;6RlHGAI~8SDJn91%Q^`@3?_(3Pxk`DiYR;6x zreOqF4*yCQ>I;rz(gHRpYuJVh+c%6PZrgfAIuY*ZO_yrbs$sVue}2j|U*Vb5YK7_U zioW{sLe(s9vF)$%{8O%bexXS)e%**Qn>9cXG!g^`=81pGl`8luvzVc_P(Lmdg)ybljO~DM2o@ z(vk{|a+bEB&nkQ(n34pA@DYh28K!AA>ab3GfnG^f1{;M^Vdwh``^PgsC%}YhzRHlv zuB5_osg%la91EexQo_DAa#8(Ogq|OWeP;rMvU+kb5g%a4ax-Sx^_pTfflv7aK|p8< z9G}qQd}>-<7B>umG+LP|_bbLb(J-EzuRFXp*J}2}_1-Up8EjOZ5e0_F>$uxu>-w;5 z|E<6C(aIowP8hhfxZ;i-OQH$OZntXnX1)p_kQ1?BJi@UebOz46cPM{Ib*%oKiOf5t z+RIhLqQeRqBoJ}2&f){p!^1t9)2&D#F0nGt3I&fRJp(!B?GdXWUxD;x^T%j!b}s>3 zf#Fm^k_15@kdrITe{}Nn`(0Kkp$MV-$O9)0<6m_ExVXZrVNnZEGC_O8>m%fS_g;H= zw;txTP(V|-V9l=7%yQDrY!C9oviyd6oA3LcM?i>gKJj@_B()d}qG=Kl{`Tg}7i{O* z3Lpb%l@E)wfKx2nX!^~|zATZC{^lDH!g{0ax^PJ>1b|nrG;{e%c&f6Q5z{=McN|!VZ>od|#ny-ShrzHv+vK@mOf-(zq6uTe{`Aplv#i1O5*%DWoI3 SNkumR0000gcNJ2}X7;H1K+r(*RJkxgUNki%{Za$=werYrG zQ#+lu=``KOPR3yv+DQ!zQH%{{X>G6#4*Mb`1Y#4~_w7mQ58bicH_2a+^Wo~g`_8$) zbAIRCbDwx$Tj7(Rdxk4chbb1PRH|Z`OiPPYJiaKEOz?PYB4FfdV9_rkGb$COGX!!Vnhn;jh;!n6nk0zQ9VAM;cyl}sk_h!HD^M54O7 z`ts$=Um1{T{)6^weV9<>IUJ7IY(9a2sr%M*3k!2tsi>$>sZ@_1JyIwXt*xzyLoSz7 z6oq}oVlgmcu^3P>LR>CaS6A1QCr|3@>%R;Zj<6V?fu(p6h7s)S*gZjC#gWq4*(al; zqr~y{_V%i(DyP#K3UdwY8h$6g>1!0uUDSvfg5KnjII7K_E>@gPb#fklZ# z;&!{?7FfyGDL9cyqznpSWb|Qk(+jZ}yJFn5+xZd^Q&N&|G}@GDftlHCmWb)YB}%t< zKU=6EQki(=O$%J{`Fuz)Jaaf4s2xH$2P`M|XdMp1%g}(K~!N>^dEW~4Q2%dl{m5MmkXj+@cYQ`A(P$;tc`v>DmkyIl0c>T11I#KnF z#-{J0jy5(n&@$k4y4X09K|(;_31BGHB0aYnL!rq3cR%a`Gx&bIs@%9Tm#dQ3oH$YQ z{7cz+x?gv^|C`_bZgO&x94rzasSyH3gglbSD2mSkJ6Xj%n5JM)faxMfq}} zureHC>s~&q)acoGRIO3}jL^u3L=zkulTWisTDVBW zw4Hmoso}U~J8-LaR&G_wO$+ zFQZccF9U;s$RoA_5?stxNjNmpLJ5hTleonrnr9nli`sOr2K&Pz=nD0l~>xTt4~c#OsuS|pgAGaz<@bPIT!*MR?r`~U0-=L znOp%FvQ3;q<^h98au<_E4EtL>hGdF&rlm!@kGK5ls~1qkofHA_wguNt2wZ_ zZoGK$wbIfyJ0e3x$@%={`42z)UZX|xDcTH^lGI!U@5+Y&u0Z`5vFBzb@kAp zLxqKf2!&*eR2Mu2+gOCo?b|~%MK?D#f`Cnn>Fu}P{QV#P*xmiFl9CegIYhuhVa^8+ zL?RFb$+^Y|(%|6K)Ko!1L1kqnMsNsj5fDPeM%V@M!R#}`9i;T^>C-Az?v~Yb^{4IF ze{^(=T;*^PyD789957!%NMgzaCzHwWH83(Vf=a=K0^ebYGXy+r1UwuSaHZ4b4-DKx zTRGd(s?1UCY^`6t`gSN3oSvSAJ`}JOLvu@CB9-y^!3>^BGI^z zPvxp|-hKBS?6AG-=YAHfxySxHb@;HJqGTxYWGd}GB(@&`NY`j+m)m`-r*~m#Nv|)& z3yXQpWHuosXlxXXyh0ecLNW1h%H#FEaq;_w`l8~(f;WEf+R|J%=Py(Hm0FRAl1XW? z2%nhZNR)NCLI@zi?%(rh(ZNtmCS}0l0gVia^LQh2xybDa!$cyXMT{^IjL|fukTYlu u(2qpo)-4~y2$eY!G~)Mud58CPmj40u$*PW_RdLh+0000>?F41@z~=T&w6L(Zr!*0^m6(vb*hSo zjy)btB=QLLa$ZWM&-wnozoiQPk1g@PZFq3&0X$#e2afr2hVmRvIE<5&x+3r+s@kBW zM-T)Qc@BUQ0_Pmo)dWF+t}VMeqhB594_^9`d*sxBW8Eh0&>>}xAA0Oh7YxT!gfs~2 z5!eRpcAvQ0MM}wHJZ5M6Caq?J8bN7bUex%F7D=21#P##!YA&nv188VwJ zm{f3mKjrVf^L+u}eFC)BQrx)kCRg?kNfh)q;M`Y^^T@-ecq9mMrsU$g7rFGq8C0Mx z6cvbib%=L7X8U%|XbMKayjXoLAS@`m+UEnlgQkM4g6^pe9)Ip@pDOez&}J`29Tc2A z9kSLe**F0&ee)sIg9B(v$Y(rpe4X=dMzDbO&MB^ZyiM&KjaHkr!4WRFkI9;jYzajr zDQZ}1aJ8jMVY3PAKKKFD4aFGAJGTyK+WLMVt8)_1v6ff{5i}I2FomcB&p=erZ>Jn> zL#$wZP_Z03@&b-+MNB7qw2h~Bwa{^;P{}!c%E`|VlWNEQ)jnG z8sYsw&N%`Pwl+G1ZiMdvz5%JhmEai~t%yMvlBS318N3ww8V3D<#b`q0Ll8lggC`-M zST;Nuv=Z9wgvyoN%u*Vg0pEJ@Sz0I0aAgtj@z~rC6hr};D>!y)i`n4_F9Cc3QecEY zi2y>MxC#9zVd)n%2GA0cMgt0?@dN0!pz;MKb8H;XOXPSc;Mt|M=^idG;(s z7UL9mZfj=4z59XUrq8gp^iKv9fM@_xf{a%%2=EGM3FwE!iy@l>h(jM~YDxiq2u%cG ztHXMz87(qCO80sG_dbtpD$afVd06j&(coZwb)Prheh=0jyBFx>u{DCwr*aVVpsitH zz+h3UyZ~zO6}IJ|Yp}Va*9FxduzP-ojSa{JczMj;?UcO{+&Y9m{PQpH#Gkx`P46%( z@6brcWRnTYy%`rSA8_m1kdteV@z~=JbMeEEKjR?{PJs4v*3L92_m&vRFMu4l8bX2S z0*wqELe!KHH;@&qcRGx+n%!y6jRm*{{Pkb`E|n;`^2)z}s@OO>AR8I-bcUT+f@w~A zZN%q(4Xj=HNCGStONz=O0w`)jZ)1R;fC>QR0csVp*e8eqW$>CnuMOFh&Ev<=g`qMv zS9UGQ5%|l${Tn)`PIB?RD_nl}IzM~$1L|SUbZ3V^8^T<2`KLEn458a>Q54I&A(O&q zp66H#S?2J=4jY>xD$rmnkTD1!y{u@3Jy>MOh6l|CEJ4>5v!dY2cFmVw+~Dllr#Zav zGcNq(D(}C&%W&UOTWHAl`ReaKiPbfGx2EiFLli?%YH;Q*kk*N1&*co0u{jNtlPKO%A-Yh9m5&lp;RBfNWl8!1=G^0nXoB9$@x!{2|88y{wz==f}pG+7Qo z5PYJ|3P=bC))EFWz1}gRBm%#W*E|j71`q->gz#~JM0NwBW}jv~EV#9f}{yi+(63D0M&Jk)|wzp zXm^i7q_}>0#F?j`0lyFF2-*@~hAgbaD4$3*Sby>htUu8OAt2j>$%s<#Ve^8|KiOx! zwdD5Bkl`5i50;#JMAB17NDt>!)k+lM0ZJl;cNfSQFvj2q2~leuTt${mpbTMemw)~K zcX;aDQI4IBiQ`RFunB4tymc5`=*DpCfJM4Xa{!?ikX}j|tSORKgY{uWK6PX>L3*%* z=La+z3RN1GQ;<@A>LK|_VKmOIdRG`=YRhnMxFU@sMpv#;Pcl$_lsW>zF^IOfbm2O? zvvk#fbxPa;5}+gLZZ(NoQ0gUBSyL|!qN?!&aI&JZh8i#qf-t16&Ap~JXr%9`>Xe`t z(r$ZPf8!PWnWkwgx}pKMb7=O!^LhQhe#!$6oM!9cBamJuukR2?K-huOqIHe7hT2<| zu}ZC4i)ex`1WJO!p$$wXlY32FmN1@<=?xsS#V%`|KF@sRi(Gm2J>GidH9QTk{`1T9 zA3VayJLKV~ALaSypMykV=N~aoFC#=ve4-1Z5Nyq|Oqpv-UV{n2>q8hybmh>Mzbvhikbw0ug+$1Ns5!tbE$QBvEX@cyilFP$J=#Nh zg5hYwa5tx3LLgV8RjnLIN9{m*kR%CF6n%F5nBrk67E`Ka2F@TN52PTEmc&~TYo|82 zdi(Y&P1FX;-vrr*LUMR>7nM7b1iBBliB2WxI%hJPbFf>nTtJ{CzVG2YAQX6kLWtE+ z+Gs>vzj5a-(0H;~#ZWkkq5xeZt;UpNmRfM`t1s}4Z-1M^`JC~ceINio27I#JF*b*W z2feM{s;Cu)JJ;vzZC6YuAeoWI0#Up@zB2EOLz^^e%v>Olb51(B?%78&z#MwLruhmPIdk}QLKxhi-n@*z+V zf=X5vtbI_eCSk|NDsVEmU!h{@xO{2IlV=|Sd79V$^L2vo2+8_M$TTQ}AYx;18uAe8 zKI!m)TbCD9X+>BjEJp>Cof=aHEF3s5z~SMX!2Y6FIjJa|W1&NA?4#8f>%9Ac7MVns z5$}IkGMQcHyZ>~aC(b^@&wh9nCo2wy+wANrE`GFRIFektc$Hh%uCW{~khP#nm$(9a zsi?I<$bh0O(YC_WmMX8&dUd<04J?)=Hcs#opLAZ_{~YtD-#F{~y^vNjq%2F4<^Vs8 z31g4A8DQ#+gW*0{80{Y*l|dMb)PQyfZSkZc4q`mdBd;s+QX`Zk@FRo}NFy&eD6Qr5Wmuc6~OVME#~vZswEgmS}m4Ej!@SI00000NkvXXu0mjfZPK8_ literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Iconic_Past_Life_feats.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Iconic_Past_Life_feats.png new file mode 100644 index 0000000000000000000000000000000000000000..8d93db8128afe1472e65af3fe39fee341cb17d7e GIT binary patch literal 2887 zcmV-N3%K-&P)?qGYkJPiWHQMlA%X!!h^(R@o(L`?E($Iv!iu_}E6BB=ppRo$T!H6uDu{9) z%R^TVc?vA|DT3Str6&wK0*nSyxk~Tg{O$i*SLY=9wlNiA3`Aqo&bx z<^R|o!R^=$RIl) z2wX#>tNCF{#1Uj^y)c7H3~y_r&6h+q9RFY&IlAln+yvO!7R)83VClK>G$4iQ#QT*`q+Wr?bx`hbmQ(Tn`iAC^TG$+8_wxf>(mrvVz?C{wWD~~4= zO#>bsw&c}q>KU|u&9O00Os(2zK3nw4p`UlJJU&-S*WVSs$1qy**6a1UcmW_tpkts; z^m*@XPo?w>SjFX?JWCM>5yZO+X{gYxrj4?_)qS7q)#<66w}1Ch)78|3b%RRAW{;RO zIN6}A{q&pUdH8y_iRJMNYY)%4+HmT~we5&8^KzW6j&wxHZlx>UG zmiN1V$c0-^et%`XcFHU+D$XnDSr>B_fI%!mh=o~>L%fYptAfmIR20pFs2hqWPhaVn z*D2SNS0h(+?brF%!Fp4s9iPeja^bQ>!(+v{#g&QDYUz6G?6%=>-qORfY}*_+XlhNm zDquy_B-PR?v;e~hjsRoXvJ4<*7??4QT}n8{gaTrdB$W!Qao3H_i?^w#_|0?nE&g!% z@UGLcX)BKrNFBt*{ZK!?)mhWr>CFaSo3YgQr7Z!i}v7s)}gXJ0tW?`yHT!* z2J*X=4B$NIK$3|_OW<-WDMTjDRdB$A; za<=Y0x_9e2Mb!f!*tu;u`Tp3t{tx__NH7(*u!UL3>9Pp` za$u@zWx#@Y-4t1b0C5zX7HD!sYKy>k%VsMx-kn=%YS1)J4 zVl}5JY6}r!Acg=U7B%Wg5>{TG(ldTmgBW>T?jKGbzkIc+!6EN3%3WHqFuq12!# zifVF}D6$!;Poc|}>M>$j#4?a^o>s2tfwiSW+I+00j0u}w;dmIYj9)ubQ5R1V0)k;t z5Co;#-~&u8tO5+>Vjq_)(9kV#eA89R41lF7#oNj&qC(8=~woht={y_A%qadC{ z2wehKcKymreMZz&Ry^3FYg0Vs7Xpb}X;%W;y)A$cxK>^@W69o6K69;^h+3*Bgh6N}!>Y)SKO$xpIrFz_WpXpy^gq zlj5|sEkY=@EFvq0TjWfW7ZrX|HK!Rkg%% lI4j^{7&PU>-Qc&Z{{kkZl7cX@Mb7{L002ovPDHLkV1j!bpNaqg literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Improved_Augment_Summoning.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Improved_Augment_Summoning.png new file mode 100644 index 0000000000000000000000000000000000000000..02fabae34289779a2ff13ee6e66effed104beb55 GIT binary patch literal 3238 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Air.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Air.png new file mode 100644 index 0000000000000000000000000000000000000000..d977c383c3e138c384133ac11814c2a3755d3ead GIT binary patch literal 3572 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Artifice.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Artifice.png new file mode 100644 index 0000000000000000000000000000000000000000..35730ef0b2eba3f8b6361a69c3da1c440e280883 GIT binary patch literal 3803 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 Ri^>21002ovPDHLkV1jSlF_r)T literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Earth.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Earth.png new file mode 100644 index 0000000000000000000000000000000000000000..2903c95061d4f2b762e34af1d612577f372dd293 GIT binary patch literal 3369 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Fire.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Fire.png new file mode 100644 index 0000000000000000000000000000000000000000..1a914d43db3ddb5de5ae47ae28af63bf7aa8c650 GIT binary patch literal 3065 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 KMNUMnLSTZeAJS(4 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Music.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Music.png new file mode 100644 index 0000000000000000000000000000000000000000..4d32c0b3c31ca4dad279aa9362ab4932218daf46 GIT binary patch literal 3063 zcmV~Xz-Nib_@DaIyFX$qx~ zI)Ok5LTV{VD3}&P38i8w5oy{K(uGe+SE*_%+Mr0#rhz6viV8^}B>{{b?C~vzp%f4-fCeDd8O|C6 zzUiqnK=|Q8f)^0Qe6QE%p?7nZeishokrrRO^x|LIeAP#<;Lw2s3=fVl&>AMs3(CUK zFM13Pwip>2WbVj3l_?k=tJ8NK3g6?dyYJ=Tls(bHr++G-W*VJX7UqeqKX>lNYp(bh zx88IM7==U$vNV&k)NIs$N3m z2T0T)GSrA<18jow4Ya9~F-%R4(nyDiRTI+-cq{333-(Rz=jv-d%CpZtxg}O2D{Xk< z-2p}7J>L5NxOn@St8Tt-CwJa-Khg{#lM#BQN2!c7ty5Z02oW_kN-d0VLTwGc0D&Zm z5>izIBZ*0HUU6{lC`qjFCnobSqCfc^(aba}#>WU2%CcghIe5H29T@NNso?OD z1I!-Y%bj=J&Qni4x23EQkxZYoq54sv1kR7(t7o6Jdhp5}SMu4rzeuP?5GJ8441)tB zlto3PHAU4!NP{;P9Wo|Xp1_L-zQM8lbxvA#G9eGl_vT0kQ*;uOn;efNi(_Vwc6oL8 zULJh#9=`JEKVGmDstgxB0sbwZEEd0j!dG5LY+ETbe2*H!VzY!tFofp4<>p9n7^9k-hsq} zRJ?v@JM4;xifszXVe zl0IEmQK3*tN@J)=lGRY8tWD2AQsbH4*NB%_tY5#LMc-j^ejlaFX{MtLgmLQqA!_9i z^K%7WYLxWyO&|gG@YEDZlrYd5C0KzHF~SQ}BoQ%m?GjzrrlP`0hXo9QqAUqPAgm{& z!P#rJvu)%O9EPtx^9bW3LkuxMEK{atrzxrmZ=fj})K#6d(Ijfs$*p+{NP=CQTg3Sa zuD zk8vc-_U16U56XaW)CMx@qjhNV7LWofr9=jB^s(ev(Z|xqg&gM#ymz?Z3DRRl1)+z+ zAyH_bV0tAQi8KlsVoqIiIyrrOY0w0EbWyRuOG6QQ6rqn5C3u6a43#}zU>ZP4Y11?# ziWIJ266jJ2C`67AIRtaOO^ASs4Aup73{h#(R#EmWS(IW;ACtD}S;6w5RkRL_v(W3~ z2snB;=ZJMg8K5mQ5?LZDjqZ9Vjt55rxDc$?8ZRU=1Z*&rvcia*fI$g~23)Xs8;B)P zLQKZU;5czqW7f=b(nr@ ziSHeKo+8oJ4$WBY(Wj$ze`<;)yfVDHQ>CTDhWj2Va>z7oVVF<2~tC^$q2 z5EN2MH14e{lV}^qDN06o8KXi~ptU)`86bV|# zC>tS#KqHB$Q)h_lF1?ZY!)?Cw@LzI-NxIBZ(gqw7i0cXMYJu7E5S9+cS^|N=T8mz8 zP;sDe6{RmoV+h(~rNQyGDg$iLo?1OdFA7Xip+^*zG1Q`Aq>Tv#ZurQxcr(XeKmQ=} z%uuj|!w?aOu+)X3?H1U(w1+O!c={+>2pv%&QA!iJfOZ}&CB3S{TvuSU#|b3iZ9t8I z8V=7$vqdfh3;8h`jTU9Mpe1Y6d`eR_`MZDqD@qpVaula>P@sH)O|Y4VQ@$hp@krgG=zvq)bOPw5(%l!NHWFP zs$qVxcMoY6y#S=w;JjUVQP?>^1^Qef5iCfuR}1114-$1gkY^!HtU;YaxL-@bs(m(fzI=yXb^`!lr51!_og+H{#Gr;Sj7 z(p#j8h;)jU5yA_q!V<+EnJ%*Nz00}&=3nFHTR+9zQU6%K5+4d!`_8(|yHct2;XRX6 z7goMlxnsw6zW>s56uF>LA0Yyia1=>S9@_W>f{;Y2jtrVuD}poB<2q7k(kRA+HXGhM z!Y^KWKEHR*y)1O>xBFGNBm`f+E9DxzEutiQAMOC)N2Xtydp~K|JpCRPxJrH{s)cB!-`vT!3zKY002ovPDHLk FV1iB8u1Ej? literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Water.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Master_of_Water.png new file mode 100644 index 0000000000000000000000000000000000000000..d54fd51e990f23f42acba29683548829fdf4502e GIT binary patch literal 3241 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 RzjXir002ovPDHLkV1i|LBKrUU literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Past_Life_feats.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Past_Life_feats.png new file mode 100644 index 0000000000000000000000000000000000000000..762a25a2e0a5c051c8f62c1859d8a58ccb1a915b GIT binary patch literal 2625 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Racial_feats.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Racial_feats.png new file mode 100644 index 0000000000000000000000000000000000000000..93ba9e7830f7348d01ff959e74aae4fc641205e5 GIT binary patch literal 2306 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Ruin.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Ruin.png new file mode 100644 index 0000000000000000000000000000000000000000..0d4a2571218ac35cb763ea87ccbb58ff60cd5d7d GIT binary patch literal 2557 zcmVu=q6eaGLQ@9lRxzjO6Hc4|8bNtFu?X`_UTbe?;wzN%}=3JkS{orOCz5`lRvi^8Ua#+NZZ{b-p=wI%cDh!Iuv9G$ z*M>`_A>WUf65QrGZQg6uo2`Z-H-A-%(nxvkt(EnSq~uezz#e__fvE?E_l(pS+~S3s zSKr(0W-wg#6KCM8ar^d1mzFx4U6X2P15N}mB4Qu_f*|2SX9L1aEM}iRBnoBEc}{zp z7|H>A@|m%Hr;Y$cz`XhL#`=}@vPUB`(UrNj1B#J2Fu^u%>nZ^Zxr5bC8{-_{Fv@9| zv3-J#g0JQFy`6kNb3$790rwOHoF_pH009JmF&7m$If^4z^C+`4{Xn7D%AAFClv}5@ z%MCK;ij2)jc3AKSiLD#+wl!f;>YjrXPS5Pz&%B`+>La`|ac;0zVgR#;Vo_qY0 zCypZ=u{?}#UUjz?gkO+Gn>|y(-Cq%xkiQ0m00n`N($#8Sb2|wmjF0)*AZNx71tb+8 z=lpqQm-_BqPRF16^eLa7``uHt|0Jb-=&Zglck`F8+X@NEnbR(=$gxR3>84;70HA*TpvC)a_#&YaRx|00W2)4QbjU2VzyNEJdY*)ycqCV$Uq~e|%T4UTyZEU0d$7cL%9OyL)TCGx@n#Bxw$U(Qa(I8kZYN3BUsc zKwcn*MgyDYQAEY@pxe#4ppWOWpzYsoXOmNz8-&)XC}R zf9s)zx8Hx`?d#{SZEy5kCv{Bx--};*+9l%V^5XkPG40+|B>^#gl2^z5ZYC!MWuOW#0r*d99Ud#ub?_K6})r*?0c( zU)Ha0e^#=e=D8+VkjQf4zS#5NXl?Q&$&+EV1Vlg?h`@x9Hi!idhu`Q2KYnAe)#)Ft zNlLTB12$ds&o_FV-Rv{RCfe=J#d`M2&pz76*lERIGx>(KPOwtR6KU##K$OR-4Gj?xf z;fyZ>a_5a+(Ka=(k~rhSS0JASBM;;)v=){D)mp5-{nD9(XP%w?z2T_VRI%~G@wD<- zzO_@HoSFOH#iX5ThPhG7n}g{RFB-?3xy9_fb$7JMEf_%)9LN(Tk)%4*nuJG8v{u?S z>vF%^TU~9<*U3Lz9MPcR+#H#E^?&+iEh<-%j^UE3u~b5A+3ZG|r%v|?yVeb~a}E}8 z01=FHxiP|Ot)wN^C``=iAh`Sw-y1AzD}*SH)!%86Un$NUd-Kn~d+4{PCXSz(f9pRx z8*9p=J^PBAw|iM?38Wn~901P9S!V$Q=Rn%oo!vTr_()}W1pXU_3XlH z=LUnp+QknV*H>?yyV|+8^yt_AaO}{7ySIOK^A~56zMefcY_zE_^}0RR&5&uNj_!*) zMga9;rs9aN*)=W*iq3`|!v`njm?=dAqB-nRDEBax^VqttiBzI?Pp|fF`gS4ej4r zU(G=hn0?{|um7%Y%87$PowMuf)g77Gh-3LwBg{=#Whs)#VS_@kc#0bB((MRauH@WIyl z&elqo5fOoVyfPMe5ntKt-)d$C&N67`EaBIS!KhL$3Qww}uRGg$p{ig9faQT5J~T

zlO8KZ%nO)M#1&H>_kA7}gd-*_$znBbEH)3E(x}v0o4D}5A3XiiANi%3!rs|8|NY_@ zzI_Vdt#{tt+31LZih^Kiq5I*bUbBOC-*q#z5|?Y_25Igx>#`gga6m@fXv;Xyz#!vj zd!+?T|K#s~;FXKVo_q!%=Bu5Z4#3gdGN8#%OcaK~s~4J!H@a!=2D!5UXDCR76262l z5lJfgRFo78;)Fa)nNG8$Jz&BWryjYxxN_;Ocb@%|)4-Niov<97Vovv*ztf>le;78Vxf@LE3R*l2af^NfdpGIBGr>Jt`^gad?~p z4n}ZbB6D)Bg)7&qjUT=`cYXEY#~ys+>^j3-(rSzz9J_I4d3j@K{puSlS6a;`@AZ&n zF3p|M%)uE)I=9-Awxk_03r*lck#o*E&v4x@(CN?a-Me>MA+S0t#6EH1g;A*xrfH|S zTTjw%lBG#voaH1$zdvwxK+Gw{eF>xUergyorF`pP970b7A`~`Y7X8fKy}R@O2B`Cz T?0AZY00000NkvXXu0mjf|Dp{0 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Watchful_Eye.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Icon_Watchful_Eye.png new file mode 100644 index 0000000000000000000000000000000000000000..e26aea8465472489fdb0d9c5065797cc74259837 GIT binary patch literal 2618 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 SNA{Hf0000SUTST literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Question_icon.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/Question_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0c613a9f8fcd3173c072e16ba08b30e45320b14d GIT binary patch literal 1658 zcmV-=28H>FP)Px*G)Y83RCwCGS4oc~M-_e%k&&5|SzA|kS9g1Qj9G*SL<=LpaPS4ONEnb0NFe)+ z#1AkxP8>m&jIabq_`nG+oZw)27!DkaK^}}OV|#pX_bl#hrl+R5s&bEr=NDPkp2~Li zBFplpJY+;>)tBFwU%VFyA1By3ZejK|#({G?m<|C6U^JZo8XCbl;6RDzpL=3uCA_sg zLW8ZAE2R^sI!kq-FbpJP0-W&SOJA2>Z)f+;{+$Eq6m5T3t6TfGV^4(r)wPB0y5Hyl zIE)LxtjGpYv_BYJccoff`t&!x`-l5vd0~F=qd!3vR*jI%@t7AfzYYHDOa@GPcHU@I z8RjwM5vE(1{|9KOazOn-m4AHxk&3b;Rdoh(=D5sjvgQ&Cm(lT1xF%1nvB-F{%LqEd z$pOX#jE9g-P-S4$F}@^8D`dB}4{OM{0Fu?{px1%+1^LNGncottm!O2Y{)*narndht z!e!p*7-t8@9I`Ry2|z_3LX}J@QIbP zA$wr01+~C3*#x7Zgt~DR0L03}^Fo7fKOJ9wM&G>3TFWetY*=&wFyn}$1WIr?1;k_& z770nD_n-XpcZbh?FS-0oa^>04?|(>YXcCN`9*xI-Vv;crmuzmGGOhH`L)SO*WtUEllAy+>OWe=1ZiQQEs`gu`JPD{9J`B zP73%SjD{jb(nb1I!Z_FQ0dT=&16zI3|17E^f9-GX7apJe*ZL#HTUUe|+6;4nFheuw zRmjHUtjX9P$|L@-^1a7Ms?6Ppt|JKhyc++=g?q1h7|0^1SNk>?uHpxdYj8(`M zdySLHI3qGQV3gosQD+(R7QL@NC05JTQ+j9yHK1kMc9Vqo}qS=Mf0_aAVuR?KscNPUbax-8g1N- z@AIY4yq|To`LE*bD_puxyGNP~$x4QH37Sfa>8*VY;KqG2ZOm!P7#(~X>uI%ATQ94v ze{!sHzKR1aiQbadnjC>73Oz!mdGzX$=j;{K&dPK_h;d?K>EO) zbL?~*l}_!-`X9`?7lL^3QQFXef|T zAdI1dPH0Gzvtn@;l!l73oxO3LG6Oodo9fAd2$s~Fe+9P*gnS~Tq)EC2y3)F8A%v(X z8;!Es(Aq>~5tSmC>Yw(@fgz0XtHxkM`K+Bl_~Jq7re$5Am7%9;l{erRMFc&j0`b07*qoM6N<$ Ef_ZErZU6uP literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/somerights20.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/somerights20.png new file mode 100644 index 0000000000000000000000000000000000000000..ab189e773de016b812ade8afc8da33db7b925dd6 GIT binary patch literal 854 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 X7?A>0x%n^e00000NkvXXu0mjfj};-z literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/36px-Icon_Feat_Elven.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/36px-Icon_Feat_Elven.png new file mode 100644 index 0000000000000000000000000000000000000000..e4ac26b461f0484907111c0756f8c2ddac4a0934 GIT binary patch literal 2824 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 literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/Icon_Feat_Elf.png b/subprojects/common/ddo-core/src/acceptanceTest/resources/images/thumb/Icon_Feat_Elf.png new file mode 100644 index 0000000000000000000000000000000000000000..3ad9a01979923fb9c8d70e29d00ba85d3da41648 GIT binary patch literal 2145 zcmV-n2%h(eP) z6YzLAT9DcLY;}2lxn5ti?VO^pm6|qByW7p~E~0<(_ke%={SW{Ar~j1d4gl`p-~b`U zFh6CcnnwgIQv&qMch1`;_QNr9n6Kx^!Oc`{8uKuv-F8T4aU7PbC0I?V=2WVxxv5(%)zw1a z#k$*WjsSo}#Ms7}AR-g0xtcXi6GH%Eb@Q4{;q2n{{BogVKc-aG8KLAf^clc&RxQ;D zV+esz0nIHSEKl10SZb+E+=Wg!k~;u^#3(Vkfi!_wYSnqiZS;QoRC9J_&6?eyOr{>2 zrnrr@MuZ@Qh=7OyfG!AKgM9(h3N%W)3=Y6d^VJFv-GI;yA%@V+;+Xbr5GG#4u*v1U z_53hStFCQhyjag&_0!wUo9AOIL`aC_>SoS_O+zW0n~N|BQ|LMospjTTt0Evbe7SCa z^`nnw;+xHO+0eG1P8TgRH6eyTfkn-~b$|JW?e(ko zZa3RnD186PFb@#hp{``AiKPlV$axu%LXjL;nApmedbuX!&pUi*KHoM~_$bb9d z775(}(U^$QL%Wc1svmst@@_jIhd5tg=n(NZq>n!Q&i8-tJ>Oj`xDl`jAvmG|Qk+RU zR|lyEW6?fE9$$W)ulu^$ZV^?1AV}8)B9v*=cD`zsD{dAadkwG4bSI`(9EkUlbM>k?)G=GTJZCpixRp! zU`+{`+_V+1)8K#{q7`-k16Ke;;?S@(qFBs5YK=AZS@JY*+pcL3<3Sh=iCo8V6ba;r zNT?;v7AF!qVDzRe&#q9S)#S(qP|Y0xNkThEZp<;~ei(+svG0dzn9QLSrbXNJ=){zY zx)%eKQozlu)KVdjyWwyore1k-`}t-$n%BS#;O5|Nh7hSS=V6?lHc$Qj*pGQgIh$yV zgs^CvJ2O)SE&EAN)~%%E*Vi{GC%{mum6EAKaIQJuJnVzOY}Pda+|<;KRHri4^1R*O z-E8llw}*Z-&8D@O2~9*%jN_e-J6 zwVo|x9?Sq7H4RTUyZpt&{&~AUjuV@Qh+Y9fvl$|_p?P?C`tEz@uh;W7tYn(>_U1aY zi?BT75Zk7uAQLyY+w$$J_U8Wa&2@hFwENDx>$VBS>~1rBd~+OCuy}+{(e}F|(KKIE zbvD%~Bt&8WM7gS1EpA?>o(V(Of-7W*X4ju@aX$;4Sjv0I&n;bDu1d}i_fNVXahkTO z$1Zk2b$8rtp08f)jiUjfX$)Mo6r|_vtsM3vfTNq0-lzsZ1atG6v|YElh>2`-|9IBP zt9MUQ#&IaD_1O297w1jOo%-Tx?eDCW=wV-TQ352EVz5gUh~zL9cXt3V=c+D*h{HI% zeE-GIKKjPf?vQ|!`l5;RZm~TiA$@*luA0?`toxyiB~^7W zSNB|N69m`T;17N9nDwFDN z%)?X=+`vmNjMBAjN||LTh;Vwc>~M;$SWz;4acC$Tdt9s22TO#6P?52e%!07O))X12mOn>8fTzW?%45Xmcn3p2O^ zF^BNaPp`L!Y3Nf<6_5kt<*Ms~Ok*CWGEQ|E@-XEomsDyliVlQc-43}XGbVH-GL$G3 zgwY)l(UISp);53rIC2hzW=U z0fCUT8VMIf4@~R^>aJ!$rp{ow>c^kmB?WZICEwlc(p1itvy-!xzO~P+sHIZV+xY_) zhk`5;B6HJ9$yqEXhB<}StpK2d8Z~OgKxQ5M<BP(TB4CT0|21Sq9Q8bBDQtP1GHAQ6h1ffIvy8pnV9_vY0*t1myh-#+h; zsis`i!4V}gGN)X%>i>Ty03ZcMGiPB02M5U>c2B!96?HTw6mbX7t~onV*EMhMH(xy- zhwF#q<1R#+iuPG6kt~|fbyKlwZt7~_ZioyHA##XpRdtx-uYd9Co3CF-k6z1SH3Q;i zHa}U;Qrd5}chhv3a!SeE1Vx5nbQ_R8Ms5RWEkja5YGP*&)qUQCPG;;a8KweXefj)9 X7?A>0x%n^e00000NkvXXu0mjfj};-z literal 0 HcmV?d00001 diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/Index.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/Index.md new file mode 100644 index 00000000..86239545 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/Index.md @@ -0,0 +1,8 @@ +# Index + +## [Basic stuff](- "Categories") + +A corresponding package to each major concept: + +- [x] [Model](truthencode/ddo/model/Model.md "c:run") - Basic Object Model of DDO Entities i.e. Feats / Skills / Spells + etc. diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/IndexSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/IndexSpec.md new file mode 100644 index 00000000..70c53947 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/IndexSpec.md @@ -0,0 +1,3 @@ +# Index + +This is index spec diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/Model.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/Model.md new file mode 100644 index 00000000..e16e4216 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/Model.md @@ -0,0 +1,23 @@ +# Model + + + +This package contains Representative objects to mirror of DDO. + +## [Basic stuff](- "Categories") + +A corresponding package to each major concept: + +- [x] [Skill](skill/SkillSpec.html "c:run") - Sneak, Attack etc. +- [x] [Feat](feats/Feats.html "c:run") - Toughness, Exotic weapon proficiencies +- [ ] [Race](races/Races.html "c:run") - Playable Races +- [ ] World - Game worlds (Eberron / Forgotten Realms etc) +- [x] [Enhancements](enhancements/Enhancements.html "c:run") - Racial / Class skill trees +- [ ] Epic Destiny - Epic Destiny Trees + +## DDO - Dungeons & Dragons Online :thumbsup: + +:bowtie: +~~strikethrough~~ ~subscript~ + +/play crickets diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/AlignmentsSpec.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/AlignmentsSpec.html new file mode 100644 index 00000000..f55e69e9 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/AlignmentsSpec.html @@ -0,0 +1,35 @@ + + + + Alignments + + + +

Alignments

+

+ Alignments combine the Law (Lawful, Neutral, Chaotic) with the Moral + (Good, Neutral, Evil) This is supported by the Alignment +

+
+

Examples

+
+ + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html new file mode 100644 index 00000000..0b7c84f3 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html @@ -0,0 +1,109 @@ + + + + + Law Axis + + + +

AlignmentSpec - Law Axis

+

+ There are two + Alignment axis. + Lawful and Moral. +

+

Lawful Axis

+ The law axis has three discrete values, which can be derived from case + insensitive string values +
+ + + + + +
Law Axis
+
+

Case Sensitive Operations

+
+ When case insensitivity is true +

+ Then a search for "Lawful,Neutral,Chaotic" should return: (Alpha Sort used for verification) +

+ + + + + + + + + + + + + +
Matching Values
Chaotic
Lawful
Neutral
+
+

Case Insensitive Operations

+
+ When case insensitivity is false +

+ Search for "LAWFUL,neutral,chAotIc" + should return: (Alpha Sort used for verification) +

+
+ Should return + 0 + results +
+
+

Invalid Values

+
+ Invalid values should be gracefully handled. +
+ Search for "Lawful,fake,Doesn't exist" should return: Lawful +

Case-Sensitive?: false

+ + + + + + + +
Matching Values
Lawful
+
+
+ + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html new file mode 100644 index 00000000..98150a5a --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html @@ -0,0 +1,104 @@ + + + + + Moral Axis + + +

Enter Title - Moral Axis

+

+ Simple summary, possibly adding a linkonline external doc for reference +

+

Moral Axis

+ Moral Axis discrete values, which can be derived from case insensitive + string values +
+ +
+

Case Sensitive Operations

+
+ When case insensitivity istrue +

+ Then a search for "Evil,Good,Neutral" should return: (Alpha Sort used for verification) +

+ + + + + + + + + + + + + +
Matching Values
Evil
Good
Neutral
+
+

Case Insensitive Operations

+
+ When case insensitivity is false +

+ Search for "[evIl, GOOD, nEUTrAL]" + should return: (Alpha Sort used for verification) +

+
+ Should return0 + results +
+
+

Invalid Values

+
+ Invalid values should be gracefully filtered out. +
+ Search for "Good,fake,Doesn't existshould return: + +

Case-Sensitive?:false

+ + + + + + + +
Matching Values
Good
+
+
+ + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/destiny/EpicDestinies.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/destiny/EpicDestinies.md new file mode 100644 index 00000000..a3dec43e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/destiny/EpicDestinies.md @@ -0,0 +1 @@ +This is an epic destiny diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.md new file mode 100644 index 00000000..00219480 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.md @@ -0,0 +1,99 @@ +# Apothecary Enhancements + +## [Core](- "setUpTier(#TEXT)") + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| [![ApothecaryDetermination.png](/images/ApothecaryDetermination.png)](https://www.ddowikie.com/page/File:ApothecaryDetermination.png) | **[Determination](https://www.ddowiki.comhttps://www.ddowiki.com/edit/Determination?redlink=1)** | +1 Will Save | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 0 | Requires: Alchemist Level 1 [![ApothecaryAlchemicalShield.png](/images/ApothecaryAlchemicalShield.png)](/page/File:ApothecaryAlchemicalShield.png) | +| | **[Alchemical Shield](https://www.ddowiki.com/edit/Alchemical_Shield?redlink=1)** | While in cloth armor or in Composite Plating, you have a +4 Alchemical bonus to AC and are protected from Magic Missiles. While your Reaction is Verdanite, +5 Positive & Negative Spell Power. | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 5 | Requires: Determination, Alchemist Level 3 | +| [![ApothecaryCurativeAdmixtureCSW.png](/images/ApothecaryCurativeAdmixtureCSW.png)](/page/File:ApothecaryCurativeAdmixtureCSW.png) | **[Curative Admixture: Cure Serious Wounds](https://www.ddowiki.com/edit/Curative_Admixture?redlink=1)** | Curative Admixture Cure Serious Wounds SLA and Curative Admixture Inflict Serious Wounds SLA that share a cooldown. (Gildleaf spells) Passive: + 1 Spell Penetration. While your Reaction is Verdanite, +5 Positive & Negative Spell Power. | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 10 | Requires: Alchemical Shield, Alchemist Level 6 | +| [![ApothecarySpillTheBadStuff.png](/images/ApothecarySpillTheBadStuff.png)](/page/File:ApothecarySpillTheBadStuff.png) | **[Spill the Bad Stuff](https://www.ddowiki.com/edit/Spill_the_Bad_Stuff?redlink=1)** | Gildleaf Offensive SLA: Deals 1d6+4 per Caster Level of a random type of damage to enemies in a short cone. The damage all scales with Positive Spell Power. Affected enemies have a chance to be Blinded, Dazed, Silenced, Tripped, Stunned, or Paralyzed. (Fortitude save negates). Passive: While your Reaction is Verdanite, +2% Positive & Negative Spell Critical Damage & 5% Magical Efficiency (reduced spell point cost) | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 20 | Requires: Curative Admixture, Alchemist Level 12 | +| [![ApothecaryCurativeAdmixtureHeal.png](/images/ApothecaryCurativeAdmixtureHeal.png)](/page/File:ApothecaryCurativeAdmixtureHeal.png) | **[Curative Admixture: Heal](https://www.ddowiki.com/edit/Curative_Admixture:_Heal?redlink=1)** | Curative Admixture Heal SLA and Curative Admixture Harm SLA that share a cooldown (Gildleaf spells). Passive: While your Reaction is Verdanite, +1 Transmutation DC | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 30 | Requires: Spill the Bad Stuff, Alchemist Level 18 | +| [![ApothecaryGeniusNeverDies.png](/images/ApothecaryGeniusNeverDies.png)](/page/File:ApothecaryGeniusNeverDies.png) | **[Genius Never Dies!](https://www.ddowiki.com/edit/Genius_Never_Dies!?redlink=1)** | +4 Intelligence. +20 Concentration. You gain +1000 Unconsciousness Range, the [Diehard](/page/Diehard) feat, and +1 Spell Penetration. +4 Intelligence Passive: While your Reaction is Verdanite, +2 Transmutation DC | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 40 | Requires: Curative Admixture: Heal, Alchemist Level 20 | + +## [Tier1](-) + +[tier1](- "#tier") + +Requires Determination, Alchemist Level 1 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------- | --------------------------------- | ------------------------------ | +| [![ApothecaryCurativeAdmixtureCLW.png](/images/ApothecaryCurativeAdmixtureCLW.png)](/page/File:ApothecaryCurativeAdmixtureCLW.png) | **[Curative Admixture: Cure Light Wounds](/page/Curative_Admixture:_Cure_Light_Wounds "Curative Admixture: Cure Light Wounds")** | Metamagic: Empower, Empower Heal, Maximize, Intensify Spell Point Cost: 4/3/2 Cooldown 12/8/4 seconds Primer Element: Gildleaf Infuses a Cure Light Wounds potion with magical energy, hurling it towards your target in an arc. The potion explodes in a small AOE that deals 1d6+2 plus 1 per caster level (maximum caster level 5) positive energy damage to nearby living allies and enemy undead. This infusion is affected by Artificer/Alchemist Knowledge: Potions. | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 1 | No requirements | +| [![ApothecarySkills.png](/images/ApothecarySkills.png)](/page/File:ApothecarySkills.png) | **[Apothecary Skills](https://www.ddowiki.com/edit/Apothecary_Skills?redlink=1 "Apothecary Skills (page does not exist)")** | +[1/2/3] Haggle, Concentration, and Heal. Rank 3: +1 Will Saves | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 1 | No requirements | +| [![ApothecarySpellCriticalI.png](/images/ApothecarySpellCriticalI.png)](/page/File:ApothecarySpellCriticalI.png) | **[Spell Critical Chance: Positive & Negative I](https://www.ddowiki.com/edit/Spell_Critical_Chance:_Positive_%26_Negative_I?redlink=1 "Spell Critical Chance: Positive & Negative I (page does not exist)")** | +2% chance to critically hit with Positive and Negative Spells. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 1 | No requirements | +| [![ApothecaryEnergyOfTheScholar.png](/images/ApothecaryEnergyOfTheScholar.png)](/page/File:ApothecaryEnergyOfTheScholar.png) | **[Energy of the Scholar](/page/Energy_of_the_Scholar "Energy of the Scholar")** | +[30/60/90] Maximum Spell Points | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 1 | No requirements | +| [![ApothecarySoothingPoultices.png](/images/ApothecarySoothingPoultices.png)](/page/File:ApothecarySoothingPoultices.png) | **[Soothing Poultices](https://www.ddowiki.com/edit/Soothing_Poultices?redlink=1 "Soothing Poultices (page does not exist)")** | While your Reaction is Verdanite, when you cast spells on yourself of allies you grant temporary hitpoints equal to third/half/full Intelligence. These last for three minutes. | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 1 | No requirements | + +## [Tier2](-) + +[tier2](- "#tier") + +Requires Determination, Alchemist Level 2 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------- | --------------------------------- | --------------------------------------------------------------------- | +| [![ApothecaryHaleAndHearty.png](/images/ApothecaryHaleAndHearty.png)](/page/File:ApothecaryHaleAndHearty.png) | **[Hale & Hearty](https://www.ddowiki.com/edit/Hale_%26_Hearty?redlink=1 "Hale & Hearty (page does not exist)")** | +[3/6/10] Positive and Negative Healing Amplification | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 5 | No requirements | +| [![ApothecarySpellCriticalII.png](/images/ApothecarySpellCriticalII.png)](/page/File:ApothecarySpellCriticalII.png) | **[Spell Critical Chance: Positive & Negative II](https://www.ddowiki.com/edit/Spell_Critical_Chance:_Positive_%26_Negative_II?redlink=1 "Spell Critical Chance: Positive & Negative II (page does not exist)")** | +2% chance to critically hit with Positive and Negative Spells. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 5 | Requires: Spell Critical Chance: Positive & Negative I | +| [![ApothecaryStoneOfTheScholar.png](/images/ApothecaryStoneOfTheScholar.png)](/page/File:ApothecaryStoneOfTheScholar.png) | **[Stone of the Scholar](https://www.ddowiki.com/edit/Stone_of_the_Scholar?redlink=1 "Stone of the Scholar (page does not exist)")** | Stone of the Scholar: Alchemist's Stone Toggle: While wielding an Orb in your off-hand, you gain +10 Healing Amplification and +20 Positive Spell Power. You can only have one Alchemist's Stone Toggle active at a time. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 5 | No requirements | +| [![ApothecaryLifeSalve.png](/images/ApothecaryLifeSalve.png)](/page/File:ApothecaryLifeSalve.png) | **[Life Salve](https://www.ddowiki.com/edit/Life_Salve?redlink=1 "Life Salve (page does not exist)")** | Training this Enhancement also grants you a similar ability Death Salve. Target player, hireling, or pet takes 100% base healing from Positive spells for the next 3 minutes (or until target dies.) Has no effect on NPC allies or allies that already take 100% base Positive healing. This overrides their innate base healing from Positive spells for the duration. Shares a cooldown with Death Salve and Converter. _Note: cannot be used on self._ | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 5 | No requirements | + +Note: cannot be used on +self.\_ | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 5 | No requirements | + +## [Tier3](-) + +[tier3](- "#tier") + + +Requires Alchemist level 3, 10 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------- | ---------------------------------- | ---------------------------------------------------------------------- | +| | **[Panacea Poultice](https://www.ddowiki.com/edit/Panacea_Poultice?redlink=1 "Panacea Poultice (page does not exist)")** | (Gildleaf SLA): Target ally at touch range takes the [Panacea](/page/Panacea "Panacea") effect. (6/3/1 spell point, 12/8/6 second cooldown). | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 10 | No requirements | +| | **[Safety Goggles](https://www.ddowiki.com/edit/Safety_Goggles?redlink=1 "Safety Goggles (page does not exist)")** | +[1/2/3] Armor Class and +[2/4/6] Resistance to Fire, Cold, Acid and Electric damage. Rank 3: Blindness Immunity. | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 10 | No requirements | +| | **[Spell Critical Chance: Positive & Negative III](https://www.ddowiki.com/edit/Spell_Critical_Chance:_Positive_%26_Negative_III?redlink=1 "Spell Critical Chance: Positive & Negative III (page does not exist)")** | +2% chance to critically hit with Positive and Negative Spells. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 10 | Requires: Spell Critical Chance: Positive & Negative II | +| | **[Willful Ambition](https://www.ddowiki.com/edit/Willful_Ambition?redlink=1 "Willful Ambition (page does not exist)")** | When your Reaction is Verdanite, you gain +1 Will Save, +1 for every 5 Alchemist Levels you have. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 10 | No requirements | +| | **[Ability I](https://www.ddowiki.com/edit/Ability_I?redlink=1 "Ability I (page does not exist)")** | +1 to either Intelligence or Constitution | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 10 | No requirements | + +## Tier Four [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=5 "Edit section: Tier Four")] + +[tier4](- "#tier") + +Requires Alchemist level 4, 20 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------- | ---------------------------------- | ----------------------------------------------------------------------- | +| | **[Insulated Boots](https://www.ddowiki.com/edit/Insulated_Boots?redlink=1 "Insulated Boots (page does not exist)")** | +[2/4/6] Magical Resistance Rating. Rank 3: You are immune to Slippery Surfaces. Not quite fashionable, but they'll keep you standing! | [AP Cost][ap]: 1 | Ranks: 3 | [Progression][progression_lnk]: 20 | No requirements | +| | **[Spell Critical Chance: Positive & Negative IV](https://www.ddowiki.com/edit/Spell_Critical_Chance:_Positive_%26_Negative_IV?redlink=1 "Spell Critical Chance: Positive & Negative IV (page does not exist)")** | +2% chance to critically hit with Positive and Negative Spells. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 20 | Requires: Spell Critical Chance: Positive & Negative III | +| | **[Run for your life!](https://www.ddowiki.com/edit/Run_for_your_life!?redlink=1 "Run for your life! (page does not exist)")** | While your Reaction is Verdanite, you gain 1% Movement Speed per Alchemist Level. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 20 | No requirements | +| | **[Ability II](https://www.ddowiki.com/edit/Ability_II?redlink=1 "Ability II (page does not exist)")** | +1 to either Intelligence or Constitution | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 20 | Requires: Ability II | + +## Tier Five [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=6 "Edit section: Tier Five")] + +[tier5](- "#tier") + +Requires Alchemist Level 5, Character Level 12, 30 APs spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | -------------- | ---------------------------------- | ---------------------------------------------------------------------- | +| | **[Curative Admixture: Cure or Inflict Critical Wounds](https://www.ddowiki.com/edit/Curative_Admixture:_Cure_or_Inflict_Critical_Wounds?redlink=1 "Curative Admixture: Cure or Inflict Critical Wounds (page does not exist)")** | Curative Admixture: Cure Critical Wounds Or Curative Admixture: Inflict Critical Wounds Metamagic: Empower, Empower Heal, Maximize, Intensify Spell Point Cost: 45 Cooldown 12 seconds Primer Element: Gildleaf Infuses a Cure/Inflict Critical Wounds potion with magical energy, hurling it towards your target in an arc. The potion explodes in a small AOE that deals 4d6+8 plus 1 per caster level (maximum caster level 20) positive/negative energy damage to nearby living allies and enemy undead. | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 30 | No requirements | +| | **[Gloves of the Master Apothecary](https://www.ddowiki.com/edit/Gloves_of_the_Master_Apothecary?redlink=1 "Gloves of the Master Apothecary (page does not exist)")** | +5 Use Magic Device, +10 Universal Spell Power. You have a 15% chance to retain a copy of any single-use Positive, Negative, or Repair Healing Potion that you drink. | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 30 | Requires: Insulated Boots | +| | **[Master Apothecary](https://www.ddowiki.com/edit/Master_Apothecary?redlink=1 "Master Apothecary (page does not exist)")** | You have no Max Caster Level with Curative Admixtures and any Gildleaf Alchemist Spells. +2 To Transmutation DCs, and +1 Spell Penetration | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 30 | Requires: Spell Critical Chance: Positive & Negative IV | +| | **[Dissolve](https://www.ddowiki.com/edit/Dissolve?redlink=1 "Dissolve (page does not exist)")** | Target enemy at touch range that is Fascinated, Sleeping, Dancing, Dazed, Tripped, Mesmerized, Paralyzed, Petrified, or Stunned must make a Fortitude save (d20 + your Heal skill) or die instantly. (20 second cooldown) | [AP Cost][ap]: 2 | Ranks: 1 | [Progression][progression_lnk]: 30 | No requirements | +| | **[Deadly Neurotoxin/Nightshade](https://www.ddowiki.com/edit/Deadly_Neurotoxin/Nightshade?redlink=1 "Deadly Neurotoxin/Nightshade (page does not exist)")** | Choose between Deadly Neurotoxin and Nightshade. Deadly Neurotoxin: Offensive Gildleaf or Ceruleite Spells will reduce your targets Armor Class and Magical Resistance rating by -1 per stack, max 5. Nightshade: Spell point Cost: 10, Cooldown: 30 seconds, Metamagics: Quicken, Accelerate Primer: Gildleaf Target enemy falls asleep for 6 seconds with no save. | [AP Cost][ap]: 1 | Ranks: 1 | [Progression][progression_lnk]: 30 | No requirements | + +Retrieved +from "[https://ddowiki.com/index.php?title=Apothecary_enhancements&oldid=447470](https://ddowiki.com/index.php?title=Apothecary_enhancements&oldid=447470) "[Category](/page/Special:Categories "Special:Categories"): + +[enhancement]: - "#enhancementId" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[setUpTier]: - "#tier = resetTier(#tier)" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" +[description]: - "?=#result.description()" +[apcost]: - "?=#result.apcost()" +[ranks]: - "?=#result.ranks()" +[progression]: - "?=#result.progression()" +[requirements]: - "?=#result.requirements()" +[ap]: https://ddowiki.com/page/Action_point +[progression_lnk]: https://ddowiki.com/page/Progression diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.md new file mode 100644 index 00000000..066acda6 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.md @@ -0,0 +1,65 @@ +# Arcanotechnician Enhancements + +## [Core](- "setUpTier(#TEXT)") + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier1](-) + +[tier1](- "#tier") + +Requires Determination, Alchemist Level 1 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier2](-) + +[tier2](- "#tier") + +Requires Determination, Alchemist Level 2 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier3](-) + +[tier3](- "#tier") + + +Requires Alchemist level 3, 10 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## Tier Four [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=5 "Edit section: Tier Four")] + +[tier4](- "#tier") + +Requires Alchemist level 4, 20 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## Tier Five [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=6 "Edit section: Tier Five")] + +[tier5](- "#tier") + +Requires Alchemist Level 5, Character Level 12, 30 APs spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.md new file mode 100644 index 00000000..10b7e021 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.md @@ -0,0 +1,65 @@ +# Battle Engineer Enhancements + +## [Core](- "setUpTier(#TEXT)") + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier1](-) + +[tier1](- "#tier") + +Requires Determination, Alchemist Level 1 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier2](-) + +[tier2](- "#tier") + +Requires Determination, Alchemist Level 2 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier3](-) + +[tier3](- "#tier") + + +Requires Alchemist level 3, 10 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## Tier Four [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=5 "Edit section: Tier Four")] + +[tier4](- "#tier") + +Requires Alchemist level 4, 20 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## Tier Five [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=6 "Edit section: Tier Five")] + +[tier5](- "#tier") + +Requires Alchemist Level 5, Character Level 12, 30 APs spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BombardierSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BombardierSpec.md new file mode 100644 index 00000000..b8a873b0 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/BombardierSpec.md @@ -0,0 +1,98 @@ +# Bombardier Enhancements + +## [Core](- "setUpTier(#TEXT)") + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | Description (Unvalidated) | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | -------------- | -------------------------- | ----------------------------------------------------------------- | +| | **Alchemical Resistance** | +2 Magical Resistance Rating | AP Cost: 1 | Ranks: 1 | Progression: 0 | Requires: Alchemist Level 1 | +| | **Arcane Oil** | All equipped weapons are considered Spellcasting Implements.
While in Pyrite Reaction, you gain +5 Fire, Cold, Electric, Acid, and Poison Spell Power. | AP Cost: 1 | Ranks: 1 | Progression: 5 | Requires: Alchemical Resistance, Alchemist Level 3 | +| | **Liquid Power I** | Select an Element to specialize in.
Liquid Power Acid: You gain +1 Caster Level with Acid Spells.
Liquid Power Cold: You gain +1 Caster Level with Cold Spells.
Liquid Power Electric: You gain +1 Caster Level with Electric Spells.
Liquid Power Fire: You gain +1 Caster Level with Fire Spells.
Liquid Power Poison: You gain +1 Caster Level with Poison Spells. While in Pyrite Reaction, you gain +5 Fire, Cold, Electric, Acid, and Poison Spell Power | AP Cost: 1 | Ranks: 1 | Progression: 10 | Requires: Arcane Oil, Alchemist Level 6 | +| | **Liquid Power II** | Select an Element to specialize in.
Liquid Power Acid: You gain +1 Caster Level with Acid Spells.
Liquid Power Cold: You gain +1 Caster Level with Cold Spells.
Liquid Power Electric: You gain +1 Caster Level with Electric Spells.
Liquid Power Fire: You gain +1 Caster Level with Fire Spells.
Liquid Power Poison: You gain +1 Caster Level with Poison Spells. While in Pyrite Reaction, you gain +2% Fire, Cold, Electric, Acid, and Poison Spell Critical Damage. | AP Cost: 1 | Ranks: 1 | Progression: 20 | Requires: Liquid Power I, Alchemist Level 12 | +| | **Liquid Power III** | Select an Element to specialize in.
Liquid Power Acid: You gain +1 Caster Level with Acid Spells, and 1 extra Burning Ambition Dice.
Liquid Power Cold: You gain +1 Caster Level with Cold Spells, and 1 extra Burning Ambition Dice.
Liquid Power Electric: You gain +1 Caster Level with Electric Spells, and 1 extra Burning Ambition Dice.
Liquid Power Fire: You gain +1 Caster Level with Fire Spells, and 1 extra Burning Ambition Dice.
Liquid Power Poison: You gain +1 Caster Level with Poison Spells, and 1 extra Burning Ambition Dice. While in Pyrite Reaction, you gain +1 Conjuration DC. | AP Cost: 1 | Ranks: 1 | Progression: 30 | Requires: Liquid Power II, Alchemist Level 18 | +| | **Multivial** | Select an Element to specialize in.
SLA:Multivial of Acid(SP:15, Cooldown:12 seconds)
SLA:Multivial of Frost(SP:15, Cooldown:12 seconds)
SLA:Multivial of Sparks(SP:15, Cooldown:12 seconds)
SLA:Multivial of Flame(SP:15, Cooldown:12 seconds)
SLA:Multivial of Poison(SP:15, Cooldown:12 seconds)Primer Element:Crimsonite (Red),Passive: +4 Intelligence, and 2 extra Burning Ambition Dice. While in Pyrite Reaction, you gain +2 Conjuration DCs. | AP Cost: 1 | Ranks: 1 | Progression: 40 | Requires: Liquid Power III, Alchemist Level 20 | + +## [Tier1](-) + +[[edit](https://www.ddowiki.com/edit/Bombardier_enhancements?section=2 "Edit section: Tier One")] +[tier1](- "#tier") + +Alchemical Resistance, Alchemist Level 1 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | Description (Unvalidated) | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------ | ------------------------------ | +| | **[Spellvial Selection](https://www.ddowiki.com/edit/Spellvial_Selection?redlink=1 "Spellvial Selection (page does not exist)")** | Select an Element to specialize in.
SLA:[Vial of Acid](https://www.ddowiki.com/page/Vial_of_Acid "Vial of Acid")
SLA:[Vial of Frost](https://www.ddowiki.com/page/Vial_of_Frost "Vial of Frost")
SLA:[Vial of Sparks](https://www.ddowiki.com/page/Vial_of_Sparks "Vial of Sparks")
SLA:[Vial of Flame](https://www.ddowiki.com/page/Vial_of_Flame "Vial of Flame")
SLA:[Vial of Venom](https://www.ddowiki.com/page/Vial_of_Venom "Vial of Venom")Metamagic: Empower, Maximize, Quicken, Heighten, Enlarge, Eschew MaterialsSpell Point Cost: 4/2/1Cooldown 12/8/4 secondsPrimer Element:Crimsonite (Red)Conjuring a bottle of (element), you throw a projectile at a single foe that deals 3 to 8 (element) damage per caster level, max caster level 10. DND Dice: Deals 1d6+2 (element) damage per caster level, max 10d6+20 | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 1 | No requirements | +| | **[Arcane Knowledge](https://www.ddowiki.com/edit/Arcane_Knowledge?redlink=1 "Arcane Knowledge (page does not exist)")** | +[1/2/3] to Spellcraft and Use Magic Device | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 1 | No requirements | +| | **[Magical Subtlety](https://www.ddowiki.com/edit/Magical_Subtlety?redlink=1 "Magical Subtlety (page does not exist)")** | -[20/40/60]% Threat with Spells | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 1 | No requirements | +| | **[Spell Critical: Elemental and Poison I](https://www.ddowiki.com/edit/Spell_Critical:_Elemental_and_Poison_I?redlink=1 "Spell Critical: Elemental and Poison I (page does not exist)")** | Your Acid, Cold, Electric, Fire, and Poison damage spells have an additional 1% chance to critically hit. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 1 | No requirements | +| | **[Wand and Scroll Mastery](https://www.ddowiki.com/page/Wand_and_Scroll_Mastery "Wand and Scroll Mastery")** | +[25/50/75]% damage and healing from your wands, scrolls, and other items that cast spells, and +[1/3/6] to the save DCs of your offensive wands. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 1 | No requirements | + +## Tier Two [[edit](https://www.ddowiki.com/edit/Bombardier_enhancements?section=3 "Edit section: Tier Two")] + +[tier2](- "#tier") + +Requires Alchemist level 2, 5 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | Description (Unvalidated) | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------- | +| | **[Spell-Like Ability: Rapid Condensation](https://www.ddowiki.com/edit/SLA:_Rapid_Condensation?redlink=1 "SLA: Rapid Condensation (page does not exist)")** | Spell Like Ability:[Rapid Condensation](https://www.ddowiki.com/page/Rapid_Condensation "Rapid Condensation")Metamagic: Quicken, AccelerateSpell Point Cost: 4/3/2Cooldown 12/8/4 secondsPrimer Element:Gildleaf (Yellow), Throw a bottle that explodes on impact, rapidly condensing water in the air with a magical reaction that forms a cloud of obscuring mist. This cloud obscures all friends within the area, granting them 20% Concealment. Fire spells will burn this chemical reaction out of the air, dispelling it. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 5 | No requirements | +| | **[Efficient Metamagics I](https://www.ddowiki.com/edit/Efficient_Metamagics_I?redlink=1 "Efficient Metamagics I (page does not exist)")** | Select a Metamagic Feat to enhance.
Efficient Empower: Using the Empower Spell Metamagic costs you 2/4/6 fewer Spell Points.
Efficient Maximize: Using the Maximize Spell Metamagic costs you 3/6/9 fewer Spell Points.
Efficient Quicken: Using the Quicken Spell Metamagic costs you 1/2/4 fewer Spell Points. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 5 | No requirements | +| | **[Stone of the Savant](https://www.ddowiki.com/edit/Stone_of_the_Savant?redlink=1 "Stone of the Savant (page does not exist)")** | Alchemist's Stone Toggle: While wielding an Orb in your off-hand, you gain +1 Magical Resistance Rating and Magical Resistance Rating Cap per Alchemist Level. You can only have one [Alchemist's Stone](https://www.ddowiki.com/edit/Alchemist%27s_Stone?redlink=1 "Alchemist's Stone (page does not exist)") Toggle active at a time. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 5 | No requirements | +| | **[Spell Critical: Elemental and Poison II](https://www.ddowiki.com/edit/Spell_Critical:_Elemental_and_Poison_II?redlink=1 "Spell Critical: Elemental and Poison II (page does not exist)")** | Your Acid, Cold, Electric, Fire, and Poison damage spells have an additional 1% chance to critically hit. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 5 | Requires: Spell Critical: Elemental and Poison I | +| | **[Elemental Defenses](https://www.ddowiki.com/edit/Elemental_Defenses?redlink=1 "Elemental Defenses (page does not exist)")** | When enemy spells deal elemental damage against you, there's a 25% chance you'll gain [10/20/30] temporary hitpoints for 30 seconds. This can trigger up to once every 12 seconds. (Elemental Damage includes Acid, Cold, Electric, Fire, Sonic.) | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 5 | No requirements | + +## [Tier3](-) Tier Three [[edit](https://www.ddowiki.com/edit/Bombardier_enhancements?section=4 "Edit section: Tier Three")] + +[tier3](- "#tier") + +Requires Alchemist level 3, 10 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | Description (Unvalidated) | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| | **[Efficient Metamagics II](https://www.ddowiki.com/edit/Efficient_Metamagics_II?redlink=1 "Efficient Metamagics II (page does not exist)")** | Select a Metamagic Feat to enhance.
Efficient Empower: Using the Empower Spell Metamagic costs you 2/4/6 fewer Spell Points.
Efficient Maximize: Using the Maximize Spell Metamagic costs you 3/6/9 fewer Spell Points.
Efficient Quicken: Using the Quicken Spell Metamagic costs you 1/2/4 fewer Spell Points. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 10 | Requires: Efficient Metamagics I | +| | **[Swift Ambition](https://www.ddowiki.com/edit/Swift_Ambition?redlink=1 "Swift Ambition (page does not exist)")** | While your Reaction is Pyrite, you gain +1 Reflex Save, +1 for every 5 Alchemist levels you have. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 10 | No requirements | +| | **[Spell Critical: Elemental and Poison III](https://www.ddowiki.com/edit/Spell_Critical:_Elemental_and_Poison_III?redlink=1 "Spell Critical: Elemental and Poison III (page does not exist)")** | Your Acid, Cold, Electric, Fire, and Poison damage spells have an additional 1% chance to critically hit. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 10 | Requires: Spell Critical: Elemental and Poison II | +| | **[Ability I](https://www.ddowiki.com/edit/Ability_I?redlink=1 "Ability I (page does not exist)")** | +1 to Intelligence | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 10 | No requirements | + +## Tier Four [[edit](https://www.ddowiki.com/edit/Bombardier_enhancements?section=5 "Edit section: Tier Four")] + +[tier4](- "#tier") + +Requires Alchemist level 4, 20 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | Description (Unvalidated) | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------- | +| | **[Spell-Like Ability: Smoke Bomb](https://www.ddowiki.com/edit/Spell_Like_Ability:_Smoke_Bomb?redlink=1 "Spell Like Ability: Smoke Bomb (page does not exist)")** | SLA: Smoke BombMetamagic: Extend, Quicken, Eschew MaterialsSpell Point Cost: 25/20/15Cooldown 12 secondsPrimer Element:Gildleaf (Yellow), Throw a bottle beneath you that explodes into a cloud of smoke and leaves you Invisible and Displaced for 12 seconds. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 20 | No requirements | +| | **[Efficient Heighten](https://www.ddowiki.com/page/Efficient_Heighten "Efficient Heighten")** | Using the Heighten Spell Metamagic costs you [1/2] fewer Spell Point per heightened level. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 2 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 20 | Requires: Efficient Metamagics II | +| | **[Burning Ambition](https://www.ddowiki.com/edit/Burning_Ambition?redlink=1 "Burning Ambition (page does not exist)")** | When your Reaction is Pyrite, your offensive Crimsonite and Gildleaf Alchemist spells will ignite your enemies with magic, dealing additional damage. This damage determines its element based on the element of the spell cast. This ability begins at 1d4 damage, adding another 1d4 for each Burning Ambition die you get from other abilities. This damage scales with Spell Power. \*Note: Burning Ambition will proc multiple times on spells that have multiple hits. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 20 | No requirements | +| | **[Spell Critical: Elemental and Poison IV](https://www.ddowiki.com/edit/Spell_Critical:_Elemental_and_Poison_IV?redlink=1 "Spell Critical: Elemental and Poison IV (page does not exist)")** | Your Acid, Cold, Electric, Fire, and Poison damage spells have an additional 1% chance to critically hit. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 20 | Requires: Spell Critical: Elemental and Poison III | +| | **[Ability II](https://www.ddowiki.com/edit/Ability_II?redlink=1 "Ability II (page does not exist)")** | +1 to Intelligence | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 20 | Requires: Ability I | + +## Tier Five [[edit](https://www.ddowiki.com/edit/Bombardier_enhancements?section=6 "Edit section: Tier Five")] + +[tier5](- "#tier") + + +Requires Alchemist Level 5, Character Level 12, 30 APs spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | Description (Unvalidated) | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------- | ----------------------------------------- | +| | **[Elemental Obliteration](https://www.ddowiki.com/page/Elemental_Obliteration "Elemental Obliteration")** | Select an Element for an explosive spell.
SLA: Caustic Obliteration
SLA: Fiery Obliteration
SLA: Frost Obliteration
SLA: Poison Obliteration
SLA: Voltaic ObliterationSpell Like Ability:[Elemental Obliteration](https://www.ddowiki.com/page/Elemental_Obliteration "Elemental Obliteration")Metamagic: Empower, Maximize, Quicken, HeightenSpell Point Cost: 12/8/6Cooldown 12/8/6 secondsPrimer Element:Crimsonite (Red), Throw a vial that explodes with (element) on impact, dealing 1d6+3 (element) damage per Caster Level to all enemies nearby. (Max Caster Level 10) | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 30 | No requirements | +| | **[Augmentation](https://www.ddowiki.com/page/Augmentation "Augmentation")** | +2 Caster Levels with Crimsonite and Gildleaf spells. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 30 | No requirements | +| | **[Inferno of Creation](https://www.ddowiki.com/edit/Inferno_of_Creation?redlink=1 "Inferno of Creation (page does not exist)")** | When your Reaction is Pyrite, you gain +1 Burning Ambition die, and your harmful Crimsonite spells apply a stack of vulnerability to enemies that have at least 3 different elements of Burning Ambition.
Vulnerable: You take 1% more damage for 3 seconds. This effect stacks up to 20 times, and loses one stack on expiration. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 30 | Requires: Burning Ambition | +| | **[Conjuration Focus](https://www.ddowiki.com/page/Conjuration_Focus "Conjuration Focus")** | +2 to Conjuration DCs | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 30 | No requirements | +| | **[Weakening Mixture](https://www.ddowiki.com/edit/Weakening_Mixture?redlink=1 "Weakening Mixture (page does not exist)")** | Select an Element to specialize in.
Weakening Mixture Acid: When cast an Acid spell on a creature that is immune to Acid, it makes them vulnerable to Acid for a short period of time.
Weakening Mixture Cold: When cast on a Cold spell on a creature that is immune to Cold, it makes them vulnerable to Cold for a short period of time.
Weakening Mixture Electric: When cast an Electric spell on a creature that is immune to Electric, it makes them vulnerable to Electric for a short period of time.
Weakening Mixture Fire: When cast on a Fire spell on a creature that is immune to Fire, it makes them vulnerable to Fire for a short period of time.
Weakening Mixture Poison: When cast on a Poison spell on a creature that is immune to Poison, it makes them vulnerable to Poison for a short period of time. Note: Any spell of the proper element can remove immunities. Tested working for Sorcerer, Alchemist, and Artificer spells. | [AP Cost](https://www.ddowiki.com/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](https://www.ddowiki.com/page/Progression "Progression"): 30 | No requirements | + +Retrieved +from "[https://ddowiki.com/index.php?title=Bombardier_enhancements&oldid=437703](https://ddowiki.com/index.php?title=Bombardier_enhancements&oldid=437703) "[Category](https://www.ddowiki.com/page/Special:Categories "Special:Categories"): + +[enhancement]: - "#enhancementId" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[setUpTier]: - "#tier = resetTier(#tier)" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" +[description]: - "?=#result.description()" +[apcost]: - "?=#result.apcost()" +[ranks]: - "?=#result.ranks()" +[progression]: - "?=#result.progression()" +[requirements]: - "?=#result.requirements()" +[ap]: https://ddowiki.comhttps://www.ddowiki.com/page/Action_point +[progression_lnk]: https://ddowiki.comhttps://www.ddowiki.com/page/Progression diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/EnhancementTree.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/EnhancementTree.html new file mode 100644 index 00000000..dc77c27f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/EnhancementTree.html @@ -0,0 +1,678 @@ + + + + EnhancementTree + + + + +

EnhancementTree

+

Description

+
+

Examples

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Alchemist + + Artificer + Dog + + Barbarian + + Bard + + Cleric +
+ Apo + Bom + VCh + + AT + BE + RM + + FB + OS + Rav + + SB + SS + WC + + DD + RS + War +
+ Druid + Wolf + + Fighter + + Favored Soul + + + Monk + + Paladin +
+ NW + NP + SH + + Ken + StD + Van + + AoV + BoH + War + + HeM + NiS + Shi + + KotC + SaD + Van +
+ Ranger + + Rogue + + Sorcerer + + Wizard + + Warlock +
+ AA + DWS + Tem + + Ass + Mec + TA + + AS + ES + FS + WS + EK + + AM + EK + PM + + ES + SE + TS +
+

+ Falconry +     ~     + Illusionist +     ~     + Harper +     ~     + Inquisitive +     ~     + Vistani + +

+
+ Reaper +
+ + + + + + + + + + + + + + + + + + + +
+ Aasimar + + Dragonborn + + Drow + + Dwarf + + Elf + / + W-Elf + (& + AA) + + Gnome +
+ Half-Elf + (& + AA) + + Half-Orc + + Halfling + + Human + + Tiefling + + Warforged +
+ + + + + + + + + + + + +
+ Bladeforged + + Deep Gnome + + Morninglord + (& + AA) + + PDK + + Scoundrel + + Scourge + + Shadar-kai +
+
+ + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/Enhancements.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/Enhancements.md new file mode 100644 index 00000000..267992ca --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/Enhancements.md @@ -0,0 +1,6 @@ +# Enhancements + +Conflict when spec name follows folder name for breadcrumbs as we then have two "Enhancement.java/scala" in the same +package. + +- [x] [Enhancement](EnhancementTree.html "c:run") - Prestige and other Enhancements diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.md new file mode 100644 index 00000000..cce9bdd6 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.md @@ -0,0 +1,65 @@ +# FrenziedBerserker Enhancements + +## [Core](- "setUpTier(#TEXT)") + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier1](-) + +[tier1](- "#tier") + +Requires Determination, Alchemist Level 1 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier2](-) + +[tier2](- "#tier") + +Requires Determination, Alchemist Level 2 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## [Tier3](-) + +[tier3](- "#tier") + + +Requires Alchemist level 3, 10 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## Tier Four [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=5 "Edit section: Tier Four")] + +[tier4](- "#tier") + +Requires Alchemist level 4, 20 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +## Tier Five [[edit](https://www.ddowiki.com/edit/Apothecary_enhancements?section=6 "Edit section: Tier Five")] + +[tier5](- "#tier") + +Requires Alchemist Level 5, Character Level 12, 30 APs spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------ | -------------------------- | ----------------- | -------------- | -------------------------- | ------------ | + +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.md new file mode 100644 index 00000000..4dad9662 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.md @@ -0,0 +1 @@ +# OccultSlayerSpec diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RavagerSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RavagerSpec.md new file mode 100644 index 00000000..c5d3b3c8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RavagerSpec.md @@ -0,0 +1 @@ +# RavagerSpec diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.md new file mode 100644 index 00000000..0a8d105f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.md @@ -0,0 +1 @@ +# RenegadeMastermakerSpec diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/VileChemistSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/VileChemistSpec.md new file mode 100644 index 00000000..3b2d328d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/enhancements/VileChemistSpec.md @@ -0,0 +1,96 @@ +# Vile Chemist Enhancements + +## [Core](- "setUpTier(#TEXT)") Core abilities [[edit](/edit/Vile_Chemist_enhancements?section=1 "Edit section: Core abilities")] + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | -------------- | -------------------------------------------------- | --------------------------------------------------------------- | +| | **[Poisoner](/edit/Poisoner?redlink=1 "Poisoner (page does not exist)")** | +2 to saves vs. Poisons, +2 to saves vs. Diseases. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 0 | Requires: Alchemist Level 1 | +| | **[Poisoned Coating](/edit/Poisoned_Coating?redlink=1 "Poisoned Coating (page does not exist)")** | Toggle: While active, deal an additional 1d6 Poison damage on hit. You gain an additional 1d6 every 3 Alchemist levels (at 6, 9, 12, 15 and 18). This damage scales with Spell Power.Passive: While your Reaction is Orchidium, +5 Physical Resistance Rating.Note: mutually exclusive with Spellsword toggle (Eldritch Knight). | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 5 | Requires: Poisoner, Alchemist Level 3 | +| | **[Hidden Blades](/edit/Hidden_Blades?redlink=1 "Hidden Blades (page does not exist)")** | +3% Doublestrike and Doubleshot. Passive: While your Reaction in Orchidium, +5 Physical Resistance Rating. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 10 | Requires: Poisoned Coating, Alchemist Level 6 | +| | **[More Hidden Blades](/edit/More_Hidden_Blades?redlink=1 "More Hidden Blades (page does not exist)")** | +10 Universal Spell Power, +5% Doublestrike and Doubleshot.Your Poisoned Coating dice are now d8s (instead of the original d6s). If you have Simple Thrown Expertise, you now use the higher of your Intelligence and Dexterity to determine how much Doubleshot you gain from that feat. Passive: While your Reaction is Orchidium, +5% Dodge and full Base Attack Bonus. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 20 | Requires: Hidden Blades, Alchemist Level 12 | +| | **[Brushed Aside](/edit/Brushed_Aside?redlink=1 "Brushed Aside (page does not exist)")** | You gain the Defensive Roll feat (While below 20% HP, there's a chance equal to your Reflex save that attacks do half damage and have their effects negated).Your Poisoned Coating Dice are now d10s (Replacing previous d8s). While holding a Simple Weapon in your Main Hand and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand, you have +1 Competence bonus to Critical Damage Multiplier. Passive: While your Reaction is Orchidium, +5 Physicial Resistance rating and +5% Dodge Cap. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 30 | Requires: More Hidden Blades, Alchemist Level 18 | +| | **[Venom's Grip](/edit/Venom%27s_Grip?redlink=1 "Venom's Grip (page does not exist)")** | Passive: +4 Intelligence. Your Poisoned Coating die size is now d12.
assive: While your Reaction is Orchidium, +10 Physicial Resistance rating and +5% Dodge Cap. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 40 | Requires: Brushed Aside, Alchemist Level 20 | + +## Tier One [[edit](/edit/Vile_Chemist_enhancements?section=2 "Edit section: Tier One")] + +[tier1](- "#tier") + +Requires Determination, Alchemist Level 1 + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | -------------- | ------------------------------------------------- | ------------------------------ | +| | **[Spell Like Ability: Stiffen Skin](/edit/Spell_Like_Ability:_Stiffen_Skin?redlink=1 "Spell Like Ability: Stiffen Skin (page does not exist)")** | SLA: Stiffen SkinMetamagic: Extend, Quicken Spell Point Cost: 8/4/2 Cooldown 20/16/12 seconds Primer Element: Ceruleite This potion will mutate you and make your skin a little bit more resistant to physical damage. This grants a +2 Deflection bonus to AC, +1 per 6 caster levels, for 1 minute per caster level. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 1 | No requirements | +| | **[Deadly Poison I](/edit/Deadly_Poison_I?redlink=1 "Deadly Poison I (page does not exist)")** | You gain +2 to hit and +1 to damage while holding a Simple Weapon in your Main Hand and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 1 | No requirements | +| | **[Alchemical Accuracy](/edit/Alchemical_Accuracy?redlink=1 "Alchemical Accuracy (page does not exist)")** | +[1/2/3] to attack. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 1 | No requirements | +| | **[Magical Subtlety](/edit/Magical_Subtlety?redlink=1 "Magical Subtlety (page does not exist)")** | -[20/30/40]% threat generation with melee attacks.Antirequisite: This enhancement cannot be taken at the same time as Subtlety enhancements in other trees.
\*\*Bug: This enhancement can be taken at the same time as the Subtlety enhancement from Ninja Spy.
| [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 1 | No requirements | +| | **[Vile Skills](/edit/Vile_Skills?redlink=1 "Vile Skills (page does not exist)")** | +[1/2/3] Hide, Move Silently, and Bluff
Rank 3: +1 Reflex Saving throws. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 1 | No requirements | + +## Tier Two [[edit](/edit/Vile_Chemist_enhancements?section=3 "Edit section: Tier Two")] + +[tier2](- "#tier") + +Requires Alchemist level 2, 5 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- | -------------- | ------------------------------------------------- | ---------------------------------------- | +| | **[Deadly Poison II](/edit/Deadly_Poison_II?redlink=1 "Deadly Poison II (page does not exist)")** | You gain +2 to hit and +1 to damage while holding a Simple Weapon in your Main Hand and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 5 | Requires: Deadly Poison I | +| | **[Poisoned Attack](/edit/Poisoned_Attack?redlink=1 "Poisoned Attack (page does not exist)")** | Choose from either a Melee or Ranged attack.
Poisoned Shot: Ranged Attack: +[1/2/3][W]: On successful damage, your opponent is Contaminated. Using this attack acts as if you cast a Crimsonite spell. Rank 3: When you hit a target that is immune to Poisons or Poison Damage with this attack, they become vulnerable to Poisons and Poison Damage for 20 seconds.
Poisoned Strike: Melee Attack: +[1/2/3][W]: On successful damage, your opponent is Contaminated. Using this attack acts as if you cast a Crimsonite spell. Rank 3: When you hit a target that is immune to Poisons or Poison Damage with this attack, they become vulnerable to Poisons and Poison Damage for 20 seconds.Note: hits all enemies in a 180 degree cone in front of you like a cleave. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 5 | No requirements | +| | **[Venom Affinity](/edit/Venom_Affinity?redlink=1 "Venom Affinity (page does not exist)")** | +[3/6/10] Poison Spell Power
Rank 3: +1 Reflex Saving throws. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 5 | No requirements | +| | **[Stone of the Subliminal](/edit/Stone_of_the_Subliminal?redlink=1 "Stone of the Subliminal (page does not exist)")** | Alchemist's Stone Toggle: While wielding an Orb in your off-hand, you gain +5% Doublestrike, +5% Doubleshot, and Blur. You can only have one Alchemist's
Stone Toggle active at a time. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 5 | No requirements | + +## Tier Three [[edit](/edit/Vile_Chemist_enhancements?section=4 "Edit section: Tier Three")] + +[tier3](- "#tier") + +Requires Alchemist level 3, 10 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | -------------- | -------------------------------------------------- | ----------------------------------------- | +| | **[Spell Like Ability: Wave of Poison](/edit/Spell_Like_Ability:_Wave_of_Poison?redlink=1 "Spell Like Ability: Wave of Poison (page does not exist)")** | SLA: Wave of PoisonMetamagic: Empower, Maximize, Quicken, Intensify Spell Point Cost: 8/6/4 Cooldown 12/10/6 seconds Primer Element: Ceruleite You infect enemies in a short cone with a deadly poison that eats away at them. Affected enemies take 2d4 Poison damage plus 1 Poison damage per 2 Caster Levels every 2 seconds for 12 seconds. This poison will leave enemies Contaminated. (Max Caster Level: 10) When you hit a target that is immune to Poisons or Poison damage with this spell, they become vulnerable to Poisons and Poison Damage for 12 seconds. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 10 | No requirements | +| | **[Deadly Poison III](/edit/Deadly_Poison_III?redlink=1 "Deadly Poison III (page does not exist)")** | You gain +2 to hit and +1 to damage while holding a Simple Weapon in your Main Hand and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 10 | Requires: Deadly Poison II | +| | **[Toxic Augmentation](/edit/Toxic_Augmentation?redlink=1 "Toxic Augmentation (page does not exist)")** | Your strikes against Contaminated enemies reduce their Fortitude saves by -1 for 6 seconds. This effect stacks up to 4 times. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 10 | No requirements | +| | **[Willful Ambition](/edit/Willful_Ambition?redlink=1 "Willful Ambition (page does not exist)")** | When your Reaction is Orchidium, you gain +1 Fortitude Save, +1 for every 5 Alchemist Levels you have. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 10 | No requirements | +| | **[Ability I](/edit/Ability_I?redlink=1 "Ability I (page does not exist)")** | +1 to either Dexterity or Intelligence | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 10 | No requirements | + +## Tier Four [[edit](/edit/Vile_Chemist_enhancements?section=5 "Edit section: Tier Four")] + +[tier4](- "#tier") + +Requires Alchemist level 4, 20 APS spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | -------------- | -------------------------------------------------- | ------------------------------------------ | +| | **[Deadly Poison IV](/edit/Deadly_Poison_IV?redlink=1 "Deadly Poison IV (page does not exist)")** | You gain +2 to hit and +1 to damage while holding a Simple Weapon in your Main Hand and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 20 | Requires: Deadly Poison III | +| | **[Venom Affinity](/edit/Venom_Affinity?redlink=1 "Venom Affinity (page does not exist)")** | +[5/10/15] Poison Spell Power.
Rank 3: +1 Reflex Saving Throws | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 3 | [Progression](/page/Progression "Progression"): 20 | No requirements | +| | **[Unbreakable Ambition](/edit/Unbreakable_Ambition?redlink=1 "Unbreakable Ambition (page does not exist)")** | While your Reaction is Orchidium, +8 Physical Resistance Rating. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 20 | No requirements | +| | **[Ability I](/edit/Ability_I?redlink=1 "Ability I (page does not exist)")** | +1 to either Dexterity or Intelligence | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 20 | Requires: Ability I | + +## Tier Five [[edit](/edit/Vile_Chemist_enhancements?section=6 "Edit section: Tier Five")] + +[tier5](- "#tier") + +Requires Alchemist Level 5, Character Level 12, 30 APs spent in tree + +| Icon | [ ][setUpEnhancement] [Enhancement][enhancement] | [Description][description] | [AP Cost][apcost] | [Ranks][ranks] | [Progression][progression] | Requirements | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | -------------- | -------------------------------------------------- | ----------------------------------------- | +| | **[Spell Like Ability: Greater Wave of Poison](/edit/Spell_Like_Ability:_Greater_Wave_of_Poison?redlink=1 "Spell Like Ability: Greater Wave of Poison (page does not exist)")** | SLA: Greater Wave of PoisonMetamagic: Empower, Maximize, Quicken, Intensify Spell Point Cost: 8 Cooldown 10 seconds Primer Element: Ceruleite You infect enemies in a short cone with a deadly poison that eats away at them. Affected enemies take 2d6 Poison damage plus 1 Poison damage per Caster Level every 2 seconds for 16 seconds. This poison will leave enemies Contaminated. (Max Caster Level: 20) When you hit a target that is immune to Poisons or Poison damage with this spell, they become vulnerable to Poisons and Poison Damage for 12 seconds. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 30 | No requirements | +| | **[Fatal Poison](/edit/Fatal_Poison?redlink=1 "Fatal Poison (page does not exist)")** | While holding a Simple Weapon in your Main Hand and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand, you gain +2 to hit, +1 damage, and +1 Competence Bonus to Critical Range. For Darts, this Range bonus is +2 instead. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 30 | Requires: Deadly Poison IV | +| | **[Contaminated Strikes](/edit/Contaminated_Strikes?redlink=1 "Contaminated Strikes (page does not exist)")** | When you strike a Contaminated enemy, they gain one stack of Vulnerable. Contaminate enemies by using Poison Alchemical Spells.
Vulnerable: You take 1% more damage for 3 seconds. This effect stacks up to 20 times, and loses one stack on expiration. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 30 | No requirements | +| | **[Chemical Weapon](/edit/Chemical_Weapon?redlink=1 "Chemical Weapon (page does not exist)")** | Your Simple Weapons gain +1[W].
Simple Thrown Weapons you wield also gain +15% Attack Speed as long as you are holding a Simple Weapon, Orb, Rune Arm, or nothing in your off hand. | [AP Cost](/page/Action_point "Action point"): 2 | Ranks: 1 | [Progression](/page/Progression "Progression"): 30 | No requirements | +| | **[Sapping Ambition](/edit/Sapping_Ambition?redlink=1 "Sapping Ambition (page does not exist)")** | While your Reaction is Orchidium, you have a Simple Weapon in your Main Hand, and a Simple Weapon, Orb, Rune Arm, or nothing in your off hand, attacking grants a 10% chance to gain 10 Temporary Spell Points, +1 per Alchemist level. | [AP Cost](/page/Action_point "Action point"): 1 | Ranks: 1 | [Progression](/page/Progression "Progression"): 30 | No requirements | + +Retrieved +from "[https://ddowiki.com/index.php?title=Vile_Chemist_enhancements&oldid=443424](https://ddowiki.com/index.php?title=Vile_Chemist_enhancements&oldid=443424) "[Categories](/page/Special:Categories "Special:Categories"): + +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" +[ranks]: - "?=#result.ranks()" +[apcost]: - "?=#result.apcost()" +[description]: - "?=#result.description()" +[progression]: - "?=#result.progression()" +[enhancement]: - "#enhancementId" +[setUpEnhancement]: - "#result = loadFromKey(#enhancementId)" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/DodgeSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/DodgeSpec.md new file mode 100644 index 00000000..43562a8a --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/DodgeSpec.md @@ -0,0 +1 @@ +# Dodge diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatEffectSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatEffectSpec.md new file mode 100644 index 00000000..a1aceed5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatEffectSpec.md @@ -0,0 +1,17 @@ +# FeatEffectSpec + +## Verify Known Tactical Feats + +| [ ][existingFeat] [Feats][result] | +| --------------------------------- | +| ImprovedSunder | +| ImprovedTrip | +| QuiveringPalm | +| StunningBlow | +| StunningFist | +| Sunder | +| Trip | + +[existingFeat]: - "c:verify-rows=#feat:tacticalFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/Feats.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/Feats.html new file mode 100644 index 00000000..f233a969 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/Feats.html @@ -0,0 +1,267 @@ + + + + Feats + + + +

Feats

+

Feats allow a player to perform a specific action.

+

Feats in DDO are broken down by the following categories:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Class Feats + - Based on character class such as a rogue's sneak attack + + Spec + Icon Class feats.png +
+ Dragonmark Feats + - Special abilities given based on heritage. + + Spec + DragonmarkofFinding.png +
+ Feats (General) + + Spec + Icon General feats.png +
+ Metamagic - Augments power, duration, range or makes spell + casting more efficient. + + Spec + Icon Feat Maximize Spell.png +
+ Racial Feats + - Are specific to race such as Half-elven dilettantes and + Warforged plating. + + Spec + Icon Racial feats.png +
+ Deity Feats + - Abilities given by a patron deity + + Spec + Icon Racial feats.png +
+ Epic Feats + - Advanced, High level feats for Character levels 20+ + + Spec + Icon Epic feats.png +
+ Epic Destiny Feats + - Feats accessible based on your epic destiny (level 21+) + + Spec + Icon Epic Destiny feats.png +
+ Legendary Feats + - Available to level 30 characters + + Spec + Icon Epic feats.png +
+ Heroic PL Feats + - attained by achieving levels 1 - 20 and starting a new + life + + Spec + Icon Past life feats.png +
+ Epic PL Feats + - attained by achieving levels 21 - 30 and reincarnating + + Spec + Icon Epic life feats.png +
+ + Iconic PL Feats‎ + - Past life feats available to characters levetdng through + all iconic levels. + + Spec + Icon Iconic Past life feats.png +
+ + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatsMd.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatsMd.md new file mode 100644 index 00000000..dce1db7b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/FeatsMd.md @@ -0,0 +1,109 @@ +# [Feats](#feats) + +Feats allow a player to perform a specific action. + +Feats in DDO are broken down by the following categories: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[Class Feats](http://ddowiki.com/page/Category:Class_feats "Category:Class feats") - Based on character class such as a rogue's sneak attack[Spec](classes/Classes.html) [![Icon Class feats.png](/images/Icon_Class_feats.png)](http://ddowiki.com/page/Category:Class_feats "Category:Class feats")
[Dragonmark Feats](http://ddowiki.com/page/Dragonmarks "Dragonmarks") - Special abilities given based on heritage.[Spec](dragonmarks/dragonmarks.html) [![DragonmarkofFinding.png](/images/DragonmarkofFinding.png)](http://ddowiki.com/page/Dragonmarks "Dragonmarks")
[Feats (General)](http://ddowiki.com/page/Feats "Feats")[Spec](GeneralFeatSpec.html) [![Icon General feats.png](/images/Icon_General_feats.png)](http://ddowiki.com/page/Feats "Feats")
Metamagic - Augments power, duration, range or makes spell casting more efficient.[Spec](metamagic/MetaMagic.html) [![Icon Feat Maximize Spell.png](/images/Icon_Feat_Maximize_Spell.png)](http://ddowiki.com/page/Feats/Metamagic "Feats/Metamagic")
[Racial Feats](http://ddowiki.com/page/Category:Racial_feats "Category:Racial feats") - Are specific to race such as Half-elven dilettantes and Warforged plating.[Spec](races/Races.html) [![Icon Racial feats.png](/images/Icon_Racial_feats.png)](http://ddowiki.com/page/Category:Racial_feats "Category:Racial feats")
[Deity Feats](http://ddowiki.com/page/Deity_feats "Deity feats") - Abilities given by a patron deity[Spec](deity/DeityFeatSpec.html) [![Icon Racial feats.png](/images/Icon_Racial_feats.png)](http://ddowiki.com/page/Deity_feats "Deity feats")
[Epic Feats](http://ddowiki.com/page/Epic_Feats "Epic Feats") - Advanced, High level feats for Character levels 20+[Spec](epic/Epic.html) [![Icon Epic feats.png](/images/Icon_Epic_feats.png)](http://ddowiki.com/page/Epic_Feats "Epic Feats")
[Epic Destiny Feats](http://ddowiki.com/page/Epic_Destiny_Feats "Epic Destiny Feats") - Feats accessible based on your epic destiny (level 21+)[Spec](EpicDestinyFeatSpec.html) [![Icon Epic Destiny feats.png](/images/Icon_Epic_Destiny_feats.png)](http://ddowiki.com/page/Epic_Destiny_Feats "Epic Destiny Feats")
[Legendary Feats](http://ddowiki.com/page/Legendary_Feats "Legendary Feats") - Available to level 30 characters[Spec](LegendaryFeatSpec.html) [![Icon Epic feats.png](/images/Icon_Epic_feats.png)](http://ddowiki.com/page/Legendary_Feats "Legendary Feats")
[Heroic PL Feats](http://ddowiki.com/page/Past_life_Feats "Past life Feats") - attained by achieving levels 1 - 20 and starting a new life[Spec](PastlifeFeatSpec.html) [![Icon Past life feats.png](/images/Icon_Past_life_feats.png)](http://ddowiki.com/page/Past_Life_Feats "Past life Feats")
[Epic PL Feats](http://ddowiki.com/page/Epic_Past_life_Feats "Epic Past life Feats") - attained by achieving levels 21 - 30 and reincarnating[Spec](EpicPastlifeFeatSpec.html) [![Icon Epic life feats.png](/images/Icon_Epic_life_feats.png)](https://ddowiki.com/page/Epic_past_life "Epic Past life Feats")
[Iconic PL Feats‎](http://ddowiki.com/page/Iconic_Past_life_Feats "Iconic Past life Feats") - Past life feats available to characters levetdng through all iconic levels.[Spec](IconicPastlifeFeatSpec.html) [![Icon Iconic Past life feats.png](/images/Icon_Iconic_Past_life_feats.png)](http://ddowiki.com/page/Iconic_Past_life_Feats "Iconic Past life Feats")
diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/GeneralFeatsSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/GeneralFeatsSpec.md new file mode 100644 index 00000000..d18762a3 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/GeneralFeatsSpec.md @@ -0,0 +1,162 @@ +# General Feats + +General Feats aren't tied to any specific race or class. + +## [Known Feats](- "#value=values") + +[-](- "ext:embed=prettyPrint()") + +## [Individual Search](- "Search") + +Searching for [Attack](- "#searchString") will return: + +| [ ][search] [Matching Feats][match] | +| ----------------------------------- | +| Attack | + +[search]: - "c:verify-rows=#username:withNameAsJavaList(#searchString)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[match]: - "?=#username" + +Feats can be searched with many case options. + +- sensitive (default) +- insensitive +- Uppercase +- Lowercase +- Snake / Camel case + +## [Verify Known Feats](- "enumerate") + +Verifying all known General Feats (from DDO Wiki) + +| Errata | | |:-:|:-:| | Rapid Reload | Listed on Main page, but moved to Class (Artificer) Category | | | | + +| Unimplemented Feats | +| ------------------- | +| Extra Turning | +| Feat Respec Token | +| Improved Turning | + +| [ ][existingFeat] [Feats][result] | +| ----------------------------------- | +| Acrobatic | +| Alertness | +| Athletic | +| Attack | +| Augment Summoning | +| Bow Strength | +| Brutal Throw | +| Bullheaded | +| Cleave | +| Coin Lord Finishing School Training | +| Combat Casting | +| Combat Expertise | +| Defensive Fighting | +| Deflect Arrows | +| Diehard | +| Discipline | +| Dismiss Charm | +| Dodge | +| Draconic Vitality | +| Exotic Weapon Proficiency | +| Force of Personality | +| Great Cleave | +| Great Fortitude | +| Greater Single Weapon Fighting | +| Greater Spell Focus | +| Greater Spell Penetration | +| Greater Two Handed Fighting | +| Greater Two Weapon Fighting | +| Greater Weapon Focus | +| Greater Weapon Specialization | +| Hamstring | +| Heavy Armor Champion | +| Heavy Armor Combatant | +| Heavy Armor Master | +| Heavy Armor Proficiency | +| Heavy Armor Training | +| Heroic Durability | +| Improved Critical | +| Improved Feint | +| Improved Heroic Durability | +| Improved Mental Toughness | +| Improved Precise Shot | +| Improved Shield Bash | +| Improved Shield Mastery | +| Improved Single Weapon Fighting | +| Improved Sunder | +| Improved Trip | +| Improved Two Handed Fighting | +| Improved Two Weapon Fighting | +| Insightful Reflexes | +| Iron Will | +| Knight's Training | +| Light Armor Proficiency | +| Lightning Reflexes | +| Luck of Heroes | +| Magical Training | +| Manyshot | +| Martial Weapon Proficiency | +| Medium Armor Proficiency | +| Mental Toughness | +| Mobile Spellcasting | +| Mobility | +| Natural Fighting | +| Negotiator | +| Nimble Fingers | +| Oversized Two Weapon Fighting | +| Point Blank Shot | +| Power Attack | +| Power Critical | +| Precise Shot | +| Precision | +| Quick Draw | +| Rapid Shot | +| Resilience | +| Resist Poison | +| Sap | +| Self Sufficient | +| Shield Deflection | +| Shield Mastery | +| Shield Proficiency (General) | +| Shot on the Run | +| Shuriken Expertise | +| Simple Thrown Weapon Expertise | +| Simple Weapon Proficiency | +| Single Weapon Fighting | +| Skill Focus | +| Slicing Blow | +| Snake Blood | +| Sneak | +| Spell Focus | +| Spell Penetration (feat) | +| Spring Attack | +| Stealthy | +| Stunning Blow | +| Stunning Fist | +| Sunder | +| Superior Weapon Focus | +| Swords to Plowshares | +| Tactical Combatant | +| Tactical Mastery | +| Tactical Supremacy | +| Tactical Training | +| Ten Thousand Stars | +| Toughness | +| Tower Shield Proficiency | +| Trip | +| Two Handed Fighting | +| Two Weapon Blocking | +| Two Weapon Defense | +| Two Weapon Fighting | +| Weapon Finesse | +| Weapon Focus | +| Weapon Specialization | +| Whirling Steel Strike | +| Whirlwind Attack | +| Zen Archery | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/ManyShotSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/ManyShotSpec.md new file mode 100644 index 00000000..cb11b0bc --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/ManyShotSpec.md @@ -0,0 +1,57 @@ +# [Feat: Manyshot](- "before") + +[Manyshot](- "setFeatId(#TEXT)") +[wiki](https://ddowiki.com/page/Manyshot "view Manyshot on wiki") + +## [Usage](- "Usage and description") + +Usage: [Active](- "?=isActive()") + +Expend one charge to fire three arrows in quick succession. You have +1 Critical Threat Range and Critical Multiplier +with these shots. Each of these shots can Doubleshot. 2 second cooldown. This feat +gives [3](- "?=javaSafeChargeInfo().getMaxCharges()") charges, you +regain [1](- "?=#qry=javaSafeChargeInfo().quantity.orElse(99)") charge +every [12](- "?=javaSafeChargeInfo().safeInterval()") seconds you don't use Manyshot. Passive: You gain Doubleshot equal +to 1.5x your Base Attack Bonus with Longbows and Shortbows. + +## [Prerequisites](-) + +Requirements needed to select this feat + +| [ ][prereq] [Prerequisites][result] | +| ----------------------------------- | +| Base Attack Bonus: 6 | +| Dexterity: 17 | +| Point Blank Shot | +| Rapid Shot | + +### [Bonus Selections](-) + +Can be selected in addition to the normal level progression + +| [ ][bonus] [Bonus Feats][result] | +| -------------------------------- | +| Fighter: 1 | +| Fighter: 2 | +| Fighter: 4 | +| Fighter: 6 | +| Fighter: 8 | +| Fighter: 10 | +| Fighter: 12 | +| Fighter: 14 | +| Fighter: 16 | +| Fighter: 18 | +| Fighter: 20 | + +### [Granted To](-) + +Includes any classes or other exceptions that provide this automatically + +| [ ][granted] [Granted][result] | +| ------------------------------ | +| Ranger: 6 | + +[prereq]: - "c:verify-rows=#feat:verifyPrerequisites()" +[bonus]: - "c:verify-rows=#feat:verifyBonusSelections()" +[granted]: - "c:verify-rows=#feat:verifyGrantSelections()" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.html new file mode 100644 index 00000000..d4021e89 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.html @@ -0,0 +1,32 @@ + + + + MartialArtsFeatSpec + + + +

MartialArtsFeatSpec

+

Description

+
+

Examples

+
+ + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/RacialFeatList.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/RacialFeatList.md new file mode 100644 index 00000000..c0e27612 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/RacialFeatList.md @@ -0,0 +1,4 @@ +| Half-Elf Dilettante: Barbarian| | Half-Elf Dilettante: Bard| | Half-Elf Dilettante: Cleric| | Half-Elf Dilettante: +Druid | Half-Elf Dilettante: Favored Soul| | Half-Elf Dilettante: Fighter| | Half-Elf Dilettante: Monk | | Half-Elf +Dilettante: Paladin| | Half-Elf Dilettante: Ranger| | Half-Elf Dilettante: Rogue| | Half-Elf Dilettante: Sorcerer| | +Half-Elf Dilettante: Warlock| | Half-Elf Dilettante: Wizard| diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/TacticalFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/TacticalFeatSpec.md new file mode 100644 index 00000000..1f585092 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/TacticalFeatSpec.md @@ -0,0 +1,18 @@ +# TacticalFeatSpec + +## Verify Known Tactical Feats + +| [ ][existingFeat] [Feats][result] | +| --------------------------------- | +| ImprovedSunder | +| ImprovedTrip | +| QuiveringPalm | +| Sap | +| StunningBlow | +| StunningFist | +| Sunder | +| Trip | + +[existingFeat]: - "c:verify-rows=#feat:tacticalFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.md new file mode 100644 index 00000000..15dd8e5d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.md @@ -0,0 +1,240 @@ +# Alchemist Class Feats + +[Alchemist](https://ddowiki.com/page/Category:Alchemist_class_feats) + +## Level 1 + +| [ ][featLevel1] [Feats][result] | Usage | Description | +| --------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Alchemical Spellcasting](https://ddowiki.com/page/Alchemical_Spellcasting) | Passive | Affects spell power based on Primers | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the Arcane. This feat is received once for every Alchemist level. | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | +| [Inscribe Alchemy Recipe](https://ddowiki.com/page/Inscribe_Alchemy_Recipe) | Active | You are able to copy alchemical formulae into your spellbooks | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Description | +| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every Alchemist level. | +| [Artificer Knowledge - Potions][artificer_knowledge] | (passive): Grants a +2 to UMD checks related to potion use, if any, and all potions used by the Alchemist have their caster levels increased by 1. This caster level bonus increases by 1 at Alchemist levels 5, 8, 11, and 14, and is capped by the Alchemist's Intelligence Bonus. This feat also gives damage bonuses to certain infusions. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Description | +| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Alchemy on the Run](https://ddowiki.com/page/Alchemy_on_the_Run) | You can now move while drinking potions. | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every Alchemist level. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Description | +| ------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +Bonus Feat: An Alchemist can select a feat from the Artificer Bonus Feat list. + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Description | +| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Potions][artificer_knowledge] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +2. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Description | +| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Multitude of Missiles](https://ddowiki.com/page/Multitude_of_Missiles) | For the next 20 seconds, while wielding a Simple Thrown Weapon add 100 to your Doubleshot and 2x your Base Attack Bonus to Ranged Power. Shares a cooldown with Manyshot. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Description | +| --------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Poisonblood](https://ddowiki.com/page/Poisonblood) | You are immune to Natural Poisons. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Description | +| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Potions][artificer_knowledge] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +3. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Description | +| ------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Description | +| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Potions][artificer_knowledge] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +4. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Description | +| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Potions][artificer_knowledge] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +5. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Description | +| -------------------------------- | ---------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. +|Sneak Attack| + +### Artificer Bonus Feats: + +| [ ][bonusFeats] [Feats][result] | Type | Description | Prerequisite | +| ----------------------------------------------------------------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Alchemical Studies - Orchidium](https://ddowiki.com/page/Alchemical_Studies_-_Orchidium) | Passive | +1 Caster Level with spells matching either of the two colors in your study. | Alchemist 4 | +| [Alchemical Studies - Pyrite](https://ddowiki.com/page/Alchemical_Studies_-_Pyrite) | Passive | +1 Caster Level with spells matching either of the two colors in your study. | Alchemist 4 | +| [Alchemical Studies - Verudite](https://ddowiki.com/page/Alchemical_Studies_-_Verudite) | Passive | +1 Caster Level with spells matching either of the two colors in your study. | Alchemist 4 | +| [Battalion Brew](https://ddowiki.com/page/Battalion_Brew) | Passive | You can use Intelligence for to hit and damage rolls with simple weapons. | Alchemist 4 | +| [Dodge](https://ddowiki.com/page/Dodge) | Passive | This feat grants a 3% Dodge bonus. | Dexterity 13+ | +| [Empower Spell](https://ddowiki.com/page/Empower_Spell "Empower Spell") | Active Toggled Metamagic | Activating **Empower Spell** increases the [Spell Power](https://ddowiki.com/page/Spell_Power "Spell Power") of each spell by 75, but makes the affected spell cost 15 more [spell points](https://ddowiki.com/page/Spell_point "Spell point"). Saving throws and spells without random values are not affected. | \* **Prerequisite:** The character must be able to cast spells. | +| [Enlarge Spell](https://ddowiki.com/page/Enlarge_Spell "Enlarge Spell") | Active Toggled Metamagic | Spells can be cast 100% further (doubling distance). In some cases a targeted monster will not even be able to figure out where the caster is -- or may not be able to reach the caster -- making the caster invulnerable to counterattack. Whereas some feats simply improve stats in ways that could also be accomplished by equipment or potions, Enlarge has an effect that is otherwise not available. Each spell cast while Enlarge is active costs 10 more spellpoints. | \* **Prerequisite:** Able to cast [spells](https://ddowiki.com/page/Spell "Spell") | +| [Eschew Materials](https://ddowiki.com/page/Eschew_Materials "Eschew Materials") | Active Toggled Metamagic | \* **Prerequisite:** Able to cast [spells](https://ddowiki.com/page/Spell "Spell") | \* **Prerequisite:** able to cast [spells](https://ddowiki.com/page/Spell "Spell") | +| [Extend Spell](https://ddowiki.com/page/Extend_Spell "Extend Spell") | Active Toggled Metamagic | **Extend Spell** grants a caster the ability to extend a spell's duration. For 10 more [spell points](https://ddowiki.com/page/Spell_point "Spell point"), a spell's duration will be increased by 100%. | \* **Prerequisite:** Must be able to cast [spells](https://ddowiki.com/page/Spell "Spell") | +| [Heighten Spell](https://ddowiki.com/page/Heighten_Spell "Heighten Spell") | Active Toggled Metamagic | This [Feat](https://ddowiki.com/page/Feat "Feat") makes spells harder for monsters to resist by raising the effective level of the [spell](https://ddowiki.com/page/Spell "Spell") to the highest spell level your character can cast, but causes the spell to consume 5 more spell points per level raised. | \* **Prerequisite:** Must be able to cast [spells](https://ddowiki.com/page/Spell "Spell") | +| [Improved Mental Toughness](https://ddowiki.com/page/Improved_Mental_Toughness) | Passive | This feat increases the character's maximum spell points by 10 at first level, and 5 spell points for each additional level. Also, it increases your spell critical chance by 1%. | Mental Toughness, and the ability to cast 3rd level spells, Artificer 7, Bard 7, Cleric 5, Druid 5, Favored Soul 6, Paladin 10, Ranger 10, Sorcerer 6, Wizard 5. | +| [Liquid Courage](https://ddowiki.com/page/Liquid_Courage) | Passive | You can use Intelligence for Will saves. Mutually exclusive with Tough Tincture. | Alchemist 8 | +| [Liquid Luck](https://ddowiki.com/page/Liquid_Luck) | Passive | Gain Evasion. | Alchemist 12 | +| [Maximize Spell](https://ddowiki.com/page/Maximize_Spell "Maximize Spell") | Active Toggled Metamagic | A spell cast using this [feat](https://ddowiki.com/page/Feat "Feat") will have its [Spell Power](https://ddowiki.com/page/Spell_Power "Spell Power") increased by +150\. Spells will cost 25 additional spell points (i.e. 10 Spell points becomes 35). [Saving throws](https://ddowiki.com/page/Saving_throw "Saving throw") and non-random values are not affected. | \* **Prerequisite:** Must be able to cast [spells](https://ddowiki.com/page/Spell "Spell") | +| [Mental Toughness](https://ddowiki.com/page/Mental_Toughness) | Passive | This feat increases the character's maximum spell points by 10 at first level, and 5 spell points for each additional level. Thus it grants a total maximum of +155 spell points at level 30. Also, increases your spell critical chance by 1%. | Able to cast spells | +| [Mobility](https://ddowiki.com/page/Mobility) | Passive | Mobility increases the maximum dexterity bonus permitted by armor and tower shields by 2, and adds a +4 bonus to Armor Class while tumbling. You will also gain a 2% dodge bonus. | Dodge | +| [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") | Passive | Grants a +1 bonus to hit within 45 feet, and your ranged weapons deal +1\[W]. (See [weapon dice multiplier](https://ddowiki.com/page/Weapon_dice_multiplier "Weapon dice multiplier") - A weapon that deals \[1d6] damage per hit will deal 2*\[1d6] damage per hit instead, while a weapon that deals \[2d8] damage per hit will deal 2*\[2d8] damage per hit instead. This effects the base dice of the associated weapon any time they are rolled, including [critical hits](https://ddowiki.com/page/Critical_hit "Critical hit").) | | +| [Precise Shot](https://ddowiki.com/page/Precise_Shot "Precise Shot") | Passive | With the Precise Shot feat, your targeted ranged attacks pass through friend and foe alike to strike your target (no damage will be done other than to your target). This feat also grants you the Offensive Ranged Stance **Archer's Focus**, which lets you deal progressively more damage with ranged attacks while standing still. | \* **Prerequisite:** [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") | +| [Precision](https://ddowiki.com/page/Precision) | Active, Toggled Stance | Offensive Combat Stance: While using Precision mode, you gain +5% to hit and reduce the target's fortification against your attacks by 25%. Cannot be used while raged. | +1 Base Attack Bonus, DEX 13 | +| [Quick Draw](https://ddowiki.com/page/Quick_Draw) | Passive | You can draw and fire throwing weapons more rapidly. In addition, you re-draw your weapons much faster after casting Spells and Spell-Like Abilities, eliminating the delay between casting and attacking. | Base attack bonus +1 | +| [Quicken Spell](https://ddowiki.com/page/Quicken_Spell "Quicken Spell") | Active Toggled Metamagic | While this [feat](https://ddowiki.com/page/Feat "Feat") is activated, [spells](https://ddowiki.com/page/Spells "Spells") will be cast faster (roughly twice as fast) and cannot be interrupted by a [concentration](https://ddowiki.com/page/Concentration "Concentration") check. During this time though, all [spells](https://ddowiki.com/page/Spell "Spell") will cost 10 more [spell points](https://ddowiki.com/page/Spell_points "Spell points") to cast. | \* **Prerequisite:** Must be able to cast [spells](https://ddowiki.com/page/Spell "Spell") | +| [Rapid Shot](https://ddowiki.com/page/Rapid_Shot "Rapid Shot") | Passive | You can make ranged attacks about 20% [faster](https://ddowiki.com/page/Attack_speed "Attack speed") and reload faster when using a ranged weapon. It appears to make the bolts from a crossbow travel faster, ie there is less elapsed time from firing to striking the target, as of 1/7/2018. | \* **Prerequisite:** [Dexterity](https://ddowiki.com/page/Dexterity "Dexterity") 13+, [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") | +| [Shot on the Run](https://ddowiki.com/page/Shot_on_the_Run "Shot on the Run") | Passive | Shot on the Run negates the (-4) penalty to attack rolls associated with moving while firing all types of [ranged weapons](https://ddowiki.com/page/Category:Ranged_weapons "Category:Ranged weapons") and [throwing weapons](https://ddowiki.com/page/Throwing_weapons "Throwing weapons") and gives +3 [ranged power](https://ddowiki.com/page/Ranged_power "Ranged power"). | \* **Prerequisite:** [Dexterity](https://ddowiki.com/page/Dexterity "Dexterity") 13+, [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot"), [Mobility](https://ddowiki.com/page/Mobility "Mobility"), [base attack bonus](https://ddowiki.com/page/Base_attack_bonus "Base attack bonus") of 4+ or higher | +| [Simple Thrown Weapon Expertise](https://ddowiki.com/page/Simple_Thrown_Weapon_Expertise) | Passive | You are skilled with the use of Simple Thrown Weapons (Throwing Daggers and Darts) and while using one, you gain Doubleshot equal to your Dexterity. | Dex 13+ | +| [Tough Tincture](https://ddowiki.com/page/Tough_Tincture) | Passive | You can use Intelligence for Fortitude saves. Mutually exclusive with Liquid Courage. | Alchemist 8 | +| [Toxic Tonic](https://ddowiki.com/page/Toxic_Tonic) | Passive | You are immune to Poison damage and get bonus saves versus poisons. | Alchemist 12 | + +| Active Toggled Metamagic | | \* **Prerequisite:** Must be able to cast [spells](https://ddowiki.com/page/Spell "Spell") | + +- [Proficiency: Bastard Sword](https://ddowiki.com/page/Proficiency:_Bastard_Sword "Proficiency: Bastard Sword") +- [Proficiency: Dwarven Waraxe](https://ddowiki.com/page/Proficiency:_Dwarven_Waraxe "Proficiency: Dwarven Waraxe") + +- [Weapon Focus: Ranged](https://ddowiki.com/page/Weapon_Focus:_Ranged "Weapon Focus: Ranged") +- [Weapon Focus: Slashing](https://ddowiki.com/page/Weapon_Focus:_Slashing "Weapon Focus: Slashing") + +|[Proficiency: Bastard Sword](https://ddowiki.com/page/Proficiency:_Bastard_Sword "Proficiency: Bastard Sword")| Passive |This [feat](https://ddowiki.com/page/Feat "Feat") negates the -4 penalty to [attack rolls](https://ddowiki.com/page/Attack_roll "Attack roll") from using an [Bastard Sword](https://ddowiki.com/page/Bastard_Sword "Bastard Sword") untrained. In addition it allows [Bastard Swords](https://ddowiki.com/page/Bastard_Sword "Bastard Sword") to deal [glancing blows](https://ddowiki.com/page/Glancing_blows "Glancing blows") as if they were a two handed weapon - if they are the only weapon wielded by a proficient user. EG: Sword and shield or single weapon attack styles only, will not work if you are dual-wielding. | _ **Prerequisite:** [Base Attack Bonus](https://ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, [Strength](https://ddowiki.com/page/Strength "Strength") 13+| +|[Proficiency: Dwarven Waraxe](https://ddowiki.com/page/Proficiency:_Dwarven_Waraxe "Proficiency: Dwarven Waraxe")|Passive |This [feat](https://ddowiki.com/page/Feat "Feat") negates the -4 penalty to [attack rolls](https://ddowiki.com/page/Attack_roll "Attack roll") from using an [Dwarven Waraxe](https://ddowiki.com/page/Dwarven_Waraxe "Dwarven Waraxe") untrained. In addition it allows [Dwarven Waraxes](https://ddowiki.com/page/Dwarven_Waraxe "Dwarven Waraxe") to deal [glancing blows](https://ddowiki.com/page/Glancing_blows "Glancing blows") as if they were a two handed weapon - if they are the only weapon wielded by a proficient user. EG: Sword and shield or single weapon attack styles only, will not work if you are dual-wielding.| _ **Prerequisite:** [Base Attack Bonus](https://ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, [Strength](https://ddowiki.com/page/Strength "Strength") 13+| +|[Weapon Focus: Ranged](https://ddowiki.com/page/Weapon_Focus:_Ranged "Weapon Focus: Ranged")|Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Ranged Power](https://ddowiki.com/page/Ranged_Power "Ranged Power").| _ **Prerequisite:** Base attack bonus of +1 or higher| +|[Weapon Focus: Slashing](https://ddowiki.com/page/Weapon_Focus:_Slashing "Weapon Focus: Slashing")|Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Melee Power](https://ddowiki.com/page/Melee_Power "Melee Power").| _ **Prerequisite:** Base attack bonus of +1 or higher| + +- [Adamantine Body](https://ddowiki.com/page/Adamantine_Body "Adamantine Body") +- [Augment Summoning](https://ddowiki.com/page/Augment_Summoning "Augment Summoning") +- [Construct Essence](https://ddowiki.com/page/Construct_Essence "Construct Essence") +- [Dragonmark of Making](https://ddowiki.com/page/Dragonmark#Human "Dragonmark") - _Human only_ +- [Exotic Weapon Proficiency](https://ddowiki.com/page/Exotic_Weapon_Proficiency "Exotic Weapon Proficiency") - Bastard Sword _or_ Dwarven Waraxe +- [Improved Critical: Bludgeoning](https://ddowiki.com/page/Improved_Critical "Improved Critical") +- [Improved Critical: Ranged](https://ddowiki.com/page/Improved_Critical "Improved Critical") +- [Improved Critical: Slashing](https://ddowiki.com/page/Improved_Critical "Improved Critical") +- [Improved Fortification](https://ddowiki.com/page/Improved_Fortification "Improved Fortification") +- [Improved Precise Shot](https://ddowiki.com/page/Improved_Precise_Shot "Improved Precise Shot") +- [Metamagic Feat](https://ddowiki.com/page/Feats/Metamagic "Feats/Metamagic") (any) +- [Mithral Body](https://ddowiki.com/page/Mithral_Body "Mithral Body") +- [Mithral Fluidity](https://ddowiki.com/page/Mithral_Fluidity "Mithral Fluidity") +- [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") +- [Precise Shot](https://ddowiki.com/page/Precise_Shot "Precise Shot") +- [Rapid Shot](https://ddowiki.com/page/Rapid_Shot "Rapid Shot") +- [Shot on the Run](https://ddowiki.com/page/Shot_on_the_Run "Shot on the Run") +- [Single Weapon Fighting](https://ddowiki.com/page/Single_Weapon_Fighting "Single Weapon Fighting") +- [Skill Focus](https://ddowiki.com/page/Skill_Focus "Skill Focus") (any) +- [Two Handed Fighting](https://ddowiki.com/page/Two_Handed_Fighting "Two Handed Fighting") +- [Weapon Focus: Ranged](https://ddowiki.com/page/Weapon_Focus "Weapon Focus") +- [Weapon Focus: Slashing](https://ddowiki.com/page/Weapon_Focus "Weapon Focus") + +[arcane_lore]: http://ddowiki.com/page/Arcane_Lore_(feat) "Arcane Lore (Feat)" +[artificer_knowledge]: http://ddowiki.com/page/Artificer_Knowledge "Artificer Knowlege" +[artificer_craft_mastery]: http://ddowiki.com/page/Artificer_Craft_Mastery +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[bonusFeats]: - "c:verify-rows=#feat:bonusFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.md new file mode 100644 index 00000000..c81ff32c --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.md @@ -0,0 +1,273 @@ +# Artificer Class Feats + +[Artificer](http://ddowiki.com/page/Category:Artificer_class_feats) + +## Level 1 + +| [ ][featLevel1] [Feats][result] | Description | +| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Construct Mastery](http://ddowiki.com/page/Artificer_Construct_Mastery) | (passive): Allows an Artificer to spontaneously cast any single-target Repair Damage or Inflict Damage spell they have inscribed in their spellbook. These spells will appear in bonus spell slots once inscribed. | +| [Artificer Knowledge - Scrolls][artificer_knowlege] | (passive): Grants a +2 to UMD checks related to scroll use, and all scrolls used by the Artificer have their caster levels increased by 1. This caster level bonus increases by 1 at Artificer levels 4, 7, 10, and 13, and is capped by the Artificer's Intelligence Bonus. | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | +| [Inscribe Artificer Scroll](http://ddowiki.com/page/Inscribe_Artificer_Scroll) | (active): Allows an Artificer to inscribe artificer spells from scrolls into their spellbook. This action will destroy the scroll. | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | +| [Rapid Reload](http://ddowiki.com/page/Rapid_Reload) | (passive): Allows crossbows, including repeating crossbows, to be reloaded faster. | +| [Reanimate Construct](http://ddowiki.com/page/Reanimate_Construct) | (active): Allows an Artificer to revive their Iron Defender minion once per rest. | +| [Trapfinding](http://ddowiki.com/page/Trapfinding) | (passive): Allows the use of the Search skill to locate traps when the task has a Difficulty Class (DC) higher than 20. | +| [Unleash Iron Defender](http://ddowiki.com/page/Unleash_Iron_Defender) | (active): Allows an Artificer to summon an Iron Defender homunculus. | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Description | +| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): Artificers gain a +1 bonus to all crafting skills for every even level of Artificer a character acquires, up to +10 at level 20. | +| [Artificer Knowledge - Potions][artificer_knowlege] | (passive): Grants a +2 to UMD checks related to potion use, if any, and all potions used by the Artificer have their caster levels increased by 1. This caster level bonus increases by 1 at Artificer levels 5, 8, 11, and 14, and is capped by the Artificer's Intelligence Bonus. This feat also gives damage bonuses to certain infusions. | +| [Rune Arm Use](http://ddowiki.com/page/Rune_Arm_Use) | (passive)(active): Allows Artificers to equip and use Rune Arms. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Description | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Wands][artificer_knowlege] | (passive): Grants a +2 to UMD checks related to wand use, and all wands used by the Artificer have their caster levels increased by 1. This caster level bonus increases by 1 at Artificer levels 6, 9, 12, and 15, and is capped by the Artificer's Intelligence Bonus. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Description | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +2. | +| [Artificer Knowledge - Scrolls][artificer_knowlege] | (passive): All scrolls used by the Artificer have their caster levels increased by an additional 1, for a total of +2. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Trapmaking](http://ddowiki.com/page/Trapmaking) | (passive): You have learned enough about traps to be able to scavenge parts from them, and with the help of the Free Agents, can craft your own. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Description | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Arms and Armor][artificer_knowlege] | (passive): Grants a +2 to UMD checks related to weapons, armor, and staves. Any activated abilities on weapons and armor ("clickies") used by the Artificer are cast at a +1 caster level. This caster level bonus increases by 1 at Artificer levels 8, 11, 14, and 17, and is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Potions][artificer_knowlege] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +2. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Retain Essence](http://ddowiki.com/page/Retain_Essence) | (passive): Whenever an Artificer uses a rod, staff, or wand, the character has a chance to not expend a charge. The percentage chance is based on (Artificer levels + Intelligence modifier)% chance not to expend a charge. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Description | +| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +3. | +| [Artificer Knowledge - Wands][artificer_knowlege] | (passive): All wands used by the Artificer have their caster levels increased by an additional 1, for a total of +2. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Description | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Scrolls][artificer_knowlege] | (passive): All scrolls used by the Artificer have their caster levels increased by an additional 1, for a total of +3. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Wondrous Items][artificer_knowlege] | (passive): Grants a +2 to UMD checks related to clothing, jewelry, and trinkets. Any activated abilities on these items ("clickies") used by the Artificer are cast at a +1 caster level. This caster level bonus increases by 1 at Artificer levels 10, 13, 16, and 19, and is capped by the Artificer's Intelligence Bonus. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Description | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +4. | +| [Artificer Knowledge - Arms and Armor][artificer_knowlege] | (passive): Any activated abilities on weapons and armor ("clickies") used by the Artificer are cast at an additional +1 caster level, for a total of +2. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Potions][artificer_knowlege] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +3. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Description | +| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Wands][artificer_knowlege] | (passive): All wands used by the Artificer have their caster levels increased by an additional 1, for a total of +3. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Description | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +5. | +| [Artificer Knowledge - Scrolls][artificer_knowlege] | (passive): All scrolls used by the Artificer have their caster levels increased by an additional 1, for a total of +4. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Wondrous Items][artificer_knowlege] | (passive): Any activated abilities ("clickies") on clothing, jewelry, and trinkets used by the Artificer are cast at an additional +1 caster level, for a total of +2. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Description | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Arms and Armor][artificer_knowlege] | (passive): Any activated abilities on weapons and armor ("clickies") used by the Artificer are cast at an additional +1 caster level, for a total of +3. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Potions][artificer_knowlege] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +4. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Description | +| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +6. | +| [Artificer Knowledge - Wands][artificer_knowlege] | (passive): All wands used by the Artificer have their caster levels increased by an additional 1, for a total of +4. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Description | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Scrolls][artificer_knowlege] | (passive): All scrolls used by the Artificer have their caster levels increased by an additional 1, for a total of +5. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Wondrous Items][artificer_knowlege] | (passive): Any activated abilities ("clickies") on clothing, jewelry, and trinkets used by the Artificer are cast at an additional +1 caster level, for a total of +3. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| Artificer Skill Mastery | (passive): Grants a +1 bonus to all skills. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Description | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +7. | +| [Artificer Knowledge - Arms and Armor][artificer_knowlege] | (passive): Any activated abilities on weapons and armor ("clickies") used by the Artificer are cast at an additional +1 caster level, for a total of +4. This caster level bonus is capped by the Artificer's Intelligence Bonus. | +| [Artificer Knowledge - Potions][artificer_knowlege] | (passive): All potions used by the Artificer have their caster levels increased by an additional 1, for a total of +5. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Description | +| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Wands][artificer_knowlege] | (passive): All wands used by the Artificer have their caster levels increased by an additional 1, for a total of +5. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Description | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +8. | +| [Artificer Knowledge - Wondrous Items][artificer_knowlege] | (passive): Any activated abilities ("clickies") on clothing, jewelry, and trinkets used by the Artificer are cast at an additional +1 caster level, for a total of +4. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Description | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Arms and Armor][artificer_knowlege] | (passive): Any activated abilities on weapons and armor ("clickies") used by the Artificer are cast at an additional +1 caster level, for a total of +5. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Description | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +9. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Description | +| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Knowledge - Wondrous Items][artificer_knowlege] | (passive): Any activated abilities ("clickies") on clothing, jewelry, and trinkets used by the Artificer are cast at an additional +1 caster level, for a total of +5. This caster level bonus is capped by the Artificer's Intelligence Bonus. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Description | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Represents your knowledge of the Arcane. This feat is received once for every artificer level. | +| [Artificer Craft Mastery][artificer_craft_mastery] | (passive): The Artificer gains an additional +1 bonus to all crafting skills, for a total of +10. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. +|Sneak Attack| + +### Artificer Bonus Feats: + +| [ ][bonusFeats] [Feats][result] | Type | Description | Prerequisite | +| ----------------------------------------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Adamantine Body](/page/Adamantine_Body "Adamantine Body") | Passive | Docents you equip provide armor equivalent to Full Plate. This is treated as metallic [heavy armor](/page/Category:Heavy_armor "Category:Heavy armor"), granting [damage reduction](/page/Damage_reduction "Damage reduction") 2/adamantine, a 35% [arcane spell failure](/page/Arcane_spell_failure "Arcane spell failure") chance, -5 [armor check penalty](/page/Armor_check_penalty "Armor check penalty") to relevant skills, and a +1 [maximum dexterity bonus](/page/Maximum_dexterity_bonus "Maximum dexterity bonus"). | \* **Prerequisite:** [Warforged](/page/Warforged "Warforged") | +| [Augment Summoning](/page/Augment_Summoning "Augment Summoning") | Passive | Your [summoned creatures](/page/Summons "Summons"), charmed minions, and hirelings have +4 to all [ability](/page/Ability "Ability") scores, increased [health](/page/Hit_point "Hit point") (amount equal to what the the [toughness](/page/Toughness "Toughness") feat would grant - Total Hitdice +2), and increased [fortification](/page/Fortification "Fortification") (+50%). | | +| [Combat Expertise](/page/Combat_Expertise "Combat Expertise") | Active | Defensive Combat Stance: While using Combat Expertise mode, you suffer -5 to your attack rolls but gain +10% feat bonus to Armor Class. Spells have three times their normal cooldown when this mode is active. Combat Expertise dispels and wards against all Rage effects. | [Intelligence](/page/Intelligence "Intelligence") 13 | +| [Construct Essence](/page/Construct_Essence "Construct Essence") | Passive | You are on the path to becoming a self-forged, augmenting yourself by replacing some of your weak flesh. You are still considered your original race (at this time), gaining 50% healing from Repair spells but suffering a -25% penalty to positive energy healing. In addition, you now take 50% damage from rust effects. | \* **Prerequisite:** [Artificer](/page/Artificer "Artificer") 3, Non-[warforged](/page/Warforged "Warforged") race | +| [Empower Healing Spell](/page/Empower_Healing_Spell "Empower Healing Spell") | Active Toggled Metamagic | **Empower Healing Spell**: While this metamagic feat is active, you gain 75 Spell Power while casting spells affected by Empower Healing, but they consume 10 additional spell points. | \* **Prerequisite:** Being able to cast [healing spells](/page/Healing_spells "Healing spells") - Thus one level of [Artificer](/page/Artificer "Artificer"), [Bard](/page/Bard "Bard"), [Druid](/page/Druid "Druid"), [Cleric](/page/Cleric "Cleric"), [Favored Soul](/page/Favored_Soul "Favored Soul"), 4 levels of [Paladin](/page/Paladin "Paladin") or 8 levels of [Ranger](/page/Ranger "Ranger") are needed to qualify. | +| [Empower Spell](/page/Empower_Spell "Empower Spell") | Active Toggled Metamagic | Activating **Empower Spell** increases the [Spell Power](/page/Spell_Power "Spell Power") of each spell by 75, but makes the affected spell cost 15 more [spell points](/page/Spell_point "Spell point"). Saving throws and spells without random values are not affected. | \* **Prerequisite:** The character must be able to cast spells. | +| [Enlarge Spell](/page/Enlarge_Spell "Enlarge Spell") | Active Toggled Metamagic | Spells can be cast 100% further (doubling distance). In some cases a targeted monster will not even be able to figure out where the caster is -- or may not be able to reach the caster -- making the caster invulnerable to counterattack. Whereas some feats simply improve stats in ways that could also be accomplished by equipment or potions, Enlarge has an effect that is otherwise not available. Each spell cast while Enlarge is active costs 10 more spellpoints. | \* **Prerequisite:** Able to cast [spells](/page/Spell "Spell") | +| [Eschew Materials](/page/Eschew_Materials "Eschew Materials") | Active Toggled Metamagic | \* **Prerequisite:** Able to cast [spells](/page/Spell "Spell") | \* **Prerequisite:** able to cast [spells](/page/Spell "Spell") | +| [Extend Spell](/page/Extend_Spell "Extend Spell") | Active Toggled Metamagic | **Extend Spell** grants a caster the ability to extend a spell's duration. For 10 more [spell points](/page/Spell_point "Spell point"), a spell's duration will be increased by 100%. | \* **Prerequisite:** Must be able to cast [spells](/page/Spell "Spell") | +| [Heighten Spell](/page/Heighten_Spell "Heighten Spell") | Active Toggled Metamagic | This [Feat](/page/Feat "Feat") makes spells harder for monsters to resist by raising the effective level of the [spell](/page/Spell "Spell") to the highest spell level your character can cast, but causes the spell to consume 5 more spell points per level raised. | \* **Prerequisite:** Must be able to cast [spells](/page/Spell "Spell") | +| [Improved Construct Essence](/page/Improved_Construct_Essence "Improved Construct Essence") | [Passive](/page/Passive_feat "Passive feat") | You have augmented yourself heavily enough to be more machine than not. You are now considered a Living Construct instead of your original race, gaining the following traits: _ 100% base healing from Repair spells and 100% damage from Rust. _ Immunity to Sleep, Hold Person, Energy Drain, Nauseated, Exhausted, and Paralyzed effects except those which physically hold you in place _ Immunity to ability score damage from natural poisons and natural diseases (but are vulnerable to those that specifically affect wood or metal) _ +10 Racial bonus to saving throws against magical poisons, and do not fail saving throws against them on a roll of a natural 1 (this renders you immune to magical poisons with a DC of less than 11+your Fortitude save) _ You may remain underwater indefinitely without the need to breathe. _ When resting at a Rest Shrine, the health you regain is now based on your Repair skill instead of your Heal skill. If you transform into a different type of creature, you will lose these benefits until you return to your normal form. | **Prerequisite:** [Artificer](/page/Artificer "Artificer") level 12+, [Construct Essence](/page/Construct_Essence "Construct Essence"), Non-[warforged](/page/Warforged "Warforged") race | +| [Improved Critical](https://ddowiki.com/page/Improved_Critical "Improved Critical") | [Passive](/page/Passive_feat "Passive feat") | **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 8 or higher | This [feat](/page/Feat "Feat") adds 1, 2, or 3 to critical [threat range](/page/Threat_range "Threat range") based on the weapon type's unmodified threat range. | +| [Improved Fortification](/page/Improved_Fortification "Improved Fortification") | Passive | Improves your [warforged fortification](/page/Warforged_fortification "Warforged fortification"), granting you immunity to [sneak attacks](/page/Sneak_attack "Sneak attack") and extra damage from [critical hits](/page/Critical_hit "Critical hit"). However, you lose the ability to be healed by spells from the [positive energy](/page/Positive_Energy "Positive Energy") sub-school, such as [Cure Light Wounds](/page/Cure_Light_Wounds "Cure Light Wounds"). | \* **Prerequisite:** [Warforged](/page/Warforged "Warforged"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +6. | +| [Improved Precise Shot](https://ddowiki.com/page/Improved_Precise_Shot "Improved Precise Shot") | Active Stance | With Improved Precise Shot, your ranged attacks pass through and potentially damage all foes in the projectile's path. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 19, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot"), [Precise Shot](/page/Precise_Shot "Precise Shot"), and [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") +11 | +| [Maximize Spell](/page/Maximize_Spell "Maximize Spell") | Active Toggled Metamagic | A spell cast using this [feat](/page/Feat "Feat") will have its [Spell Power](/page/Spell_Power "Spell Power") increased by +150\. Spells will cost 25 additional spell points (i.e. 10 Spell points becomes 35). [Saving throws](/page/Saving_throw "Saving throw") and non-random values are not affected. | \* **Prerequisite:** Must be able to cast [spells](/page/Spell "Spell") | +| [Mithral Body](/page/Mithral_Body "Mithral Body") | Passive | Docents you equip provide armor equivalent to chainmail. This is treated as metallic [light armor](/page/Category:Light_armor "Category:Light armor"), granting a 15% [arcane spell failure](/page/Arcane_spell_failure "Arcane spell failure") chance, -1 [armor check penalty](/page/Armor_check_penalty "Armor check penalty") to relevant skills, and a +5 [maximum dexterity bonus](/page/Maximum_dexterity_bonus "Maximum dexterity bonus"). | \* **Prerequisite:** [Warforged](/page/Warforged "Warforged") | +| [Mithral Fluidity](/page/Mithral_Fluidity "Mithral Fluidity") | Passive | The maximum [Dexterity](/page/Dexterity "Dexterity") bonus you have is increased by 1, and the [armor check penalty](/page/Armor_check_penalty "Armor check penalty") is decreased by 1. | \* **Prerequisite:** [Mithral Body](/page/Mithral_Body "Mithral Body"), [Warforged](/page/Warforged "Warforged") | +| [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") | Passive | Grants a +1 bonus to hit within 45 feet, and your ranged weapons deal +1[W]. (See [weapon dice multiplier](/page/Weapon_dice_multiplier "Weapon dice multiplier") - A weapon that deals [1d6] damage per hit will deal 2*[1d6] damage per hit instead, while a weapon that deals [2d8] damage per hit will deal 2*[2d8] damage per hit instead. This effects the base dice of the associated weapon any time they are rolled, including [critical hits](/page/Critical_hit "Critical hit").) | | +| [Precise Shot](https://ddowiki.com/page/Precise_Shot "Precise Shot") | Passive | With the Precise Shot feat, your targeted ranged attacks pass through friend and foe alike to strike your target (no damage will be done other than to your target). This feat also grants you the Offensive Ranged Stance **Archer's Focus**, which lets you deal progressively more damage with ranged attacks while standing still. | \* **Prerequisite:** [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot") | +| [Quicken Spell](/page/Quicken_Spell "Quicken Spell") | Active Toggled Metamagic | While this [feat](/page/Feat "Feat") is activated, [spells](/page/Spells "Spells") will be cast faster (roughly twice as fast) and cannot be interrupted by a [concentration](/page/Concentration "Concentration") check. During this time though, all [spells](/page/Spell "Spell") will cost 10 more [spell points](/page/Spell_points "Spell points") to cast. | \* **Prerequisite:** Must be able to cast [spells](/page/Spell "Spell") | +| [Rapid Shot](/page/Rapid_Shot "Rapid Shot") | Passive | You can make ranged attacks about 20% [faster](/page/Attack_speed "Attack speed") and reload faster when using a ranged weapon. It appears to make the bolts from a crossbow travel faster, ie there is less elapsed time from firing to striking the target, as of 1/7/2018. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 13+, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot") | +| [Shot on the Run](https://ddowiki.com/page/Shot_on_the_Run "Shot on the Run") | Passive | Shot on the Run negates the (-4) penalty to attack rolls associated with moving while firing all types of [ranged weapons](/page/Category:Ranged_weapons "Category:Ranged weapons") and [throwing weapons](/page/Throwing_weapons "Throwing weapons") and gives +3 [ranged power](/page/Ranged_power "Ranged power"). | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 13+, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot"), [Mobility](/page/Mobility "Mobility"), [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 4+ or higher | +| [Skill Focus](/page/Skill_Focus "Skill Focus") | Passive | Skill Focus grants a +3 bonus to the chosen [skill](/page/Skill "Skill") when making [skill check](/page/Skill_check "Skill check") rolls. This [feat](/page/Feat "Feat") can be taken multiple times, but only once for each skill. | | +| [Two Handed Fighting](https://ddowiki.com/page/Two_Handed_Fighting "Two Handed Fighting") | Passive | Increases the damage of [glancing blow](/page/Glancing_blow "Glancing blow") attacks when wielding a two-handed weapon by 10% (from a base of 20% normal weapon damage.) This feat also grants a 3% chance for weapon effects to trigger on glancing blows. While fighting with a two-handed weapon you gain a +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** 15 [Strength](/page/Strength "Strength") | + +| Active Toggled Metamagic | | \* **Prerequisite:** Must be able to cast [spells](/page/Spell "Spell") | + +- [Proficiency: Bastard Sword](/page/Proficiency:_Bastard_Sword "Proficiency: Bastard Sword") +- [Proficiency: Dwarven Waraxe](/page/Proficiency:_Dwarven_Waraxe "Proficiency: Dwarven Waraxe") + +- [Weapon Focus: Ranged](/page/Weapon_Focus:_Ranged "Weapon Focus: Ranged") +- [Weapon Focus: Slashing](/page/Weapon_Focus:_Slashing "Weapon Focus: Slashing") + +|[Proficiency: Bastard Sword](https://ddowiki.com/page/Proficiency:_Bastard_Sword "Proficiency: Bastard Sword")| Passive |This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using an [Bastard Sword](/page/Bastard_Sword "Bastard Sword") untrained. In addition it allows [Bastard Swords](/page/Bastard_Sword "Bastard Sword") to deal [glancing blows](/page/Glancing_blows "Glancing blows") as if they were a two handed weapon - if they are the only weapon wielded by a proficient user. EG: Sword and shield or single weapon attack styles only, will not work if you are dual-wielding. | _ **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, [Strength](/page/Strength "Strength") 13+| +|[Proficiency: Dwarven Waraxe](https://ddowiki.com/page/Proficiency:_Dwarven_Waraxe "Proficiency: Dwarven Waraxe")|Passive |This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using an [Dwarven Waraxe](/page/Dwarven_Waraxe "Dwarven Waraxe") untrained. In addition it allows [Dwarven Waraxes](/page/Dwarven_Waraxe "Dwarven Waraxe") to deal [glancing blows](/page/Glancing_blows "Glancing blows") as if they were a two handed weapon - if they are the only weapon wielded by a proficient user. EG: Sword and shield or single weapon attack styles only, will not work if you are dual-wielding.| _ **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, [Strength](/page/Strength "Strength") 13+| +|[Weapon Focus: Ranged](https://ddowiki.com/page/Weapon_Focus:_Ranged "Weapon Focus: Ranged")|Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Ranged Power](/page/Ranged_Power "Ranged Power").| _ **Prerequisite:** Base attack bonus of +1 or higher| +|[Weapon Focus: Slashing](https://ddowiki.com/page/Weapon_Focus:_Slashing "Weapon Focus: Slashing")|Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Melee Power](/page/Melee_Power "Melee Power").| _ **Prerequisite:** Base attack bonus of +1 or higher| + +- [Adamantine Body](/page/Adamantine_Body "Adamantine Body") +- [Augment Summoning](/page/Augment_Summoning "Augment Summoning") +- [Construct Essence](/page/Construct_Essence "Construct Essence") +- [Dragonmark of Making](/page/Dragonmark#Human "Dragonmark") - _Human only_ +- [Exotic Weapon Proficiency](/page/Exotic_Weapon_Proficiency "Exotic Weapon Proficiency") - Bastard Sword _or_ Dwarven Waraxe +- [Improved Critical: Bludgeoning](/page/Improved_Critical "Improved Critical") +- [Improved Critical: Ranged](/page/Improved_Critical "Improved Critical") +- [Improved Critical: Slashing](/page/Improved_Critical "Improved Critical") +- [Improved Fortification](/page/Improved_Fortification "Improved Fortification") +- [Improved Precise Shot](/page/Improved_Precise_Shot "Improved Precise Shot") +- [Metamagic Feat](/page/Feats/Metamagic "Feats/Metamagic") (any) +- [Mithral Body](/page/Mithral_Body "Mithral Body") +- [Mithral Fluidity](/page/Mithral_Fluidity "Mithral Fluidity") +- [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot") +- [Precise Shot](/page/Precise_Shot "Precise Shot") +- [Rapid Shot](/page/Rapid_Shot "Rapid Shot") +- [Shot on the Run](/page/Shot_on_the_Run "Shot on the Run") +- [Single Weapon Fighting](/page/Single_Weapon_Fighting "Single Weapon Fighting") +- [Skill Focus](/page/Skill_Focus "Skill Focus") (any) +- [Two Handed Fighting](/page/Two_Handed_Fighting "Two Handed Fighting") +- [Weapon Focus: Ranged](/page/Weapon_Focus "Weapon Focus") +- [Weapon Focus: Slashing](/page/Weapon_Focus "Weapon Focus") + +[arcane_lore]: http://ddowiki.com/page/Arcane_Lore_(feat) "Arcane Lore (Feat)" +[artificer_knowlege]: http://ddowiki.com/page/Artificer_Knowledge "Artificer Knowlege" +[artificer_craft_mastery]: http://ddowiki.com/page/Artificer_Craft_Mastery +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[bonusFeats]: - "c:verify-rows=#feat:bonusFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.md new file mode 100644 index 00000000..9a408c60 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.md @@ -0,0 +1,202 @@ +# Barbarian Class Feats + +[Barbarian](http://ddowiki.com/page/Barbarian) + +## [Granted Feats](- "granted_level_1") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisites | +| --------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | None | +| [Dismiss Rage](http://ddowiki.com/page/Dismiss_Rage) | Active | Activate this barbarian ability to prematurely end your rage. | Barbarian Level 1 | +| [Fast Movement (Barbarian Class Feat)][fast_movement_barbarian] | Passive | The Fast Movement class feat allows a Barbarian to move 10% faster. | Barbarian Level 1 | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Favored Soul Level 1 | +| [Martial Weapon Proficiency: Light Hammer][martial_weapon] | Passive | You are proficient with Light Hammers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Longbow][martial_weapon] | Passive | You are proficient with Longbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Longsword][martial_weapon] | Passive | You are proficient with Longswords and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Rapier][martial_weapon] | Passive | You are proficient with Rapiers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Shortbow][martial_weapon] | Passive | You are proficient with Shortbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Shortsword][martial_weapon] | Passive | You are proficient with Shortswords and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Throwing Hammer][martial_weapon] | Passive | You are proficient with Throwing Hammers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Warhammer][martial_weapon] | Passive | You are proficient with Warhammers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Medium Armor Proficiency][medium_armor] | Passive | You are proficient with medium armor, and do not suffer the armor check penalty to attack rolls when wearing medium armor. You also gain 4 + 2/3 of your base attack bonus in physical resistance when wearing medium armor. Notes: A piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. Gaining Medium Armor Proficiency through Wizard Eldritch Knight, Sorcerer Eldritch Knight or bard Warchanter enhancements, medium armor will give less PRR than stated, even less than light armor. (DDO Forums) | Barbarian Level 1 | +| [Rage][rage_barbarian] | Active | A Barbarian can fly into a Barbarian Rage a certain number of times per day (Shrine). While raged, a Barbarian temporarily gains a +4 bonus to Strength, a +4 bonus to Constitution, and a +2 morale bonus on Will saves, but they suffer a –2 penalty to Armor Class. When the rage ends, however, you will lose the hit points granted to you by increased Constitution score and become fatigued (–2 penalty to Strength, –2 penalty to Dexterity, -10% penalty to movement speed) for 60 seconds. This penalty is removed later on by the Tireless Rage feat (granted at Barbarian level 17). Also note the Warforged Race is immune to fatigue - including Barbarian fatigue, from level 1. The fatigue may also be removed normally by standard means such as drinking a potion of lesser restoration. You can prematurely end your rage by using the Dismiss Rage feat. While raging, a barbarian cannot use any Intelligence-based skills or the Concentration skill, nor can he cast spells or activate magic items that require a command word, a spell trigger (such as a wand or clicky), or spell completion (such as a scroll) to function. He can use any feat he has except Defensive Fighting and Combat Expertise. A Barbarian also cannot drink any of the following potions while raged: Remove Curse, Remove Fear, Remove Blindness, Remove Disease unless they are the non-clicky types. Generally ones purchased from a guild vendor are non-clicky. The only clicky-type potion that can be drunk while raged is lesser restore. The duration of Rage is 18 + (Constitution modifier x 6) seconds. The rage-enhanced Constitution score is used for this calculation. The in-game text description of "30 seconds plus an additional amount of time based on your Constitution" is incorrect. | Barbarian Level 1 | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | Barbarian Level 1 | +| [Simple Weapon Proficiency: Club][simple_weapon] | Passive | You are proficient with Clubs and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Dagger][simple_weapon] | Passive | You are proficient with Daggers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Dart][simple_weapon] | Passive | You are proficient with Darts and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Handwrap][simple_weapon] | Passive | You are proficient with Handwraps and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Heavy Crossbow][simple_weapon] | Passive | You are proficient with Heavy Crossbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Heavy Mace][simple_weapon] | Passive | You are proficient with Heavy Maces and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Light Crossbow][simple_weapon] | Passive | You are proficient with Light Crossbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Light Mace][simple_weapon] | Passive | You are proficient with Light Maces and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Morningstar][simple_weapon] | Passive | You are proficient with Morningstars and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Quarterstaff][simple_weapon] | Passive | You are proficient with Quarterstaffs and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Sickle][simple_weapon] | Passive | You are proficient with Sickles and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Simple Projectile][simple_weapon] | Passive | You are proficient with Simple Projectiles and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Throwing Dagger][simple_weapon] | Passive | You are proficient with Throwing Daggers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | Barbarian, Ranger, Druid 1 | + +## Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trap Sense](http://ddowiki.com/page/Trap_Sense) | Passive | +1 on [reflex saving throws](http://ddowiki.com/page/Reflex_Save "Reflex Save") vs. [traps](http://ddowiki.com/page/Trap "Trap"), +1 [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") vs. [trap](http://ddowiki.com/page/Trap "Trap") attacks. The bonuses increase every 3 [levels](http://ddowiki.com/page/Level "Level") by +1. | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| ------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Uncanny Dodge](http://ddowiki.com/page/Uncanny_dodge) | Active | This feat grants you a 1% passive bonus to Dodge at levels 4, 6, 8, 12, 16, and 20. Also, you can activate this ability to gain a temporary 25% dodge bonus and a +4 reflex save bonus. As of Update 14, using this ability is no longer restricted by number of uses per rest. However, it is restricted by cooldown. | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trap Sense](http://ddowiki.com/page/Trap_Sense) | Passive | +1 on [reflex saving throws](http://ddowiki.com/page/Reflex_Save "Reflex Save") vs. [traps](http://ddowiki.com/page/Trap "Trap"), +1 [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") vs. [trap](http://ddowiki.com/page/Trap "Trap") attacks. The bonuses increase every 3 [levels](http://ddowiki.com/page/Level "Level") by +1. | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | Prerequisites | +| ------------------------------------------------------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| [Improved Uncanny Dodge](http://ddowiki.com/page/Improved_uncanny_dodge) | Passive / Active | This feat grants you a 1% passive bonus to Dodge at levels 4, 6, 8, 12, 16, and 20. Also, you can activate this ability to gain a temporary 50% dodge bonus and a +6 reflex save bonus. As of Update 14, using this ability is no longer restricted by number of uses per rest. However, it is restricted by cooldown. | Barbarian Level 8, Rogue Level 8 | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | Barbarian, Druid, Ranger Level 1 | + +## Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trap Sense](http://ddowiki.com/page/Trap_Sense) | Passive | +1 on [reflex saving throws](http://ddowiki.com/page/Reflex_Save "Reflex Save") vs. [traps](http://ddowiki.com/page/Trap "Trap"), +1 [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") vs. [trap](http://ddowiki.com/page/Trap "Trap") attacks. The bonuses increase every 3 [levels](http://ddowiki.com/page/Level "Level") by +1. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| ---------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Greater Rage](http://ddowiki.com/page/Greater_Rage) | Active | The bonuses of the barbarian's rage increase to a total of +6 strength, +6 constitution and +3 to will saving throws but the barbarian still incurs a reduction of its Armor Class by 2. Fatigue penalties remain the same as regular Rage. Enhances the regular Barbarian Rage feat. +10 Physical Resistance Rating when wearing Medium armor. +10 Melee Power while the rage is active. | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | + +## Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trap Sense](http://ddowiki.com/page/Trap_Sense) | Passive | +1 on [reflex saving throws](http://ddowiki.com/page/Reflex_Save "Reflex Save") vs. [traps](http://ddowiki.com/page/Trap "Trap"), +1 [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") vs. [trap](http://ddowiki.com/page/Trap "Trap") attacks. The bonuses increase every 3 [levels](http://ddowiki.com/page/Level "Level") by +1. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| [Indomitable Will](http://ddowiki.com/page/Indomitable_Will) | Passive | While in a Barbarian rage, a barbarian of 14th level or higher gains a +4 bonus on Will saves to resist enchantment spells. This bonus stacks with all other modifiers, including the morale bonus on Will saves he also receives during his rage. | Barbarian Level 14 | +| Wilderness Lore | Passive | This feat grants represents your knowledge of the wilderness. Barbarian, Druid, Ranger receive this feat once for every level. Bard received this feat at level 1, 3, 5, 7, 9 ,11, 13 ,15, 17, 19. | Barbarian, Ranger, Druid Level 1 | + +## Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | +| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trap Sense](http://ddowiki.com/page/Trap_Sense) | Passive | +1 on [reflex saving throws](http://ddowiki.com/page/Reflex_Save "Reflex Save") vs. [traps](http://ddowiki.com/page/Trap "Trap"), +1 [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") vs. [trap](http://ddowiki.com/page/Trap "Trap") attacks. The bonuses increase every 3 [levels](http://ddowiki.com/page/Level "Level") by +1. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| ------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------- | +| [Tireless Rage](http://ddowiki.com/page/Tireless_Rage) | Passive | Upon reaching level 17, a barbarian is no longer fatigued after raging. Als | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trap Sense](http://ddowiki.com/page/Trap_Sense) | Passive | +1 on [reflex saving throws](http://ddowiki.com/page/Reflex_Save "Reflex Save") vs. [traps](http://ddowiki.com/page/Trap "Trap"), +1 [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") vs. [trap](http://ddowiki.com/page/Trap "Trap") attacks. The bonuses increase every 3 [levels](http://ddowiki.com/page/Level "Level") by +1. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| -------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Mighty Rage](http://ddowiki.com/page/Mighty_Rage) | Passive / Active | The bonuses of the barbarian's rage increase to a total of +10 strength, +10 constitution and +5 to will saving throws but the barbarian still incurs a reduction of his Armor Class by 2. No longer has any fatigue penalties, as they were removed at level17 with Tireless Rage. Enhances the regular Barbarian Rage feat. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[martial_weapon]: http://ddowiki.com/page/Category:Martial_weapons "Martial Weapons" +[simple_weapon]: http://ddowiki.com/page/Category:Simple_weapons +[rage_barbarian]: http://ddowiki.com/page/Rage_(barbarian) "Rage (Barbarian)" +[fast_movement_barbarian]: http://ddowiki.com/page/Fast_Movement_(barbarian_class_feat) "Fast Movement (Barbarian)" +[wilderness_lore]: http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.md new file mode 100644 index 00000000..00f4e33d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.md @@ -0,0 +1,213 @@ +# Bard Class Feat + +## [Granted Feats](- "granted") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | This feat grants represents your knowledge of the Arcane. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. Artificer, Bard, Sorcerer, Wizard received this feat once for every level. | Bard Level 1 | | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | | +| **[Fascinate](http://ddowiki.com/page/Fascinate "Fascinate")** | [active](http://ddowiki.com/page/Active_feat "Active feat") | This [feat](http://ddowiki.com/page/Feat "Feat") forces the enemy to sit quietly and take no action for a short period of time or until it is attacked. | requires a minimum of 3 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform")) | | +| **[Inspire Courage](http://ddowiki.com/page/Inspire_Courage "Inspire Courage")** | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard with 3 or more ranks in the [Perform](http://ddowiki.com/page/Perform "Perform") [skill](http://ddowiki.com/page/Skill "Skill") can use song or poetics to inspire courage in his allies (including themselves), bolstering the party against [fear](http://ddowiki.com/page/Fear "Fear") and improving their combat abilities. To be affected, an ally must be able to hear the bard sing. The effect lasts for 4 minutes. An affected ally receives a +1 morale bonus on [saving throws](http://ddowiki.com/page/Saving_throw "Saving throw") against [charm](http://ddowiki.com/page/Charm "Charm") and [fear](http://ddowiki.com/page/Fear "Fear") effects and a +1 morale bonus on [attack](http://ddowiki.com/page/Attack "Attack") and weapon [damage](http://ddowiki.com/page/Damage "Damage") rolls. At 8th [level](http://ddowiki.com/page/Level "Level"), this bonus increases by 1 (+2 at level 8). Inspire courage is a mind-affecting ability. | requires a minimum of 3 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform")) | | +| Light Armor Proficiency | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | | | +| [Martial Weapon Proficiency: Longsword][martial_weapon] | Passive | You are proficient with Longswords and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Martial Weapon Proficiency: Rapier][martial_weapon] | Passive | You are proficient with Rapiers and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Martial Weapon Proficiency: Shortbow][martial_weapon] | Passive | You are proficient with Shortbows and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Martial Weapon Proficiency: Shortsword][martial_weapon] | Passive | You are proficient with Shortswords and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| [Simple Weapon Proficiency: Club][simple_weapon] | Passive | You are proficient with Clubs and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Dagger][simple_weapon] | Passive | You are proficient with Daggers and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Dart][simple_weapon] | Passive | You are proficient with Darts and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Handwrap][simple_weapon] | Passive | You are proficient with Handwraps and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Heavy Crossbow][simple_weapon] | Passive | You are proficient with Heavy Crossbows and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Heavy Mace][simple_weapon] | Passive | You are proficient with Heavy Maces and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Light Crossbow][simple_weapon] | Passive | You are proficient with Light Crossbows and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Light Mace][simple_weapon] | Passive | You are proficient with Light Maces and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Morningstar][simple_weapon] | Passive | You are proficient with Morningstars and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Quarterstaff][simple_weapon] | Passive | You are proficient with Quarterstaffs and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Sickle][simple_weapon] | Passive | You are proficient with Sickles and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Simple Projectile][simple_weapon] | Passive | You are proficient with Simple Projectiles and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| [Simple Weapon Proficiency: Throwing Dagger][simple_weapon] | Passive | You are proficient with Throwing Daggers and do not suffer a -4 attack penalty for using this weapon | Bard Level 1 | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | Prerequisites | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | --- | +| [Arcane Lore][arcane_lore] | Passive | This feat grants represents your knowledge of the Arcane. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. Artificer, Bard, Sorcerer, Wizard received this feat once for every level. | Bard Level 1 | | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | This feat grants represents your knowledge of the Arcane. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. Artificer, Bard, Sorcerer, Wizard received this feat once for every level. | Bard Level 1 | | +| [Inspire Competence](http://ddowiki.com/page/Inspire_competence "Inspire competence") | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard can use its music or poetics to help an ally succeed at a task. The ally must be within 30 feet and able to see and hear the bard. The bard must also be able to see the ally. The ally gets a +2 [competence bonus](http://ddowiki.com/page/Competence_bonus "Competence bonus") on [skill checks](http://ddowiki.com/page/Skill_check "Skill check") with all [skills](http://ddowiki.com/page/Skill "Skill"). A bard cannot inspire competence in themselves. Inspire competence is a mind-affecting ability. | requires 6 skill [rank (skill)s](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform") | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | Prerequisite | Icon | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------ | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------------------------------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Suggestion Song](http://ddowiki.com/page/Suggestion_%28song%29 "Suggestion (song)") | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard of 6th [level](http://ddowiki.com/page/Level "Level") or higher with 9 or more [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in the [Perform](http://ddowiki.com/page/Perform "Perform") [skill](http://ddowiki.com/page/Skill "Skill") can make a [Suggestion](http://ddowiki.com/page/Suggestion_%28song%29 "Suggestion (song)") (as the [Suggestion](http://ddowiki.com/page/Suggestion_%28spell%29 "Suggestion (spell)") [spell](http://ddowiki.com/page/Spell "Spell")) to a creature that he has already [fascinated](http://ddowiki.com/page/Fascinate "Fascinate"). Using this ability does not break the bard's concentration on the [fascinate](http://ddowiki.com/page/Fascinate "Fascinate") effect, nor does it allow a second [saving throw](http://ddowiki.com/page/Saving_throw "Saving throw") against the [fascinate](http://ddowiki.com/page/Fascinate "Fascinate") effect. | requires a minimum of 9 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform")) | | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Improved Inspire Courage](http://ddowiki.com/page/Improved_Inspire_Courage "Improved Inspire Courage") | [Passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat increases the bonuses of the Inspire Courage feat (i.e., attack and damage bonuses, and [saving throws](http://ddowiki.com/page/Saving_throw "Saving throw") vs. [charm](http://ddowiki.com/page/Charm "Charm") and [fear](http://ddowiki.com/page/Fear "Fear") effects) by an additional +1, for a total of +2. | requires [Inspire Courage](http://ddowiki.com/page/Inspire_Courage "Inspire Courage")) | | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | Prerequisites | Icon | +| ---------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Inspire Greatness](http://ddowiki.com/page/Inspire_Greatness "Inspire Greatness") | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard of 9th level or higher with 12 or more [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in a Perform skill can use its music or poetics to help an ally excel in combat. The ally must be within 30 feet and able to see and hear the bard. The bard must also be able to see the ally. The ally gets a +2 attack roll competence bonus, a +1 fortitude save competence bonus, and 2 temporary [hit dice](http://ddowiki.com/page/Hit_dice "Hit dice"). | requires a minimum of 12 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform") | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | Prerequisites | Icon | +| ---------------------------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Song of Freedom](http://ddowiki.com/page/Song_of_Freedom "Song of Freedom") | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard of 12th [level](http://ddowiki.com/page/Level "Level") or higher with 15 or more [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in a [Perform](http://ddowiki.com/page/Perform "Perform") [skill](http://ddowiki.com/page/Skill "Skill") can use its music or poetics to break all [enchantments](http://ddowiki.com/page/Enchantment "Enchantment") affecting an ally. The ally must be within 30 feet and able to see and hear the bard. The bard must also be able to see the ally. This ability is equivalent to the [Break Enchantment](http://ddowiki.com/page/Break_Enchantment "Break Enchantment") [spell](http://ddowiki.com/page/Spell "Spell"). | requires a minimum of 15 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform") | | + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Improved Inspire Courage](http://ddowiki.com/page/Improved_Inspire_Courage "Improved Inspire Courage") | [Passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat increases the bonuses of the Inspire Courage feat (i.e., attack and damage bonuses, and [saving throws](http://ddowiki.com/page/Saving_throw "Saving throw") vs. [charm](http://ddowiki.com/page/Charm "Charm") and [fear](http://ddowiki.com/page/Fear "Fear") effects) by an additional +1, for a total of +3. | requires [Inspire Courage](http://ddowiki.com/page/Inspire_Courage "Inspire Courage")) | | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Inspire Heroics](http://ddowiki.com/page/Inspire_Heroics "Inspire Heroics") | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard of 15th [level](http://ddowiki.com/page/Level "Level") or higher with 18 or more [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in a [Perform](http://ddowiki.com/page/Perform "Perform") [skill](http://ddowiki.com/page/Skill "Skill") can use its music or poetics to grant a +4 to saves (does not stack with Greater Heroism) and a +4 to AC to a single target. | requires a minimum of 18 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform") | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------ | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | Prerequisite | Icon | +| ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Mass Suggestion](http://ddowiki.com/page/Mass_Suggestion_%28song%29 "Mass Suggestion (song)") | [active](http://ddowiki.com/page/Active_feat "Active feat") | A bard of 18th [level](http://ddowiki.com/page/Level "Level") or higher with 21 or more [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in a [Perform](http://ddowiki.com/page/Perform "Perform") [skill](http://ddowiki.com/page/Skill "Skill") can activate this bard ability to charm multiple fascinated foes for a short time. | requires a minimum of 21 skill [ranks](http://ddowiki.com/page/Rank_%28skill%29 "Rank (skill)") in [Perform](http://ddowiki.com/page/Perform "Perform") | | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | Prerequisite | Icon | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| **[Religious Lore](http://ddowiki.com/page/Religious_Lore "Religious Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of religion. Obtain at level 1, 3, 5, 7, etc. of bard taken. | | | +| **[Wilderness Lore](http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore")** | [passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat grants represents your knowledge of the wilderness. | Obtain at level 1, 3, 5, 7, etc. of bard taken. | | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | Prerequisite | Icon | +| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | | +| [Improved Inspire Courage](http://ddowiki.com/page/Improved_Inspire_Courage "Improved Inspire Courage") | [Passive](http://ddowiki.com/page/Passive_feat "Passive feat") | This feat increases the bonuses of the Inspire Courage feat (i.e., attack and damage bonuses, and [saving throws](http://ddowiki.com/page/Saving_throw "Saving throw") vs. [charm](http://ddowiki.com/page/Charm "Charm") and [fear](http://ddowiki.com/page/Fear "Fear") effects) by an additional +1, for a total of +4. | requires [Inspire Courage](http://ddowiki.com/page/Inspire_Courage "Inspire Courage")) | | + +|[Wilderness Lore][wilderness_lore]| (passive): Represents your knowledge of the wilderness. This feat is received once +for every druid level. + +[existingFeat]: - "c:verify-rows=#feat:grantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[arcane_lore]: http://ddowiki.com/page/Arcane_lore "Arcane Lore" +[religious_lore]: http://ddowiki.com/page/Religious_Lore "Religious Lore" +[wilderness_lore]: http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore" +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[martial_weapon]: http://ddowiki.com/page/Category:Martial_weapons "Martial Weapons" +[simple_weapon]: http://ddowiki.com/page/Category:Simple_weapons diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/Classes.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/Classes.md new file mode 100644 index 00000000..afd40692 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/Classes.md @@ -0,0 +1,21 @@ +# Class Feats + +## Class Based Feats + +Certain traits can only be acquired by specific classes. + +- [x] [Alchemist](AlchemistClassFeatSpec.html "c:run") +- [x] [Artificer](ArtificerClassFeatSpec.html) +- [x] [Barbarian](BarbarianClassFeatSpec.html) +- [x] [Bard](BardClassFeatSpec.html) +- [x] [Cleric](ClericClassFeatSpec.html) +- [x] [Druid](DruidClassFeatSpec.html) +- [x] [FavoredSoul](FavoredSoulClassFeatSpec.html) +- [x] [Fighter](FighterClassFeatSpec.html "c:run") +- [x] [Monk](MonkClassFeatSpec.html) +- [x] [Paladin](PaladinClassFeatSpec.html) +- [x] [Ranger](RangerClassFeatSpec.html) +- [x] [Rogue](RogueClassFeatSpec.html) +- [x] [Sorcerer](SorcererClassFeatSpec.html) +- [x] [Warlock](WarlockClassFeatSpec.html) +- [x] [Wizard](WizardClassFeatSpec.html) diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.md new file mode 100644 index 00000000..50e494a0 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.md @@ -0,0 +1,39 @@ +# Cleric Class Feats + +## [Granted Feats](- "granted") + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ---- | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | | +| [Heavy Armor Proficiency][heavy_armor] | Passive | Benefit: You are proficient with heavy armor, and do not suffer the armor check penalty to attack rolls when wearing heavy armor. You also gain 6 + your base attack bonus in physical resistance when wearing heavy armor. | Cleric Level 1 | | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Cleric Level 1 | | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | | | +| [Medium Armor Proficiency][medium_armor] | Passive | You are proficient with medium armor, and do not suffer the armor check penalty to attack rolls when wearing medium armor. You also gain 4 + 2/3 of your base attack bonus in physical resistance when wearing medium armor. Notes: A piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. Gaining Medium Armor Proficiency through Wizard Eldritch Knight, Sorcerer Eldritch Knight or bard Warchanter enhancements, medium armor will give less PRR than stated, even less than light armor. (DDO Forums) | Cleric Level 1 | | +| [Religious Lore][religious_lore] | Passive | This feat grants represents your knowledge of the Religion. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. | Cleric Receives once for every heroic level | | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | Cleric Level 1 | | +| [Turn Undead](https://ddowiki.com/page/Turn_Undead) | Active | Attempts to drive away nearby undead or force them to cower. | Cleric Level 1 | | + +## Errata + +The following feats are not yet implemented + +- Turn Undead (active and passive): This feat allows the character to halt, or at higher levels destroy, undead + creatures. The character can do this (3 + their charisma modifier) times per day. While turning undead is an active + skill, this feat is passive as it adds to the total amount of turns per day. While enhancements from both Cleric and + Paladin stack, as far as number and power of turns, the base number of turns do not stack with each other. + +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[heavy_armor]: http://ddowiki.com/page/Heavy_Armor_Proficiency "Heavy Armor Proficiency" +[religious_lore]: http://ddowiki.com/page/Religious_Lore "Religious Lore" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[existingFeat]: - "c:verify-rows=#feat:grantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.md new file mode 100644 index 00000000..4d47adf0 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.md @@ -0,0 +1,164 @@ +# Druid Class Feats + +[Druid Class](http://ddowiki.com/page/Druid) + +## [Granted Feats](- "granted") + +## Level 1 + +| [ ][featLevel1] [Feats][result] | Description | +| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Call Wolf Companion](http://ddowiki.com/page/Call_Wolf_Companion) | (active):Activate this ability to summon your wolf companion. | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | +| [Druid: Spontaneous Casting](http://ddowiki.com/page/Druid:_Spontaneous_Casting) | (passive): You gain an additional spell preparation slot per spell level to cast Summon Nature's Ally spell of that level. | +| [Druidic Oath](http://ddowiki.com/page/Druidic_Oath) | (passive): Druids are prohibited from wearing metal armour, using metal shields, and using rune arms. Doing so suppresses your Druidic abilities. Warforged Druids are forbidden from taking armour feats other than Composite Plating. | +| [Goodberry](http://ddowiki.com/page/Goodberry) | (active): Transmutes natural matter around you into Goodberries. Goodberries are infused with primal magic, and provide a full meal's nourishment. If eaten in a tavern, they act as tavern food and drink, refilling your health and spell points. When cast, Goodberries appear in your inventory. The higher the caster level, the more nourishing the Goodberries are. | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | +| [Wild Empathy](http://ddowiki.com/page/Wild_Empathy) | (active): Activate this ability to lower an animal's or beast's aggression, effectively mesmerizing them. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Description | +| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | +| [Wild Shape: Bear](http://ddowiki.com/page/Wild_Shape) | Druids must pick between Wolf or Bear for their first wild shape. They will receive the other shape at level 5. | +| [Wild Shape: Wolf](http://ddowiki.com/page/Wild_Shape) | Druids must pick between Wolf or Bear for their first wild shape. They will receive the other shape at level 5. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Description | +| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- | +| [Wild Shape: Bear](http://ddowiki.com/page/Wild_Shape) | Druids now are granted the shape they did not pick at level 2. | +| [Wild Shape: Wolf](http://ddowiki.com/page/Wild_Shape) | Druids now are granted the shape they did not pick at level 2. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Description | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Improved Wild Empathy](http://ddowiki.com/page/Improved_wild_empathy) | (active): Allows the druid to charm an animal (similar to the Charm monster spell)[official] for 5 mins.[official] It can be used 3 times / rest period with a 60 second cool down.[official] Note: Improved wild empathy can not be dispelled. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Description | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | +| [Wild Shape: Dire Bear](http://ddowiki.com/page/Wild_Shape) | Druids must pick between Wolf or Bear for their first wild shape. They will receive the other shape at level 5. | +| [Wild Shape: Winter Wolf](http://ddowiki.com/page/Wild_Shape) | Druids must pick between Wolf or Bear for their first wild shape. They will receive the other shape at level 5. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Description | +| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Venom Immunity | Passive : You are immune to ability score damage from natural poisons. (This has no effect on magical or supernatural poisons.) | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Description | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | +| [Wild Shape: Dire Bear](http://ddowiki.com/page/Wild_Shape) | Druids must pick between Wolf or Bear for their first wild shape. They will receive the other shape at level 5. | +| [Wild Shape: Winter Wolf](http://ddowiki.com/page/Wild_Shape) | Druids must pick between Wolf or Bear for their first wild shape. They will receive the other shape at level 5. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Description | +| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Wild Shape: Fire Elemental](http://ddowiki.com/page/Wild_Shape) | Transform into a Fire Elemental. While in Fire Elemental form, you gain +1 bonus to caster level and max caster level to fire spells, but your air/earth/water spells get a -3 penalty to caster level and max caster level. You gain +10 racial bonus to fire resistance, -10 cold resistance. | +| [Wild Shape: Water Elemental](http://ddowiki.com/page/Wild_Shape) | Transform into a Water Elemental. While in Water Elemental form, you gain +1 bonus to caster level and max caster level to water spells, but your air/earth/fire spells get a -3 penalty to caster level and max caster level. You gain +10 racial bonus to cold resistance,+20 swim and -10 electric resistance. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Description | +| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| [Timeless Body](http://ddowiki.com/page/Timeless_Body) | (passive): Your soul is balanced. No corrupt influences can possess your body after death - you are immune to the spawn effect of most undead. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Description | +| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Wild Shape: Fire Elemental](http://ddowiki.com/page/Wild_Shape) | Transform into a Fire Elemental. While in Fire Elemental form, you gain +1 bonus to caster level and max caster level to fire spells, but your air/earth/water spells get a -3 penalty to caster level and max caster level. You gain +10 racial bonus to fire resistance, -10 cold resistance. | +| [Wild Shape: Water Elemental](http://ddowiki.com/page/Wild_Shape) | Transform into a Water Elemental. While in Water Elemental form, you gain +1 bonus to caster level and max caster level to water spells, but your air/earth/fire spells get a -3 penalty to caster level and max caster level. You gain +10 racial bonus to cold resistance,+20 swim and -10 electric resistance. | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Description | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | (passive): Represents your knowledge of the wilderness. This feat is received once for every druid level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +[wilderness_lore]: http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore" +[wild_shape]: http://ddowiki.com/page/Wild_Shape "Wild Shape" +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.md new file mode 100644 index 00000000..529bee33 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.md @@ -0,0 +1,191 @@ +# Favored Soul Class Feats + +[Favored Soul](http://ddowiki.com/page/Favored_Soul) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Favored Soul Level 1 | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | | +| [Medium Armor Proficiency][medium_armor] | Passive | You are proficient with medium armor, and do not suffer the armor check penalty to attack rolls when wearing medium armor. You also gain 4 + 2/3 of your base attack bonus in physical resistance when wearing medium armor. Notes: A piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. Gaining Medium Armor Proficiency through Wizard Eldritch Knight, Sorcerer Eldritch Knight or bard Warchanter enhancements, medium armor will give less PRR than stated, even less than light armor. (DDO Forums) | Favored Soul Level 1 | +| [Religious Lore][religious_lore] | Passive | This feat grants represents your knowledge of the Religion. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. | Favored Soul Receives once for every heroic level | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | Cleric Level 1 | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| --------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Energy Resistance: Acid][energy_resistance_acid] | Passive | GrantsAcid Resistance + 10 | +| [Energy Resistance: Cold][energy_resistance_cold] | Passive | GrantsCold Resistance + 10 | +| [Energy Resistance: Electricity][energy_resistance_electricity] | Passive | GrantsElectricity Resistance + 10 | +| [Energy Resistance: Fire][energy_resistance_fire] | Passive | GrantsFire Resistance + 10 | +| [Energy Resistance: Sonic][energy_resistance_sonic] | Passive | GrantsSonic Resistance + 10 | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| --------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------ | +| [Energy Resistance: Acid][energy_resistance_acid] | Passive | GrantsAcid Resistance + 10 | Available if not selected at level 5 | +| [Energy Resistance: Cold][energy_resistance_cold] | Passive | GrantsCold Resistance + 10 | Available if not selected at level 5 | +| [Energy Resistance: Electricity][energy_resistance_electricity] | Passive | GrantsElectricity Resistance + 10 | Available if not selected at level 5 | +| [Energy Resistance: Fire][energy_resistance_fire] | Passive | Grants Fire Resistance + 10 | Available if not selected at level 5 | +| [Energy Resistance: Sonic][energy_resistance_sonic] | Passive | Grants Sonic Resistance + 10 | Available if not selected at level 5 | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| --------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| [Energy Resistance: Acid][energy_resistance_acid] | Passive | GrantsAcid Resistance + 10 | Available if not selected at level 5 or 10 | +| [Energy Resistance: Cold][energy_resistance_cold] | Passive | GrantsCold Resistance + 10 | Available if not selected at level 5 or 10 | +| [Energy Resistance: Electricity][energy_resistance_electricity] | Passive | GrantsElectricity Resistance + 10 | Available if not selected at level 5 or 10 | +| [Energy Resistance: Fire][energy_resistance_fire] | Passive | Grants Fire Resistance + 10 | Available if not selected at level 5 or 10 | +| [Energy Resistance: Sonic][energy_resistance_sonic] | Passive | Grants Sonic Resistance + 10 | Available if not selected at level 5 or 10 | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Errata + +- Need to add Simple weapons +- Deity based feats are covered under separate spec + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[religious_lore]: http://ddowiki.com/page/Religious_Lore "Religious Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.md new file mode 100644 index 00000000..de6e48e0 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.md @@ -0,0 +1,224 @@ +# Fighter Class Feats + +[Fighter](http://ddowiki.com/page/Fighter) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | Fighter Level 1 | +| [Heavy Armor Proficiency][heavy_armor] | Passive | Benefit: You are proficient with heavy armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Fighter Level 1 | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Fighter Level 1 | +| [Martial Weapon Proficiency: Light Hammer][martial_weapon] | Passive | You are proficient with Light Hammers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Longbow][martial_weapon] | Passive | You are proficient with Longbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Longsword][martial_weapon] | Passive | You are proficient with Longswords and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Rapier][martial_weapon] | Passive | You are proficient with Rapiers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Shortbow][martial_weapon] | Passive | You are proficient with Shortbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Shortsword][martial_weapon] | Passive | You are proficient with Shortswords and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Throwing Hammer][martial_weapon] | Passive | You are proficient with Throwing Hammers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Martial Weapon Proficiency: Warhammer][martial_weapon] | Passive | You are proficient with Warhammers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Medium Armor Proficiency][medium_armor] | Passive | You are proficient with medium armor, and do not suffer the armor check penalty to attack rolls when wearing medium armor. You also gain 4 + 2/3 of your base attack bonus in physical resistance when wearing medium armor. Notes: A piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. Gaining Medium Armor Proficiency through Wizard Eldritch Knight, Sorcerer Eldritch Knight or bard Warchanter enhancements, medium armor will give less PRR than stated, even less than light armor. (DDO Forums) | Fighter Level 1 | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | Fighter Level 1 | +| [Simple Weapon Proficiency: Club][simple_weapon] | Passive | You are proficient with Clubs and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Dagger][simple_weapon] | Passive | You are proficient with Daggers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Dart][simple_weapon] | Passive | You are proficient with Darts and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Handwrap][simple_weapon] | Passive | You are proficient with Handwraps and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Heavy Crossbow][simple_weapon] | Passive | You are proficient with Heavy Crossbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Heavy Mace][simple_weapon] | Passive | You are proficient with Heavy Maces and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Light Crossbow][simple_weapon] | Passive | You are proficient with Light Crossbows and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Light Mace][simple_weapon] | Passive | You are proficient with Light Maces and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Morningstar][simple_weapon] | Passive | You are proficient with Morningstars and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Quarterstaff][simple_weapon] | Passive | You are proficient with Quarterstaffs and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Sickle][simple_weapon] | Passive | You are proficient with Sickles and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Simple Projectile][simple_weapon] | Passive | You are proficient with Simple Projectiles and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Throwing Dagger][simple_weapon] | Passive | You are proficient with Throwing Daggers and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | + +## Fighter Bonus Feats + +| [ ][fighterBonusFeats] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Bow Strength](https://ddowiki.com/page/Bow_Strength "Bow Strength") | Passive | Your brute strength allows you to draw your bow farther, allowing your arrows to strike harder. You add your Strength modifier to bow damage. | \* **Prerequisite:** [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot"), [Weapon Focus: Ranged Weapons](https://ddowiki.com/page/Weapon_Focus:_Ranged "Weapon Focus: Ranged"), [Base Attack Bonus +4](https://ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus"), **and one of:** [Power Attack](https://ddowiki.com/page/Power_Attack "Power Attack"), [Combat Expertise](https://ddowiki.com/page/Combat_Expertise "Combat Expertise"), [Zen Archery](https://ddowiki.com/page/Zen_Archery "Zen Archery"), or [Weapon Specialization: Ranged Weapons](https://ddowiki.com/page/Weapon_Specialization "Weapon Specialization"). | +| [Brutal Throw](https://ddowiki.com/page/Brutal_Throw "Brutal Throw") | Passive | You can use your Strength bonus instead of Dexterity bonus to determine bonus to attack with Thrown weapons if it is higher. | \* **Prerequisite:** +1 [Base Attack Bonus](https://ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus"), [Strength](https://ddowiki.com/page/Strength "Strength") 13 | +| [Cleave](https://ddowiki.com/page/Cleave "Cleave") | Active | Activate this feat to attack one or more enemies in an arc in front of you. This attack deals +1[W] damage. The area of effect is the same as any regular two handed weapons glancing blow reach. The difference is that cleave counts a full attack, dealing full special effect damage to all targets hit, and also producing a glancing blow (if using an appropriate weapon that allows them). Cleave uses a special animation which varies with weapon style, interrupts your regular attack chain, and generally executes at a slower speed. As of update 9, cleave now executes much faster for most weapon styles, resulting in much lower loss of attack speed than before. Additionally, attack speed debuffs do not apply to cleave; if you are under the effects of one, you can actually attack faster by using it. | [Power Attack](https://ddowiki.com/page/Power_Attack "Power Attack") | +| [Combat Expertise](https://ddowiki.com/page/Combat_Expertise "Combat Expertise") | Active | Defensive Combat Stance: While using Combat Expertise mode, you suffer -5 to your attack rolls but gain +10% feat bonus to Armor Class. Spells have three times their normal cooldown when this mode is active. Combat Expertise dispels and wards against all Rage effects. | [Intelligence](https://ddowiki.com/page/Intelligence "Intelligence") 13 | +| [Dodge](https://ddowiki.com/page/Dodge "Dodge") | Passive | This [feat](https://ddowiki.com/page/Feat "Feat") grants a 3% [Dodge bonus](https://ddowiki.com/page/Dodge_bonus "Dodge bonus"). | \* **Prerequisite:** [Dexterity](https://ddowiki.com/page/Dexterity "Dexterity") 13+ | +| [Exotic Weapon Proficiency](https://ddowiki.com/page/Exotic_Weapon_Proficiency "Exotic Weapon Proficiency") | Passive | This feat negates the -4 penalty to attack rolls from using an exotic weapon untrained. This feat only grants proficiency with a single weapon of your choice, so must be taken multiple times to gain proficiency in multiple exotic weapons. Most exotic weapons also have further special features unlocked by having the correct proficiency feat, see each individual sub feat for full details.[1](#myfootnote1) | \* **Prerequisite:** [Base Attack Bonus](https://ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, Some have Strength requirements - see sub feats | +| ![Icon Feat Great Cleave.png](/images/thumb/Icon_Feat_Great_Cleave.png/36px-Icon_Feat_Great_Cleave.png) [Great Cleave](https://ddowiki.com/page/Great_Cleave "Great Cleave") | **[Cooldown](/page/Cooldown "Cooldown"):** 5 seconds\* **Usage:** [Active](/page/Active_feat "Active feat") | This [feat](/page/Feat "Feat") attacks enemies in a wider arc than [Cleave](/page/Cleave "Cleave"). This attack deals +2[W] damage. Great Cleave has a greater chance to hit more enemies than [Cleave](/page/Cleave "Cleave"). This feat has a cooldown of 5 seconds. Like Cleave, Great Cleave also counts a full attack, dealing full special effect damage to all targets hit, and also producing a glancing blow (if using an appropriate weapon that allows them). \* Great Cleave does not replace [Cleave](/page/Cleave "Cleave"). In fact, both abilities are on separate timers, allowing both to be used and chained together in a fight. | [Cleave](/page/Cleave "Cleave"), [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 4 or higher | +| [Greater Single Weapon Fighting](https://ddowiki.com/page/Greater_Single_Weapon_Fighting "Greater Single Weapon Fighting") | Passive | Your Single Weapon Fighting bonus is increased to a +30% [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [attack speed](/page/Attack_speed "Attack speed") and an additional +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"), for a total of +6 Combat Style bonus to Melee Power. You now apply 50% more of your appropriate ability score to your damage. | \* **Prerequisite:** 7 ranks of [Balance](/page/Balance "Balance"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") +11, [Improved Single Weapon Fighting](/page/Improved_Single_Weapon_Fighting "Improved Single Weapon Fighting") | +| [Greater Two Handed Fighting](https://ddowiki.com/page/Greater_Two_Handed_Fighting "Greater Two Handed Fighting") | Passive | The Greater Two Handed Fighting feat adds a [glancing blow](/page/Glancing_blow "Glancing blow") to your attack sequence, and increases the damage of glancing blow attacks when wielding a two-handed weapon by an additional 10% for a total of 50%. Also increases the chance for weapon effects to trigger on glancing blows by an additional 3% for a total of 9%. Your [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power") is increased by +2 to a total of +6. | \* **Prerequisite:** 17 [Strength](/page/Strength "Strength"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") +11, and [Improved Two Handed Fighting](/page/Improved_Two_Handed_Fighting "Improved Two Handed Fighting") | +| [Greater Two Weapon Fighting](https://ddowiki.com/page/Greater_Two_Weapon_Fighting "Greater Two Weapon Fighting") | Passive | Greater Two Weapon Fighting increases the chance to proc an off-hand attack by 20%, bringing the total chance to 80%. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 17+, [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 11 or higher, [Improved Two Weapon Fighting](/page/Improved_Two_Weapon_Fighting "Improved Two Weapon Fighting"). | +| [Greater Weapon Focus](https://ddowiki.com/page/Greater_Weapon_Focus "Greater Weapon Focus") | Passive | This [feat](/page/Feat "Feat") grants an additional +1 on to-hit rolls with the chosen [weapon type](/page/Weapon_type "Weapon type") (thrown, ranged, bludgeoning, piercing or slashing). It also grants +2 [Melee Power](/page/Melee_Power "Melee Power") (bludgeoning/piercing/slashing) or +2 [Ranged Power](/page/Ranged_Power "Ranged Power") (ranged/thrown). It can be taken multiple times, once for each of the different types, and the melee/ranged power stacks. This [feat](/page/Feat "Feat") stacks with [Weapon Focus](/page/Weapon_Focus "Weapon Focus"). | \* **Prerequisite:** [Fighter](/page/Fighter "Fighter") (level 8) and [Weapon Focus](/page/Weapon_Focus "Weapon Focus") in a specific [weapon type](/page/Weapon_type "Weapon type") | +| [Greater Weapon Specialization](https://ddowiki.com/page/Greater_Weapon_Specialization "Greater Weapon Specialization") | Passive | Greater Weapon Specialization in a [weapon type](/page/Weapon_type "Weapon type") adds +2 damage when using the specified weapon type, that stacks with the bonus from [Weapon Specialization](/page/Weapon_Specialization "Weapon Specialization"). It also grants +2 [Melee Power](/page/Melee_Power "Melee Power") (bludgeoning/piercing/slashing) or +2 [Ranged Power](/page/Ranged_Power "Ranged Power") (ranged/thrown). It can be taken multiple times, once for each of the different types, and the melee/ranged power stacks. | [Fighter](/page/Fighter "Fighter") level 12, [Weapon Focus](/page/Weapon_Focus "Weapon Focus") and [Weapon Specialization](/page/Weapon_Specialization "Weapon Specialization") in the same weapon type | +| [Hamstring](https://ddowiki.com/page/Hamstring "Hamstring") | Active | When this [feat](/page/Feat "Feat") is activated, a [melee special attack](/page/Melee*special_attack "Melee special attack") is made. If it hits, the target's movement rate is reduced by 50% for 12 seconds. Unlike [Trip](/page/Trip "Trip") and [Stunning Blow](/page/Stunning_Blow "Stunning Blow"), no save is made against this effect, as of [Module 4](/page/Module_4.0:\_Reaver%27s_Bane#Skills.2C_Feats.2C*.26_Abilities "Module 4.0: Reaver's Bane"). | \* **Prerequisite:** [Sneak Attack](/page/Sneak_Attack "Sneak Attack") ([Rogue](/page/Rogue "Rogue") level 1) | +| [Heavy Armor Champion](https://ddowiki.com/page/Heavy_Armor_Champion "Heavy Armor Champion") | Passive | While in [heavy armor](/page/Heavy_armor "Heavy armor"), get +12 [PRR](/page/PRR "PRR") and [MRR](/page/MRR "MRR").While in [heavy armor](/page/Heavy_armor "Heavy armor"), get +12 [PRR](/page/PRR "PRR") and [MRR](/page/MRR "MRR"). | \* **Prerequisite:** 14 [Fighter](/page/Fighter "Fighter") levels | +| [Heavy Armor Combatant](https://ddowiki.com/page/Heavy_Armor_Combatant "Heavy Armor Combatant") | Passive | While in [heavy armor](/page/Heavy_armor "Heavy armor"), get +6 [PRR](/page/PRR "PRR") and [MRR](/page/MRR "MRR"). | \* **Prerequisite:** 6 [Fighter](/page/Fighter "Fighter") levels | +| [Heavy Armor Master](https://ddowiki.com/page/Heavy_Armor_Master "Heavy Armor Master") | Passive | While in [heavy armor](/page/Heavy_armor "Heavy armor"), get +9 [PRR](/page/PRR "PRR") and [MRR](/page/MRR "MRR"). | \* **Prerequisite:** 10 [Fighter](/page/Fighter "Fighter") levels | +| [Heavy Armor Training](https://ddowiki.com/page/Heavy_Armor_Training "Heavy Armor Training") | Passive | While in [heavy armor](/page/Heavy_armor "Heavy armor"), get +3 [PRR](/page/PRR "PRR") and [MRR](/page/MRR "MRR"). | \* **Prerequisite:** 2 [Fighter](/page/Fighter "Fighter") levels | +| [Improved Critical](https://ddowiki.com/page/Improved_Critical "Improved Critical") | [Passive](/page/Passive_feat "Passive feat") | **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 8 or higher | This [feat](/page/Feat "Feat") adds 1, 2, or 3 to critical [threat range](/page/Threat_range "Threat range") based on the weapon type's unmodified threat range. | +| [Improved Feint](https://ddowiki.com/page/Improved_Feint "Improved Feint") | Active | **Official**: "A melee attack which also [Bluffs](/page/Bluff "Bluff") the enemy, enabling [Sneak attacks](/page/Sneak_attack "Sneak attack") for a short period of time." \* As of [Update 34 Patch 2 (Release Notes)](/page/Update_34_Patch_2_Release_Notes "Update 34 Patch 2 Release Notes") Improved Feint no longer requires [Combat Expertise](/page/Combat_Expertise "Combat Expertise"). The feat now adds +2[W] damage, and has had its cooldown reduced to six seconds. Threat reduction has been increased to 40%. | \* **Prerequisite:** One of [Sneak Attack](/page/Sneak_Attack "Sneak Attack") ([Rogue](/page/Rogue "Rogue") level 1) or [Half-Elf Dilettante: Rogue](/page/Half-Elf_Dilettante:\_Rogue "Half-Elf Dilettante: Rogue") | +| [Improved Precise Shot](https://ddowiki.com/page/Improved_Precise_Shot "Improved Precise Shot") | Active Stance | With Improved Precise Shot, your ranged attacks pass through and potentially damage all foes in the projectile's path. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 19, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot"), [Precise Shot](/page/Precise_Shot "Precise Shot"), and [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") +11 | +| [Improved Shield Bash](https://ddowiki.com/page/Improved_Shield_Bash "Improved Shield Bash") | Active | You keep your [shield bonus](/page/Shield*bonus "Shield bonus") while bashing with a shield, and gain a 20% chance to make a secondary shield bash while attacking up to once a second.\* Improved Shield Bash enables the character to retain the [shield bonus](/page/Shield_bonus "Shield bonus") to his [armor class](/page/Armor_class "Armor class") when actively using [shield bash](/page/Shield_bash "Shield bash"), and adds +20% to the characters total chance of making a [Secondary Shield Bash](/page/Shield_bashing#Secondary*.28passive.29_shield_bashing "Shield bashing") when attacking with a one-handed weapon and shield. | \* **Prerequisite:** [Shield Proficiency: General](/page/Shield_Proficiency:\_General "Shield Proficiency: General") | +| [Improved Shield Mastery](https://ddowiki.com/page/Improved_Shield_Mastery "Improved Shield Mastery") | Passive | You are exceptionally skilled with the use of a shield, and your [physical resistance](/page/Physical_Resistance_Rating "Physical Resistance Rating") is increased by 5 when using a buckler or small shield, 10 when using a large shield, or 15 when using a tower shield. Your [doublestrike](/page/Doublestrike "Doublestrike") chance while using a shield is increased by 5% to 8%. Your [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power") is increased by +3 to +6. | \* **Prerequisite:** [Shield Mastery](/page/Shield_Mastery "Shield Mastery"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") +8 | +| [Improved Single Weapon Fighting](https://ddowiki.com/page/Improved_Single_Weapon_Fighting "Improved Single Weapon Fighting") | Passive | Your Single Weapon Fighting bonus is increased to a +20% [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [attack speed](/page/Attack_speed "Attack speed") and an additional +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). You now apply 25% more of your appropriate ability score modifier to your damage instead of just your modifier (for instance, you add 1.25 times your Strength modifier as damage, similar to [Two Handed Fighting](/page/Two_Handed_Fighting "Two Handed Fighting").) | \* **Prerequisite:** 4 ranks of [Balance](/page/Balance "Balance"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") +6, [Single Weapon Fighting](/page/Single_Weapon_Fighting "Single Weapon Fighting") | +| [Improved Sunder](https://ddowiki.com/page/Improved_Sunder "Improved Sunder") | Active | Using this [melee special attack](/page/Melee_special_attack "Melee special attack"), you may reduce the target's [Armor Class](/page/Armor_Class "Armor Class") by 5 and fortification by 10% on a failed saving throw for 24 seconds. Some creatures may be immune to the sunder effect. A successful [Fortitude save](/page/Fortitude_save "Fortitude save") negates this effect. Additionally, Improved Sunder will apply a -3 [Fortitude](/page/Fortitude "Fortitude") Saving Throw penalty that lasts for 24 seconds on a successful hit (regardless of if they save). The saving throw penalty stacks up to five times (Maximum of -15 to [Fortitude](/page/Fortitude "Fortitude") save). [DC](/page/DC "DC") 14 + [Str](/page/Str "Str") mod. | \* **Prerequisite:** [Sunder](/page/Sunder "Sunder"), [Power Attack](/page/Power_Attack "Power Attack") | +| [Improved Trip](https://ddowiki.com/page/Improved_Trip "Improved Trip") | Active | Improved Trip has a chance to trip the target, rendering it prone. Improved trip has a superior base DC (+4) and lasts for a longer maximum period of time than [Trip](/page/Trip "Trip") (60 seconds instead of 30). This feat replaces [Trip](/page/Trip "Trip") as an action. | \* **Prerequisite:** [Combat Expertise](/page/Combat_Expertise "Combat Expertise") | +| [Improved Two Handed Fighting](https://ddowiki.com/page/Improved_Two_Handed_Fighting "Improved Two Handed Fighting") | Passive | Increases the damage of [glancing blow](/page/Glancing_blow "Glancing blow") attacks when wielding a two-handed weapon by an additional 10%, for a total of 40%. Also increases the chance for weapon effects to trigger on glancing blows by an additional 3% for a total of 6%. Your [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power") is increased by +2 to a total of +4. | \* **Prerequisite:** 17 [Strength](/page/Strength "Strength"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +6, [Two Handed Fighting](/page/Two_Handed_Fighting "Two Handed Fighting") | +| [Improved Two Weapon Fighting](https://ddowiki.com/page/Improved_Two_Weapon_Fighting "Improved Two Weapon Fighting") | Passive | This feat increases the chance to proc an off-hand attack by 20% (includes unarmed [Monk](/page/Monk "Monk")), bringing the total chance to 60%. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 17, [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 6 or higher, [Two-weapon fighting](/page/Two-weapon_fighting "Two-weapon fighting"). | +| [Knight's Training](https://ddowiki.com/page/Knight%27s_Training "Knight's Training") | Passive | You have undergone rigorous military training with the traditional weapons of war. These weapons receive one of the following [morale bonuses](/page/Morale_bonus "Morale bonus") in your hands. | | +| [Manyshot](https://ddowiki.com/page/Manyshot "Manyshot") | Active | For the next 20 seconds, add 120 to your [Doubleshot](/page/Doubleshot "Doubleshot") and {4x your Base Attack Bonus} to [Ranged Power](/page/Ranged_Power "Ranged Power"). Cooldown: 2 minutes. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 17, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot"), [Rapid Shot](/page/Rapid_Shot "Rapid Shot"), and [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") +6 | +| [Mobility](https://ddowiki.com/page/Mobility "Mobility") | Passive | Mobility increases the maximum dexterity bonus permitted by armor and tower shields by 2, and adds a +4 bonus to [Armor Class](/page/Armor_Class "Armor Class") while [tumbling](/page/Tumbling "Tumbling"). You will also gain a 2% [dodge bonus](/page/Dodge_bonus "Dodge bonus"). | \* **Prerequisite:** [Dodge](/page/Dodge "Dodge") | +| [Oversized Two Weapon Fighting](https://ddowiki.com/page/Oversized_Two_Weapon_Fighting "Oversized Two Weapon Fighting") | Passive | When wielding a one handed weapon in your off-hand, you take penalties for fighting with two weapons as if you were wielding a [light weapon](/page/Light_weapon "Light weapon") on your offhand. | \* **Prerequisite:** [Strength](/page/Strength "Strength") 12+, [Two Weapon Fighting](/page/Two_Weapon_Fighting "Two Weapon Fighting") | +| [Point Blank Shot](https://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") | Passive | Grants a +1 bonus to hit within 45 feet, and your ranged weapons deal +1[W]. (See [weapon dice multiplier](/page/Weapon_dice_multiplier "Weapon dice multiplier") - A weapon that deals [1d6] damage per hit will deal 2*[1d6] damage per hit instead, while a weapon that deals [2d8] damage per hit will deal 2*[2d8] damage per hit instead. This effects the base dice of the associated weapon any time they are rolled, including [critical hits](/page/Critical_hit "Critical hit").) | | +| [Power Attack](https://ddowiki.com/page/Power_Attack "Power Attack") | Active Toggled Stance | This [feat](/page/Feat "Feat") exchanges part of your attack bonus for extra melee damage. It reduces your hit bonus by 5, or your [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus"), whichever is lower. Then your successful attacks will have their damage increased by the same amount. [Two-handed weapons](/page/Two-handed_weapons "Two-handed weapons") get twice that damage bonus. (Unarmed strikes count as one-handed.) Typically, this means [one-handed weapons](/page/One-handed_weapons "One-handed weapons") get +5 and two-handed get +10 to damage. | \* **Prerequisite:** [Strength](/page/Strength "Strength") Base 13+ | +| [Power Critical](https://ddowiki.com/page/Power_Critical "Power Critical") | Passive | Power Critical grants a +2 bonus to confirm [critical hits](/page/Critical_hit "Critical hit") and +2 bonus to critical hit damage (before multipliers are applied). | \* **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 4+, [Weapon Focus](/page/Weapon_Focus "Weapon Focus") | +| [Precise Shot](https://ddowiki.com/page/Precise_Shot "Precise Shot") | Passive | With the Precise Shot feat, your targeted ranged attacks pass through friend and foe alike to strike your target (no damage will be done other than to your target). This feat also grants you the Offensive Ranged Stance **Archer's Focus**, which lets you deal progressively more damage with ranged attacks while standing still. | \* **Prerequisite:** [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot") | +| [Precision](https://ddowiki.com/page/Precision "Precision") | Active Toggled Stance | Offensive Combat Stance: While using Precision mode, you gain +5% to hit and reduce the target's fortification against your attacks by 25%. Cannot be used while raged. | \* **Prerequisite:** +1 [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus"), [DEX](/page/DEX "DEX") 13 | +| [Quick Draw](https://ddowiki.com/page/Quick_Draw "Quick Draw") | Passive | You can draw and fire throwing weapons more rapidly. In addition, you re-draw your weapons much faster after casting Spells and Spell-Like Abilities, eliminating the delay between casting and attacking. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Rapid Reload](https://ddowiki.com/page/Rapid_Reload "Rapid Reload") | Passive | [Rapid reload](/page/Rapid_reload "Rapid reload") allows crossbows, including repeating crossbows, to be reloaded significantly [faster](/page/Attack_speed "Attack speed"), \_About 25% faster if you have no other attack speed boosts active | \* **Prerequisite:** Proficiency with [light crossbows](/page/Light_crossbow "Light crossbow"), [Artificer](/page/Artificer "Artificer") Level 1 | +| [Rapid Shot](https://ddowiki.com/page/Rapid_Shot "Rapid Shot") | Passive | You can make ranged attacks about 20% [faster](/page/Attack_speed "Attack speed") and reload faster when using a ranged weapon. It appears to make the bolts from a crossbow travel faster, ie there is less elapsed time from firing to striking the target, as of 1/7/2018. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 13+, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot") | +| [Resilience](https://ddowiki.com/page/Resilience "Resilience") | Active Toggled Stance | Defensive Combat Stance: While using Resilience mode, you gain a +4 bonus to all [saves](/page/Save "Save"). [Spells](/page/Spell "Spell") have three times their normal [cooldown](/page/Cooldown "Cooldown") when this mode is active. Cannot be used while Barbarian [raged](/page/Rage*(feat) "Rage (feat)"). The [Rage (spell)](/page/Rage*(spell) "Rage (spell)") and Resilience coexist without any issues. | \* **Prerequisite:** [Constitution](/page/Constitution "Constitution") 13+, [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Sap](https://ddowiki.com/page/Sap "Sap") | Active | When this [feat](/page/Feat "Feat") is activated, a [melee special attack](/page/Melee*special_attack "Melee special attack") is made. If it hits, the victim is [dazed](/page/Dazed "Dazed") for 18 seconds normally or 30 seconds from a successful sneak attack. (Whether or not your character can normally perform sneak attacks) or until they are damaged. Unlike [Trip](/page/Trip "Trip") and [Stunning Blow](/page/Stunning_Blow "Stunning Blow"), no save is made against this effect, as of [Module 4](/page/Module_4.0:\_Reaver%27s_Bane#Skills.2C_Feats.2C*.26_Abilities "Module 4.0: Reaver's Bane"). | | +| [Shield Deflection](https://ddowiki.com/page/Shield_Deflection "Shield Deflection") | Active | When actively blocking with any type of shield you are proficient with, you have a (competence bonus) chance to completely ignore Acid, Cold, Electric, and Fire damage. The chance is based on the type of shield being used:\* Buckler: 20% Small Shield: 25% Large Shield: 30% Tower Shield: 40% | \* **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") +8, [proficiency](/page/Proficiency "Proficiency") with [shields](/page/Shield "Shield") | +| [Shield Mastery](https://ddowiki.com/page/Shield_Mastery "Shield Mastery") | Passive | You are skilled with the use of a shield, and your [physical resistance](/page/Physical_Resistance_Rating "Physical Resistance Rating") is increased by 3 when using a buckler or small shield, 5 when using a large shield, or 10 when using a tower shield. You gain 3% [doublestrike](/page/Doublestrike "Doublestrike") while using a shield. While fighting with a shield you gain a +3 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** [Shield Proficiency (General)](/page/Shield*Proficiency*(General) "Shield Proficiency (General)") | +| [Shot on the Run](https://ddowiki.com/page/Shot_on_the_Run "Shot on the Run") | Passive | Shot on the Run negates the (-4) penalty to attack rolls associated with moving while firing all types of [ranged weapons](/page/Category:Ranged_weapons "Category:Ranged weapons") and [throwing weapons](/page/Throwing_weapons "Throwing weapons") and gives +3 [ranged power](/page/Ranged_power "Ranged power"). | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 13+, [Point Blank Shot](/page/Point_Blank_Shot "Point Blank Shot"), [Mobility](/page/Mobility "Mobility"), [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 4+ or higher | +| [Single Weapon Fighting](https://ddowiki.com/page/Single_Weapon_Fighting "Single Weapon Fighting") | Passive | While Single Weapon Fighting, you gain +10% [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [attack speed](/page/Attack_speed "Attack speed") and +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). Requires fighting with a single one-handed weapon, and wielding only an [orb](/page/Orb "Orb"), [runearm](/page/Runearm "Runearm"), or nothing in your offhand. | \* **Prerequisite:** 2 ranks of [Balance](/page/Balance "Balance") | +| [Slicing Blow](https://ddowiki.com/page/Slicing_Blow "Slicing Blow") | Active | Using this attack, you deal 1 point of [Constitution](/page/Constitution "Constitution") damage to your target and deal 1d4 additional damage 2 seconds later as the target bleeds. The target suffers an additional round of bleeding for every 3 character levels, up to a max of 6 at level 15\. Unlike [Trip](/page/Trip "Trip") and [Stunning Blow](/page/Stunning_Blow "Stunning Blow"), no save is made against this effect. | | +| [Spring Attack](https://ddowiki.com/page/Spring_Attack "Spring Attack") | Passive | Character suffers no penalty to his attack roll when meleeing and moving. You will also gain a 2% [dodge bonus](/page/Dodge_bonus "Dodge bonus"). | \* [Mobility](/page/Mobility "Mobility"), [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 4 or higher, [Dodge](/page/Dodge "Dodge"), [Dexterity](/page/Dexterity "Dexterity") 13+ | +| [Stunning Blow](https://ddowiki.com/page/Stunning_Blow "Stunning Blow") | Active | Using this [melee special attack](/page/Melee_special_attack "Melee special attack"), you may stun the target for 6 seconds. [Stunned](/page/Stunned "Stunned") creatures are considered [helpless](/page/Helpless "Helpless"). A successful [Fortitude save](/page/Fortitude_save "Fortitude save") negates this effect. ([DC](/page/DC "DC"): 10 + [Strength](/page/Strength "Strength") modifier + other modifiers) | | +| [Superior Weapon Focus](https://ddowiki.com/page/Superior_Weapon_Focus "Superior Weapon Focus") | Passive | This [feat](/page/Feat "Feat") grants an additional +1 on to-hit rolls with the chosen [weapon type](/page/Weapon_type "Weapon type") (thrown, ranged, bludgeoning, piercing or slashing). This [feat](/page/Feat "Feat") stacks with [Weapon Focus](/page/Weapon_Focus "Weapon Focus") and [Greater Weapon Focus](/page/Greater_Weapon_Focus "Greater Weapon Focus"). It also grants +2 [Melee Power](/page/Melee_Power "Melee Power") (bludgeoning/piercing/slashing) or +2 [Ranged Power](/page/Ranged_Power "Ranged Power") (ranged/thrown). It can be taken multiple times, once for each of the different types, and the melee/ranged power stacks. | \* **Prerequisite:** [Fighter](/page/Fighter "Fighter") level 16 and [Greater Weapon Focus](/page/Greater_Weapon_Focus "Greater Weapon Focus") in a specific weapon type | +| [Tactical Combatant](https://ddowiki.com/page/Tactical_Combatant "Tactical Combatant") | Passive | +4 bonus to [tactical feat](/page/Tactical_feat "Tactical feat") DC's. | \* **Prerequisite:** 8 [Fighter](/page/Fighter "Fighter") levels | +| [Tactical Mastery](https://ddowiki.com/page/Tactical_Mastery "Tactical Mastery") | Passive | +6 bonus to [tactical feat](/page/Tactical_feat "Tactical feat") DC's. | \* **Prerequisite:** 12 [Fighter](/page/Fighter "Fighter") levels | +| [Tactical Supremacy](https://ddowiki.com/page/Tactical_Supremacy "Tactical Supremacy") | Passive | \* **Prerequisite:** 16 [Fighter](/page/Fighter "Fighter") levels | \* **Prerequisite:** 16 [Fighter](/page/Fighter "Fighter") levels | +| [Tactical Training](https://ddowiki.com/page/Tactical_Training "Tactical Training") | Passive | \* **Prerequisite:** 16 [Fighter](/page/Fighter "Fighter") levels | \* **Prerequisite:** 4 [Fighter](/page/Fighter "Fighter") levels | +| [Two Handed Fighting](https://ddowiki.com/page/Two_Handed_Fighting "Two Handed Fighting") | Passive | Increases the damage of [glancing blow](/page/Glancing_blow "Glancing blow") attacks when wielding a two-handed weapon by 10% (from a base of 20% normal weapon damage.) This feat also grants a 3% chance for weapon effects to trigger on glancing blows. While fighting with a two-handed weapon you gain a +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** 15 [Strength](/page/Strength "Strength") | +| [Two Weapon Blocking](https://ddowiki.com/page/Two_Weapon_Blocking "Two Weapon Blocking") | Passive | Two Weapon Blocking increases by +2 the [damage reduction](/page/Damage_reduction "Damage reduction") when [actively blocking](/page/Active_blocking "Active blocking") with two weapons. | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 15+, [Two Weapon Fighting](/page/Two_Weapon_Fighting "Two Weapon Fighting") | +| [Two Weapon Defense](https://ddowiki.com/page/Two_Weapon_Defense "Two Weapon Defense") | Passive | Two Weapon Defense grants you a +1 bonus to your AC and 5 [Physical Resistance Rating](/page/Physical_Resistance_Rating "Physical Resistance Rating") when you wield two weapons. (This bonus does not apply when fighting unarmed/with handwraps.) | \* **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 15+, [Two Weapon Fighting](/page/Two_Weapon_Fighting "Two Weapon Fighting") | +| [Two Weapon Fighting](https://ddowiki.com/page/Two_Weapon_Fighting "Two Weapon Fighting") | Passive | Two Weapon Fighting reduces the to-hit penalty when using two weapons at the same time. | **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 15 | +| [Weapon Finesse](https://ddowiki.com/page/Weapon_Finesse "Weapon Finesse") | Passive | Weapon finesse allows the character to use his [dexterity](/page/Dexterity "Dexterity") [modifier](/page/Modifier "Modifier") instead of the [strength](/page/Strength "Strength") [modifier](/page/Modifier "Modifier") when making melee attack rolls with [light weapons,](/page/Light_weapons "Light weapons") [rapiers](/page/Rapier "Rapier"), and [unarmed](/page/Unarmed "Unarmed") strikes. The highest of the [strength](/page/Strength "Strength") and [dexterity](/page/Dexterity "Dexterity") modifiers will be used for attack rolls with qualifying weapons. The [strength](/page/Strength "Strength") [modifier](/page/Modifier "Modifier") is still used as a bonus to the damage roll, however. | \* **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of +1, [Dexterity](/page/Dexterity "Dexterity") 13+ | +| [Weapon Focus](https://ddowiki.com/page/Weapon_Focus "Weapon Focus") | Passive | Weapon Focus grants a +1 bonus on to-hit rolls with any of the weapons listed in the chosen [weapon type](/page/Weapon_type "Weapon type") ([bludgeoning](/page/Bludgeoning "Bludgeoning") (includes animal form), [piercing](/page/Piercing "Piercing"), [ranged](/page/Ranged_weapon "Ranged weapon"), [slashing](/page/Slashing "Slashing") or [thrown](/page/Thrown_weapon "Thrown weapon")). It also grants +2 [Melee Power](/page/Melee_Power "Melee Power") (bludgeoning/piercing/slashing) or +2 [Ranged Power](/page/Ranged_Power "Ranged Power") (ranged/thrown). It can be taken multiple times, once for each of the different types, and the melee/ranged power stacks. | \* **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of +1 or higher | +| [Weapon Specialization](https://ddowiki.com/page/Weapon_Specialization "Weapon Specialization") | Passive | **Weapon Specialization** grants a bonus of +2 to damage with the chosen [weapon type](/page/Weapon_type "Weapon type") (thrown, ranged, bludgeoning, piercing or slashing). It also grants +2 [Melee Power](/page/Melee_Power "Melee Power") (bludgeoning/piercing/slashing) or +2 [Ranged Power](/page/Ranged_Power "Ranged Power") (ranged/thrown). It can be taken multiple times, once for each of the different types, and the melee/ranged power stacks. | \* \* **Prerequisite:** [Fighter](/page/Fighter "Fighter") (level 4), [Weapon focus](/page/Weapon_focus "Weapon focus") with the same [weapon type](/page/Weapon_type "Weapon type") | +| [Whirling Steel Strike](https://ddowiki.com/page/Whirling_Steel_Strike "Whirling Steel Strike") | Passive | You treat [longswords](/page/Longsword "Longsword") as if they were [monk weapons](/page/Monk_weapons "Monk weapons"), remaining [centered](/page/Centered "Centered") when you wield them. | [Weapon Focus](/page/Weapon_Focus "Weapon Focus"): Slashing [Monk](/page/Monk "Monk") Level 1 one of following; Proficiency: Longswords, [Favored by the Sovereign Host](/page/Favored_by_the_Sovereign_Host "Favored by the Sovereign Host"), or [Half-Elf](/page/Half-Elf "Half-Elf") race with [Fighter dilettante](/page/Half-Elf_Dilettante:\_Fighter "Half-Elf Dilettante: Fighter"). | +| [Whirlwind Attack](https://ddowiki.com/page/Whirlwind_Attack "Whirlwind Attack") | Active | This [feat](/page/Feat "Feat") attacks all enemies in a 360 degree arc around the character. This attack deals +4[W] damage. | \* **Prerequisite:** [Combat Expertise](/page/Combat_Expertise "Combat Expertise"), [Spring Attack](/page/Spring_Attack "Spring Attack") (which requires [Dodge](/page/Dodge "Dodge") and [Mobility](/page/Mobility "Mobility")), [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of +4 or higher | +| [Zen Archery](https://ddowiki.com/page/Zen_Archery "Zen Archery") | Passive | You can use your [Wisdom](/page/Wisdom "Wisdom") bonus instead of [Dexterity](/page/Dexterity "Dexterity") bonus to determine bonus to attack with ranged missile weapons if it is higher. | \* **Prerequisite:** +1 [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus"), [Wisdom](/page/Wisdom "Wisdom") 13+ | + +### SubFeats + +The subfeats listed below are included in the table above, but listed here for reference + +| Feat | Active | Description | | +| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | --- | +| [Proficiency: Bastard Sword](https://ddowiki.com/page/Proficiency:\_Bastard_Sword "Proficiency: Bastard Sword") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using an [Bastard Sword](/page/Bastard_Sword "Bastard Sword") untrained. In addition it allows [Bastard Swords](/page/Bastard_Sword "Bastard Sword") to deal [glancing blows](/page/Glancing_blows "Glancing blows") as if they were a two handed weapon - if they are the only weapon wielded by a proficient user. EG: Sword and shield or single weapon attack styles only, will not work if you are dual-wielding. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, [Strength](/page/Strength "Strength") 13+ | +| [Proficiency: Dwarven Waraxe](https://ddowiki.com/page/Proficiency:\_Dwarven_Waraxe "Proficiency: Dwarven Waraxe") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using an [Dwarven Waraxe](/page/Dwarven_Waraxe "Dwarven Waraxe") untrained. In addition it allows [Dwarven Waraxes](/page/Dwarven_Waraxe "Dwarven Waraxe") to deal [glancing blows](/page/Glancing_blows "Glancing blows") as if they were a two handed weapon - if they are the only weapon wielded by a proficient user. EG: Sword and shield or single weapon attack styles only, will not work if you are dual-wielding. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher, [Strength](/page/Strength "Strength") 13+ | +| [Proficiency: Great Crossbow](https://ddowiki.com/page/Proficiency:\_Great_Crossbow "Proficiency: Great Crossbow") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using a [Great Crossbow](/page/Great_Crossbow "Great Crossbow") untrained. In addition it allows [Great Crossbows](/page/Great_Crossbow "Great Crossbow") to knock opponents to the ground on a confirmed attack roll of a natural 20 (regardless of if it delt critical damage or not). The [knockdown](/page/Knockdown "Knockdown") lasts for 6 seconds and offers no recurring save to get up. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Proficiency: Handwraps](https://ddowiki.com/page/Proficiency:\_Handwraps "Proficiency: Handwraps") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using [Handwraps](/page/Handwraps "Handwraps") untrained. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Proficiency: Kama](https://ddowiki.com/page/Proficiency:\_Kama "Proficiency: Kama") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using a [Kama](/page/Kama "Kama") untrained. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Proficiency: Khopesh](https://ddowiki.com/page/Proficiency:\_Khopesh "Proficiency: Khopesh") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using a [Khopesh](/page/Khopesh "Khopesh") untrained. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Proficiency: Repeating Heavy Crossbow](https://ddowiki.com/page/Proficiency:\_Repeating_Heavy_Crossbow "Proficiency: Repeating Heavy Crossbow") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using a [Repeating Heavy Crossbow](/page/Repeating_Heavy_Crossbow "Repeating Heavy Crossbow") untrained. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Proficiency: Repeating Light Crossbow](https://ddowiki.com/page/Proficiency:\_Repeating_Light_Crossbow "Proficiency: Repeating Light Crossbow") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using a [Repeating Light Crossbow](/page/Repeating_Light_Crossbow "Repeating Light Crossbow") untrained. In addition it allows [Repeating Light Crossbows](/page/Repeating_Light_Crossbow "Repeating Light Crossbow") to fire off a volley of 3 bolts per shot. Un-proficient users may only fire 1 bolt per shot. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Proficiency: Shuriken](https://ddowiki.com/page/Proficiency:\_Shuriken "Proficiency: Shuriken") | Passive | This [feat](/page/Feat "Feat") negates the -4 penalty to [attack rolls](/page/Attack_roll "Attack roll") from using a [Shuriken](/page/Shuriken "Shuriken") untrained. | \* **Prerequisite:** [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Weapon Focus: Bludgeoning](https://ddowiki.com/page/Weapon_Focus:\_Bludgeoning "Weapon Focus: Bludgeoning") | Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** Base attack bonus of +1 or higher | | +| [Weapon Focus: Piercing](https://ddowiki.com/page/Weapon_Focus:\_Piercing "Weapon Focus: Piercing") | Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** Base attack bonus of +1 or higher | +| [Weapon Focus: Ranged](https://ddowiki.com/page/Weapon_Focus:\_Ranged "Weapon Focus: Ranged") | Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Ranged Power](/page/Ranged_Power "Ranged Power"). | \* **Prerequisite:** Base attack bonus of +1 or higher | +| [Weapon Focus: Slashing](https://ddowiki.com/page/Weapon_Focus:\_Slashing "Weapon Focus: Slashing") | Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** Base attack bonus of +1 or higher | +| [Weapon Focus: Thrown](https://ddowiki.com/page/Weapon_Focus:\_Thrown "Weapon Focus: Thrown") | Passive | This feat grants a +1 bonus on to-hit rolls with any of the listed weapons. It also grants +2 [Ranged Power](/page/Ranged_Power "Ranged Power"). | \* **Prerequisite:** Base attack bonus of +1 or higher | + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[fighterBonusFeats]: - "c:verify-rows=#feat:bonusFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[heavy_armor]: http://ddowiki.com/page/Heavy_Armor_Proficiency "Heavy Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[martial_weapon]: http://ddowiki.com/page/Category:Martial_weapons "Martial Weapons" +[simple_weapon]: http://ddowiki.com/page/Category:Simple_weapons + +1: +This [feat](https://ddowiki.com/page/Feat "Feat") negates the -4 penalty +to [attack rolls](https://ddowiki.com/page/Attack_roll "Attack roll") from using +an [exotic weapon](https://ddowiki.com/page/Exotic_weapon "Exotic weapon") untrained. This feat only grants proficiency +with a single weapon of your choice, so must be taken multiple times to gain proficiency in multiple exotic weapons. +Most exotic weapons also have further special features unlocked by having the correct proficiency feat, see each +individual sub feat for full details. + +Sub-feat selection: + +- [Proficiency: Bastard Sword](https://ddowiki.com/page/Proficiency:_Bastard_Sword "Proficiency: Bastard Sword") +- [Proficiency: Dwarven Waraxe](https://ddowiki.com/page/Proficiency:_Dwarven_Waraxe "Proficiency: Dwarven Waraxe") ( + Free for [Dwarves](https://ddowiki.com/page/Dwarves "Dwarves") that are proficient with ** + all** [Martial weapons](https://ddowiki.com/page/Martial_weapons "Martial weapons")) +- [Proficiency: Great Crossbow](https://ddowiki.com/page/Proficiency:_Great_Crossbow "Proficiency: Great Crossbow") ( + Free for [Artificers](https://ddowiki.com/page/Artificer "Artificer") + and [Rogue Mechanic: Arbalester](https://ddowiki.com/page/Mechanic_enhancements "Mechanic enhancements")) +- [Proficiency: Handwraps](https://ddowiki.com/page/Proficiency:_Handwraps "Proficiency: Handwraps") (free + for [Monks](https://ddowiki.com/page/Monk "Monk")) +- [Proficiency: Kama](https://ddowiki.com/page/Proficiency:_Kama "Proficiency: Kama") (free + for [Monks](https://ddowiki.com/page/Monk "Monk")) +- [Proficiency: Khopesh](https://ddowiki.com/page/Proficiency:_Khopesh "Proficiency: Khopesh") +- [Proficiency: Repeating Heavy Crossbow](https://ddowiki.com/page/Proficiency:_Repeating_Heavy_Crossbow "Proficiency: Repeating Heavy Crossbow") ( + free for [Artificers](https://ddowiki.com/page/Artificer "Artificer") + and [Rogue Mechanic: Improved Detection](https://ddowiki.com/page/Mechanic_enhancements "Mechanic enhancements")) +- [Proficiency: Repeating Light Crossbow](https://ddowiki.com/page/Proficiency:_Repeating_Light_Crossbow "Proficiency: Repeating Light Crossbow") ( + free for [Artificers](https://ddowiki.com/page/Artificer "Artificer") + and [Rogue Mechanic: Targeting Sights](https://ddowiki.com/page/Mechanic_enhancements "Mechanic enhancements")) +- [Proficiency: Shuriken](https://ddowiki.com/page/Proficiency:_Shuriken "Proficiency: Shuriken") (free + for [Monks](https://ddowiki.com/page/Monk "Monk") and [Drow](https://ddowiki.com/page/Drow "Drow")) + _1_ Footnote content here. [↩](#a1) + +Improved Critical: + +- +3 for falchion, great crossbow, kukri, rapier, and scimitar. +- +2 for bastard sword, dagger, greatsword, heavy crossbow, khopesh, light crossbow, long sword, repeating heavy + crossbow, repeating light crossbow, short sword, and throwing dagger. +- +1 to all other weapons. + +Improved Critical does not [stack](/page/Stack "Stack") with the [Keen](/page/Keen "Keen") +or [Impact](/page/Impact "Impact") weapon enchantments. + +- Multiple versions of this feat exist, one for + each [weapon type](/page/Weapon_type "Weapon type") ([Bludgeoning](/page/Category:Bludgeoning_weapons "Category:Bludgeoning weapons") + , [Piercing](/page/Category:Piercing_weapons "Category:Piercing weapons") + , [Ranged](/page/Category:Ranged_weapons "Category:Ranged weapons") + , [Slashing](/page/Category:Slashing_weapons "Category:Slashing weapons") + or [Thrown](/page/Category:Thrown_weapons "Category:Thrown weapons")). This feat can be taken multiple times, though + each time must be for a different type. + +- Shields do not benefit from Improved Critical. + +- An [Artificer](/page/Artificer "Artificer") may select this feat as one of + his [artificer bonus feats](/page/Category:Artificer_bonus_feats "Category:Artificer bonus feats"). +- A [Fighter](/page/Fighter "Fighter") may select this feat as one of + his [fighter bonus feats](/page/Category:Fighter_bonus_feats "Category:Fighter bonus feats"). + +For artificers taking it as a bonus feat, it is restricted to bludgeoning, ranged, and slashing. + +Knight's Training + +- [Long Sword](/page/Long_Sword "Long Sword") critical multiplier is increased by 1. +- [Battle Axe](/page/Battle_Axe "Battle Axe")'s critical threat range is increased by 1\. The bonus is doubled + by [Improved Critical](/page/Improved_Critical "Improved Critical"): Slashing (crit profile 17-20/x3, same as long + sword). +- [Heavy Maces](/page/Heavy_Mace "Heavy Mace"), [Morningstars](/page/Morningstar "Morningstar") + & [War Hammers](/page/War_Hammer "War Hammer") critical threat range is increased by 1. The bonus is unaffected by + Improved Critical: Bludgeoning (final crit profile 18-20/x3). diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.md new file mode 100644 index 00000000..91f4383b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.md @@ -0,0 +1,257 @@ +# Monk Class Feats + +[Monk Class](http://ddowiki.com/page/Monk) + +## [Granted Feats](- "granted") + +## Level 1 + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Armor Class Bonus](http://ddowiki.com/page/AC_Bonus) | Passive | While unarmored and not equipping a shield, monks gain a passive bonus to Armor Class equal to their Wisdom modifier, if their Wisdom modifier is positive. ( Receives +3 additional bonus to Armor Class at levels 2, 5, 10, 15 and 20.) | None | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | None | +| [Finishing Moves](http://ddowiki.com/page/Finishing_moves) | Active | As your martial arts training continues, you will be able perform special finishing moves of great versatility and power. These finishing moves are unlocked by performing certain sequences of attack forms, and the finishing move icon will change (and a visible glow of Ki will appear about you) when you are ready to perform one. | None | +| [Flurry of Blows](http://ddowiki.com/page/Flurry_of_Blows) | Passive | When a monk is either unarmed or is wielding only monk weapons (Kama, Shuriken, Quarterstaff), the monk is treated as if they had a full Base Attack Bonus for all monk levels they possess rather than a 3/4 Base Attack Bonus. | None | +| [Unarmed Strike](http://ddowiki.com/page/Unarmed_Strike) | Passive | Monks are tremendously skilled at unarmed combat and inflict more damage with their bare hands. As they increase in levels, so will the damage they will inflict with their unarmed attacks at level 4, 8, 12, 16 and 20. | None | + +Martial Arts Bonus Feat + +## Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Evasion](http://ddowiki.com/page/Evasion) | Passive | When a monk makes a successful Reflex save to avoid damage, he or she suffers no damage instead of half damage. Evasion requires light or no armor. | | +| [Meditation](http://ddowiki.com/page/Meditation) | Active | A two times per rest, a monk can meditate to slowly regain Ki. It stabilizes when it reaches over three times his Concentration score. | | + +Choice of a Martial arts feat: At second level, a monk may select martial arts feat for free. He must meet all +prerequisites of the feat he selects. + +## Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| [Fast Movement (Monk Class Feat)][fast_movement_feat] | Passive | While centered (unarmored, unencumbered, and wielding monk weapons), a monk runs faster for every three monk levels he possesses. | | +| [Path of Harmonious Balance][path_of_harmonious_balance] | Passive | Unlocks the Light Path and related feats and enhancements. | Blocks the Path of Dominion | +| [Path of Inevitable Dominion][path_of_inevitable_dominion] | Passive | Unlocks the Dark Path and related feats and enhancements. | Blocks the Path of Harmony | +| [Still Mind](http://ddowiki.com/page/Still_Mind) | Passive | Training and meditation have improved the monk's resistance to mind-affecting attacks, granting you a +2 bonus on saving throws against enchantments. | | + +[fast_movement_feat]: http://ddowiki.com/page/Fast_Movement_(monk_class_feat) "Fast Movement (monk class feat)" +[path_of_harmonious_balance]: http://ddowiki.com/page/Path_of_Harmonious_Balance "Philosophy: Path of Harmonious Balance" +[path_of_inevitable_dominion]: http://ddowiki.com/page/Path_of_Inevitable_Dominion "Philosophy: Path of Inevitable Dominion" + +## Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Ki Strike: Magic][ki_strike_magic] | Passive | All of a monk's unarmed melee attacks are empowered with Ki and are considered magical for damage reduction purposes. | | +| [Slow Fall](http://ddowiki.com/page/Slow_Fall) | Active | A monk's focus allows him to bend nature around him to reduce gravity's effect. This is an active feat, and can be turned off should you desire normal gravity to affect you. The Monk must be centered to use this ability, and its effectiveness increases as you continue to gain power, at every two level. | | +| [Unarmed Strike](http://ddowiki.com/page/Unarmed_Strike) | Passive | While centered (unarmored, unencumbered, and wielding monk weapons), your fists and feet are lethal weapons. | | + +## Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Purity of Body](http://ddowiki.com/page/Purity_of_Body) | Passive | At this level, a monk has gained control over his body’s immune system and is now unaffected by all natural diseases. | | + +## Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------- | ------------ | +| [Adept of Forms](http://ddowiki.com/page/Adept_of_Forms) | Passive / Active | You continue on the path to enlightenment, improving your elemental stances and learning new elemental strikes. | | + +Slow Fall (active): Your focus allows you to bend nature around you to make gravity have less effect. This is an active +feat, and can be turned off should you desire normal gravity to affect you. Choice of a Martial arts feat: At sixth +level, a monk may select martial arts feat for free. He must meet all prerequisites of the feat he selects. Fast +Movement (passive): While centered (unarmored, unencumbered, and wielding monk weapons), a monk runs faster for every +three monk levels he possesses. + +## Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Wholeness of Body](http://ddowiki.com/page/Wholeness_of_Body) | Active | This feat allows monks expend 10 Ki to heal half their hit points over time. The formula for how many hit points is regained is (Monk level)/2 + Wisdom modifier every 2 seconds for 30 seconds. This feat cannot be used in combat, the monk must stand still and perform no action while he regenarates some of his hit points. There is a cool-down of 180 seconds. (Healing Amplification items and Improved Recovery enhancements may result in a full regeneration of HP.) | | + +## Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------ | ------------ | +| Unarmed Strike | Passive | While centered (unarmored, unencumbered, and wielding monk weapons), your fists and feet are lethal weapons. | + +## Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------- | ------------ | +| [Improved Evasion](http://ddowiki.com/page/Improved_Evasion) | Passive | When a monk fails to make a successful Reflex save to avoid damage, he or she suffers only half damage. | | + +Fast Movement (passive): While centered (unarmored, unencumbered, and wielding monk weapons), a monk runs faster for +every three monk levels he possesses. + +## Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- | ------------ | +| [Ki Strike: Lawful][ki_strike_lawful] | Passive | Unarmed attacks from the monk are now considered Lawful and Magic weapons for damage reduction purposes. | | + +Armor Class Bonus (passive): Your training improves your armor class, You gain +3 additional bonus to Armor Class. Slow +Fall (active): Your focus allows you to bend nature around you to make gravity have less effect. This is an active feat, +and can be turned off should you desire normal gravity to affect you. + +## Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------------------------- | ------- | --------------------------------------------- | ------------ | +| [Diamond Body](http://ddowiki.com/page/Diamond_Body) | Passive | This feat grants the Monk immunity to poison. | | + +## Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ | +| [Abundant Step](http://ddowiki.com/page/Abundant_Step) | Active) | At the cost of 10 Ki, a monk can use this ability to make horizontal leaps, closing to targets, traversing chasms, or zipping past enemies with less chance of being detected. There is a cooldown of three seconds on this feat and can only be used on yourself. | | +| [Master of Forms](http://ddowiki.com/page/Master_of_Forms) | Passive / Active | : You continue on the path to enlightenment, further improving your elemental stances and learning new elemental strikes. These stance improvements replace those granted by Adept of Forms. | | +| [Unarmed Strike](http://ddowiki.com/page/Unarmed_Strike) | Passive | Monks are tremendously skilled at unarmed combat and inflict more damage with their bare hands. As they increase in levels, so will the damage they will inflict with their unarmed attacks at level 4, 8, 12, 16 and 20. | | + +Fast Movement (passive): While centered (unarmored, unencumbered, and wielding monk weapons), a monk runs faster for +every three monk levels he possesses. Slow Fall (active): Your focus allows you to bend nature around you to make +gravity have less effect. This is an active feat, and can be turned off should you desire normal gravity to affect you. +Unarmed Strike (passive): While centered (unarmored, unencumbered, and wielding monk weapons), your fists and feet are +lethal weapons. + +## Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------------------------- | ------- | ------------------------------------------------------- | ------------ | +| [Diamond Soul](http://ddowiki.com/page/Diamond_Soul) | Passive | The Monk gains Spell Resistance equal to Monk Level +10 | | + +## Level 14 + +Slow Fall (active): Your focus allows you to bend nature around you to make gravity have less effect. This is an active +feat, and can be turned off should you desire normal gravity to affect you. + +## Level 15: + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Quivering Palm](http://ddowiki.com/page/Quivering_Palm) | Active | Starting at 15th level, a monk can set up fatal vibrations within the body of a living creature. Constructs, oozes, plants, undeads, incorporeal creatures such as wraiths, and creatures immune to critical hits cannot be affected, but other creatures must make a Fortitude Save after being struck by the Quivering Palm or die instantly. The saving throw is equal to DC of 10 + (monk level)/2 + wisdom modifier. | | + +Armor Class Bonus (passive): Your training improves your armor class, You gain +3 additional bonus to Armor Class. Fast +Movement (passive): While centered (unarmored, unencumbered, and wielding monk weapons), a monk runs faster for every +three monk levels he possesses. + +## Level 16: + +| [ ][featLevel16] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Ki Strike: Adamantine][ki_strike_adamantine] | Passive | Unarmed attacks from the monk are now considered Adamantine, Lawful, and Magic weapons for damage reduction purposes. | | +| [Unarmed Strike](http://ddowiki.com/page/Unarmed_Strike) | Passive | Monks are tremendously skilled at unarmed combat and inflict more damage with their bare hands. As they increase in levels, so will the damage they will inflict with their unarmed attacks at level 4, 8, 12, 16 and 20. | | + +Slow Fall (active): Your focus allows you to bend nature around you to make gravity have less effect. This is an active +feat, and can be turned off should you desire normal gravity to affect you. + +## Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Timeless Body](http://ddowiki.com/page/Timeless_Body) | Passive | Your soul is balanced. No corrupt influences can possess your body after death - you are immune to the spawn effect of most undead. | | + +## Level 18: + +| [ ][featLevel18] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Grandmaster of Forms](http://ddowiki.com/page/Grandmaster_of_Forms) | Passive / Active | You continue on the path to enlightenment, further improving your elemental stances and learning new elemental strikes. These stance improvements replace those granted by Master of Forms. | | + +Fast Movement (passive): While centered (unarmored, unencumbered, and wielding monk weapons), a monk runs faster for +every three monk levels he possesses. Slow Fall (active): Your focus allows you to bend nature around you to make +gravity have less effect. This is an active feat, and can be turned off should you desire normal gravity to affect you. + +## Level 19: + +| [ ][featLevel19] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Empty Body](http://ddowiki.com/page/Empty_Body) | Active | You are able to focus your ki and walk the edge of the Plane of Shadow, mimicing the effects of a Shadow Walk spell. While this effect is active, you move much faster than normal and your outline appears faint and you are harder to hit. Attacking another creature or otherwise interacting with objects shunts you back to the Material Plane. | | + +## Level 20: + +| [ ][featLevel20] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Perfect Self](http://ddowiki.com/page/Perfect_Self) | Passive | You have transcended your former race, and are now considered a Lawful Outsider. You have gained damage reduction 10 / epic. Warforged retain most living construct traits. | | +| [Perfect Slow Fall](http://ddowiki.com/page/Perfect_Slow_Fall) | Active | You have perfected the ability to recover from a fall unharmed. You never take damage from falling no matter how far you fall. | | +| [Shining Star](http://ddowiki.com/page/Shining_Star) | Active | You use the combined power of Earth, Wind, and Fire to set up harmonic vibrations within your enemy that force them to dance. A successful Will save negates this effect. (DC 10 + Monk Level + Charisma mod) | | +| [Unarmed Strike](http://ddowiki.com/page/Unarmed_Strike) | Passive | Monks are tremendously skilled at unarmed combat and inflict more damage with their bare hands. As they increase in levels, so will the damage they will inflict with their unarmed attacks at level 4, 8, 12, 16 and 20. | | + +Armor Class Bonus (passive): Your training improves your armor class, You gain +3 additional bonus to Armor Class. +Unarmed Strike (passive): While centered (unarmored, unencumbered, and wielding monk weapons), your fists and feet are +lethal weapons. + +## Martial Arts Feats: + +- **Martial arts feats** + At level 1, 2, and 6 a [monk](/page/Monk "Monk") gets to select a bonus **martial arts feat**. All prerequisites of + the selected feat must be met. + +| [ ][martialArtsFeats] [Feats][result] | Type | Description | Prerequisite | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Combat Expertise](/page/Combat_Expertise "Combat Expertise") | Active | Defensive Combat Stance: While using Combat Expertise mode, you suffer -5 to your attack rolls but gain +10% feat bonus to Armor Class. Spells have three times their normal cooldown when this mode is active. Combat Expertise dispels and wards against all Rage effects. | [Intelligence](/page/Intelligence "Intelligence") 13 | +| [Deflect Arrows](https://ddowiki.com/page/Deflect_Arrows "Deflect Arrows") | Passive | You knock aside one incoming projectile that would have struck you every 6 seconds. | \* **Prerequisite:** [Monk](/page/Monk "Monk"), [Dexterity](/page/Dexterity "Dexterity") 13 | +| [Diehard](https://ddowiki.com/page/Diehard "Diehard") | Passive | You automatically [stabilize](/page/Stable "Stable") when you become [unconscious](/page/Unconscious "Unconscious") from damage. | | +| [Discipline](https://ddowiki.com/page/Discipline "Discipline") | Passive | This [feat](/page/Feat "Feat") grants +2 bonus to [Concentration](/page/Concentration "Concentration") [skill checks](/page/Skill_check "Skill check"), and +1 to [Will saves](/page/Will_save "Will save"). | | +| [Dodge](https://ddowiki.com/page/Dodge "Dodge") | Passive | This [feat](https://ddowiki.com/page/Feat "Feat") grants a 3% [Dodge bonus](https://ddowiki.com/page/Dodge_bonus "Dodge bonus"). | \* **Prerequisite:** [Dexterity](https://ddowiki.com/page/Dexterity "Dexterity") 13+ | +| [Great Fortitude](https://ddowiki.com/page/Great_Fortitude "Great Fortitude") | Passive | This feat grants a +2 bonus to all Fortitude saving throws. | | +| [Improved Sunder](https://ddowiki.com/page/Improved_Sunder "Improved Sunder") | Active | Using this [melee special attack](/page/Melee_special_attack "Melee special attack"), you may reduce the target's [Armor Class](/page/Armor_Class "Armor Class") by 5 and fortification by 10% on a failed saving throw for 24 seconds. Some creatures may be immune to the sunder effect. A successful [Fortitude save](/page/Fortitude_save "Fortitude save") negates this effect. Additionally, Improved Sunder will apply a -3 [Fortitude](/page/Fortitude "Fortitude") Saving Throw penalty that lasts for 24 seconds on a successful hit (regardless of if they save). The saving throw penalty stacks up to five times (Maximum of -15 to [Fortitude](/page/Fortitude "Fortitude") save). [DC](/page/DC "DC") 14 + [Str](/page/Str "Str") mod. | \* **Prerequisite:** [Sunder](/page/Sunder "Sunder"), [Power Attack](/page/Power_Attack "Power Attack") | +| [Improved Trip](https://ddowiki.com/page/Improved_Trip "Improved Trip") | Active | Improved Trip has a chance to trip the target, rendering it prone. Improved trip has a superior base DC (+4) and lasts for a longer maximum period of time than [Trip](/page/Trip "Trip") (60 seconds instead of 30). This feat replaces [Trip](/page/Trip "Trip") as an action. | \* **Prerequisite:** [Combat Expertise](/page/Combat_Expertise "Combat Expertise") | +| [Improved Two Handed Fighting](https://ddowiki.com/page/Improved_Two_Handed_Fighting "Improved Two Handed Fighting") | Passive | Increases the damage of [glancing blow](/page/Glancing_blow "Glancing blow") attacks when wielding a two-handed weapon by an additional 10%, for a total of 40%. Also increases the chance for weapon effects to trigger on glancing blows by an additional 3% for a total of 6%. Your [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power") is increased by +2 to a total of +4. | \* **Prerequisite:** 17 [Strength](/page/Strength "Strength"), [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +6, [Two Handed Fighting](/page/Two_Handed_Fighting "Two Handed Fighting") | +| [Iron Will](https://ddowiki.com/page/Iron_Will "Iron Will") | Passive | This feat grants a +2 bonus to Will saves. | | +| [Lightning Reflexes](https://ddowiki.com/page/Lightning_Reflexes "Lightning Reflexes") | Passive | This [feat](/page/Feat "Feat") grants a +2 bonus to all [Reflex saving throws](/page/Reflex_saving_throw "Reflex saving throw"). | | +| [Mobility](https://ddowiki.com/page/Mobility "Mobility") | Passive | Mobility increases the maximum dexterity bonus permitted by armor and tower shields by 2, and adds a +4 bonus to [Armor Class](/page/Armor_Class "Armor Class") while [tumbling](/page/Tumbling "Tumbling"). You will also gain a 2% [dodge bonus](/page/Dodge_bonus "Dodge bonus"). | \* **Prerequisite:** [Dodge](/page/Dodge "Dodge") | +| [Power Attack](https://ddowiki.com/page/Power_Attack "Power Attack") | Active Toggled Stance | This [feat](/page/Feat "Feat") exchanges part of your attack bonus for extra melee damage. It reduces your hit bonus by 5, or your [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus"), whichever is lower. Then your successful attacks will have their damage increased by the same amount. [Two-handed weapons](/page/Two-handed_weapons "Two-handed weapons") get twice that damage bonus. (Unarmed strikes count as one-handed.) Typically, this means [one-handed weapons](/page/One-handed_weapons "One-handed weapons") get +5 and two-handed get +10 to damage. | \* **Prerequisite:** [Strength](/page/Strength "Strength") Base 13+ | +| [Precision](https://ddowiki.com/page/Precision "Precision") | Active Toggled Stance | Offensive Combat Stance: While using Precision mode, you gain +5% to hit and reduce the target's fortification against your attacks by 25%. Cannot be used while raged. | \* **Prerequisite:** +1 [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus"), [DEX](/page/DEX "DEX") 13 | +| [Resilience](https://ddowiki.com/page/Resilience "Resilience") | Active Toggled Stance | Defensive Combat Stance: While using Resilience mode, you gain a +4 bonus to all [saves](/page/Save "Save"). [Spells](/page/Spell "Spell") have three times their normal [cooldown](/page/Cooldown "Cooldown") when this mode is active. Cannot be used while Barbarian [raged]( "Rage (feat)"). The [Rage (spell)]( "Rage (spell)") and Resilience coexist without any issues. | \* **Prerequisite:** [Constitution](/page/Constitution "Constitution") 13+, [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus") of +1 or higher | +| [Shuriken Expertise](https://ddowiki.com/page/Shuriken_Expertise "Shuriken Expertise")![Shuriken Expertise.PNG](/images/thumb/Shuriken_Expertise.PNG/36px-Shuriken_Expertise.PNG) | Passive | You are skilled with the use of the [shuriken](/page/Shuriken "Shuriken"), and have a chance to throw an additional one per throw. (Percent chance to throw an additional shuriken is equal to your [Dexterity](/page/Dexterity "Dexterity").) This is also a racial feat given to all [Drow Elves](/page/Drow "Drow") at level 1, regardless of class. | \* **Prerequisite:** either [Proficiency: Shuriken](/page/Exotic_Weapon_Proficiency "Exotic Weapon Proficiency") or [Half-Elf Dilettante: Monk](/page/Half-Elf_Dilettante:_Monk "Half-Elf Dilettante: Monk") and [Dexterity](/page/Dexterity "Dexterity") 13+, or [Drow](/page/Drow "Drow") | +| [Single Weapon Fighting](/page/Single_Weapon_Fighting "Single Weapon Fighting") | Passive | While Single Weapon Fighting, you gain +10% [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [attack speed](/page/Attack_speed "Attack speed") and +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). Requires fighting with a single one-handed weapon, and wielding only an [orb](/page/Orb "Orb"), [runearm](/page/Runearm "Runearm"), or nothing in your offhand. | \* **Prerequisite:** 2 ranks of [Balance](/page/Balance "Balance") | +| [Spring Attack](https://ddowiki.com/page/Spring_Attack "Spring Attack") | Passive | Character suffers no penalty to his attack roll when meleeing and moving. You will also gain a 2% [dodge bonus](/page/Dodge_bonus "Dodge bonus"). | \* [Mobility](/page/Mobility "Mobility"), [base attack bonus](/page/Base_attack_bonus "Base attack bonus") of 4 or higher, [Dodge](/page/Dodge "Dodge"), [Dexterity](/page/Dexterity "Dexterity") 13+ | +| [Stunning Fist](/page/Stunning_Fist "Stunning Fist") | Active | A swift unarmed attack to vulnerable areas that cause your target to be [stunned](/page/Stunned "Stunned") for 6 seconds if it fails a ([DC](/page/DC "DC") = 10 + half character levels + [Wis](/page/Wis "Wis") mod + other modifiers) [Fortitude save](/page/Fortitude_save "Fortitude save"). | \* **Prerequisite:** [Flurry of Blows](/page/Flurry_of_Blows "Flurry of Blows") | +| [Swords to Plowshares](/page/Swords_to_Plowshares "Swords to Plowshares") | Passive | The feat grants [Quarterstaves](/page/Quarterstaff "Quarterstaff"), [Kamas](/page/Kama "Kama"), and [Sickles](/page/Sickle "Sickle") a +1 [Morale bonus](/page/Morale_bonus "Morale bonus") to their [Critical threat](/page/Critical_threat "Critical threat") tange. | \* **Prerequisite:** +4 BAB | +| [Ten Thousand Stars](/page/Ten_Thousand_Stars "Ten Thousand Stars") | Active | Activate this ability to enter a trance for 30 seconds (or until you become uncentered). Add your [Wisdom](/page/Wisdom "Wisdom") ability score to your [Ranged Power](/page/Ranged_Power "Ranged Power") and add your monk level \* 5 to your [Doubleshot](/page/Doubleshot "Doubleshot"). | \* **Prerequisite:** [Monk](/page/Monk "Monk") 6, [Dexterity](/page/Dexterity "Dexterity") 13 | +| [Toughness](/page/Toughness "Toughness") | Passive | Increases your [hit points](/page/Hit_point "Hit point") by +3 at first level, and 1 additional hit point for each additional [level](/page/Level "Level"). | | +| [Two Handed Fighting](https://ddowiki.com/page/Two_Handed_Fighting "Two Handed Fighting") | Passive | Increases the damage of [glancing blow](/page/Glancing_blow "Glancing blow") attacks when wielding a two-handed weapon by 10% (from a base of 20% normal weapon damage.) This feat also grants a 3% chance for weapon effects to trigger on glancing blows. While fighting with a two-handed weapon you gain a +2 [Combat Style bonus](/page/Combat_Style_bonus "Combat Style bonus") to [Melee Power](/page/Melee_Power "Melee Power"). | \* **Prerequisite:** 15 [Strength](/page/Strength "Strength") | +| [Two Weapon Fighting](https://ddowiki.com/page/Two_Weapon_Fighting "Two Weapon Fighting") | Passive | Two Weapon Fighting reduces the to-hit penalty when using two weapons at the same time. | **Prerequisite:** [Dexterity](/page/Dexterity "Dexterity") 15 | +| [Weapon Finesse](https://ddowiki.com/page/Weapon_Finesse "Weapon Finesse") | Passive | Weapon finesse allows the character to use his [dexterity](/page/Dexterity "Dexterity") [modifier](/page/Modifier "Modifier") instead of the [strength](/page/Strength "Strength") [modifier](/page/Modifier "Modifier") when making melee attack rolls with [light weapons,](/page/Light_weapons "Light weapons") [rapiers](/page/Rapier "Rapier"), and [unarmed](/page/Unarmed "Unarmed") strikes. The highest of the [strength](/page/Strength "Strength") and [dexterity](/page/Dexterity "Dexterity") modifiers will be used for attack rolls with qualifying weapons. The [strength](/page/Strength "Strength") [modifier](/page/Modifier "Modifier") is still used as a bonus to the damage roll, however. | \* **Prerequisite:** [Base attack bonus](/page/Base_attack_bonus "Base attack bonus") of +1, [Dexterity](/page/Dexterity "Dexterity") 13+ | +| [Whirling Steel Strike](https://ddowiki.com/page/Whirling_Steel_Strike "Whirling Steel Strike") | Passive | You treat [longswords](/page/Longsword "Longsword") as if they were [monk weapons](/page/Monk_weapons "Monk weapons"), remaining [centered](/page/Centered "Centered") when you wield them. | [Weapon Focus](/page/Weapon_Focus "Weapon Focus"): Slashing [Monk](/page/Monk "Monk") Level 1 one of following; Proficiency: Longswords, [Favored by the Sovereign Host](/page/Favored_by_the_Sovereign_Host "Favored by the Sovereign Host"), or [Half-Elf](/page/Half-Elf "Half-Elf") race with [Fighter dilettante](/page/Half-Elf_Dilettante:_Fighter "Half-Elf Dilettante: Fighter"). | +| [Zen Archery](https://ddowiki.com/page/Zen_Archery "Zen Archery") | Passive | You can use your [Wisdom](/page/Wisdom "Wisdom") bonus instead of [Dexterity](/page/Dexterity "Dexterity") bonus to determine bonus to attack with ranged missile weapons if it is higher. | \* **Prerequisite:** +1 [Base Attack Bonus](/page/Base_Attack_Bonus "Base Attack Bonus"), [Wisdom](/page/Wisdom "Wisdom") 13+ | + +## Errata + +- Armor Class Bonus is listed on DDO Wiki several times, but it is only listed here once, as the feat is not stackable + unlike Toughness or Religious Lore. However, the bonus it provides increases at certain monk level breaks (2,5,10,15 + etc) + +[ki_strike_magic]: http://ddowiki.com/page/Ki_Strike:_Magic "Ki Strike: Magic" +[ki_strike_lawful]: http://ddowiki.com/page/Ki_Strike:_Lawful "Ki Strike: Lawful" +[ki_strike_adamantine]: http://ddowiki.com/page/Ki_Strike:_Adamantine "Ki Strike: Adamantine" +[featExample]: - "c:verify-rows=#feat:simple()" +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[martialArtsFeats]: - "c:verify-rows=#feat:allBonusFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.md new file mode 100644 index 00000000..b50b60f3 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.md @@ -0,0 +1,240 @@ +# Paladin Class Feats + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | +| ------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Aura of Good](http://ddowiki.com/page/Aura_of_Good) | Passive | Grants +1 bonus to AC and +1 bonus to saving throws to all characters within range. | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | +| [Heavy Armor Proficiency][heavy_armor] | Passive | Benefit: You are proficient with heavy armor, and do not suffer the armor check penalty to attack rolls when wearing heavy armor. You also gain 6 + your base attack bonus in physical resistance when wearing heavy armor. | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | +| [Martial Weapon Proficiency: Light Hammer](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Light Hammer and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Longbow](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Longbow and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Longsword](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Longsword and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Rapier](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Rapier and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Shortbow](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Shortbow and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Shortsword](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Shortsword and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Throwing Hammer](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Throwing Hammer and do not suffer an attack penalty to use them. | +| [Martial Weapon Proficiency: Warhammer](http://ddowiki.com/page/Martial_Weapon_Proficiency) | Passive | You are proficient with Warhammer and do not suffer an attack penalty to use them. | +| [Medium Armor Proficiency][medium_armor] | Passive | You are proficient with medium armor, and do not suffer the armor check penalty to attack rolls when wearing medium armor. You also gain 4 + 2/3 of your base attack bonus in physical resistance when wearing medium armor. Notes: A piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. Gaining Medium Armor Proficiency through Wizard Eldritch Knight, Sorcerer Eldritch Knight or bard Warchanter enhancements, medium armor will give less PRR than stated, even less than light armor. (DDO Forums) | +| [Religious Lore][religious_lore] | Passive | This feat grants represents your knowledge of the Religion. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | +| [Simple Weapon Proficiency: Club][simple_weapon] | Passive | You are proficient with Clubs and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Dagger][simple_weapon] | Passive | You are proficient with Daggers and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Dart][simple_weapon] | Passive | You are proficient with Darts and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Handwrap][simple_weapon] | Passive | You are proficient with Handwraps and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Heavy Crossbow][simple_weapon] | Passive | You are proficient with Heavy Crossbows and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Heavy Mace][simple_weapon] | Passive | You are proficient with Heavy Maces and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Light Crossbow][simple_weapon] | Passive | You are proficient with Light Crossbows and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Light Mace][simple_weapon] | Passive | You are proficient with Light Maces and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Morningstar][simple_weapon] | Passive | You are proficient with Morningstars and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Quarterstaff][simple_weapon] | Passive | You are proficient with Quarterstaffs and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Sickle][simple_weapon] | Passive | You are proficient with Sickles and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Simple Projectile][simple_weapon] | Passive | You are proficient with Simple Projectiles and do not suffer a -4 attack penalty for using this weapon | +| [Simple Weapon Proficiency: Throwing Dagger][simple_weapon] | Passive | You are proficient with Throwing Daggers and do not suffer a -4 attack penalty for using this weapon | +| [Smite Evil](http://ddowiki.com/page/Smite_Evil) | Passive | When activated, this feat triggers a special melee attack against Evil creatures. The Paladin adds his/her Charisma modifier x 2 (if any) to his/her attack roll and deals extra damage based on his/her paladin level. The extra damage done is 7+3\* | + +level. For instance, a 6th level paladin does 7+( +3\*6) (or 25) extra damage on a successful smite. If the paladin accidentally smites a creature that is not evil, or is not in range, the smite has no effect, but the ability is still used up. Paladins get one base use of this ability at level one, plus one more at level five and every five levels after 5th (at 10th, 15th and 20th, for a maximum of 5 uses). Smite Evil recharges at a rate of 1 every 90 seconds, and all uses return after any rest period. + +## Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ---------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Divine Grace](http://ddowiki.com/page/Divine_Grace) | Passive | Allows the paladin to add its charisma modifier to all saving throws. Divine Grace is capped at 2+(3\*paladin level). | +| [Lay on Hands](http://ddowiki.com/page/Lay_on_Hands) | Active | Heals a friendly target for ( 10 + Paladin level ) x Charisma modifier amount of hit points, or deals that much damage to an undead target. The amount healed does not suffer a penalty when used on Warforged. | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ---------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Aura of Courage](http://ddowiki.com/page/Aura_of_Courage) | Passive | Beginning at 3rd level, a paladin is immune to fear (magical or otherwise). Each ally within 10 feet of the paladin gains a +4 morale bonus on saving throws against fear effects. This ability functions while the paladin is conscious, but not if she is unconscious or dead. | +| [Divine Health](http://ddowiki.com/page/Divine_Health) | Passive | Makes the paladin immune to all diseases. | +| [Fear Immunity](http://ddowiki.com/page/Fear_Immunity) | Passive | A paladin is immune to fear effects. | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| --------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | +| [Turn Undead](https://ddowiki.com/page/Turn_Undead) | Active | Attempts to drive away nearby undead or force them to cower. | + +Gain the ability to cast Paladin spells. Your effective caster level is equal to your Paladin level, contrary to PnP ( +thus, the starting duration for a Bless spell is 4 minutes). Turn Undead (active and passive): This feat allows the +character to turn or at higher levels destroy undead creatures. The character can do this (3 + their charisma modifier) +times per day. While turning undead is an active skill, this feat is passive as it adds to the total amount of turns per +day. While enhancements from both Cleric and Paladin stack, as far as number and power of turns, the base number of +turns do not stack with each other. + +## Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Smite evil (active): Paladins can use this ability one additional time per rest period. You can now Smite evil 2 times +per rest. Smite evil also recharges at a rate of 1 every 90 seconds. + +## Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Remove Disease (active): At 6th level, a paladin can produce a remove disease effect, as the spell, once per rest +period. It can use this ability one additional time per rest period for every three levels after 6th (twice per rest at +9th level). + +## Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Remove Disease (active): Paladins can use this ability one additional time per rest period. You can now Remove Disease 2 +times per rest. + +## Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Smite evil (active): Paladins can use this ability one additional time per rest period. You can now Smite evil 3 times +per rest. Smite evil also recharges at a rate of 1 every 90 seconds. + +## Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Remove Disease (active): Paladins can use this ability one additional time per rest period. You can now Remove Disease 3 +times per rest. + +## Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------- | ------- | ------------------------------------------- | --------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. | This feat is received once for every Paladin level. | + +Remove Disease (active): Paladins can use this ability one additional time per rest period. You can now Remove Disease 4 +times per rest. Smite evil (active): Paladins can use this ability one additional time per rest period. You can now +Smite evil 4 times per rest. Smite evil also recharges at a rate of 1 every 90 seconds. + +## Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Bonus Feat: An artificer can select a feat from the Artificer Bonus Feat list. + +## Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Remove Disease (active): Paladins can use this ability one additional time per rest period. You can now Remove Disease 5 +times per rest. + +## Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Religious Lore][religious_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +Smite evil (active): Paladins can use this ability one additional time per rest period. You can now Smite evil 5 times +per rest. Smite evil also recharges at a rate of 1 every 90 seconds. + +## Errata + +- Need to add Simple and Martial weapons +- Deity based feats are covered under separate spec + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[heavy_armor]: http://ddowiki.com/page/Heavy_Armor_Proficiency "Heavy Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[religious_lore]: http://ddowiki.com/page/Religious_Lore "Religious Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[simple_weapon]: http://ddowiki.com/page/Category:Simple_weapons diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.md new file mode 100644 index 00000000..ecab6eae --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.md @@ -0,0 +1,219 @@ +# Ranger Class Feat + +[Ranger](http://ddowiki.com/page/Ranger) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | +| [Bow Strength](http://ddowiki.com/page/Bow_Strength) | Passive | This feat allows the ranger to apply their strength modifier to bow damage. | Ranger Level 1 | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | Ranger Level 1 | +| [Favored Enemy][favored_enemy] | Passive | At first level a ranger can select a type of creature from the favored enemy list. Favored Enemy grants +2 to damage and +2 to the skills bluff, listen, and spot against the chosen creature type. At 5th level and every 5 levels thereafter (10th, 15th, and 20th) a ranger may select an additional creature type from the favored enemy list. In addition, every 5 levels, the damage bonus against favored enemies increases by 2. | Ranger Level 1 | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Ranger Level 1 | +| [Martial Weapon Proficiency: Light Hammer][martial_weapon] | Passive | You are proficient with Light Hammers and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Longbow][martial_weapon] | Passive | You are proficient with Longbows and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Longsword][martial_weapon] | Passive | You are proficient with Longswords and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Rapier][martial_weapon] | Passive | You are proficient with Rapiers and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Shortbow][martial_weapon] | Passive | You are proficient with Shortbows and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Shortsword][martial_weapon] | Passive | You are proficient with Shortswords and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Throwing Hammer][martial_weapon] | Passive | You are proficient with Throwing Hammers and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Martial Weapon Proficiency: Warhammer][martial_weapon] | Passive | You are proficient with Warhammers and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | Ranger Level 1 | +| [Simple Weapon Proficiency: Club][simple_weapon] | Passive | You are proficient with Clubs and do not suffer a -4 attack penalty for using this weapon | Fighter Level 1 | +| [Simple Weapon Proficiency: Dagger][simple_weapon] | Passive | You are proficient with Daggers and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Dart][simple_weapon] | Passive | You are proficient with Darts and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Handwrap][simple_weapon] | Passive | You are proficient with Handwraps and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Heavy Crossbow][simple_weapon] | Passive | You are proficient with Heavy Crossbows and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Heavy Mace][simple_weapon] | Passive | You are proficient with Heavy Maces and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Light Crossbow][simple_weapon] | Passive | You are proficient with Light Crossbows and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Light Mace][simple_weapon] | Passive | You are proficient with Light Maces and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Morningstar][simple_weapon] | Passive | You are proficient with Morningstars and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Quarterstaff][simple_weapon] | Passive | You are proficient with Quarterstaffs and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Sickle][simple_weapon] | Passive | You are proficient with Sickles and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Simple Projectile][simple_weapon] | Passive | You are proficient with Simple Projectiles and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Simple Weapon Proficiency: Throwing Dagger][simple_weapon] | Passive | You are proficient with Throwing Daggers and do not suffer a -4 attack penalty for using this weapon | Ranger Level 1 | +| [Wild Empathy](http://ddowiki.com/page/Wild_Empathy) | Active | This feat allows the ranger to fascinate an animal as per the Hypnotism spell so that it will not attack. It can be used 3 times / rest period. | Ranger Level 1 | +| [Wilderness Lore][wilderness_lore] | Passive | This feat grants represents your knowledge of the Religion. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. | Favored Soul Receives once for every heroic level | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Rapid Shot](http://ddowiki.com/page/Rapid_Shot) | Passive | This feat allows you to fire ranged attacks faster and reload faster when using a ranged weapon; it affects thrown weapons, crossbows (normal and repeating), and bows; and it stacks with Quick Draw and Rapid Reload. | +| [Two Weapon Fighting](http://ddowiki.com/page/Two_Weapon_Fighting) | Passive | This feat reduces the to-hit penalty when using two weapons at the same time, and increases the chance to proc an off-hand attack by 20%, bringing the total chance to 40%. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------- | +| [Diehard](http://ddowiki.com/page/Diehard) | Passive | This feat causes the ranger to automatically stabilize when they become unconscious. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ | +| [Precise Shot](http://ddowiki.com/page/Precise_Shot) | Passive | Your targeted ranged attacks pass through friend and foe to strike your target (no damage will be done except to your target). | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +Gain the ability to cast Ranger spells. Your effective caster level is equal to your Ranger level, contrary to PnP ( +thus, the starting duration for a Resist energy spell is 4 minutes). A Ranger needs a Wisdom score of at least (10 + +spell level) to prepare and cast spells. + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Favored Enemy][favored_enemy] | Passive | You can now select an additional creature type from the favored enemy list. In addition, the damage bonus against favored enemies increases by 2. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| ------------------------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Improved Two Weapon Fighting](http://ddowiki.com/page/Improved_Two_Weapon_Fighting) | Passive | This feat increases the chance to produce an off-hand attack by 20%, bringing the total chance to 60%. | +| [Manyshot](http://ddowiki.com/page/Manyshot) | Active | This feat enables the character to fire multiple arrows with every bow attack he makes for the next 20 seconds, though each shot suffers an attack penalty. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| ---------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Improved Wild Empathy](http://ddowiki.com/page/Improved_wild_empathy) | Active | Allows the ranger to charm an animal (similar to the Charm monster spell)[official] for 5 mins.[official] It can be used 3 times / rest period with a 60 second cool down.[official] Note: Improved wild empathy can not be dispelled. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| ------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Evasion](http://ddowiki.com/page/Evasion) | Passive | This feat allows the character to avoid even magical and unusual attacks with great agility. If they make a successful reflex saving throw against an attack that normally deals half damage on a successful save, they will instead take no damage. A helpless character does not gain the benefit of evasion. Evasion can only be used if the character is wearing light or no armor and is not heavily encumbered. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Favored Enemy][favored_enemy] | Passive | You can now select an additional creature type from the favored enemy list. In addition, the damage bonus against favored enemies increases by 2. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| ---------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------ | +| [Greater Two Weapon Fighting](http://ddowiki.com/page/Greater_Two_Weapon_Fighting) | Passive | This feat increases the chance to produce an off-hand attack by 20%, bringing the total chance to 80%. | +| [Improved Precise Shot](http://ddowiki.com/page/Improved_Precise_Shot) | Active | Your targeted ranged attacks pass through and potentially damage all enemies in the projectile's path. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Favored Enemy][favored_enemy] | Passive | You can now select an additional creature type from the favored enemy list. In addition, the damage bonus against favored enemies increases by 2. | | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| ------------------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Hide in Plain Sight](http://ddowiki.com/page/Hide_in_Plain_Sight) | Passive | You are a master when it comes to hiding in places others think impossible. At all times while sneaking, conditions are treated as two 'eyes' better - you can hide even in plain daylight, and it takes opponents longer to detect you. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Favored Enemy][favored_enemy] | Passive | You can now select an additional creature type from the favored enemy list. In addition, the damage bonus against favored enemies increases by 2. | +| [Wilderness Lore][wilderness_lore] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +## Errata + +- Need to add Simple weapons +- Deity based feats are covered under separate spec + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[favored_enemy]: http://ddowiki.com/page/Favored_Enemy "Favored Enemy" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[wilderness_lore]: http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[martial_weapon]: http://ddowiki.com/page/Category:Martial_weapons "Martial Weapons" +[simple_weapon]: http://ddowiki.com/page/Category:Simple_weapons diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.md new file mode 100644 index 00000000..6e9b5ed7 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.md @@ -0,0 +1,207 @@ +# Rogue Class Feat + +[Rogue](http://ddowiki.com/page/Rogue) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Favored Soul Level 1 | +| [Shield Proficiency (General)][shield_feat] | Passive | This feat allows using all shields except Tower Shields without penalty | Cleric Level 1 | +| [Sneak Attack][sneak_attack] | Passive | This feat adds 1d6 damage when attacking enemies who are not targeting you. This feat can be used with ranged weapons within 30 ft. The damage benefit increases by 1d6 at levels 3, 5, 7, 9, 11, 13, 15, 17 and 19. Sneak Attack does not affect the undead, plants, constructs or oozes. | | +| [Trapfinding](http://ddowiki.com/page/Trap_Finding) | Passive | Rogues (and only rogues and artificers) can use the Search skill to locate difficult traps when the task has a Difficulty Class higher than 20. | | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Evasion](http://ddowiki.com/page/Evasion) | Passive | This feat allows the character to avoid even magical and unusual attacks with great agility. If they make a successful reflex saving throw against an attack that normally deals half damage on a successful save, they will instead take no damage. A helpless character does not gain the benefit of evasion. Evasion can only be used if the character is wearing light or no armor and is not heavily encumbered. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 2d6. | +| [Trap Sense][trap_sense] | Passive | This feat grants the following bonuses: +1 on reflex saving throws vs. traps and +1 Armor Class vs. trap attacks. The bonuses increase at levels 6, 9, 12, 15 and 18. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| ------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Trapmaking][trap_sense] | Passive | You have learned enough about traps to be able to scavenge parts from them, and with the help of the Free Agents, can craft your own. Automatically granted to rogues at level 4. | +| [Uncanny Dodge][uncanny_dodge] | Passive / Active | Active: Activate this ability to gain a temporary 25% dodge bonus and a +4 Reflex save bonus. Passive: Grants you a stacking 1% passive Dodge bonus at levels 4, 6, 8, 12, 16, and 20. | + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------- | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 3d6. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| ------------------------------- | ------- | -------------------------------- | +| [Trap Sense][trap_sense] | Passive | Trap sense bonus improves to +2. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------- | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 4d6. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| ------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------------- | +| [Improved Uncanny Dodge](http://ddowiki.com/page/Improved_uncanny_dodge) | Active | Activate this ability to gain a temporary 50% dodge bonus and a +6 reflex save bonus. | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------- | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 5d6. | +| [Trap Sense][trap_sense] | Passive | Trap sense bonus improves to +3. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Crippling Strike](http://ddowiki.com/page/Crippling_Strike) | Passive | A rogue with this ability can sneak attack opponents with such precision that his or her blows weaken and hamper them. An opponent damaged by a sneak attack also takes 2 points of Strength damage. | +| [Defensive Roll](http://ddowiki.com/page/Defensive_Roll) | Passive | If you are at below 20% of your hitpoint maximum, each time you are struck with an attack there is a percentage chance equal to your Reflex save that the attack does half main damage, and its special effects are negated (as if you were blocking). | +| [Improved Evasion](http://ddowiki.com/page/Improved_Evasion) | Passive | You can avoid even magical and unusual attacks with great agility. When you attempt a Reflex save against an effect that normally does half damage when saved against, you suffer no damage if you successfully save and half damage even if you fail. | +| [Opportunist](http://ddowiki.com/page/Opportunist) | Passive | A Rogue with this ability gains a 3% chance to double strike with melee weapons and bypasses 10% fortification. | +| [Skill Mastery](http://ddowiki.com/page/Skill_Mastery) | Passive | A rogue with this ability gains +1 to all skills. This ability may be taken multiple times. | +| [Slippery Mind](http://ddowiki.com/page/Slippery_Mind) | Passive | You can wriggle free from magical effects that would otherwise control or compel you. You gain a second saving throw versus enchantments. | + +Special Ability: Select one of +Crippling Strike, Defensive Roll, Improved Evasion, Opportunist, Skill Mastery, or Slippery Mind. + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------- | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 6d6. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ----------------------------------------------------------------------------------------------------- | +| [Trap Sense][trap_sense] | Passive | Represents your knowledge of the wilderness. This feat is received once for every favored soul level. | + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Crippling Strike](http://ddowiki.com/page/Crippling_Strike) | Passive | A rogue with this ability can sneak attack opponents with such precision that his or her blows weaken and hamper them. An opponent damaged by a sneak attack also takes 2 points of Strength damage. | +| [Defensive Roll](http://ddowiki.com/page/Defensive_Roll) | Passive | If you are at below 20% of your hitpoint maximum, each time you are struck with an attack there is a percentage chance equal to your Reflex save that the attack does half main damage, and its special effects are negated (as if you were blocking). | +| [Improved Evasion](http://ddowiki.com/page/Improved_Evasion) | Passive | You can avoid even magical and unusual attacks with great agility. When you attempt a Reflex save against an effect that normally does half damage when saved against, you suffer no damage if you successfully save and half damage even if you fail. | +| [Opportunist](http://ddowiki.com/page/Opportunist) | Passive | A Rogue with this ability gains a 3% chance to double strike with melee weapons and bypasses 10% fortification. | +| [Skill Mastery](http://ddowiki.com/page/Skill_Mastery) | Passive | A rogue with this ability gains +1 to all skills. This ability may be taken multiple times. | +| [Slippery Mind](http://ddowiki.com/page/Slippery_Mind) | Passive | You can wriggle free from magical effects that would otherwise control or compel you. You gain a second saving throw versus enchantments. | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 7d6. | + +Special Ability: Select one of Crippling Strike, Defensive Roll, Improved Evasion, Opportunist, Skill Mastery, or +Slippery Mind. + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------- | ------- | ---------------------------------------- | ------------ | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 8d6. | | +| [Trap Sense][trap_sense] | Passive | Trap sense bonus improves to +5. | | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Crippling Strike](http://ddowiki.com/page/Crippling_Strike) | Passive | A rogue with this ability can sneak attack opponents with such precision that his or her blows weaken and hamper them. An opponent damaged by a sneak attack also takes 2 points of Strength damage. | +| [Defensive Roll](http://ddowiki.com/page/Defensive_Roll) | Passive | If you are at below 20% of your hitpoint maximum, each time you are struck with an attack there is a percentage chance equal to your Reflex save that the attack does half main damage, and its special effects are negated (as if you were blocking). | +| [Improved Evasion](http://ddowiki.com/page/Improved_Evasion) | Passive | You can avoid even magical and unusual attacks with great agility. When you attempt a Reflex save against an effect that normally does half damage when saved against, you suffer no damage if you successfully save and half damage even if you fail. | +| [Opportunist](http://ddowiki.com/page/Opportunist) | Passive | A Rogue with this ability gains a 3% chance to double strike with melee weapons and bypasses 10% fortification. | +| [Skill Mastery](http://ddowiki.com/page/Skill_Mastery) | Passive | A rogue with this ability gains +1 to all skills. This ability may be taken multiple times. | +| [Slippery Mind](http://ddowiki.com/page/Slippery_Mind) | Passive | You can wriggle free from magical effects that would otherwise control or compel you. You gain a second saving throw versus enchantments. | + +Special Ability: Select one of Crippling Strike, Defensive Roll, Improved Evasion, Opportunist, Skill Mastery, or +Slippery Mind. + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------- | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 9d6. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| -------------------------------- | ------- | -------------------------------- | +| [Trap Sense][trap_sense] | Passive | Trap sense bonus improves to +6. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Crippling Strike](http://ddowiki.com/page/Crippling_Strike) | Passive | A rogue with this ability can sneak attack opponents with such precision that his or her blows weaken and hamper them. An opponent damaged by a sneak attack also takes 2 points of Strength damage. | +| [Defensive Roll](http://ddowiki.com/page/Defensive_Roll) | Passive | If you are at below 20% of your hitpoint maximum, each time you are struck with an attack there is a percentage chance equal to your Reflex save that the attack does half main damage, and its special effects are negated (as if you were blocking). | +| [Improved Evasion](http://ddowiki.com/page/Improved_Evasion) | Passive | You can avoid even magical and unusual attacks with great agility. When you attempt a Reflex save against an effect that normally does half damage when saved against, you suffer no damage if you successfully save and half damage even if you fail. | +| [Opportunist](http://ddowiki.com/page/Opportunist) | Passive | A Rogue with this ability gains a 3% chance to double strike with melee weapons and bypasses 10% fortification. | +| [Skill Mastery](http://ddowiki.com/page/Skill_Mastery) | Passive | A rogue with this ability gains +1 to all skills. This ability may be taken multiple times. | +| [Slippery Mind](http://ddowiki.com/page/Slippery_Mind) | Passive | You can wriggle free from magical effects that would otherwise control or compel you. You gain a second saving throw versus enchantments. | +| [Sneak Attack][sneak_attack] | Passive | Sneak Attack damage now is equal to 10d6. | + +### Level 20 + +[//]: # "| [ ][featLevel20] [Feats][result]| Type | Description|" +[//]: # "|------------------------------------------|----|----|" +[//]: # "|[Uncanny Dodge][uncanny_dodge] | Passive| Grants you a stacking 1% passive Dodge bonus at levels 4, 6, 8, 12, 16, and 20." + +## Errata + +- Need to add Simple weapons +- Need to add Martial weapons (Rapier, Shortbow, Shortsword) +- Deity based feats are covered under separate spec + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[trap_sense]: http://ddowiki.com/page/Trap_Sense "Trap Sense" +[uncanny_dodge]: http://ddowiki.com/page/Uncanny_Dodge "Uncanny Dodge" +[sneak_attack]: http://ddowiki.com/page/Sneak_attack "Sneak Attack" +[favored_enemy]: http://ddowiki.com/page/Favored_Enemy "Favored Enemy" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[wilderness_lore]: http://ddowiki.com/page/Wilderness_Lore "Wilderness Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.md new file mode 100644 index 00000000..110c7121 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.md @@ -0,0 +1,170 @@ +# Sorcerer Class Feat + +[Sorcerer](http://ddowiki.com/page/Sorcerer) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | This feat grants represents your knowledge of the Religion. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. | Sorcerer Receives once for every heroic level | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------ | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Errata + +- Need to add Simple weapons + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[arcane_lore]: http://ddowiki.com/page/Arcane_lore "Arcane Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.md new file mode 100644 index 00000000..9ff1ba0b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.md @@ -0,0 +1,221 @@ +# Warlock Class Feat + +[Warlock](http://ddowiki.com/page/Warlock) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | | +| Eldritch Blast: Focused | Toggle | Turn your basic attack into a ranged attack that does 1d6 force damage | | +| [Light Armor Proficiency][light_armor] | Passive | Benefit: You are proficient with light armor, and do not suffer the armor check penalty to attack rolls when wearing light armor. You also gain 2 + 1/2 of your base attack bonus in physical resistance when wearing light armor. Note that a piece of armor with an ACP of 0 can be worn without penalty by all characters whether they're proficient with it or not. You will however still be reminded in the upper right corner of the screen that you are not proficient with what you are wearing. Note: The armor check penalty to skills (if any) and arcane spell failure (if any) of the armor you equip will still apply. | Cleric Level 1 | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | | +| Pact: Fey | Passive / Toggle | Your Eldritch Blast deals +1 Sonic damage, plus 1d4 per two Warlock levels. This damage is halved on a successful Reflex saving throw vs DC(19+ CHA Mod + Evo Bonuses) | | +| Pact: Fiend | Passive / Toggle | | | +| Pact: Great Old One | Passive / Toggle | | | + +Pact Choice: Choose between Fey, Fiend, or Great Old One; this will affect what alignment you can be, your save bonus, +extra spells, special abilities, and extra damage for your Eldritch Blast (see below). + +## Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ---------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Deceive Item](http://ddowiki.com/page/Deceive_Item) | Passive | UMD +5; increases to +10 at Level 13. | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | + +1st-level Pact Spell: Receive a bonus 1st-level spell in your spellbook based on your pact (see below); this is in +addition to the spells you can already learn, and cannot be changed (similar to the spontaneous casting of healing +spells by clerics and repair spells by artificers). + +## Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | + +## Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| ------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Beguiling Defenses | Passive | +1 to Reflex Saves | +| Fiendish Resilience | Passive | +1 to Fortitude Saves | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | +| Thought Shield | Passive | +1 to Will Saves | + +Pact Save Bonus: +1 to a save based on your pact (see below); increases by +1 at Warlock levels 8, 12, 16, and 20. + +## Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | +| Pact Magic: Blindness | Spell Like Ability | Adds the spell [Blindness](http://ddowiki.com/page/Blindness) to your spellbook @ Level 2 | +| Pact Magic: Knock | Spell Like Ability | Adds the spell [Knock](http://ddowiki.com/page/Knock) to your spellbook @ Level 2 | +| Pact Magic: Rage | Spell Like Ability | Adds the spell [Rage](http://ddowiki.com/page/Rage) to your spellbook @ Level 2 | + +2nd-level Pact Spell. + +## Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| ------------------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Dark Delirium](http://ddowiki.com/page/Dark_Delirium) | Spell | (Daze Monster: 10% chance damage breaks; no save; works on orange-named) | +| [Dark One's Luck](http://ddowiki.com/page/Dark_One%27s_Luck) | Spell | +2 to all saves | +| [Entropic Ward](http://ddowiki.com/page/Entropic_Ward) | Spell | +5 MRR, +25% Fortification | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | + +Special Ability: Gain a special ability based on your pact (see below). + +(Sort order places Delirium below One's Luck for some reason... TBD) + +## Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | + +## Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| ------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | + +## Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | + +## Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| -------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | + +3rd-level Pact Spell. + +## Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | + +## Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| -------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | +| [Paragon's Aegis][paragon_aegis] | Passive | : +5 MRR; increases by +5 at Warlock Levels 14, 16, 18, and 20. | + +## Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| ---------------------------------------------------- | ------- | ------------------------------------- | +| [Deceive Item](http://ddowiki.com/page/Deceive_Item) | Passive | UMD +5; increases to +10 at Level 13. | + +## Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | +| [Paragon's Aegis][paragon_aegis] | Passive | : +5 MRR; increases by +5 at Warlock Levels 14, 16, 18, and 20. | + +4th-level Pact Spell. + +## Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| [Create Thrall](http://ddowiki.com/page/Create_Thrall) | Active | Display DC = 15 + Warlock Level + Cha Mod. Displayed DC not affected by Enchantment Focus items. Rather quick casting time; no metamagic feats allowed. Affects also Undead. | | +| [Hurl through Hell](http://ddowiki.com/page/Hurl_through_Hell) | Active | Exile one target enemy from this existence. An enemy succeeding on a Will save vs DC(10 + Warlock level + Charisma Modifier) is instead paralyzed and helpless with fear for 6 seconds. | | +| [Misty Escape](http://ddowiki.com/page/Misty_Escape) | Active | You become invisible and charge forward. During your escape, you move through monsters as if you were ethereal. These effects last for six seconds. | | + +Special Ability: Gain a second special ability based on your pact (see below). + +## Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| -------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | +| [Paragon's Aegis][paragon_aegis] | Passive | : +5 MRR; increases by +5 at Warlock Levels 14, 16, 18, and 20. | + +## Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | + +5th-level Pact Spell. + +## Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| -------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | +| [Paragon's Aegis][paragon_aegis] | Passive | : +5 MRR; increases by +5 at Warlock Levels 14, 16, 18, and 20. | + +## Level 19 + +6th-level Pact Spell. + +## Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| ---------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Eldritch Blast Damage][eldritch_blast_damage] | Stance | Eldritch Blast deals 1d6 damage at level 1, and increases by +1d6 at Warlock level 3, 5, 7, 9, 11, 14, 17, and 20; for a total of 9d6 at level 20. The base damage is Force, though enhancements can change this to Evil (will affect evil enemies) or Piercing. The base Eldritch Blast scales with 130% spell power, but different shape or essences can change this percentage. | +| Pact Damage | Passive | +1d4 extra damage to your Eldritch Blast based on your pact (see below); this will increase by +1d4 every even Warlock levels, for a total of 10d4 at level 20. | +| [Paragon's Aegis][paragon_aegis] | Passive | : +5 MRR; increases by +5 at Warlock Levels 14, 16, 18, and 20. | + +## Errata + +- Need to add Simple weapons +- [Edritch Blast Damage][eldritch_blast_damage] is listed on Wiki as Eldritch Blast, In game it is listed as Eldritch + Blast _Damage_ +- Pact-Save Bonus is listed under class feats on Wiki but does not show up under Feats so the we are likely going to + apply the bonuses at the CharacterClass Level. + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[eldritch_blast_damage]: http://ddowiki.com/page/Eldritch_Blast "Eldritch Blast Damage" +[paragon_aegis]: http://ddowiki.com/page/Paragon%27s_Aegis "Paragon's Aegis" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[arcane_lore]: http://ddowiki.com/page/Arcane_lore "Arcane Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.md new file mode 100644 index 00000000..b41c6cf1 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.md @@ -0,0 +1,170 @@ +# Wizard Class Feat + +[Wizard](http://ddowiki.com/page/Wizard) + +## [Granted Feats](- "granted") + +## [Level 1](- "level1_class_feats") + +| [ ][featLevel1] [Feats][result] | Type | Description | Prerequisite | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | This feat grants represents your knowledge of the Religion. Characters with this feat are granted special quest-specific dialog options/object interactions that classes without this feat otherwise could not perform. It may also allow certain skill checks to learn insight into specific situations. | Sorcerer Receives once for every heroic level | +| [Dismiss Charm](http://ddowiki.com/page/Dismiss_Charm) | Active | Activate this short-ranged ability while targeting a charmed, commanded, controlled, or dominated enemy that is under your control to dispel the controlling effect. | | +| [Magical Training](http://ddowiki.com/page/Magical_Training) | Passive | Magical training increases maximum spell points by 80. It also applies Echoes of Power if the caster drops below 12 spell points. Characters with this feat are considered proficient with orbs. As of Update 17, this feat is now a trainable feat. As of Update 19, this feat also grants +5% chance to Spell Critical. | | + +### Level 2 + +| [ ][featLevel2] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 3 + +| [ ][featLevel3] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 4 + +| [ ][featLevel4] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 5 + +| [ ][featLevel5] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 6 + +| [ ][featLevel6] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 7 + +| [ ][featLevel7] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 8 + +| [ ][featLevel8] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 9 + +| [ ][featLevel9] [Feats][result] | Type | Description | +| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 10 + +| [ ][featLevel10] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 11 + +| [ ][featLevel11] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 12 + +| [ ][featLevel12] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 13 + +| [ ][featLevel13] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 14 + +| [ ][featLevel14] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 15 + +| [ ][featLevel15] [Feats][result] | Type | Description | Prerequisite | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------------ | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | | + +### Level 16 + +| [ ][featLevel16] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 17 + +| [ ][featLevel17] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 18 + +| [ ][featLevel18] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 19 + +| [ ][featLevel19] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +### Level 20 + +| [ ][featLevel20] [Feats][result] | Type | Description | +| -------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | +| [Arcane Lore][arcane_lore] | Passive | Represents your knowledge of the religious. This feat is received once for every favored soul level. | + +## Errata + +- Need to add Simple weapons + +[featLevel1]: - "c:verify-rows=#feat:grantedFeatsByLevel(1)" +[featLevel2]: - "c:verify-rows=#feat:grantedFeatsByLevel(2)" +[featLevel3]: - "c:verify-rows=#feat:grantedFeatsByLevel(3)" +[featLevel4]: - "c:verify-rows=#feat:grantedFeatsByLevel(4)" +[featLevel5]: - "c:verify-rows=#feat:grantedFeatsByLevel(5)" +[featLevel6]: - "c:verify-rows=#feat:grantedFeatsByLevel(6)" +[featLevel7]: - "c:verify-rows=#feat:grantedFeatsByLevel(7)" +[featLevel8]: - "c:verify-rows=#feat:grantedFeatsByLevel(8)" +[featLevel9]: - "c:verify-rows=#feat:grantedFeatsByLevel(9)" +[featLevel10]: - "c:verify-rows=#feat:grantedFeatsByLevel(10)" +[featLevel11]: - "c:verify-rows=#feat:grantedFeatsByLevel(11)" +[featLevel12]: - "c:verify-rows=#feat:grantedFeatsByLevel(12)" +[featLevel13]: - "c:verify-rows=#feat:grantedFeatsByLevel(13)" +[featLevel14]: - "c:verify-rows=#feat:grantedFeatsByLevel(14)" +[featLevel15]: - "c:verify-rows=#feat:grantedFeatsByLevel(15)" +[featLevel16]: - "c:verify-rows=#feat:grantedFeatsByLevel(16)" +[featLevel17]: - "c:verify-rows=#feat:grantedFeatsByLevel(17)" +[featLevel18]: - "c:verify-rows=#feat:grantedFeatsByLevel(18)" +[featLevel19]: - "c:verify-rows=#feat:grantedFeatsByLevel(19)" +[featLevel20]: - "c:verify-rows=#feat:grantedFeatsByLevel(20)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[light_armor]: http://ddowiki.com/page/Light_Armor_Proficiency "Light Armor Proficiency" +[medium_armor]: http://ddowiki.com/page/Medium_Armor_Proficiency "Medium Armor Proficiency" +[shield_feat]: http://ddowiki.com/page/Shield_Proficiency_(General) "Shield Proficiency" +[energy_resistance_acid]: http://ddowiki.com/page/Energy_Resistance:_Acid "Energy Resistance: Acid" +[energy_resistance_cold]: http://ddowiki.com/page/Energy_Resistance:_Cold "Energy Resistance: Cold" +[energy_resistance_electricity]: http://ddowiki.com/page/Energy_Resistance:_Electricity "Energy Resistance: Electricity" +[energy_resistance_fire]: http://ddowiki.com/page/Energy_Resistance:_Fire "Energy Resistance: Fire" +[energy_resistance_sonic]: http://ddowiki.com/page/Energy_Resistance:_Sonic "Energy Resistance: Sonic" +[arcane_lore]: http://ddowiki.com/page/Arcane_lore "Arcane Lore" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.md new file mode 100644 index 00000000..622b29e8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.md @@ -0,0 +1,37 @@ +# Deity Feats + +## Eberron + +[Eberron](- "setUpWorld(#TEXT)") + +| [ ][setUpReligion] [Religion][religion] | [Favored weapon][favoredWeapon] | [Level 1 feat][followerOf] ^°\*^ | [Level 3 feat][childOf] ^°^ | [Level 6 feat][unique] ^°\*^ | [Level 12 feat][belovedOf] ^°^ | [Level 20 feat][damageReduction] ^°†^ | +| --------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Aureon | [Quarterstaff](http://ddowiki.com/page/Quarterstaff "Quarterstaff") | [Follower of Aureon](http://ddowiki.com/page/Follower_of_Aureon "Follower of Aureon") | [Child of Aureon](http://ddowiki.com/page/Child_of_Aureon "Child of Aureon") | [Aureon's Instruction](http://ddowiki.com/page/Aureon%27s_Instruction "Aureon's Instruction") | [Beloved of Aureon](http://ddowiki.com/edit/Beloved_of_Aureon?redlink=1 "Beloved of Aureon (page does not exist)") | Damage Reduction: [TBD](http://ddowiki.com/page/TBD "TBD") | +| Blood of Vol | [Dagger](http://ddowiki.com/page/Dagger "Dagger") | [Follower of the Blood of Vol](http://ddowiki.com/page/Follower_of_the_Blood_of_Vol "Follower of the Blood of Vol") | [Child of the Blood of Vol](http://ddowiki.com/page/Child_of_the_Blood_of_Vol "Child of the Blood of Vol") | [The Blood is The Life](http://ddowiki.com/page/The_Blood_is_The_Life "The Blood is The Life") | [Beloved of the Blood of Vol](http://ddowiki.com/edit/Beloved_of_the_Blood_of_Vol?redlink=1 "Beloved of the Blood of Vol (page does not exist)") | Damage Reduction: [TBD](http://ddowiki.com/page/TBD "TBD") | +| Lord of Blades | [Greatsword](http://ddowiki.com/page/Greatsword "Greatsword") | [Follower of the Lord of Blades](http://ddowiki.com/page/Follower_of_the_Lord_of_Blades "Follower of the Lord of Blades") | [Child of the Lord of Blades](http://ddowiki.com/page/Child_of_the_Lord_of_Blades "Child of the Lord of Blades") | [Bladesworn Transformation](http://ddowiki.com/page/Bladesworn_Transformation "Bladesworn Transformation") | [Beloved of the Lord of Blades](http://ddowiki.com/page/Beloved_of_the_Lord_of_Blades "Beloved of the Lord of Blades") | [Damage Reduction: Adamantine](http://ddowiki.com/page/Damage_Reduction:_Adamantine "Damage Reduction: Adamantine") | +| Olladra | [Sickle](http://ddowiki.com/page/Sickle "Sickle") | [Follower of Olladra](http://ddowiki.com/page/Follower_of_Olladra "Follower of Olladra") | [Child of Olladra](http://ddowiki.com/page/Child_of_Olladra "Child of Olladra") | [Luck of Olladra](http://ddowiki.com/page/Luck_of_Olladra "Luck of Olladra") | [Beloved of Olladra](http://ddowiki.com/page/Beloved_of_Olladra "Beloved of Olladra") | Damage Reduction: [TBD](http://ddowiki.com/page/TBD "TBD") | +| Onatar | [Warhammer](http://ddowiki.com/page/Warhammer "Warhammer") | [Follower of Onatar](http://ddowiki.com/page/Follower_of_Onatar "Follower of Onatar") | [Child of Onatar](http://ddowiki.com/page/Child_of_Onatar "Child of Onatar") | [Onatar's Forge](http://ddowiki.com/page/Onatar%27s_Forge "Onatar's Forge") | [Beloved of Onatar](http://ddowiki.com/edit/Beloved_of_Onatar?redlink=1 "Beloved of Onatar (page does not exist)") | Damage Reduction: [TBD](http://ddowiki.com/page/TBD "TBD") | +| Silver Flame | [Longbow](http://ddowiki.com/page/Longbow "Longbow") | [Follower of the Silver Flame](http://ddowiki.com/page/Follower_of_the_Silver_Flame "Follower of the Silver Flame") | [Child of the Silver Flame](http://ddowiki.com/page/Child_of_the_Silver_Flame "Child of the Silver Flame") | [Silver Flame Exorcism](http://ddowiki.com/page/Silver_Flame_Exorcism "Silver Flame Exorcism") | [Beloved of the Silver Flame](http://ddowiki.com/page/Beloved_of_the_Silver_Flame "Beloved of the Silver Flame") | [Damage Reduction: Silver](http://ddowiki.com/page/Damage_Reduction:_Silver "Damage Reduction: Silver") | +| Sovereign Host | [Longsword](http://ddowiki.com/page/Longsword "Longsword") | [Follower of the Sovereign Host](http://ddowiki.com/page/Follower_of_the_Sovereign_Host "Follower of the Sovereign Host") | [Child of the Sovereign Host](http://ddowiki.com/page/Child_of_the_Sovereign_Host "Child of the Sovereign Host") | [Unyielding Sovereignty](http://ddowiki.com/page/Unyielding_Sovereignty "Unyielding Sovereignty") | [Beloved of the Sovereign Host](http://ddowiki.com/page/Beloved_of_the_Sovereign_Host "Beloved of the Sovereign Host") | [Damage Reduction: Cold Iron](http://ddowiki.com/page/Damage_Reduction:_Cold_Iron "Damage Reduction: Cold Iron"), [Silver](http://ddowiki.com/page/Damage_Reduction:_Silver "Damage Reduction: Silver") | +| Undying Court | [Scimitar](http://ddowiki.com/page/Scimitar "Scimitar") | [Follower of the Undying Court](http://ddowiki.com/page/Follower_of_the_Undying_Court "Follower of the Undying Court") | [Child of the Undying Court](http://ddowiki.com/page/Child_of_the_Undying_Court "Child of the Undying Court") | [Undying Call](http://ddowiki.com/page/Undying_Call "Undying Call") | [Beloved of the Undying Court](http://ddowiki.com/page/Beloved_of_the_Undying_Court "Beloved of the Undying Court") | [Damage Reduction: Cold Iron](http://ddowiki.com/page/Damage_Reduction:_Cold_Iron "Damage Reduction: Cold Iron") | +| Vulkoor | [Shortsword](http://ddowiki.com/page/Shortsword "Shortsword") | [Follower of Vulkoor](http://ddowiki.com/page/Follower_of_Vulkoor "Follower of Vulkoor") | [Child of Vulkoor](http://ddowiki.com/page/Child_of_Vulkoor "Child of Vulkoor") | [Vulkoor's Avatar](http://ddowiki.com/page/Vulkoor%27s_Avatar "Vulkoor's Avatar") | [Beloved of Vulkoor](http://ddowiki.com/page/Beloved_of_Vulkoor "Beloved of Vulkoor") | [Damage Reduction: Good](http://ddowiki.com/page/Damage_Reduction:_Good "Damage Reduction: Good") | + +## Forgotten Realms + +[Forgotten Realms](- "setUpWorld(#TEXT)") + +| [ ][setUpReligion] [Religion][religion] | [Favored weapon][favoredWeapon] | [Level 1 feat][followerOf] ^°\*^ | [Level 3 feat][childOf] ^°^ | [Level 6 feat][unique] ^°\*^ | [Level 12 feat][belovedOf] ^°^ | [Level 20 feat][damageReduction] ^°†^ | +| --------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| Amaunator | [Heavy Mace](http://ddowiki.com/page/Heavy_Mace "Heavy Mace") | [Favored by Amaunator](http://ddowiki.com/page/Favored_by_Amaunator "Favored by Amaunator") | [Child of Amaunator](http://ddowiki.com/page/Child_of_Amaunator "Child of Amaunator") | [Amaunator's Flames](http://ddowiki.com/page/Amaunator%27s_Flames "Amaunator's Flames") | [Beloved of Amaunator](http://ddowiki.com/page/Beloved_of_Amaunator "Beloved of Amaunator") | [Damage Reduction: Silver](http://ddowiki.com/page/Damage_Reduction:_Silver "Damage Reduction: Silver") | +| Helm | [Bastard Sword](http://ddowiki.com/page/Bastard_Sword "Bastard Sword") | [Favored by Helm](http://ddowiki.com/page/Favored_by_Helm "Favored by Helm") | [Child of Helm](http://ddowiki.com/page/Child_of_Helm "Child of Helm") | [Ever Watchful](http://ddowiki.com/page/Ever_Watchful "Ever Watchful") | [Beloved of Helm](http://ddowiki.com/page/Beloved_of_Helm "Beloved of Helm") | Damage Reduction: [TBD](http://ddowiki.com/page/TBD "TBD") | +| Silvanus | [Maul](http://ddowiki.com/page/Maul "Maul") | [Favored by Silvanus](http://ddowiki.com/page/Favored_by_Silvanus "Favored by Silvanus") | [Child of Silvanus](http://ddowiki.com/page/Child_of_Silvanus "Child of Silvanus") | [Blessing of Silvanus](http://ddowiki.com/page/Blessing_of_Silvanus "Blessing of Silvanus") | [Beloved of Silvanus](http://ddowiki.com/page/Beloved_of_Silvanus "Beloved of Silvanus") | Damage Reduction: [TBD](http://ddowiki.com/page/TBD "TBD") | + +[religion]: - "#religionId" +[setUpReligion]: - "#result = loadFromKey(#religionId)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[unique]: - "?=#result.unique()" +[followerOf]: - "?=#result.follow()" +[childOf]: - "?=#result.child()" +[belovedOf]: = "?=#result.beloved()" +[favoredWeapon]: - "?=#result.favoredWeapon()" +[damageReduction]: - "?=#result.damageReduction()" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.md new file mode 100644 index 00000000..ce1795c4 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.md @@ -0,0 +1,23 @@ +# Dragonmarks + +Dragonmarks are spell-like abilities that certain races can acquire as racial feats and enhancements. + +Least Dragonmarks are Feats, but the Lesser and Greater marks are now enhancements. + +## Least Dragonmarks + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| --------------------------------- | ---------------- | ---------------------------------------------------------------------- | ------------- | ---- | +| Least Dragonmark of Finding | Passive / Active | Search +2, Spell-Like Ability: Locate Objects | +| Least Dragonmark of Healing | Passive / Active | Heal +2, Spell-Like Ability: Cure Light Wounds | +| Least Dragonmark of Making | Passive / Active | Repair +2, Spell-Like Ability: Repair Light Damage, +3 Crafting Skills | +| Least Dragonmark of Passage | Passive / Active | Balance +2, Spell-Like Ability: Expeditious Retreat | +| Least Dragonmark of Scribing | Passive / Active | +2 UMD, Shield SLA | +| Least Dragonmark of Sentinel | Passive / Active | Intimidate +2, Spell-Like Ability: Shield of Faith | +| Least Dragonmark of Shadow | Passive / Active | Hide +2, Spell-Like Ability: Invisibility | +| Least Dragonmark of Storm | Passive / Active | Balance +2, Spell-Like Ability: Gust of Wind | +| Least Dragonmark of Warding | Passive / Active | Search +2, Spell-Like Ability: Neutralize Poison | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/Epic.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/Epic.md new file mode 100644 index 00000000..b65908b5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/Epic.md @@ -0,0 +1,12 @@ +# Epic Feats + +[Epic Feats](http://ddowiki.com/page/Epic_Feats) + +## Epic Feats by Category + +- [x] [Epic General Passive](EpicGeneralFeatSpec.html "Epic General Feats") +- [x] [Ranged Combat](EpicRangedCombatFeatSpec.html) +- [x] [Active Spell](EpicActiveSpellFeatSpec.html) +- [x] [SpellCasting](EpicSpellCastingFeatSpec.html) +- [x] [Metamagic](EpicMetamagicFeatSpec.html) +- [x] [Class](EpicClassFeatSpec.html) diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.md new file mode 100644 index 00000000..93a37617 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.md @@ -0,0 +1,17 @@ +# Epic Active Spell Feats + +[wiki](http://ddowiki.com/page/Epic_Feats) + +# Feats + +## Epic Active Spell feats[[edit](http://ddowiki.com/edit/Epic_Feats?section=4 "Edit section: Epic Active Spell feats")] + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------------------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- | +| **[Burst of Glacial Wrath](http://ddowiki.com/page/Burst_of_Glacial_Wrath "Burst of Glacial Wrath")** | Active - Spell | Spell Point Cost: 35. Target: Foe, Directional, Breakable Cone spell, deals 30d6 Cold Damage and freezes creatures within the cone. Monster who succeed at a Fortitude Save of (20 + the highest of your INT/WIS/CHA modifiers + Evocation bonuses) negate the freeze. Cooldown: 10 seconds. Passive: +140 Maximum Spell Points. | \* Level 24 | ![Icon Burst of Glacial Wrath.png](/images/Icon_Burst_of_Glacial_Wrath.png) | +| **[Ruin](http://ddowiki.com/page/Ruin_%28feat%29 "Ruin (feat)")** | Active - Spell | Spell Point Cost: 75. Target: Foe Deal 500 untyped damage to a single enemy. (No saving throw.) Cooldown: 15 seconds. | \* Level 27 | ![Icon Ruin.png](/images/Icon_Ruin.png) | +| **[Greater Ruin](http://ddowiki.com/edit/Greater_Ruin?redlink=1 "Greater Ruin (page does not exist)")** | Active - Spell | Spell Point Cost: 150. Target: Foe Deal 1000 untyped damage to a single enemy. (No saving throw.) Cooldown: 15 seconds. Passive: +140 Maximum Spell points. | _ Level 30 _ [Ruin](http://ddowiki.com/page/Ruin "Ruin") | ![Icon Greater Ruin.png](/images/Icon_Greater_Ruin.png) | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.md new file mode 100644 index 00000000..536d3335 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.md @@ -0,0 +1,50 @@ +# Epic Class Feats + +[wiki](http://ddowiki.com/page/Epic_Feats) + +## Epic Class feats[[edit](http://ddowiki.com/edit/Epic_Feats?section=7 "Edit section: Epic Class feats")] + +### Artificer + +[Artificer](- "setUpClass(#TEXT)") + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ----------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| **[Construct Exemplar](http://ddowiki.com/page/Construct_Exemplar "Construct Exemplar")** | Passive | You have augmented yourself heavily enough to be more machine than not. You are now considered a Living Construct instead of your original race. | _ Level 21 _ [Artificer](http://ddowiki.com/page/Artificer "Artificer") level 12+ _ [Improved Construct Essence](http://ddowiki.com/page/Improved_Construct_Essence "Improved Construct Essence") _ Non-warforged race | ![Icon Construct Essence.png](http://ddowiki.com/images/Icon_Construct_Essence.png) | + +### Bard + +[Bard](- "setUpClass(#TEXT)") + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ----------------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | +| **[Inspire Excellence](http://ddowiki.com/page/Inspire_Excellence "Inspire Excellence")** | Active - Bard Song | Inspire Excellence is a song granting +2 [competence bonus](http://ddowiki.com/page/Competence_bonus "Competence bonus") to all [stats](http://ddowiki.com/page/Ability "Ability") for you and your allies. | _ [Inspire Heroics](http://ddowiki.com/page/Inspire_Heroics "Inspire Heroics") (Level 15 [Bard song](http://ddowiki.com/page/Bardic_music "Bardic music")) _ [Perform](http://ddowiki.com/page/Perform "Perform"): 20 trained ranks. | ![Icon Feat Inspire Excellence.png](http://ddowiki.com/images/Icon_Feat_Inspire_Excellence.png) | + +### Monk + +[Monk](- "setUpClass(#TEXT)") + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| **[Improved Martial Arts](http://ddowiki.com/page/Improved_Martial_Arts "Improved Martial Arts")** | Passive | +1(W) with unarmed. +0.5 (W) with other ki weapons. | \* [Monk](http://ddowiki.com/page/Monk "Monk") level 12+ | ![Icon Feat Improved Martial Arts.png](http://ddowiki.com/images/Icon_Feat_Improved_Martial_Arts.png) | +| **[Vorpal Strikes](http://ddowiki.com/page/Vorpal_Strikes "Vorpal Strikes")** | Active - Combat Stance | Your unarmed strikes are now considered vorpal and slashing. | _ [Monk](http://ddowiki.com/page/Monk "Monk") level 12+ _ [Wisdom](http://ddowiki.com/page/Wisdom "Wisdom") 23 \* [Improved Critical](http://ddowiki.com/page/Improved_Critical "Improved Critical") bludgeoning weapons | ![Icon Feat Vorpal Strikes.png](http://ddowiki.com/images/Icon_Feat_Vorpal_Strikes.png) | + +### Rogue + +[Rogue](- "setUpClass(#TEXT)") + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------- | ------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| **[Improved Sneak Attack](http://ddowiki.com/page/Improved_Sneak_Attack "Improved Sneak Attack")** | Passive | +3d6 sneak damage | _ [Rogue](http://ddowiki.com/page/Rogue "Rogue") level 12+ _ [Dexterity](http://ddowiki.com/page/Dexterity "Dexterity") 21 | ![Icon Feat Improved Sneak Attack.png](http://ddowiki.com/images/Icon_Feat_Improved_Sneak_Attack.png) | + +### Warlock + +[Warlock](- "setUpClass(#TEXT)") + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| **[Epic Eldritch Blast](http://ddowiki.com/page/Epic_Eldritch_Blast "Epic Eldritch Blast")** | Passive | +2d6 [Eldritch Blast](http://ddowiki.com/page/Eldritch_Blast "Eldritch Blast") dice. | \* [Warlock](http://ddowiki.com/page/Warlock "Warlock") level 12+ | ![Icon Epic Eldritch Blast.png](http://ddowiki.com/images/Icon_Epic_Eldritch_Blast.png) | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.md new file mode 100644 index 00000000..2d619805 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.md @@ -0,0 +1,30 @@ +# Epic General Feats + +[wiki](http://ddowiki.com/page/Epic_Feats) + +# General + +## General Epic passive feats[[edit](http://ddowiki.com/edit/Epic_Feats?section=2 "Edit section: General Epic passive feats")] + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ---------------------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| **[Blinding Speed](http://ddowiki.com/page/Blinding_Speed "Blinding Speed")** | Passive | You are permanently [Hasted](http://ddowiki.com/page/Haste "Haste") | \* Level 27 | ![Icon Blinding Speed.png](/images/Icon_Blinding_Speed.png) | +| **[Bulwark of Defense](http://ddowiki.com/page/Bulwark_of_Defense "Bulwark of Defense")** | Passive | When in a defensive stance, you gain an additional +2 to all [saving throws](http://ddowiki.com/page/Saving_throw "Saving throw") and +4 to [Armor class](http://ddowiki.com/page/Armor_class "Armor class"). | \* None | ![Icon Feat Bulwark Of Defense.png](/images/Icon_Feat_Bulwark_Of_Defense.png) | +| **[Epic Damage Reduction](http://ddowiki.com/page/Epic_Damage_Reduction "Epic Damage Reduction")** | Passive | +10 [Physical Resistance](http://ddowiki.com/page/Physical_Resistance "Physical Resistance") | \* Level 27 | ![Icon Epic Damage Reduction.png](/images/Icon_Epic_Damage_Reduction.png) | +| **[Epic Fortitude](http://ddowiki.com/edit/Epic_Fortitude?redlink=1 "Epic Fortitude (page does not exist)")** | Passive | +2 [Fortitude](http://ddowiki.com/page/Fortitude "Fortitude") [Saving Throws](http://ddowiki.com/page/Saving_Throw "Saving Throw"). You don't automatically fail Fortitude saving throws on a roll of 1. | \* Level 27 | ![Icon Epic Fortitude.png](/images/Icon_Epic_Fortitude.png) | +| **[Epic Reflexes](http://ddowiki.com/edit/Epic_Reflexes?redlink=1 "Epic Reflexes (page does not exist)")** | Passive | +2 [Reflex](http://ddowiki.com/page/Reflex "Reflex") [Saving Throws](http://ddowiki.com/page/Saving_Throw "Saving Throw"). You don't automatically fail Reflex saving throws on a roll of 1. | \* Level 27 | ![Icon Epic Reflexes.png](/images/Icon_Epic_Reflexes.png) | +| **[Epic Reputation](http://ddowiki.com/edit/Epic_Reputation?redlink=1 "Epic Reputation (page does not exist)")** | Passive | +3 [Bluff](http://ddowiki.com/page/Bluff "Bluff"), [Diplomacy](http://ddowiki.com/page/Diplomacy "Diplomacy"), [Haggle](http://ddowiki.com/page/Haggle "Haggle"), [Intimidate](http://ddowiki.com/page/Intimidate "Intimidate"), and [Perform](http://ddowiki.com/page/Perform "Perform"). | \* Level 27 | ![Icon Epic Reputation.png](/images/Icon_Epic_Reputation.png) | +| **[Epic Skills](http://ddowiki.com/page/Epic_Skills "Epic Skills")** | Passive | As part of your epic training, you gain +1 to all [skills](http://ddowiki.com/page/Skills "Skills"). This feat can be taken multiple times. | \* None | ![Icon Feat Epic Skill.png](/images/Icon_Feat_Epic_Skill.png) | +| **[Epic Will](http://ddowiki.com/edit/Epic_Will?redlink=1 "Epic Will (page does not exist)")** | Passive | +2 [Will](http://ddowiki.com/page/Will "Will") [Saving Throws](http://ddowiki.com/page/Saving_Throw "Saving Throw"). You don't automatically fail Will saving throws on a roll of 1. | \* Level 27 | ![Icon Epic Will.png](/images/Icon_Epic_Will.png) | +| **[Great Ability](http://ddowiki.com/page/Great_Ability "Great Ability")** | Passive | +1 to [Charisma](http://ddowiki.com/page/Charisma "Charisma") or [Constitution](http://ddowiki.com/page/Constitution "Constitution") or [Dexterity](http://ddowiki.com/page/Dexterity "Dexterity") or [Intelligence](http://ddowiki.com/page/Intelligence "Intelligence") or [Strength](http://ddowiki.com/page/Strength "Strength") or [Wisdom](http://ddowiki.com/page/Wisdom "Wisdom"). This feat can be taken multiple times. | \* None | ![Question icon.png](/images/Question_icon.png) | +| **[Overwhelming Critical](http://ddowiki.com/page/Overwhelming_Critical "Overwhelming Critical")** | Passive | When rolling a 19 or 20 on an attack with any [weapons](http://ddowiki.com/page/Weapon "Weapon") used by the character, your critical damage multiplier is increased by +1. | \* [Improved Critical](http://ddowiki.com/page/Improved_Critical "Improved Critical") | ![Icon Feat Overwhelming Critical.png](/images/Icon_Feat_Overwhelming_Critical.png) | +| **[Epic Toughness](http://ddowiki.com/page/Epic_Toughness "Epic Toughness")** | Passive | This [feat](http://ddowiki.com/page/Feat "Feat") increases the characters maximum [hit points](http://ddowiki.com/page/Hit_point "Hit point") by 50. | _ [Toughness (feat)](http://ddowiki.com/page/Toughness "Toughness") _ [Constitution](http://ddowiki.com/page/Constitution "Constitution") 21 | ![Icon Feat Epic Toughness.png](/images/Icon_Feat_Epic_Toughness.png) | +| **[Watchful Eye](http://ddowiki.com/edit/Watchful_Eye?redlink=1 "Watchful Eye (page does not exist)")** | Passive | If you pass within 5 feet of a trap, you make a Search check to notice it as if actively Searching. (You still need the [Trapfinding](http://ddowiki.com/page/Trapfinding "Trapfinding") feat to successfully Search for difficult traps.) \*\* | | | + +Note: For this feat to function properly, both your Spot and Search skill must be equal or higher than the search DC for +the trap +itself.\*_ | _ Level 27 | ![Icon Watchful Eye.png](/images/Icon_Watchful_Eye.png) | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.md new file mode 100644 index 00000000..d13d5542 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.md @@ -0,0 +1,16 @@ +# Epic Metamagic Feats + +[wiki](http://ddowiki.com/page/Epic_Feats) + +# Metamagic + +## Epic Metamagic feats[[edit](http://ddowiki.com/edit/Epic_Feats?section=5 "Edit section: Epic Metamagic feats")] + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------- | +| **[Embolden Spell](http://ddowiki.com/page/Embolden_Spell "Embolden Spell")** | Metamagic | While this metamagic feat is active, you gain +2 to the [DC](http://ddowiki.com/page/DC "DC") of all spells with DCs, but they consume 10 additional [spell points](http://ddowiki.com/page/Spell_point "Spell point"). Passive: +140 Maximum [Spell Points](http://ddowiki.com/page/Spell_Point "Spell Point"). | \* Level 24 | ![Icon Embolden Spell.png](/images/Icon_Embolden_Spell.png) | +| **[Intensify Spell](http://ddowiki.com/page/Intensify_Spell "Intensify Spell")** | Metamagic | While this metamagic feat is active, you gain +75 [Spell Power](http://ddowiki.com/page/Spell_Power "Spell Power") with any spell affected by Intensify Spell, but they cost 15 additional [spell points](http://ddowiki.com/page/Spell_point "Spell point"). This bonus stacks with [Empower](http://ddowiki.com/page/Empower "Empower") and [Maximize](http://ddowiki.com/page/Maximize "Maximize"). Passive: +140 Maximum [Spell Points](http://ddowiki.com/page/Spell_Point "Spell Point"). | \* Level 24 | ![Icon Intensify Spell.png](/images/Icon_Intensify_Spell.png) | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.md new file mode 100644 index 00000000..1cc0a8ec --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.md @@ -0,0 +1,15 @@ +# Epic Ranged Combat Feats + +[wiki](http://ddowiki.com/page/Epic_Feats) + +# Ranged Combat + +## Epic Ranged Combat Passive feats[[edit](http://ddowiki.com/edit/Epic_Feats?section=3 "Edit section: Epic Ranged Combat Passive feats")] + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ----------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| **[Combat Archery](http://ddowiki.com/page/Combat_Archery "Combat Archery")** | Passive | Your ranged damage is increased by +1(W). You also gain a +2% [Dodge bonus](http://ddowiki.com/page/Dodge_bonus "Dodge bonus") while using a ranged weapon. | _ [Point Blank Shot](http://ddowiki.com/page/Point_Blank_Shot "Point Blank Shot") _ [Dexterity](http://ddowiki.com/page/Dexterity "Dexterity") 21 | ![Icon Feat Combat Archery.png](/images/Icon_Feat_Combat_Archery.png) | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.md new file mode 100644 index 00000000..dc4ddd5f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.md @@ -0,0 +1,29 @@ +# Epic SpellCasting + +[wiki](http://ddowiki.com/page/Epic_Feats) + +# Epic Spellcasting Feats + +## Epic Ranged Combat Passive feats[[edit](http://ddowiki.com/edit/Epic_Feats?section=5 "Edit section: Epic Ranged Combat Passive feats")] + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | Icon | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| **[Epic Mental Toughness](http://ddowiki.com/page/Epic_Mental_Toughness "Epic Mental Toughness")** | Passive | Increases your maximum spell points by 200. Increase Spell Crit by 1% | \* [Improved Mental Toughness](http://ddowiki.com/page/Improved_Mental_Toughness "Improved Mental Toughness") | ![Icon Feat Epic Mental Toughness.png](/images/Icon_Feat_Epic_Mental_Toughness.png) | +| **[Epic Spell Focus](http://ddowiki.com/page/Epic_Spell_Focus "Epic Spell Focus")** | Passive | Adds an additional +1 to the [DCs](http://ddowiki.com/page/DC "DC") of your spells from the chosen [school of magic](http://ddowiki.com/page/School_of_magic "School of magic"), making them harder to resist. This bonus stacks with the bonus from [Spell focus](http://ddowiki.com/page/Spell_focus "Spell focus") and [Greater Spell Focus](http://ddowiki.com/page/Greater_Spell_Focus "Greater Spell Focus") feat of the same school. | _ [Greater Spell Focus](http://ddowiki.com/page/Greater_Spell_Focus "Greater Spell Focus") for same school _ Level 11: [Cleric](http://ddowiki.com/page/Cleric "Cleric"), [Druid](http://ddowiki.com/page/Druid "Druid"), [Wizard](http://ddowiki.com/page/Wizard "Wizard") _ Level 12: [Sorcerer](http://ddowiki.com/page/Sorcerer "Sorcerer"), [Favored Soul](http://ddowiki.com/page/Favored_Soul "Favored Soul") _ Level 15: [Artificer](http://ddowiki.com/page/Artificer "Artificer") or Level 16: [Bard](http://ddowiki.com/page/Bard "Bard") | ![Icon Feat Epic Spell Focus.png](/images/Icon_Feat_Epic_Spell_Focus.png) | +| **[Epic Spell Penetration](http://ddowiki.com/page/Epic_Spell_Penetration "Epic Spell Penetration")** | Passive | Adds +4 to your caster level check for defeating [Spell Resistance](http://ddowiki.com/page/Spell_Resistance "Spell Resistance") (in addition to the +4 from the [Spell Penetration](http://ddowiki.com/page/Spell_Penetration "Spell Penetration") and [Greater Spell Penetration](http://ddowiki.com/page/Greater_Spell_Penetration "Greater Spell Penetration") feats). | _ [Spell Penetration](http://ddowiki.com/page/Spell_Penetration "Spell Penetration") _ [Greater Spell Penetration](http://ddowiki.com/page/Greater_Spell_Penetration "Greater Spell Penetration") | ![Icon Feat Epic Spell Penetration.png](/images/Icon_Feat_Epic_Spell_Penetration.png) | +| **[Improved Augment Summoning](http://ddowiki.com/edit/Improved_Augment_Summoning?redlink=1 "Improved Augment Summoning (page does not exist)")** | Passive | Your summoned creatures, charmed minions, pets, and hirelings have +8 to all ability scores, +10% Dodge, and +100 Maximum Hitpoints. Passive: +140 Maximum Spell Points _ Note: The HP & boost to ability scores stacks with that from [Augment Summoning](http://ddowiki.com/page/Augment_Summoning "Augment Summoning") for a total of +12 to all ability scores._ | _ Level 24 _ [Augment Summoning](http://ddowiki.com/page/Augment_Summoning "Augment Summoning") | ![Icon Improved Augment Summoning.png](/images/Icon_Improved_Augment_Summoning.png) | +| **[Master of Air](http://ddowiki.com/edit/Master_of_Air?redlink=1 "Master of Air (page does not exist)")** | Passive | Your [Shocking Grasp](http://ddowiki.com/page/Shocking_Grasp "Shocking Grasp"), [Electric Loop](http://ddowiki.com/page/Electric_Loop "Electric Loop"), and [Lightning Bolt](http://ddowiki.com/page/Lightning_Bolt "Lightning Bolt") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Air.png](/images/Icon_Master_of_Air.png) | +| **[Master of Alignment](http://ddowiki.com/edit/Master_of_Alignment?redlink=1 "Master of Alignment (page does not exist)")** | Passive | Your [Holy Smite](http://ddowiki.com/page/Holy_Smite "Holy Smite"), [Deific Vengeance](http://ddowiki.com/page/Deific_Vengeance "Deific Vengeance"), [Unholy Blight](http://ddowiki.com/page/Unholy_Blight "Unholy Blight"), [Chaos Hammer](http://ddowiki.com/page/Chaos_Hammer "Chaos Hammer"), and [Order's Wrath](http://ddowiki.com/page/Order%27s_Wrath "Order's Wrath") spells get +10 to their maximum caster level.Grants +140 Maximum Spell Points. | \* Level 24 | ![Icon Master of Alignment.png](/images/Icon_Master_of_Alignment.png) | +| **[Master of Artifice](http://ddowiki.com/edit/Master_of_Artifice?redlink=1 "Master of Artifice (page does not exist)")** | Passive | Your [Static Shock](http://ddowiki.com/page/Static_Shock "Static Shock"), [Lightning Sphere](http://ddowiki.com/page/Lightning_Sphere "Lightning Sphere"), [Blast Rod](http://ddowiki.com/page/Blast_Rod "Blast Rod"), and [Lightning Motes](http://ddowiki.com/page/Lightning_Motes "Lightning Motes") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Artifice.png](/images/Icon_Master_of_Artifice.png) | +| **[Master of Earth](http://ddowiki.com/edit/Master_of_Earth?redlink=1 "Master of Earth (page does not exist)")** | Passive | Your [Acid Spray](http://ddowiki.com/page/Acid_Spray "Acid Spray"), [Melf's Acid Arrow](http://ddowiki.com/page/Melf%27s_Acid_Arrow "Melf's Acid Arrow"), and [Acid Blast](http://ddowiki.com/page/Acid_Blast_%28spell%29 "Acid Blast (spell)") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Earth.png](/images/Icon_Master_of_Earth.png) | +| **[Master of Fire](http://ddowiki.com/edit/Master_of_Fire?redlink=1 "Master of Fire (page does not exist)")** | Passive | Your [Burning Hands](http://ddowiki.com/page/Burning_Hands "Burning Hands"), [Scorch](http://ddowiki.com/page/Scorch "Scorch"), and [Fireball](http://ddowiki.com/page/Fireball "Fireball") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Fire.png](/images/Icon_Master_of_Fire.png) | +| **[Master of Knowledge](http://ddowiki.com/page/Master_of_Knowledge "Master of Knowledge")** | Passive | Your [Arcane Bolt](http://ddowiki.com/page/Arcane_Bolt "Arcane Bolt") and [Arcane Blast](http://ddowiki.com/page/Arcane_Blast "Arcane Blast") spells now grant you one stack of Mental Honing (+3 Universal Spell Power, +2% Spell Crit Damage) when cast. This effect can stack up to 30 times. One stack is removed every 6 seconds. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Knowledge.png](/images/Icon_Master_of_Knowledge.png) | +| **[Master of Light](http://ddowiki.com/page/Master_of_Light "Master of Light")** | Passive | Your [Sun Bolt](http://ddowiki.com/page/Sun_Bolt "Sun Bolt"), [Searing Light](http://ddowiki.com/page/Searing_Light "Searing Light"), and [Divine Punishment](http://ddowiki.com/page/Divine_Punishment "Divine Punishment") spells gain +10 to their maximum caster level. Grants +140 Maximum Spell Points. | \* Level 24 | ![Icon Master of Light.png](/images/Icon_Master_of_Light.png) | +| **[Master of Music](http://ddowiki.com/edit/Master_of_Music?redlink=1 "Master of Music (page does not exist)")** | Passive | Your [Shout](http://ddowiki.com/page/Shout "Shout"), [Greater Shout](http://ddowiki.com/page/Greater_Shout "Greater Shout"), [Sonic Blast](http://ddowiki.com/page/Sonic_Blast "Sonic Blast"), and [Reverberate](http://ddowiki.com/page/Spellsinger_enhancements#Tier_Two "Spellsinger enhancements") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Music.png](/images/Icon_Master_of_Music.png) | +| **[Master of Water](http://ddowiki.com/edit/Master_of_Water?redlink=1 "Master of Water (page does not exist)")** | Passive | Your [Niac's Cold Ray](http://ddowiki.com/page/Niac%27s_Cold_Ray "Niac's Cold Ray"), [Snowball Swarm](http://ddowiki.com/page/Snowball_Swarm "Snowball Swarm"), and [Niac's Biting Cold](http://ddowiki.com/page/Niac%27s_Biting_Cold "Niac's Biting Cold") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of Water.png](/images/Icon_Master_of_Water.png) | +| **[Master of the Dead](http://ddowiki.com/edit/Master_of_the_Dead?redlink=1 "Master of the Dead (page does not exist)")** | Passive | Your [Chill Touch](http://ddowiki.com/page/Chill_Touch "Chill Touch"), [Death Aura](http://ddowiki.com/page/Death_Aura "Death Aura"), and [Negative Energy Burst](http://ddowiki.com/page/Negative_Energy_Burst "Negative Energy Burst") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of the Dead.png](/images/Icon_Master_of_the_Dead.png) | +| **[Master of the Wilds](http://ddowiki.com/edit/Master_of_the_Wilds?redlink=1 "Master of the Wilds (page does not exist)")** | Passive | Your [Produce Flame](http://ddowiki.com/page/Produce_Flame "Produce Flame"), [Creeping Cold](http://ddowiki.com/page/Creeping_Cold "Creeping Cold"), [Call Lightning](http://ddowiki.com/page/Call_Lightning "Call Lightning"), and [Word of Balance](http://ddowiki.com/page/Word_of_Balance "Word of Balance") spells gain +10 to their maximum caster level. Grants +140 maximum Spell Points. | \* Level 24 | ![Icon Master of the Wilds.png](/images/Icon_Master_of_the_Wilds.png) | + +[existingFeat]: - "c:verify-rows=#feat:verify()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.md new file mode 100644 index 00000000..590b90a4 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.md @@ -0,0 +1 @@ +# Favor Based Feats diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/metamagic/MetaMagic.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/metamagic/MetaMagic.md new file mode 100644 index 00000000..193ded3f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/metamagic/MetaMagic.md @@ -0,0 +1,24 @@ +# Meta Magic Feat + +## Metamagics + +| [ ][existingFeat] [Feats][result] | Description | Prerequisites | Icon | +| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ----------------------------------------------------------------------------------- | +| [Empower Healing Spell](http://ddowiki.com/page/Empower_Healing_Spell) | Positive energy spells gain 75 Spell Power and costs an extra 10 spell points per spell. | Metamagic | ![Icon Feat Empower Healing Spell.png](/images/Icon_Feat_Empower_Healing_Spell.png) | +| [Empower Spell](http://ddowiki.com/page/Empower_Spell) | Increases the Spell Power by 75, but increases the spell point cost of casting the spell by 15. | Metamagic | ![Icon Feat Empower Spell.png](/images/Icon_Feat_Empower_Spell.png) | +| [Enlarge Spell](http://ddowiki.com/page/Enlarge_Spell) | Doubles the range of a spell, but increases the amount of spell points needed to cast the spell by 10. | Metamagic | ![Icon Feat Enlarge Spell.png](/images/Icon_Feat_Enlarge_Spell.png) | +| [Eschew Materials](http://ddowiki.com/page/Eschew_Materials) | Allows the caster to cast a spell without its material component. Using this feat increases the spell points consumed by the spell by 2. | Metamagic | ![Icon Feat Eschew Materials.png](/images/Icon_Feat_Eschew_Materials.png) | +| [Extend Spell](http://ddowiki.com/page/Extend_Spell) | Doubles the duration of a spell, but increases the amount of spell points needed to cast the spell by 10. | Metamagic | ![Icon Feat Extend Spell.png](/images/Icon_Feat_Extend_Spell.png) | +| [Heighten Spell](http://ddowiki.com/page/Heighten_Spell) | While this spell is active, spells are raised to the highest spell level your character can cast, but the spells cost 5 more spell points per level raised. | Metamagic | ![Icon Feat Heighten Spell.png](/images/Icon_Feat_Heighten_Spell.png) | +| [Maximize Spell](http://ddowiki.com/page/Maximize_Spell) | Increases the Spell Power by 150. Spells will cost 25 more spell points while this feat is active. | Metamagic | ![Icon Feat Maximize Spell.png](/images/Icon_Feat_Maximize_Spell.png) | +| [Quicken Spell](http://ddowiki.com/page/Quicken_Spell) | While this feat is activated, spells cast twice as fast and cannot be interrupted by enemy attacks, though all spells will cost 10 more spell points to cast. | Metamagic | ![Icon Feat Quicken Spell.png](/images/Icon_Feat_Quicken_Spell.png) | + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[race_feat]: http://ddowiki.com/page/Category:Racial_feats +[cls_feat]: http://ddowiki.com/page/Category:Class_feats +[existingFeat]: - "c:verify-rows=#feat:verifyFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.md new file mode 100644 index 00000000..f9b40325 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.md @@ -0,0 +1,31 @@ +# Bladeforged Feats + +## Granted + +| [ ][grantedFeats] [Feats][result] | Description | Type | Prerequisites | Icon | +| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| [Bladeforged][bladeforged] | Increases Aura of Good: +2 AC and +1 saving throws
-10% Slashing damage. When you take Slashing damage, you gain +1 PRR for 3 seconds (up to +20 PRR)
Positive healing reduced by -10% compared to Warforged (-5% starting positive damage vulnerability)
Grants Repair Light, Moderate, Serious, Critical and Mass Repair Light, Moderate, Serious Damage as Paladin spells | Passive | [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Bladeforged.png](/images/Icon_Feat_Bladeforged.png) | +| [Composite Plating](http://ddowiki.com/page/Composite_Plating "Composite Plating") | You are not considered to be wearing armor. You have a 5% [arcane spell failure](http://ddowiki.com/page/Arcane_spell_failure "Arcane spell failure") chance. | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Light Fortification (feat)][light_fort] | Warforged have a 25% immunity to critical hits and Sneak Attacks. | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Warforged Traits](http://ddowiki.com/page/Warforged_Traits "Warforged Traits") | Warforged are naturally immune to [Sleep](http://ddowiki.com/page/Sleep "Sleep"), [Energy drained](http://ddowiki.com/page/Energy_drained "Energy drained"), [Nauseated](http://ddowiki.com/page/Nauseated "Nauseated"), [Sickened](http://ddowiki.com/page/Sickened "Sickened"), [Exhausted](http://ddowiki.com/page/Exhausted "Exhausted"), and [Paralyzed](http://ddowiki.com/page/Paralyzed "Paralyzed") effects.
Immune to ability score damage from [Natural Poisons](http://ddowiki.com/page/Poison "Poison"), and [Natural Diseases](http://ddowiki.com/page/Disease "Disease") but are vulnerable to those that effect wood or metal.
Warforged gain a +10 racial bonus to [saving throws](http://ddowiki.com/page/Saving_throw "Saving throw") against [Magical Poisons](http://ddowiki.com/page/Poison "Poison") and do not fail saving throws against them on a roll of a natural 1 (this makes you immune to [Magical Poisons](http://ddowiki.com/page/Poison "Poison") with a DC of less than 11+your [Fortitude](http://ddowiki.com/page/Fortitude "Fortitude") save). If you transform into a different type of creature, you will lose these benefits until you are return to your Warforged form. | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | + +## Purchasable + +| [ ][availableFeats] [Feats][result] | Description | Type | Prerequisites | Icon | +| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | +| [Adamantine Body](http://ddowiki.com/page/Adamantine_Body "Adamantine Body") | This plating is counted as a [heavy armor](http://ddowiki.com/page/Category:Heavy_armor "Category:Heavy armor"). It grants a +8 [armor bonus](http://ddowiki.com/page/Armor_bonus "Armor bonus") to [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class") and a [damage reduction](http://ddowiki.com/page/Damage_reduction "Damage reduction") bonus of 2/[adamantine](http://ddowiki.com/page/Adamantine "Adamantine"). The character also incurs a 35% chance for [arcane spell failure](http://ddowiki.com/page/Arcane_spell_failure "Arcane spell failure"), a -5 [armor check penalty](http://ddowiki.com/page/Armor_check_penalty "Armor check penalty"), and a +1 maximum [dexterity bonus](http://ddowiki.com/page/Dexterity_bonus "Dexterity bonus"). | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Improved Damage Reduction](http://ddowiki.com/page/Improved_Damage_Reduction "Improved Damage Reduction") | Warforged gain [damage reduction](http://ddowiki.com/page/Damage_reduction "Damage reduction") 1/adamantine, or improves the characters existing [damage reduction](http://ddowiki.com/page/Damage_reduction "Damage reduction") by 1/adamantine. | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Improved Fortification](http://ddowiki.com/page/Improved_Fortification "Improved Fortification") | Improves the Warforged fortifications. It gains immunity to [Sneak Attacks](http://ddowiki.com/page/Sneak_Attack "Sneak Attack") and extra damage from [critical hits](http://ddowiki.com/page/Critical_hit "Critical hit"). This [Feat](http://ddowiki.com/page/Feat "Feat") will cause the character to lose the ability to be healed by spells such as [Cure Light Wounds](http://ddowiki.com/page/Cure_Light_Wounds "Cure Light Wounds"). | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged")
[Base Attack Bonus](http://ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus") +6 | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Mithral Body](http://ddowiki.com/page/Mithral_Body "Mithral Body") | This plating is counted as a [light armor](http://ddowiki.com/page/Category:Light_armor "Category:Light armor") and grants a +5 bonus to [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class"). It also incurs a 15% [arcane spell failure](http://ddowiki.com/page/Arcane_spell_failure "Arcane spell failure"), a -1 [armor check penalty](http://ddowiki.com/page/Armor_check_penalty "Armor check penalty"), and has a +5 maximum [dexterity bonus](http://ddowiki.com/page/Dexterity_bonus "Dexterity bonus"). | Passive | [Warforged](http://ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Mithral Fluidity](http://ddowiki.com/page/Mithral_Fluidity "Mithral Fluidity") | [Maximum dexterity bonus](http://ddowiki.com/page/Maximum_dexterity_bonus "Maximum dexterity bonus") from [mithral body](http://ddowiki.com/page/Mithral_Body "Mithral Body") plating is increase by 1 and it decreases the [armor check penalties](http://ddowiki.com/page/Armor_check_penalty "Armor check penalty") by 1. | Passive | [Mithral Body](http://ddowiki.com/page/Mithral_Body "Mithral Body") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[bladeforged]: http://ddowiki.com/edit/Bladeforged_(feat)?redlink=1 +[light_fort]: http://ddowiki.com/page/Light_Fortification_%28feat%29 "Light Fortification (feat)" +[grantedFeats]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[availableFeats]: - "c:verify-rows=#feat:verifyAvailableFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.md new file mode 100644 index 00000000..4941a18e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.md @@ -0,0 +1,26 @@ +# Deep Gnome Feat Spec + +[Specification](http://ddowiki.com/page/Category:Deep_Gnome_feats) + +## Granted + +| [ ][grantedFeats] [Feats][result] | Description | Type | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------- | -------------------------------------------------------------------------------------------------------- | +| **[Gnomish Proficiencies](http://ddowiki.com/edit/Gnomish_Proficiencies?redlink=1 "Gnomish Proficiencies (page does not exist)")** | You have some special bonuses due to your gnomish heritage:_ +2 Haggle _ +2 Use Magic Device | Passive | | ![Icon Enhancement Shadow Phase.png](/images/Icon_Enhancement_Shadow_Phase.png) | +| **[Martial Weapon Proficiency: Light Hammer](http://ddowiki.com/page/Martial_Weapon_Proficiency#Light_Hammer "Martial Weapon Proficiency")** | You do not suffer a -4 penalty on attack rolls when using a Light Hammer. | Passive | | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| **[Martial Weapon Proficiency: Throwing Hammer](http://ddowiki.com/page/Martial_Weapon_Proficiency#Throwing_Hammer "Martial Weapon Proficiency")** | You do not suffer a -4 penalty on attack rolls when using a Throwing Hammer. | Passive | | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| **[Martial Weapon Proficiency: Warhammer](http://ddowiki.com/page/Martial_Weapon_Proficiency#Warhammer "Martial Weapon Proficiency")** | You do not suffer a -4 penalty on attack rolls when using a Warhammer. | Passive | | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| **[Small Size Bonus](http://ddowiki.com/page/Small_Size_Bonus "Small Size Bonus")** | As a [Small](http://ddowiki.com/page/Small "Small") creature, [Gnomes](http://ddowiki.com/page/Gnome "Gnome") gain a +1 [size bonus](http://ddowiki.com/page/Size_bonus "Size bonus") to [attack rolls](http://ddowiki.com/page/Attack_roll "Attack roll") and [Armor Class](http://ddowiki.com/page/Armor_Class "Armor Class"), and a +4 bonus on [Hide](http://ddowiki.com/page/Hide "Hide") checks. | Passive | | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | + +[grantedFeats]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[availableFeats]: - "c:verify-rows=#feat:verifyAvailableFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DrowFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DrowFeatSpec.md new file mode 100644 index 00000000..c94b82d5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DrowFeatSpec.md @@ -0,0 +1,26 @@ +# Drow Feat Spec + +[Drow Feats](http://ddowiki.com/page/Category:Drow_feats) + +## Granted + +| [ ][grantedFeats] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ---------------------------------------- | +| [Drow Spell Resistance](http://ddowiki.com/page/Drow_Spell_Resistance) | Passive | Drow are naturally resistant to spells and magical effects. They have Spell Resistance 10+Character Level. | Drow | Icon Feat Drow Spell Resistance.png | +| [Elven Keen Senses](http://ddowiki.com/page/Elven_Keen_Senses) | Passive | Elves have keen senses and gain a +2 bonus to Listen, Search, and Spot checks. | Drow | Icon Feat Elven.png | +| [Enchantment Save Bonus](http://ddowiki.com/page/Enchantment_Save_Bonus) | Passive | Elves are naturally resistant to enchantments, receiving a +2 bonus on saves against enchantments. | Drow | Icon Feat Elven.png | +| [ Exotic Weapon Proficiency: Shuriken](http://ddowiki.com/page/Exotic_Weapon_Proficiency#Shuriken) | Passive | You do not suffer a -4 penalty on attack rolls when using a shuriken. | Drow | Icon Feat Martial Weapon Proficiency.png | +| [Immunity to Sleep](http://ddowiki.com/page/Immunity_to_Sleep) | Passive | Elves are naturally immune to magical sleep effects. | Drow | Icon Feat Elven.png | +| [ Martial Weapon Proficiency: Rapier](http://ddowiki.com/page/Martial_Weapon_Proficiency#Rapier) | Passive | You do not suffer a -4 penalty on attack rolls when using a rapier. | Drow | Shuriken Expertise.PNG | +| [ Martial Weapon Proficiency: Shortsword](http://ddowiki.com/page/Martial_Weapon_Proficiency#Shortsword) | Passive | You do not suffer a -4 penalty on attack rolls when using a shortsword. | Drow | Shuriken Expertise.PNG | +| [Shuriken Expertise](http://ddowiki.com/page/Shuriken_Expertise) | Passive | You are skilled with the use of the shuriken, and have a chance to throw an additional one per throw. (Percent chance to throw an additional shuriken is equal to your Dexterity.) | Drow | Shuriken Expertise.PNG | +| [Spell Save Bonus](http://ddowiki.com/page/Spell_Save_Bonus) | Passive | Drow are naturally resistant to spells, receiving a +2 bonus on Will saves against spell effects. | Drow | Icon Feat Exotic Weapon Proficiency.png | + +[grantedFeats]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[availableFeats]: - "c:verify-rows=#feat:verifyAvailableFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.md new file mode 100644 index 00000000..8443c71c --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.md @@ -0,0 +1,25 @@ +# Dwarf Feat Spec + +[Specification](http://ddowiki.com/page/Category:Dwarf_feats) + +| [ ][existingFeat] [Feats][result] | Description | Type | Icon | +| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------ | +| [Dwarven Stability](http://ddowiki.com/page/Dwarven_Stability) | Dwarves gain a +4 modifier to the Balance skill. | Passive | ![Icon Feat Dwarven.png](/images/Icon_Feat_Dwarven.png) | +| [Dwarven Stonecunning](http://ddowiki.com/page/Dwarven_Stonecunning) | Dwarves naturally are able to find secret doors more often, receiving a +2 bonus on their Search skill. | Passive | ![Icon Feat Dwarven.png](/images/Icon_Feat_Dwarven.png) | +| [Exotic Weapon Proficiency: Dwarven Axe](http://ddowiki.com/page/Exotic_Weapon_Proficiency:_Dwarven_Axe) | You do not suffer a -4 penalty on attack rolls when using a Dwarven axe. Dwarves treat the dwarven axe as a martial, rather than exotic, weapon. | Passive | ![Icon Feat Exotic Weapon Proficiency.png](/images/36px-Icon_Feat_Exotic_Weapon_Proficiency.png) | +| [Giant Evasion](http://ddowiki.com/page/Giant_Evasion) | Dwarves gain a bonus of +4 to their armor class vs. giant-type monsters including giants, ogres, trolls, etc. | Passive | ![Icon Feat Dwarven.png](/images/Icon_Feat_Dwarven.png) | +| [Orc and Goblin Bonus](http://ddowiki.com/page/Orc_and_Goblin_Bonus) | Dwarves a +1 racial bonus on attack rolls against orcs and goblinoids. | Passive | ![Icon Feat Dwarven.png](/images/Icon_Feat_Dwarven.png) | +| [Poison Save Bonus](http://ddowiki.com/page/Poison_Save_Bonus) | Dwarves are naturally resistant to poison, receiving a +2 bonus on saving throws against poisons. | Passive | ![Icon Feat Dwarven.png](/images/Icon_Feat_Dwarven.png) | +| [Spell Save Bonus](http://ddowiki.com/page/Spell_Save_Bonus) | Dwarves are naturally resistant to spells receving a +2 bonus to saving throws vs. spells and spell-like effects. | Passive | ![Icon Feat Dwarven.png](/images/Icon_Feat_Dwarven.png) | + +[existingFeat]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ElfFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ElfFeatSpec.md new file mode 100644 index 00000000..c2f5606d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ElfFeatSpec.md @@ -0,0 +1,26 @@ +# Elf Feats + +## [Elf Feats](http://ddowiki.com/page/Category:Elf_feats) + +| [ ][grantedFeats] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| [Elf][elf_feat] | Passive | You are considered an Elf. You are treated as such by magical abilities and effects, and are able to use appropriate equipment. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elf.png](images/Icon_Feat_Elf.png) | +| [Elven Keen Senses](http://www.ddowiki.com/page/Elven_Keen_Senses "Elven Keen Senses") | Passive | Elves have keen senses and gain a +2 bonus to [Listen](http://www.ddowiki.com/page/Listen "Listen"), [Search](http://www.ddowiki.com/page/Search "Search"), and [Spot](http://www.ddowiki.com/page/Spot "Spot") checks. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elven.png](/images/thumb/36px-Icon_Feat_Elven.png) | +| [Enchantment Save Bonus](http://www.ddowiki.com/page/Enchantment_Save_Bonus "Enchantment Save Bonus") | Passive | Elves are naturally resistant to enchantments, receiving a +2 bonus on saves against [enchantments](http://www.ddowiki.com/page/Enchantment "Enchantment") | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elven.png](/images/thumb/36px-Icon_Feat_Elven.png) | +| [Immunity to Sleep](http://www.ddowiki.com/page/Immunity_to_Sleep "Immunity to Sleep") | Passive | Elves are naturally immune to magical sleep effects. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elven.png](/images/thumb/36px-Icon_Feat_Elven.png) | +| [Martial Weapon Proficiency: Longbow](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Longbow "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Longbow | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Longsword](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Longsword "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Longsword | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Rapier](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Rapier "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Rapier. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Shortbow](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Shortbow "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Shortbow. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | + +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[grantedFeats]: - "c:verify-rows=#feat:verifyGrantedFeats()" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.md new file mode 100644 index 00000000..3099a5c8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.md @@ -0,0 +1,25 @@ +# Gnome Feat Spec + +[Specification](http://ddowiki.com/page/Category:Gnome_feats) + +## Feats + +| [ ][existingFeat] [Feats][result] | Description | Type | Icon | +| ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- | +| [Gnomish Proficiencies](http://ddowiki.com/edit/Gnomish_Proficiencies?redlink=1) | You have some special bonuses due to your gnomish heritage: +2 Haggle +2 Use Magic Device | Passive | ![Icon Enhancement Shadow Phase.png](/images/Icon_Enhancement_Shadow_Phase.png) | +| [Martial Weapon Proficiency: Light Hammer](http://ddowiki.com/page/Martial_Weapon_Proficiency#Light_Hammer) | You do not suffer a -4 penalty on attack rolls when using a Light Hammer. | Passive | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Throwing Hammer](http://ddowiki.com/page/Martial_Weapon_Proficiency#Throwing_Hammer) | You do not suffer a -4 penalty on attack rolls when using a Throwing Hammer. | Passive | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Warhammer](http://ddowiki.com/page/Martial_Weapon_Proficiency#Warhammer) | You do not suffer a -4 penalty on attack rolls when using a de4Warhammer. | Passive | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Small Size Bonus](http://ddowiki.com/page/Small_Size_Bonus) | As a Small creature, Gnomes gain a +1 size bonus to attack rolls and Armor Class, and a +4 bonus on Hide checks. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | + +[existingFeat]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md new file mode 100644 index 00000000..4dbe0ba8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.md @@ -0,0 +1,56 @@ +# Half-Elf Feats + +## [Half Elf Feats](http://ddowiki.com/page/Category:Half-Elf_feats) + +| [ ][existingFeat] [Feats][result] | Type | Description | Prerequisites | +| ------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +| [Half-Elf Keen Senses](http://ddowiki.com/edit/Half-Elf_Keen_Senses?redlink=1 "Half-Elf Keen Senses (page does not exist)") | Passive | +1 racial bonus to Listen, Search, and Spot checks. | \* Half-Elf | +| [Half-Elf Mixed Heritage](http://ddowiki.com/edit/Half-Elf_Mixed_Heritage?redlink=1 "Half-Elf Mixed Heritage (page does not exist)") | Passive | Half-elves are treated as both an Elf and a Human by magical items and effects if one would be beneficial. Negative effects treat Half-Elves as if they were Elves. | \* Half-Elf | +| [Half-Elf Social Graces](http://ddowiki.com/edit/Half-Elf_Social_Graces?redlink=1 "Half-Elf Social Graces (page does not exist)") | Passive | Half-Elves get an additional roll for each use of the skills Intimidate, Diplomacy, and Bluff. | Half-Elf | +| [Immunity to Sleep](http://ddowiki.com/page/Immunity_to_Sleep "Immunity to Sleep") | Passive | Half Elves are naturally immune to magical sleep effects. | Drow Elf, Elf, Half-Elf, Sun Elf | + +[existingFeat]: - "c:verify-rows=#feat:verifyNonDilettante()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" + +## Dilettante feats + +Dilettante feats are special [feats](http://ddowiki.com/page/Feat "Feat") available +to [Half-Elves](http://ddowiki.com/page/Half-Elves "Half-Elves"). They enable a Half-Elf to garner some of the abilities +of another class other than the class they have chosen. A Half-Elf can choose any one of these feats he or she meets the +listed requirements for at [character creation](http://ddowiki.com/page/Character_creation "Character creation"). + +When retraining feats by talking to [Fred](http://ddowiki.com/page/Fred "Fred"), ability +increase [tome](http://ddowiki.com/page/Tome "Tome") bonuses are NOT counted for prerequisites, however, ability +increases +from [level-up](http://ddowiki.com/page/Ability "Ability") +Characters can increase an [ability](http://ddowiki.com/page/Ability "Ability") by one at levels: 4, 8, 12, 16, 20, and 24. ARE counted. [(Nov 2012 forum post)](http://forums.ddo.com/showthread.php?t=399599) + +Along with various bonuses, you, with these feats, count as a level one of the class for item use purposes (class +restricted items, [scrolls](http://ddowiki.com/page/Scroll "Scroll") and [wands](http://ddowiki.com/page/Wand "Wand")). +These feats are not recommended for characters with actual levels of the class. + +| [ ][existingDilettanteFeat] [Feats][result] | Type | Description | Prerequisites | +| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| [Half-Elf Dilettante: Artificer](http://ddowiki.com/edit/Half-Elf_Dilettante:_Artificer?redlink=1 "Half-Elf Dilettante: Artificer (page does not exist)") | Passive | You have watched the artificers of House Cannith work their trade. You gain proficiency with all crossbows, and Artificer Knowledge: Scrolls (You gain a +2 bonus to Use Magical Device checks when using scrolls, and their Caster Level is increased by one - this Caster Level increase is capped by your Intelligence modifier.) You are able to use wands and scrolls as if you are a level one artificer. For item use purposes you count as a level one artificer in addition to any other classes you possess (though this does not grant the ability to use Rune Arms). | Half-Elf 13 Intelligence | +| [Half-Elf Dilettante: Barbarian](http://ddowiki.com/page/Half-Elf_Dilettante:_Barbarian "Half-Elf Dilettante: Barbarian") | Passive | [Damage Reduction](http://ddowiki.com/page/Damage_Reduction "Damage Reduction") 1/- (does not stack with Barbarian Damage Reduction). | _ Half-Elf _ 13 Constitution | +| [Half-Elf Dilettante: Bard](http://ddowiki.com/page/Half-Elf_Dilettante:_Bard "Half-Elf Dilettante: Bard") | Active | Can produce a Bardic [Fascinate](http://ddowiki.com/page/Fascinate "Fascinate") effect three times per rest that mesmerizes nearby enemies, with a Will DC based on a Perform check (or 1d20 + Charisma Modifier if untrained) to negate. Able to use wands and scrolls as if you were a level one bard. | _ Half-Elf_ 13 Charisma | +| [Half-Elf Dilettante: Cleric](http://ddowiki.com/pagepage/Half-Elf_Dilettante:_Cleric "Half-Elf Dilettante: Cleric") | Passive | Able to use wands and scrolls as if you were a level one cleric. | _ Half-Elf _ 13 Wisdom | +| [Half-Elf Dilettante: Druid](http://ddowiki.com/page/Half-Elf_Dilettante:_Druid?redlink=1 "Half-Elf Dilettante: Druid (page does not exist)") | Passive | Able to use wands and scrolls as if you were a level one druid. | _ Half-Elf _ 13 Wisdom | +| [Half-Elf Dilettante: Favored Soul](http://ddowiki.com/page/Half-Elf_Dilettante:_Favored_Soul "Half-Elf Dilettante: Favored Soul") | Passive | Able to use wands and scrolls as if you were a level one favored soul. | _ Half-Elf _ 13 Charisma | +| [Half-Elf Dilettante: Fighter](http://ddowiki.com/page/Half-Elf_Dilettante:_Fighter "Half-Elf Dilettante: Fighter") | Passive | Proficiency with all martial melee weapons. | _ Half-Elf_ 13 Strength | +| [Half-Elf Dilettante: Monk](http://ddowiki.com/page/Half-Elf_Dilettante:_Monk "Half-Elf Dilettante: Monk") | Passive | Proficiency with the [quarterstaff](http://ddowiki.com/page/Quarterstaff "Quarterstaff"), [kama](http://ddowiki.com/page/Kama "Kama"), and [shuriken](http://ddowiki.com/page/Shuriken "Shuriken"), and can add up to 2 points of your Wisdom bonus to your Armor Class as long as you are Defensively [Centered](http://ddowiki.com/page/Centered "Centered") (unarmored and unencumbered, does not stack with the similar monk class ability). | _ Half-Elf _ 13 Wisdom | +| [Half-Elf Dilettante: Paladin](http://ddowiki.com/page/Half-Elf_Dilettante:_Paladin "Half-Elf Dilettante: Paladin") | Passive | Can add up to 2 points of your Charisma bonus to all saves (does not stack with the [Divine Grace](http://ddowiki.com/page/Divine_Grace "Divine Grace") ability). Able to use wands and scrolls as if you were a level one paladin. | _ Half-Elf,_ 13 Charisma | +| [Half-Elf Dilettante: Ranger](http://ddowiki.com/page/Half-Elf_Dilettante:_Ranger "Half-Elf Dilettante: Ranger") | Passive | Proficiency with all martial ranged weapons, and can add up to 2 points of your Strength bonus to bow damage. Able to use wands and scrolls as if you were a level one ranger. | _ Half-Elf _ 13 Dexterity | +| [Half-Elf Dilettante: Rogue](http://ddowiki.com/page/Half-Elf_Dilettante:_Rogue "Half-Elf Dilettante: Rogue") | Passive | You deal +1d6 Sneak Attack damage (does not stack with the Rogue [Sneak Attack](http://ddowiki.com/page/Sneak_Attack "Sneak Attack") ability). | _ Half-Elf,_ 13 Dexterity | +| [Half-Elf Dilettante: Sorcerer](http://ddowiki.com/page/Half-Elf_Dilettante:_Sorcerer "Half-Elf Dilettante: Sorcerer") | Passive | Able to use wands and scrolls as if you were a level one sorcerer. | _ Half-Elf_ 13 Charisma | +| [Half-Elf Dilettante: Warlock](http://ddowiki.com/page/Half-Elf_Dilettante:_Warlock "Half-Elf Dilettante: Warlock") | Passive | Able to use wands and scrolls as if you were a level one warlock. Toggle: You deal 1D4 extra Fire damage with attacks and spells. This trigger at most once every two seconds. This toggle is exclusive with Warlock Pact toggles. | _ Half-Elf_ 13 Charisma | +| [Half-Elf Dilettante: Wizard](http://ddowiki.com/page/Half-Elf_Dilettante:_Wizard "Half-Elf Dilettante: Wizard") | Passive | Able to use wands and scrolls as if you were a level one wizard. | _ Half-Elf_ 13 Intelligence | + + + +[existingDilettanteFeat]: - "c:verify-rows=#feat:verifyDilettante()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" + + diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.md new file mode 100644 index 00000000..a8da76fa --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.md @@ -0,0 +1,19 @@ +# Half-Orc Feat Spec + +## [Half-orc Feats](http://ddowiki.com/page/Category:Half-Orc_feats) + +| [ ][existingFeat] [Feats][result] | Description | Type | Icon | +| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------- | +| [Half-Orc Orc Blood](http://ddowiki.com/page/Half-Orc_Orc_Blood) | As a Small creature, Gnomes gain a +1 size bonus to attack rolls and Armor Class, and a +4 bonus on Hide checks. | Passive | ![Icon Half Orc Blood.png](/images/HalfOrcOrcBlood.png) | + +[existingFeat]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.md new file mode 100644 index 00000000..fd8e67fc --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.md @@ -0,0 +1,25 @@ +# Halfling Feat Spec + +## [Halfling Feats](http://ddowiki.com/page/Category:Halfling_feats) + +| [ ][existingFeat] [Feats][result] | Description | Type | Icon | +| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------- | +| [Halfling Agility][halfling_agility] | Halflings are agile and gain a +2 bonus to Jump and Move Silently checks. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | +| [Halfling Bravery](http://ddowiki.com/page/Halfling_Bravery) | Halflings are naturally resistant to fear and gain a +2 morale bonus to saving throws versus fear effects. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | +| [Halfling Keen Ears](http://ddowiki.com/page/Halfling_Keen_Ears) | Halflings have keen ears and gain a +2 bonus to Listen checks. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | +| [Halfling Luck](http://ddowiki.com/page/Halfling_Luck) | Halflings are surprisingly lucky and gain a +1 luck bonus on all saving throws. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | +| [Halfling Thrown Weapon Focus](http://ddowiki.com/page/Halfling_Thrown_Weapon_Focus) | Halflings develop their throwing skill starting at a very young age. As a result, halflings get a +1 bonus to attack rolls when using any thrown weapon. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | +| [Small Size Bonus](http://ddowiki.com/page/Halfling_Size_Bonus) | As a Small creature, Halflings gain a +1 size bonus to attack rolls and Armor Class, and a +4 bonus on Hide checks. | Passive | ![Icon Feat Halfling Agility.png](/images/Icon_Feat_Halfling_Agility.png) | + +[existingFeat]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[halfling_agility]: http://ddowiki.com/page/Halfling_Agility_(feat) +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.md new file mode 100644 index 00000000..630e9d8f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.md @@ -0,0 +1,20 @@ +# Purple Dragon Knights Feats + +## [Feats](http://ddowiki.com/page/Category:Purple_Dragon_Knight_feats) + +| [ ][existingFeat] [Feats][result] | Description | Type | Icon | +| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------- | --------------------------------------------------- | +| [Human](http://ddowiki.com/page/Human) | You are considered human. You are treated as such by magical abilities and effects, and are able to use appropriate equipment. | Passive | ![Icon Feat Human.png](/images/Human_race_icon.png) | + +[existingFeat]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[halfling_agility]: http://ddowiki.com/page/Halfling_Agility_(feat) +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/Races.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/Races.md new file mode 100644 index 00000000..048a54b0 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/Races.md @@ -0,0 +1,22 @@ +# Racial Feats + +## Race Specific Feats + +Each race or race-family may have traits exclusive to it. For example, all elves (Drow, Sun and true elves) are +naturally immune to sleep. + +- [Bladeforged](BladeforgedFeatSpec.html) +- [Deep Gnome (Svirfneblin)](DeepGnomeFeatSpec.html) +- [Drow Elf](DrowFeatSpec.html) +- [Dwarf](DwarfFeatSpec.html) +- [Elf](ElfFeatSpec.html) +- [Half-Elf](HalfElfFeatSpec.html) +- [Gnome](GnomeFeatSpec.html) +- [Halfling](HalflingFeatSpec.html) +- [Half-Elf](HalfElfFeatSpec.html) +- [Half-Orc](HalfOrcFeatSpec.html) +- Human (No Human specific feats) +- [Morninglord (Sun Elf)](SunElfFeatSpec.html) +- [Purple Dragon Knight](PurpleDragonKnightsFeatSpec.html) +- [Shadar-kai](ShardarkaiFeatSpec.html) +- [Warforged](WarforgedFeatSpec.html) diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.md new file mode 100644 index 00000000..24db8948 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.md @@ -0,0 +1,20 @@ +# Shardarkai Feat Spec + +# [Feats](http://ddowiki.com/page/Category:Shadar-kai_feats) + +| [ ][existingFeat] [Feats][result] | Description | Type | Icon | +| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------- | --------------------------------------------------- | +| [Human](http://ddowiki.com/page/Human) | You are considered human. You are treated as such by magical abilities and effects, and are able to use appropriate equipment. | Passive | ![Icon Feat Human.png](/images/Icon_Feat_Human.png) | + +[existingFeat]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[halfling_agility]: http://ddowiki.com/page/Halfling_Agility_(feat) +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) + +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.md new file mode 100644 index 00000000..1272956e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.md @@ -0,0 +1,26 @@ +# Sun-Elf Feat + +# [Feats](http://ddowiki.com/page/Category:Sun_Elf_feats) + +| [ ][grantedFeats] [Feats][result] | Type | Description | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| [Elf][elf_feat] | Passive | You are considered an Elf. You are treated as such by magical abilities and effects, and are able to use appropriate equipment. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elf.png](/images/Icon_Feat_Elf.png) | +| [Elven Keen Senses](http://www.ddowiki.com/page/Elven_Keen_Senses "Elven Keen Senses") | Passive | Elves have keen senses and gain a +2 bonus to [Listen](http://www.ddowiki.com/page/Listen "Listen"), [Search](http://www.ddowiki.com/page/Search "Search"), and [Spot](http://www.ddowiki.com/page/Spot "Spot") checks. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elven.png](/images/thumb/36px-Icon_Feat_Elven.png) | +| [Enchantment Save Bonus](http://www.ddowiki.com/page/Enchantment_Save_Bonus "Enchantment Save Bonus") | Passive | Elves are naturally resistant to enchantments, receiving a +2 bonus on saves against [enchantments](http://www.ddowiki.com/page/Enchantment "Enchantment") | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elven.png](/images/thumb/36px-Icon_Feat_Elven.png) | +| [Immunity to Sleep](http://www.ddowiki.com/page/Immunity_to_Sleep "Immunity to Sleep") | Passive | Elves are naturally immune to magical sleep effects. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Elven.png](/images/thumb/36px-Icon_Feat_Elven.png) | +| [Martial Weapon Proficiency: Longbow](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Longbow "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Longbow | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Longsword](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Longsword "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Longsword | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Rapier](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Rapier "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Rapier. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | +| [Martial Weapon Proficiency: Shortbow](http://www.ddowiki.com/page/Martial_Weapon_Proficiency#Shortbow "Martial Weapon Proficiency") | Passive | You do not suffer a -4 penalty on attack rolls when using a Shortbow. | [Elf][elf_race] , [Sun Elf][sunelf_race] | ![Icon Feat Martial Weapon Proficiency.png](/images/thumb/36px-Icon_Feat_Martial_Weapon_Proficiency.png) | + +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com + +[grantedFeats]: - "c:verify-rows=#feat:verifyGrantedFeats()" diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.md new file mode 100644 index 00000000..a0e74520 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.md @@ -0,0 +1,34 @@ +# Warforged + +# [Feats](http://ddowiki.com/page/Category:Warforged_feats) + +## Granted + +| [ ][grantedFeats] [Feats][result] | Description | Type | Prerequisites | Icon | +| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | +| [Composite Plating](http://www.ddowiki.com/page/Composite_Plating "Composite Plating") | You are not considered to be wearing armor. You have a 5% [arcane spell failure](http://www.ddowiki.com/page/Arcane_spell_failure "Arcane spell failure") chance. | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Light Fortification (feat)][light_fort] | Warforged have a 25% immunity to critical hits and Sneak Attacks. | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Warforged Traits](http://www.ddowiki.com/page/Warforged_Traits "Warforged Traits") | Warforged are naturally immune to [Sleep](http://www.ddowiki.com/page/Sleep "Sleep"), [Energy drained](http://www.ddowiki.com/page/Energy_drained "Energy drained"), [Nauseated](http://www.ddowiki.com/page/Nauseated "Nauseated"), [Sickened](http://www.ddowiki.com/page/Sickened "Sickened"), [Exhausted](http://www.ddowiki.com/page/Exhausted "Exhausted"), and [Paralyzed](http://www.ddowiki.com/page/Paralyzed "Paralyzed") effects.
Immune to ability score damage from [Natural Poisons](http://www.ddowiki.com/page/Poison "Poison"), and [Natural Diseases](http://www.ddowiki.com/page/Disease "Disease") but are vulnerable to those that effect wood or metal.
Warforged gain a +10 racial bonus to [saving throws](http://www.ddowiki.com/page/Saving_throw "Saving throw") against [Magical Poisons](http://www.ddowiki.com/page/Poison "Poison") and do not fail saving throws against them on a roll of a natural 1 (this makes you immune to [Magical Poisons](http://www.ddowiki.com/page/Poison "Poison") with a DC of less than 11+your [Fortitude](http://www.ddowiki.com/page/Fortitude "Fortitude") save). If you transform into a different type of creature, you will lose these benefits until you are return to your Warforged form. | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | + +## Purchasable + +| [ ][availableFeats] [Feats][result] | Description | Type | Prerequisites | Icon | +| -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | +| [Adamantine Body](http://www.ddowiki.com/page/Adamantine_Body "Adamantine Body") | This plating is counted as a [heavy armor](http://www.ddowiki.com/page/Category:Heavy_armor "Category:Heavy armor"). It grants a +8 [armor bonus](http://www.ddowiki.com/page/Armor_bonus "Armor bonus") to [Armor Class](http://www.ddowiki.com/page/Armor_Class "Armor Class") and a [damage reduction](http://www.ddowiki.com/page/Damage_reduction "Damage reduction") bonus of 2/[adamantine](http://www.ddowiki.com/page/Adamantine "Adamantine"). The character also incurs a 35% chance for [arcane spell failure](http://www.ddowiki.com/page/Arcane_spell_failure "Arcane spell failure"), a -5 [armor check penalty](http://www.ddowiki.com/page/Armor_check_penalty "Armor check penalty"), and a +1 maximum [dexterity bonus](http://www.ddowiki.com/page/Dexterity_bonus "Dexterity bonus"). | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Improved Damage Reduction](http://www.ddowiki.com/page/Improved_Damage_Reduction "Improved Damage Reduction") | Warforged gain [damage reduction](http://www.ddowiki.com/page/Damage_reduction "Damage reduction") 1/adamantine, or improves the characters existing [damage reduction](http://www.ddowiki.com/page/Damage_reduction "Damage reduction") by 1/adamantine. | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Improved Fortification](http://www.ddowiki.com/page/Improved_Fortification "Improved Fortification") | Improves the Warforged fortifications. It gains immunity to [Sneak Attacks](http://www.ddowiki.com/page/Sneak_Attack "Sneak Attack") and extra damage from [critical hits](http://www.ddowiki.com/page/Critical_hit "Critical hit"). This [Feat](http://www.ddowiki.com/page/Feat "Feat") will cause the character to lose the ability to be healed by spells such as [Cure Light Wounds](http://www.ddowiki.com/page/Cure_Light_Wounds "Cure Light Wounds"). | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged")
[Base Attack Bonus](http://www.ddowiki.com/page/Base_Attack_Bonus "Base Attack Bonus") +6 | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Mithral Body](http://www.ddowiki.com/page/Mithral_Body "Mithral Body") | This plating is counted as a [light armor](http://www.ddowiki.com/page/Category:Light_armor "Category:Light armor") and grants a +5 bonus to [Armor Class](http://www.ddowiki.com/page/Armor_Class "Armor Class"). It also incurs a 15% [arcane spell failure](http://www.ddowiki.com/page/Arcane_spell_failure "Arcane spell failure"), a -1 [armor check penalty](http://www.ddowiki.com/page/Armor_check_penalty "Armor check penalty"), and has a +5 maximum [dexterity bonus](http://www.ddowiki.com/page/Dexterity_bonus "Dexterity bonus"). | Passive | [Warforged](http://www.ddowiki.com/page/Warforged "Warforged"), [Bladeforged](http://www.ddowiki.com/page/Bladeforged "Bladeforged") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | +| [Mithral Fluidity](http://www.ddowiki.com/page/Mithral_Fluidity "Mithral Fluidity") | [Maximum dexterity bonus](http://www.ddowiki.com/page/Maximum_dexterity_bonus "Maximum dexterity bonus") from [mithral body](http://www.ddowiki.com/page/Mithral_Body "Mithral Body") plating is increase by 1 and it decreases the [armor check penalties](http://www.ddowiki.com/page/Armor_check_penalty "Armor check penalty") by 1. | Passive | [Mithral Body](http://www.ddowiki.com/page/Mithral_Body "Mithral Body") | ![Icon Feat Composite Plating.png](/images/Icon_Feat_Composite_Plating.png) | + +[light_fort]: http://www.ddowiki.com/page/Light_Fortification_%28feat%29 "Light Fortification (feat)" +[grantedFeats]: - "c:verify-rows=#feat:verifyGrantedFeats()" +[availableFeats]: - "c:verify-rows=#feat:verifyAvailableFeats()" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[result]: - "?=#feat" +[elf_feat]: http://www.ddowiki.com/edit/Elf_(feat)?redlink=1 "Elf (feat) (page does not exist)" +[elf_race]: http://www.ddowiki.com/page/Elf "Elf" +[sunelf_race]: http://www.ddowiki.com/page/Sun_Elf_(Morninglord) "Sun Elf (Morninglord)" + +![Attribution-ShareAlike 2.5](/images/somerights20.png) +[Attribution-ShareAlike 2.5](https://creativecommons.org/licenses/by-sa/2.5/) Images and general information available +from http://ddowiki.com diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/races/Races.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/races/Races.md new file mode 100644 index 00000000..0b89bd8f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/races/Races.md @@ -0,0 +1,3 @@ +# Races + +The playable races diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/skill/SkillSpec.md b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/skill/SkillSpec.md new file mode 100644 index 00000000..00e210ee --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/skill/SkillSpec.md @@ -0,0 +1,30 @@ +# Skill + +[Skills](http://ddowiki.com/page/Skills "DDO Wiki: Skills") are abilities that characters can use to accomplish or +enhance something. + +In this context, we encapsulate all supported skills here. + +## [Known Skills](- "#value=values") + +[-](- "ext:embed=prettyPrint()") + +### [Example](- "Search") + +Searching for [Balance](- "#searchString") will return: + +| [ ][search] [Matching Skills][match] | +| ------------------------------------ | +| Balance | + +[search]: - "c:verify-rows=#username:withNameAsList(#searchString)" +[_matchStrategy_]: - "c:matchStrategy=KeyMatch" +[match]: - "?=#username" + +Skills can be searched with many case options. + +- Case sensitive (default) +- Case insensitive +- Uppercase +- Lowercase +- Snake / Camel case diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/acceptanceTests/AcceptanceTests.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/acceptanceTests/AcceptanceTests.scala new file mode 100644 index 00000000..4a693c2b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/acceptanceTests/AcceptanceTests.scala @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package acceptanceTests + +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +//@Extensions(Array(classOf[EmbedExtension], classOf[CollapseOutputExtension])) +@RunWith(classOf[ConcordionRunner]) +//@ConcordionOptions( +// declareNamespaces = Array("ext", "urn:concordion-extensions:2010"), +// markdownExtensions = Array(MarkdownExtensions.WIKILINKS, +// MarkdownExtensions.AUTOLINKS, +// MarkdownExtensions.TASKLISTITEMS) +//) +class AcceptanceTests diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/Index.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/Index.scala new file mode 100644 index 00000000..f856355b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/Index.scala @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io + +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class Index {} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/DisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/DisplayHelper.scala new file mode 100644 index 00000000..722b57d1 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/DisplayHelper.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model + +import enumeratum.{Enum, EnumEntry} +import io.truthencode.ddo.support.naming.DisplayProperties + +trait DisplayHelper { + type Entry = EnumEntry with DisplayProperties + type E = Enum[_ <: Entry] + + val displayEnum: E +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/Model.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/Model.scala new file mode 100644 index 00000000..eb868f1d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/Model.scala @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model + +import io.truthencode.ddo.testoptions.DefaultFlexmark +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class Model extends DefaultFlexmark diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/AlignmentsSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/AlignmentsSpec.scala new file mode 100644 index 00000000..bc1c4593 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/AlignmentsSpec.scala @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.alignment + +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class AlignmentsSpec diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/LawAxisSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/LawAxisSpec.scala new file mode 100644 index 00000000..b6ef6d91 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/LawAxisSpec.scala @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.alignment + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.support.ConcordionEnumBuilderSupport +import org.concordion.api.FullOGNL +// import org.concordion.ext.EmbedExtension +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +@FullOGNL +// @Extensions(Array(classOf[EmbedExtension])) +class LawAxisSpec extends LazyLogging { + + val helper: ConcordionEnumBuilderSupport = new ConcordionEnumBuilderSupport { + override def actual: Seq[String] = LawAxis.values.map(_.toString) + } + + val rows: scala.collection.mutable.SortedSet[String] = scala.collection.mutable.TreeSet.empty + + def setUpRow(value: String): Unit = { + rows += value + } + + def getCaseSensitive: String = "Values can be located / limited in a case-sensitive manner" + + def getCaseInSensitive: String = "Values can be located / limited in a case-insensitive manner" + + def getInvalidValues: String = "Invalid values should be handled gracefully" +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/MoralAxisSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/MoralAxisSpec.scala new file mode 100644 index 00000000..ad687840 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/alignment/MoralAxisSpec.scala @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.alignment + +import io.truthencode.ddo.support.ConcordionEnumBuilderSupport +import org.concordion.api.FullOGNL +//import org.concordion.ext.EmbedExtension +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +@FullOGNL +//@Extensions(Array(classOf[EmbedExtension])) +class MoralAxisSpec { + + val helper: ConcordionEnumBuilderSupport = new ConcordionEnumBuilderSupport { + override def actual: Seq[String] = MoralAxis.values.map(_.toString) + } + + val rows: scala.collection.mutable.SortedSet[String] = scala.collection.mutable.TreeSet.empty + + def setUpRow(value: String): Unit = { + rows += value + } + + def getCaseSensitive: String = "Values can be located / limited in a case-sensitive manner" + + def getCaseInSensitive: String = "Values can be located / limited in a case-insensitive manner" + + def getInvalidValues: String = "Invalid values should be handled gracefully" + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.java new file mode 100644 index 00000000..80016541 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ApothecaryEnhancementSpec.java @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class ApothecaryEnhancementSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public ApothecaryEnhancementSpec() { + this.setTreeId("Apothecary"); + } + +// @Override +// public String treeId() { +// return "Apothecary"; +// } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.java new file mode 100644 index 00000000..aa21ac05 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ArcanotechnicianSpec.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class ArcanotechnicianSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public ArcanotechnicianSpec() { + this.setTreeId("Apothecary"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.java new file mode 100644 index 00000000..18d08439 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BattleEngineerSpec.java @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class BattleEngineerSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public BattleEngineerSpec() { + + } + + @Override + public String treeId() { + return "Apothecary"; + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BombardierSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BombardierSpec.java new file mode 100644 index 00000000..37498da8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/BombardierSpec.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class BombardierSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public BombardierSpec() { + this.setTreeId("Bombardier"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelper.scala new file mode 100644 index 00000000..0aeb8298 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelper.scala @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.enhancement.enhancements.ClassEnhancement +import io.truthencode.ddo.model.enhancement.{ClassBasedEnhancements, Tier} +import io.truthencode.ddo.support.requisite.{ + ActionPointRequisite, + PointInTreeRequisite, + PointsAvailableRequisite, + RequiresActionPoints +} + +trait ClassEnhancementDisplayHelper extends EnhancementDisplayHelper with LazyLogging { + type ENH = ClassEnhancement with Tier with ActionPointRequisite with PointInTreeRequisite + lazy val mappedValues: Map[String, ClassEnhancementInfo] = { + + val ee = ClassEnhancement.values.collect { + case x: ClassEnhancement with Tier with ClassBasedEnhancements with PointInTreeRequisite with PointsAvailableRequisite with RequiresActionPoints + if x.tree == tree => + x + } + logger.info(s"Display Helper loaded ${ee.size} values for ${tree.displayText}") + ee.map { v => + logger.info(s"Loading enhancement with entry id: ${v.entryName} with key ${v.displayText}") + + // val c = ClassEnhancementInfo.apply(v.entryName,Some(v.displayText)) + val c = ClassEnhancementInfo.apply(v) + logger.info(s"Added using key ${c.name}") + c.name -> c + }.toMap + } + override val displayEnum: E = ClassEnhancement + val values: Seq[ENH] = displayEnum.values.collect { case x: ENH => x } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelperTest.scala.scalatest b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelperTest.scala.scalatest new file mode 100644 index 00000000..f4022193 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementDisplayHelperTest.scala.scalatest @@ -0,0 +1,113 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.enhancement.Tier +import io.truthencode.ddo.model.enhancement.enhancements.ClassEnhancement +import io.truthencode.ddo.support.StringUtils._ +import io.truthencode.ddo.support.requisite.{ActionPointRequisite, PointInTreeRequisite} +import io.truthencode.ddo.support.tree.ClassTrees +import org.scalatest.prop.ScalaCheckPropertyChecks +import org.scalatest.{FunSpec, Matchers} + +// @RunWith(classOf[JUnitRunner]) +class ClassEnhancementDisplayHelperTest + extends FunSpec + with Matchers + with ScalaCheckPropertyChecks + with LazyLogging { + describe("Mapped Values") { + it("should just work") { + type ENH = ClassEnhancement with Tier with ActionPointRequisite with PointInTreeRequisite + val values: Seq[ENH] = ClassEnhancement.values collect { case x: ENH => x } + val baseSize = ClassEnhancement.values.size + val tSite = values.size + val baseNames = ClassEnhancement.values.map(_.entryName) + val tNames = values.map(_.entryName) + baseNames.intersect(tNames).size shouldEqual (baseSize) + val enhancement = "Curative Admixture: Cure Serious Wounds" + val csw = ClassEnhancement.CurativeAdmixtureCureSeriousWounds + val cswName = csw.displayText + val cswId = cswName.toPascalCase.filterAlphaNumeric + + cswName shouldEqual enhancement + cswId shouldEqual (csw.entryName) + + implicit val identifier: String = cswId + val vs = values.filter(_.entryName.contains("Cure")) + noException shouldBe thrownBy { + val rslt = values.find(p => p.entryName.equals(identifier)) + + } +// noException shouldBe thrownBy { +// val r = values +// .map { e => +// e.entryName -> e.displayText +// } +// .map { t => +// t._2 -> CEnhancement(t._2)(t._1) +// } +// .toMap +// } + } + they("Should support ampersands") { + val e = ClassEnhancement.SpellCriticalChancePositiveAndNegativeI + val id = e.entryName + val dt = e.displayText + val expectedDisplay = "Spell Critical Chance: Positive & Negative I" + val expectedId = "SpellCriticalChancePositiveAndNegativeI" + dt.shouldEqual(expectedDisplay) + id.shouldEqual(expectedId) + } + + they("should support prefixes") { + val e = ClassEnhancement.SmokeBomb + val id = e.entryName + val dt = e.displayText + val expectedDisplay = "Spell-Like Ability: Smoke Bomb" + val expectedId = "SmokeBomb" + dt.shouldEqual(expectedDisplay) + id.shouldEqual(expectedId) + } + + they("should have values") { + val t = new ClassEnhancementDisplayHelper { + override val tree: ClassTrees = ClassTrees.Apothecary + + } + noException shouldBe thrownBy { t.mappedValues } + } + they("should support prefixes, affixes, Roman numerals and special symbols") { + val validCombos = + Table( + ("id", "display"), + ("RapidCondensation", "Spell-Like Ability: Rapid Condensation"), + ("EfficientMetamagicsII", "Efficient Metamagics II"), + ("Spell Critical: Elemental And Poison III".filterAlphaNumeric,"Spell Critical: Elemental and Poison III") + ) + + forAll(validCombos) { (n: String, d: String) => + ClassEnhancement.withNameOption(n) should be(defined) + ClassEnhancement.withNameOption(n) match { + case Some(value) => value.displayText shouldEqual(d) + } + } + } + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementInfo.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementInfo.scala new file mode 100644 index 00000000..5d1eebf8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/ClassEnhancementInfo.scala @@ -0,0 +1,174 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.enhancement.enhancements.ClassEnhancement +import io.truthencode.ddo.model.enhancement.{ClassBasedEnhancements, Tier} +import io.truthencode.ddo.support.StringUtils._ +import io.truthencode.ddo.support.requisite.{ + ActionPointRequisite, + PointInTreeRequisite, + PointsAvailableRequisite, + RequiresActionPoints +} + +trait ClassEnhancementInfo { + type ENH = ClassEnhancement with Tier with ActionPointRequisite with PointInTreeRequisite + val values: Seq[ENH] = ClassEnhancement.values.collect { case x: ENH => x } + val name: String + val actionPointCost: Int + val ranks: Int + val progression: Int + val requirements: Option[List[String]] + val description: String + + /** + * This should == ClassEnhancement.entryName + */ + def id: String +} + +object ClassEnhancementInfo extends LazyLogging { + +// scalastyle:off + def apply( + classEnhancement: ClassEnhancement + with Tier with ClassBasedEnhancements with PointInTreeRequisite with PointsAvailableRequisite + with RequiresActionPoints + ) = { + val e = classEnhancement + def id: String = e.entryName + val actionPointCost: Int = e.apCostPerRank + val ranks: Int = e.ranks + val key = e.displayText + val progression: Int = e.progressionInTree.find { p => + p._1 == e.tree + } match { + case Some(x) => x._3 + case _ => 0 + } // .flatMap{x => x._3} //.flatMap {p => p._3} + val requirements: Option[List[String]] = None + + val description: String = e.rawDescription + CEnhancementDumb(key, id, actionPointCost, ranks, progression, requirements, description) + } + + def apply(key: String, fullText: Option[String] = None): ClassEnhancementInfo = { + val srch = key.symbolsToWords.filterAlphaNumeric + logger.info(s"Searching $key using: $srch") + val eOpt = ClassEnhancement.withNameInsensitiveOption(srch) match { + case Some( + x: ClassEnhancement with Tier with ClassBasedEnhancements with PointInTreeRequisite with PointsAvailableRequisite with RequiresActionPoints + ) => + logger.info(s"Found ${x.displayText} => ${x.entryName}") + Some(x) + case _ => + fullText match { + case Some(y) => + logger.warn( + s"Failed to locate ClassEnhancement with key $key, attempting using fullText $fullText" + ) + ClassEnhancement.values.map { v => + v.displayText -> v.entryName + } + .find(_._1 == y) match { + case Some(value) => + logger.info(s"located valid key from fulltext, recursing using ${value._2}") + apply(value._2) + case None => + logger.warn("Could not locate $key") + None + } + case None => + logger.warn("could not locate with key $key and no alternate supplied") + None + } + None + } + if (eOpt.nonEmpty) { + val e = eOpt.get + logger.info(s"located ${e.displayText}") + + /** + * The string id used to create the object + */ + def id: String = e.entryName + val actionPointCost: Int = e.apCostPerRank + val ranks: Int = e.ranks + + val progression: Int = e.progressionInTree.find { p => + p._1 == e.tree + } match { + case Some(x) => x._3 + case _ => 0 + } // .flatMap{x => x._3} //.flatMap {p => p._3} + val requirements: Option[List[String]] = None + + val description: String = e.rawDescription + CEnhancementDumb(key, id, actionPointCost, ranks, progression, requirements, description) + } else { + logger.warn(s"did not locate id, using safe wrapper for $key") + CEnhancementDumb(key) + } + + } + // scalastyle:off number.of.methods +} + +case class CEnhancementDumb( + name: String, + id: String = "", + actionPointCost: Int = 0, + ranks: Int = 0, + progression: Int = 0, + requirements: Option[List[String]] = None, + description: String = "" +) extends ClassEnhancementInfo + +case class CEnhancement( + name: String +)(implicit identifier: String = name.toPascalCase.filterAlphaNumeric) + extends ClassEnhancementInfo with LazyLogging { + + override val actionPointCost: Int = enh.apCostPerRank + // require(_enh.nonEmpty,s"No value found matching Id $id") + override val ranks: Int = enh.ranks + override val progression: Int = enh.progressionInTree.find { p => + p._1 == enh.tree + } match { + case Some(x) => x._3 + case _ => 0 + } // .flatMap{x => x._3} //.flatMap {p => p._3} + override val requirements: Option[List[String]] = None + override val description: String = enh.rawDescription + private val enh: ENH = _enh.get + + private def _enh = { + logger.info(s"locating values with entryname eq $id") + val v = values.find(p => p.entryName.equals(identifier)) + logger.info(s"result ${v}") + v + } + + /** + * The string id used to create the object + */ + override def id: String = enh.entryName + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementDisplayHelper.scala new file mode 100644 index 00000000..e81aab41 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementDisplayHelper.scala @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements + +import io.truthencode.ddo.model.DisplayHelper +import io.truthencode.ddo.model.enhancement.Enhancement +import io.truthencode.ddo.support.tree.ClassTrees + +trait EnhancementDisplayHelper extends DisplayHelper { + override val displayEnum: E = Enhancement + def tree: ClassTrees +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementTree.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementTree.java new file mode 100644 index 00000000..599810a5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/EnhancementTree.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@RunWith(ConcordionRunner.class) +public class EnhancementTree { +// @ConcordionResources(value = {"../../../../../../resources/acceptanceTest/css/*.css","../../../../../../resources/acceptanceTest/images/*.png"},includeDefaultStyling = false,insertType = ConcordionResources.InsertType.EMBEDDED) + // ../../../../../../../resources/acceptanceTest/ +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/Enhancements.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/Enhancements.scala new file mode 100644 index 00000000..935a8fcf --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/Enhancements.scala @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements + +import io.truthencode.ddo.testoptions.DefaultFlexmark +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class Enhancements extends DefaultFlexmark {} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.java new file mode 100644 index 00000000..9352527b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/FrenziedBerserkerSpec.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class FrenziedBerserkerSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public FrenziedBerserkerSpec() { + setTreeId("FrenziedBerserker"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/JEnhancementDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/JEnhancementDisplayHelper.scala new file mode 100644 index 00000000..7cc93374 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/JEnhancementDisplayHelper.scala @@ -0,0 +1,123 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.enhancement.Tier +import io.truthencode.ddo.support.tree.ClassTrees + +import scala.beans.BeanProperty + +abstract class JEnhancementDisplayHelper extends ClassEnhancementDisplayHelper with LazyLogging { + + override lazy val tree: ClassTrees = ClassTrees.withName(treeId) + + /** + * Java Work-around to set + */ + @BeanProperty + var treeId: String = _ + @BeanProperty + var currentTier: String = _ + + @BeanProperty + var currentEnhancement: String = _ + + // [enhancement] | [Description][description] | [AP_Cost][apcost] | [Ranks][ranks] | [Progression][progression]| [Requirements][requirements]| + def tier: Tier = + Tier + .withNameOption(currentTier) + .getOrElse({ + logger.error( + s"Could not find a valid Tier using ID $currentTier defaulting to ${Tier.Core.entryName}" + ) + Tier.Core + }) + + def loadFromKey(enhancementId: String): ResultObject = { + val trimmed = enhancementId.trim + logger.info( + s"************* Attempting to load Enhancement ResultObject using key: [$trimmed]" + ) + // logger.info(s"mappvalues has ${mappedValues.size} elements") + val ce: ClassEnhancementInfo = + mappedValues.getOrElse( + trimmed, { + logger.warn(s"Failed to find Enhancement with id $enhancementId") + CEnhancementDumb(enhancementId) + }) + logger.debug(ce.toString) + implicit val altName: Option[String] = Some(enhancementId) + ResultObject.apply(ce) + + } + + sealed trait prefixes { + val text: String + val separator: String = ": " + + def prefix(value: Int): String = prefix(value.toString) + + def prefix(value: String): String = { + s"$text$separator$value" + } + } + + case class ResultObject( + enhancement: String, + description: String, + apcost: String, + ranks: String, + progression: String, + requirements: String + ) + + case object Prefix_AP extends prefixes { + override val text: String = "AP Cost" + } + + case object Prefix_Rank extends prefixes { + override val text: String = "Ranks" + } + + case object Prefix_Progression extends prefixes { + override val text: String = "Progression" + } + + case object Prefix_Requires extends prefixes { + override val text: String = "Requires" + } + + object ResultObject { + + def apply( + cc: ClassEnhancementInfo + )(implicit altNameText: Option[String] = None): ResultObject = { + ResultObject( + enhancement = altNameText.getOrElse(cc.name), + description = cc.description, + apcost = Prefix_AP.prefix(cc.actionPointCost), + ranks = Prefix_Rank.prefix(cc.ranks), + progression = Prefix_Progression.prefix(cc.progression), + requirements = Prefix_Requires.prefix("") + ) + + } + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.java new file mode 100644 index 00000000..12e5f62b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/OccultSlayerSpec.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class OccultSlayerSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public OccultSlayerSpec() { + setTreeId("OccultSlayer"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RavagerSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RavagerSpec.java new file mode 100644 index 00000000..41ae57f2 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RavagerSpec.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class RavagerSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public RavagerSpec() { + setTreeId("Ravager"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.java new file mode 100644 index 00000000..2bb2ff7d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/RenegadeMastermakerSpec.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class RenegadeMastermakerSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public RenegadeMastermakerSpec() { + setTreeId("RenegateMastermaker"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/VileChemistSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/VileChemistSpec.java new file mode 100644 index 00000000..3d5bfa61 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/enhancements/VileChemistSpec.java @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.enhancements; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.Ignore; +import org.junit.runner.RunWith; + + +@FullOGNL +@Ignore +@RunWith(ConcordionRunner.class) +public class VileChemistSpec extends JEnhancementDisplayHelper { + // override val tree: ClassTrees = ClassTrees.Apothecary + public VileChemistSpec() { + setTreeId("VileChemist"); + } + + public String setUpTier(String TEXT) { + setCurrentTier(TEXT); + return getCurrentTier(); + } + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/BonusFeatTest.scala.scalatest b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/BonusFeatTest.scala.scalatest new file mode 100644 index 00000000..513386a9 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/BonusFeatTest.scala.scalatest @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import org.junit.runner.RunWith +import org.scalatest.{FunSpec, Matchers} +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class BonusFeatTest extends FunSpec with Matchers { + val helper = new ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Monk + + override val enum: E = Feat + } + + describe("Helper Class Feat Selection") { + it("should retrieve bonus feats based on class") { + val values = helper.enum.values collect helper.filterByClassBonusFeat + values shouldNot be(empty) + } + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassDisplayBonusFeatTest.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassDisplayBonusFeatTest.scala new file mode 100644 index 00000000..6632ea6f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassDisplayBonusFeatTest.scala @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +class ClassDisplayBonusFeatTest diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassFeatDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassFeatDisplayHelper.scala new file mode 100644 index 00000000..c4eb07d2 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ClassFeatDisplayHelper.scala @@ -0,0 +1,162 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.support.requisite.{ClassRequisite, SelectableToClass} + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +/** + * Created by Adarro on 3/5/2017. + */ +trait ClassFeatDisplayHelper extends FeatDisplayHelper with LazyLogging { + + type FNLevel = Entry => Seq[(HeroicCharacterClass, Int)] + type FNClass = Entry => Seq[HeroicCharacterClass] + lazy val classFeatByLevelMap: Seq[(String, Seq[Int])] = { + val levels = for { + f <- displayEnum.values + e <- allTypesByLevelFilter(f) + } yield f.displayText -> e + levels + .groupBy(_._1) + .map { x => + (x._1, x._2.map(_._2)) + } + .to(Seq) + } + lazy val grantedFeats: util.List[String] = { + val values = { displayEnum.values.collect(filterByGrantedTo) }.collect(filterByMainFeat) + values.map(_.displayText).sorted.asJava + } + val cClass: HeroicCharacterClass +// Currently no sub-feats with Class based restrictions? + val filterByAllOf: PartialFunction[Entry, Entry] = { + case x: ClassRequisite if x.allOfClass.exists(isDefinedForClass(_)) => x + } + + val filterByAnyOf: PartialFunction[Entry, Entry] = { + case x: ClassRequisite if x.anyOfClass.exists(isDefinedForClass(_)) => x + } + + val filterByGrantedTo: PartialFunction[Entry, Entry] = { + case x: ClassRequisite if x.grantToClass.exists(isDefinedForClass(_)) => x + } + + val filterByGrantedToByLevel: PartialFunction[(Entry, Int), (Entry, Int)] = { + case (x: ClassRequisite, y) if x.grantToClass.exists(isDefinedForClass(_, Some(y))) => + (x, y) + } + + val filterByClassBonusFeat: PartialFunction[Entry, Entry] = { + case x: BonusSelectableFeat with SubFeatInformation + if x.bonusCharacterClass.contains(cClass) && !x.isSubFeat => + lazy val msg = s"Entry ${x.displayText} matched type and character class $cClass" + lazy val idInfo = Map( + "entryName" -> x.entryName, + "displaySource" -> x.displaySource, + "displayText" -> x.displayText + ) + logger.debug(msg) + if (x.displayText.contains("Construct")) { + logger.debug(s"Id Info $idInfo") + } + x + } + + val filterByClassBonusFeatByLevel: PartialFunction[(Entry, Int), (Entry, Int)] = { + case (x: SelectableToClass with SubFeatInformation, y) + if x.bonusSelectableToClass.exists(isDefinedForClass(_, Some(y))) && !x.isSubFeat => + (x, y) + } + + val existing: PartialFunction[Entry, Entry] = + filterByAllOf.orElse(filterByAnyOf).orElse(filterByGrantedTo) + + def isDefinedForClass(e: (HeroicCharacterClass, Int), level: Option[Int] = None): Boolean = + e._1.eq(cClass) && isEqualOrEmpty(e._2, level) + + private def isEqualOrEmpty(i: Int, source: Option[Int]): Boolean = + source.isEmpty || (source.nonEmpty && source.contains(i)) + + def allTypesByLevelFilter(as: Entry): Seq[Int] = + extractLevels(as, allOfFilterByLevel, anyOfFilterByLevel, grantToFilterByLevel) + .map(_._2) + + def allOfFilterByLevel(as: Entry): Seq[(HeroicCharacterClass, Int)] = as match { + case x: ClassRequisite => x.allOfClass.filter(_._1.eq(cClass)) + } + + def anyOfFilterByLevel(as: Entry): Seq[(HeroicCharacterClass, Int)] = as match { + case x: ClassRequisite => x.anyOfClass.filter(_._1.eq(cClass)) + } + + def grantToFilterByLevel(as: Entry): Seq[(HeroicCharacterClass, Int)] = as match { + case x: ClassRequisite => x.grantToClass.filter(_._1.eq(cClass)) + } + + def extractLevels(as: Entry, fn: FNLevel*): Seq[(HeroicCharacterClass, Int)] = + fn.flatMap(f => f(as)) + + def grantedFeatsByLevel(level: Int): util.List[String] = { + val values = displayEnum.values.map((_, level)).collect(filterByGrantedToByLevel) + values + // .filterNot(_._1.isSubFeat) + .filter(_._2 == level) + .map(_._1.displayText) + .sorted + .asJava + } + + def bonusFeatsByLevel(level: Int): util.List[String] = { + val values = displayEnum.values.map((_, level)).collect(filterByClassBonusFeatByLevel) + values + .filter(_._2 == level) + .map(_._1.displayText) + .sorted + .asJava + } + + /** + * Retrieves Display Text for bonus feats as a Java List. (Use of parenthesis needed when calling + * from Java (concordion) + * + * @return + * List of Bonus Feat Names for the specific class sorted in Alpha ascending order. + */ + def bonusFeats(): util.List[String] = { + val values = displayEnum.values.collect(filterByClassBonusFeat) + values.map(_.displayText).sorted.asJava + } + + def classByLevel(level: Int): util.List[String] = + classFeatByLevelMap.filter { p => + p._2.contains(level) + } + .map(_._1) + .sortWith(_ < _) + .asJava + + case class Param(e: Entry with ClassRequisite, l: Int) + + case class Param2(e: Entry with MartialArtsFeat, l: Int) + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ConcordionResourcesBundleSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ConcordionResourcesBundleSpec.scala new file mode 100644 index 00000000..1d75e440 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ConcordionResourcesBundleSpec.scala @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import org.concordion.api.ConcordionResources +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +/** + * Created by adarr on 2/19/2017. + */ +@ConcordionResources(Array("/images/*.png", "resources/*.png")) +@RunWith(classOf[ConcordionRunner]) +trait ConcordionResourcesBundleSpec diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/DragonmarkFeatDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/DragonmarkFeatDisplayHelper.scala new file mode 100644 index 00000000..f929588e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/DragonmarkFeatDisplayHelper.scala @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +/** + * Created by adarr on 3/26/2017. + */ +trait DragonmarkFeatDisplayHelper extends FeatDisplayHelper { + override val displayEnum: E = DragonmarkFeat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/EpicFeatFeatDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/EpicFeatFeatDisplayHelper.scala new file mode 100644 index 00000000..6d3a7527 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/EpicFeatFeatDisplayHelper.scala @@ -0,0 +1,37 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +/** + * Verifies basic creation of Epic Feats, categorized as per + * [[http://ddowiki.com/page/Epic_Feats ddo Epic Feats]]. + */ +trait EpicFeatFeatDisplayHelper extends FeatDisplayHelper { + + final override val displayEnum: E = Feat + // val categoryFilter: EpicFeatCategory + + val filterByCategory: PartialFunction[Entry, Entry] + + override def verify(): util.List[String] = { + val v = displayEnum.values.collect(filterByCategory) + v.map(_.displayText).asJava + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/FeatDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/FeatDisplayHelper.scala new file mode 100644 index 00000000..9f8a849b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/FeatDisplayHelper.scala @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import io.truthencode.ddo.model.DisplayHelper + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +/** + * Created by adarr on 2/17/2017. Adds convenience and display functions for Concordion Acceptance + * testing against Feats in various contexts. + */ +trait FeatDisplayHelper extends DisplayHelper { + + /** + * Removes Sub-Feats such as Weapon Proficiencies + */ + val filterByMainFeat: PartialFunction[Entry, Entry] = { + case x: Feat with SubFeatInformation if !x.isSubFeat => x + } + + def prettyPrint(): String = { + listValues("Current Supported Feats", collapse = true) + } + + def listValues(heading: String, collapse: Boolean = false): String = { + + val data = displayEnum.values.map { a => + s"${a.displayText}" + }.sorted.mkString + val header = s"" + val footer = "
$heading
" + val table = s"$header$data$footer" + if (collapse) { + s"""
$table
""" + } else { + table + } + } + + def verify(): util.List[String] = { displayEnum.values.collect(filterByMainFeat) }.map { x => + x.displayText + }.toList.sorted.asJava + + def withNameAsJavaList(id: String): util.List[String] = withNameAsList(id).asJava + + def withNameAsList(skillId: String*): Seq[String] = { + for { + id <- skillId + skill <- withName(id) + } yield skill.displayText + } + + protected def withName(skillId: String): Option[Entry] = + displayEnum.withNameOption(skillId) + + def findByName(skillId: String): String = { + withNameAsList(skillId).headOption.orNull + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/Feats.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/Feats.scala new file mode 100644 index 00000000..e95e0543 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/Feats.scala @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class Feats diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatRelatedFixture.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatRelatedFixture.scala new file mode 100644 index 00000000..0c0812f6 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatRelatedFixture.scala @@ -0,0 +1,40 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import org.concordion.api.FullOGNL +import org.concordion.api.option.{ConcordionOptions, MarkdownExtensions} +//import org.concordion.ext.EmbedExtension +//import org.concordion.ext.collapse.CollapseOutputExtension +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +//@FullOGNL +////@Extensions(Array(classOf[EmbedExtension], classOf[CollapseOutputExtension])) +//@ConcordionOptions( +// declareNamespaces = Array("ext", "urn:concordion-extensions:2010"), +// markdownExtensions = Array( +// MarkdownExtensions.WIKILINKS, +// MarkdownExtensions.AUTOLINKS, +// MarkdownExtensions.TASKLISTITEMS) +//) +//@RunWith(classOf[ConcordionRunner]) +class GeneralFeatRelatedFixture extends FeatDisplayHelper { + val displayEnum: E = GeneralFeat + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatsSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatsSpec.java new file mode 100644 index 00000000..a29b946b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/GeneralFeatsSpec.java @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats; + +import org.concordion.api.FullOGNL; +import org.concordion.api.option.ConcordionOptions; +import org.concordion.api.option.MarkdownExtensions; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@FullOGNL +//@Extensions(Array(classOf[EmbedExtension], classOf[CollapseOutputExtension])) +@ConcordionOptions( + declareNamespaces = {"ext", "urn:concordion-extensions:2010"}, + markdownExtensions = { + MarkdownExtensions.WIKILINKS, + MarkdownExtensions.AUTOLINKS, + MarkdownExtensions.TASKLISTITEMS}) +@RunWith(ConcordionRunner.class) +public class GeneralFeatsSpec extends GeneralFeatRelatedFixture { +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/IndividualFeatFixture.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/IndividualFeatFixture.scala new file mode 100644 index 00000000..c7d4cd1c --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/IndividualFeatFixture.scala @@ -0,0 +1,83 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.DisplayHelper +import io.truthencode.ddo.model.feats.classes.ChargeSupport +import io.truthencode.ddo.support.charges.Chargeable +import io.truthencode.ddo.support.requisite._ + +import java.util +import scala.beans.BeanProperty +import scala.jdk.CollectionConverters._ + +class IndividualFeatFixture extends DisplayHelper with ChargeSupport with LazyLogging { + override val displayEnum: E = Feat + @BeanProperty + var feat: String = _ + + def setFeatId(id: String): Unit = { + feat = id + } + type F = E with FeatType with Requisite with Inclusion + def valueWithRequirements: Seq[ValueWithRequirements] = + displayEnum.withNameInsensitiveOption(feat) match { + case Some(f) => + f match { + case x: RequisiteExpression with RequisiteType with Inclusion => + x.prerequisites.map { pr => + ValueWithRequirements(x, pr.reqType, pr.incl, pr.groupKey, pr.req) + } + } + case None => Nil + } + + lazy val sortish: SemiOrderedRequirements = SemiOrderedRequirements(valueWithRequirements: _*) + def verifyPrerequisites(): util.Collection[String] = { + sortish.displayPrerequisites.asJavaCollection + } + + def verifyBonusSelections(): util.Collection[String] = { + sortish.displayBonusSelections.asJavaCollection + } + + def verifyGrantSelections(): util.Collection[String] = { + sortish.displayGranted.asJavaCollection + } + + case class FeatResult(id: String) { + val f = Feat.withName(id) + val active: String = f match { + case x: ActiveFeat => "Active" + case _ => "Passive" + } + } + def fr: FeatResult = FeatResult(feat) + def isActive: String = fr.active + + def javaSafeChargeInfo(): ChargeInfo = { + fr.f match { + case x: Chargeable => readChargeInfo(x) + case _ => + logger.warn("failed to get charge info") + null + } + + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ManyShotSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ManyShotSpec.java new file mode 100644 index 00000000..1185c283 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/ManyShotSpec.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class ManyShotSpec extends IndividualFeatFixture { + + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.java new file mode 100644 index 00000000..0b493b48 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/MartialArtsFeatSpec.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats; + +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@RunWith(ConcordionRunner.class) +public class MartialArtsFeatSpec { + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/RaceSupport.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/RaceSupport.scala new file mode 100644 index 00000000..c8592e2a --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/RaceSupport.scala @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.race.Race +import io.truthencode.ddo.support.requisite.RequirementOption + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +/** + * Created by adarr on 2/19/2017. + */ +trait RaceSupport extends LazyLogging { + val raceId: Race + implicit class Util(source: Seq[Feat]) { + def toJava: util.List[String] = { + source.map(_.displayText).toList.sorted.asJava + } + } + + def verifyGrantedFeats: util.List[String] = { + val f = Feat + .featsFromRace(raceId, RequirementOption.AutoGrant) + .toJava + + logger.info(s"verify ${RequirementOption.AutoGrant.entryName} racial feats located ${f + .size()} values for Race $raceId ") + logger.debug(s"values: $f") + f + } + + def verifyAvailableFeats: util.List[String] = { + val f = Feat + .featsFromRace(raceId, RequirementOption.Available) + .toJava + + logger.info(s"verify ${RequirementOption.Available.entryName} racial feats located ${f + .size()} values for Race $raceId ") + logger.debug(s"values: $f") + f + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatFeatDisplayHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatFeatDisplayHelper.scala new file mode 100644 index 00000000..e88618dc --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatFeatDisplayHelper.scala @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats + +import com.typesafe.scalalogging.LazyLogging + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +trait TacticalFeatFeatDisplayHelper extends FeatDisplayHelper with LazyLogging { + override val displayEnum: E = Feat +} + +abstract class TacticalFeatFeatDisplayHelperJava extends TacticalFeatFeatDisplayHelper { + type S = Feat with Tactical + + val filterByTactical: PartialFunction[Entry, Entry] = { case x: Tactical => + x + } + + def tacticalFeats: util.List[Entry] = { displayEnum.values.collect(filterByTactical) } + .sortBy(_.entryName) + .asJava +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatSpec.java new file mode 100644 index 00000000..159d469c --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/TacticalFeatSpec.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats; + +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@RunWith(ConcordionRunner.class) +public class TacticalFeatSpec extends TacticalFeatFeatDisplayHelperJava { + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.scala new file mode 100644 index 00000000..c8db6b6f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/AlchemistClassFeatSpec.scala @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class AlchemistClassFeatSpec extends ClassFeatDisplayHelper { + override val displayEnum: E = Feat + + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Alchemist + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.scala new file mode 100644 index 00000000..070340ac --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ArtificerClassFeatSpec.scala @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class ArtificerClassFeatSpec extends ClassFeatDisplayHelper { + override val displayEnum: E = Feat + + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Artificer + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.scala new file mode 100644 index 00000000..166a4b4d --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BarbarianClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class BarbarianClassFeatSpec extends ClassFeatDisplayHelper { + override val displayEnum: E = Feat + + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Barbarian +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.scala new file mode 100644 index 00000000..676504d3 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/BardClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class BardClassFeatSpec extends ClassFeatDisplayHelper { + override val displayEnum: E = Feat + + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Bard +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ChargeSupport.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ChargeSupport.scala new file mode 100644 index 00000000..5b30334b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ChargeSupport.scala @@ -0,0 +1,68 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.DisplayHelper +import io.truthencode.ddo.support.charges.Interval.OnTimer +import io.truthencode.ddo.support.charges.{Chargeable, Rechargeable} + +import java.time.Duration +import java.util.Optional +import scala.beans.BeanProperty +import scala.jdk.OptionConverters._ + +/** + * Helper classs to test Entities with Charges + */ +trait ChargeSupport { + self: DisplayHelper => + case class ChargeInfo( + @BeanProperty var maxCharges: Int, + @BeanProperty var quantity: java.util.OptionalInt, + @BeanProperty var interval: Optional[Duration]) { + var safeInterval: Long = interval.toScala match { + case Some(x) => x.toSeconds + case None => -99L + } + } + def readChargeInfo[T <: Chargeable](s: T): ChargeInfo = { + val resultMaxCharges = s.charges.maxCharges + + val rechargeable = s.charges match { + case x: Rechargeable => Some(x) + case _ => None + } + val d = rechargeable.flatMap { s => + (s.rechargeType match { + case Left(x) => x.apply() + case Right(x) => x + }) match { + case OnTimer(x) => Some(x) + } + } + val q = rechargeable match { + case Some(x) => x.quantity + case _ => None + } + val resultTimeValue = + if (d.isDefined) { Some(d.get.toSeconds) } + else { None } + ChargeInfo(resultMaxCharges, q.toJavaPrimitive, d.toJava) + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClassFeats.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClassFeats.scala new file mode 100644 index 00000000..eb2d4088 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClassFeats.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.feats.{ClassFeat, FeatDisplayHelper} +import io.truthencode.ddo.testoptions.DefaultFlexmark +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class Classes extends FeatDisplayHelper with DefaultFlexmark { + override val displayEnum: E = ClassFeat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.scala new file mode 100644 index 00000000..1936326e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/ClericClassFeatSpec.scala @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class ClericClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Cleric + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.scala new file mode 100644 index 00000000..bbd0a898 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/DruidClassFeatSpec.scala @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class DruidClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = HeroicCharacterClass.Druid + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.scala new file mode 100644 index 00000000..25ffc582 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FavoredSoulClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.FavoredSoul +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class FavoredSoulClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = FavoredSoul + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.scala new file mode 100644 index 00000000..7e14d67b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/FighterClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Fighter +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class FighterClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Fighter + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.java b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.java new file mode 100644 index 00000000..ce020992 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkClassFeatSpec.java @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes; + +import org.concordion.api.FullOGNL; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; + +@FullOGNL +@RunWith(ConcordionRunner.class) +public class MonkClassFeatSpec extends MonkJavaHelperFeat { + // This wrapper class is no longer needed. +// MonkJavaHelper helper = new MonkJavaHelper() { +// @Override +// public CharacterClass cClass() { +// return super.cClass(); +// } +// }; +// public List grantedFeatsByLevel(Integer level) { +// return helper.grantedFeatsByLevel(level); +// } +// +// public List Simple() { +// return java.util.Arrays.asList("Simple"); //helper.grantedFeatsByLevel(level); +// } +// +// public List filterByClassBonusFeat() { +// return java.util.Arrays.asList("Simple"); //helper.grantedFeatsByLevel(level); +// } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkJavaHelperFeat.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkJavaHelperFeat.scala new file mode 100644 index 00000000..dce7cc38 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/MonkJavaHelperFeat.scala @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Monk +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} + +import java.util + +abstract class MonkJavaHelperFeat extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Monk + override val displayEnum: E = Feat + def allBonusFeats(): util.List[String] = bonusFeats() + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.scala new file mode 100644 index 00000000..0d83f46e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/PaladinClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Paladin +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class PaladinClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Paladin + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.scala new file mode 100644 index 00000000..2e29e628 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RangerClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Ranger +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class RangerClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Ranger + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.scala new file mode 100644 index 00000000..c72a1733 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/RogueClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Rogue +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class RogueClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Rogue + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.scala new file mode 100644 index 00000000..00f8cf37 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/SorcererClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Sorcerer +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class SorcererClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Sorcerer + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.scala new file mode 100644 index 00000000..123e4452 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WarlockClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Warlock +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class WarlockClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Warlock + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.scala new file mode 100644 index 00000000..ec8f55a7 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/classes/WizardClassFeatSpec.scala @@ -0,0 +1,32 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.classes + +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.classes.HeroicCharacterClass.Wizard +import io.truthencode.ddo.model.feats.{ClassFeatDisplayHelper, Feat} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class WizardClassFeatSpec extends ClassFeatDisplayHelper { + override val cClass: HeroicCharacterClass = Wizard + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.scala new file mode 100644 index 00000000..41252a61 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/deity/DeityFeatSpec.scala @@ -0,0 +1,155 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.deity + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.feats._ +import io.truthencode.ddo.model.item.weapon.FavoredWeapon +import io.truthencode.ddo.model.religions.Religion +import io.truthencode.ddo.model.worlds.World +import io.truthencode.ddo.support.StringUtils.Extensions +import io.truthencode.ddo.support.naming.{DisplayName, Prefix} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +import java.util +import scala.collection.immutable +import scala.jdk.CollectionConverters.SeqHasAsJava + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class DeityFeatSpec extends FeatDisplayHelper with LazyLogging { + + override val displayEnum: E = Feat + private val filterEberron: PartialFunction[Entry, Entry with ReligionFeatBase] = { + case x: EberronReligionBase with ReligionFeatBase => x + } + private val filterForgottenRealms: PartialFunction[Entry, Entry with ReligionFeatBase] = { + case x: ForgottenRealmsReligionBase with ReligionFeatBase => x + } + private val filterFollower: PartialFunction[Entry, Entry] = { case x: FollowerOfLevel => + x + } + private val filterChild: PartialFunction[Entry, Entry] = { case x: ChildOfLevel => + x + } + private val filterBeloved: PartialFunction[Entry, Entry] = { case x: BelovedOfLevel => + x + } + private val filterUnique: PartialFunction[Entry, Entry] = { case x: UniqueLevel => + x + } + private val filterDR: PartialFunction[Entry, Entry with DisplayName with Prefix] = { + case x: DamageReductionLevel with DisplayName with Prefix => x + } + + implicit class ListEntryOpts(source: Option[Entry]) { + def firstStringValue: String = { + source match { + case Some(x) => x.displayText + case _ => "" + } + } + } + private val filterFavoredWeapons: PartialFunction[Entry, Entry with FavoredWeapon] = { + case x: FavoredWeapon => + x + } + var instanceWorld: Option[World] = None + + override def verify(): util.List[String] = { + displayEnum.values.map(_.displayText).asJava + } + + def setUpWorld(TEXT: String): Unit = { + instanceWorld = World.withNameOption(TEXT.toPascalCase) + } + + def loadFromKey(data: String): ResultObject = { + val dataS = data.trim().toPascalCase + logger.debug(s"Attempting to find religion $dataS for world $instanceWorld") + val worldReligion: immutable.Seq[Entry with ReligionFeatBase] = + instanceWorld match { + case Some(World.Eberron) => displayEnum.values.collect(filterEberron) + case Some(World.ForgottenRealms) => + displayEnum.values.collect(filterForgottenRealms) + case _ => Nil + } + logger.debug(s"Located ${worldReligion.size} matching world religion feats for $instanceWorld") + val oRel: Option[Religion] = findReligion(dataS) + logger.debug(s"Religion $oRel") + + val f = myFilter(worldReligion.toList, oRel) + logger.debug(s"Located ${f.size} matching feats for $dataS $f") + + val fw: String = oRel match { + case Some(x: FavoredWeapon) => x.favoredWeapon.displayText + } + + val follower = f.collectFirst(filterFollower).firstStringValue + val beloved = f.collectFirst(filterBeloved).firstStringValue + val child = f.collectFirst(filterChild).firstStringValue + val unique = f.collectFirst(filterUnique).firstStringValue + val drFeats = f.collect(filterDR) + val k = for { + x <- drFeats + p <- x.withPrefix + } yield x.displaySource.replace(p, "") + logger.debug(s"DR Feats $drFeats") + logger.debug(s"DR Feats (Mapped) $k") + val prefix = "Damage Reduction: " + val dr: String = if (k.nonEmpty) { + k.sorted.mkString(start = prefix, sep = ", ", end = "") + } else { + s"$prefix TBD" + } + val result = ResultObject( + religion = data, + follow = follower, + favoredWeapon = fw, + child = child, + unique = unique, + beloved = beloved, + damageReduction = dr) + logger.debug(s"Result: $result") + result + + } + + def findReligion(id: String): Option[Religion] = Religion.withNameOption(id) + + def myFilter(f: List[Entry with ReligionFeatBase], rOpt: Option[Religion]): List[Entry] = { + for { + x <- f + o <- x.allowedReligions + if rOpt.contains(o) + } yield x + } + + case class ReligionWeapon(r: FavoredWeapon, re: Religion) + + case class ResultObject( + religion: String, + favoredWeapon: String, + follow: String, + child: String, + unique: String, + beloved: String, + damageReduction: String) +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.scala new file mode 100644 index 00000000..f62ec868 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/dragonmarks/DragonmarksFeatSpec.scala @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.dragonmarks + +import io.truthencode.ddo.model.feats.DragonmarkFeatDisplayHelper +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class DragonmarksFeatSpec extends DragonmarkFeatDisplayHelper diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/Epic.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/Epic.scala new file mode 100644 index 00000000..98356217 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/Epic.scala @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import io.truthencode.ddo.model.feats.{Feat, FeatDisplayHelper} +import io.truthencode.ddo.testoptions.DefaultFlexmark +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class Epic extends FeatDisplayHelper with DefaultFlexmark { + override val displayEnum: E = Feat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.scala new file mode 100644 index 00000000..5f02de25 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicActiveSpellFeatSpec.scala @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import io.truthencode.ddo.model.feats.{EpicFeat, EpicFeatFeatDisplayHelper, SpellFeats} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class EpicActiveSpellFeatSpec extends EpicFeatFeatDisplayHelper { + override val filterByCategory: PartialFunction[Entry, EpicFeat] = { case x: SpellFeats => + x.asInstanceOf[EpicFeat] + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.scala new file mode 100644 index 00000000..fa846bfe --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicClassFeatSpec.scala @@ -0,0 +1,97 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import com.typesafe.scalalogging.LazyLogging +import enumeratum.{Enum, EnumEntry} +import io.truthencode.ddo.model.classes.HeroicCharacterClass +import io.truthencode.ddo.model.feats.{ + ClassFeatDisplayHelper, + ClassRestricted, + EpicFeatFeatDisplayHelper +} +import io.truthencode.ddo.support.naming.DisplayProperties +import io.truthencode.ddo.support.requisite.ClassRequisite +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +@RunWith(classOf[ConcordionRunner]) +class EpicClassFeatSpec extends LazyLogging { + type Entry = EnumEntry with DisplayProperties + type E = Enum[_ <: Entry] + type CharClass = Option[HeroicCharacterClass] + type EpicClassHelper = ClassFeatDisplayHelper with EpicFeatFeatDisplayHelper + + val helperMap: scala.collection.mutable.HashMap[CharClass, EpicClassHelper] = + scala.collection.mutable.HashMap.empty + + val filterByAnyOfs: PartialFunction[Entry, Entry] = { + case x: ClassRequisite if x.anyOfClass.exists(findHelper.isDefinedForClass(_)) => x + } + private var instanceClass: Option[HeroicCharacterClass] = None + + def setUpClass(classId: String): Unit = { + logger.info(s"classId $classId") + val result = HeroicCharacterClass.namesToValuesMap.view + .filterKeys(_ == classId) + .values + .headOption + logger.info(s"classId $classId Set instance to $result") + instanceClass = result + + } + + def verify(): util.List[String] = { + logger.info(s"Verify instance $instanceClass") + val h = findHelper + + val y: Seq[Entry] = h.displayEnum.values.collect(h.existing) + logger.info(s"count from existing ${y.size}") + val z = y.collect(h.filterByCategory) + logger.info(s"count from filterByCategory ${z.size}") + z.map(_.displayText).asJava + } + + def findHelper(implicit charClass: CharClass = instanceClass): EpicClassHelper = { + helperMap.getOrElseUpdate(charClass, makeHelper(charClass)) + } + + def makeHelper(clazz: CharClass): EpicClassHelper = { + new ClassFeatDisplayHelper with EpicFeatFeatDisplayHelper { + override val cClass: HeroicCharacterClass = + instanceClass.getOrElse(clazz.get) + override val filterByCategory: PartialFunction[Entry, Entry] = { case x: ClassRestricted => + x + } + + override def verify(): util.List[String] = { + logger.info(s"Verify instance $instanceClass") + + val y: Seq[Entry] = displayEnum.values.collect(existing) + logger.info(s"count from existing ${y.size}") + val z = y.collect(filterByCategory) + logger.info(s"count from filterByCategory ${z.size}") + z.map(_.displayText).asJava + } + } + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.scala new file mode 100644 index 00000000..4788d37b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicGeneralFeatSpec.scala @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import io.truthencode.ddo.model.feats.{EpicFeat, EpicFeatFeatDisplayHelper, GeneralPassive} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class EpicGeneralFeatSpec extends EpicFeatFeatDisplayHelper { + override val filterByCategory: PartialFunction[Entry, EpicFeat] = { case x: GeneralPassive => + x.asInstanceOf[EpicFeat] + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.scala new file mode 100644 index 00000000..2ed823d7 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicMetamagicFeatSpec.scala @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import io.truthencode.ddo.model.feats.{EpicFeat, EpicFeatFeatDisplayHelper, EpicMetaMagic} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class EpicMetamagicFeatSpec extends EpicFeatFeatDisplayHelper { + override val filterByCategory: PartialFunction[Entry, EpicFeat] = { case x: EpicMetaMagic => + x.asInstanceOf[EpicFeat] + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.scala new file mode 100644 index 00000000..91e79ed5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicRangedCombatFeatSpec.scala @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import io.truthencode.ddo.model.feats.{EpicFeat, EpicFeatFeatDisplayHelper, RangedCombatPassive} +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class EpicRangedCombatFeatSpec extends EpicFeatFeatDisplayHelper { + + override val filterByCategory: PartialFunction[Entry, EpicFeat] = { case x: RangedCombatPassive => + x.asInstanceOf[EpicFeat] + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.scala new file mode 100644 index 00000000..7ccdee0c --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/epic/EpicSpellCastingFeatSpec.scala @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.epic + +import io.truthencode.ddo.model.feats.{EpicFeat, EpicFeatFeatDisplayHelper, SpellCastingPassive} +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class EpicSpellCastingFeatSpec extends EpicFeatFeatDisplayHelper { + override val filterByCategory: PartialFunction[Entry, EpicFeat] = { case x: SpellCastingPassive => + x.asInstanceOf[EpicFeat] + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.scala new file mode 100644 index 00000000..423f6a3a --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/favor/FavorFeatSpec.scala @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.favor + +import com.typesafe.scalalogging.LazyLogging +import io.truthencode.ddo.model.feats.{Feat, FeatDisplayHelper} +import io.truthencode.ddo.support.requisite.RequiresAllOfPatron +import org.concordion.api.FullOGNL +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +class FavorFeatSpec extends FeatDisplayHelper with LazyLogging { + + override val displayEnum: E = Feat + // RequiresAllOfPatron + private val filterFavor: PartialFunction[Entry, Entry with RequiresAllOfPatron] = { + case x: RequiresAllOfPatron => + x + } + + override def verify(): util.List[String] = { + displayEnum.values.map(_.displayText).asJava + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/metamagic/MetaMagic.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/metamagic/MetaMagic.scala new file mode 100644 index 00000000..6c94ea88 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/metamagic/MetaMagic.scala @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.metamagic + +import io.truthencode.ddo.model.feats.MetaMagicFeat +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +@RunWith(classOf[ConcordionRunner]) +class MetaMagic { + def verifyFeats(): util.List[String] = { + MetaMagicFeat.values.map { x => + x.displayText + }.toList.sorted.asJava + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.scala new file mode 100644 index 00000000..6d98b5d3 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/BladeforgedFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class BladeforgedFeatSpec extends RaceSupport { + override val raceId: Race = Race.Bladeforged +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.scala new file mode 100644 index 00000000..8b60e62e --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DeepGnomeFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class DeepGnomeFeatSpec extends RaceSupport { + override val raceId: Race = Race.DeepGnome +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DrowFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DrowFeatSpec.scala new file mode 100644 index 00000000..5aaa2942 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DrowFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class DrowFeatSpec extends RaceSupport { + override val raceId: Race = Race.DrowElf +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.scala new file mode 100644 index 00000000..2fc76e84 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/DwarfFeatSpec.scala @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class DwarfFeatSpec extends RaceSupport { + override val raceId: Race = Race.Dwarf + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ElfFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ElfFeatSpec.scala new file mode 100644 index 00000000..9e05b1b9 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ElfFeatSpec.scala @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.{ConcordionResourcesBundleSpec, RaceSupport} +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +// @ConcordionResources(Array("/images/thumb/*.png", "/images/*.png")) +@RunWith(classOf[ConcordionRunner]) +class ElfFeatSpec extends ConcordionResourcesBundleSpec with RaceSupport { + override val raceId = Race.Elf + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.scala new file mode 100644 index 00000000..7feb7dd4 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/GnomeFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class GnomeFeatSpec extends RaceSupport { + override val raceId: Race = Race.Gnome +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.scala new file mode 100644 index 00000000..551422f8 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfElfFeatSpec.scala @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.{Feat, FeatDisplayHelper, RaceSupport} +import io.truthencode.ddo.model.race.Race +import io.truthencode.ddo.support.requisite.RequirementOption +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +@RunWith(classOf[ConcordionRunner]) +class HalfElfFeatSpec extends FeatDisplayHelper with RaceSupport { + + override val raceId: Race = Race.HalfElf + override val displayEnum: E = Feat + + def verifyNonDilettante(): util.List[String] = verifyGrantedFeats + + def verifyDilettante(): util.List[String] = + Feat + .featsFromRace(Race.HalfElf, RequirementOption.Available) + .filter { x => + !x.isSubFeat && x.entryName.contains("Dilettante") + } + .map { x => + x.displayText + } + .toList + .sorted + .asJava +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.scala new file mode 100644 index 00000000..de8585e6 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalfOrcFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class HalfOrcFeatSpec extends RaceSupport { + override val raceId: Race = Race.HalfOrc +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.scala new file mode 100644 index 00000000..4cc053d5 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/HalflingFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class HalflingFeatSpec extends RaceSupport { + override val raceId: Race = Race.Halfling +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.scala new file mode 100644 index 00000000..5743820f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/PurpleDragonKnightsFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class PurpleDragonKnightsFeatSpec extends RaceSupport { + override val raceId: Race = Race.PurpleDragonKnight +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/Races.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/Races.scala new file mode 100644 index 00000000..ce067720 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/Races.scala @@ -0,0 +1,40 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.{FeatDisplayHelper, RacialFeat} +import org.concordion.api.FullOGNL +import org.concordion.api.option.{ConcordionOptions, MarkdownExtensions} +//import org.concordion.ext.EmbedExtension +//import org.concordion.ext.collapse.CollapseOutputExtension +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@FullOGNL +//@Extensions(Array(classOf[EmbedExtension], classOf[CollapseOutputExtension])) +@RunWith(classOf[ConcordionRunner]) +@ConcordionOptions( + declareNamespaces = Array("ext", "urn:concordion-extensions:2010"), + markdownExtensions = Array( + MarkdownExtensions.WIKILINKS, + MarkdownExtensions.AUTOLINKS, + MarkdownExtensions.TASKLISTITEMS) +) +class Races extends FeatDisplayHelper { + override val displayEnum: E = RacialFeat +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.scala new file mode 100644 index 00000000..e37c972f --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/ShardarkaiFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class ShardarkaiFeatSpec extends RaceSupport { + override val raceId: Race = Race.Shadarkai +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.scala new file mode 100644 index 00000000..c657f3fa --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/SunElfFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class SunElfFeatSpec extends RaceSupport { + override val raceId: Race = Race.Morninglord +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.scala new file mode 100644 index 00000000..376e3482 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/feats/races/WarforgedFeatSpec.scala @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.feats.races + +import io.truthencode.ddo.model.feats.RaceSupport +import io.truthencode.ddo.model.race.Race +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class WarforgedFeatSpec extends RaceSupport { + override val raceId: Race = Race.Warforged +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/races/Races.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/races/Races.scala new file mode 100644 index 00000000..5c7e8cce --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/races/Races.scala @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.races + +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +@RunWith(classOf[ConcordionRunner]) +class Races diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/skill/SkillSpec.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/skill/SkillSpec.scala new file mode 100644 index 00000000..d2332cc9 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/model/skill/SkillSpec.scala @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.model.skill + +import org.concordion.api.FullOGNL +import org.concordion.api.option.{ConcordionOptions, MarkdownExtensions} +import org.concordion.integration.junit4.ConcordionRunner +import org.junit.runner.RunWith + +import java.util +import scala.jdk.CollectionConverters.SeqHasAsJava + +@FullOGNL +@RunWith(classOf[ConcordionRunner]) +@ConcordionOptions( + declareNamespaces = Array("ext", "urn:concordion-extensions:2010"), + markdownExtensions = Array( + MarkdownExtensions.WIKILINKS, + MarkdownExtensions.AUTOLINKS, + MarkdownExtensions.TASKLISTITEMS) +) +class SkillSpec { + val skillEnum: Skill.type = Skill + + def prettyPrint(): String = { + listValues("Current Supported Skills", collapse = true) + } + + def listValues(heading: String, collapse: Boolean = false): String = { + + val data = skillEnum.values.map { a => s"${a.entryName}" }.mkString + val header = s"" + val footer = "
$heading
" + val table = s"$header$data$footer" + if (collapse) { + s"""
$table
""" + } else { + table + } + + } + + def withNameAsList(skillId: String): util.List[Skill] = { + for { + v <- skillEnum.values + if v.toString == skillId + } yield v + }.asJava + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderHelper.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderHelper.scala new file mode 100644 index 00000000..cd9c4457 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderHelper.scala @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.support + +/** + * Created by adarr on 8/14/2016. + */ +class ConcordionEnumBuilderHelper(helper: ConcordionEnumBuilderSupport) { + def actual: Seq[String] = helper.actual + + implicit private val myStringOrdering: scala.math.Ordering[String] = + Ordering.fromLessThan[String](_ > _) + + def listValues(heading: String): String = helper.listValues(heading) + + /** + * Needed for Concordion / Java compatability as it does not recognize optional parameters. + * + * @return + */ + def listValues(): String = helper.listValues() + + def getValidSingleValue: String = helper.getValidSingleValue + + def resultCount(searchString: String, ignoreCase: String): Int = + helper.resultCount(searchString, ignoreCase) + + def withNames(searchString: String, ignoreCase: Boolean): Seq[String] = { + helper.withNames(searchString, ignoreCase = ignoreCase) + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderSupport.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderSupport.scala new file mode 100644 index 00000000..ff1b8264 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumBuilderSupport.scala @@ -0,0 +1,78 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.support + +import java.lang +import scala.jdk.CollectionConverters.IterableHasAsJava +import scala.util.Try + +/** + * Created by adarr on 1/25/2017. + */ +trait ConcordionEnumBuilderSupport { + implicit protected[this] val myStringOrdering: Ordering[String] = + Ordering.fromLessThan[String](_ > _) + + def actual: Seq[String] + + /** + * Needed for Concordion / Java compatibility as it does not recognize optional parameters. + * + * @return + */ + def listValues(): String = { + listValues("Expected Values") + } + + def listValues(heading: String): String = { + val data = actual.map { a => s"$a" }.mkString + val header = s"" + val footer = "
$heading
" + s"$header$data$footer" + } + + def getValidSingleValue: String = + actual.headOption.getOrElse("Please specify at least one value for this enum") + + def resultCount(searchString: String, ignoreCase: String): Int = { + resultCount(searchString, strToBool(ignoreCase)) + } + + protected def strToBool(s: String): Boolean = Try(s.toBoolean).getOrElse(false) + + protected[this] def resultCount(searchString: String, ignoreCase: Boolean): Int = { + withNames(searchString, ignoreCase = ignoreCase).size + } + + def withNames(searchString: String, ignoreCase: Boolean): Seq[String] = { + val ss = searchString.split(',').toSet.toSeq + if (ignoreCase) { + for { + a <- actual + s <- ss + if a.equalsIgnoreCase(s.trim) + } yield s + } else { + ss.intersect(actual) + } + } + + def withNames(searchString: String, ignoreCase: String): lang.Iterable[String] = { + withNames(searchString, strToBool(ignoreCase)) + }.sortWith(_ < _).asJava +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumHelperTest.scala.scalatest b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumHelperTest.scala.scalatest new file mode 100644 index 00000000..82c9951a --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionEnumHelperTest.scala.scalatest @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.support + +import com.typesafe.scalalogging.LazyLogging +import com.wix.accord.scalatest.ResultMatchers +import io.truthencode.ddo.model.alignment.MoralAxis +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{FunSpec, Matchers} +import scala.language.reflectiveCalls + +/** + * Created by adarr on 8/14/2016. + */ +@RunWith(classOf[JUnitRunner]) +class ConcordionEnumHelperTest extends FunSpec with Matchers with ResultMatchers with LazyLogging { + val fixture = new { + val builder = new ConcordionEnumBuilderSupport { + override def actual = MoralAxis.values.map(_.toString) + } + val helper = new ConcordionEnumBuilderHelper(builder) + } + describe("An Enum Helper") { + it("should be generated from a jade template") { + val f = fixture + val lst = f.helper.listValues() + logger.info(lst) + } + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilder.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilder.scala new file mode 100644 index 00000000..bd2c3e8c --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilder.scala @@ -0,0 +1,115 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.support + +import com.typesafe.scalalogging.LazyLogging +import de.neuland.jade4j.{Jade4J, JadeConfiguration} +import enumeratum.{Enum, EnumEntry} +import io.truthencode.ddo.enumeration.Companionable +import io.truthencode.ddo.support.StringUtils.{randomAlphaString, Extensions} + +import scala.jdk.CollectionConverters.IterableHasAsJava +import scala.reflect.ClassTag + +/** + * Created by adarr on 8/14/2016. + */ +class ConcordionTemplateBuilder extends LazyLogging { + val basePath = "/template" + val config: JadeConfiguration = { + val c = new JadeConfiguration + c.setPrettyPrint(true) + c.setMode(Jade4J.Mode.HTML) + c.setCaching(false) + c + } + + def renderEnum(fqn: String): Option[String] = { + val path = s"$basePath/Enum.jade" + val cpPath = getClass.getResource(path).getFile + logger.info(s"Attempting to load Template file => $cpPath") + + try { + // WOW!!! Unsafe + val cls = Class.forName(fqn).newInstance + val template = config.getTemplate(cpPath) + nameToClass(cls) match { + case Some(x) => + val model = modelBuilder(x) + + val output = Jade4J.render(template, model) + logger.info(s"Pretty printing results? ${config.isPrettyPrint} ") + Option(output) + case None => + logger.error(s"Failed to convert $fqn, could not build model.") + None + } + } catch { + case e: InstantiationException => + logger.error(s"Could not instantiate $fqn, ${e.getMessage}") + None + case e: Exception => + logger.error(s"Failed to render file $cpPath", e) + None + } + } + + def nameToClass[T: ClassTag](cls: T): Option[Enum[_ <: EnumEntry]] = { + val cName = cls.getClass.getName + cls match { + case x: Companionable => + logger.info(s"Casting $cName from Companionable") + Some(x.companion.asInstanceOf[Enum[_ <: EnumEntry]]) + case x: Enum[_] => + logger.info(s"Returning Enum from base") + Some(x) + case _: EnumEntry => + logger.info(s"EnumEntry located $cName") + None + case _: AnyRef => + logger.warn(s"nameToClass resolved $cName") + None + case _ => None + } + } + + /*def findCompanion[E <: Companion[EnumEntry]](entry: E): Enum[_ <: EnumEntry] = { + entry.comp + }*/ + + def modelBuilder(source: Enum[_]): java.util.HashMap[String, Object] = { + val model = new java.util.HashMap[String, Object]() + + val name = source.getClass.getSimpleName.filterAlphaNumeric.splitByCase + val values = source.values.asJava + val ciValues = source.values.map { x => x.toString.randomCase }.asJava + + val sLen = 10 + val invalid = (for { x <- 0 to 3 } yield randomAlphaString(sLen).randomCase).asJava + val singleValue = + source.values.headOption.map { h => h.toString } + .getOrElse("Please specify at least one value for this enum") + model.put("name", name) + model.put("values", values) + model.put("invalidValues", invalid) + model.put("ciValues", ciValues) + model.put("singleValue", singleValue) + + model + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilderTest.scala.scalatest b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilderTest.scala.scalatest new file mode 100644 index 00000000..5e0e01f2 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/ConcordionTemplateBuilderTest.scala.scalatest @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.support + +import com.typesafe.scalalogging.LazyLogging +import com.wix.accord.scalatest.ResultMatchers +import org.scalatest.{FunSpec, Matchers} + +/** + * Created by adarr on 8/14/2016. + */ +// @RunWith(classOf[JUnitRunner]) +class ConcordionTemplateBuilderTest + extends FunSpec + with Matchers + with ResultMatchers + with LazyLogging { + ignore("A Custom enum") { + it("should be generated from a jade template") { + val builder = new ConcordionTemplateBuilder() + val actual = builder.renderEnum("io.truthencode.ddo.model.alignment.MoralAxis") + actual should not be empty + logger.info(actual.getOrElse("No data returned")) + } + } +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/requisite/Requisite.md b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/requisite/Requisite.md new file mode 100644 index 00000000..3f3a71d1 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/support/requisite/Requisite.md @@ -0,0 +1,3 @@ +# Requisite + +Requisites represent the basic requirements that need to be met or exceeded in order to obtain a given item. diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/DefaultFlexmark.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/DefaultFlexmark.scala new file mode 100644 index 00000000..4c266885 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/DefaultFlexmark.scala @@ -0,0 +1,22 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +trait DefaultFlexmark + extends FlexmarkImpl with GfmStrikethroughSubscript with GfmTaskListOptions with Emoji + with WikiLink diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Emoji.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Emoji.scala new file mode 100644 index 00000000..56cc0c8b --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Emoji.scala @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +import _root_.io.truthencode.ddo.testoptions.Flexmark._ +import com.vladsch.flexmark.ext.emoji.{EmojiExtension, EmojiImageType, EmojiShortcutType} +import com.vladsch.flexmark.util.data.MutableDataSet +import com.vladsch.flexmark.util.misc.Extension + +/** + * Configures and enables Flexmarks Emojis hopefully with the help of + * [[https://github.com/WebpageFX/emoji-cheat-sheet.com emojii cheat sheet]] extension + * + * @see + * [[https://github.com/vsch/flexmark-java/wiki/Extensions#emoji]] + */ +trait Emoji extends Flexmark { + + abstract override def flexmarkExtensions: Seq[Extension] = + super.flexmarkExtensions :+ EmojiExtension.create() + + abstract override def calls: Seq[() => MutableDataSet] = super.calls :+ taskOptions() + + /** + * see [[https://github.com/vsch/flexmark-java/wiki/Extensions#emoji]] + * @param dataSet + * @return + * Mutated dataset with specified default options + */ + private[this] def taskOptions()(implicit dataSet: MutableDataSet): () => MutableDataSet = { () => + dataSet + .set(EmojiExtension.ATTR_IMAGE_SIZE, "24") + .set(EmojiExtension.USE_IMAGE_TYPE, EmojiImageType.UNICODE_FALLBACK_TO_IMAGE) + .set(EmojiExtension.USE_SHORTCUT_TYPE, EmojiShortcutType.ANY_EMOJI_CHEAT_SHEET_PREFERRED) + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Flexmark.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Flexmark.scala new file mode 100644 index 00000000..7f9ba243 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/Flexmark.scala @@ -0,0 +1,87 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +import com.vladsch.flexmark.parser.Parser +import com.vladsch.flexmark.util.data.{DataKey, MutableDataSet} +import com.vladsch.flexmark.util.misc.Extension +import org.concordion.api.option.FlexmarkOptions + +import scala.jdk.CollectionConverters.SeqHasAsJava + +/** + * Scala wrapper for applying flexmark options to Concordion specs. + */ +trait Flexmark { + import Flexmark._ + @FlexmarkOptions val flexmarkOptions: MutableDataSet = { + calls.foreach(f => f()) + ds.set(Parser.EXTENSIONS, flexmarkExtensions.toList.toJavaList) + + } + + def flexmarkExtensions: Seq[Extension] + + def calls: Seq[() => MutableDataSet] +} + +object Flexmark { + + implicit class ExtOpts(source: List[Extension]) { + + /** + * Extension Wrapper because scala is not inferring downcast due to Invariant T + * @return + * Downcast T <: Extension + */ + def toJavaList: java.util.List[Extension] = { + source.asJava + } + } + + implicit class FlexOpts(source: Seq[(DataKey[_], Any)]) { + + /** + * Extension Wrapper because scala is not inferring downcast due to Invariant T + * @return + * Downcast T <: Extension + */ + def toJavaList: java.util.List[(DataKey[_], Any)] = { + source.asJava + } + } + + implicit class TupOpts(source: Seq[(_, _)]) { + def toJavaList: java.util.List[(_, _)] = { + source.asJava + } + } + implicit class HtmlEscape(source: String) { + + /** + * Replaces HTML breaking space" " with entity " " + * @return + * Entity for html escaped non-breaking space. + */ + def removeNbsp(): String = { + source.replace(" ", " ") + } + } + implicit lazy val ds: MutableDataSet = new MutableDataSet() + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/FlexmarkImpl.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/FlexmarkImpl.scala new file mode 100644 index 00000000..8186c25a --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/FlexmarkImpl.scala @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +import com.vladsch.flexmark.util.data.MutableDataSet +import com.vladsch.flexmark.util.misc.Extension + +trait FlexmarkImpl extends Flexmark { + override def flexmarkExtensions: Seq[Extension] = Seq.empty + + override def calls: Seq[() => MutableDataSet] = Seq.empty +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmStrikethroughSubscript.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmStrikethroughSubscript.scala new file mode 100644 index 00000000..1abc8b13 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmStrikethroughSubscript.scala @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughSubscriptExtension +import com.vladsch.flexmark.util.data.MutableDataSet +import com.vladsch.flexmark.util.misc.Extension + +/** + * Configures and enables Flexmarks GFM Strikethroughsubscript extension + * @see + * [[https://github.com/vsch/flexmark-java/wiki/Extensions#gfm-strikethroughsubscript]] + */ +trait GfmStrikethroughSubscript extends Flexmark { + + abstract override def flexmarkExtensions: Seq[Extension] = + super.flexmarkExtensions :+ StrikethroughSubscriptExtension.create() + + // No options currently specified + // abstract override def calls: Seq[() => MutableDataSet] = super.calls :+ taskOptions() + + /** + * see [[https://github.com/vsch/flexmark-java/wiki/Extensions#gfm-strikethroughsubscript]] + * @param dataSet + * @return + */ + private[this] def taskOptions()(implicit dataSet: MutableDataSet): () => MutableDataSet = { () => + dataSet + // .set(StrikethroughSubscriptExtension.STRIKETHROUGH_STYLE_HTML_CLOSE,"someCssClassLikely") + + } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmTaskListOptions.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmTaskListOptions.scala new file mode 100644 index 00000000..ba865ce3 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/GfmTaskListOptions.scala @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +import _root_.io.truthencode.ddo.testoptions.Flexmark._ +import com.vladsch.flexmark.ext.gfm.tasklist.{TaskListExtension, TaskListItemPlacement} +import com.vladsch.flexmark.util.data.MutableDataSet +import com.vladsch.flexmark.util.misc.Extension + +trait GfmTaskListOptions extends Flexmark { + abstract override def flexmarkExtensions: Seq[Extension] = + super.flexmarkExtensions :+ TaskListExtension.create() + + abstract override def calls: Seq[() => MutableDataSet] = super.calls :+ gfmTaskOptions() + + def gfmTaskOptions()(implicit dataSet: MutableDataSet): () => MutableDataSet = { () => + dataSet + .set(TaskListExtension.ITEM_DONE_MARKER, safeItemDone) + .set(TaskListExtension.ITEM_NOT_DONE_MARKER, safeItemNotDone) + .set(TaskListExtension.FORMAT_LIST_ITEM_PLACEMENT, TaskListItemPlacement.INCOMPLETE_FIRST) + + // var d = dataSet + // oThingsToSet.foreach(e => d = d.set(e._1, e._2)) + // d + + } + + private def safeItemDone = TaskListExtension.ITEM_DONE_MARKER.getDefaultValue.removeNbsp() + + private def safeItemNotDone = TaskListExtension.ITEM_NOT_DONE_MARKER.getDefaultValue.removeNbsp() + +// def set[T](key: DataKey[T], value: T)(implicit dataSet: MutableDataSet): MutableDataSet = { +// dataSet.set(key, value) +// } + +} diff --git a/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/WikiLink.scala b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/WikiLink.scala new file mode 100644 index 00000000..3b608934 --- /dev/null +++ b/subprojects/common/ddo-core/src/acceptanceTest/scala/io/truthencode/ddo/testoptions/WikiLink.scala @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2015-2021 Andre White. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.truthencode.ddo.testoptions + +import _root_.io.truthencode.ddo.testoptions.Flexmark._ +import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension +import com.vladsch.flexmark.util.data.MutableDataSet +import com.vladsch.flexmark.util.misc.Extension + +/** + * Configures and enables Flexmarks Emojis hopefully with the help of + * [[https://github.com/WebpageFX/emoji-cheat-sheet.com emojii cheat sheet]] extension + * + * @see + * [[https://github.com/vsch/flexmark-java/wiki/Extensions#emoji]] + */ +trait WikiLink extends Flexmark { + + abstract override def flexmarkExtensions: Seq[Extension] = + super.flexmarkExtensions :+ WikiLinkExtension.create() + + abstract override def calls: Seq[() => MutableDataSet] = super.calls :+ wikiLinkTaskOptions() + + /** + * see [[https://github.com/vsch/flexmark-java/wiki/Extensions#emoji]] + * @param dataSet + * @return + * Mutated dataset with specified default options + */ + private[this] def wikiLinkTaskOptions()(implicit + dataSet: MutableDataSet): () => MutableDataSet = { () => + dataSet + .set(WikiLinkExtension.IMAGE_LINKS, Boolean.box(true)) + + } + +} From f12d25fbcbc032382e5a1a7cce02c7463825e59f Mon Sep 17 00:00:00 2001 From: Andre White Date: Sat, 9 Sep 2023 02:01:32 -0600 Subject: [PATCH 13/19] :bug: Html validation fixed improper cased DOCTYPE in spec template which caused 2 concordion tests to fail with initialization errors. --- .../ddo/model/alignment/LawAxisSpec.html | 17 +++++------------ .../ddo/model/alignment/MoralAxisSpec.html | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html index 0b7c84f3..ed913966 100644 --- a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/LawAxisSpec.html @@ -17,11 +17,8 @@ limitations under the License. --> - - + + Law Axis @@ -49,12 +46,9 @@

Case Sensitive Operations

When case insensitivity is true

Then a search for "Lawful,Neutral,Chaotic" should return: (Alpha Sort used for verification) + >Lawful,Neutral,Chaotic" should return: (Alpha Sort used for verification)

- +
@@ -80,8 +74,7 @@

Case Insensitive Operations

Should return 0 + >0 results diff --git a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html index 98150a5a..87b8f0f7 100644 --- a/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html +++ b/subprojects/common/ddo-core/src/acceptanceTest/resources/io/truthencode/ddo/model/alignment/MoralAxisSpec.html @@ -17,7 +17,7 @@ limitations under the License. --> - + Date: Sat, 9 Sep 2023 09:16:08 +0000 Subject: [PATCH 14/19] Bump git-commit-id-plugin from 2.2.0 to 4.9.10 Bumps git-commit-id-plugin from 2.2.0 to 4.9.10. --- updated-dependencies: - dependency-name: pl.project13.maven:git-commit-id-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 472cdc96..83bcca07 100644 --- a/pom.xml +++ b/pom.xml @@ -592,7 +592,7 @@ pl.project13.maven git-commit-id-plugin - 2.2.0 + 4.9.10 dd.MM.yyyy '@' HH:mm:ss z - + - 2.13.0 + 2.32.0 2.12 2.13.6 From 82322e4e1ad8f3d259afaf061b53e50b1b4d9d0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Sep 2023 09:51:31 +0000 Subject: [PATCH 16/19] Bump taglist-maven-plugin from 2.4 to 3.0.0 Bumps [taglist-maven-plugin](https://github.com/mojohaus/taglist-maven-plugin) from 2.4 to 3.0.0. - [Release notes](https://github.com/mojohaus/taglist-maven-plugin/releases) - [Commits](https://github.com/mojohaus/taglist-maven-plugin/compare/taglist-maven-plugin-2.4...taglist-maven-plugin-3.0.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:taglist-maven-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fe8fbf16..d93ba471 100644 --- a/pom.xml +++ b/pom.xml @@ -1294,7 +1294,7 @@ org.codehaus.mojo taglist-maven-plugin - 2.4 + 3.0.0 From 2758917b20f01844e05e4b9c00fd459edb86c879 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Sep 2023 09:52:15 +0000 Subject: [PATCH 17/19] Bump pegdown from 1.5.0 to 1.6.0 Bumps [pegdown](https://github.com/sirthias/pegdown) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/sirthias/pegdown/releases) - [Changelog](https://github.com/sirthias/pegdown/blob/master/CHANGELOG) - [Commits](https://github.com/sirthias/pegdown/compare/1.5.0...1.6.0) --- updated-dependencies: - dependency-name: org.pegdown:pegdown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fe8fbf16..526c1fb3 100644 --- a/pom.xml +++ b/pom.xml @@ -979,7 +979,7 @@ org.pegdown pegdown - 1.5.0 + 1.6.0 From b99df40729bae81ab7f7cdd084123651fe595de5 Mon Sep 17 00:00:00 2001 From: Andre White Date: Sat, 9 Sep 2023 14:22:51 -0600 Subject: [PATCH 18/19] Formatting sync --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 44fd0498..bf8facf4 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ hs*.log docsold/ +subprojects/common/ddo-modeling/src/main/avro/io/truthencode/ddo/model/protocol/ + #Maven exclusions target/ pom.xml.tag From 030df0e6e6d1594455b101767f1b147a9ca798f9 Mon Sep 17 00:00:00 2001 From: Andre White Date: Sat, 9 Sep 2023 15:10:20 -0600 Subject: [PATCH 19/19] SLug Needed a push --- local.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/local.properties b/local.properties index 10a01e71..177507c2 100644 --- a/local.properties +++ b/local.properties @@ -4,5 +4,5 @@ # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. -#Tue Jun 28 02:46:01 MDT 2022 -sdk.dir=/home/adarro/.android +#Sat Sep 09 14:55:15 MDT 2023 +sdk.dir=C\:\\Users\\adarr\\AppData\\Local\\Android\\Sdk
Matching Values