-
Notifications
You must be signed in to change notification settings - Fork 1
/
bladesinger.py
170 lines (147 loc) · 6.57 KB
/
bladesinger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
from templeplus.pymod import PythonModifier
from toee import *
import tpdp
import char_class_utils
import d20_action_utils
###################################################
def GetConditionName():
return "Bladesinger"
def GetSpellCasterConditionName():
return "Bladesinger Spellcasting"
print "Registering " + GetConditionName()
classEnum = stat_level_bladesinger
classSpecModule = __import__('class033_bladesinger')
###################################################
#### standard callbacks - BAB and Save values
def OnGetToHitBonusBase(attachee, args, evt_obj):
classLvl = attachee.stat_level_get(classEnum)
babvalue = game.get_bab_for_class(classEnum, classLvl)
evt_obj.bonus_list.add(babvalue, 0, 137)
return 0
def OnGetSaveThrowFort(attachee, args, evt_obj):
value = char_class_utils.SavingThrowLevel(classEnum, attachee, D20_Save_Fortitude)
evt_obj.bonus_list.add(value, 0, 137)
return 0
def OnGetSaveThrowReflex(attachee, args, evt_obj):
value = char_class_utils.SavingThrowLevel(classEnum, attachee, D20_Save_Reflex)
evt_obj.bonus_list.add(value, 0, 137)
return 0
def OnGetSaveThrowWill(attachee, args, evt_obj):
value = char_class_utils.SavingThrowLevel(classEnum, attachee, D20_Save_Will)
evt_obj.bonus_list.add(value, 0, 137)
return 0
def IsLightlyArmored( obj ):
armor = obj.item_worn_at(5)
if armor != OBJ_HANDLE_NULL:
armorFlags = armor.obj_get_int(obj_f_armor_flags)
if armorFlags != ARMOR_TYPE_NONE or ARMOR_TYPE_LIGHT:
return 0
shield = obj.item_worn_at(11)
if shield != OBJ_HANDLE_NULL:
return 0
return 1
def IsRangedWeapon( weap ):
weapFlags = weap.obj_get_int(obj_f_weapon_flags)
if (weapFlags & OWF_RANGED_WEAPON) == 0:
return 0
return 1
def IsRapierorLongsword( obj, weap):
weaponType = weap.obj_get_int(obj_f_weapon_type)
if weaponType != wt_rapier or wt_longsword:
return 0
def IsUsingBladeSongWeapon( obj ):
weap = obj.item_worn_at(3)
offhand = obj.item_worn_at(4)
if weap == OBJ_HANDLE_NULL and offhand == OBJ_HANDLE_NULL:
return 0
if weap == OBJ_HANDLE_NULL:
weap = offhand
offhand = OBJ_HANDLE_NULL
if IsRapierorLongsword(obj, weap):
return 1
if offhand != OBJ_HANDLE_NULL:
if IsRapierorLongsword(obj, offhand):
return 1
return 0
def BladesongAcBonus(attachee, args, evt_obj):
if not IsLightlyArmored(attachee):
return 0
if not IsUsingBladeSongWeapon(obj):
return 0
if offhand != OBJ_HANDLE_NULL:
return 0
weap = attachee.item_worn_at(3)
if weap == OBJ_HANDLE_NULL or IsRangedWeapon(weap):
weap = attachee.item_worn_at(4)
if weap == OBJ_HANDLE_NULL or IsRangedWeapon(weap):
return 0
bladesingerLvl = attachee.stat_level_get(classEnum)
intScore = attachee.stat_level_get(stat_intelligence)
intBonus = (intScore - 10)/2
if intBonus <= 0:
return
if bladesingerLvl < intBonus:
intBonus = bladesingerLvl
evt_obj.bonus_list.modify(intBonus , 3, 104)
return 0
classSpecObj = PythonModifier(GetConditionName(), 0)
classSpecObj.AddHook(ET_OnToHitBonusBase, EK_NONE, OnGetToHitBonusBase, ())
classSpecObj.AddHook(ET_OnSaveThrowLevel, EK_SAVE_FORTITUDE, OnGetSaveThrowFort, ())
classSpecObj.AddHook(ET_OnSaveThrowLevel, EK_SAVE_REFLEX, OnGetSaveThrowReflex, ())
classSpecObj.AddHook(ET_OnSaveThrowLevel, EK_SAVE_WILL, OnGetSaveThrowWill, ())
classSpecObj.AddHook(ET_OnGetAC, EK_NONE, BladesongAcBonus, ())
##### Spell casting
def OnAddSpellCasting(attachee, args, evt_obj):
if (args.get_arg(0) == 0):
args.set_arg(0, char_class_utils.GetHighestArcaneClass(attachee))
return 0
def OnGetBaseCasterLevel(attachee, args, evt_obj):
class_extended_1 = args.get_arg(0)
class_code = evt_obj.arg0
if (class_code != class_extended_1):
if (evt_obj.arg1 == 0):
return 0
classLvl = attachee.stat_level_get(classEnum)
evt_obj.bonus_list.add(classLvl, 0, 137)
return 0
def OnSpellListExtensionGet(attachee, args, evt_obj):
class_extended_1 = args.get_arg(0)
class_code = evt_obj.arg0
if (class_code != class_extended_1):
if (evt_obj.arg1 == 0):
return 0
classLvl = attachee.stat_level_get(classEnum)
evt_obj.bonus_list.add(classLvl, 0, 137)
return 0
def OnInitLevelupSpellSelection(attachee, args, evt_obj):
if (evt_obj.arg0 != classEnum):
return 0
classLvl = attachee.stat_level_get(classEnum)
if (classLvl == 0):
return 0
class_extended_1 = args.get_arg(0)
classSpecModule.InitSpellSelection(attachee, class_extended_1)
return 0
def OnLevelupSpellsCheckComplete(attachee, args, evt_obj):
if (evt_obj.arg0 != classEnum):
return 0
class_extended_1 = args.get_arg(0)
if (not classSpecModule.LevelupCheckSpells(attachee, class_extended_1) ):
evt_obj.bonus_list.add(-1, 0, 137)
return 1
def OnLevelupSpellsFinalize(attachee, args, evt_obj):
if (evt_obj.arg0 != classEnum):
return 0
classLvl = attachee.stat_level_get(classEnum)
if (classLvl == 0):
return 0
class_extended_1 = args.get_arg(0)
classSpecModule.LevelupSpellsFinalize(attachee, class_extended_1)
return
spellCasterSpecObj = PythonModifier(GetSpellCasterConditionName(), 8)
spellCasterSpecObj.AddHook(ET_OnConditionAdd, EK_NONE, OnAddSpellCasting, ())
spellCasterSpecObj.AddHook(ET_OnGetBaseCasterLevel, EK_NONE, OnGetBaseCasterLevel, ())
spellCasterSpecObj.AddHook(ET_OnSpellListExtensionGet, EK_NONE, OnSpellListExtensionGet, ())
spellCasterSpecObj.AddHook(ET_OnLevelupSystemEvent, EK_LVL_Spells_Activate, OnInitLevelupSpellSelection, ())
spellCasterSpecObj.AddHook(ET_OnLevelupSystemEvent, EK_LVL_Spells_Check_Complete, OnLevelupSpellsCheckComplete, ())
spellCasterSpecObj.AddHook(ET_OnLevelupSystemEvent, EK_LVL_Spells_Finalize, OnLevelupSpellsFinalize, ())