From c62bd76d90f0ae3ff9bfdb85d15d67061cf420cd Mon Sep 17 00:00:00 2001 From: Wil Thieme Date: Mon, 26 Feb 2024 11:18:35 -0500 Subject: [PATCH] styling --- README.md | 2 +- scripts/UNPC_abilities.lua | 398 +++++++++++++++------------- scripts/UNPC_effectdescriptions.lua | 68 ++--- scripts/UNPC_upgradespells.lua | 321 +++++++++++++--------- 4 files changed, 450 insertions(+), 339 deletions(-) diff --git a/README.md b/README.md index 08a44f8..4a0ebbf 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This extension improves automation of NPC abilities and spells. # Compatibility and Instructions -This extension has been tested with [FantasyGrounds Unity](https://www.fantasygrounds.com/home/FantasyGroundsUnity.php) v4.4.9 (2023-12-18). +This extension has been tested with [FantasyGrounds Unity](https://www.fantasygrounds.com/home/FantasyGroundsUnity.php) v4.5.0 (2024-02-21). Most features of this extension require the [PFRPG - Spellbook](https://www.fantasygrounds.com/forums/showthread.php?58962-PFRPG-Spellbook) module by [dllewell](https://www.fantasygrounds.com/forums/member.php?276423-dllewell). diff --git a/scripts/UNPC_abilities.lua b/scripts/UNPC_abilities.lua index 95ddfa7..ad72678 100644 --- a/scripts/UNPC_abilities.lua +++ b/scripts/UNPC_abilities.lua @@ -5,29 +5,36 @@ -- PARSER FUNCTIONS local function parse_breath_weapon(string_parenthetical, table_ability_information) - local string_parenthetical_lower = string.lower(', ' .. string_parenthetical .. ',') - local dice_damage, string_damage_type = string_parenthetical_lower:match(',%s(%d%d*d*d%d+)%s*(%l+)[.+]?') - local string_save_type, number_save_dc = string_parenthetical_lower:match(',%s(%l*%l*%l*%l*%l*%l*%l*%l*)%s*dc%s*(%d+)[.+]?') - if string_save_type == 'fort' then string_save_type = 'fortitude' end - local dice_recharge = string_parenthetical_lower:match(',%susable%severy%s(%d%d*d*d%d+)%srounds[.+]?') + local string_parenthetical_lower = string.lower(", " .. string_parenthetical .. ",") + local dice_damage, string_damage_type = string_parenthetical_lower:match(",%s(%d%d*d*d%d+)%s*(%l+)[.+]?") + local string_save_type, number_save_dc = + string_parenthetical_lower:match(",%s(%l*%l*%l*%l*%l*%l*%l*%l*)%s*dc%s*(%d+)[.+]?") + if string_save_type == "fort" then + string_save_type = "fortitude" + end + local dice_recharge = string_parenthetical_lower:match(",%susable%severy%s(%d%d*d*d%d+)%srounds[.+]?") - table_ability_information['actions']['breathweapondmg']['damagelist']['primarydamage']['dice']['value'] = dice_damage - table_ability_information['actions']['breathweapondmg']['damagelist']['primarydamage']['type']['value'] = string_damage_type - if string_save_type and string_save_type ~= '' then - table_ability_information['actions']['breathweaponsave']['savetype']['value'] = string_save_type + table_ability_information["actions"]["breathweapondmg"]["damagelist"]["primarydamage"]["dice"]["value"] = + dice_damage + table_ability_information["actions"]["breathweapondmg"]["damagelist"]["primarydamage"]["type"]["value"] = + string_damage_type + if string_save_type and string_save_type ~= "" then + table_ability_information["actions"]["breathweaponsave"]["savetype"]["value"] = string_save_type end - table_ability_information['actions']['breathweaponsave']['savedcmod']['value'] = number_save_dc - table_ability_information['actions']['breathweaponsave']['onmissdamage']['value'] = 'half' - if dice_recharge and dice_recharge ~= '' then - if dice_recharge:sub(1, 2) == '1d' then dice_recharge = dice_recharge:gsub('1d', 'd') end - table_ability_information['actions']['breathweaponrecharge']['durdice']['value'] = dice_recharge + table_ability_information["actions"]["breathweaponsave"]["savedcmod"]["value"] = number_save_dc + table_ability_information["actions"]["breathweaponsave"]["onmissdamage"]["value"] = "half" + if dice_recharge and dice_recharge ~= "" then + if dice_recharge:sub(1, 2) == "1d" then + dice_recharge = dice_recharge:gsub("1d", "d") + end + table_ability_information["actions"]["breathweaponrecharge"]["durdice"]["value"] = dice_recharge end end local function parse_bleed(string_parenthetical, table_ability_information) - if string_parenthetical ~= '' then - table_ability_information['actions']['zeffect-1']['label']['value'] = - string.format(table_ability_information['actions']['zeffect-1']['label']['value'], string_parenthetical) + if string_parenthetical ~= "" then + table_ability_information["actions"]["zeffect-1"]["label"]["value"] = + string.format(table_ability_information["actions"]["zeffect-1"]["label"]["value"], string_parenthetical) end end @@ -36,203 +43,232 @@ end -- luacheck: globals array_abilities array_abilities = { -- luacheck: no max line length - ['Ancestral Enmity'] = { - ['name'] = 'Ancestral Enmity', - ['auto_add'] = true, - ['description'] = 'You gain a +2 bonus on melee attack rolls against dwarves and gnomes. You may select this feat twice. Its effects stack.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['label'] = { ['type'] = 'string', ['value'] = 'Ancestral Enmity; IFT: TYPE(gnome); ATK: %d', ['tiermultiplier'] = 2 }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, - }, - ['zeffect-2'] = { - ['label'] = { ['type'] = 'string', ['value'] = 'Ancestral Enmity; IFT: TYPE(dwarf); ATK: %d', ['tiermultiplier'] = 2 }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Ancestral Enmity"] = { + ["name"] = "Ancestral Enmity", + ["auto_add"] = true, + ["description"] = "You gain a +2 bonus on melee attack rolls against dwarves and gnomes. You may select this feat twice. Its effects stack.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["label"] = { + ["type"] = "string", + ["value"] = "Ancestral Enmity; IFT: TYPE(gnome); ATK: %d", + ["tiermultiplier"] = 2, + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, + }, + ["zeffect-2"] = { + ["label"] = { + ["type"] = "string", + ["value"] = "Ancestral Enmity; IFT: TYPE(dwarf); ATK: %d", + ["tiermultiplier"] = 2, + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Arcane Strike'] = { - ['name'] = 'Arcane Strike', - ['description'] = 'As a swift action, you can imbue your weapons with a fraction of your power. For 1 round, your weapons deal +1 damage and are treated as magic for the purpose of overcoming damage reduction. For every five caster levels you possess, this bonus increases by +1, to a maximum of +5 at 20th level.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['dmaxstat'] = { ['type'] = 'number', ['value'] = 4 }, - ['durmod'] = { ['type'] = 'number', ['value'] = 1 }, - ['durmult'] = { ['type'] = 'number', ['value'] = 0.25 }, - ['durstat'] = { ['type'] = 'string', ['value'] = 'cl' }, - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Arcane Strike; DMG: 1; DMGTYPE: magic' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Arcane Strike"] = { + ["name"] = "Arcane Strike", + ["description"] = "As a swift action, you can imbue your weapons with a fraction of your power. For 1 round, your weapons deal +1 damage and are treated as magic for the purpose of overcoming damage reduction. For every five caster levels you possess, this bonus increases by +1, to a maximum of +5 at 20th level.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["dmaxstat"] = { ["type"] = "number", ["value"] = 4 }, + ["durmod"] = { ["type"] = "number", ["value"] = 1 }, + ["durmult"] = { ["type"] = "number", ["value"] = 0.25 }, + ["durstat"] = { ["type"] = "string", ["value"] = "cl" }, + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { ["type"] = "string", ["value"] = "Arcane Strike; DMG: 1; DMGTYPE: magic" }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Breath Weapon'] = { - ['name'] = 'Breath Weapon', - ['description'] = 'Some creatures can exhale a cloud, cone, or line of magical effects. A breath weapon usually deals damage and is often based on some type of energy. Breath weapons allow a Reflex save for half damage (DC = 10 + 1/2 breathing creature’s racial HD + breathing creature’s Constitution modifier; the exact DC is given in the creature’s descriptive text). A creature is immune to its own breath weapon unless otherwise noted. Some breath weapons allow a Fortitude save or a Will save instead of a Reflex save. Each breath weapon also includes notes on how often it can be used.', - ['string_ability_type'] = 'Special Abilities', - ['level'] = 0, - ['parser'] = parse_breath_weapon, - ['actions'] = { - ['breathweaponsave'] = { - ['onmissdamage'] = { ['type'] = 'string', ['value'] = nil }, - ['srnotallowed'] = { ['type'] = 'number', ['value'] = 1 }, - ['savedcmod'] = { ['type'] = 'number', ['value'] = nil }, - ['savedctype'] = { ['type'] = 'string', ['value'] = 'fixed' }, - ['savetype'] = { ['type'] = 'string', ['value'] = 'reflex' }, - ['type'] = { ['type'] = 'string', ['value'] = 'cast' }, - }, - ['breathweapondmg'] = { - ['damagelist'] = { - ['primarydamage'] = { ['dice'] = { ['type'] = 'dice', ['value'] = nil }, ['type'] = { ['type'] = 'string', ['value'] = nil } }, + ["Breath Weapon"] = { + ["name"] = "Breath Weapon", + ["description"] = "Some creatures can exhale a cloud, cone, or line of magical effects. A breath weapon usually deals damage and is often based on some type of energy. Breath weapons allow a Reflex save for half damage (DC = 10 + 1/2 breathing creature’s racial HD + breathing creature’s Constitution modifier; the exact DC is given in the creature’s descriptive text). A creature is immune to its own breath weapon unless otherwise noted. Some breath weapons allow a Fortitude save or a Will save instead of a Reflex save. Each breath weapon also includes notes on how often it can be used.", + ["string_ability_type"] = "Special Abilities", + ["level"] = 0, + ["parser"] = parse_breath_weapon, + ["actions"] = { + ["breathweaponsave"] = { + ["onmissdamage"] = { ["type"] = "string", ["value"] = nil }, + ["srnotallowed"] = { ["type"] = "number", ["value"] = 1 }, + ["savedcmod"] = { ["type"] = "number", ["value"] = nil }, + ["savedctype"] = { ["type"] = "string", ["value"] = "fixed" }, + ["savetype"] = { ["type"] = "string", ["value"] = "reflex" }, + ["type"] = { ["type"] = "string", ["value"] = "cast" }, + }, + ["breathweapondmg"] = { + ["damagelist"] = { + ["primarydamage"] = { + ["dice"] = { ["type"] = "dice", ["value"] = nil }, + ["type"] = { ["type"] = "string", ["value"] = nil }, + }, }, - ['dmgnotspell'] = { ['type'] = 'number', ['value'] = 1 }, - ['type'] = { ['type'] = 'string', ['value'] = 'damage' }, + ["dmgnotspell"] = { ["type"] = "number", ["value"] = 1 }, + ["type"] = { ["type"] = "string", ["value"] = "damage" }, }, - ['breathweaponrecharge'] = { - ['durdice'] = { ['type'] = 'dice', ['value'] = 'd4' }, - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Breath Weapon Recharge' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["breathweaponrecharge"] = { + ["durdice"] = { ["type"] = "dice", ["value"] = "d4" }, + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { ["type"] = "string", ["value"] = "Breath Weapon Recharge" }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Bleed'] = { - ['name'] = 'Bleed', - ['description'] = 'A creature with this ability causes wounds that continue to bleed, dealing additional damage each round at the start of the affected creature’s turn. This bleeding can be stopped with a successful DC 15 Heal skill check or through the application of any magical healing. The amount of damage each round is specified in the creature’s entry.', - ['string_ability_type'] = 'Special Abilities', - ['level'] = 0, - ['parser'] = parse_bleed, - ['actions'] = { - ['zeffect-1'] = { - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Bleed; DMGO: %s bleed' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Bleed"] = { + ["name"] = "Bleed", + ["description"] = "A creature with this ability causes wounds that continue to bleed, dealing additional damage each round at the start of the affected creature’s turn. This bleeding can be stopped with a successful DC 15 Heal skill check or through the application of any magical healing. The amount of damage each round is specified in the creature’s entry.", + ["string_ability_type"] = "Special Abilities", + ["level"] = 0, + ["parser"] = parse_bleed, + ["actions"] = { + ["zeffect-1"] = { + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { ["type"] = "string", ["value"] = "Bleed; DMGO: %s bleed" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Combat Expertise'] = { - ['name'] = 'Combat Expertise', - ['description'] = 'You can choose to take a -1 penalty on melee attack rolls and combat maneuver checks to gain a +1 dodge bonus to your Armor Class. When your base attack bonus reaches +4, and every +4 thereafter, the penalty increases by -1 and the dodge bonus increases by +1. You can only choose to use this feat when you declare that you are making an attack or a full-attack action with a melee weapon. The effects of this feat last until your next turn.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Combat Expertise; ATK: -1 [-QBAB] ,melee; AC: 1 [QBAB] dodge' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Combat Expertise"] = { + ["name"] = "Combat Expertise", + ["description"] = "You can choose to take a -1 penalty on melee attack rolls and combat maneuver checks to gain a +1 dodge bonus to your Armor Class. When your base attack bonus reaches +4, and every +4 thereafter, the penalty increases by -1 and the dodge bonus increases by +1. You can only choose to use this feat when you declare that you are making an attack or a full-attack action with a melee weapon. The effects of this feat last until your next turn.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { + ["type"] = "string", + ["value"] = "Combat Expertise; ATK: -1 [-QBAB] ,melee; AC: 1 [QBAB] dodge", + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Critical Focus'] = { - ['name'] = 'Critical Focus', - ['auto_add'] = true, - ['description'] = 'You receive a +4 circumstance bonus on attack rolls made to confirm critical hits.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Critical Focus; CC: +4 circumstance' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Critical Focus"] = { + ["name"] = "Critical Focus", + ["auto_add"] = true, + ["description"] = "You receive a +4 circumstance bonus on attack rolls made to confirm critical hits.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { ["type"] = "string", ["value"] = "Critical Focus; CC: +4 circumstance" }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Deadly Aim'] = { - ['name'] = 'Deadly Aim', - ['description'] = 'You can choose to take a -1 penalty on all ranged attack rolls to gain a +2 bonus on all ranged damage rolls. When your base attack bonus reaches +4, and every +4 thereafter, the penalty increases by -1 and the bonus to damage increases by +2. You must choose to use this feat before making an attack roll and its effects last until your next turn. The bonus damage does not apply to touch attacks or effects that do not deal hit point damage.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Deadly Aim; ATK: -1 [-QBAB] ,ranged; DMG: 2 [QBAB] [QBAB] ,ranged' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Deadly Aim"] = { + ["name"] = "Deadly Aim", + ["description"] = "You can choose to take a -1 penalty on all ranged attack rolls to gain a +2 bonus on all ranged damage rolls. When your base attack bonus reaches +4, and every +4 thereafter, the penalty increases by -1 and the bonus to damage increases by +2. You must choose to use this feat before making an attack roll and its effects last until your next turn. The bonus damage does not apply to touch attacks or effects that do not deal hit point damage.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { + ["type"] = "string", + ["value"] = "Deadly Aim; ATK: -1 [-QBAB] ,ranged; DMG: 2 [QBAB] [QBAB] ,ranged", + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Defended Movement'] = { - ['name'] = 'Defended Movement', - ['auto_add'] = true, - ['description'] = 'You gain a +2 bonus to your AC against attacks of opportunity.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['durunit'] = { ['type'] = 'string', ['value'] = 'round' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Defended Movement; AC: 4 ,,opportunity' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Defended Movement"] = { + ["name"] = "Defended Movement", + ["auto_add"] = true, + ["description"] = "You gain a +2 bonus to your AC against attacks of opportunity.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["durunit"] = { ["type"] = "string", ["value"] = "round" }, + ["label"] = { ["type"] = "string", ["value"] = "Defended Movement; AC: 4 ,,opportunity" }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Furious Focus'] = { - ['name'] = 'Furious Focus', - ['auto_add'] = true, - ['description'] = 'When you are wielding a two-handed weapon or a one-handed weapon with two hands, and using the Power Attack feat, you do not suffer Power Attack’s penalty on melee attack rolls on the first attack you make each turn. You still suffer the penalty on any additional attacks, including attacks of opportunity.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['apply'] = { ['type'] = 'string', ['value'] = 'roll' }, - ['label'] = { ['type'] = 'string', ['value'] = 'Furious Focus; IF: CUSTOM(Power Attack 2-H); ATK: 1 [QBAB] ,melee' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Furious Focus"] = { + ["name"] = "Furious Focus", + ["auto_add"] = true, + ["description"] = "When you are wielding a two-handed weapon or a one-handed weapon with two hands, and using the Power Attack feat, you do not suffer Power Attack’s penalty on melee attack rolls on the first attack you make each turn. You still suffer the penalty on any additional attacks, including attacks of opportunity.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["apply"] = { ["type"] = "string", ["value"] = "roll" }, + ["label"] = { + ["type"] = "string", + ["value"] = "Furious Focus; IF: CUSTOM(Power Attack 2-H); ATK: 1 [QBAB] ,melee", + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Mobility'] = { - ['name'] = 'Mobility', - ['auto_add'] = true, - ['description'] = 'You get a +4 dodge bonus to Armor Class against attacks of opportunity caused when you move out of or within a threatened area. A condition that makes you lose your Dexterity bonus to Armor Class (if any) also makes you lose dodge bonuses. Dodge bonuses stack with each other, unlike most types of bonuses.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['label'] = { ['type'] = 'string', ['value'] = 'Mobility; AC: 4 dodge,opportunity' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["Mobility"] = { + ["name"] = "Mobility", + ["auto_add"] = true, + ["description"] = "You get a +4 dodge bonus to Armor Class against attacks of opportunity caused when you move out of or within a threatened area. A condition that makes you lose your Dexterity bonus to Armor Class (if any) also makes you lose dodge bonuses. Dodge bonuses stack with each other, unlike most types of bonuses.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["label"] = { ["type"] = "string", ["value"] = "Mobility; AC: 4 dodge,opportunity" }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, - ['Power Attack'] = { - ['name'] = 'Power Attack', - ['description'] = 'You can choose to take a -1 penalty on all melee attack rolls and combat maneuver checks to gain a +2 bonus on all melee damage rolls. This bonus to damage is increased by half (+50%) if you are making an attack with a two-handed weapon, a one handed weapon using two hands, or a primary natural weapon that adds 1-1/2 times your Strength modifier on damage rolls. This bonus to damage is halved (-50%) if you are making an attack with an off-hand weapon or secondary natural weapon. When your base attack bonus reaches +4, and every 4 points thereafter, the penalty increases by -1 and the bonus to damage increases by +2. You must choose to use this feat before making an attack roll, and its effects last until your next turn. The bonus damage does not apply to touch attacks or effects that do not deal hit point damage.', - ['string_ability_type'] = 'Feats', - ['level'] = 0, - ['actions'] = { - ['zeffect-1'] = { - ['label'] = { ['type'] = 'string', ['value'] = 'Power Attack 1-H; ATK: -1 [-QBAB] ,melee; DMG: 2 [QBAB] [QBAB] ,melee' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, - }, - ['zeffect-2'] = { - ['label'] = { ['type'] = 'string', ['value'] = 'REMOVE: Power Attack 1-H; ATK: -1 [-QBAB] ,melee; DMG: 2 [QBAB] [QBAB] ,melee' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, - }, - ['zeffect-3'] = { - ['label'] = { ['type'] = 'string', ['value'] = 'Power Attack 2-H; ATK: -1 [-QBAB] ,melee; DMG: 3 [QBAB] [QBAB] [QBAB] ,melee' }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, - }, - ['zeffect-4'] = { - ['label'] = { - ['type'] = 'string', - ['value'] = 'REMOVE: Power Attack 2-H; ATK: -1 [-QBAB] ,melee; DMG: 3 [QBAB] [QBAB] [QBAB] ,melee', + ["Power Attack"] = { + ["name"] = "Power Attack", + ["description"] = "You can choose to take a -1 penalty on all melee attack rolls and combat maneuver checks to gain a +2 bonus on all melee damage rolls. This bonus to damage is increased by half (+50%) if you are making an attack with a two-handed weapon, a one handed weapon using two hands, or a primary natural weapon that adds 1-1/2 times your Strength modifier on damage rolls. This bonus to damage is halved (-50%) if you are making an attack with an off-hand weapon or secondary natural weapon. When your base attack bonus reaches +4, and every 4 points thereafter, the penalty increases by -1 and the bonus to damage increases by +2. You must choose to use this feat before making an attack roll, and its effects last until your next turn. The bonus damage does not apply to touch attacks or effects that do not deal hit point damage.", + ["string_ability_type"] = "Feats", + ["level"] = 0, + ["actions"] = { + ["zeffect-1"] = { + ["label"] = { + ["type"] = "string", + ["value"] = "Power Attack 1-H; ATK: -1 [-QBAB] ,melee; DMG: 2 [QBAB] [QBAB] ,melee", + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, + }, + ["zeffect-2"] = { + ["label"] = { + ["type"] = "string", + ["value"] = "REMOVE: Power Attack 1-H; ATK: -1 [-QBAB] ,melee; DMG: 2 [QBAB] [QBAB] ,melee", + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, + }, + ["zeffect-3"] = { + ["label"] = { + ["type"] = "string", + ["value"] = "Power Attack 2-H; ATK: -1 [-QBAB] ,melee; DMG: 3 [QBAB] [QBAB] [QBAB] ,melee", + }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, + }, + ["zeffect-4"] = { + ["label"] = { + ["type"] = "string", + ["value"] = "REMOVE: Power Attack 2-H; ATK: -1 [-QBAB] ,melee; DMG: 3 [QBAB] [QBAB] [QBAB] ,melee", }, - ['targeting'] = { ['type'] = 'string', ['value'] = 'self' }, - ['type'] = { ['type'] = 'string', ['value'] = 'effect' }, + ["targeting"] = { ["type"] = "string", ["value"] = "self" }, + ["type"] = { ["type"] = "string", ["value"] = "effect" }, }, }, }, diff --git a/scripts/UNPC_effectdescriptions.lua b/scripts/UNPC_effectdescriptions.lua index a5d6eac..70d4bda 100644 --- a/scripts/UNPC_effectdescriptions.lua +++ b/scripts/UNPC_effectdescriptions.lua @@ -6,39 +6,39 @@ -- luacheck: no max line length -- luacheck: globals conditionshelp conditionshelp = { - blinded = 'Fantasy Grounds Automation: AC:-2; GRANTCA; SKILL:-2 strength dexterity; SKILL:-4 search perception\nThe creature cannot see. It takes a –2 penalty to Armor Class, loses its Dexterity bonus to AC (if any), and takes a –4 penalty on most Strength-based and Dexterity-based skill checks and on opposed Perception skill checks. All checks and activities that rely on vision (such as reading and Perception checks based on sight) automatically fail. All opponents are considered to have total concealment (50% miss chance) against the blinded character. Blind creatures must make a DC 10 Acrobatics skill check to move faster than half speed. Creatures that fail this check fall prone. Characters who remain blinded for a long time grow accustomed to these drawbacks and can overcome some of them.', - climbing = 'Fantasy Grounds Automation: GRANTCA\nUsing Athletics, you can advance up, down, or across a slope, wall, or other steep incline (or a ceiling if it has handholds). You move at one-quarter your speed, though you can move at half your speed if you take a –5 penalty. If you fail the check by 4 or less, you make no progress. If you fail by 5 or more, you fall. A perfectly smooth vertical (or inverted) surface can’t be climbed.\nYou need both hands free to climb, but can cling with one hand while using the other to cast a spell or take some other action. You can’t use a shield while climbing. You lose your Dexterity bonus to AC while climbing. If you take damage while climbing, you must succeed at an Athletics check against the DC of the surface or fall.', - confused = 'A confused creature is mentally befuddled and cannot act normally. A confused creature cannot tell the difference between ally and foe, treating all creatures as enemies. Allies wishing to cast a beneficial spell that requires a touch on a confused creature must succeed on a melee touch attack. If a confused creature is attacked, it attacks the creature that last attacked it until that creature is dead or out of sight.\nA confused creature who can’t carry out the indicated action does nothing but babble incoherently. Attackers are not at any special advantage when attacking a confused creature. Any confused creature who is attacked automatically attacks its attackers on its next turn, as long as it is still confused when its turn comes. Note that a confused creature will not make attacks of opportunity against anything that it is not already devoted to attacking (either because of its most recent action or because it has just been attacked).\n01-25: Acts normally\n26-50: Does nothing but babble incoherently\n51-75: Deals 1d8 points of damage + Str modifier to self with item in hand\n76-100: Attacks nearest creature (for this purpose, a familiar counts as part of the subject’s self).', - cowering = 'Fantasy Grounds Automation: AC:-2\nThe character is frozen in fear and can take no actions. A cowering character takes a –2 penalty to Armor Class and loses his Dexterity bonus (if any).', - dazed = 'The creature is unable to act normally. A dazed creature can take no actions, but has no penalty to AC. A dazed condition typically lasts 1 round.', - dazzled = 'Fantasy Grounds Automation: ATK:-1; SKILL:-1 spot search perception\nThe creature is unable to see well because of overstimulation of the eyes. A dazzled creature takes a –1 penalty on attack rolls and sight-based Perception checks.', - deafened = 'Fantasy Grounds Automation: INIT: -4\nA deafened character cannot hear. He takes a –4 penalty on initiative checks, automatically fails Perception checks based on sound, takes a –4 penalty on opposed Perception checks, and has a 20% chance of spell failure when casting spells with verbal components. Characters who remain deafened for a long time grow accustomed to these drawbacks and can overcome some of them.', - entangled = 'Fantasy Grounds Automation: ATK:-2; DEX:-4\nThe character is ensnared. Being entangled impedes movement, but does not entirely prevent it unless the bonds are anchored to an immobile object or tethered by an opposing force. An entangled creature moves at half speed, cannot run or charge, and takes a –2 penalty on all attack rolls and a –4 penalty to Dexterity. An entangled character who attempts to cast a spell must make a concentration check (DC 15 + spell level) or lose the spell.', - exhausted = 'Fantasy Grounds Automation: DEX:-6; STR:-6\nAn exhausted character moves at half speed, cannot run or charge, and takes a –6 penalty to Strength and Dexterity. After 1 hour of complete rest, an exhausted character becomes fatigued. A fatigued character becomes exhausted by doing something else that would normally cause fatigue.', - fascinated = 'Fantasy Grounds Automation: SKILL:-4 spot listen perception\nA fascinated creature is entranced by a supernatural or spell effect. The creature stands or sits quietly, taking no actions other than to pay attention to the fascinating effect, for as long as the effect lasts. It takes a –4 penalty on skill checks made as reactions, such as Perception checks. Any potential threat, such as a hostile creature approaching, allows the fascinated creature a new saving throw against the fascinating effect. Any obvious threat, such as someone drawing a weapon, casting a spell, or aiming a ranged weapon at the fascinated creature, automatically breaks the effect. A fascinated creature’s ally may shake it free of the spell as a standard action.', - fatigued = 'Fantasy Grounds Automation: DEX:-2; STR:-2\nA fatigued character can neither run nor charge and takes a –2 penalty to Strength and Dexterity. Doing anything that would normally cause fatigue causes the fatigued character to become exhausted. After 8 hours of complete rest, fatigued characters are no longer fatigued.', - flatfooted = 'A character who has not yet acted during a combat is flat-footed, unable to react normally to the situation. A flat-footed character loses his Dexterity bonus to AC (if any) and cannot make attacks of opportunity.', - frightened = 'Fantasy Grounds Automation: ATK:-2; SAVE:-2; SKILL:-2; ABIL:-2\nA frightened creature flees from the source of its fear as best it can. If unable to flee, it may fight. A frightened creature takes a –2 penalty on all attack rolls, saving throws, skill checks, and ability checks. A frightened creature can use special abilities, including spells, to flee; indeed, the creature must use such means if they are the only way to escape./nFrightened is like shaken, except that the creature must flee if possible. Panicked is a more extreme state of fear.', - grappled = 'Fantasy Grounds Automation: GRANTCA; ATK: -2; DEX: -4\nA grappled creature is restrained by a creature, trap, or effect. Grappled creatures cannot move and take a –4 penalty to Dexterity. A grappled creature takes a –2 penalty on all attack rolls and combat maneuver checks, except those made to grapple or escape a grapple. In addition, grappled creatures can take no action that requires two hands to perform. A grappled character who attempts to cast a spell or use a spell-like ability must make a concentration check (DC 10 + grappler’s CMB + spell level, see Concentration), or lose the spell. Grappled creatures cannot make attacks of opportunity.\nA grappled creature cannot use Stealth to hide from the creature grappling it, even if a special ability, such as hide in plain sight, would normally allow it to do so. If a grappled creature becomes invisible, through a spell or other ability, it gains a +2 circumstance bonus on its CMD to avoid being grappled, but receives no other benefit.', - helpless = 'Fantasy Grounds Automation: AC:-4 melee\nA helpless character is paralyzed, held, bound, sleeping, unconscious, or otherwise completely at an opponent’s mercy. A helpless target is treated as having a Dexterity of 0 (–5 modifier). Melee attacks against a helpless target get a +4 bonus (equivalent to attacking a prone target). Ranged attacks get no special bonus against helpless targets. Rogues can sneak attack helpless targets.\nAs a full-round action, an enemy can use a melee weapon to deliver a coup de grace to a helpless foe. An enemy can also use a bow or crossbow, provided he is adjacent to the target. The attacker automatically hits and scores a critical hit. (A rogue also gets his sneak attack damage bonus against a helpless foe when delivering a coup de grace.) If the defender survives, he must make a Fortitude save (DC 10 + damage dealt) or die. Delivering a coup de grace provokes attacks of opportunity.\nCreatures that are immune to critical hits do not take critical damage, nor do they need to make Fortitude saves to avoid being killed by a coup de grace.', - incorporeal = 'Creatures with the incorporeal condition do not have a physical body. Incorporeal creatures are immune to all nonmagical attack forms. Incorporeal creatures take half damage (50%) from magic weapons, spells, spell-like effects, and supernatural effects. Incorporeal creatures take full damage from other incorporeal creatures and effects, as well as all force effects.', - invisible = 'Fantasy Grounds Automation: ATK:2; CA; TCONC\nInvisible creatures are visually undetectable. An invisible creature gains a +2 bonus on attack rolls against a sighted opponent, and ignores its opponent’s Dexterity bonus to AC (if any). See Invisibility, under Special Abilities.', - kneeling = 'Fantasy Grounds Automation: AC: -2 melee; AC: 2 ranged', - nauseated = 'Creatures with the nauseated condition experience stomach distress. Nauseated creatures are unable to attack, cast spells, concentrate on spells, or do anything else requiring attention. The only action such a character can take is a single move actions per turn.', - panicked = 'Fantasy Grounds Automation: ATK:-2; SAVE:-2; SKILL:-2; ABIL:-2\nA panicked creature must drop anything it holds and flee at top speed from the source of its fear, as well as any other dangers it encounters, along a random path. It can’t take any other actions. In addition, the creature takes a –2 penalty on all saving throws, skill checks, and ability checks. If cornered, a panicked creature cowers and does not attack, typically using the total defense action in combat. A panicked creature can use special abilities, including spells, to flee; indeed, the creature must use such means if they are the only way to escape.', - paralyzed = 'Fantasy Grounds Automation: AC:-4 melee\nA paralyzed character is frozen in place and unable to move or act. A paralyzed character has effective Dexterity and Strength scores of 0 and is helpless, but can take purely mental actions. A winged creature f lying in the air at the time that it becomes paralyzed cannot flap its wings and falls. A paralyzed swimmer can’t swim and may drown. A creature can move through a space occupied by a paralyzed creature—ally or not. Each square occupied by a paralyzed creature, however, counts as 2 squares to move through.', - petrified = 'Fantasy Grounds Automation: AC:-4 melee\nA petrified character has been turned to stone and is considered unconscious. If a petrified character cracks or breaks, but the broken pieces are joined with the body as he returns to flesh, he is unharmed. If the character’s petrified body is incomplete when it returns to flesh, the body is likewise incomplete and there is some amount of permanent hit point loss and/or debilitation.', - pinned = 'Fantasy Grounds Automation: GRANTCA, AC:-4\nA pinned creature is tightly bound and can take few actions. A pinned creature cannot move and is denied its Dexterity bonus. A pinned character also takes an additional –4 penalty to his Armor Class. A pinned creature is limited in the actions that it can take. A pinned creature can always attempt to free itself, usually through a combat maneuver check or Escape Artist check. A pinned creature can take verbal and mental actions, but cannot cast any spells that require a somatic or material component. A pinned character who attempts to cast a spell or use a spell-like ability must make a concentration check (DC 10 + grappler’s CMB + spell level) or lose the spell. Pinned is a more severe version of grappled, and their effects do not stack.', - prone = 'Fantasy Grounds Automation: ATK:-4 melee; AC:-4 melee; AC:4 ranged\nThe character is lying on the ground. A prone attacker has a –4 penalty on melee attack rolls and cannot use a ranged weapon (except for a crossbow). A prone defender gains a +4 bonus to Armor Class against ranged attacks, but takes a –4 penalty to AC against melee attacks.\nStanding up is a move-equivalent action that provokes an attack of opportunity.', - rebuked = 'Fantasy Grounds Automation: AC:-2', - running = 'Fantasy Grounds Automation: GRANTCA\nYou can run as a full-round action. If you do, you do not also get a 5-foot step. When you run, you can move up to four times your speed in a straight line (or three times your speed if you’re in heavy armor). You lose any Dexterity bonus to AC unless you have the Run feat.\nYou can run for a number of rounds equal to your Constitution score, but after that you must make a DC 10 Constitution check to continue running. You must check again each round in which you continue to run, and the DC of this check increases by 1 for each check you have made. When you fail this check, you must stop running. A character who has run to his limit must rest for 1 minute (10 rounds) before running again. During a rest period, a character can move no faster than a normal move action.\nYou can’t run across difficult terrain or if you can’t see where you’re going.\nA run represents a speed of about 13 miles per hour for an unencumbered human.', - shaken = 'Fantasy Grounds Automation: ATK:-2; SAVE:-2; SKILL:-2; ABIL:-2\nA shaken character takes a –2 penalty on attack rolls, saving throws, skill checks, and ability checks. Shaken is a less severe state of fear than frightened or panicked.', - sickened = 'Fantasy Grounds Automation: ATK:-2; DMG:-2; SAVE:-2; SKILL:-2; ABIL:-2\nThe character takes a –2 penalty on all attack rolls, weapon damage rolls, saving throws, skill checks, and ability checks.', - sitting = 'Fantasy Grounds Automation: AC:-2 melee; AC:2 ranged', + blinded = "Fantasy Grounds Automation: AC:-2; GRANTCA; SKILL:-2 strength dexterity; SKILL:-4 search perception\nThe creature cannot see. It takes a –2 penalty to Armor Class, loses its Dexterity bonus to AC (if any), and takes a –4 penalty on most Strength-based and Dexterity-based skill checks and on opposed Perception skill checks. All checks and activities that rely on vision (such as reading and Perception checks based on sight) automatically fail. All opponents are considered to have total concealment (50% miss chance) against the blinded character. Blind creatures must make a DC 10 Acrobatics skill check to move faster than half speed. Creatures that fail this check fall prone. Characters who remain blinded for a long time grow accustomed to these drawbacks and can overcome some of them.", + climbing = "Fantasy Grounds Automation: GRANTCA\nUsing Athletics, you can advance up, down, or across a slope, wall, or other steep incline (or a ceiling if it has handholds). You move at one-quarter your speed, though you can move at half your speed if you take a –5 penalty. If you fail the check by 4 or less, you make no progress. If you fail by 5 or more, you fall. A perfectly smooth vertical (or inverted) surface can’t be climbed.\nYou need both hands free to climb, but can cling with one hand while using the other to cast a spell or take some other action. You can’t use a shield while climbing. You lose your Dexterity bonus to AC while climbing. If you take damage while climbing, you must succeed at an Athletics check against the DC of the surface or fall.", + confused = "A confused creature is mentally befuddled and cannot act normally. A confused creature cannot tell the difference between ally and foe, treating all creatures as enemies. Allies wishing to cast a beneficial spell that requires a touch on a confused creature must succeed on a melee touch attack. If a confused creature is attacked, it attacks the creature that last attacked it until that creature is dead or out of sight.\nA confused creature who can’t carry out the indicated action does nothing but babble incoherently. Attackers are not at any special advantage when attacking a confused creature. Any confused creature who is attacked automatically attacks its attackers on its next turn, as long as it is still confused when its turn comes. Note that a confused creature will not make attacks of opportunity against anything that it is not already devoted to attacking (either because of its most recent action or because it has just been attacked).\n01-25: Acts normally\n26-50: Does nothing but babble incoherently\n51-75: Deals 1d8 points of damage + Str modifier to self with item in hand\n76-100: Attacks nearest creature (for this purpose, a familiar counts as part of the subject’s self).", + cowering = "Fantasy Grounds Automation: AC:-2\nThe character is frozen in fear and can take no actions. A cowering character takes a –2 penalty to Armor Class and loses his Dexterity bonus (if any).", + dazed = "The creature is unable to act normally. A dazed creature can take no actions, but has no penalty to AC. A dazed condition typically lasts 1 round.", + dazzled = "Fantasy Grounds Automation: ATK:-1; SKILL:-1 spot search perception\nThe creature is unable to see well because of overstimulation of the eyes. A dazzled creature takes a –1 penalty on attack rolls and sight-based Perception checks.", + deafened = "Fantasy Grounds Automation: INIT: -4\nA deafened character cannot hear. He takes a –4 penalty on initiative checks, automatically fails Perception checks based on sound, takes a –4 penalty on opposed Perception checks, and has a 20% chance of spell failure when casting spells with verbal components. Characters who remain deafened for a long time grow accustomed to these drawbacks and can overcome some of them.", + entangled = "Fantasy Grounds Automation: ATK:-2; DEX:-4\nThe character is ensnared. Being entangled impedes movement, but does not entirely prevent it unless the bonds are anchored to an immobile object or tethered by an opposing force. An entangled creature moves at half speed, cannot run or charge, and takes a –2 penalty on all attack rolls and a –4 penalty to Dexterity. An entangled character who attempts to cast a spell must make a concentration check (DC 15 + spell level) or lose the spell.", + exhausted = "Fantasy Grounds Automation: DEX:-6; STR:-6\nAn exhausted character moves at half speed, cannot run or charge, and takes a –6 penalty to Strength and Dexterity. After 1 hour of complete rest, an exhausted character becomes fatigued. A fatigued character becomes exhausted by doing something else that would normally cause fatigue.", + fascinated = "Fantasy Grounds Automation: SKILL:-4 spot listen perception\nA fascinated creature is entranced by a supernatural or spell effect. The creature stands or sits quietly, taking no actions other than to pay attention to the fascinating effect, for as long as the effect lasts. It takes a –4 penalty on skill checks made as reactions, such as Perception checks. Any potential threat, such as a hostile creature approaching, allows the fascinated creature a new saving throw against the fascinating effect. Any obvious threat, such as someone drawing a weapon, casting a spell, or aiming a ranged weapon at the fascinated creature, automatically breaks the effect. A fascinated creature’s ally may shake it free of the spell as a standard action.", + fatigued = "Fantasy Grounds Automation: DEX:-2; STR:-2\nA fatigued character can neither run nor charge and takes a –2 penalty to Strength and Dexterity. Doing anything that would normally cause fatigue causes the fatigued character to become exhausted. After 8 hours of complete rest, fatigued characters are no longer fatigued.", + flatfooted = "A character who has not yet acted during a combat is flat-footed, unable to react normally to the situation. A flat-footed character loses his Dexterity bonus to AC (if any) and cannot make attacks of opportunity.", + frightened = "Fantasy Grounds Automation: ATK:-2; SAVE:-2; SKILL:-2; ABIL:-2\nA frightened creature flees from the source of its fear as best it can. If unable to flee, it may fight. A frightened creature takes a –2 penalty on all attack rolls, saving throws, skill checks, and ability checks. A frightened creature can use special abilities, including spells, to flee; indeed, the creature must use such means if they are the only way to escape./nFrightened is like shaken, except that the creature must flee if possible. Panicked is a more extreme state of fear.", + grappled = "Fantasy Grounds Automation: GRANTCA; ATK: -2; DEX: -4\nA grappled creature is restrained by a creature, trap, or effect. Grappled creatures cannot move and take a –4 penalty to Dexterity. A grappled creature takes a –2 penalty on all attack rolls and combat maneuver checks, except those made to grapple or escape a grapple. In addition, grappled creatures can take no action that requires two hands to perform. A grappled character who attempts to cast a spell or use a spell-like ability must make a concentration check (DC 10 + grappler’s CMB + spell level, see Concentration), or lose the spell. Grappled creatures cannot make attacks of opportunity.\nA grappled creature cannot use Stealth to hide from the creature grappling it, even if a special ability, such as hide in plain sight, would normally allow it to do so. If a grappled creature becomes invisible, through a spell or other ability, it gains a +2 circumstance bonus on its CMD to avoid being grappled, but receives no other benefit.", + helpless = "Fantasy Grounds Automation: AC:-4 melee\nA helpless character is paralyzed, held, bound, sleeping, unconscious, or otherwise completely at an opponent’s mercy. A helpless target is treated as having a Dexterity of 0 (–5 modifier). Melee attacks against a helpless target get a +4 bonus (equivalent to attacking a prone target). Ranged attacks get no special bonus against helpless targets. Rogues can sneak attack helpless targets.\nAs a full-round action, an enemy can use a melee weapon to deliver a coup de grace to a helpless foe. An enemy can also use a bow or crossbow, provided he is adjacent to the target. The attacker automatically hits and scores a critical hit. (A rogue also gets his sneak attack damage bonus against a helpless foe when delivering a coup de grace.) If the defender survives, he must make a Fortitude save (DC 10 + damage dealt) or die. Delivering a coup de grace provokes attacks of opportunity.\nCreatures that are immune to critical hits do not take critical damage, nor do they need to make Fortitude saves to avoid being killed by a coup de grace.", + incorporeal = "Creatures with the incorporeal condition do not have a physical body. Incorporeal creatures are immune to all nonmagical attack forms. Incorporeal creatures take half damage (50%) from magic weapons, spells, spell-like effects, and supernatural effects. Incorporeal creatures take full damage from other incorporeal creatures and effects, as well as all force effects.", + invisible = "Fantasy Grounds Automation: ATK:2; CA; TCONC\nInvisible creatures are visually undetectable. An invisible creature gains a +2 bonus on attack rolls against a sighted opponent, and ignores its opponent’s Dexterity bonus to AC (if any). See Invisibility, under Special Abilities.", + kneeling = "Fantasy Grounds Automation: AC: -2 melee; AC: 2 ranged", + nauseated = "Creatures with the nauseated condition experience stomach distress. Nauseated creatures are unable to attack, cast spells, concentrate on spells, or do anything else requiring attention. The only action such a character can take is a single move actions per turn.", + panicked = "Fantasy Grounds Automation: ATK:-2; SAVE:-2; SKILL:-2; ABIL:-2\nA panicked creature must drop anything it holds and flee at top speed from the source of its fear, as well as any other dangers it encounters, along a random path. It can’t take any other actions. In addition, the creature takes a –2 penalty on all saving throws, skill checks, and ability checks. If cornered, a panicked creature cowers and does not attack, typically using the total defense action in combat. A panicked creature can use special abilities, including spells, to flee; indeed, the creature must use such means if they are the only way to escape.", + paralyzed = "Fantasy Grounds Automation: AC:-4 melee\nA paralyzed character is frozen in place and unable to move or act. A paralyzed character has effective Dexterity and Strength scores of 0 and is helpless, but can take purely mental actions. A winged creature f lying in the air at the time that it becomes paralyzed cannot flap its wings and falls. A paralyzed swimmer can’t swim and may drown. A creature can move through a space occupied by a paralyzed creature—ally or not. Each square occupied by a paralyzed creature, however, counts as 2 squares to move through.", + petrified = "Fantasy Grounds Automation: AC:-4 melee\nA petrified character has been turned to stone and is considered unconscious. If a petrified character cracks or breaks, but the broken pieces are joined with the body as he returns to flesh, he is unharmed. If the character’s petrified body is incomplete when it returns to flesh, the body is likewise incomplete and there is some amount of permanent hit point loss and/or debilitation.", + pinned = "Fantasy Grounds Automation: GRANTCA, AC:-4\nA pinned creature is tightly bound and can take few actions. A pinned creature cannot move and is denied its Dexterity bonus. A pinned character also takes an additional –4 penalty to his Armor Class. A pinned creature is limited in the actions that it can take. A pinned creature can always attempt to free itself, usually through a combat maneuver check or Escape Artist check. A pinned creature can take verbal and mental actions, but cannot cast any spells that require a somatic or material component. A pinned character who attempts to cast a spell or use a spell-like ability must make a concentration check (DC 10 + grappler’s CMB + spell level) or lose the spell. Pinned is a more severe version of grappled, and their effects do not stack.", + prone = "Fantasy Grounds Automation: ATK:-4 melee; AC:-4 melee; AC:4 ranged\nThe character is lying on the ground. A prone attacker has a –4 penalty on melee attack rolls and cannot use a ranged weapon (except for a crossbow). A prone defender gains a +4 bonus to Armor Class against ranged attacks, but takes a –4 penalty to AC against melee attacks.\nStanding up is a move-equivalent action that provokes an attack of opportunity.", + rebuked = "Fantasy Grounds Automation: AC:-2", + running = "Fantasy Grounds Automation: GRANTCA\nYou can run as a full-round action. If you do, you do not also get a 5-foot step. When you run, you can move up to four times your speed in a straight line (or three times your speed if you’re in heavy armor). You lose any Dexterity bonus to AC unless you have the Run feat.\nYou can run for a number of rounds equal to your Constitution score, but after that you must make a DC 10 Constitution check to continue running. You must check again each round in which you continue to run, and the DC of this check increases by 1 for each check you have made. When you fail this check, you must stop running. A character who has run to his limit must rest for 1 minute (10 rounds) before running again. During a rest period, a character can move no faster than a normal move action.\nYou can’t run across difficult terrain or if you can’t see where you’re going.\nA run represents a speed of about 13 miles per hour for an unencumbered human.", + shaken = "Fantasy Grounds Automation: ATK:-2; SAVE:-2; SKILL:-2; ABIL:-2\nA shaken character takes a –2 penalty on attack rolls, saving throws, skill checks, and ability checks. Shaken is a less severe state of fear than frightened or panicked.", + sickened = "Fantasy Grounds Automation: ATK:-2; DMG:-2; SAVE:-2; SKILL:-2; ABIL:-2\nThe character takes a –2 penalty on all attack rolls, weapon damage rolls, saving throws, skill checks, and ability checks.", + sitting = "Fantasy Grounds Automation: AC:-2 melee; AC:2 ranged", slowed = "Fantasy Grounds Automation: ATK:-1; AC:-1; REF:-1\nAn affected creature moves and attacks at a drastically slowed rate. Creatures affected by this spell are staggered and can take only a single move action or standard action each turn, but not both (nor may it take full-round actions). Additionally, it takes a –1 penalty on attack rolls, AC, and Reflex saves. A slowed creature moves at half its normal speed (round down to the next 5-foot increment), which affects the creature's jumping distance as normal for decreased speed.", - squeezing = 'Fantasy Grounds Automation: AC:-4; ATK:-4\nIn some cases, you may have to squeeze into or through an area that isn’t as wide as the space you take up. You can squeeze through or into a space that is at least half as wide as your normal space. Each move into or through a narrow space counts as if it were 2 squares, and while squeezed in a narrow space, you take a –4 penalty on attack rolls and a –4 penalty to AC.', - stable = 'Fantasy Grounds Automation: no automatic death saving throws\nA character who was dying but who has stopped losing hit points each round and still has negative hit points is stable. The character is no longer dying, but is still unconscious. If the character has become stable because of aid from another character (such as a Heal check or magical healing), then the character no longer loses hit points. The character can make a DC 10 Constitution check each hour to become conscious and disabled (even though his hit points are still negative). The character takes a penalty on this roll equal to his negative hit point total.\nIf a character has become stable on his own and hasn’t had help, he is still at risk of losing hit points. Each hour he can make a Constitution check to become stable (as a character that has received aid), but each failed check causes him to lose 1 hit point.', - stunned = 'Fantasy Grounds Automation: AC:-2; GRANTCA\nA stunned creature drops everything held, can’t take actions, takes a –2 penalty to AC, and loses its Dexterity bonus to AC (if any).', - turned = 'Fantasy Grounds Automation: AC:-2', - unconscious = 'Fantasy Grounds Automation: AC:-4 melee\nUnconscious creatures are knocked out and helpless. Unconsciousness can result from having negative hit points (but not more than the creature’s Constitution score), or from nonlethal damage in excess of current hit points.', + squeezing = "Fantasy Grounds Automation: AC:-4; ATK:-4\nIn some cases, you may have to squeeze into or through an area that isn’t as wide as the space you take up. You can squeeze through or into a space that is at least half as wide as your normal space. Each move into or through a narrow space counts as if it were 2 squares, and while squeezed in a narrow space, you take a –4 penalty on attack rolls and a –4 penalty to AC.", + stable = "Fantasy Grounds Automation: no automatic death saving throws\nA character who was dying but who has stopped losing hit points each round and still has negative hit points is stable. The character is no longer dying, but is still unconscious. If the character has become stable because of aid from another character (such as a Heal check or magical healing), then the character no longer loses hit points. The character can make a DC 10 Constitution check each hour to become conscious and disabled (even though his hit points are still negative). The character takes a penalty on this roll equal to his negative hit point total.\nIf a character has become stable on his own and hasn’t had help, he is still at risk of losing hit points. Each hour he can make a Constitution check to become stable (as a character that has received aid), but each failed check causes him to lose 1 hit point.", + stunned = "Fantasy Grounds Automation: AC:-2; GRANTCA\nA stunned creature drops everything held, can’t take actions, takes a –2 penalty to AC, and loses its Dexterity bonus to AC (if any).", + turned = "Fantasy Grounds Automation: AC:-2", + unconscious = "Fantasy Grounds Automation: AC:-4 melee\nUnconscious creatures are knocked out and helpless. Unconsciousness can result from having negative hit points (but not more than the creature’s Constitution score), or from nonlethal damage in excess of current hit points.", } diff --git a/scripts/UNPC_upgradespells.lua b/scripts/UNPC_upgradespells.lua index 59dc7d7..cc63081 100644 --- a/scripts/UNPC_upgradespells.lua +++ b/scripts/UNPC_upgradespells.lua @@ -5,99 +5,121 @@ -- luacheck: globals array_modules -- Modules to check for spells array_modules = { - ['SpellbookExtended'] = { ['name'] = '@PFRPG - Spellbook Extended', ['prefix'] = 'spelldesc.' }, - ['Spellbook'] = { ['name'] = '@PFRPG - Spellbook', ['prefix'] = 'spelldesc.' }, + ["SpellbookExtended"] = { ["name"] = "@PFRPG - Spellbook Extended", ["prefix"] = "spelldesc." }, + ["Spellbook"] = { ["name"] = "@PFRPG - Spellbook", ["prefix"] = "spelldesc." }, } -- -- SPELL ACTION REPLACEMENT FUNCTIONS -- local function trim_spell_name(string_spell_name) - local tFormats = { ['Greater'] = false, ['Lesser'] = false, ['Communal'] = false, ['Mass'] = false } - local tTrims = { ['Maximized'] = false, ['Heightened'] = false, ['Empowered'] = false, ['Quickened'] = false } + local tFormats = { ["Greater"] = false, ["Lesser"] = false, ["Communal"] = false, ["Mass"] = false } + local tTrims = { ["Maximized"] = false, ["Heightened"] = false, ["Empowered"] = false, ["Quickened"] = false } local string_spell_name_lower = string_spell_name:lower() -- remove tags from spell name for s, _ in pairs(tFormats) do local nS, nE = string_spell_name_lower:find(s:lower()) if nS and nE then - string_spell_name = string_spell_name:sub(0, nS - 1) .. string_spell_name:sub(nE + 1, string_spell_name:len()) + string_spell_name = string_spell_name:sub(0, nS - 1) + .. string_spell_name:sub(nE + 1, string_spell_name:len()) tFormats[s] = true end end for s, _ in pairs(tTrims) do local nS, nE = string_spell_name_lower:find(s:lower()) if nS and nE then - string_spell_name = string_spell_name:sub(0, nS - 1) .. string_spell_name:sub(nE + 1, string_spell_name:len()) + string_spell_name = string_spell_name:sub(0, nS - 1) + .. string_spell_name:sub(nE + 1, string_spell_name:len()) tTrims[s] = true end end -- remove certain sets of characters - string_spell_name = string_spell_name:gsub('%u%u%u%u', '') - string_spell_name = string_spell_name:gsub('%u%u%u', '') - string_spell_name = string_spell_name:gsub('AP%d+', '') - string_spell_name = string_spell_name:gsub('%u%u', '') - string_spell_name = string_spell_name:gsub('.+:', '') - string_spell_name = string_spell_name:gsub(',.+', '') - string_spell_name = string_spell_name:gsub('%[.-%]', '') - string_spell_name = string_spell_name:gsub('%(.-%)', '') - string_spell_name = string_spell_name:gsub('%A+', '') + string_spell_name = string_spell_name:gsub("%u%u%u%u", "") + string_spell_name = string_spell_name:gsub("%u%u%u", "") + string_spell_name = string_spell_name:gsub("AP%d+", "") + string_spell_name = string_spell_name:gsub("%u%u", "") + string_spell_name = string_spell_name:gsub(".+:", "") + string_spell_name = string_spell_name:gsub(",.+", "") + string_spell_name = string_spell_name:gsub("%[.-%]", "") + string_spell_name = string_spell_name:gsub("%(.-%)", "") + string_spell_name = string_spell_name:gsub("%A+", "") -- remove uppercase D or M at end of name - local number_name_end = string.find(string_spell_name, 'D', string.len(string_spell_name)) - or string.find(string_spell_name, 'M', string.len(string_spell_name)) - if number_name_end then string_spell_name = string_spell_name:sub(1, number_name_end - 1) end + local number_name_end = string.find(string_spell_name, "D", string.len(string_spell_name)) + or string.find(string_spell_name, "M", string.len(string_spell_name)) + if number_name_end then + string_spell_name = string_spell_name:sub(1, number_name_end - 1) + end -- convert to lower-case string_spell_name_lower = string_spell_name:lower() -- append relevant tags to end of spell name for s, v in pairs(tFormats) do - if v == true then string_spell_name_lower = string.format('%s%s', string_spell_name_lower, s:lower()) end + if v == true then + string_spell_name_lower = string.format("%s%s", string_spell_name_lower, s:lower()) + end end - return string_spell_name_lower, tTrims['Maximized'], tTrims['Empowered'] + return string_spell_name_lower, tTrims["Maximized"], tTrims["Empowered"] end local function replace_action_nodes(node_spell, node_reference_spell, is_maximized, is_empowered) - if not node_reference_spell then return end + if not node_reference_spell then + return + end - local node_reference_actions = DB.getChild(node_reference_spell, 'actions') - if not node_reference_actions then return end + local node_reference_actions = DB.getChild(node_reference_spell, "actions") + if not node_reference_actions then + return + end - local node_actions = DB.createChild(node_spell, 'actions') + local node_actions = DB.createChild(node_spell, "actions") DB.deleteChildren(node_actions) for _, node_reference_action in ipairs(DB.getChildList(node_reference_actions)) do DB.copyNode(node_reference_action, DB.createChild(node_actions, DB.getName(node_reference_action))) end - local node_spell_new_damage = DB.getChild(node_actions, 'damage') - if not node_spell_new_damage then return end + local node_spell_new_damage = DB.getChild(node_actions, "damage") + if not node_spell_new_damage then + return + end -- set up metamagic if applicable - if is_empowered then DB.setValue(node_spell_new_damage, 'meta', 'string', 'empower') end - if is_maximized then DB.setValue(node_spell_new_damage, 'meta', 'string', 'maximize') end + if is_empowered then + DB.setValue(node_spell_new_damage, "meta", "string", "empower") + end + if is_maximized then + DB.setValue(node_spell_new_damage, "meta", "string", "maximize") + end end local function add_spell_description(node_spell, node_reference_spell) - if not node_reference_spell or not node_spell or type(node_spell) ~= 'databasenode' then return end - local sOrigSpellDesc = DB.getValue(node_spell, 'description', '') - if sOrigSpellDesc ~= '' and sOrigSpellDesc ~= '

' then return end - - DB.deleteChild(node_spell, 'description') - local string_full_description = DB.getValue(node_reference_spell, 'description', '

') - DB.setValue(node_spell, 'description_full', 'formattedtext', string_full_description) - DB.setValue(node_spell, 'description', 'formattedtext', string_full_description) + if not node_reference_spell or not node_spell or type(node_spell) ~= "databasenode" then + return + end + local sOrigSpellDesc = DB.getValue(node_spell, "description", "") + if sOrigSpellDesc ~= "" and sOrigSpellDesc ~= "

" then + return + end + + DB.deleteChild(node_spell, "description") + local string_full_description = DB.getValue(node_reference_spell, "description", "

") + DB.setValue(node_spell, "description_full", "formattedtext", string_full_description) + DB.setValue(node_spell, "description", "formattedtext", string_full_description) SpellManager.convertSpellDescToString(node_spell) end local function add_spell_information(node_spell, node_reference_spell) - if not node_reference_spell or not node_spell then return end + if not node_reference_spell or not node_spell then + return + end for _, node_reference_spell_subnode in ipairs(DB.getChildList(node_reference_spell)) do local string_node_name = DB.getName(node_reference_spell_subnode) - if string_node_name ~= 'description' and string_node_name ~= 'name' then + if string_node_name ~= "description" and string_node_name ~= "name" then if not DB.getChild(node_spell, string_node_name) then local string_node_type = DB.getType(node_reference_spell_subnode) local node_spell_subnode = DB.createChild(node_spell, string_node_name, string_node_type) @@ -109,18 +131,23 @@ end local function find_reference_spell(string_spell_name) for _, table_module_data in pairs(array_modules) do - local node_reference_spell = DB.findNode(table_module_data['prefix'] .. string_spell_name .. table_module_data['name']) - if node_reference_spell then return node_reference_spell end + local node_reference_spell = + DB.findNode(table_module_data["prefix"] .. string_spell_name .. table_module_data["name"]) + if node_reference_spell then + return node_reference_spell + end end end local function replace_spell_actions(node_spell) - local string_spell_name, is_maximized, is_empowered = trim_spell_name(DB.getValue(node_spell, 'name', '')) + local string_spell_name, is_maximized, is_empowered = trim_spell_name(DB.getValue(node_spell, "name", "")) --Debug.chat(type(node_spell)) local node_reference_spell = find_reference_spell(string_spell_name) --Debug.chat(node_reference_spell, type(node_reference_spell)) - if not node_reference_spell then return end + if not node_reference_spell then + return + end replace_action_nodes(node_spell, node_reference_spell, is_maximized, is_empowered) add_spell_description(node_spell, node_reference_spell) @@ -130,17 +157,17 @@ local function replace_spell_actions(node_spell) end local function find_spell_nodes(nodeEntry) - for _, nodeSpellset in ipairs(DB.getChildList(nodeEntry, 'spellset')) do - for _, nodeSpellLevel in ipairs(DB.getChildList(nodeSpellset, 'levels')) do - for _, nodeSpell in ipairs(DB.getChildList(nodeSpellLevel, 'spells')) do + for _, nodeSpellset in ipairs(DB.getChildList(nodeEntry, "spellset")) do + for _, nodeSpellLevel in ipairs(DB.getChildList(nodeSpellset, "levels")) do + for _, nodeSpell in ipairs(DB.getChildList(nodeSpellLevel, "spells")) do --Debug.chat(type(nodeSpell)) - if DB.getType(nodeSpell) == 'node' and type(nodeSpell) ~= 'error' then - local sSpellName = DB.getValue(nodeSpell, 'name', '') - if not string.find(sSpellName, '[LOCK]') and not string.match(sSpellName, '%(Mythic.*%)') then + if DB.getType(nodeSpell) == "node" and type(nodeSpell) ~= "error" then + local sSpellName = DB.getValue(nodeSpell, "name", "") + if not string.find(sSpellName, "[LOCK]") and not string.match(sSpellName, "%(Mythic.*%)") then replace_spell_actions(nodeSpell) end --Debug.console('nodeSpell', nodeSpell) - --else + --else --Debug.console('nodeSpell', nodeSpell) --Debug.console('nodeSpell.getType', DB.getType(nodeSpell)) --Debug.console('nodeSpell.getValue', DB.getValue(nodeSpell)) @@ -158,13 +185,15 @@ end -- @param s input, a string of values separated by semicolons -- @return t output, an indexed table of values local function string_to_table(string_input) - if not string_input or string_input == '' then return {} end + if not string_input or string_input == "" then + return {} + end - string_input = string_input .. ';' -- ending semicolon + string_input = string_input .. ";" -- ending semicolon local table_output = {} -- table to collect fields local number_field_start = 1 repeat - local number_nexti = string.find(string_input, ';', number_field_start) + local number_nexti = string.find(string_input, ";", number_field_start) table.insert(table_output, string.sub(string_input, number_field_start, number_nexti - 1)) number_field_start = number_nexti + 1 until number_field_start > string.len(string_input) @@ -175,26 +204,26 @@ end --- This function adds a link to matching creature maladies. -- To work, it needs the malady node and npc node. local function add_malady_link(node_malady, node_npc) - local table_malady_npcs = string_to_table(DB.getValue(node_malady, 'npc')) or {} + local table_malady_npcs = string_to_table(DB.getValue(node_malady, "npc")) or {} if table_malady_npcs ~= {} then for _, string_malady_linked_npc in pairs(table_malady_npcs) do - local string_difficulty_class = (string_malady_linked_npc:match(' %(DC %d+%)')) or '' - string_malady_linked_npc = string_malady_linked_npc:gsub(' %(DC %d+%)', '') - string_malady_linked_npc = string.lower(string_malady_linked_npc:gsub('%A', '')) - local string_npc_name = DB.getValue(node_npc, 'name') - string_npc_name = string.lower(string_npc_name:gsub('%A', '')) + local string_difficulty_class = (string_malady_linked_npc:match(" %(DC %d+%)")) or "" + string_malady_linked_npc = string_malady_linked_npc:gsub(" %(DC %d+%)", "") + string_malady_linked_npc = string.lower(string_malady_linked_npc:gsub("%A", "")) + local string_npc_name = DB.getValue(node_npc, "name") + string_npc_name = string.lower(string_npc_name:gsub("%A", "")) if string_malady_linked_npc == string_npc_name then - local string_description = DB.getValue(node_npc, 'text', '') - local string_malady_name = DB.getValue(node_malady, 'name', '') + local string_description = DB.getValue(node_npc, "text", "") + local string_malady_name = DB.getValue(node_malady, "name", "") local string_malady_link = ( 'Malady: ' .. string_malady_name .. string_difficulty_class - .. '' + .. "" ) - DB.setValue(node_npc, 'text', 'formattedtext', string_malady_link .. string_description) + DB.setValue(node_npc, "text", "formattedtext", string_malady_link .. string_description) end end end @@ -205,14 +234,14 @@ end -- It does nothing if the DiseaseTracker script isn't found. local function search_for_maladies(node_npc) if DiseaseTracker then - if DB.getValue(node_npc, 'name') then - if DB.findNode('reference.diseases@*') then - for _, node_malady in ipairs(DB.getChildList('reference.diseases@*')) do + if DB.getValue(node_npc, "name") then + if DB.findNode("reference.diseases@*") then + for _, node_malady in ipairs(DB.getChildList("reference.diseases@*")) do add_malady_link(node_malady, node_npc) end end - if DB.findNode('disease') then - for _, node_malady in ipairs(DB.getChildList('disease')) do + if DB.findNode("disease") then + for _, node_malady in ipairs(DB.getChildList("disease")) do add_malady_link(node_malady, node_npc) end end @@ -227,69 +256,104 @@ end local function add_ability_automation(node_npc, table_ability_information, number_rank, string_parenthetical) if not node_npc - or table_ability_information['name'] == '' + or table_ability_information["name"] == "" or not table_ability_information or table_ability_information == {} - or (table_ability_information['daily_uses'] and table_ability_information['daily_uses'] < 0) - or table_ability_information['level'] < 0 - or table_ability_information['level'] > 9 - or not table_ability_information['actions'] + or (table_ability_information["daily_uses"] and table_ability_information["daily_uses"] < 0) + or table_ability_information["level"] < 0 + or table_ability_information["level"] > 9 + or not table_ability_information["actions"] then return end -- create spellset and intermediate subnodes - local node_spellset = DB.createChild(node_npc, 'spellset') - local node_spellclass = DB.createChild(node_spellset, table_ability_information['string_ability_type'] or 'Abilities') - local node_spelllevel = DB.createChild(DB.createChild(node_spellclass, 'levels'), 'level' .. table_ability_information['level']) - local node_ability = DB.createChild(DB.createChild(node_spelllevel, 'spells')) + local node_spellset = DB.createChild(node_npc, "spellset") + local node_spellclass = + DB.createChild(node_spellset, table_ability_information["string_ability_type"] or "Abilities") + local node_spelllevel = + DB.createChild(DB.createChild(node_spellclass, "levels"), "level" .. table_ability_information["level"]) + local node_ability = DB.createChild(DB.createChild(node_spelllevel, "spells")) -- set up spellset and intermediate subnodes - DB.setValue(node_spellclass, 'label', 'string', table_ability_information['string_ability_type']) - DB.setValue(node_spellclass, 'castertype', 'string', 'spontaneous') - DB.setValue(node_spellclass, 'availablelevel' .. table_ability_information['level'], 'number', table_ability_information['daily_uses'] or 1) - DB.setValue(node_spellclass, 'cl', 'number', 0) - DB.setValue(node_spelllevel, 'level', 'number', table_ability_information['level']) + DB.setValue(node_spellclass, "label", "string", table_ability_information["string_ability_type"]) + DB.setValue(node_spellclass, "castertype", "string", "spontaneous") + DB.setValue( + node_spellclass, + "availablelevel" .. table_ability_information["level"], + "number", + table_ability_information["daily_uses"] or 1 + ) + DB.setValue(node_spellclass, "cl", "number", 0) + DB.setValue(node_spelllevel, "level", "number", table_ability_information["level"]) -- set name and description - DB.setValue(node_ability, 'name', 'string', table_ability_information['name']) - DB.setValue(node_ability, 'description', 'string', (table_ability_information['description'] or '') .. (string_parenthetical or '')) - if table_ability_information['perday'] then DB.setValue(node_ability, 'prepared', 'number', table_ability_information['perday']) end - DB.setValue(node_ability, 'sr', 'string', 'no') + DB.setValue(node_ability, "name", "string", table_ability_information["name"]) + DB.setValue( + node_ability, + "description", + "string", + (table_ability_information["description"] or "") .. (string_parenthetical or "") + ) + if table_ability_information["perday"] then + DB.setValue(node_ability, "prepared", "number", table_ability_information["perday"]) + end + DB.setValue(node_ability, "sr", "string", "no") -- create actions - local node_actions = DB.createChild(node_ability, 'actions') - for string_name_action, table_action_information in pairs(table_ability_information['actions']) do + local node_actions = DB.createChild(node_ability, "actions") + for string_name_action, table_action_information in pairs(table_ability_information["actions"]) do local node_action = DB.createChild(node_actions, string_name_action) for string_node_name, table_node_info in pairs(table_action_information) do - if string_node_name == 'damagelist' or string_node_name == 'heallist' then + if string_node_name == "damagelist" or string_node_name == "heallist" then for string_damage_name, table_damage_information in pairs(table_node_info) do - local node_damage = DB.createChild(DB.createChild(node_action, string_node_name), string_damage_name) + local node_damage = + DB.createChild(DB.createChild(node_action, string_node_name), string_damage_name) for string_damagenode_name, table_damagenode_info in pairs(table_damage_information) do - if table_damagenode_info['type'] and table_damagenode_info['value'] then - if table_damagenode_info['tiermultiplier'] then - if table_damagenode_info['type'] == 'string' then - local string_result = - string.format(table_damagenode_info['value'], (table_damagenode_info['tiermultiplier'] * (number_rank or 1))) - DB.setValue(node_damage, string_damagenode_name, table_damagenode_info['type'], string_result) - elseif table_damagenode_info['type'] == 'number' then - local number_result = table_damagenode_info['value'] - * (table_damagenode_info['tiermultiplier'] * (number_rank or 1)) - DB.setValue(node_damage, string_damagenode_name, table_damagenode_info['type'], number_result) + if table_damagenode_info["type"] and table_damagenode_info["value"] then + if table_damagenode_info["tiermultiplier"] then + if table_damagenode_info["type"] == "string" then + local string_result = string.format( + table_damagenode_info["value"], + (table_damagenode_info["tiermultiplier"] * (number_rank or 1)) + ) + DB.setValue( + node_damage, + string_damagenode_name, + table_damagenode_info["type"], + string_result + ) + elseif table_damagenode_info["type"] == "number" then + local number_result = table_damagenode_info["value"] + * (table_damagenode_info["tiermultiplier"] * (number_rank or 1)) + DB.setValue( + node_damage, + string_damagenode_name, + table_damagenode_info["type"], + number_result + ) end else - DB.setValue(node_damage, string_damagenode_name, table_damagenode_info['type'], table_damagenode_info['value']) + DB.setValue( + node_damage, + string_damagenode_name, + table_damagenode_info["type"], + table_damagenode_info["value"] + ) end end end end else - if table_node_info['type'] and table_node_info['value'] then - if table_node_info['tiermultiplier'] then - local result = string.format(table_node_info['value'], (table_node_info['tiermultiplier'] * (number_rank or 1))) - DB.setValue(node_action, string_node_name, table_node_info['type'], result) + if table_node_info["type"] and table_node_info["value"] then + if table_node_info["tiermultiplier"] then + local result = string.format( + table_node_info["value"], + (table_node_info["tiermultiplier"] * (number_rank or 1)) + ) + DB.setValue(node_action, string_node_name, table_node_info["type"], result) else - DB.setValue(node_action, string_node_name, table_node_info['type'], table_node_info['value']) + DB.setValue(node_action, string_node_name, table_node_info["type"], table_node_info["value"]) end end end @@ -303,37 +367,41 @@ end local function search_for_abilities(node_npc) --- This function checks NPCs for feats, traits, and/or special abilities. local function hasSpecialAbility(nodeActor, sSearchString, sAbilType) - if not nodeActor or not sSearchString then return false end + if not nodeActor or not sSearchString then + return false + end local function matchInTable(table, search) for _, string in ipairs(table) do string = string:lower() local match = string:match(search:lower(), 1) - if match then return match end + if match then + return match + end end end local tScope = {} - if sAbilType == 'Feats' then - tScope = { DB.getValue(nodeActor, '.specialattacks', ''), DB.getValue(nodeActor, '.feats', '') } - elseif sAbilType == 'Special Abilities' then - tScope = { DB.getValue(nodeActor, '.specialattacks', ''), DB.getValue(nodeActor, '.specialqualities', '') } + if sAbilType == "Feats" then + tScope = { DB.getValue(nodeActor, ".specialattacks", ""), DB.getValue(nodeActor, ".feats", "") } + elseif sAbilType == "Special Abilities" then + tScope = { DB.getValue(nodeActor, ".specialattacks", ""), DB.getValue(nodeActor, ".specialqualities", "") } end return matchInTable(tScope, sSearchString) ~= nil, - matchInTable(tScope, sSearchString .. ' (%d+)') or 1, - matchInTable(tScope, sSearchString .. ' %((.-)%)') + matchInTable(tScope, sSearchString .. " (%d+)") or 1, + matchInTable(tScope, sSearchString .. " %((.-)%)") end for string_ability_name, table_ability_information in pairs(UNPCAbilities.array_abilities) do local is_match, number_rank, string_parenthetical = - hasSpecialAbility(node_npc, string_ability_name, table_ability_information['string_ability_type']) + hasSpecialAbility(node_npc, string_ability_name, table_ability_information["string_ability_type"]) if is_match then -- call ability parser function if supplied - if string_parenthetical and table_ability_information['parser'] then - table_ability_information['parser'](string_parenthetical, table_ability_information) + if string_parenthetical and table_ability_information["parser"] then + table_ability_information["parser"](string_parenthetical, table_ability_information) end -- add ability @@ -349,13 +417,16 @@ function onInit() local function addNPC_new(tCustom, ...) addNPC_old(tCustom, ...) -- call original function - local bAutomatedModule, tSourceModule = nil, Module.getModuleInfo(DB.getPath(tCustom['nodeRecord']):gsub('.+%@', '')) - if tSourceModule then bAutomatedModule = tSourceModule['author'] == 'Tanor' end + local bAutomatedModule, tSourceModule = + nil, Module.getModuleInfo(DB.getPath(tCustom["nodeRecord"]):gsub(".+%@", "")) + if tSourceModule then + bAutomatedModule = tSourceModule["author"] == "Tanor" + end if not bAutomatedModule then - find_spell_nodes(tCustom['nodeCT']) - search_for_abilities(tCustom['nodeCT']) - search_for_maladies(tCustom['nodeCT']) + find_spell_nodes(tCustom["nodeCT"]) + search_for_abilities(tCustom["nodeCT"]) + search_for_maladies(tCustom["nodeCT"]) end end @@ -367,10 +438,14 @@ function onInit() -- If not Spellbook spell is found, it passes the call to the original addNPC function. local parseSpell_old -- placeholder for original parseSpell function local function parseSpell_new(nodeSpell, ...) - if not nodeSpell then return nil end + if not nodeSpell then + return nil + end local node_reference_spell = replace_spell_actions(nodeSpell) -- if spellbook actions not found, run original parsing script - if not node_reference_spell then parseSpell_old(nodeSpell, ...) end + if not node_reference_spell then + parseSpell_old(nodeSpell, ...) + end end parseSpell_old = SpellManager.parseSpell