Skip to content

Commit

Permalink
Merge pull request #393 from doug1234/master
Browse files Browse the repository at this point in the history
Add Swift Ambusher and Daring Outlaw feats also Atari Bug 81 and 90 fix
  • Loading branch information
doug1234 authored Jun 4, 2020
2 parents 8ce0cd5 + 3269474 commit a17c061
Show file tree
Hide file tree
Showing 21 changed files with 169 additions and 19 deletions.
17 changes: 0 additions & 17 deletions TemplePlus/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ class ClassAbilityCallbacks
static int DruidWildShapeCheck(DispatcherCallbackArgs args);
static int DruidWildShapePerform(DispatcherCallbackArgs args);
static int DruidWildShapeScale(DispatcherCallbackArgs args);
static bool IsIncompatibleWithDruid(objHndl item, objHndl critter);

static int BardicMusicPlaySound(int bardicSongIdx, objHndl performer, int evtType);
static int BardicMusicBeginRound(DispatcherCallbackArgs args);
Expand Down Expand Up @@ -312,7 +311,6 @@ class ConditionFunctionReplacement : public TempleFix {

//Old version of the function to be used within the replacement
int (*oldTurnUndeadPerform)(DispatcherCallbackArgs) = nullptr;
bool (*oldIsIncompatibleWithDruid)(objHndl item, objHndl critter) = nullptr;

void apply() override {
logger->info("Replacing Condition-related Functions");
Expand Down Expand Up @@ -482,10 +480,6 @@ class ConditionFunctionReplacement : public TempleFix {
replaceFunction<int(DispatcherCallbackArgs)>(0x100FBC60, classAbilityCallbacks.DruidWildShapeCheck);
replaceFunction<int(DispatcherCallbackArgs)>(0x100FBCE0, classAbilityCallbacks.DruidWildShapePerform);


// Druid Armor Restriction
oldIsIncompatibleWithDruid = replaceFunction<bool(objHndl item, objHndl critter)>(0x10066430, classAbilityCallbacks.IsIncompatibleWithDruid);

// Fixes Weapon Damage Bonus for ammo items
replaceFunction<int(DispatcherCallbackArgs)>(0x100FFE90, itemCallbacks.WeaponDamageBonus);

Expand Down Expand Up @@ -6080,17 +6074,6 @@ int ClassAbilityCallbacks::DruidWildShapeScale(DispatcherCallbackArgs args){
return 0;
}

bool ClassAbilityCallbacks::IsIncompatibleWithDruid(objHndl item, objHndl critter)
{
bool result = condFuncReplacement.oldIsIncompatibleWithDruid(item, critter); //Just call the old version now

if (result) {
auto res = dispatch.DispatchIgnoreDruidOathCheck(critter, item);
if (res) return false;
}

return result;
}


// ************************************
Expand Down
3 changes: 3 additions & 0 deletions TemplePlus/feat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,9 @@ uint32_t _WeaponFeatCheck(objHndl objHnd, feat_enums * featArray, uint32_t featA
{
return 1;
}
else if (d20Sys.D20QueryPython(objHnd, "Proficient with Weapon", static_cast<int>(wpnType))) { //Python "extra proficiency" support
return 1;
}

return 0;
}
Expand Down
30 changes: 30 additions & 0 deletions TemplePlus/inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ static class InventoryHooks : public TempleFix {

static int (__cdecl*orgItemInsertGetLocation)(objHndl, objHndl, int*, objHndl, int);
static int(__cdecl*orgIsProficientWithArmor)(objHndl, objHndl);
static bool(__cdecl*orgIsIncompatibleWithDruid)(objHndl, objHndl);

void apply() override {

Expand Down Expand Up @@ -91,6 +92,10 @@ static class InventoryHooks : public TempleFix {
return inventory.GetItemAtInvIdx(handle, idx);
});

orgIsIncompatibleWithDruid = replaceFunction<bool(objHndl item, objHndl critter)>(0x10066430, [](objHndl item, objHndl critter) {
return inventory.IsIncompatibleWithDruid(item, critter);
});

// ClearInventory
replaceFunction<void(__cdecl)(objHndl, BOOL)>(0x10069E00, [](objHndl handle, BOOL preservePersistentItems){
if (!handle)
Expand Down Expand Up @@ -193,6 +198,8 @@ static class InventoryHooks : public TempleFix {
} hooks;
int(__cdecl*InventoryHooks::orgItemInsertGetLocation)(objHndl, objHndl, int*, objHndl, int);
int(__cdecl*InventoryHooks::orgIsProficientWithArmor)(objHndl, objHndl);
bool(__cdecl* InventoryHooks::orgIsIncompatibleWithDruid)(objHndl, objHndl);



void InventorySystem::MoveItem(const objHndl& item, const locXY& loc){
Expand Down Expand Up @@ -248,6 +255,18 @@ bool InventorySystem::IsInvIdxWorn(int invIdx){
return invIdx >= INVENTORY_WORN_IDX_START && invIdx <= INVENTORY_WORN_IDX_END;
}

bool InventorySystem::IsIncompatibleWithDruid(objHndl item, objHndl critter)
{
bool result = InventoryHooks::orgIsIncompatibleWithDruid(item, critter); //Just call the old version now

if (result) {
auto res = dispatch.DispatchIgnoreDruidOathCheck(critter, item);
if (res) return false;
}

return result;
}

objHndl InventorySystem::GetItemAtInvIdx(objHndl handle, uint32_t nIdx){
auto invenField = obj_f_begin;
auto invenNumField = obj_f_begin; inventory.GetInventoryNumField(handle);
Expand Down Expand Up @@ -1794,6 +1813,17 @@ ItemErrorCode InventorySystem::ItemTransferFromTo(objHndl owner, objHndl receive
}
if (ownerObj && ownerObj->IsCritter() && IsInvIdxWorn(invSlot)){
result = CheckTransferToWieldSlot(item, invSlot, receiver);

//Fix for Atari bug #81
if (invSlot == 211) { //Shield slot
if (result == IEC_OK || flags & IIF_Allow_Swap) {
bool incompatible = IsIncompatibleWithDruid(item, receiver);
if (incompatible) {
return IEC_Incompatible_With_Druid;
}
}
}

if (result != IEC_OK){
if (!(flags & IIF_Allow_Swap)){
return result;
Expand Down
5 changes: 4 additions & 1 deletion TemplePlus/inventory.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ enum ItemErrorCode: uint32_t
IEC_Cannot_Wield_Magical =15,
IEC_Cannot_Wield_Techno =16,
IEC_Wield_Slot_Occupied =17,
IEC_Prohibited_Due_To_Class =18
IEC_Prohibited_Due_To_Class =18,
IEC_Incompatible_With_Druid = 40
};


Expand Down Expand Up @@ -71,6 +72,8 @@ struct InventorySystem : temple::AddressTable

static bool IsInvIdxWorn(int invIdx); // does the inventory index refer to a designated "worn item" slot?

bool InventorySystem::IsIncompatibleWithDruid(objHndl item, objHndl critter);

objHndl(__cdecl *GetSubstituteInventory) (objHndl);
objHndl GetItemAtInvIdx(objHndl, uint32_t nIdx); // returns the item at obj_f_critter_inventory subIdx nIdx (or obj_f_container_inventory for containers); Note the difference to ItemWornAt! (this is a more low level function)
objHndl FindMatchingStackableItem(objHndl objHndReceiver, objHndl objHndItem);
Expand Down
Binary file modified tpdata/co8infra.dat
Binary file not shown.
Binary file modified tpdata/kotbfixes.dat
Binary file not shown.
Binary file modified tpdata/tpgamefiles.dat
Binary file not shown.
2 changes: 1 addition & 1 deletion tpdatasrc/tpgamefiles/rules/char_class/class046_scout.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def GetClassHelpTopic():
feat_skill_focus_jump, feat_skill_focus_knowledge, feat_skill_focus_listen, feat_skill_focus_move_silently, feat_skill_focus_open_lock,
feat_skill_focus_performance, feat_skill_focus_slight_of_hand, feat_skill_focus_profession, feat_skill_focus_read_lips, feat_skill_focus_ride,
feat_skill_focus_scry, feat_skill_focus_search, feat_skill_focus_sense_motive, feat_skill_focus_speak_language, feat_skill_focus_spellcraft, feat_skill_focus_spot,
feat_skill_focus_swim, feat_skill_focus_tumble, feat_skill_focus_use_magic_device, feat_skill_focus_use_rope, feat_skill_focus_survival
feat_skill_focus_swim, feat_skill_focus_tumble, feat_skill_focus_use_magic_device, feat_skill_focus_use_rope, feat_skill_focus_survival, "Swift Ambusher"
]

class_skills = (skill_alchemy, skill_balance, skill_climb, skill_craft, skill_disable_device, skill_escape_artist, skill_hide, skill_jump, skill_knowledge_nature, skill_listen, skill_move_silently, skill_ride, skill_search, skill_sense_motive, skill_spot, skill_wilderness_lore, skill_swim, skill_tumble, skill_use_rope)
Expand Down
5 changes: 5 additions & 0 deletions tpdatasrc/tpgamefiles/rules/feats/daring outlaw.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: Daring Outlaw
flags: 12582912
prereqs:
description: Your rogue and swashbuckler levels stack for the purpose of determining your competence bonus on Reflex saves from the grace class feature and the swashbuckler's dodge bonus to AC. Your rogue and swashbuckler levels also stack for the purpose of determining your sneak attack bonus damage.
prereq descr: Sneak attack +2d6, Grace +1
5 changes: 5 additions & 0 deletions tpdatasrc/tpgamefiles/rules/feats/swift ambusher.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: Swift Ambusher
flags: 12582912
prereqs:
description: Your rogue and scout levels stack for the purpose of determining the extra damage and bonus to Armor Class granted when skirmishing.
prereq descr: Sneak attack +1d6, Skirmish +1d6
17 changes: 17 additions & 0 deletions tpdatasrc/tpgamefiles/scr/feats/feat - Daring Outlaw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from toee import *
import char_editor

def CheckPrereq(attachee, classLeveled, abilityScoreRaised):

#Sneak Attack Bonus +2D6
if attachee.d20_query_with_data("Sneak Attack Dice", classLeveled) < 2:
return 0

#Grace +1 requirement
swashBucklerLevel = attachee.stat_level_get(stat_level_swashbuckler)
if classLeveled == stat_level_swashbuckler:
swashBucklerLevel = swashBucklerLevel + 1
if swashBucklerLevel < 2:
return 0

return 1
18 changes: 18 additions & 0 deletions tpdatasrc/tpgamefiles/scr/feats/feat - Swift Ambusher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from toee import *
import char_editor

def CheckPrereq(attachee, classLeveled, abilityScoreRaised):

#Sneak Attack Bonus +1D6
if attachee.d20_query_with_data("Sneak Attack Dice", classLeveled) < 1:
if classLeveled != stat_level_rogue:
return 0

#Skirmish +1D6
scoutLevel = attachee.stat_level_get(stat_level_scout)
if classLeveled == stat_level_scout:
scoutLevel = scoutLevel + 1
if scoutLevel < 1:
return 0

return 1
2 changes: 2 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/arcane_trickster.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def OnGetSaveThrowWill(attachee, args, evt_obj):

def ArcTrkSneakAttackDice(attachee, args, evt_obj):
arcTrkLvl = attachee.stat_level_get(classEnum)
if evt_obj.data1 == classEnum: #class leveling up
arcTrkLvl = arcTrkLvl + 1
if arcTrkLvl <= 0:
return 0
evt_obj.return_val += arcTrkLvl /2
Expand Down
2 changes: 2 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/assassin.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def OnGetSaveThrowWill(attachee, args, evt_obj):

def AssassinSneakAttackDice(attachee, args, evt_obj):
ass_lvl = attachee.stat_level_get(classEnum)
if evt_obj.data1 == classEnum: #class leveling up
ass_lvl = ass_lvl + 1
evt_obj.return_val += 1+(ass_lvl-1) /2
return 0

Expand Down
3 changes: 3 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/blackguard.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def OnGetSaveThrowWill(attachee, args, evt_obj):
def BlackguardSneakAttackDice(attachee, args, evt_obj):
blg_lvl = attachee.stat_level_get(classEnum)
palLvl = attachee.stat_level_get(stat_level_paladin)

if evt_obj.data1 == classEnum: #class leveling up
blg_lvl = blg_lvl + 1

if blg_lvl < 4 and palLvl < 5:
return 0
Expand Down
18 changes: 18 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/bracers_of_archery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from templeplus.pymod import PythonModifier
from toee import *
import tpdp

# Fix for Atari Bug 90
# Extend bracers of archery (greater - 6267 and lesser - 6268) to provide the appropriate proficiencies
print "Bracers of Archery extender"

def BracersOfArcheryProficientWithWeapon(attachee, args, evt_obj):
# Makes the character proficient with all bows (except crossbows)
weaponType = evt_obj.data1
if (weaponType == wt_longbow or weaponType == wt_shortbow or weaponType == wt_composite_shortbow or weaponType == wt_composite_longbow):
evt_obj.return_val = 1
return 0

modExtender = PythonModifier()
modExtender.ExtendExisting("Bracers of Archery")
modExtender.AddHook(ET_OnD20PythonQuery, "Proficient with Weapon", BracersOfArcheryProficientWithWeapon, ())
30 changes: 30 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/daring_outlaw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from templeplus.pymod import PythonModifier
from toee import *
import tpdp
import math

#Daring Outlaw: Complete Scoundrel, p. 76

print "Registering Daring Outlaw"

def SneakAttackLevelBonus(attachee, args, evt_obj):
swashLevel = attachee.stat_level_get(stat_level_swashbuckler)
evt_obj.return_val += swashLevel
return 0

def GraceLevelBonus(attachee, args, evt_obj):
rogueLevel = attachee.stat_level_get(stat_level_rogue)
evt_obj.return_val += rogueLevel
return 0

def DodgeLevelBonus(attachee, args, evt_obj):
rogueLevel = attachee.stat_level_get(stat_level_rogue)
evt_obj.return_val += rogueLevel
return 0

daringOutlaw = PythonModifier("Daring Outlaw", 2) # args are just-in-case placeholders
daringOutlaw.MapToFeat("Daring Outlaw")
daringOutlaw.AddHook(ET_OnD20PythonQuery, "Rogue Sneak Attack Level Bonus", SneakAttackLevelBonus, ())
daringOutlaw.AddHook(ET_OnD20PythonQuery, "Swashbuckler Grace Level Bonus", GraceLevelBonus, ())
daringOutlaw.AddHook(ET_OnD20PythonQuery, "Swashbuckler Dodge Level Bonus", DodgeLevelBonus, ())

4 changes: 4 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/rogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def OnGetSaveThrowWill(attachee, args, evt_obj):

def RogueSneakAttackDice(attachee, args, evt_obj):
rogLvl = attachee.stat_level_get(classEnum)
rogLvlBonus = attachee.d20_query("Rogue Sneak Attack Level Bonus")
rogLvl = rogLvl + rogLvlBonus
if evt_obj.data1 == classEnum: #class leveling up
rogLvl = rogLvl + 1
if rogLvl <= 0:
return 0
evt_obj.return_val += 1+ (rogLvl - 1)/2
Expand Down
4 changes: 4 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/scout.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,15 @@ def ScoutEncumberedCheck(obj):
#Calculate the skrimish bonus for the scout
def GetSkirmishACBonus(obj):
scoutLevel = float(obj.stat_level_get(stat_level_scout))
scoutBonusLevels = obj.d20_query("Skrimish Level Bonus")
scoutLevel = scoutLevel + scoutBonusLevels
bonusValue = int((scoutLevel + 1.0) / 4.0)
return bonusValue

def GetSkirmishDamageDice(obj):
scoutLevel = float(obj.stat_level_get(stat_level_scout))
scoutBonusLevels = obj.d20_query("Skrimish Level Bonus")
scoutLevel = scoutLevel + scoutBonusLevels
bonusValue = int((scoutLevel - 1)/ 4.0 + 1)
bonusDice = str(bonusValue) + "d6"
return bonusDice
Expand Down
4 changes: 4 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/swashbuckler.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ def SwashbucklerGraceReflexBonus(attachee, args, evt_obj):
return 0

classLvl = attachee.stat_level_get(classEnum)
classBonusLvls = attachee.d20_query("Swashbuckler Grace Level Bonus")
classLvl = classLvl + classBonusLvls
if classLvl < 11:
bonval = 1
elif classLvl < 20:
Expand Down Expand Up @@ -157,6 +159,8 @@ def SwashbucklerDodgeACBonus(attachee, args, evt_obj):
return 0

classLvl = attachee.stat_level_get(classEnum)
classBonusLvls = attachee.d20_query("Swashbuckler Dodge Level Bonus")
classLvl = classLvl + classBonusLvls
bonval = classLvl / 5
evt_obj.bonus_list.add(bonval, 8, 137 ) #Dodge bonus
args.set_args_from_obj(0, attacker)
Expand Down
19 changes: 19 additions & 0 deletions tpdatasrc/tpgamefiles/scr/tpModifiers/swift_ambusher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from templeplus.pymod import PythonModifier
from toee import *
import tpdp
import math

#Swift Ambusher: Complete Scoundrel, p. 81

print "Registering Complete Scoundrel"

def SkirmishBonusLevels(attachee, args, evt_obj):
rogueLevel = attachee.stat_level_get(stat_level_rogue)
evt_obj.return_val += rogueLevel
return 0


daringOutlaw = PythonModifier("Swift Ambusher", 2) # args are just-in-case placeholders
daringOutlaw.MapToFeat("Swift Ambusher")
daringOutlaw.AddHook(ET_OnD20PythonQuery, "Skrimish Level Bonus", SkirmishBonusLevels, ())

0 comments on commit a17c061

Please sign in to comment.