From b34f30cd15dac6d0296000e7c0bf98701d711027 Mon Sep 17 00:00:00 2001 From: doug1234 Date: Fri, 23 Feb 2024 18:36:34 -0500 Subject: [PATCH] Added bashing enhancement. --- TemplePlus/condition.cpp | 23 ++++++++ TemplePlus/dice.cpp | 58 +++++++++++++++++++ TemplePlus/dice.h | 5 ++ TemplePlus/ui/ui_item_creation.cpp | 7 +++ TemplePlus/ui/ui_item_creation.h | 3 +- tpdata/tpmes/item_creation.mes | 2 +- tpdata/tprules/craft_maa_specs.tab | 10 ++-- .../scr/tpModifiers/shield_bashing.py | 12 ++++ 8 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 tpdatasrc/tpgamefiles/scr/tpModifiers/shield_bashing.py diff --git a/TemplePlus/condition.cpp b/TemplePlus/condition.cpp index a4d4b11e9..2f5c71ea5 100644 --- a/TemplePlus/condition.cpp +++ b/TemplePlus/condition.cpp @@ -1787,6 +1787,28 @@ int ArmorWeaponDice(DispatcherCallbackArgs args) if (dispIo->weapon == armor) { dispIo->dicePacked = conds.CondNodeGetArg(args.subDispNode->condNode, 1); dispIo->attackDamageType = (DamageType)conds.CondNodeGetArg(args.subDispNode->condNode, 0); + //Bashing Bumps by 2 categories + if (d20Sys.D20QueryPython(args.objHndCaller, "Has Bashing") > 0) { + const auto dice = Dice::FromPacked(dispIo->dicePacked); + const auto largerDice = dice.IncreaseWeaponSize(2); + dispIo->dicePacked = largerDice.ToPacked(); + } + } + + return 0; +} + +int ArmorDealingDamage(DispatcherCallbackArgs args) +{ + DispIoDamage* dispIo = dispatch.DispIoCheckIoType4(args.dispIO); + + auto invIdx = args.GetCondArg(2); + auto armor = inventory.GetItemAtInvIdx(args.objHndCaller, invIdx); + + if (dispIo->attackPacket.weaponUsed == armor) { + if (d20Sys.D20QueryPython(args.objHndCaller, "Has Bashing") > 0) { + dispIo->damage.attackPowerType |= D20DAP_MAGIC; //The shield acts as a +1 weapon when used to bash. + } } return 0; @@ -3249,6 +3271,7 @@ void ConditionSystem::RegisterNewConditions() static CondStructNew shieldBash("Shield Bash", 5); shieldBash.AddHook(dispTypeD20Query, DK_QUE_Can_Shield_Bash, genericCallbacks.QuerySetReturnVal1); shieldBash.AddHook(dispTypeGetAttackDice, DK_NONE, ArmorWeaponDice); + shieldBash.AddHook(dispTypeDealingDamage, DK_NONE, ArmorDealingDamage); shieldBash.AddHook(dispTypeGetCriticalHitExtraDice, DK_NONE, ArmorCritMultiplier); shieldBash.AddHook(dispTypeGetCriticalHitRange, DK_NONE, ArmorCritRange); shieldBash.AddHook(dispTypeToHitBonus2, DK_NONE, ShieldBashProficiencyPenalty); diff --git a/TemplePlus/dice.cpp b/TemplePlus/dice.cpp index cad04e3f3..5445089d6 100644 --- a/TemplePlus/dice.cpp +++ b/TemplePlus/dice.cpp @@ -41,6 +41,64 @@ bool Dice::Parse(const char* diceStr, int& count, int& sides, int& modifier) { return false; } +Dice Dice::IncreaseWeaponSize(int numIncreases) const +{ + auto diceCount = mCount; + auto diceSide = mSides; + auto diceMod = mModifier; + + for (int i = 0; i < numIncreases; ++i) { + switch (diceSide) + { + case 2: + diceSide = 3; + break; + case 3: + diceSide = 4; + break; + case 4: + diceSide = 6; + break; + case 6: + if (diceCount == 1) + diceSide = 8; + else if (diceCount <= 3) + diceCount++; + else + diceCount += 2; + break; + case 8: + if (diceCount == 1) { + diceCount = 2; + diceSide = 6; + } + else if (diceCount <= 3) + { + diceCount++; + } + else if (diceCount <= 6) { + diceCount += 2; + } + else + diceCount += 4; + break; + case 10: + diceCount *= 2; + diceSide = 8; + break; + case 12: + diceCount = 3; + diceSide = 6; + break; + default: + break; + } + } + + return Dice(diceCount, diceSide, diceMod); +} + + int RandomIntRange(int from, int to) { return addresses.RandomIntRange(from, to); } diff --git a/TemplePlus/dice.h b/TemplePlus/dice.h index 747c5766f..493ec4dff 100644 --- a/TemplePlus/dice.h +++ b/TemplePlus/dice.h @@ -23,6 +23,11 @@ class Dice { */ static int Roll(int count, int sides, int modifier = 0); + /* + Returns the dice for a larger sized weapon. + */ + Dice IncreaseWeaponSize(int numIncreases = 1) const; + int Roll(); /* diff --git a/TemplePlus/ui/ui_item_creation.cpp b/TemplePlus/ui/ui_item_creation.cpp index 4103be951..800d72b6c 100644 --- a/TemplePlus/ui/ui_item_creation.cpp +++ b/TemplePlus/ui/ui_item_creation.cpp @@ -60,6 +60,7 @@ const std::unordered_map ItemEnhSpecFlagDict = { {"iesf_shield",IESF_SHIELD }, {"iesf_ranged",IESF_RANGED }, {"iesf_two_handed", IESF_TWO_HANDED }, + {"iesf_no_tower_shield", IESF_NO_TOWER_SHIELD }, {"iesf_melee",IESF_MELEE }, {"iesf_thrown",IESF_THROWN }, @@ -648,6 +649,12 @@ bool UiItemCreation::MaaEffectIsApplicable(int effIdx){ if (!(itEnh.flags & IESF_SHIELD)) return false; + if ((itEnh.flags & IESF_NO_TOWER_SHIELD)) { + const auto spellFailure = itemObj->GetInt32(obj_f_armor_arcane_spell_failure); + if (spellFailure > 15) { //Towershields have high arcane failure + return false; + } + } } else{ if (!(itEnh.flags & IESF_ARMOR)) diff --git a/TemplePlus/ui/ui_item_creation.h b/TemplePlus/ui/ui_item_creation.h index 62d39edc5..0edbaedb7 100644 --- a/TemplePlus/ui/ui_item_creation.h +++ b/TemplePlus/ui/ui_item_creation.h @@ -37,7 +37,8 @@ enum ItemEnhancementSpecFlags{ IESF_INCREMENTAL = 0x400, // indicates that there are multiple progressive versions of this that supercede each other IESF_NONCORE = 0x800, // enhancement based on non-core rules material (e.g. splatbook/fanmade), enabled only when non-core materials config is set IESF_LIGHT_ONLY = 0x1000, // only for light armor - IESF_TWO_HANDED = 0x2000 // two handed weapon only + IESF_TWO_HANDED = 0x2000, // two handed weapon only + IESF_NO_TOWER_SHIELD = 0x4000 // can't be tower shield }; struct ItemEnhancementSpec { diff --git a/tpdata/tpmes/item_creation.mes b/tpdata/tpmes/item_creation.mes index b9f9149cd..e35ba7f3a 100644 --- a/tpdata/tpmes/item_creation.mes +++ b/tpdata/tpmes/item_creation.mes @@ -255,7 +255,7 @@ {2404}{+5 Shield enhancement bonus to AC.} {2405}{Floats providing protection normally but freeing up both hands.} {2406}{Once per round make a DC 20 Reflex save to avoid ranged damage.} -{2407}{Deals damage as if it were two size categories larger.} +{2407}{When shield bashing, deals damage as if it were two size categories larger.} {2408}{2/day all within 20 feet except the wielder make a DC 14 Reflex save or be blinded for 1d4 rounds.} {2409}{Grants a 25% chance to avoid a critical hit.} {2410}{Grants spell resistance 13.} diff --git a/tpdata/tprules/craft_maa_specs.tab b/tpdata/tprules/craft_maa_specs.tab index c2a0fd471..0e9c8dfc1 100644 --- a/tpdata/tprules/craft_maa_specs.tab +++ b/tpdata/tprules/craft_maa_specs.tab @@ -92,11 +92,11 @@ 402 Shield Enhancement Bonus IESF_ENABLED IESF_SHIELD IESF_PLUS_BONUS 1 3 C9 401 403 Shield Enhancement Bonus IESF_ENABLED IESF_SHIELD IESF_PLUS_BONUS 1 4 C12 402 404 Shield Enhancement Bonus IESF_ENABLED IESF_SHIELD IESF_PLUS_BONUS 1 5 C15 403 -405 Shield Bashing IESF_SHIELD 1 0 C3 -406 Shield Blinding IESF_SHIELD 1 0 C3 -407 Shield Light Fortification IESF_SHIELD 1 0 C3 -408 Shield Arrow Deflection IESF_SHIELD 1 0 C3 -409 Shield Animated IESF_SHIELD 1 0 C3 +405 Shield Animated IESF_SHIELD 1 0 C3 +406 Shield Arrow Deflection IESF_SHIELD 1 0 C3 +407 Shield Bashing IESF_ENABLED IESF_SHIELD IESF_NO_TOWER_SHIELD 1 0 C8 'bulls strength' +408 Shield Blinding IESF_SHIELD 1 0 C3 +409 Shield Light Fortification IESF_SHIELD 1 0 C3 410 Armor Spell Resistance IESF_ENABLED IESF_SHIELD IESF_INCREMENTAL 2 13 C15 'spell resistance' 411 Armor Spell Resistance IESF_ENABLED IESF_SHIELD IESF_INCREMENTAL 3 15 C15 'spell resistance' 410 412 Armor Spell Resistance IESF_ENABLED IESF_SHIELD IESF_INCREMENTAL 4 17 C15 'spell resistance' 411 diff --git a/tpdatasrc/tpgamefiles/scr/tpModifiers/shield_bashing.py b/tpdatasrc/tpgamefiles/scr/tpModifiers/shield_bashing.py new file mode 100644 index 000000000..02d2f1e0e --- /dev/null +++ b/tpdatasrc/tpgamefiles/scr/tpModifiers/shield_bashing.py @@ -0,0 +1,12 @@ +from templeplus.pymod import PythonModifier +from toee import * +import tpdp + +print "Registering Shield Bashing" + +def ShieldBashingQuery(attachee, args, evt_obj): + evt_obj.return_val = 1 + return 0 + +shieldBashingEnch = PythonModifier("Shield Bashing", 3) # spare, spare, inv_idx +shieldBashingEnch.AddHook(ET_OnD20PythonQuery, "Has Bashing", ShieldBashingQuery, ())