diff --git a/cdtweaks/languages/english/overwhelming_devastating_critical.tra b/cdtweaks/languages/english/overwhelming_devastating_critical.tra new file mode 100644 index 0000000..a3e8620 --- /dev/null +++ b/cdtweaks/languages/english/overwhelming_devastating_critical.tra @@ -0,0 +1,4 @@ +@0 = "Overwhelming Critical" +@1 = "Unaffected by effects from Overwhelming Critical" +@2 = "Devastating Critical" +@3 = "Unaffected by effects from Devastating Critical" \ No newline at end of file diff --git a/cdtweaks/languages/english/weidu.tra b/cdtweaks/languages/english/weidu.tra index 40c02b8..0235612 100644 --- a/cdtweaks/languages/english/weidu.tra +++ b/cdtweaks/languages/english/weidu.tra @@ -842,6 +842,8 @@ Use Baldur.lua options: a7_interval_ini @619000 = "Dirty Fighting class feat for Chaotic-aligned Rogues [Luke (EEex)]" +@620000 = "Overwhelming/Devastating Critical class feat for Trueclass Fighters [Luke]" + @621000 = "Self Concealment class feat for Monks [Luke (EEex)]" @622000 = "Parry Mode kit feat for Blades e Swashbucklers [Luke (EEex)]" @@ -853,3 +855,4 @@ Use Baldur.lua options: a7_interval_ini @625000 = "Nature Sense class feat for Druids [Luke (EEex)]" @626000 = "Uncanny Dodge class feat for Barbarians and Rogues [Luke (EEex)]" + diff --git a/cdtweaks/languages/italian/overwhelming_devastating_critical.tra b/cdtweaks/languages/italian/overwhelming_devastating_critical.tra new file mode 100644 index 0000000..057860d --- /dev/null +++ b/cdtweaks/languages/italian/overwhelming_devastating_critical.tra @@ -0,0 +1,4 @@ +@0 = "Colpo Critico Possente" +@1 = "Non soggetto agli effetti di Colpo Critico Possente" +@2 = "Colpo Critico Devastante" +@3 = "Non soggetto agli effetti di Colpo Critico Devastante" \ No newline at end of file diff --git a/cdtweaks/languages/italian/weidu.tra b/cdtweaks/languages/italian/weidu.tra index e772286..1d6e8f8 100644 --- a/cdtweaks/languages/italian/weidu.tra +++ b/cdtweaks/languages/italian/weidu.tra @@ -753,6 +753,8 @@ Usa opzioni di Baldur.lua: a7_interval_ini @619000 = "Aggiungi talento di classe Combattimento Scorretto per i Ladri di allineamento Caotico [Luke (EEex)]" +@620000 = "Aggiungi talento di classe Colpo Critico Possente/Devastante per i Guerrieri [Luke]" + @621000 = "Aggiungi talento di classe Auto-Occultamento per i Monaci [Luke (EEex)]" @622000 = "Aggiungi talento di classe Modalità Parata per Bardi Lama e Rodomonti [Luke (EEex)]" @@ -764,3 +766,4 @@ Usa opzioni di Baldur.lua: a7_interval_ini @625000 = "Aggiungi talento di classe Senso della Natura per i Druidi [Luke (EEex)]" @626000 = "Aggiungi talento di classe Schivata Prodigiosa per i Barbari e i Ladri [Luke (EEex)]" + diff --git a/cdtweaks/lib/comp_6200.tpa b/cdtweaks/lib/comp_6200.tpa new file mode 100644 index 0000000..6f354a4 --- /dev/null +++ b/cdtweaks/lib/comp_6200.tpa @@ -0,0 +1,18 @@ +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// +///// \\\\\////\\\\//// +///// Overwhelming/Devastating Critical class feat for Trueclass Fighters \\\\\ +///// \\\\\////\\\\//// +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// + +WITH_SCOPE BEGIN + INCLUDE "cdtweaks\luke\misc.tph" + INCLUDE "cdtweaks\ardanis\functions.tph" + // + INCLUDE "cdtweaks\lib\overwhelming_devastating_critical.tph" + // + WITH_TRA "cdtweaks\languages\english\overwhelming_devastating_critical.tra" "cdtweaks\languages\%LANGUAGE%\overwhelming_devastating_critical.tra" BEGIN + LAF "OVERWHELMING_DEVASTATING_CRITICAL" END + END +END \ No newline at end of file diff --git a/cdtweaks/lib/overwhelming_devastating_critical.tph b/cdtweaks/lib/overwhelming_devastating_critical.tph new file mode 100644 index 0000000..1a8a439 --- /dev/null +++ b/cdtweaks/lib/overwhelming_devastating_critical.tph @@ -0,0 +1,57 @@ +DEFINE_ACTION_FUNCTION "OVERWHELMING_DEVASTATING_CRITICAL" +BEGIN + LAF "GT_ADD_SPELL" + INT_VAR + "level" = 1 + "type" = 4 + STR_VAR + "idsName" = "TRUECLASS_FIGHTER_CRITICAL" + RET + "TRUECLASS_FIGHTER_CRITICAL" = "resName" + END + // + WITH_SCOPE BEGIN + ACTION_TO_LOWER "TRUECLASS_FIGHTER_CRITICAL" + // + CREATE "eff" "%TRUECLASS_FIGHTER_CRITICAL%b" + COPY_EXISTING "%TRUECLASS_FIGHTER_CRITICAL%b.eff" "override" + WRITE_LONG 0x10 341 // opcode: critical hit effect + WRITE_LONG 0x20 1 // mode: by this weapon only + WRITE_SHORT 0x2C 100 // prob1 + WRITE_ASCII 0x30 "%TRUECLASS_FIGHTER_CRITICAL%b" #8 // SPL resref + BUT_ONLY + // + CREATE "spl" "%TRUECLASS_FIGHTER_CRITICAL%b" + COPY_EXISTING "%TRUECLASS_FIGHTER_CRITICAL%b.spl" "override" + WRITE_LONG NAME1 "-1" + WRITE_LONG UNIDENTIFIED_DESC "-1" + WRITE_LONG 0x18 (BIT9 BOR BIT10 BOR BIT14 BOR BIT25) // break sanctuary/invisibility, ignore dead/wild magic, castable when silenced + WRITE_LONG 0x1C 4 // type: innate + WRITE_LONG 0x34 1 // level + WRITE_ASCII 0x3A "SPCL905B" #8 // icon + // + LPF ~ADD_SPELL_HEADER~ STR_VAR "icon" = "SPCL905B" END + LPF ~ADD_SPELL_HEADER~ INT_VAR "required_level" = 30 STR_VAR "icon" = "SPCL905B" END + // + LPF "ADD_SPELL_EFFECT" INT_VAR "header" = 1 "opcode" = 402 "target" = 2 "parameter1" = 1 STR_VAR "resource" = "%DEST_RES%" END // invoke lua + LPF "ADD_SPELL_EFFECT" INT_VAR "header" = 2 "opcode" = 402 "target" = 2 "parameter1" = 2 STR_VAR "resource" = "%DEST_RES%" END // invoke lua + BUT_ONLY_IF_IT_CHANGES + END + // Listener: run 'func' each time a sprite has finished evaluating its effects + WITH_SCOPE BEGIN + OUTER_SET "feedback_strref_overwhelming_crit_hit" = RESOLVE_STR_REF (@0) + OUTER_SET "feedback_strref_overwhelming_crit_immune" = RESOLVE_STR_REF (@1) + OUTER_SET "feedback_strref_devastating_crit_hit" = RESOLVE_STR_REF (@2) + OUTER_SET "feedback_strref_devastating_crit_immune" = RESOLVE_STR_REF (@3) + // + LAF "APPEND_LUA_FUNCTION" STR_VAR "description" = "Class/Kit Abilities" "sourceFileSpec" = "cdtweaks\luke\lua\class\overwhelming_devastating_critical.lua" "destRes" = "m_gtspcl" END + END + // + ACTION_IF !(FILE_EXISTS_IN_GAME "m_gttbls.lua") BEGIN + COPY "cdtweaks\luke\lua\m_gttbls.lua" "override" + END + // + ACTION_IF !(FILE_EXISTS_IN_GAME "gtabmod.2da") BEGIN + COPY "cdtweaks\luke\2da\gtabmod.2da" "override" + END +END \ No newline at end of file diff --git a/cdtweaks/luke/lua/class/overwhelming_devastating_critical.lua b/cdtweaks/luke/lua/class/overwhelming_devastating_critical.lua new file mode 100644 index 0000000..4ef90f2 --- /dev/null +++ b/cdtweaks/luke/lua/class/overwhelming_devastating_critical.lua @@ -0,0 +1,207 @@ +--[[ ++---------------------------------------------------------------------------------------+ +| cdtweaks, NWN-ish Overwhelming/Devastating Critical class feat for Trueclass Fighters | ++---------------------------------------------------------------------------------------+ +--]] + +-- Apply ability -- + +EEex_Opcode_AddListsResolvedListener(function(sprite) + -- Sanity check + if not EEex_GameObject_IsSprite(sprite) then + return + end + -- internal function that applies the actual feat + local apply = function(mainHandResRef) + -- Update tracking var + sprite:setLocalString("gtTrueFighterCriticalMainHand", mainHandResRef) + -- Mark the creature as 'feat applied' + sprite:setLocalInt("gtTrueFighterCritical", 1) + -- + sprite:applyEffect({ + ["effectID"] = 321, -- Remove effects by resource + ["res"] = "%TRUECLASS_FIGHTER_CRITICAL%", + ["sourceID"] = sprite.m_id, + ["sourceTarget"] = sprite.m_id, + }) + sprite:applyEffect({ + ["effectID"] = 182, -- Use EFF file while ITM is equipped + ["durationType"] = 9, + ["res"] = string.upper(mainHandResRef), -- ITM + ["m_res2"] = "%TRUECLASS_FIGHTER_CRITICAL%B", -- EFF + ["m_sourceRes"] = "%TRUECLASS_FIGHTER_CRITICAL%", + ["sourceID"] = sprite.m_id, + ["sourceTarget"] = sprite.m_id, + }) + end + -- Check creature's equipment / class / pips + local equipment = sprite.m_equipment -- CGameSpriteEquipment + local selectedWeapon = equipment.m_items:get(equipment.m_selectedWeapon) -- CItem + local selectedWeaponHeader = selectedWeapon.pRes.pHeader -- Item_Header_st + local selectedWeaponResRef = selectedWeapon.pRes.resref:get() + -- + local selectedWeaponProficiencyType = selectedWeaponHeader.proficiencyType + -- get launcher if needed + local launcher = sprite:getLauncher(selectedWeapon:getAbility(equipment.m_selectedWeaponAbility)) -- CItem + if launcher ~= nil then + local pHeader = launcher.pRes.pHeader -- Item_Header_st + selectedWeaponProficiencyType = pHeader.proficiencyType + end + -- + local spriteClassStr = GT_Resource_IDSToSymbol["class"][sprite.m_typeAI.m_Class] + -- since ``EEex_Opcode_AddListsResolvedListener`` is running after the effect lists have been evaluated, ``m_bonusStats`` has already been added to ``m_derivedStats`` by the engine + local spriteKitStr = sprite.m_derivedStats.m_nKit == 0 and "TRUECLASS" or GT_Resource_IDSToSymbol["kit"][sprite.m_derivedStats.m_nKit] + -- + local grandmastery = EEex_Trigger_ParseConditionalString(string.format("ProficiencyGT(Myself,%d,4)", selectedWeaponProficiencyType)) + -- + local applyAbility = spriteClassStr == "FIGHTER" and (spriteKitStr == "TRUECLASS" or spriteKitStr == "MAGESCHOOL_GENERALIST") and grandmastery:evalConditionalAsAIBase(sprite) + -- + if sprite:getLocalInt("gtTrueFighterCritical") == 0 then + if applyAbility then + apply(selectedWeaponResRef) + end + else + if applyAbility then + -- Check if weapon resref has changed since the last application + if selectedWeaponResRef ~= sprite:getLocalString("gtTrueFighterCriticalMainHand") then + apply(selectedWeaponResRef) + end + else + -- Mark the creature as 'feat removed' + sprite:setLocalInt("gtTrueFighterCritical", 0) + -- + sprite:applyEffect({ + ["effectID"] = 321, -- Remove effects by resource + ["res"] = "%TRUECLASS_FIGHTER_CRITICAL%", + ["sourceID"] = sprite.m_id, + ["sourceTarget"] = sprite.m_id, + }) + end + end + -- + grandmastery:free() +end) + +-- Core function -- + +function %TRUECLASS_FIGHTER_CRITICAL%(CGameEffect, CGameSprite) + local sourceSprite = EEex_GameObject_Get(CGameEffect.m_sourceId) + -- + local equipment = sourceSprite.m_equipment -- CGameSpriteEquipment + local selectedWeapon = equipment.m_items:get(equipment.m_selectedWeapon) -- CItem + local selectedWeaponHeader = selectedWeapon.pRes.pHeader -- Item_Header_st + local selectedWeaponAbility = EEex_Resource_GetItemAbility(selectedWeaponHeader, equipment.m_selectedWeaponAbility) -- Item_ability_st + -- + if CGameEffect.m_effectAmount == 1 then + -- Overwhelming Critical + local immunityToDamage = EEex_Trigger_ParseConditionalString("EEex_IsImmuneToOpcode(Myself,12)") + -- + local targetActiveStats = EEex_Sprite_GetActiveStats(CGameSprite) + -- + local itmAbilityDamageTypeToIDS = { + [0] = 0x0, -- none (crushing) + [1] = 0x10, -- piercing + [2] = 0x0, -- crushing + [3] = 0x100, -- slashing + [4] = 0x80, -- missile + [5] = 0x800, -- non-lethal + [6] = targetActiveStats.m_nResistPiercing > targetActiveStats.m_nResistCrushing and 0x0 or 0x10, -- piercing/crushing (better) + [7] = targetActiveStats.m_nResistPiercing > targetActiveStats.m_nResistSlashing and 0x100 or 0x10, -- piercing/slashing (better) + [8] = targetActiveStats.m_nResistCrushing > targetActiveStats.m_nResistSlashing and 0x0 or 0x100, -- slashing/crushing (worse) + } + -- + if itmAbilityDamageTypeToIDS[selectedWeaponAbility.damageType] then -- sanity check + if not immunityToDamage:evalConditionalAsAIBase(CGameSprite) then + EEex_GameObject_ApplyEffect(sourceSprite, + { + ["effectID"] = 139, -- Display string + ["effectAmount"] = %feedback_strref_overwhelming_crit_hit%, + ["m_sourceRes"] = CGameEffect.m_sourceRes:get(), + ["m_sourceType"] = CGameEffect.m_sourceType, + ["sourceID"] = sourceSprite.m_id, + ["sourceTarget"] = sourceSprite.m_id, + }) + -- + EEex_GameObject_ApplyEffect(CGameSprite, + { + ["effectID"] = 12, -- Damage + ["dwFlags"] = itmAbilityDamageTypeToIDS[selectedWeaponAbility.damageType] * 0x10000, -- mode: normal + ["numDice"] = 2, + ["diceSize"] = 6, + ["m_sourceRes"] = CGameEffect.m_sourceRes:get(), + ["m_sourceType"] = CGameEffect.m_sourceType, + ["sourceID"] = CGameEffect.m_sourceId, + ["sourceTarget"] = CGameEffect.m_sourceTarget, + }) + else + EEex_GameObject_ApplyEffect(CGameSprite, + { + ["effectID"] = 139, -- Display string + ["effectAmount"] = %feedback_strref_overwhelming_crit_immune%, + ["m_sourceRes"] = CGameEffect.m_sourceRes:get(), + ["m_sourceType"] = CGameEffect.m_sourceType, + ["sourceID"] = CGameEffect.m_sourceId, + ["sourceTarget"] = CGameEffect.m_sourceTarget, + }) + end + end + -- + immunityToDamage:free() + elseif CGameEffect.m_effectAmount == 2 then + -- Devastating Critical + local sourceActiveStats = EEex_Sprite_GetActiveStats(sourceSprite) + -- + local gtabmod = GT_Resource_2DA["gtabmod"] + -- + local savebonus = tonumber(gtabmod[string.format("%s", sourceActiveStats.m_nSTR)]["BONUS"]) + if selectedWeaponAbility.type == 2 then -- if ranged, make it scale with Dexterity + savebonus = tonumber(gtabmod[string.format("%s", sourceActiveStats.m_nDEX)]["BONUS"]) + end + -- + local immunityToKillTarget = EEex_Trigger_ParseConditionalString("EEex_IsImmuneToOpcode(Myself,13)") + -- + if not immunityToKillTarget:evalConditionalAsAIBase(CGameSprite) then + EEex_GameObject_ApplyEffect(sourceSprite, + { + ["effectID"] = 139, -- Display string + ["effectAmount"] = %feedback_strref_devastating_crit_hit%, + ["m_sourceRes"] = CGameEffect.m_sourceRes:get(), + ["m_sourceType"] = CGameEffect.m_sourceType, + ["sourceID"] = sourceSprite.m_id, + ["sourceTarget"] = sourceSprite.m_id, + }) + -- + local effectCodes = { + {["op"] = 0xD7, ["tmg"] = 1, ["res"] = "SPBOLTGL"}, -- feedback vfx + {["op"] = 0xD, ["tmg"] = 4, ["p2"] = 0x4} -- kill target (normal death) + } + -- + for _, attributes in ipairs(effectCodes) do + CGameSprite:applyEffect({ + ["effectID"] = attributes["op"] or EEex_Error("opcode number not specified"), + ["dwFlags"] = attributes["p2"] or 0, + ["durationType"] = attributes["tmg"] or 0, + ["res"] = attributes["res"] or "", + ["savingThrow"] = 0x4, -- save vs. death + ["saveMod"] = -1 * savebonus, + ["m_sourceRes"] = CGameEffect.m_sourceRes:get(), + ["m_sourceType"] = CGameEffect.m_sourceType, + ["sourceID"] = CGameEffect.m_sourceId, + ["sourceTarget"] = CGameEffect.m_sourceTarget, + }) + end + else + EEex_GameObject_ApplyEffect(CGameSprite, + { + ["effectID"] = 139, -- Display string + ["effectAmount"] = %feedback_strref_devastating_crit_immune%, + ["m_sourceRes"] = CGameEffect.m_sourceRes:get(), + ["m_sourceType"] = CGameEffect.m_sourceType, + ["sourceID"] = CGameEffect.m_sourceId, + ["sourceTarget"] = CGameEffect.m_sourceTarget, + }) + end + -- + immunityToKillTarget:free() + end +end diff --git a/cdtweaks/readme-cdtweaks.html b/cdtweaks/readme-cdtweaks.html index 9fed7be..54898b1 100644 --- a/cdtweaks/readme-cdtweaks.html +++ b/cdtweaks/readme-cdtweaks.html @@ -1520,6 +1520,104 @@
Overwhelming/Devastating Critical class feat for Trueclass Fighters [Luke]
+ EEex
+ This component aims at giving Trueclass Fighters the passive feats Overwhelming/Devastating Critical. +
++ Overwhelming Critical: If the character is wielding a weapon he is grandmaster (+++++) with, he will deal 2d6 extra points of damage on a successful critical hit. +
++ Devastating Critical: If the character is wielding a weapon he is grandmaster (+++++) with and he is level 30+, the character's target must make a Save vs. Death or die instantly. +
++ Notes: +
Strength / Dexterity | +Modifier | +
---|---|
0 | ++20 | +
1 | ++6 | +
2 | ++4 | +
3 | ++3 | +
4 | ++2 | +
5 | ++1 | +
6 to 15 | +0 | +
16 | +-1 | +
17 | +-2 | +
18 | +-2 | +
19 | +-3 | +
20 | +-3 | +
21 | +-4 | +
22 | +-4 | +
23 | +-4 | +
24 | +-5 | +
25 | +-5 | +
Self Concealment class feat for Monks [Luke]
EEex
diff --git a/cdtweaks/setup-cdtweaks.tp2 b/cdtweaks/setup-cdtweaks.tp2 index e51e345..8028952 100644 --- a/cdtweaks/setup-cdtweaks.tp2 +++ b/cdtweaks/setup-cdtweaks.tp2 @@ -5116,6 +5116,21 @@ REQUIRE_PREDICATE MOD_IS_INSTALLED "EEex.tp2" 0 @29 REQUIRE_PREDICATE FILE_EXISTS ~cdtweaks/languages/%LANGUAGE%/dirty_fighting.tra~ @7 LABEL ~cd_tweaks_nwn_dirty_fighting~ +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// +///// \\\\\////\\\\//// +///// Overwhelming/Devastating Critical class feat for Trueclass Fighters \\\\\ +///// \\\\\////\\\\//// +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// +/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// + +BEGIN @620000 DESIGNATED 6200 +GROUP @30 +REQUIRE_PREDICATE GAME_IS ~bgee bg2ee eet iwdee~ @25 +REQUIRE_PREDICATE MOD_IS_INSTALLED "EEex.tp2" 0 @29 +REQUIRE_PREDICATE FILE_EXISTS ~cdtweaks/languages/%LANGUAGE%/overwhelming_devastating_critical.tra~ @7 +LABEL ~cd_tweaks_nwn_overwhelming_devastating_critical~ + /////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// /////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\////\\\\//// ///// \\\\\////\\\\////