diff --git a/tpdatasrc/palcov/scr/Spell026 - Banishment.py b/tpdatasrc/palcov/scr/Spell026 - Banishment.py new file mode 100644 index 000000000..cf2da6e86 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell026 - Banishment.py @@ -0,0 +1,103 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Banishment OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Banishment OnSpellEffect" + + remove_list = [] + + spell.duration = 0 + hitDiceAmount = 2 * spell.caster_level + banish_casterLV = spell.caster_level + + # check for any item that is distasteful to the subjects (Needs suggestions) + bonus1_list = [8028] ## Potion of Protection From Outsiders + for bonus1 in bonus1_list: + if spell.caster.item_find(bonus1) != OBJ_HANDLE_NULL: + spell.dc = spell.dc + 2 ## the saving throw DC increases by 2 + # does NOT work! (Needs a fix.) + # spell.caster_level = spell.caster_level + 1 ## +1 bonus on your caster level check for overcoming Spell Resistance + + # check for rare items that work twice as well as a normal item for the purpose of the bonuses (Needs suggestions) + bonus2_list = [12900] ## Swamp Lotus + for bonus2 in bonus2_list: + if spell.caster.item_find(bonus2) != OBJ_HANDLE_NULL: + spell.dc = spell.dc + 4 ## the saving throw DC increases by 4 + # does NOT work! (Needs a fix.) + # spell.caster_level = spell.caster_level + 2 ## +2 bonus on your caster level check for overcoming Spell Resistance + + for target_item in spell.target_list: + + # check critter hit dice + targetHitDice = target_item.obj.hit_dice_num + + # check if target does not exceed the amount allowed + if hitDiceAmount >= targetHitDice: + + # spell.dc is DC - target's HD + caster's caster_level + #- spell.dc = spell.dc - targetHitDice + banish_casterLV + #- spell.dc = max( 1, spell.dc ) + + # Fix for DC growing out of control, marc. + special_save_dc = spell.dc - targetHitDice + banish_casterLV + special_save_dc = max( 1, special_save_dc ) + + if (target_item.obj.type == obj_t_npc): + + # check target is EXTRAPLANAR + if target_item.obj.d20_query_has_spell_condition( sp_Summoned ) or target_item.obj.is_category_type( mc_type_outsider ) or target_item.obj.is_category_subtype(mc_subtype_extraplanar): + + # subtract the target's hit dice from the amount allowed + hitDiceAmount = hitDiceAmount - targetHitDice + + # allow Will saving throw to negate + if target_item.obj.saving_throw_spell( special_save_dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target_item.obj ) + + else: + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # creature is sent back to its own plane (no 20% of wrong plane, DUMB) + # kill for now + # So you'll get awarded XP for the kill + if not target_item.obj in game.leader.group_list(): + target_item.obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item.obj.critter_kill() + if target_item.obj.d20_query_has_spell_condition( sp_Summoned ): + game.particles( 'sp-Dismissal', target_item.obj.location ) + target_item.obj.destroy() + else: + game.particles( 'sp-Dismissal', target_item.obj ) + target_item.obj.condition_add_with_args( 'sp-Animate Dead', spell.id, spell.duration, 3 ) + + else: + # target is not EXTRAPLANAR + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31007 ) + game.particles( 'Fizzle', target_item.obj ) + + else: + # target is not an NPC + game.particles( 'Fizzle', target_item.obj ) + + else: + # ran out of allowed HD + game.particles( 'Fizzle', target_item.obj ) + + remove_list.append( target_item.obj ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Banishment OnBeginRound" + +def OnEndSpellCast( spell ): + print "Banishment OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell036 - Blasphemy.py b/tpdatasrc/palcov/scr/Spell036 - Blasphemy.py new file mode 100644 index 000000000..2b4d47e34 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell036 - Blasphemy.py @@ -0,0 +1,98 @@ +from toee import * +from utilities import dbug + +def OnBeginSpellCast( spell ): + print "Blasphemy OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Blasphemy OnSpellEffect" + + remove_list = [] + spell.dc = spell.dc + 4 # will save vs. Banishment is -4 + spell.caster_level = fix_caster_level(spell) + + # List can mutate during processing, so loop through a copy, marc + for target_item in list(spell.target_list): # for target_item in spell.target_list: + + obj_hit_dice = target_item.obj.hit_dice_num + alignment = target_item.obj.critter_get_alignment() + dbug(" target_item.obj",target_item.obj,'holy') + + # Only works on non-evil creatures + if not (alignment & ALIGNMENT_EVIL) and not (target_item.obj == spell.caster): + + game.particles( 'sp-Slay Living', target_item.obj ) + dbug(" target_item NOT EVIL",-99,'holy') + + # Anything ten or more levels below the caster's level dies + if obj_hit_dice <= (spell.caster_level - 10): + # So you'll get awarded XP for the kill + if not target_item.obj in game.leader.group_list(): + target_item.obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item.obj.critter_kill() + + # Anything five or more levels below the caster's level is paralyzed + if obj_hit_dice <= (spell.caster_level - 5): + spell.duration = game.random_range(1,10) * 10 + target_item.obj.condition_add_with_args( 'sp-Hold Monster', spell.id, spell.duration, 0 ) + + # Anything one or more levels below the caster's level is weakened + if obj_hit_dice <= (spell.caster_level - 1): + spell.duration = game.random_range(1,4) + game.random_range(1,4) + dam_amount = game.random_range(1,6) + game.random_range(1,6) + target_item.obj.condition_add_with_args( 'sp-Ray of Enfeeblement', spell.id, spell.duration, dam_amount ) + + # Anything the caster's level or below is dazed + if obj_hit_dice <= (spell.caster_level): + spell.duration = 1 + target_item.obj.condition_add_with_args( 'sp-Daze', spell.id, spell.duration, 0 ) + + # Summoned and extraplanar creatures below the caster's level are also banished + # if they fail a Will save at -4 + if target_item.obj.d20_query_has_spell_condition( sp_Summoned ) or target_item.obj.npc_flags_get() & ONF_EXTRAPLANAR != 0: + + # allow Will saving throw to negate + if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target_item.obj ) + + else: + + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # creature is sent back to its own plane + # kill for now + target_item.obj.critter_kill() + + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Blasphemy OnBeginRound" + +def OnEndSpellCast( spell ): + print "Blasphemy OnEndSpellCast" + +#------------------------------------------------------------------------------ +# Fix for cleric domain bug, which wrongly increases caster level by +1 +# for each unfriendly target on the list. +#------------------------------------------------------------------------------ +def fix_caster_level (spell): + dbug("\n\nBLASPHEMY\n----------------",-99,'holy') + dbug("BEFORE spell.caster_level",spell.caster_level,'holy') + dbug("BEFORE len(spell.target_list)",len(spell.target_list),'holy') + if spell.caster.obj_get_int(obj_f_critter_domain_1) == evil or spell.caster.obj_get_int(obj_f_critter_domain_2) == evil: + if spell.caster.stat_level_get(stat_level_cleric) >= 13: + for t in spell.target_list: + if not spell.caster.is_friendly(t.obj): + spell.caster_level = spell.caster_level - 1 + dbug("AFTER spell.caster_level",spell.caster_level,'holy') + return spell.caster_level diff --git a/tpdatasrc/palcov/scr/Spell040 - Blindness Deafness.py b/tpdatasrc/palcov/scr/Spell040 - Blindness Deafness.py new file mode 100644 index 000000000..5c36af8c8 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell040 - Blindness Deafness.py @@ -0,0 +1,67 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Blindness/Deafness OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-necromancy-conjure", spell.caster ) + return 1 + +def OnSpellEffect( spell ): + print "Blindness/Deafness OnSpellEffect" + + if spell.caster.name == 14959: # Nymph + spell.dc = 17 # 10 + 3 + 4 (charisma) + spell.caster_level = 7 + + spell.duration = 14400 + target_item = spell.target_list[0] + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg != 1 and spell_arg != 2: + spell_arg = 1 # blineness, marc + + # allow Fortitude saving throw to negate + if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + if spell_arg == 1: + # apply blindness + return_val = target_item.obj.condition_add_with_args( 'sp-Blindness', spell.id, spell.duration, 0 ) + if return_val == 1: + target_item.partsys_id = game.particles( 'sp-Blindness-Deafness', target_item.obj ) + + else: + # apply deafness + return_val = target_item.obj.condition_add_with_args( 'sp-Deafness', spell.id, spell.duration, 0 ) + if return_val == 1: + target_item.partsys_id = game.particles( 'sp-Blindness-Deafness', target_item.obj ) + + # Nymph + if spell.caster.name == 14959: + for pc in game.party: + if pc != target_item.obj and spell.caster.distance_to(pc) <= 50: + if pc.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + pc.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', pc ) + else: + pc.float_mesfile_line( 'mes\\spell.mes', 30002 ) + return_val = pc.condition_add_with_args( 'sp-Blindness', spell.id, spell.duration, 0 ) + if return_val == 1: + game.particles( 'sp-Blindness-Deafness', pc ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Blindness/Deafness OnBeginRound" + +def OnEndSpellCast( spell ): + print "Blindness/Deafness OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell056 - Charm Person.py b/tpdatasrc/palcov/scr/Spell056 - Charm Person.py new file mode 100644 index 000000000..34e95090d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell056 - Charm Person.py @@ -0,0 +1,79 @@ +from toee import * +from utilities import * +from exclusions import * + +def OnBeginSpellCast( spell ): + print "Charm Person OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Charm Person OnSpellEffect" + + if spell.caster.name in [14937]: # Nixie + spell.dc = 15 # 10 + 1 + 4 (charisma) + spell.caster_level = 4 + elif spell.caster.name in [14507]: # Dryad + spell.dc = 13 # 10 + 1 + 2 (wisdom) + spell.caster_level = 6 + + spell.duration = 600 * spell.caster_level + target_item = spell.target_list[0] + target_item_obj = target_item.obj + + if game.global_vars[451] & 2**2 != 0: + if game.combat_is_active(): + spell.dc = spell.dc - 5 # to reflect a bonus to the saving throw for casting charm in combat + + if (not spell.caster in game.party) and (target_item.obj.type != obj_t_pc) and (target_item.obj in game.party): + # NPC enemy is trying to charm an NPC from your party - this is bad because it effectively kills the NPC (is dismissed from party and becomes hostile, thus becoming unrecruitable unless you use dominate person/monster) + target_item_obj = party_closest( spell.caster, conscious_only= 1, mode_select= 0, exclude_warded= 0, exclude_charmed = 1) # select nearest conscious PC instead, who isn't already charmed + if target_item_obj == OBJ_HANDLE_NULL: + target_item_obj = target_item.obj + + if not target_item_obj.is_friendly( spell.caster ): + if target_item_obj.is_category_type( mc_type_humanoid ): + + if not target_item_obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw unsuccessful + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + spell.caster.ai_follower_add( target_item_obj ) + + target_item_obj.condition_add_with_args( 'sp-Charm Person', spell.id, spell.duration, target_item.obj.hit_dice_num ) + target_item.partsys_id = game.particles( 'sp-Charm Person', target_item_obj ) + + # add target to initiative, just in case + target_item_obj.add_to_initiative() + game.update_combat_ui() + + else: + + # saving throw successful + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item_obj ) + spell.target_list.remove_target( target_item_obj ) + + else: + # not a humanoid + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item_obj ) + + else: + + # can't target friendlies + game.particles( 'Fizzle', target_item_obj ) + spell.target_list.remove_target( target_item_obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Charm Person OnBeginRound" + +def OnEndSpellCast( spell ): + print "Charm Person OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell065 - Cloudkill.py b/tpdatasrc/palcov/scr/Spell065 - Cloudkill.py new file mode 100644 index 000000000..3eda66c62 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell065 - Cloudkill.py @@ -0,0 +1,46 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Cloudkill OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Cloudkill OnSpellEffect" + + spell.duration = 10 * spell.caster_level + + # added so you'll get awarded XP for the kill + for target_item in spell.target_list: + if not target_item.obj in game.leader.group_list(): + if target_item.obj.object_flags_get() & OF_INVULNERABLE == 0: + target_item.obj.object_flag_set(OF_INVULNERABLE) + target_item.obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item.obj.object_flag_unset(OF_INVULNERABLE) + else: + target_item.obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + + # spawn one Cloudkill scenery object + cloudkill_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + cloudkill_obj.d20_status_init() + cloudkill_obj.set_initiative( caster_init_value ) + + # put sp-cloudkill_obj condition on obj + cloudkill_obj_partsys_id = game.particles( 'sp-Cloudkill', cloudkill_obj ) + cloudkill_obj.condition_add_with_args( 'sp-Cloudkill', spell.id, spell.duration, 0, cloudkill_obj_partsys_id ) + +def OnBeginRound( spell ): + print "Cloudkill OnBeginRound" + +def OnEndSpellCast( spell ): + print "Cloudkill OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Cloudkill OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Cloudkill OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell067 - Command.py b/tpdatasrc/palcov/scr/Spell067 - Command.py new file mode 100644 index 000000000..b322ce9d2 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell067 - Command.py @@ -0,0 +1,96 @@ +from utilities import * +from toee import * + +import _include +from co8Util.PersistentData import * +from co8Util.ObjHandling import * +from co8Util.spells import * + +def OnBeginSpellCast( spell ): + print "Command OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Command OnSpellEffect" + + spell.duration = 1 + target_item = spell.target_list[0] + + npc = spell.caster ## added so NPC's will choose valid targets + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg != 1 and spell_arg != 2 and spell_arg != 3 and spell_arg != 4: + spell_arg = 2 + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + spell_arg = 2 + + if not target_item.obj.is_friendly( spell.caster ): + if (target_item.obj.type == obj_t_pc) or (target_item.obj.type == obj_t_npc): + if not target_item.obj.is_category_type( mc_type_animal ): + #if ( target_item.obj.get_size < STAT_SIZE_LARGE or target_item.obj.is_category_type(mc_type_humanoid) ): + if 1: # let creatures of STAT_SIZE_LARGE be affected too, marc + + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id): + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + if target_item.obj.condition_add_with_args( 'sp-Command', spell.id, spell.duration, 2 ): + add_to_persistent_list (COMMAND_KEY, spell.id, target_item.obj) # marc + else: ## added so NPC's can cast Command + if target_item.obj.condition_add_with_args( 'sp-Command', spell.id, spell.duration, spell_arg ): + add_to_persistent_list (COMMAND_KEY, spell.id, target_item.obj) # marc + target_item.partsys_id = game.particles( 'sp-Command', target_item.obj ) + + # add target to initiative, just in case + #target_item.obj.add_to_initiative() + #game.update_combat_ui() + + else: + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + # not medium sized or smaller + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31005 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + # a monster + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + # not a person + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31001 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + + # can't target friendlies + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30003 ) + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Command OnBeginRound" + +def OnEndSpellCast( spell ): + print "Command OnEndSpellCast" + remove_from_persistent_list (COMMAND_KEY, spell.id) # marc diff --git a/tpdatasrc/palcov/scr/Spell090 - Cure Light Wounds.py b/tpdatasrc/palcov/scr/Spell090 - Cure Light Wounds.py new file mode 100644 index 000000000..a8a8621f7 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell090 - Cure Light Wounds.py @@ -0,0 +1,81 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Cure Light Wounds OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Cure Light Wounds OnSpellEffect" + + npc = spell.caster ## added so NPC's can use potion + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL and spell.caster_level <= 0: + spell.caster_level = 4 + + dice = dice_new( "1d8" ) + dice.bonus = min( 5, spell.caster_level ) + + target = spell.target_list[0].obj + + # check if target is friendly (willing target) + if target.is_friendly( spell.caster ): + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # heal target + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + #target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + game.particles( 'sp-Cure Light Wounds', target ) + + spell.target_list.remove_target( target ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Cure Light Wounds OnBeginRound" + +def OnEndSpellCast( spell ): + print "Cure Light Wounds OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell092 - Cure Moderate Wounds.py b/tpdatasrc/palcov/scr/Spell092 - Cure Moderate Wounds.py new file mode 100644 index 000000000..ce98301ce --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell092 - Cure Moderate Wounds.py @@ -0,0 +1,81 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Cure Moderate Wounds OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Cure Moderate Wounds OnSpellEffect" + + npc = spell.caster ## added so NPC's can use potion + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL and spell.caster_level <= 0: + spell.caster_level = 7 + dice = dice_new( "2d8" ) + dice.bonus = min( 10, spell.caster_level ) + + target = spell.target_list[0].obj + + # check if target is friendly (willing target) + if target.is_friendly( spell.caster ): + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # heal target + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + #target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + game.particles( 'sp-Cure Moderate Wounds', target ) + + spell.target_list.remove_target( target ) + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Cure Moderate Wounds OnBeginRound" + +def OnEndSpellCast( spell ): + print "Cure Moderate Wounds OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell093 - Cure Serious Wounds.py b/tpdatasrc/palcov/scr/Spell093 - Cure Serious Wounds.py new file mode 100644 index 000000000..13c2aa765 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell093 - Cure Serious Wounds.py @@ -0,0 +1,81 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Cure Serious Wounds OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Cure Serious Wounds OnSpellEffect" + + npc = spell.caster ## added so NPC's can use potion + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL and spell.caster_level <= 0: + spell.caster_level = 10 + + dice = dice_new( "3d8" ) + dice.bonus = min( 15, spell.caster_level ) + + target = spell.target_list[0].obj + + # check if target is friendly (willing target) + if target.is_friendly( spell.caster ): + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # heal target + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + #target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + game.particles( 'sp-Cure Serious Wounds', target ) + + spell.target_list.remove_target( target ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Cure Serious Wounds OnBeginRound" + +def OnEndSpellCast( spell ): + print "Cure Serious Wounds OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell104 - Delay Poison.py b/tpdatasrc/palcov/scr/Spell104 - Delay Poison.py new file mode 100644 index 000000000..1af99114d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell104 - Delay Poison.py @@ -0,0 +1,41 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Delay Poison OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Delay Poison OnSpellEffect" + + spell.duration = 600 * spell.caster_level + target_item = spell.target_list[0] + + if target_item.obj.is_friendly( spell.caster ): + target_item.obj.condition_add_with_args( 'sp-Delay Poison', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Delay Poison', target_item.obj ) + else: + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw unsuccesful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + target_item.obj.condition_add_with_args( 'sp-Delay Poison', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Delay Poison', target_item.obj ) + + else: + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Delay Poison OnBeginRound" + +def OnEndSpellCast( spell ): + print "Delay Poison OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell105 - Delayed Blast Fireball.py b/tpdatasrc/palcov/scr/Spell105 - Delayed Blast Fireball.py new file mode 100644 index 000000000..fda7b4777 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell105 - Delayed Blast Fireball.py @@ -0,0 +1,191 @@ +from toee import * +from utilities import * +from scripts import set_spell_flag, get_spell_flags, find_spell_obj_with_flag + +## How this works: +## +## A variable is set in moduels\ToEE\delayed_blast_fireball.txt, that determines how many rounds the fireball is delayed. +## If it's 0, the spell works just like ordinary Fireball, except the damage is limited to 20d6 rather than 10d6. +## If it's greater than 0: +## The spell's duration is set to the delay. +## A "spell object" is created. (proto 6271; actually an armor object) +## This spell object is assigned a randomized ID, and borks the dc ??????? +## When the number of rounds equal to the delay passes, the spell "ends". +## This triggers the OnEndSpellCast() script. +## The script looks for the spell object in the spell caster's vicinity. +## NB: This means that changing maps or walking far away will bork the spell. +## If the spell object is found: +## Target everything in its vicinity using a 360 degree targeting cone, with a reach of 20. +## Asplode! +## Possibly enlarge spell, maximize spell etc won't work? +## Now given the Water Temple pool treatment + +def OnBeginSpellCast( spell ): + print "Delayed Blast Fireball OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Delayed Blast Fireball OnSpellEffect" + + if spell.caster.name in [14691]: # Gelwea + spell.dc = 17 # 10 + 7 + 3 + spell.caster_level = 16 + + game.particles( 'sp-Fireball-conjure', spell.caster ) + remove_list = [] + delay = 0 + dam = dice_new( '1d6' ) + dam.number = min( 20, spell.caster_level ) #edited by Allyx + +#- if game.global_vars[451] & 2**1 != 0: +#- if game.leader.map == 5083: ## Fire node - fire spells do x2 damage +#- dam.number = dam.number * 2 +#- elif game.leader.map == 5084: ## Water node - fire spells do 1/2 damage +#- dam.number = dam.number / 2 + + print type(spell.target_loc) + + # delay for npc casters is in global_vars[66] set in the casters's script, marc + if spell.caster.type != obj_t_pc and spell.caster.leader_get() == OBJ_HANDLE_NULL: + delay = game.global_vars[66] + game.global_vars[66] = 0 + else: + ifile = file('delayed_blast_fireball.txt','r') + str = ifile.readline() + ifile.close() + delay = int(str) + + print "delay = ", delay + spell.duration = delay + game.pfx_lightning_bolt( spell.caster, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y, spell.target_loc_off_z ) + + if delay == 0: + + xx,yy = location_to_axis(spell.target_loc) + if game.leader.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + # Water Temple Pool Enchantment prevents fire spells from working inside the chamber, according to the module -SA + tro = game.obj_create(14070, spell.target_loc) + game.particles( 'swirled gas', spell.target_loc ) + tro.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1 ) + tro.destroy() + game.sound(7581,1) + game.sound(7581,1) + for target_item in spell.target_list: + remove_list.append( target_item.obj ) + spell.target_list.remove_list( remove_list ) + spell.spell_end( spell.id ) + return + + game.particles( 'sp-Fireball-Hit', spell.target_loc ) + soundfizzle = 0 + + + for target_item in spell.target_list: + xx,yy = location_to_axis(target_item.obj.location) + if target_item.obj.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + # Water Temple Pool Enchantment prevents fire spells from working inside the chamber, according to the module -SA + target_item.obj.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1 ) + game.particles( 'swirled gas', target_item.obj ) + soundfizzle = 1 + remove_list.append( target_item.obj ) + continue + + if target_item.obj.reflex_save_and_damage( spell.caster, spell.dc, D20_Save_Reduction_Half, D20STD_F_NONE, dam, D20DT_FIRE, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ): + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + else: + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + remove_list.append( target_item.obj ) + + if soundfizzle == 1: + game.sound(7581,1) + game.sound(7581,1) + + spell.target_list.remove_list( remove_list ) + spell.spell_end( spell.id ) + + else: + + spell_obj = game.obj_create(6271, spell.target_loc) + spell_obj.item_flag_unset(OIF_NO_DROP) + for target_item in spell.target_list: + remove_list.append( target_item.obj) + spell.target_list.remove_list( remove_list ) + spell.num_of_targets = 1 + spell.target_list[0].obj = spell.caster + spell.target_list[0].obj.condition_add_with_args('sp-Mage Armor', spell.id, spell.duration, 0) + # spell.dc = game.random_range(0, 2147483647) + spell.target_loc = game.random_range(0,2147483647) + set_spell_flag(spell_obj, spell.dc ^ spell.target_loc) + + + +def OnBeginRound( spell ): + print "Delayed Blast Fireball OnBeginRound" + +def OnEndSpellCast( spell ): + print "Delayed Blast Fireball OnEndSpellCast" + spell_obj = OBJ_HANDLE_NULL + object_list = list(game.obj_list_cone( spell.caster, OLC_ARMOR, 200, -180, 360 )) + for t in object_list: #find the blast object in the area... + if get_spell_flags(t) == spell.dc ^ spell.target_loc: + spell_obj = t + if spell_obj == OBJ_HANDLE_NULL:#okay not there, maybe someone picked it up.... + pot_carriers = list(game.obj_list_cone( spell.caster, OLC_CRITTERS, 200, -180, 360 )) + for c in pot_carriers: + temp_obj = find_spell_obj_with_flag(c, 6271, 2147483647) + if temp_obj != OBJ_HANDLE_NULL: + if get_spell_flags(temp_obj) == spell.dc ^ spell.target_loc: + spell_obj = game.obj_create(6271, c.location) + temp_obj.destroy() + break + + if spell_obj != OBJ_HANDLE_NULL:#if spell_obj is null here then it has gone beyond my reach (map change or too far away) + targets = list(game.obj_list_cone( spell_obj, OLC_CRITTERS, 20, -180, 360 )) + dam = dice_new('1d6') + dam.number = min(20, spell.caster_level) + if game.leader.map == 5083: ## Fire node - fire spells do x2 damage + dam.number = dam.number * 2 + elif game.leader.map == 5084: ## Water node - fire spells do 1/2 damage + dam.number = dam.number / 2 + + + xx,yy = location_to_axis(spell_obj.location) + if game.leader.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + # Water Temple Pool Enchantment prevents fire spells from working inside the chamber, according to the module -SA + game.particles( 'swirled gas', spell_obj.location ) + spell_obj.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1 ) + game.sound(7581,1) + game.sound(7581,1) + spell_obj.destroy() + return + + game.particles( 'sp-Fireball-Hit', spell_obj.location ) + + soundfizzle = 0 + for target_item in targets: + xx,yy = location_to_axis(target_item.location) + if target_item.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + # Water Temple Pool Enchantment prevents fire spells from working inside the chamber, according to the module -SA + target_item.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1 ) + game.particles( 'swirled gas', target_item ) + soundfizzle = 1 + continue + if target_item.reflex_save_and_damage( spell.caster, spell.dc, D20_Save_Reduction_Half, D20STD_F_NONE, dam, D20DT_FIRE, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ): + # saving throw successful + target_item.float_mesfile_line( 'mes\\spell.mes', 30001 ) + else: + # saving throw unsuccessful + target_item.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + if soundfizzle == 1: + game.sound(7581,1) + game.sound(7581,1) + + spell_obj.destroy() + + diff --git a/tpdatasrc/palcov/scr/Spell121 - Dictum.py b/tpdatasrc/palcov/scr/Spell121 - Dictum.py new file mode 100644 index 000000000..ab5a15807 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell121 - Dictum.py @@ -0,0 +1,100 @@ +from toee import * +from utilities import dbug + +def OnBeginSpellCast( spell ): + print "Dictum OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Dictum OnSpellEffect" + + remove_list = [] + spell.dc = spell.dc + 4 # will save vs. Banishment is -4 + spell.caster_level = fix_caster_level(spell) + + # List can mutate during processing, so loop through a copy, marc + for target_item in list(spell.target_list): # for target_item in spell.target_list: + + obj_hit_dice = target_item.obj.hit_dice_num + alignment = target_item.obj.critter_get_alignment() + dbug(" target_item.obj",target_item.obj,'holy') + + # Only works on non-lawful creatures + if not (alignment & ALIGNMENT_LAWFUL) and not (target_item.obj == spell.caster): + + game.particles( 'sp-Destroy Undead', target_item.obj ) + dbug(" target_item NOT LAWFUL",-99,'holy') + + # Anything ten or more levels below the caster's level dies + if obj_hit_dice <= (spell.caster_level - 10): + # So you'll get awarded XP for the kill + if not target_item.obj in game.leader.group_list(): + target_item.obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item.obj.critter_kill() + + # Anything five or more levels below the caster's level is paralyzed + if obj_hit_dice <= (spell.caster_level - 5): + spell.duration = game.random_range(1,10) * 10 + target_item.obj.condition_add_with_args( 'sp-Hold Monster', spell.id, spell.duration, 0 ) + + # Anything one or more levels below the caster's level is slowed + if obj_hit_dice <= (spell.caster_level - 1): + spell.duration = game.random_range(1,4) + game.random_range(1,4) + target_item.obj.condition_add_with_args( 'sp-Slow', spell.id, spell.duration, 1 ) + + # Anything the caster's level or below is deafened + if obj_hit_dice <= (spell.caster_level): + spell.duration = game.random_range(1,4) + target_item.obj.condition_add_with_args( 'sp-Shout', spell.id, spell.duration, 0 ) + + # Summoned and extraplanar creatures below the caster's level are also banished + # if they fail a Will save at -4 + if target_item.obj.d20_query_has_spell_condition( sp_Summoned ) or target_item.obj.npc_flags_get() & ONF_EXTRAPLANAR != 0: + + # allow Will saving throw to negate + if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target_item.obj ) + + else: + + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # creature is sent back to its own plane + # kill for now + # So you'll get awarded XP for the kill + if not target_item.obj in game.leader.group_list(): + target_item.obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item.obj.critter_kill() + + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Dictum OnBeginRound" + +def OnEndSpellCast( spell ): + print "Dictum OnEndSpellCast" + +#------------------------------------------------------------------------------ +# Fix for cleric domain bug, which wrongly increases caster level by +1 +# for each unfriendly target on the list. +#------------------------------------------------------------------------------ +def fix_caster_level (spell): + dbug("\n\nDICTUM\n----------------",-99,'holy') + dbug("BEFORE spell.caster_level",spell.caster_level,'holy') + dbug("BEFORE len(spell.target_list)",len(spell.target_list),'holy') + if spell.caster.obj_get_int(obj_f_critter_domain_1) == law or spell.caster.obj_get_int(obj_f_critter_domain_2) == law: + if spell.caster.stat_level_get(stat_level_cleric) >= 13: + for t in spell.target_list: + if not spell.caster.is_friendly(t.obj): + spell.caster_level = spell.caster_level - 1 + dbug("AFTER spell.caster_level",spell.caster_level,'holy') + return spell.caster_level diff --git a/tpdatasrc/palcov/scr/Spell122 - Dimensional Anchor.py b/tpdatasrc/palcov/scr/Spell122 - Dimensional Anchor.py new file mode 100644 index 000000000..4f377cd54 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell122 - Dimensional Anchor.py @@ -0,0 +1,44 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Dimensional Anchor OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Dimensional Anchor OnSpellEffect" + +def OnBeginRound( spell ): + print "Dimensional Anchor OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Dimensional Anchor OnBeginProjectile" + + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Dimensional Anchor-proj', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Dimensional Anchor OnEndProjectile" + + spell.duration = 60 * spell.caster_level + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target_item = spell.target_list[0] + + if spell.caster.perform_touch_attack( target_item.obj ) & D20CAF_HIT: + + target_item.obj.condition_add_with_args( 'sp-Dimensional Anchor', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Dimensional Anchor', target_item.obj ) + + else: + # missed + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Dimensional Anchor OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell127 - Disintegrate.py b/tpdatasrc/palcov/scr/Spell127 - Disintegrate.py new file mode 100644 index 000000000..eed9dc8e5 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell127 - Disintegrate.py @@ -0,0 +1,101 @@ +from toee import * +from casters import staff_has, staff_stats +from Co8 import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Disintegrate OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-transmutation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Disintegrate OnSpellEffect" + +def OnBeginRound( spell ): + print "Disintegrate OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Disintegrate OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Ray of Frost', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Disintegrate', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Disintegrate OnEndProjectile" + + if staff_has(spell.caster) == 1: + CL, mod = staff_stats (spell.caster, '00011') + spell.caster_level = CL + spell.dc = 10 + 6 + mod + + damage_dice = dice_new( "1d6" ) + damage_dice.num = min( 40, spell.caster_level * 2 ) + spell.duration = 0 + + is_immune_to_crit = 0 + changed_con = 0 + + target_item = spell.target_list[0] + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + + return_val = spell.caster.perform_touch_attack( target_item.obj ) + + # hit + if return_val & D20CAF_HIT: + + game.particles( 'sp-Disintegrate-Hit', target_item.obj ) + + # Spiritual Weapon + if target_item.obj.name in (14629,14621,14604) and not is_spell_flag_set(target_item.obj, OSF_IS_FLAMING_SPHERE): + if target_item.obj.d20_query_has_spell_condition(sp_Otilukes_Resilient_Sphere) == 1: + target_item.obj.condition_add_with_args( 'sp-Break Enchantment', spell.id, spell.duration, 0 ) + game.particles( 'sp-Otilukes Resilient Sphere-END', target_item.obj.location ) + else: + game.particles( 'sp-Stoneskin', target_item.obj.location ) + target_item.obj.destroy() + + else: + + if target_item.obj.is_category_type( mc_type_construct ) or target_item.obj.is_category_type( mc_type_undead ): + if target_item.obj.stat_base_get(stat_constitution) < 0: + target_item.obj.stat_base_set(stat_constitution, 10) + changed_con = 1 + is_immune_to_crit = 1 + elif target_item.obj.is_category_type( mc_type_plant ) or target_item.obj.is_category_type( mc_type_ooze ) or target_item.obj.is_category_type( mc_type_elemental ): + is_immune_to_crit = 1 + elif return_val == 2: + damage_dice.num = damage_dice.num * 2 + + if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + damage_dice.num = 5 + #elif return_val == 2: + # damage_dice.num = damage_dice.num * 2 # handled internally now + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + target_item.obj.spell_damage( spell.caster, D20DT_FORCE, damage_dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + if target_item.obj.stat_level_get(stat_hp_current) < 1: + target_item.obj.critter_kill_by_effect() + # Don't Animate Dead on party members, only NPCs, it messes up spell scripting, marc + if target_item.obj.type != obj_t_pc and target_item.obj.leader_get() == OBJ_HANDLE_NULL: + target_item.obj.condition_add_with_args( 'sp-Animate Dead', spell.id, spell.duration, 3 ) + game.particles( 'sp-Stoneskin', target_item.obj ) + + # check for Otiluke's Resilient Sphere + if target_item.obj.d20_query_has_spell_condition(sp_Otilukes_Resilient_Sphere) == 1: + target_item.obj.condition_add_with_args( 'sp-Break Enchantment', spell.id, spell.duration, 0 ) + game.particles( 'sp-Otilukes Resilient Sphere-END', target_item.obj ) + + # missed + else: + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + game.particles( 'Fizzle', target_item.obj ) + + if changed_con == 1: + target_item.obj.stat_base_set(stat_constitution, -1) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Disintegrate OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell133 - Dispel Magic.py b/tpdatasrc/palcov/scr/Spell133 - Dispel Magic.py new file mode 100644 index 000000000..21612961d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell133 - Dispel Magic.py @@ -0,0 +1,114 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Dispel Magic OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + + # Max caster level for Dispel Magic is 10, marc + spell.caster_level = min(10, spell.caster_level) + + if spell.caster.name == 14938: # Pixie + spell.caster_level = 8 + elif spell.caster.name == 14950: # Noble Salamander + spell.caster_level = 15 + elif spell.caster.name == 14155: # Alrem Ghost (works as 7th level spell) + spell.caster_level = 15 + elif spell.caster.name == 14775: # Concubines, just to make them more effective + spell.caster_level = 10 + elif spell.caster.name == 14985: # Nightwalker + spell.caster_level = 21 + + # Make a normal list, as spell.target_list only attempts to dispel half the targets, marc + spell.spell_target_list_sort (SORT_TARGET_LIST_BY_DIST, SORT_TARGET_LIST_ORDER_ASCENDING) + targets = [] + for t in spell.target_list: + targets.append(t.obj) + + # NPC will use break enchantment, since condition "sp-Dispel Magic" will not target spells of 4th level or higher, marc + if spell.caster not in game.party: + float_mes(spell.caster,352,2) + target = targets[0] + if (target.type == obj_t_pc) or (target.type == obj_t_npc): + game.particles( 'sp-Dispel Magic - Targeted', target ) + target.condition_add_with_args( 'sp-Break Enchantment', spell.id, spell.duration, 0 ) + + # check if we are targeting an object or an area + elif spell.is_object_selected() == 1: + float_mes(spell.caster,352,2) + + #- target = spell.target_list[0] + target = targets[0] + + # support dispel on critters + #-if (target.obj.type == obj_t_pc) or (target.obj.type == obj_t_npc): + #- target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + if (target.type == obj_t_pc) or (target.type == obj_t_npc): + game.particles( 'sp-Dispel Magic - Targeted', target ) + target.condition_add_with_args( 'sp-Dispel Magic', spell.id, 0, 0 ) + + # support dispel on portals and containers + elif (target.obj.type == obj_t_portal) or (target.obj.type == obj_t_container): + if target.obj.portal_flags_get() & OPF_MAGICALLY_HELD: + target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + target.obj.portal_flag_unset( OPF_MAGICALLY_HELD ) + spell.target_list.remove_target( target.obj ) + + # support dispel on these obj_types: weapon, ammo, armor, scroll + # NO support for: money, food, key, written, generic, scenery, trap, bag + #elif (target.obj.type == obj_t_weapon) or (target.obj.type == obj_t_ammo) or (target.obj.type == obj_t_armor) or (target.obj.type == obj_t_scroll): + #print "[dispel magic] - items not supported yet!" + #game.particles( 'Fizzle', target.obj ) + #spell.target_list.remove_target( target.obj ) + + else: + float_mes(spell.caster,353,2) + + # draw area effect particles + game.particles( 'sp-Dispel Magic - Area', spell.target_loc ) + + #- for target in spell.target_list: + for target in targets: + float_num(target, max( int(target.distance_to(spell.caster)), 0 ), 2) + + #- if (target.obj.type == obj_t_pc) or (target.obj.type == obj_t_npc): + if (target.type == obj_t_pc) or (target.type == obj_t_npc): + + #- target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + game.particles( 'sp-Dispel Magic - Targeted', target) + + # fourth argument: 0 = dispel all, 1 = dispel once + # target.obj is removed from spell.target_list during the call, marc + + #- target.obj.condition_add_with_args( 'sp-Dispel Magic', spell.id, 0, 1 ) + target.condition_add_with_args( 'sp-Dispel Magic', spell.id, 0, 1 ) + + # Commented out this code, which will never do anything, marc + # Doors do not get targeted in the area of the spell. + # Containers do, but will not have portal flags set. + + # support dispel on portals and containers + #- elif (target.obj.type == obj_t_portal) or (target.obj.type == obj_t_container): + #- if target.obj.portal_flags_get() & OPF_MAGICALLY_HELD: + #- target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + #- target.obj.portal_flag_unset( OPF_MAGICALLY_HELD ) + #- spell.target_list.remove_target( target.obj ) + + # support dispel on these obj_types: weapon, ammo, armor, scroll + # NO support for: money, food, key, written, generic, scenery, trap, bag + #elif (target.obj.type == obj_t_weapon) or (target.obj.type == obj_t_ammo) or (target.obj.type == obj_t_armor) or (target.obj.type == obj_t_scroll): + #print "[dispel magic] - items not supported yet!" + #game.particles( 'Fizzle', target.obj ) + #spell.target_list.remove_target( target.obj ) + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Dispel Magic OnBeginRound" + +def OnEndSpellCast( spell ): + print "Dispel Magic OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell135 - Disrupt Undead.py b/tpdatasrc/palcov/scr/Spell135 - Disrupt Undead.py new file mode 100644 index 000000000..dbf8857a1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell135 - Disrupt Undead.py @@ -0,0 +1,58 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Disrupt Undead OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-necromancy-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Disrupt Undead OnSpellEffect" + +def OnBeginRound( spell ): + print "Disrupt Undead OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Disrupt Undead OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Disrupt Undead-proj', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Disrupt Undead-proj', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Disrupt Undead OnEndProjectile" + + spell.duration = 0 + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target = spell.target_list[0] + + if target.obj.is_category_type( mc_type_undead ): + + # perform ranged touch attack + attack_successful = spell.caster.perform_touch_attack( target.obj ) + if attack_successful & D20CAF_HIT: + + damage_dice = dice_new( '1d6' ) + + # hit + target.obj.spell_damage_weaponlike( spell.caster, D20DT_POSITIVE_ENERGY, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, attack_successful, index_of_target ) + target.partsys_id = game.particles( 'sp-Disrupt Undead-hit', target.obj ) + else: + + # missed + target.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + + game.particles( 'Fizzle', target.obj ) + + else: + + # not undead! + target.obj.float_mesfile_line( 'mes\\spell.mes', 31008 ) + + game.particles( 'Fizzle', target.obj ) + + spell.target_list.remove_target( target.obj ) + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Disrupt Undead OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell141 - Dominate Person.py b/tpdatasrc/palcov/scr/Spell141 - Dominate Person.py new file mode 100644 index 000000000..dbf41a3e6 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell141 - Dominate Person.py @@ -0,0 +1,63 @@ +from toee import * +from exclusions import * + +def OnBeginSpellCast( spell ): + print "Dominate Person OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Dominate Person OnSpellEffect" + + if spell.caster.name in [14286,14358]: # Balor + spell.dc = 27 # 10 + 9 (Dominate Monster) + 8 (Cha) + + spell.duration = 14400 * spell.caster_level + target_item = spell.target_list[0] + + if not target_item.obj.is_friendly( spell.caster ) and target_item.obj.name not in charm_exclusions: + + if (target_item.obj.is_category_type( mc_type_humanoid ) == 1): + + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id): + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + target_item.obj.condition_add_with_args( 'sp-Dominate Person', spell.id, spell.duration, target_item.obj.hit_dice_num ) + target_item.partsys_id = game.particles( 'sp-Dominate Person', target_item.obj ) + + # add target to initiative, just in case + target_item.obj.add_to_initiative() + game.update_combat_ui() + + else: + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + + # not an humanoid + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + else: + + # can't target friendlies + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Dominate Person OnBeginRound" + +def OnEndSpellCast( spell ): + print "Dominate Person OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell142 - Doom.py b/tpdatasrc/palcov/scr/Spell142 - Doom.py new file mode 100644 index 000000000..e376bf866 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell142 - Doom.py @@ -0,0 +1,74 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Doom OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-necromancy-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Doom OnSpellEffect" + + spell.duration = 10 * spell.caster_level + + target = spell.target_list[0] + + npc = spell.caster ## added so NPC's will choose valid targets + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + if (target.obj.type == obj_t_pc or target.obj.type == obj_t_npc) and critter_is_unconscious(target.obj) != 1 and not target.obj.d20_query(Q_Prone): + npc = spell.caster + + else: + game.global_flags[811] = 0 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 5 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 10 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 15 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 20 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 25 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 30 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 100 and critter_is_unconscious(obj) != 1 and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone) and (obj.type == obj_t_pc or obj.type == obj_t_npc): + target.obj = obj + game.global_flags[811] = 1 + + if (target.obj.type == obj_t_pc) or (target.obj.type == obj_t_npc): + # allow Will saving throw to negate + if target.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw successful + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target.obj ) + spell.target_list.remove_target( target.obj ) + + else: + # saving throw unsuccessful + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + # HTN - apply condition DOOM + target.obj.condition_add_with_args( 'sp-Doom', spell.id, spell.duration, 0 ) + target.partsys_id = game.particles( 'sp-Doom', target.obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Doom OnBeginRound" + +def OnEndSpellCast( spell ): + print "Doom OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell152 - Enlarge.py b/tpdatasrc/palcov/scr/Spell152 - Enlarge.py new file mode 100644 index 000000000..d16c516a1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell152 - Enlarge.py @@ -0,0 +1,125 @@ +from toee import * +from Co8 import * + +import _include +from co8Util import size +from co8Util.PersistentData import * +from co8Util.ObjHandling import * + +ENLARGE_KEY = "Sp152_Enlarge_Activelist" + +def OnBeginSpellCast( spell ): + print "Enlarge OnBeginSpellCast\n" + #print "\nspell.target_list=" , str(spell.target_list) , "\n" + #print "\nspell.caster=" + str( spell.caster) + " caster.level= ", spell.caster_level , "\n" + #print "\nspell.id=", spell.id , "\n" + game.particles( "sp-transmutation-conjure", spell.caster ) + + +def OnSpellEffect( spell ): + print "Enlarge OnSpellEffect\n" +## print "spell.id=", spell.id +## print "spell.target_list=", spell.target_list + spell.duration = 10 * spell.caster_level + target_item = spell.target_list[0] + + # HTN - 3.5, enlarge PERSON only + if ( target_item.obj.is_category_type( mc_type_humanoid ) == 1 ): + if target_item.obj.is_friendly( spell.caster ): + return_val = target_item.obj.condition_add_with_args( 'sp-Enlarge', spell.id, spell.duration, 0 ) +# print "condition_add_with_args return_val: " + str(return_val) + "\n" + if return_val == 1: + #size mod +# print "Size:" + str(target_item.obj.obj_get_int(obj_f_size)) +# print "Reach:" + str(target_item.obj.obj_get_int(obj_f_critter_reach)) + size.incSizeCategory(target_item.obj) +# print "performed size Increase\n" + #save target_list + activeList = Co8PersistentData.getData(ENLARGE_KEY) + if isNone(activeList): activeList = [] + activeList.append([spell.id, derefHandle(target_item.obj)]) + Co8PersistentData.setData(ENLARGE_KEY, activeList) + +# print "new Size:" + str(target_item.obj.obj_get_int(obj_f_size)) +# print "new Reach:" + str(target_item.obj.obj_get_int(obj_f_critter_reach)) + + + target_item.partsys_id = game.particles( 'sp-Enlarge', target_item.obj ) + else: + # sp-Enlarge not applied, probably dispelled sp-Reduce + spell.target_list.remove_target(target_item.obj) + else: + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw unsuccesful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + return_val = target_item.obj.condition_add_with_args( 'sp-Enlarge', spell.id, spell.duration, 0 ) + #enemies seem to work fine? + ## print "Size:" + str(target_item.obj.obj_get_int(obj_f_size)) + ## print "Reach:" + str(target_item.obj.obj_get_int(obj_f_critter_reach)) + ## size.incSizeCategory(target_item.obj) + ## print "new Size:" + str(target_item.obj.obj_get_int(obj_f_size)) + ## print "new Reach:" + str(target_item.obj.obj_get_int(obj_f_critter_reach)) + if return_val == 1: + target_item.partsys_id = game.particles( 'sp-Enlarge', target_item.obj ) + else: + # sp-Enlarge not applied, probably dispelled sp-Reduce + spell.target_list.remove_target(target_item.obj) + else: + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + else: # not a humanoid + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + print "spell.target_list=", spell.target_list + spell.spell_end( spell.id ) + + +def OnBeginRound( spell ): + print "Enlarge OnBeginRound" + return + + +def OnEndSpellCast( spell ): + #strangely enough the target_list gets zeroed before entering this, not after + print "Enlarge OnEndSpellCast" +## print "spell.target_list=", spell.target_list +## print "spell.id=", spell.id + + #size mod + + activeList = Co8PersistentData.getData(ENLARGE_KEY) + if isNone(activeList): + print "ERROR! Active Enlarge spell without activeList!" + return + + for entry in activeList: + spellID, target = entry + targetObj = refHandle(target) + if spellID == spell.id: +## print "Size:" + str(targetObj.obj_get_int(obj_f_size)) +## print "Reach:" + str(targetObj.obj_get_int(obj_f_critter_reach)) + weap_too_big(targetObj) + size.resetSizeCategory(targetObj) +## print "resetting reach on", targetObj +## print "new Size:" + str(targetObj.obj_get_int(obj_f_size)) +## print "new Reach:" + str(targetObj.obj_get_int(obj_f_critter_reach)) + activeList.remove(entry) + #no more active spells + if len(activeList) == 0: + Co8PersistentData.removeData(ENLARGE_KEY) + break + #save new activeList + Co8PersistentData.setData(ENLARGE_KEY, activeList) + break + + else: print "ERROR! Active Enlarge spell without entry in activeList!" + diff --git a/tpdatasrc/palcov/scr/Spell153 - Entangle.py b/tpdatasrc/palcov/scr/Spell153 - Entangle.py new file mode 100644 index 000000000..60d353653 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell153 - Entangle.py @@ -0,0 +1,91 @@ +from toee import * +import _include +from co8Util import size +from co8Util.PersistentData import * +from co8Util.ObjHandling import * + +ENTANGLE_KEY = "Sp153_Entangle_Activelist" + +def OnBeginSpellCast( spell ): + print "Entangle OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-transmutation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Entangle OnSpellEffect" + + spell.duration = 10 * spell.caster_level + outdoor_map_list = [5001, 5050, 5051, 5052, 5054, 5062, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5091, 5093, 5094, 5095, 5106, 5110, 5111, 5112, 5113] + + if (game.leader.map in outdoor_map_list) or (game.global_vars[451] & 2**0 == 0): + + # spawn one Entangle scenery object + entangle_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + entangle_obj.d20_status_init() + entangle_obj.set_initiative( caster_init_value ) + + # put sp-Entangle condition on obj + entangle_partsys_id = game.particles( 'sp-Entangle-Area', entangle_obj ) + entangle_obj.condition_add_with_args( 'sp-Entangle', spell.id, spell.duration, 0, entangle_partsys_id ) + #entangle_obj.condition_add_arg_x( 3, entangle_partsys_id ) + #objectevent_id = entangle_obj.condition_get_arg_x( 2 ) + + ######################### + # Added by Sitra Achara # + ######################### + + entangle_obj.obj_set_int( obj_f_secretdoor_dc, 153 + (1<<15) ) + # Mark it as an "obscuring mist" object. + # 1<<15 - marks it as "active" + # bits 16 and onward - random ID number + + activeList = Co8PersistentData.getData(ENTANGLE_KEY) + if isNone(activeList): activeList = [] + activeList.append([spell.id, derefHandle(entangle_obj)]) + Co8PersistentData.setData(ENTANGLE_KEY, activeList) + + ######################### + # End of Section # + ######################### + + else: + # No plants to entangle with + game.particles( 'Fizzle', spell.caster ) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 30000 ) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16014 ) + +def OnBeginRound( spell ): + print "Entangle OnBeginRound" + +def OnEndSpellCast( spell ): + print "Entangle OnEndSpellCast" + + activeList = Co8PersistentData.getData(ENTANGLE_KEY) + if isNone(activeList): + print "ERROR! Active Entangle spell without activeList!" + return + + for entry in activeList: + spellID, target = entry + targetObj = refHandle(target) + if spellID == spell.id: + aaa = targetObj.obj_get_int( obj_f_secretdoor_dc ) + aaa &= ~(1<<15) + targetObj.obj_set_int( obj_f_secretdoor_dc, aaa ) + activeList.remove(entry) + # no more active spells + if len(activeList) == 0: + Co8PersistentData.removeData(ENTANGLE_KEY) + break + Co8PersistentData.setData(ENTANGLE_KEY, activeList) + break + +def OnAreaOfEffectHit( spell ): + print "Entangle OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Entangle OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell170 - Finger of Death.py b/tpdatasrc/palcov/scr/Spell170 - Finger of Death.py new file mode 100644 index 000000000..7f471c580 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell170 - Finger of Death.py @@ -0,0 +1,58 @@ +from toee import * +from utilities import * +from casters import staff_has, staff_stats + +def OnBeginSpellCast( spell ): + print "Finger of Death OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-necromancy-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Finger of Death OnSpellEffect" + + if staff_has(spell.caster) == 1: + CL, mod = staff_stats (spell.caster, '01011') + spell.caster_level = CL + spell.dc = 10 + 7 + mod + + elif spell.caster.name == 14985: # nightwalker + spell.dc = 21 # 10 + 7 + 4 (charisma) + spell.caster_level = 21 + + elif spell.caster.name == 14988: # nightcrawler + spell.dc = 21 # 10 + 7 + 4 (charisma) + spell.caster_level = 25 + + damage_dice = dice_new( "3d6" ) + damage_dice.bonus = min( 25, spell.caster.stat_level_get( spell.caster_class ) ) + + target = spell.target_list[0] + + game.particles( 'sp-Slay Living', target.obj ) + + # damage target + if target.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target + target.obj.spell_damage( spell.caster, D20DT_NEGATIVE_ENERGY, damage_dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, kill target + + # set attribute for proper XP award + if target.obj.type == obj_t_npc: + target.obj.obj_set_obj(obj_f_last_hit_by, spell.caster) + + target.obj.critter_kill_by_effect() + + spell.target_list.remove_target( target.obj ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Finger of Death OnBeginRound" + +def OnEndSpellCast( spell ): + print "Finger of Death OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell183 - Fog Cloud.py b/tpdatasrc/palcov/scr/Spell183 - Fog Cloud.py new file mode 100644 index 000000000..af01a9695 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell183 - Fog Cloud.py @@ -0,0 +1,42 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Fog Cloud OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Fog Cloud OnSpellEffect" + + spell.duration = 100 * spell.caster_level + + npc = spell.caster ## added so NPC's can pre-buff + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL and not game.combat_is_active(): + spell.duration = 2000 * spell.caster_level + + # spawn one spell_object object + spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + spell_obj.d20_status_init() + spell_obj.set_initiative( caster_init_value ) + + # put sp-Fog Cloud condition on obj + spell_obj_partsys_id = game.particles( 'sp-Fog Cloud', spell_obj ) + spell_obj.condition_add_with_args( 'sp-Fog Cloud', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #spell_obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = spell_obj.condition_get_arg_x( 2 ) + +def OnBeginRound( spell ): + print "Fog Cloud OnBeginRound" + +def OnEndSpellCast( spell ): + print "Fog Cloud OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Fog Cloud OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Fog Cloud OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell192 - Gentle Repose.py b/tpdatasrc/palcov/scr/Spell192 - Gentle Repose.py new file mode 100644 index 000000000..9af0e39a3 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell192 - Gentle Repose.py @@ -0,0 +1,49 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Gentle Repose OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-necromancy-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Gentle Repose OnSpellEffect" + + target = spell.target_list[0] + + if not target.obj.is_friendly( spell.caster ): + + if not target.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id): + # saving throw unsuccessful + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + game.particles( 'sp-Inflict Light Wounds', target.obj ) + target.obj.float_mesfile_line( 'mes\\spell.mes', 192 ) + x = target.obj.obj_get_int(obj_f_critter_flags2) + x = x | 64 + target.obj.obj_set_int(obj_f_critter_flags2, x) + # why is this here? hommlet farm animals killed counter, marc. + # game.global_vars[900] = target.obj.obj_get_int(obj_f_critter_flags2) + + else: + + # saving throw successful + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target.obj ) + + else: + game.particles( 'sp-Inflict Light Wounds', target.obj ) + target.obj.float_mesfile_line( 'mes\\spell.mes', 192 ) + + x = target.obj.obj_get_int(obj_f_critter_flags2) + x = x | 64 + target.obj.obj_set_int(obj_f_critter_flags2, x) + + spell.target_list.remove_target( target.obj ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Gentle Repose OnBeginRound" + +def OnEndSpellCast( spell ): + print "Gentle Repose OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell201 - Greater Command.py b/tpdatasrc/palcov/scr/Spell201 - Greater Command.py new file mode 100644 index 000000000..dcb85bd6d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell201 - Greater Command.py @@ -0,0 +1,86 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Greater Command OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Greater Command OnSpellEffect" + + remove_list = [] + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg != 1 and spell_arg != 2 and spell_arg != 3 and spell_arg != 4: + spell_arg = 2 + npc = spell.caster + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + spell_arg = 2 + + for target_item in spell.target_list: + if not target_item.obj.is_friendly( spell.caster ): + if (target_item.obj.type == obj_t_pc) or (target_item.obj.type == obj_t_npc): + if not target_item.obj.is_category_type( mc_type_animal ): + if target_item.obj.get_size < STAT_SIZE_LARGE: + + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + target_item.obj.condition_add_with_args( 'sp-Command', spell.id, spell.duration, spell_arg ) + target_item.partsys_id = game.particles( 'sp-Command', target_item.obj ) + + # add target to initiative, just in case + #target_item.obj.add_to_initiative() + #game.update_combat_ui() + + else: + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + else: + # not medium sized or smaller + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31005 ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + else: + # a monster + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + else: + # not a person + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31001 ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + else: + + # can't target friendlies + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Greater Command OnBeginRound" + +def OnEndSpellCast( spell ): + print "Greater Command OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell202 - Greater Dispelling.py b/tpdatasrc/palcov/scr/Spell202 - Greater Dispelling.py new file mode 100644 index 000000000..6fe66cad9 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell202 - Greater Dispelling.py @@ -0,0 +1,67 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Dispel Magic OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + + spell.caster_level = min( 20, spell.caster_level ) + + # check if we are targetting an object or an area + if spell.is_object_selected() == 1: + target = spell.target_list[0] + + # support dispel on critters + if (target.obj.type == obj_t_pc) or (target.obj.type == obj_t_npc): + target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + target.obj.condition_add_with_args( 'sp-Dispel Magic', spell.id, 0, 0 ) + + # support dispel on portals and containers + elif (target.obj.type == obj_t_portal) or (target.obj.type == obj_t_container): + if target.obj.portal_flags_get() & OPF_MAGICALLY_HELD: + target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + target.obj.portal_flag_unset( OPF_MAGICALLY_HELD ) + spell.target_list.remove_target( target.obj ) + + # support dispel on these obj_types: weapon, ammo, armor, scroll + # NO support for: money, food, key, written, generic, scenery, trap, bag + #elif (target.obj.type == obj_t_weapon) or (target.obj.type == obj_t_ammo) or (target.obj.type == obj_t_armor) or (target.obj.type == obj_t_scroll): + #print "[dispel magic] - items not supported yet!" + #game.particles( 'Fizzle', target.obj ) + #spell.target_list.remove_target( target.obj ) + + else: + # draw area effect particles + game.particles( 'sp-Dispel Magic - Area', spell.target_loc ) + + for target in spell.target_list: + + if (target.obj.type == obj_t_pc) or (target.obj.type == obj_t_npc): + target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + target.obj.condition_add_with_args( 'sp-Dispel Magic', spell.id, 0, 1 ) + + # support dispel on portals and containers + elif (target.obj.type == obj_t_portal) or (target.obj.type == obj_t_container): + if target.obj.portal_flags_get() & OPF_MAGICALLY_HELD: + target.partsys_id = game.particles( 'sp-Dispel Magic - Targeted', target.obj ) + target.obj.portal_flag_unset( OPF_MAGICALLY_HELD ) + spell.target_list.remove_target( target.obj ) + + # support dispel on these obj_types: weapon, ammo, armor, scroll + # NO support for: money, food, key, written, generic, scenery, trap, bag + #elif (target.obj.type == obj_t_weapon) or (target.obj.type == obj_t_ammo) or (target.obj.type == obj_t_armor) or (target.obj.type == obj_t_scroll): + #print "[dispel magic] - items not supported yet!" + #game.particles( 'Fizzle', target.obj ) + #spell.target_list.remove_target( target.obj ) + + spell.spell_end( spell.id , 1) + +def OnBeginRound( spell ): + spell.spell_end(spell.id, 1) + print "Dispel Magic OnBeginRound" + +def OnEndSpellCast( spell ): + print "Dispel Magic OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell225 - Heroes' Feast.py b/tpdatasrc/palcov/scr/Spell225 - Heroes' Feast.py new file mode 100644 index 000000000..cce892ff7 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell225 - Heroes' Feast.py @@ -0,0 +1,44 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Heroes' Feast OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Heroes' Feast OnSpellEffect" + + spell.duration = 7200 + + for target_item in spell.target_list: + return_val1 = target_item.obj.condition_add_with_args( 'sp-Aid', spell.id, spell.duration, 1 ) + if return_val1 == 1: + target_item.partsys_id = game.particles( 'sp-Aid', target_item.obj ) + + for target_item in spell.target_list: + return_val2 = target_item.obj.condition_add_with_args( 'sp-Neutralize Poison', spell.id, spell.duration, 1 ) + if return_val2 == 1: + game.particles( 'sp-Neutralize Poison', target_item.obj ) + + for target_item in spell.target_list: + #return_val3 = target_item.obj.condition_add_with_args( 'sp-Remove Disease', spell.id, 0, 1 ) + #if return_val3 == 1: + # game.particles( 'sp-Remove Disease', target_item.obj ) + # Removed this since it removes the target object, as the Remove Disease spell is instantaneous + # Instead, using S_Remove_Disease + # Not perfect since it doesn't cure Vrock Spores... + target_item.obj.d20_send_signal(S_Remove_Disease) + + for target_item in spell.target_list: + return_val4 = target_item.obj.condition_add_with_args( 'sp-Remove Fear', spell.id, spell.duration, 0 ) + if return_val4 == 1: + target_item.partsys_id = game.particles( 'sp-Remove Fear', target_item.obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Heroes' Feast OnBeginRound" + +def OnEndSpellCast( spell ): + print "Heroes' Feast OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell228 - Hold Person.py b/tpdatasrc/palcov/scr/Spell228 - Hold Person.py new file mode 100644 index 000000000..26c266a68 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell228 - Hold Person.py @@ -0,0 +1,91 @@ +from utilities import * +from toee import * + +def OnBeginSpellCast( spell ): + print "Hold Person OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Hold Person OnSpellEffect" + + if spell.caster.name in [14927]: # Avoral + spell.dc = 16 # 10 + 3 + 3 (charisma) + + spell.duration = 1 * spell.caster_level + + target = spell.target_list[0] + + npc = spell.caster ## added so NPC's will choose valid targets + + + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + if target.obj.is_category_type( mc_type_humanoid ) and critter_is_unconscious(target.obj) != 1 and not target.obj.d20_query(Q_Prone): + npc = spell.caster + else: + game.global_flags[811] = 0 + + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 5 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 10 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 15 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 20 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 25 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 30 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 100 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target.obj = obj + game.global_flags[811] = 1 + + if target.obj.is_category_type( mc_type_humanoid ): + + # allow Will saving throw to negate + if target.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target.obj ) + spell.target_list.remove_target( target.obj ) + else: + # saving throw unsuccessful + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # HTN - apply condition HOLD (paralyzed) + target.obj.condition_add_with_args( 'sp-Hold Person', spell.id, spell.duration, 0 ) + target.partsys_id = game.particles( 'sp-Hold Person', target.obj ) + + else: + # not a person + target.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target.obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target.obj ) + spell.target_list.remove_target( target.obj ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Hold Person OnBeginRound" + +def OnEndSpellCast( spell ): + print "Hold Person OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell233 - Holy Word.py b/tpdatasrc/palcov/scr/Spell233 - Holy Word.py new file mode 100644 index 000000000..7e3575e7e --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell233 - Holy Word.py @@ -0,0 +1,93 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Holy Word OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Holy Word OnSpellEffect" + + remove_list = [] + + # The Will save versus banishment is at a -4 penalty + spell.dc = spell.dc + 4 + + + obj_list = [] + # extracting the obj's so we don't get changed iterator bullshit (see http://www.co8.org/community/index.php?threads/holy-word-killed-my-cg-pc.12164/#post-145537) + for target_item in spell.target_list: + # Only works on non-good creatures + target_item_obj = target_item.obj + alignment = target_item_obj.critter_get_alignment() + + if not (alignment & ALIGNMENT_GOOD): + obj_list.append(target_item_obj ) + remove_list.append( target_item_obj ) + + #for target_item in spell.target_list: + #target_item_obj = target_item.obj + for target_item_obj in obj_list: + + print "target item: " + str(target_item_obj) + obj_hit_dice = target_item_obj.hit_dice_num + + game.particles( 'sp-Holy Smite', target_item_obj ) + + # Anything ten or more levels below the caster's level dies + if obj_hit_dice <= (spell.caster_level - 10): + if not target_item_obj in game.leader.group_list(): + #print "Inflicting damage due to low critter HD: " + str(target_item_obj) + target_item_obj.damage( game.leader , D20DT_POSITIVE_ENERGY, dice_new("52d52")) + # So you'll get awarded XP for the kill + #print "Killing due to low critter HD: " + str(target_item_obj) + target_item_obj.critter_kill() + + # Anything five or more levels below the caster's level is paralyzed + if obj_hit_dice <= (spell.caster_level - 5): + spell.duration = game.random_range(1,10) * 10 + target_item_obj.condition_add_with_args( 'sp-Hold Monster', spell.id, spell.duration, 0 ) + + # Anything one or more levels below the caster's level is blinded + if obj_hit_dice <= (spell.caster_level - 1): + spell.duration = game.random_range(1,4) + game.random_range(1,4) + target_item_obj.condition_add_with_args( 'sp-Blindness', spell.id, spell.duration, 0 ) + + # Anything the caster's level or below is deafened + if obj_hit_dice <= (spell.caster_level): + spell.duration = game.random_range(1,4) + target_item_obj.condition_add_with_args( 'sp-Deafness', spell.id, spell.duration, 0 ) + + # Summoned and extraplanar creatures below the caster's level are also banished + # if they fail a Will save at -4 + if target_item_obj.d20_query_has_spell_condition( sp_Summoned ) or target_item_obj.npc_flags_get() & ONF_EXTRAPLANAR != 0: + + # allow Will saving throw to negate + if target_item_obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target_item_obj ) + + else: + # saving throw unsuccessful + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # creature is sent back to its own plane + # kill for now + if not target_item_obj in game.leader.group_list(): + #print "Inflicting damage due to Summoned/Extraplanar: " + str(target_item_obj) + target_item_obj.damage( game.leader , D20DT_POSITIVE_ENERGY, dice_new("52d52")) + # So you'll get awarded XP for the kill + + #print "critter_kill due to Summoned or Extraplanar: " + str(target_item_obj) + target_item_obj.critter_kill() + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Holy Word OnBeginRound" + +def OnEndSpellCast( spell ): + print "Holy Word OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell237 - Ice Storm.py b/tpdatasrc/palcov/scr/Spell237 - Ice Storm.py new file mode 100644 index 000000000..1311cd9a1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell237 - Ice Storm.py @@ -0,0 +1,42 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Ice Storm OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Ice Storm OnSpellEffect" + + if spell.caster.name == 14977: # Ice Devil + spell.dc = 19 # 10 + 4 + 5 + spell.caster_level = 13 + + spell.duration = 0 + + # spawn one spell_object object + spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + spell_obj.d20_status_init() + spell_obj.set_initiative( caster_init_value ) + + # put sp-Ice Storm condition on obj + spell_obj_partsys_id = game.particles( 'sp-Ice Storm', spell_obj ) + spell_obj.condition_add_with_args( 'sp-Ice Storm', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #spell_obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = spell_obj.condition_get_arg_x( 2 ) + +def OnBeginRound( spell ): + print "Ice Storm OnBeginRound" + +def OnEndSpellCast( spell ): + print "Ice Storm OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Ice Storm OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Ice Storm OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell247 - Inflict Light Wounds.py b/tpdatasrc/palcov/scr/Spell247 - Inflict Light Wounds.py new file mode 100644 index 000000000..c02e88ca5 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell247 - Inflict Light Wounds.py @@ -0,0 +1,84 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Inflict Light Wounds OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-necromancy-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Inflict Light Wounds OnSpellEffect" + + dice = dice_new( "1d8" ) + dice.bonus = min( 5, spell.caster.stat_level_get( spell.caster_class ) ) + + target = spell.target_list[0] + + npc = spell.caster ## added so NPC's will choose valid targets + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + if critter_is_unconscious(target.obj) != 1 and not target.obj.d20_query(Q_Prone): + npc = spell.caster + else: + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 10 and critter_is_unconscious(obj) != 1 and not obj.d20_query(Q_Prone): + target.obj = obj + + # check if target is friendly (willing target) + if target.obj.is_friendly( spell.caster ): + + # check if target is undead + if target.obj.is_category_type( mc_type_undead ): + target.obj.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + # damage target + if target.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.obj.spell_damage_with_reduction( spell.caster, D20DT_NEGATIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.obj.spell_damage( spell.caster, D20DT_NEGATIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + + else: + attack_result = spell.caster.perform_touch_attack(target.obj, 1) + if attack_result & D20CAF_HIT: + # check if target is undead + if target.obj.is_category_type( mc_type_undead ): + # check saving throw, heal target + if target.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.obj.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + #target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.obj.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw, damage target + if target.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.obj.spell_damage_weaponlike( spell.caster, D20DT_NEGATIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id, attack_result, 0 ) + else: + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.obj.spell_damage_weaponlike( spell.caster, D20DT_NEGATIVE_ENERGY, dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, attack_result, 0 ) + + game.particles( 'sp-Inflict Light Wounds', target.obj ) + + spell.target_list.remove_target( target.obj ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Inflict Light Wounds OnBeginRound" + +def OnEndSpellCast( spell ): + print "Inflict Light Wounds OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell255 - Invisibility Sphere.py b/tpdatasrc/palcov/scr/Spell255 - Invisibility Sphere.py new file mode 100644 index 000000000..5920fc766 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell255 - Invisibility Sphere.py @@ -0,0 +1,38 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Invisibility Sphere OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-illusion-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Invisibility Sphere OnSpellEffect" + + spell.duration = 100 * spell.caster_level + + # spawn one spell_object object + spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + spell_obj.d20_status_init() + spell_obj.set_initiative( caster_init_value ) + + # put sp-Invisibility Sphere condition on obj + spell_obj_partsys_id = game.particles( 'sp-Invisibility Sphere', spell_obj ) + spell_obj.condition_add_with_args( 'sp-Invisibility Sphere', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #spell_obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = spell_obj.condition_get_arg_x( 2 ) + +def OnBeginRound( spell ): + print "Invisibility Sphere OnBeginRound" + +def OnEndSpellCast( spell ): + print "Invisibility Sphere OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Invisibility Sphere OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Invisibility Sphere OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell288 - Magic Missile.py b/tpdatasrc/palcov/scr/Spell288 - Magic Missile.py new file mode 100644 index 000000000..4f953459d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell288 - Magic Missile.py @@ -0,0 +1,113 @@ +from toee import * +import tpdp + +def OnBeginSpellCast( spell ): + print "Magic Missile OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + + #spell.num_of_projectiles = spell.num_of_projectiles + 1 + #spell.target_list.push_target(spell.caster) # didn't work :( + # generally the sequence is: OnBeginSpellCast, OnBeginProjectile, OnSpellEffect,OnEndProjectile (OnBeginRound isn't called) + +def OnSpellEffect( spell ): + print "Magic Missile OnSpellEffect" + + # only enable mirror image behavior in strict rules + if not tpdp.config_get_bool('stricterRulesEnforcement'): return + + # Calculate which missiles hit mirror images instead of the actual target. + # + # This needs to be calculated ahead of time if we want to simulate picking + # targets _before_ we know which is the real one, for situations where there + # are more missiles than (real and fake) targets. + offsets = [] + seen = [] + hits = [0,0,0,0,0] + hi = -1 + for target_item in spell.target_list: + target = target_item.obj + hi += 1 + + # handles can't be hashed, so we need to do something like this + if target in seen: + ix = seen.index(target) + # if the same spell target occurs more than once, assume we're targeting + # as many distinct copies if possible + off, copies = offsets[ix] + offsets[ix] = (off+1, copies) + + if off % copies > 0: hits[hi] = 1 + else: + mirrors = target.d20_query(Q_Critter_Has_Mirror_Image) + # no mirrors, always hit + if mirrors <= 0: continue + + copies = mirrors+1 + off = dice_new(1, copies, -1).roll() + + # save the _next_ offset + offsets.append((off+1, copies)) + seen.append(target) + + if off > 0: hits[hi] = 1 + + h1, h2, h3, h4, h5 = hits + spell.caster.condition_add_with_args('Magic Missile Mirror', spell.id, h1, h2, h3, h4, h5) + +def OnBeginRound( spell ): + print "Magic Missile OnBeginRound" + + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Magic Missile OnBeginProjectile" + + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-magic missle-proj', projectile ) ) + + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Magic Missile OnEndProjectile" + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + + target_item = spell.target_list[ index_of_target ] + target = target_item.obj + + hit_mirror = spell.caster.d20_query_with_data('Missile Mirror Hit', spell.id, index_of_target + 1) + + if hit_mirror > 0: + if target.d20_query(Q_Critter_Has_Mirror_Image) > 0: + mirror_id = target.d20_query_get_data(Q_Critter_Has_Mirror_Image, 0) + target.d20_send_signal(S_Spell_Mirror_Image_Struck, mirror_id, 0) + target.float_mesfile_line('mes\\combat.mes', 109) + game.create_history_from_pattern(10, spell.caster, target) + else: # normal damage + damage_dice = dice_new(1,4,1) + is_enemy = not spell.caster in game.party[0].group_list() + target_charmed = target.d20_query(Q_Critter_Is_Charmed) + if is_enemy and target_charmed: + # NPC enemy is trying to cast on a charmed target - this is mostly meant for the Cult of the Siren encounter + target = party_closest( spell.caster, conscious_only= 1, mode_select= 1, exclude_warded= 1, exclude_charmed = 1) # select nearest conscious PC instead, who isn't already charmed + if target == OBJ_HANDLE_NULL: + target = target_item.obj + + # always hits + target.condition_add_with_args('sp-Magic Missile', spell.id, spell.duration, damage_dice.roll()) + target_item.partsys_id = game.particles('sp-magic missle-hit', target) + + # special scripting for NPCs no longer necessary - NPCs will launch multiple projectiles now + + #spell.target_list.remove_target_by_index( index_of_target ) + spell.num_of_projectiles -= 1 + + if spell.num_of_projectiles == 0: +## loc = target.location +## target.destroy() +## mxcr = game.obj_create( 12021, loc ) +## game.global_vars[30] = game.global_vars[30] + 1 + spell.caster.d20_send_signal(S_Spell_End, spell.id) + spell.spell_end( spell.id, 1 ) + +def OnEndSpellCast( spell ): + print "Magic Missile OnEndSpellCast" diff --git a/tpdatasrc/palcov/scr/Spell307 - Meteor Swarm.py b/tpdatasrc/palcov/scr/Spell307 - Meteor Swarm.py new file mode 100644 index 000000000..04fa4ee38 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell307 - Meteor Swarm.py @@ -0,0 +1,87 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Meteor Swarm OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Meteor Swarm OnSpellEffect" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Meteor Swarm OnBeginProjectile" + + projectiles = 4 + if index_of_target < projectiles: + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Spheres of Fire-proj', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Meteor Swarm OnEndProjectile" + + dam = dice_new( '2d6' ) + dam2 = dice_new( '6d6' ) + + projectiles = 4 + if index_of_target < projectiles: + spell.duration = 0 + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + + target_item = spell.target_list[ index_of_target ] + + return_val = spell.caster.perform_touch_attack( target_item.obj ) + xx,yy = location_to_axis(target_item.obj.location) + if target_item.obj.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + target_item.obj.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1) + game.particles( 'swirled gas', target_item.obj ) + game.sound(7581,1) + game.sound(7581,1) + else: + if (return_val & D20CAF_HIT): + # hit target + if index_of_target > 0: + return_val |= D20CAF_NO_PRECISION_DAMAGE + game.particles( 'sp-Spheres of Fire-hit', target_item.obj ) + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_BLUDGEONING, dam, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, return_val, index_of_target ) + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_FIRE, dam2, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, return_val, index_of_target ) + + else: + # miss target + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + game.particles( 'Fizzle', target_item.obj ) + + if target_item.obj.reflex_save_and_damage( spell.caster, spell.dc, D20_Save_Reduction_Half, D20STD_F_NONE, dam2, D20DT_FIRE, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ): + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + else: + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + game.particles( 'sp-Fireball-Hit', target_item.obj ) + + for critter in game.obj_list_cone( target_item.obj, OLC_CRITTERS, 40, -180, 360 ): + if (critter != target_item.obj) and (critter.d20_query(Q_Dead) == 0): + xx,yy = location_to_axis(critter.location) + if critter.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + critter.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1) + game.particles( 'swirled gas', critter ) + game.sound(7581,1) + game.sound(7581,1) + else: + game.particles( 'hit-FIRE-burst', critter ) + if critter.reflex_save_and_damage( spell.caster, spell.dc, D20_Save_Reduction_Half, D20STD_F_NONE, dam2, D20DT_FIRE, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ): + # saving throw successful + critter.float_mesfile_line( 'mes\\spell.mes', 30001 ) + else: + # saving throw unsuccessful + critter.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + spell.num_of_projectiles = spell.num_of_projectiles - 1 + + if ( spell.num_of_projectiles <= 0 ): + spell.spell_end( spell.id, 1 ) + +def OnEndSpellCast( spell ): + print "Meteor Swarm OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell311 - Minor Globe of Invulnerability.py b/tpdatasrc/palcov/scr/Spell311 - Minor Globe of Invulnerability.py new file mode 100644 index 000000000..65f47a877 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell311 - Minor Globe of Invulnerability.py @@ -0,0 +1,45 @@ +from toee import * +import _include +from co8Util.PersistentData import * +from co8Util.ObjHandling import * + +MINOR_GLOBE_OF_INVULNERABILITY_KEY = "Sp311_MINOR_GLOBE_OF_INVULNERABILITY_Activelist" + + +def OnBeginSpellCast( spell ): + print "Minor Globe of Invulnerability OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Minor Globe of Invulnerability OnSpellEffect" + + spell.duration = 1 * spell.caster_level + target_item = spell.target_list[0] + + npc = spell.caster ## added so NPC's can use wand/potion/scroll + + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL and spell.duration <= 0: + spell.duration = 10 + spell.caster_level = 10 + + # put sp-Minor Globe condition on target + spell_obj_partsys_id = game.particles( 'sp-Minor Globe of Invulnerability', target_item.obj ) +# target_item.partsys_id = game.particles( 'sp-Minor Globe of Invulnerability', target_item.obj ) + target_item.obj.condition_add_with_args( 'sp-Minor Globe of Invulnerability', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #target_item.obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = target_item.obj.condition_get_arg_x( 2 ) + + +def OnBeginRound( spell ): + print "Minor Globe of Invulnerability OnBeginRound" + +def OnEndSpellCast( spell ): + print "Minor Globe of Invulnerability OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Minor Globe of Invulnerability OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Minor Globe of Invulnerability OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell317 - Mislead.py b/tpdatasrc/palcov/scr/Spell317 - Mislead.py new file mode 100644 index 000000000..0345e709a --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell317 - Mislead.py @@ -0,0 +1,58 @@ +from toee import * +from casters import staff_has, staff_stats + +mislead_spell_list = {} + + +def OnBeginSpellCast( spell ): + print "Mislead OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-illusion-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Mislead OnSpellEffect" + + if staff_has(spell.caster) == 1: + CL, mod = staff_stats (spell.caster, '10011') + spell.caster_level = CL + + spell.duration = 1 * spell.caster_level + target_item = spell.target_list[0] + + num_of_images = spell.caster_level + + #print "num of images=", num_of_images + + game.particles( 'sp-Mirror Image', target_item.obj ) + target_item.obj.condition_add_with_args( 'sp-Mirror Image', spell.id, spell.duration, num_of_images ) + #target_item.partsys_id = game.particles( 'sp-Mirror Image', target_item.obj ) + +# spell.id = spell.id + 1 + + target_item.obj.condition_add_with_args( 'sp-Improved Invisibility', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Improved Invisibility', target_item.obj ) + + # spell.spell_end( spell.id, 1 )# do not end the spell, else the effect countdown is interrupted + +def OnBeginRound( spell ): + # Crappy workaround to end the spell (otherwise it never ends...) + # Note: OnBeginRound gets called num_of_images times each round, because sp-Mirror Image duplicates the target num_of_images times (to store the particle FX) + # Thus we check the game time to prevent decrementing the duration multiple times + cur_time = game.time.time_game_in_seconds(game.time) + if spell.id in mislead_spell_list: + entry = mislead_spell_list[spell.id] + entry_time = entry[1] + if cur_time > entry_time: + entry[1] = cur_time + entry[0] -= 1 + #mislead_spell_list[spell.id] = entry + print "Mislead OnBeginRound, duration: " + str(entry[0]) + ", ID: " + str(spell.id) + if entry[0] <= 0: + spell.spell_end(spell.id, 1) + else: + print "Mislead OnBeginRound, duration: " + str(spell.duration) + ", ID: " + str(spell.id) + mislead_spell_list[spell.id] = [spell.duration - 1, cur_time ] + +def OnEndSpellCast( spell ): + print "Mislead OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell318 - Modify Memory.py b/tpdatasrc/palcov/scr/Spell318 - Modify Memory.py new file mode 100644 index 000000000..f41b82c1e --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell318 - Modify Memory.py @@ -0,0 +1,134 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Modify Memory OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Modify Memory OnSpellEffect" + + spell.duration = 1 + + ################################ + # + # First find the nearest NPC to the target location + # + ################################ + + new_targ = 0 + dist = 4 + + for obj in game.obj_list_vicinity(spell.target_loc, OLC_NPC): + NEWdistance = 0 + if (obj.leader_get() == OBJ_HANDLE_NULL): + x1, y1 = location_to_axis(obj.location) + x2, y2 = location_to_axis(spell.target_loc) + if x1 > x2: + x3 = x1 - x2 + else: + x3 = x2 - x1 + + if y1 > y2: + y3 = y1 - y2 + else: + y3 = y2 - y1 + NEWdistance = ((x3*x3) + (y3*y3))**0.5 + bet = NEWdistance + + else: + NEWdistance = 6 + if NEWdistance <= dist: + dist = NEWdistance + new_targ = obj + + if new_targ == OBJ_HANDLE_NULL or new_targ == 0: + bob = spell.caster + game.particles( 'Fizzle', bob ) + bob.float_mesfile_line( 'mes\\narrative.mes', 161 ) + else: + game.particles( 'sp-Feat of Strength-END', new_targ) + + + if new_targ.stat_level_get(stat_intelligence) >= 1: + if not (new_targ.is_category_type( mc_type_undead ) or new_targ.is_category_type( mc_type_ooze ) or new_targ.is_category_type( mc_type_aberration ) or new_targ.is_category_type( mc_type_outsider ) or new_targ.is_category_type( mc_type_construct )): + + if new_targ.is_friendly( spell.caster ): + if not new_targ.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + new_targ.reaction_adj( game.party[0], 40 ) + new_targ.npc_flag_unset(ONF_KOS) + new_targ.npc_flag_set(ONF_KOS_OVERRIDE) + + x = new_targ.scripts[19] + new_targ.scripts[19] = 0 + game.timeevent_add( reset_sid, ( new_targ, x ), 300000 ) + game.particles( 'sp-Feat of Strength-END', new_targ ) + + cozen = game.obj_create( 12696, new_targ.location) + new_targ.item_get(cozen) + cozen.object_script_execute( cozen, 28 ) + # game.particles( "sp-summon monster I", game.party[0] ) + + else: + + # saving throw successful + new_targ.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + vigilance = game.obj_create( 12695, new_targ.location) + new_targ.item_get(vigilance) + vigilance.object_script_execute( vigilance, 28 ) + # game.particles( "sp-summon monster I", game.party[0] ) + + else: + if not new_targ.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + new_targ.reaction_adj( game.party[0], 40 ) + new_targ.npc_flag_unset(ONF_KOS) + new_targ.npc_flag_set(ONF_KOS_OVERRIDE) + x = new_targ.scripts[19] + new_targ.scripts[19] = 0 + game.timeevent_add( reset_sid, ( new_targ, x ), 300000 ) + game.particles( 'sp-Feat of Strength-END', new_targ ) + + cozen = game.obj_create( 12696, new_targ.location) + new_targ.item_get(cozen) + cozen.object_script_execute( cozen, 28 ) + # game.particles( "sp-summon monster I", game.party[0] ) + + else: + + # saving throw successful + new_targ.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + vigilance = game.obj_create( 12695, new_targ.location) + new_targ.item_get(vigilance) + vigilance.object_script_execute( vigilance, 28 ) + # game.particles( "sp-summon monster I", game.party[0] ) + + else: + # something weird: undead, construct etc + new_targ.float_mesfile_line( 'mes\\spell.mes', 30003 ) + game.particles( 'Fizzle', new_targ ) + + else: + + # critters with no intelligence have no memories! + new_targ.float_mesfile_line( 'mes\\spell.mes', 20055 ) + game.particles( 'Fizzle', new_targ ) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Modify Memory OnBeginRound" + +def OnEndSpellCast( spell ): + print "Modify Memory OnEndSpellCast" + +def reset_sid(targ, id_x): + targ.scripts[19] = id_x + game.sound(7461,1) + game.particles( 'Fizzle', targ ) + return \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell364 - Produce Flame.py b/tpdatasrc/palcov/scr/Spell364 - Produce Flame.py new file mode 100644 index 000000000..df853cac6 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell364 - Produce Flame.py @@ -0,0 +1,62 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Produce Flame OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + +def OnSpellEffect( spell ): + print "Produce Flame OnSpellEffect" + + xx,yy = location_to_axis(spell.caster.location) + if game.leader.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + # Water Temple Pool Enchantment prevents fire spells from working inside the chamber, according to the module -SA + game.particles( 'swirled gas', spell.caster ) + spell.caster.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1 ) + game.sound(7581,1) + game.sound(7581,1) + else: + spell.duration = 10* spell.caster_level + if spell.caster_level > 5: + spell.caster_level = 5 + + target = spell.target_list[0] + + target.obj.condition_add_with_args( 'sp-Produce Flame', spell.id, spell.duration, 0 ) + target.partsys_id = game.particles( 'sp-Produce Flame', target.obj ) + +def OnBeginRound( spell ): + print "Produce Flame OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Produce Flame OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Produce Flame-proj', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Produce Flame-proj', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Produce Flame OnEndProjectile" + + targg364 = spell.target_list[index_of_target].obj + xx,yy = location_to_axis(targg364.location) + if targg364.map == 5067 and ( xx >= 521 and xx <= 555 ) and ( yy >= 560 and yy <= 610): + # Water Temple Pool Enchantment prevents fire spells from working inside the chamber, according to the module -SA + targg364.float_mesfile_line( 'mes\\skill_ui.mes', 2000 , 1 ) + game.sound(7581,1) + game.sound(7581,1) + game.particles( 'swirled gas', targg364 ) + else: + #return_val = spell.caster.perform_touch_attack( targg364 ) + #if return_val >= 1: + #damage_dice = dice_new( '4d6' ) + #game.particles( 'sp-Produce Flame-Hit', targg364 ) + #target.obj.spell_damage( spell.caster, D20DT_FIRE, damage_dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + spell.caster.d20_send_signal_ex( S_TouchAttack, spell.target_list[ index_of_target ].obj ) + ##else: + # missed + targg364.float_mesfile_line( 'mes\\spell.mes', 30007 ) + game.particles( 'Fizzle', targg364 ) + +def OnEndSpellCast( spell ): + print "Produce Flame OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell379 - Raise Dead.py b/tpdatasrc/palcov/scr/Spell379 - Raise Dead.py new file mode 100644 index 000000000..8558e74e6 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell379 - Raise Dead.py @@ -0,0 +1,92 @@ +from toee import * +from scripts import End_Spell +from exclusions import * +from Co8 import * + +def OnBeginSpellCast( spell ): + print "Raise Dead OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Raise Dead OnSpellEffect" + + spell.duration = 0 + target_item = spell.target_list[0] + + raise_dead_exclusions = get_raise_dead_exclusions() + if target_item.obj.name not in raise_dead_exclusions: + #For aasumars and tieflings temporarily remove the outsider tag so raise dead will work + prevType = 0 + if target_item.obj.is_category_type( mc_type_outsider ) and target_item.obj.is_category_subtype(mc_subtype_human): + subrace = target_item.obj.stat_base_get(stat_subrace) + if (subrace == human_subrace_aasumar or subrace == human_subrace_tiefling): + prevType = target_item.obj.obj_get_int64(obj_f_critter_monster_category) + target_item.obj.obj_set_int64(obj_f_critter_monster_category, mc_type_humanoid) + + target_item.obj.condition_add_with_args( 'sp-Raise Dead', spell.id, spell.duration, 0 ) + #target_item.partsys_id = game.particles( 'sp-Raise Dead', target_item.obj ) + + if target_item.obj.stat_level_get( stat_level ) == 1: + game.global_vars[752] = 0 + elif target_item.obj.stat_level_get( stat_level ) == 2: + game.global_vars[752] = 500 + elif target_item.obj.stat_level_get( stat_level ) == 3: + game.global_vars[752] = 2000 + elif target_item.obj.stat_level_get( stat_level ) == 4: + game.global_vars[752] = 4500 + elif target_item.obj.stat_level_get( stat_level ) == 5: + game.global_vars[752] = 8000 + elif target_item.obj.stat_level_get( stat_level ) == 6: + game.global_vars[752] = 12500 + elif target_item.obj.stat_level_get( stat_level ) == 7: + game.global_vars[752] = 18000 + elif target_item.obj.stat_level_get( stat_level ) == 8: + game.global_vars[752] = 24500 + elif target_item.obj.stat_level_get( stat_level ) == 9: + game.global_vars[752] = 32000 + elif target_item.obj.stat_level_get( stat_level ) == 10: + game.global_vars[752] = 40500 + elif target_item.obj.stat_level_get( stat_level ) == 11: + game.global_vars[752] = 50000 + elif target_item.obj.stat_level_get( stat_level ) == 12: + game.global_vars[752] = 60500 + elif target_item.obj.stat_level_get( stat_level ) == 13: + game.global_vars[752] = 72000 + elif target_item.obj.stat_level_get( stat_level ) == 14: + game.global_vars[752] = 84500 + elif target_item.obj.stat_level_get( stat_level ) == 15: + game.global_vars[752] = 98000 + elif target_item.obj.stat_level_get( stat_level ) == 16: + game.global_vars[752] = 112500 + elif target_item.obj.stat_level_get( stat_level ) == 17: + game.global_vars[752] = 128000 + elif target_item.obj.stat_level_get( stat_level ) == 18: + game.global_vars[752] = 144500 + elif target_item.obj.stat_level_get( stat_level ) == 19: + game.global_vars[752] = 162000 + else: + game.global_vars[752] = 180500 + + #Restore the outsider tag if necessary + if prevType != 0: + target_item = spell.target_list[0] + target_item.obj.obj_set_int64(obj_f_critter_monster_category, prevType) + + target_item.obj.stat_base_set(stat_experience, game.global_vars[752]) + + target_item.obj.object_script_execute( target_item.obj, 18 ) + else: + game.particles( 'Fizzle', target_item.obj ) + target_item.obj.float_mesfile_line ('mes\\spell.mes', 16020) + target_item.obj.float_mesfile_line ('mes\\spell.mes', 16020) + + spell.spell_end( spell.id, 1 ) + +def OnBeginRound( spell ): + spell.spell_end( spell.id, 1 ) + print "Raise Dead OnBeginRound" + +def OnEndSpellCast( spell ): + print "Raise Dead OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell383 - Ray of Enfeeblement.py b/tpdatasrc/palcov/scr/Spell383 - Ray of Enfeeblement.py new file mode 100644 index 000000000..6d2060202 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell383 - Ray of Enfeeblement.py @@ -0,0 +1,73 @@ +from toee import * +import tpdp + +def OnBeginSpellCast( spell ): + print "Ray of Enfeeblement OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + +def OnSpellEffect( spell ): + print "Ray of Enfeeblement OnSpellEffect" + +def OnBeginRound( spell ): + print "Ray of Enfeeblement OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Ray of Enfeeblement OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Ray of Enfeeblement', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Ray of Enfeeblement', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Ray of Enfeeblement OnEndProjectile" + + dam_bonus = min( 5, spell.caster_level / 2 ) + dam_amount = spell.roll_dice_with_metamagic(1, 6, dam_bonus) + + + print "amount=", dam_amount + + spell.duration = 10 * spell.caster_level + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target_item = spell.target_list[0] + + if spell.caster.perform_touch_attack( target_item.obj ) & D20CAF_HIT: + + # HTN - 3.5, no fortitude save + # hit + #if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw successful + #target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + #game.particles( 'Fizzle', target_item.obj ) + #spell.target_list.remove_target( target_item.obj ) + #else: + # saving throw unsuccessful + #target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # check target strength and adjust damage if the target's strength drops below 1 + target_strength = target_item.obj.stat_level_get(stat_strength) + if target_strength > 1: + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 20022, tf_red ) + if target_strength - dam_amount < 1: + z = 0 + while z < target_strength: + if target_strength - z == 1: + dam_amount = z + z = z + 1 + else: + dam_amount = 0 + + target_item.obj.condition_add_with_args( 'sp-Ray of Enfeeblement', spell.id, spell.duration, dam_amount ) + target_item.partsys_id = game.particles( 'sp-Ray of Enfeeblement-Hit', target_item.obj ) + + else: + # missed + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Ray of Enfeeblement OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell384 - Ray of Frost.py b/tpdatasrc/palcov/scr/Spell384 - Ray of Frost.py new file mode 100644 index 000000000..4d0e966b8 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell384 - Ray of Frost.py @@ -0,0 +1,50 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Ray of Frost OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Ray of Frost OnSpellEffect" + +def OnBeginRound( spell ): + print "Ray of Frost OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Ray of Frost OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Ray of Frost', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Ray of Frost', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Ray of Frost OnEndProjectile" + + damage_dice = dice_new( '1d3' ) + spell.duration = 0 + + if spell.caster.name == 14897: # fog turtle + spell.dc = 13 # 10 + 0 + 3 (cha) + spell.caster_level = 3 + num = max (1, int(group_average_level(game.leader)/2) ) + damage_dice = dice_new(str(num) + 'd6') + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target_item = spell.target_list[0] + + return_val = spell.caster.perform_touch_attack( target_item.obj ) + if return_val & D20CAF_HIT: + # hit + game.particles( 'sp-Ray of Frost-Hit', target_item.obj ) + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_COLD, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, return_val, index_of_target ) + else: + # missed + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + game.particles( 'Fizzle', target_item.obj ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Ray of Frost OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell385 - Read Magic.py b/tpdatasrc/palcov/scr/Spell385 - Read Magic.py new file mode 100644 index 000000000..1095a87e1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell385 - Read Magic.py @@ -0,0 +1,37 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Read Magic OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-divination-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Read Magic OnSpellEffect" + + spell.duration = 0 + + target_item = spell.target_list[0] + + if target_item.obj.name == 9900: + game.particles( 'sp-Bestow Curse', spell.caster ) + game.sound(6562,1) # sp_Bestow_Curse.wav + target_item.obj.destroy() + for x in (1,2,3): + spell.caster.float_mesfile_line( 'mes\\spell.mes', 30020 ) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 30021 ) + cha = spell.caster.stat_base_get(stat_charisma) + spell.caster.stat_base_set(stat_charisma, cha - 1) + + else: + game.particles( 'sp-Read Magic', spell.caster ) + target_item.obj.item_flag_set( OIF_IDENTIFIED ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Read Magic OnBeginRound" + +def OnEndSpellCast( spell ): + print "Read Magic OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell401 - Restoration.py b/tpdatasrc/palcov/scr/Spell401 - Restoration.py new file mode 100644 index 000000000..bf3f14431 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell401 - Restoration.py @@ -0,0 +1,50 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Restoration OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Restoration OnSpellEffect" + + spell.duration = 0 + target_item = spell.target_list[0] + + # get the ability type (from radial menu, -1 to offset index and D20Strength == 0) + ability_type = (spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) - 1) + + ## Solves Radial menu problem for Wands/NPCs + if ability_type != 0 and ability_type != 1 and ability_type != 2 and ability_type != 3 and ability_type != 4 and ability_type != 5: + ability_type = game.random_range(1,6) + ability_type = ability_type - 1 + + if target_item.obj.is_friendly( spell.caster ) or spell.caster.name == 14656: # Mabon + + target_item.obj.condition_add_with_args( 'sp-Restoration', spell.id, spell.duration, ability_type ) + target_item.partsys_id = game.particles( 'sp-Restoration', target_item.obj ) + + elif not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw unsuccesful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + target_item.obj.condition_add_with_args( 'sp-Restoration', spell.id, spell.duration, ability_type ) + target_item.partsys_id = game.particles( 'sp-Restoration', target_item.obj ) + + else: + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Restoration OnBeginRound" + +def OnEndSpellCast( spell ): + print "Restoration OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell404 - Righteous Might.py b/tpdatasrc/palcov/scr/Spell404 - Righteous Might.py new file mode 100644 index 000000000..a5e1bb006 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell404 - Righteous Might.py @@ -0,0 +1,78 @@ +from toee import * + +import _include +from co8Util import size +from co8Util.PersistentData import * +from co8Util.ObjHandling import * + +RM_KEY = "Sp404_RighteousMight_Activelist" + +def OnBeginSpellCast( spell ): + print "Righteous Might OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-transmutation-conjure", spell.caster ) + + +def OnSpellEffect( spell ): + print "Righteous Might OnSpellEffect" + + spell.duration = 1 * spell.caster_level + target_item = spell.target_list[0] + + #size mod +## print "Size:" + str(target_item.obj.obj_get_int(obj_f_size)) +## print "Reach:" + str(target_item.obj.obj_get_int(obj_f_critter_reach)) + size.incSizeCategory(target_item.obj) + + #save target_list + activeList = Co8PersistentData.getData(RM_KEY) + if isNone(activeList): activeList = [] + activeList.append([spell.id, derefHandle(target_item.obj)]) + Co8PersistentData.setData(RM_KEY, activeList) + +## print "new Size:" + str(target_item.obj.obj_get_int(obj_f_size)) +## print "new Reach:" + str(target_item.obj.obj_get_int(obj_f_critter_reach)) + + + target_item.obj.condition_add_with_args( 'sp-Righteous Might', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Righteous Might', target_item.obj ) + + +def OnBeginRound( spell ): + print "Righteous Might OnBeginRound" + + +def OnEndSpellCast( spell ): + print "Righteous Might OnEndSpellCast" + ##print "spell.target_list=", spell.target_list + ##print "spell.id=", spell.id + + #size mod + + activeList = Co8PersistentData.getData(RM_KEY) + if isNone(activeList): + print "ERROR! Active RM spell without activeList!" + return + + for entry in activeList: + spellID, target = entry + targetObj = refHandle(target) + #print "activeLIst Entry:" + str(spellID) + if spellID == spell.id: + #print "Size:" + str(targetObj.obj_get_int(obj_f_size)) + #print "Reach:" + str(targetObj.obj_get_int(obj_f_critter_reach)) + size.resetSizeCategory(targetObj) + #print "resetting reach on", targetObj + #print "new Size:" + str(targetObj.obj_get_int(obj_f_size)) + #print "new Reach:" + str(targetObj.obj_get_int(obj_f_critter_reach)) + activeList.remove(entry) + #no more active spells + if len(activeList) == 0: + Co8PersistentData.removeData(RM_KEY) + break + + Co8PersistentData.setData(RM_KEY, activeList) + break + + else: print "ERROR! Active RM spell without entry in activeList!" diff --git a/tpdatasrc/palcov/scr/Spell412 - Searing Light.py b/tpdatasrc/palcov/scr/Spell412 - Searing Light.py new file mode 100644 index 000000000..d88ddef2e --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell412 - Searing Light.py @@ -0,0 +1,89 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Searing Light OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + +def OnSpellEffect( spell ): + print "Searing Light OnSpellEffect" + +def OnBeginRound( spell ): + print "Searing Light OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Searing Light OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Searing Light', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Searing Light', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Searing Light OnEndProjectile" + + + damage_dice = dice_new( '1d8' ) + damage_dice.number = min( 5, spell.caster_level / 2 ) + + spell.duration = 0 + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target_item = spell.target_list[0] + + npc = spell.caster + if npc.name == 20003: + for obj in game.party[0].group_list(): + if obj.name == 8072 and obj.leader_get() != OBJ_HANDLE_NULL: + curr = obj.stat_level_get( stat_hp_current ) + if curr >= -9: + target_item.obj = obj + + ################################################################################################ + # adding fix for an undead creature particularly vulnerable to bright light (& six lines below) + ################################################################################################ + + # check if undead has a vulnerability to sunlight, an aversion to daylight, or a sunlight or daylight powerlessness + # current creatures: Bodak, Nightwalker + undead_list = [14328,14849,14986] + if (target_item.obj.is_category_type( mc_type_undead )): # bodak, wraith, dread wraith + undead_vulnerable = 0 + for undead in undead_list: + if undead == target_item.obj.name: + undead_vulnerable = 1 + + ################################################################################################ + + if spell.caster.name in (14396,14888): # lantern archon, marc 5/8/16 + damage_dice = dice_new('2d6') + + attack_successful = spell.caster.perform_touch_attack( target_item.obj ) + + if attack_successful & D20CAF_HIT: + if index_of_target > 0: + attack_successful |= D20CAF_NO_PRECISION_DAMAGE + game.particles( 'sp-Searing Light-Hit', target_item.obj ) + + # hit + if (target_item.obj.is_category_type( mc_type_undead )): + if undead_vulnerable == 1: + damage_dice.size = 8 + else: + damage_dice.size = 6 + damage_dice.number = min( 10, spell.caster_level ) + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_POSITIVE_ENERGY, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id , attack_successful, index_of_target) + else: + if (target_item.obj.is_category_type( mc_type_construct )): + damage_dice.size = 6 + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_POSITIVE_ENERGY, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id , attack_successful, index_of_target) + + else: + + # missed + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + + game.particles( 'Fizzle', target_item.obj ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Searing Light OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell432 - Shout.py b/tpdatasrc/palcov/scr/Spell432 - Shout.py new file mode 100644 index 000000000..4a1b9987f --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell432 - Shout.py @@ -0,0 +1,76 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Shout OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Shout OnSpellEffect" + + remove_list = [] + + damage_dice = dice_new( '5d6' ) + duration_dice = dice_new( '2d6' ) + spell.duration = duration_dice.roll() + earth_dam = dice_new ( '1d6' ) + earth_dam.number = min( 15, spell.caster_level ) + + game.particles( 'sp-Shout', spell.caster ) + + # get all targets in a 25ft + 2ft/level cone (60') + + npc = spell.caster ## added so NPC's can target Shout + + #### Caster is NOT in game party + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: +# range = 25 + 2 * int(spell.caster_level/2) + range = 30 + target_list = list(game.obj_list_cone( spell.caster, OLC_CRITTERS, range, -30, 90 )) + target_list.remove(spell.caster) + for obj in target_list: + if not obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw unsuccessful + obj.spell_damage( spell.caster, D20DT_SONIC, damage_dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + obj.condition_add_with_args( 'sp-Shout', spell.id, spell.duration, 0 ) +# obj.partsys_id = game.particles( 'sp-Shout-Hit', obj ) + game.particles( 'sp-Shout-Hit', obj ) + else: + # saving throw successful, apply half damage + obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + obj.spell_damage_with_reduction( spell.caster, D20DT_SONIC, damage_dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) +# obj.partsys_id = game.particles( 'sp-Shout-Hit', obj ) + game.particles( 'sp-Shout-Hit', obj ) + game.particles( 'Fizzle', obj ) + + + #### Caster is in game party + if npc.type == obj_t_pc or npc.leader_get() != OBJ_HANDLE_NULL: + for target_item in spell.target_list: + + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, spell.id ): + # saving throw unsuccessful + target_item.obj.spell_damage( spell.caster, D20DT_SONIC, damage_dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + + target_item.obj.condition_add_with_args( 'sp-Shout', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Shout-Hit', target_item.obj ) + + else: + + # saving throw successful, apply half damage + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + target_item.obj.spell_damage_with_reduction( spell.caster, D20DT_SONIC, damage_dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + target_item.partsys_id = game.particles( 'sp-Shout-Hit', target_item.obj ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Shout OnBeginRound" + +def OnEndSpellCast( spell ): + print "Shout OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell434 - Silence.py b/tpdatasrc/palcov/scr/Spell434 - Silence.py new file mode 100644 index 000000000..67000fc06 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell434 - Silence.py @@ -0,0 +1,66 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Silence OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-illusion-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Silence OnSpellEffect" + + npc = spell.caster ## added so NPC's can use wand/potion/scroll + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL and spell.caster_level <= 0: + spell.caster_level = 8 + + if npc.name == 14425 and game.global_vars[711] == 1: + spell.caster_level = 6 + spell.dc = 17 + + spell.duration = 10 * spell.caster_level + + # test whether we targeted the ground or an object + if spell.is_object_selected() == 1: + target_item = spell.target_list[0] + + # allow Will saving throw to negate + if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + spell.target_list.remove_target( target_item.obj ) + else: + # put sp-Silence condition on target + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + spell_obj_partsys_id = game.particles( 'sp-Silence', target_item.obj ) + target_item.obj.condition_add_with_args( 'sp-Silence', spell.id, spell.duration, 0, spell_obj_partsys_id ) + + else: + # spawn one spell_object object + spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + spell_obj.d20_status_init() + spell_obj.set_initiative( caster_init_value ) + + # put sp-Silence condition on obj + spell_obj_partsys_id = game.particles( 'sp-Silence', spell_obj ) + spell_obj.condition_add_with_args( 'sp-Silence', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #spell_obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = spell_obj.condition_get_arg_x( 2 ) + +def OnBeginRound( spell ): + print "Silence OnBeginRound" + +def OnEndSpellCast( spell ): + print "Silence OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Silence OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Silence OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell455 - Spike Growth.py b/tpdatasrc/palcov/scr/Spell455 - Spike Growth.py new file mode 100644 index 000000000..edc6060ce --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell455 - Spike Growth.py @@ -0,0 +1,49 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Spike Growth OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-transmutation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Spike Growth OnSpellEffect" + + spell.duration = 600 * spell.caster_level + + outdoor_map_list = [5001, 5050, 5051, 5052, 5054, 5062, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5091, 5093, 5094, 5095, 5106, 5110, 5111, 5112, 5113] + + if game.leader.map in outdoor_map_list: + + # spawn one spell_object object + spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + spell_obj.d20_status_init() + spell_obj.set_initiative( caster_init_value ) + + # put sp-Spike Growth condition on obj + spell_obj_partsys_id = game.particles( 'sp-Spike Growth', spell_obj ) + spell_obj.condition_add_with_args( 'sp-Spike Growth', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #spell_obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = spell_obj.condition_get_arg_x( 2 ) + + else: + + # No plants to grow + game.particles( 'Fizzle', spell.caster ) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 30000 ) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16019 ) + +def OnBeginRound( spell ): + print "Spike Growth OnBeginRound" + +def OnEndSpellCast( spell ): + print "Spike Growth OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Spike Growth OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Spike Growth OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell457 - Spiritual Weapon.py b/tpdatasrc/palcov/scr/Spell457 - Spiritual Weapon.py new file mode 100644 index 000000000..ffbfe9eff --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell457 - Spiritual Weapon.py @@ -0,0 +1,204 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Spiritual Weapon OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Spiritual Weapon OnSpellEffect" + + spell.duration = 1 * spell.caster_level + + # get the caster's deity + deity = spell.caster.get_deity() + + # find the deity's preferred weapon, default is dagger + weapon_proto = 4142 + weapon_portrait = 0; + if (deity == DEITY_BOCCOB): + # staff + weapon_proto = 4152 + weapon_portrait = 8060; + elif (deity == DEITY_CORELLON_LARETHIAN): + # longsword + weapon_proto = 4146 + weapon_portrait = 8010; + elif (deity == DEITY_EHLONNA): + # staff + weapon_proto = 4152 + weapon_portrait = 8060; + elif (deity == DEITY_ERYTHNUL): + # morningstar + weapon_proto = 4147 + weapon_portrait = 8040; + elif (deity == DEITY_FHARLANGHN): + # staff + weapon_proto = 4152 + weapon_portrait = 8060; + elif (deity == DEITY_GARL_GLITTERGOLD): + # battleaxe blue + weapon_proto = 4140 + weapon_portrait = 7950; + elif (deity == DEITY_GRUUMSH): + # spear + weapon_proto = 4151 + weapon_portrait = 8050; + elif (deity == DEITY_HEIRONEOUS): + # longsword + weapon_proto = 4146 + weapon_portrait = 8010; + elif (deity == DEITY_HEXTOR): + # morningstar + weapon_proto = 4147 + weapon_portrait = 8040; + elif (deity == DEITY_KORD): + # greatsword + weapon_proto = 4143 + weapon_portrait = 7980; + elif (deity == DEITY_MORADIN): + # warhammer + weapon_proto = 4153 + weapon_portrait = 8070; + elif (deity == DEITY_NERULL): + # scythe + weapon_proto = 4149 + weapon_portrait = 8030; + elif (deity == DEITY_OBAD_HAI): + # staff + weapon_proto = 4152 + weapon_portrait = 8060; + elif (deity == DEITY_OLIDAMMARA): + # rapier + weapon_proto = 4148 + weapon_portrait = 8020; + elif (deity == DEITY_PELOR): + # heavymace + weapon_proto = 4144 + weapon_portrait = 7970; + elif (deity == DEITY_ST_CUTHBERT): + # heavymace + weapon_proto = 4144 + weapon_portrait = 7970; + elif (deity == DEITY_VECNA): + # dagger + weapon_proto = 4142 + weapon_portrait = 7960; + elif (deity == DEITY_WEE_JAS): + # dagger + weapon_proto = 4142 + weapon_portrait = 7960; + elif (deity == DEITY_YONDALLA): + # shortsword + weapon_proto = 4150 + weapon_portrait = 8000; + elif (deity == DEITY_OLD_FAITH): + # heavymace + weapon_proto = 4144 + weapon_portrait = 7970; + elif (deity == DEITY_ZUGGTMOY): + # warhammer + weapon_proto = 4153 + weapon_portrait = 8070; + elif (deity == DEITY_IUZ): + # greatsword + weapon_proto = 4143 + weapon_portrait = 7980; + elif (deity == DEITY_LOLTH): + # dagger + weapon_proto = 4142 + weapon_portrait = 7960; + elif (deity == DEITY_PROCAN): + # spear + weapon_proto = 4151 + weapon_portrait = 8050; + elif (deity == DEITY_NOREBO): + # dagger + weapon_proto = 4142 + weapon_portrait = 7960; + elif (deity == DEITY_PYREMIUS): + # longsword + weapon_proto = 4146 + weapon_portrait = 8010; + elif (deity == DEITY_RALISHAZ): + # staff + weapon_proto = 4152 + weapon_portrait = 8060; + else: + # staff + weapon_proto = 4152 + weapon_portrait = 8060; + print "SPIRITUAL WEAPON WARNING: deity=", deity," not found!" + + # figure out the proto_id from the deity + monster_proto_id = 14370 + + # Barnibus, Alterius, Parvo, Foote, Pia, Ileviam + if spell.caster.name in [14514,14605,14606,14607,14608,14623]: + monster_proto_id = 14464 # faction 9 + + # create monster + monster_obj = game.obj_create( monster_proto_id, spell.target_loc ) + monster_obj.obj_set_int( obj_f_critter_portrait, weapon_portrait ) + + hit_points = 6 * spell.caster_level + hit_points = 25 + hit_points + monster_obj.stat_base_set(stat_hp_max, hit_points) + + + # equip the tempman with the appropriate weapon + weapon_obj = game.obj_create( weapon_proto, monster_obj.location ) + monster_obj.item_get( weapon_obj ) + monster_obj.item_wield_best_all() + print "SPIRITUAL WEAPON: equipped obj=( ", monster_obj, " ) with weapon=( ", weapon_obj, " )!" + + # add monster to follower list for spell_caster + spell.caster.ai_follower_add( monster_obj ) + print "added as follower" + + # add monster_obj to d20initiative, and set initiative to spell_caster's + caster_init_value = spell.caster.get_initiative() + print "got the caster's initiative" + monster_obj.add_to_initiative() + print "added to initiative" + + if not (spell.caster in game.party[0].group_list()): + highest = -999 + initt = -999 + for dude in game.party: + if dude.get_initiative() > highest and critter_is_unconscious(dude) == 0: + highest = dude.get_initiative() + if dude.get_initiative() > initt and dude.get_initiative() < caster_init_value and critter_is_unconscious(dude) == 0: + initt = max(dude.get_initiative() - 1, 1) + if initt == -999: + initt = max( highest , 1) + else: + initt = caster_init_value + monster_obj.set_initiative( initt ) # changed by S.A. - in case you have the same faction as the summoned weapon, it needs to see you fighting other members of its faction otherwise it won't act + #monster_obj.set_initiative( caster_init_value ) # removed by S.A. - in case you have the same faction as the summoned weapon, it needs to see you fighting other members of its faction otherwise it won't act and lose a turn + game.update_combat_ui() + print "update cmbat ui" + + # monster should disappear when duration is over, apply "TIMED_DISAPPEAR" condition + monster_obj.condition_add_with_args( 'sp-Summoned', spell.id, spell.duration, 0 ) + monster_obj.condition_add_with_args( 'sp-Spiritual Weapon', spell.id, spell.duration, weapon_proto ) + + print "condition have been added to Spiritual Weapon" + + # add monster to target list + spell.num_of_targets = 1 + spell.target_list[0].obj = monster_obj + spell.target_list[0].partsys_id = game.particles( 'sp-spell resistance', spell.target_list[0].obj ) + print "particles" + + spell.spell_end( spell.id ) + + print "spell ended, end of OnSpellEffect script" + +def OnBeginRound( spell ): + print "Spiritual Weapon OnBeginRound" + +def OnEndSpellCast( spell ): + print "Spiritual Weapon OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell460 - Stinking Cloud.py b/tpdatasrc/palcov/scr/Spell460 - Stinking Cloud.py new file mode 100644 index 000000000..c1c77f5b6 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell460 - Stinking Cloud.py @@ -0,0 +1,45 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Stinking Cloud OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Stinking Cloud OnSpellEffect" + + spell.duration = 1 * spell.caster_level + + if spell.caster.name in [14259,14360]: # Hezrou + spell.dc = 24 # Monster Manual + spell.duration = 3 + + # spawn one spell_object object + spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc, spell.target_loc_off_x, spell.target_loc_off_y ) + + # add to d20initiative + caster_init_value = spell.caster.get_initiative() + spell_obj.d20_status_init() + spell_obj.set_initiative( caster_init_value ) + + # put sp-Stinking Cloud condition on obj + spell_obj_partsys_id = game.particles( 'sp-Stinking Cloud', spell_obj ) + spell_obj.condition_add_with_args( 'sp-Stinking Cloud', spell.id, spell.duration, 0, spell_obj_partsys_id ) + #spell_obj.condition_add_arg_x( 3, spell_obj_partsys_id ) + #objectevent_id = spell_obj.condition_get_arg_x( 2 ) + + if spell.caster.name in (14259,14360): # Hezrou + game.global_vars[369] = spell_obj_partsys_id + +def OnBeginRound( spell ): + print "Stinking Cloud OnBeginRound" + +def OnEndSpellCast( spell ): + print "Stinking Cloud OnEndSpellCast" + +def OnAreaOfEffectHit( spell ): + print "Stinking Cloud OnAreaOfEffectHit" + +def OnSpellStruck( spell ): + print "Stinking Cloud OnSpellStruck" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell467 - Summon Monster I.py b/tpdatasrc/palcov/scr/Spell467 - Summon Monster I.py new file mode 100644 index 000000000..21da3c375 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell467 - Summon Monster I.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster I OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster I OnSpellEffect" + teststr = "; summon monster 1\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster I', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster I OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster I OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell468 - Summon Monster II.py b/tpdatasrc/palcov/scr/Spell468 - Summon Monster II.py new file mode 100644 index 000000000..08d9196ae --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell468 - Summon Monster II.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster II OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster II OnSpellEffect" + teststr = "; summon monster 2\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster II', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster II OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster II OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell469 - Summon Monster III.py b/tpdatasrc/palcov/scr/Spell469 - Summon Monster III.py new file mode 100644 index 000000000..6075cf413 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell469 - Summon Monster III.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster III OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster III OnSpellEffect" + teststr = "; summon monster 3\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster III', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster III OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster III OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell470 - Summon Monster IV.py b/tpdatasrc/palcov/scr/Spell470 - Summon Monster IV.py new file mode 100644 index 000000000..f7ead86cf --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell470 - Summon Monster IV.py @@ -0,0 +1,41 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster IV OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster IV OnSpellEffect" + teststr = "; summon monster 4\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + npc = spell.caster + if npc.name == 8047: # Alrrem + spell_arg = 14569 # Fiendish Huge Viper w. faction 5 + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster IV', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster IV OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster IV OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell471 - Summon Monster V.py b/tpdatasrc/palcov/scr/Spell471 - Summon Monster V.py new file mode 100644 index 000000000..cc12d74e9 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell471 - Summon Monster V.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster V OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster V OnSpellEffect" + teststr = "; summon monster 5\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster V OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster V OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell472 - Summon Monster VI.py b/tpdatasrc/palcov/scr/Spell472 - Summon Monster VI.py new file mode 100644 index 000000000..757027192 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell472 - Summon Monster VI.py @@ -0,0 +1,39 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster VI OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster VI OnSpellEffect" + teststr = "; summon monster 6\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + + target_item = spell.target_list[0] + game.particles('sp-Summon Monster V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster VI OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster VI OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell473 - Summon Monster VII.py b/tpdatasrc/palcov/scr/Spell473 - Summon Monster VII.py new file mode 100644 index 000000000..cf4bfef4c --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell473 - Summon Monster VII.py @@ -0,0 +1,44 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster VII OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster VII OnSpellEffect" + + teststr = "; summon monster 7\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + if spell.caster.name == 14950: # Noble Salamander + spell.dc = 19 # 10 + 7 + 2 (charisma) + spell.caster_level = 15 + options = [14902,14300,14898,14291] # huge fire elem, fire toad, dire hell hound, wisp + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster VII OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster VII OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell474 - Summon Monster VIII.py b/tpdatasrc/palcov/scr/Spell474 - Summon Monster VIII.py new file mode 100644 index 000000000..150093854 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell474 - Summon Monster VIII.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster VIII OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster VIII OnSpellEffect" + teststr = "; summon monster 8\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster VIII OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster VIII OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell475 - Summon Monster IX.py b/tpdatasrc/palcov/scr/Spell475 - Summon Monster IX.py new file mode 100644 index 000000000..6f538ff51 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell475 - Summon Monster IX.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Monster IX OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Monster IX OnSpellEffect" + teststr = "; summon monster 9\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Monster V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Monster IX OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Monster IX OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell476 - Summon Nature's Ally I.py b/tpdatasrc/palcov/scr/Spell476 - Summon Nature's Ally I.py new file mode 100644 index 000000000..eb3ceaff0 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell476 - Summon Nature's Ally I.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's I OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's I OnSpellEffect" + teststr = "; summon nature's ally 1\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally I', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's I OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's I OnEndSpellCast" + \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell477 - Summon Nature's Ally II.py b/tpdatasrc/palcov/scr/Spell477 - Summon Nature's Ally II.py new file mode 100644 index 000000000..cf62b1667 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell477 - Summon Nature's Ally II.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's II OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's II OnSpellEffect" + teststr = "; summon nature's ally 2\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally II', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's II OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's II OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell478 - Summon Nature's Ally III.py b/tpdatasrc/palcov/scr/Spell478 - Summon Nature's Ally III.py new file mode 100644 index 000000000..f696c44df --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell478 - Summon Nature's Ally III.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's III OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's III OnSpellEffect" + teststr = "; summon nature's ally 3\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally III', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's III OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's III OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell479 - Summon Nature's Ally IV.py b/tpdatasrc/palcov/scr/Spell479 - Summon Nature's Ally IV.py new file mode 100644 index 000000000..7df824f8c --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell479 - Summon Nature's Ally IV.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's IV OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's IV OnSpellEffect" + teststr = "; summon nature's ally 4\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally IV', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's IV OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's IV OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell480 - Summon Nature's Ally V.py b/tpdatasrc/palcov/scr/Spell480 - Summon Nature's Ally V.py new file mode 100644 index 000000000..b8d56e2cd --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell480 - Summon Nature's Ally V.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's V OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's V OnSpellEffect" + teststr = "; summon nature's ally 5\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's V OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's V OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell481 - Summon Nature's Ally VI.py b/tpdatasrc/palcov/scr/Spell481 - Summon Nature's Ally VI.py new file mode 100644 index 000000000..aa75d2c4b --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell481 - Summon Nature's Ally VI.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's VI OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's VI OnSpellEffect" + teststr = "; summon nature's ally 6\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's VI OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's VI OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell482 - Summon Nature's Ally VII.py b/tpdatasrc/palcov/scr/Spell482 - Summon Nature's Ally VII.py new file mode 100644 index 000000000..60f011bf1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell482 - Summon Nature's Ally VII.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's VII OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's VII OnSpellEffect" + teststr = "; summon nature's ally 7\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's VII OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's VII OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell483 - Summon Nature's Ally VIII.py b/tpdatasrc/palcov/scr/Spell483 - Summon Nature's Ally VIII.py new file mode 100644 index 000000000..6614e1515 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell483 - Summon Nature's Ally VIII.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's VIII OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's VIII OnSpellEffect" + teststr = "; summon nature's ally 8\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's VIII OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's VIII OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell484 - Summon Nature's Ally IX.py b/tpdatasrc/palcov/scr/Spell484 - Summon Nature's Ally IX.py new file mode 100644 index 000000000..caeada262 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell484 - Summon Nature's Ally IX.py @@ -0,0 +1,38 @@ +from toee import * +from utilities import * +from scripts import * + +def OnBeginSpellCast( spell ): + print "Summon Nature's IX OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Summon Nature's IX OnSpellEffect" + teststr = "; summon nature's ally 9\n" #change this to the header line for the spell in spells_radial_menu_options.mes + options = get_options_from_mes(teststr) + + spell.duration = 1 * spell.caster_level + + ## Solves Radial menu problem for Wands/NPCs + spell_arg = spell.spell_get_menu_arg( RADIAL_MENU_PARAM_MIN_SETTING ) + if spell_arg not in options: + x = game.random_range(0,len(options)-1) + spell_arg = options[x] + + # create monster, monster should be added to target_list + spell.summon_monsters( 1, spell_arg) + target_item = spell.target_list[0] + game.particles('sp-Summon Natures Ally V', target_item.obj) + + SummonMonster_Rectify_Initiative(spell, spell_arg) # Added by S.A. - sets iniative to caster's initiative -1, so that it gets to act in the same round + + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Summon Nature's IX OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Nature's IX OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell539 - Word of Chaos.py b/tpdatasrc/palcov/scr/Spell539 - Word of Chaos.py new file mode 100644 index 000000000..7f598c1d8 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell539 - Word of Chaos.py @@ -0,0 +1,97 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Word of Chaos OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Word of Chaos OnSpellEffect" + + remove_list = [] + + # The Will save versus banishment is at a -4 penalty + spell.dc = spell.dc + 4 + + npc = spell.caster + npc_caster_level = spell.caster_level + if npc.name == 14286 or npc.name == 14358: # Balors + npc_caster_level = 20 + spell.dc = 25+4 #only affects banishment anyway + + #f = open('wordofchaos_feedback.txt', 'w') + #f.write( 'ccc\n' ) + target_list = pyspell_targetarray_copy_to_obj_list(spell) + + for target_item_obj in target_list: + #f.write( str(target_item_obj.name) + '\n' ) + obj_hit_dice = target_item_obj.hit_dice_num + is_confused = 0 + + # Only works on non-chaotic creatures + alignment = target_item_obj.critter_get_alignment() + if not (alignment & ALIGNMENT_CHAOTIC) and not (npc == target_item_obj): + game.particles( 'sp-Polymorph Other', target_item_obj ) + + # Anything ten or more levels below the caster's level dies + if obj_hit_dice <= (npc_caster_level - 10): + # So you'll get awarded XP for the kill + if not target_item_obj in game.leader.group_list(): + target_item_obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item_obj.critter_kill() + + # Anything five or more levels below the caster's level is confused + if obj_hit_dice <= (npc_caster_level - 5): + spell.duration = game.random_range(1,10) * 10 + target_item_obj.float_mesfile_line( 'mes\\combat.mes', 113, tf_red ) + target_item_obj.condition_add_with_args( 'sp-Confusion', spell.id, spell.duration, 0 ) + is_confused = 1 ## added because Confusion will end when either the stun or deafness spell end (Confusion needs a fix.) + + # Anything one or more levels below the caster's level is stunned + if obj_hit_dice <= (npc_caster_level - 1): + if is_confused == 0: ## added because Confusion will end when the stun spell ends + spell.duration = 0 + target_item_obj.condition_add_with_args( 'sp-Color Spray Stun', spell.id, spell.duration, 0 ) + + # Anything the caster's level or below is deafened + if obj_hit_dice <= (npc_caster_level): + if is_confused == 0: ## added because Confusion will end when the deafness spell ends + spell.duration = game.random_range(1,4) + target_item_obj.condition_add_with_args( 'sp-Shout', spell.id, spell.duration, 0 ) + + # Summoned and extraplanar creatures below the caster's level are also banished + # if they fail a Will save at -4 + if target_item_obj.d20_query_has_spell_condition( sp_Summoned ) or target_item_obj.npc_flags_get() & ONF_EXTRAPLANAR != 0: + + # allow Will saving throw to negate + if target_item_obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target_item_obj ) + + else: + + # saving throw unsuccessful + target_item_obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # creature is sent back to its own plane + # kill for now + # So you'll get awarded XP for the kill + if not target_item_obj in game.leader.group_list(): + target_item_obj.damage( game.leader , D20DT_UNSPECIFIED, dice_new( "1d1" ) ) + target_item_obj.critter_kill() + + remove_list.append( target_item_obj ) + #f.close() + + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Word of Chaos OnBeginRound" + +def OnEndSpellCast( spell ): + print "Word of Chaos OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell555 - Acid Splash.py b/tpdatasrc/palcov/scr/Spell555 - Acid Splash.py new file mode 100644 index 000000000..380edca9e --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell555 - Acid Splash.py @@ -0,0 +1,49 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Acid Splash OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Acid Splash OnSpellEffect" + +def OnBeginRound( spell ): + print "Acid Splash OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Acid Splash OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Acid Splash', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Melfs Acid Arrow Projectile', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Acid Splash OnEndProjectile" + + damage_dice = dice_new( '1d3' ) + + spell.duration = 0 + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target_item = spell.target_list[0] + + return_val = spell.caster.perform_touch_attack( target_item.obj ) + if return_val & D20CAF_HIT: + + game.particles( 'sp-Acid Splash-Hit', target_item.obj ) + + # hit + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_ACID, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, return_val, index_of_target ) + else: + + # missed + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + + game.particles( 'Fizzle', target_item.obj ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Acid Splash OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell567 - Reincarnation.py b/tpdatasrc/palcov/scr/Spell567 - Reincarnation.py new file mode 100644 index 000000000..1df3a7d7d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell567 - Reincarnation.py @@ -0,0 +1,54 @@ +from toee import * +from scripts import End_Spell +from transform import * +from exclusions import * + +def OnBeginSpellCast( spell ): + print "Reincarnation OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-transmutation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Reincarnation OnSpellEffect" + + spell.duration = 1 + target_item = spell.target_list[0] + + raise_dead_exclusions = get_raise_dead_exclusions() + + if target_item.obj.name not in raise_dead_exclusions: + + target_item.obj.condition_add_with_args( 'sp-Raise Dead', spell.id, spell.duration, 0 ) + #target_item.partsys_id = game.particles( 'sp-Raise Dead', target_item.obj ) + + xp_current_level, xp_previous_level = 0, 0 + for L in range (1, target_item.obj.stat_level_get(stat_level)+1): + xp_previous_level = xp_current_level + xp_current_level += (L-1)*1000 + xp_new = xp_current_level - ((xp_current_level - xp_previous_level) / 2) + + target_item.obj.stat_base_set(stat_experience, xp_new) + target_item.obj.object_script_execute( target_item.obj, 18 ) + + # Vernox Reincarnation, change to random humanoid. Mark it as done to this pc. + if target_item.obj.type == obj_t_pc and spell.caster.name == 14555: + reincarnate (target_item.obj, "random", -1, -99) + dc = target_item.obj.obj_get_int(obj_f_secretdoor_dc) + if target_item.obj.obj_get_int(obj_f_secretdoor_dc) & 2**9 == 0: + target_item.obj.obj_set_int (obj_f_secretdoor_dc, dc + (2**9)) + + else: + game.particles( 'Fizzle', target_item.obj ) + target_item.obj.float_mesfile_line ('mes\\spell.mes', 16020) + target_item.obj.float_mesfile_line ('mes\\spell.mes', 16020) + + End_Spell(spell) + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Reincarnation OnBeginRound" + +def OnEndSpellCast( spell ): + print "Reincarnation OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell577 - Mass Cure Moderate Wounds.py b/tpdatasrc/palcov/scr/Spell577 - Mass Cure Moderate Wounds.py new file mode 100644 index 000000000..f195492d1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell577 - Mass Cure Moderate Wounds.py @@ -0,0 +1,86 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Healing Circle OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Healing Circle OnSpellEffect" + + remove_list = [] + + dice = dice_new( '2d8' ) + #dice.bonus = min( 30, spell.caster.stat_level_get( spell.caster_class ) ) + dice.bonus = min( 30, spell.caster_level ) + +# game.particles( 'sp-Healing Circle', spell.target_loc ) + + for target_item in spell.target_list: + + target = target_item.obj + + # check if target is friendly (willing target) + if target.is_friendly( spell.caster ): + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # heal target + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + #target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + game.particles( 'sp-Cure Moderate Wounds', target ) + + remove_list.append( target ) + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Healing Circle OnBeginRound" + +def OnEndSpellCast( spell ): + print "Healing Circle OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell578 - Mass Cure Serious Wounds.py b/tpdatasrc/palcov/scr/Spell578 - Mass Cure Serious Wounds.py new file mode 100644 index 000000000..82f484852 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell578 - Mass Cure Serious Wounds.py @@ -0,0 +1,86 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Healing Circle OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Healing Circle OnSpellEffect" + + remove_list = [] + + dice = dice_new( '3d8' ) + dice.bonus = min( 35, spell.caster.stat_level_get( spell.caster_class ) ) + +# game.particles( 'sp-Healing Circle', spell.target_loc ) + + for target_item in spell.target_list: + + target = target_item.obj + + # check if target is friendly (willing target) + if target.is_friendly( spell.caster ): + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # heal target + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + else: + #target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + game.particles( 'sp-Cure Serious Wounds', target ) + + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Healing Circle OnBeginRound" + +def OnEndSpellCast( spell ): + print "Healing Circle OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell579 - Mass Cure Critical Wounds.py b/tpdatasrc/palcov/scr/Spell579 - Mass Cure Critical Wounds.py new file mode 100644 index 000000000..62036f707 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell579 - Mass Cure Critical Wounds.py @@ -0,0 +1,86 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Healing Circle OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + print "Healing Circle OnSpellEffect" + + remove_list = [] + + dice = dice_new( '4d8' ) + #dice.bonus = min( 40, spell.caster.stat_level_get( spell.caster_class ) ) + dice.bonus = min( 40, spell.caster_level ) + + + for target_item in spell.target_list: + + target = target_item.obj + + # check if target is friendly (willing target) + if target.is_friendly( spell.caster ): + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # heal target + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + + # check if target is undead + if target.is_category_type( mc_type_undead ): + # check saving throw, damage target + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, damage target, 1/2 damage + target.spell_damage_with_reduction( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20A_CAST_SPELL, spell.id ) + else: + target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, damage target, full damage + target.spell_damage( spell.caster, D20DT_POSITIVE_ENERGY, dice, D20DAP_UNSPECIFIED, D20A_CAST_SPELL, spell.id ) + else: + # check saving throw + if target.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + #target.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + # saving throw succesful, heal target, 1/2 heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + else: + #target.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # saving throw unsuccesful, heal target, full heal + target.spell_heal( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + target.healsubdual( spell.caster, dice, D20A_CAST_SPELL, spell.id ) + + game.particles( 'sp-Cure Critical Wounds', target ) + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end(spell.id) + +def OnBeginRound( spell ): + print "Healing Circle OnBeginRound" + +def OnEndSpellCast( spell ): + print "Healing Circle OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell586 - Polar Ray.py b/tpdatasrc/palcov/scr/Spell586 - Polar Ray.py new file mode 100644 index 000000000..9857e406e --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell586 - Polar Ray.py @@ -0,0 +1,55 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Polar Ray OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Polar Ray OnSpellEffect" + +def OnBeginRound( spell ): + print "Polar Ray OnBeginRound" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Polar Ray OnBeginProjectile" + + #spell.proj_partsys_id = game.particles( 'sp-Ray of Frost', projectile ) + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Ray of Frost', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Polar Ray OnEndProjectile" + + if spell.caster.name == 14714: # Shadow Wizard + spell.caster_level = 20 + if spell.caster.name == 14968: # Lich + spell.caster_level = 20 + + damage_dice = dice_new( '1d6' ) + damage_dice.num = min (25, spell.caster_level) + + spell.duration = 0 + + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + target_item = spell.target_list[0] + + return_val = spell.caster.perform_touch_attack( target_item.obj ) + if return_val & D20CAF_HIT: + + game.particles( 'sp-Ray of Frost-Hit', target_item.obj ) + + # hit + target_item.obj.spell_damage_weaponlike( spell.caster, D20DT_COLD, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, return_val, index_of_target ) + else: + + # missed + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + + game.particles( 'Fizzle', target_item.obj ) + + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnEndSpellCast( spell ): + print "Polar Ray OnEndSpellCast" diff --git a/tpdatasrc/palcov/scr/Spell588 - Mass Hold Person.py b/tpdatasrc/palcov/scr/Spell588 - Mass Hold Person.py new file mode 100644 index 000000000..b19c6bc61 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell588 - Mass Hold Person.py @@ -0,0 +1,87 @@ +from utilities import * +from toee import * + +def OnBeginSpellCast( spell ): + print "Hold Person OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Hold Person OnSpellEffect" + + spell.duration = 1 * spell.caster_level + + remove_list = [] + + for target_item in spell.target_list: + + npc = spell.caster ## added so NPC's will choose valid targets + if npc.type != obj_t_pc and npc.leader_get() == OBJ_HANDLE_NULL: + if target_item.obj.is_category_type( mc_type_humanoid ) and critter_is_unconscious(target_item.obj) != 1 and not target_item.obj.d20_query(Q_Prone): + npc = spell.caster + else: + game.global_flags[811] = 0 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 5 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 10 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 15 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 20 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 25 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 30 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + for obj in game.party[0].group_list(): + if obj.distance_to(npc) <= 100 and critter_is_unconscious(obj) != 1 and obj.is_category_type( mc_type_humanoid ) and game.global_flags[811] == 0 and not obj.d20_query(Q_Prone): + target_item.obj = obj + game.global_flags[811] = 1 + + + if target_item.obj.is_category_type( mc_type_humanoid ): + # allow Will saving throw to negate + if target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + else: + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + # HTN - apply condition HOLD (paralyzed) + target_item.obj.condition_add_with_args( 'sp-Hold Person', spell.id, spell.duration, 0 ) + target_item.partsys_id = game.particles( 'sp-Hold Person', target_item.obj ) + else: + # not a person + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30000 ) + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 31004 ) + + game.particles( 'Fizzle', target_item.obj ) + remove_list.append( target_item.obj ) + + spell.target_list.remove_list( remove_list ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Hold Person OnBeginRound" + +def OnEndSpellCast( spell ): + print "Hold Person OnEndSpellCast" + diff --git a/tpdatasrc/palcov/scr/Spell589 - Resist Fire.py b/tpdatasrc/palcov/scr/Spell589 - Resist Fire.py new file mode 100644 index 000000000..a2f509cce --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell589 - Resist Fire.py @@ -0,0 +1,53 @@ +from toee import * +from co8Util.spells import * + +def OnBeginSpellCast( spell ): + print "Resist Fire OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Resist Fire OnSpellEffect" + + element_type = FIRE + partsys_type = 'sp-Resist Elements-fire' + pd_key = RESIST_FIRE_KEY + + spell.duration = spell.caster_level*100 + if (spell.caster not in game.party) and (spell.caster.object_flags_get() & OF_INVULNERABLE == 0): + spell.duration = 600*24*30 # 30 days + + target_item = spell.target_list[0] + + # Archer's Brew, 'Resist Fire (INTERNAL)' domain_special 11 + if spell.caster_level == 21 or (target_item.obj not in game.party and spell.caster.name != 14467): # pool caster + spell.caster_level = 15 + spell.duration = 100 + dex_amount = 4 + num_of_images = 8 + target_item.obj.condition_add_with_args( 'sp-Cats Grace', spell.id, spell.duration, dex_amount ) + target_item.obj.condition_add_with_args( 'sp-Haste', spell.id, spell.duration, 1 ) + target_item.obj.condition_add_with_args( 'sp-Mirror Image', spell.id, spell.duration, num_of_images ) + target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, COLD, spell.duration ) + + if target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target_item.obj) # marc + target_item.partsys_id = game.particles( partsys_type, target_item.obj ) + + # Pool + if spell.caster.name == 14467: + spell.caster_level = game.global_vars[911] + for target in game.party: + if target.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target) # marc + game.particles( 'sp-dispel air-end', target ) + game.particles( 'sp-aid-end', target ) + game.particles_end(target_item.partsys_id) # so npc caster doesn't get particles + +def OnBeginRound( spell ): + print "Resist Fire OnBeginRound" + +def OnEndSpellCast( spell ): + print "Resist Fire OnEndSpellCast" + remove_from_persistent_list (RESIST_FIRE_KEY, spell.id) # marc diff --git a/tpdatasrc/palcov/scr/Spell590 - Resist Acid.py b/tpdatasrc/palcov/scr/Spell590 - Resist Acid.py new file mode 100644 index 000000000..fbb91a00d --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell590 - Resist Acid.py @@ -0,0 +1,41 @@ +from toee import * +from co8Util.spells import * + +def OnBeginSpellCast( spell ): + print "Resist Acid OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Resist Acid OnSpellEffect" + + element_type = ACID + partsys_type = 'sp-Resist Elements-acid' + pd_key = RESIST_ACID_KEY + + spell.duration = spell.caster_level*100 + if (spell.caster not in game.party) and (spell.caster.object_flags_get() & OF_INVULNERABLE == 0): + spell.duration = 600*24*30 # 30 days + + target_item = spell.target_list[0] + + if target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target_item.obj) # marc + target_item.partsys_id = game.particles( partsys_type, target_item.obj ) + + if spell.caster.name == 14467: # pool + spell.caster_level = game.global_vars[911] + for target in game.party: + if target.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target) # marc + game.particles( 'sp-dispel air-end', target ) + game.particles( 'sp-aid-end', target ) + game.particles_end(target_item.partsys_id) # so npc caster doesn't get particles + +def OnBeginRound( spell ): + print "Resist Acid OnBeginRound" + +def OnEndSpellCast( spell ): + print "Resist Acid OnEndSpellCast" + remove_from_persistent_list (RESIST_ACID_KEY, spell.id) # marc diff --git a/tpdatasrc/palcov/scr/Spell591 - Resist Electricity.py b/tpdatasrc/palcov/scr/Spell591 - Resist Electricity.py new file mode 100644 index 000000000..89d264daa --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell591 - Resist Electricity.py @@ -0,0 +1,42 @@ +from toee import * +from co8Util.spells import * + +def OnBeginSpellCast( spell ): + print "Resist Electricity OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Resist Electricity OnSpellEffect" + + element_type = ELECTRICITY + partsys_type = 'sp-Resist Elements-electricity' + pd_key = RESIST_ELECTRICITY_KEY + + spell.duration = spell.caster_level*100 + if (spell.caster not in game.party) and (spell.caster.object_flags_get() & OF_INVULNERABLE == 0): + spell.duration = 600*24*30 # 30 days + + target_item = spell.target_list[0] + + if target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target_item.obj) # marc + target_item.partsys_id = game.particles( partsys_type, target_item.obj ) + + if spell.caster.name == 14467: # pool + spell.caster_level = game.global_vars[911] + for target in game.party: + if target.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target) # marc + game.particles( 'sp-dispel air-end', target ) + game.particles( 'sp-aid-end', target ) + game.particles_end(target_item.partsys_id) # so npc caster doesn't get particles + +def OnBeginRound( spell ): + print "Resist Electricity OnBeginRound" + +def OnEndSpellCast( spell ): + print "Resist Electricity OnEndSpellCast" + remove_from_persistent_list (RESIST_ELECTRICITY_KEY, spell.id) # marc + \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell592 - Resist Cold.py b/tpdatasrc/palcov/scr/Spell592 - Resist Cold.py new file mode 100644 index 000000000..f0a825cfa --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell592 - Resist Cold.py @@ -0,0 +1,41 @@ +from toee import * +from co8Util.spells import * + +def OnBeginSpellCast( spell ): + print "Resist Cold OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Resist Cold OnSpellEffect" + + element_type = COLD + partsys_type = 'sp-Resist Elements-cold' + pd_key = RESIST_COLD_KEY + + spell.duration = spell.caster_level*100 + if (spell.caster not in game.party) and (spell.caster.object_flags_get() & OF_INVULNERABLE == 0): + spell.duration = 600*24*30 # 30 days + + target_item = spell.target_list[0] + + if target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target_item.obj) # marc + target_item.partsys_id = game.particles( partsys_type, target_item.obj ) + + if spell.caster.name == 14467: # pool + spell.caster_level = game.global_vars[911] + for target in game.party: + if target.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + add_to_persistent_list (pd_key, spell.id, target) # marc + game.particles( 'sp-dispel air-end', target ) + game.particles( 'sp-aid-end', target ) + game.particles_end(target_item.partsys_id) # so npc caster doesn't get particles + +def OnBeginRound( spell ): + print "Resist Cold OnBeginRound" + +def OnEndSpellCast( spell ): + print "Resist Cold OnEndSpellCast" + remove_from_persistent_list (RESIST_COLD_KEY, spell.id) # marc diff --git a/tpdatasrc/palcov/scr/Spell593 - Resist Sonic.py b/tpdatasrc/palcov/scr/Spell593 - Resist Sonic.py new file mode 100644 index 000000000..081948d27 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell593 - Resist Sonic.py @@ -0,0 +1,30 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Resist Sonic OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-abjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Resist Sonic OnSpellEffect" + + element_type = SONIC + partsys_type = 'sp-Resist Elements-sonic' + + spell.duration = spell.caster_level*100 + if (spell.caster not in game.party) and (spell.caster.object_flags_get() & OF_INVULNERABLE == 0): + spell.duration = 600*24*30 # 30 days + + target_item = spell.target_list[0] + + #target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, spell.duration, element_type ) + if target_item.obj.condition_add_with_args( 'sp-Resist Elements', spell.id, element_type, spell.duration ): + target_item.partsys_id = game.particles( partsys_type, target_item.obj ) + + +def OnBeginRound( spell ): + print "Resist Sonic OnBeginRound" + +def OnEndSpellCast( spell ): + print "Resist Sonic OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell733 - Scorching Ray.py b/tpdatasrc/palcov/scr/Spell733 - Scorching Ray.py new file mode 100644 index 000000000..a0646bcdc --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell733 - Scorching Ray.py @@ -0,0 +1,78 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Scorching Ray OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-evocation-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Scorching Ray OnSpellEffect" + +def OnBeginProjectile( spell, projectile, index_of_target ): + print "Scorching Ray OnBeginProjectile" + + dbug("\nOnBeginProjectile\n spell.target_list",spell.target_list,"scorching_ray") + dbug(" spell.num_of_projectiles",spell.num_of_projectiles,"scorching_ray") + dbug(" projectile",projectile,"scorching_ray") + dbug(" index_of_target",index_of_target,"scorching_ray") + + projectiles = min( 3, (spell.caster_level + 1) / 4 ) + + if spell.caster.name == 14340: # efreeti + spell.dc = 14 # 10 + 2 + 2 (charisma) + spell.caster_level = 12 + projectiles = 1 + + if index_of_target < projectiles: + projectile.obj_set_int( obj_f_projectile_part_sys_id, game.particles( 'sp-Scorching Ray', projectile ) ) + +def OnEndProjectile( spell, projectile, index_of_target ): + print "Scorching Ray OnEndProjectile" + + dbug("\nOnEndProjectile\n spell.target_list",spell.target_list,"scorching_ray") + dbug(" spell.num_of_projectiles",spell.num_of_projectiles,"scorching_ray") + dbug(" projectile",projectile,"scorching_ray") + dbug(" index_of_target",index_of_target,"scorching_ray") + projectiles = min( 3, (spell.caster_level + 1) / 4 ) + + if spell.caster.name == 14340: # efreeti + spell.dc = 14 # 10 + 2 + 2 (charisma) + spell.caster_level = 12 + projectiles = 1 + + if index_of_target < projectiles: + spell.duration = 0 + game.particles_end( projectile.obj_get_int( obj_f_projectile_part_sys_id ) ) + + # NPC may get extra rays, marc + extra = 0 + if not spell.caster in game.party: + if spell.caster.name in [14893,14792,14793]: # 1 extra ray (orc warlock, W7, W9), + extra = 1 + elif spell.caster.name in [14537]: # 2 extra rays, (thormund) + extra = 2 + + target = spell.target_list[ index_of_target ] + return_val = spell.caster.perform_touch_attack( target.obj ) + + if return_val & D20CAF_HIT: + if index_of_target > 0: + return_val |= D20CAF_NO_PRECISION_DAMAGE + damage_dice = dice_new( '4d6' ) + game.particles( 'sp-Scorching Ray-Hit', target.obj ) + target.obj.spell_damage_weaponlike( spell.caster, D20DT_FIRE, damage_dice, D20DAP_UNSPECIFIED, 100, D20A_CAST_SPELL, spell.id, return_val, index_of_target ) + else: + + # missed + target.obj.float_mesfile_line( 'mes\\spell.mes', 30007 ) + + game.particles( 'Fizzle', target.obj ) + + spell.num_of_projectiles = spell.num_of_projectiles - 1 + if ( spell.num_of_projectiles == 0 ): + spell.spell_end( spell.id, 1 ) + +def OnEndSpellCast( spell ): + print "Scorching Ray OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell735 - Hezrou Stench.py b/tpdatasrc/palcov/scr/Spell735 - Hezrou Stench.py new file mode 100644 index 000000000..fbce88ea1 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell735 - Hezrou Stench.py @@ -0,0 +1,87 @@ +from toee import * +from stench import * + + +''' +Stench (Ex) + +sp-Hezrou Stench + OnEnter: + If first time: + - Do saving throw (Con, DC24) + Success: + - Apply Sickened + Failure: + - Apply Nauseated + D20Signal (S_Spell_End): data1 DONE + 0x100D3430 AoESpellRemove(DCA) + OnConditionAdd: + BeginHezrouStench: + similar to stinking cloud + + (no ImmunityTrigger, no CountDown, no Q_Critter_Has_Spell_Active) +sp-Hezrou Stench Hit + OnLeave: + if Nauseated: + change duration to 1d4 + Countdown expired: (relevant only for 1d4 really) + if Nauseated: + if inside AoE: + demote to Sickened + if outside AoE: + nothing + TurnbasedInit: + if Nauseated: + reduce hourglass to 1 + AoOPossible: + if Nauseated: + SetTo0 + Attack Rolls: + -2 penalty + Damage Rolls: + -2 penalty + Saving Throws: + -2 penalty + Skill checks: + -2 penalty + Ability checks: + -2 penalty + + + +Add to ImmunityHandler (type 13/14 I think) + +A hezrou’s skin produces a foul-smelling, toxic liquid whenever it fights. + +Any living creature (except other demons) within 10 feet must succeed on a DC 24 Fortitude save or be nauseated for as long as it remains within the affected area and for 1d4 rounds afterward. + +Creatures that successfully save are sickened for as long as they remain in the area. +A creature that successfully saves cannot be affected again by the same hezrou’s stench for 24 hours. +A delay poison or neutralize poison spell removes either condition from one creature. +Creatures that have immunity to poison are unaffected, and creatures resistant to poison receive their normal bonus on their saving throws. The save DC is Constitution-based. + +''' +def OnBeginSpellCast( spell ): + print "Hezrou Stench OnBeginSpellCast id= ", spell.id + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) # change to stinking cloud? + +def OnSpellEffect( spell ): + print "Hezrou Stench OnSpellEffect" + spell.dc = 100 + spell.duration = 1000 + #processStench(spell.caster, spell.id) # fuck youuuuuuuu + spell.caster.condition_add_with_args('Hezrou Stench', spell.id, spell.duration,0) + #spell.spell_end(spell.id) + +def OnAreaOfEffectHit( spell ): + print "Hezrou Stench OnAreaOfEffectHit: " + +def OnBeginRound( spell ): + print "Hezrou Stench OnBeginRound" + +def OnEndSpellCast( spell ): + print "Hezrou Stench OnEndSpellCast" + spell.spell_end(spell.id) + diff --git a/tpdatasrc/palcov/scr/Spell738 - Petrifying Gaze.py b/tpdatasrc/palcov/scr/Spell738 - Petrifying Gaze.py new file mode 100644 index 000000000..a6f7a3852 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell738 - Petrifying Gaze.py @@ -0,0 +1,70 @@ +from toee import * +from scripts import * + + +from utilities import float_num + + +def OnBeginSpellCast( spell ): + print "Petrifying Gaze OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-enchantment-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Petrifying Gaze OnSpellEffect" + + spell.dc = 13 + spell.duration = 100 + spell.caster_level = 10 + + if spell.caster.name == 14295: # basilisk + spell.dc = 19 + if spell.caster.name == 14987: # greater basilisk + spell.dc = 21 + + target = spell.target_list[0] + + num = 0 + num2 = 0 + target_list = list(game.obj_list_cone( spell.caster, OLC_CRITTERS, 60, -30, 60 )) +# print >> efile, "spell range= ", range, "\n" + target_list.remove(spell.caster) +# print >> efile, "target list: ", target_list, "\n" + for obj in target_list: + if not obj.is_friendly(spell.caster): + num = num + 1 + else: + target_list.remove(obj) + num = game.random_range(1,num) + for obj in target_list: + num2 = num2 + 1 + if num == num2: + target.obj = obj + +# print >> efile, "target.obj: ", target.obj, "\n" + + + if spell.caster.d20_query(Q_Critter_Is_Blinded): + spell.caster.float_mesfile_line( 'mes\\spell.mes', 20019 ) + elif target.obj.saving_throw( spell.dc, D20_Save_Fortitude, D20STD_F_NONE, spell.caster, D20A_CAST_SPELL ): + game.particles( 'sp-Shout', spell.caster ) + target.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + game.particles( 'Fizzle', target.obj ) + spell.target_list.remove_target( target.obj ) + else: + game.particles( 'sp-Shout', spell.caster ) + target.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + # HTN - apply condition HALT (Petrifyed) + target.obj.condition_add_with_args( 'sp-Command', spell.id, spell.duration, 4 ) + game.particles( "sp-Bestow Curse", target.obj ) + + spell.spell_end( spell.id ) +# efile.close() + + +def OnBeginRound( spell ): + print "Petrifying Gaze OnBeginRound" + +def OnEndSpellCast( spell ): + print "Petrifying Gaze OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell753 - Harpy Song.py b/tpdatasrc/palcov/scr/Spell753 - Harpy Song.py new file mode 100644 index 000000000..2e1600569 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell753 - Harpy Song.py @@ -0,0 +1,47 @@ +from toee import * + +def OnBeginSpellCast( spell ): + print "Fear OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + #game.particles( "sp-necromancy-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Harpy Song OnSpellEffect" + + #remove_list = [] + + npc = spell.caster + if npc.name == 14243: ## Harpy + spell.dc = 16 + + spell.duration = 5 + + game.sound(4300, 1) + + for target_item in spell.target_list: + if not target_item.obj in game.party[0].group_list(): + continue + if not target_item.obj.saving_throw_spell( spell.dc, D20_Save_Will, D20STD_F_NONE, spell.caster, spell.id ): + + # saving throw unsuccessful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30002 ) + + #target_item.obj.condition_add_with_args( 'Fascinate', spell.id, spell.duration, 0 ) + target_item.obj.condition_add_with_args( 'Captivating Song', spell.id, spell.duration, 0,0,0,0,0,0 ) + # target_item.partsys_id = game.particles( 'sp-Fear-Hit', target_item.obj ) + + else: + + # saving throw successful + target_item.obj.float_mesfile_line( 'mes\\spell.mes', 30001 ) + + + #spell.target_list.remove_list( remove_list ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Song OnBeginRound" + +def OnEndSpellCast( spell ): + print "Song OnEndSpellCast" \ No newline at end of file diff --git a/tpdatasrc/palcov/scr/Spell760 - Summon Familiar.py b/tpdatasrc/palcov/scr/Spell760 - Summon Familiar.py new file mode 100644 index 000000000..2e7e2cf68 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell760 - Summon Familiar.py @@ -0,0 +1,247 @@ +from toee import * +from utilities import * +from scripts import GetCritterHandle + +familiar_table = { +12045: 14990, +12046: 14991, +12047: 14992, +12048: 14993, +12049: 14994, +12050: 14995, +12051: 14996, +12052: 14997, +12053: 14998, +12054: 14999 +} + +def OnBeginSpellCast( spell ): + print "Summon Familiar OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + #game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect( spell ): + print "Summon Familiar OnSpellEffect" + + spell.duration = 2147483647 + master = spell.caster + + # get familiar inventory object handle + inv_proto = FindFamiliarProto( spell.caster, 0 ) + familiar = spell.caster.item_find_by_proto( inv_proto ) + if ( get_ID( familiar ) != 0 ): + return SKIP_DEFAULT + + # get the proto_id for this familiar + familiar_proto_id = FindFamiliarProto( spell.caster, 1 ) + if (familiar_proto_id == 0): # not a recognized familiar type + return SKIP_DEFAULT + + # creates random ID number + ID_number = game.random_range( 1,2147483647 ) + ID_number = ID_number^game.random_range( 1,2147483647 )#xor with next "random" number in line, should be more random + + # create familiar + spell.summon_monsters( 1, familiar_proto_id ) + + # get familiar's handle + familiar_obj = GetCritterHandle( spell, familiar_proto_id ) + + if ( familiar_obj == OBJ_HANDLE_NULL ): # no new familiar present + return SKIP_DEFAULT + + # summoning effect + #game.particles( 'Orb-Summon-Air-Elemental', familiar_obj ) + + # assigns familiar ownership + set_ID( familiar_obj, ID_number ) + set_ID( familiar, ID_number ) + + #game.particles( "sp-summon monster II", game.party[0] ) + + # sets familiar's stat's and bonuses depending on it's masters level + master_level = GetLevel( spell.caster ) + f_level = ( ( master_level + 1 ) / 2 ) + + f_hp = ( ( spell.caster.stat_level_get( stat_hp_max ) ) / 2 ) ## familiar's hp = i/2 masters hp + base_hp = familiar_obj.stat_level_get( stat_hp_max ) ## familiar's base hp from proto + prev_max_hp = familiar.obj_get_int( obj_f_item_pad_i_1 ) ## familiar's max hp from last time summoned ( 0 if never summoned before) + prev_curr_hp = familiar.obj_get_int( obj_f_item_pad_i_2 ) ## familiar's current xp from last time stowed ( 0 if never summoed before) + if ( base_hp <= f_hp ): ## if 1/2 master's hp is greater than base hp from proto, will use 1/2 masters hp + new_hp = familiar_obj.stat_base_set( stat_hp_max, f_hp ) + curr_max_hp = familiar_obj.stat_level_get( stat_hp_max ) ## familiar's max hp from current summons + hp_diff = ( curr_max_hp - prev_max_hp ) ## difference between max hp from last time summoned and max hp now ( 0 if master has not gained a level since) + if ( prev_max_hp != 0): ## has been summoned before + if ( hp_diff >=1 ): ## adds gained hp if master has gained hp since last time summoned + hp_now = prev_currr_hp + hp_diff + else: + hp_now = prev_curr_hp + dam = dice_new("1d1") + dam.num = curr_max_hp - hp_now + if (dam.num >= 1): + familiar_obj.damage(OBJ_HANDLE_NULL, D20DT_FORCE, dam, D20DAP_NORMAL) + + ## This next bit gives the familiar it's masters BAB. The familiar should have a BAB (without the masters BAB) of zero, but since + ## the game engine doesn't allow for Weapon Finesse with natural attacks( which would let the familiar use their dexterity modifier + ## instead of the strength modifier), I fiddled with the "to hit" in the protos to counteract the negative attack modifier do to + ## low strength and add the dexterity modifier. - Ceruleran the Blue ## + f_to_hit = spell.caster.stat_base_get(stat_attack_bonus) + + ## Remove the strength penalty and add the dex bonus to simulate weapon finesse, marc + ## Assumes all familars are using dex to hit and not strength. +# str = familiar_obj.stat_base_get(stat_strength) +# dex = familiar_obj.stat_base_get(stat_dexterity) +# adj = game.get_stat_mod(dex) - game.get_stat_mod(str) +# f_to_hit += adj + + new_to_hit = familiar_obj.condition_add_with_args( 'To Hit Bonus', f_to_hit, 0 ) + + new_int = familiar_obj.stat_base_set( stat_intelligence, ( 5 + f_level ) ) ## familiar INT bonus + + armor = familiar_obj.obj_set_int( obj_f_npc_ac_bonus, (f_level) ) ## Natrual Armor bonus + + if ( master_level >= 11 ): + spell_resistance = familiar_obj.condition_add_with_args( 'Monster Spell Resistance', ( 5 + master_level ), 0 ) ## spell resistance + + ## familiar uses masters saving throw bonuses if they are higher than it's own. + fortitude_bonus = Fortitude( spell.caster ) + if ( fortitude_bonus >= 3 ): + fortitude_save = familiar_obj.obj_set_int( obj_f_npc_save_fortitude_bonus, fortitude_bonus ) + reflex_bonus = Reflex( spell.caster ) + if ( reflex_bonus >= 3 ): + reflex_save = familiar_obj.obj_set_int( obj_f_npc_save_reflexes_bonus, reflex_bonus ) + will_bonus = Will( spell.caster ) + if ( will_bonus >= 1 ): + wlll_save = familiar_obj.obj_set_int( obj_f_npc_save_willpower_bonus, will_bonus ) + + # add familiar to follower list for spell_caster + if not ( spell.caster.follower_atmax() ): + spell.caster.follower_add( familiar_obj ) + else: + spell.caster.ai_follower_add( familiar_obj ) + + # add familiar_obj to d20initiative, and set initiative to spell_caster's + caster_init_value = spell.caster.get_initiative() + familiar_obj.add_to_initiative() + familiar_obj.set_initiative( caster_init_value ) + game.update_combat_ui() + + # familiar should disappear when duration is over, apply "TIMED_DISAPPEAR" condition + #familiar_obj.condition_add_with_args( 'sp-Summoned', spell.id, spell.duration, 0 ) + + # add familiar to target list + spell.num_of_targets = 1 + spell.target_list[0].obj = familiar_obj + + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + familiar_obj = spell.target_list[0].obj + if familiar_obj.stat_level_get(stat_hp_current) <= -10: + # Remove familiar if dead after one day. + game.timevent_add( RemoveDead, ( spell.caster, familiar_obj ), 86400000) # 1000 = 1 second + return + if familiar_obj not in game.party: + familiar_obj.destroy() + for f,p in familiar_table.items(): + itemA = spell.caster.item_find_by_proto( f ) + if itemA != OBJ_HANDLE_NULL: + clear_ID( itemA ) + print "Summon Familiar OnBeginRound" + +def OnEndSpellCast( spell ): + print "Summon Familiar OnEndSpellCast" + for f,p in familiar_table.items(): + itemA = spell.caster.item_find_by_proto( f ) + if itemA != OBJ_HANDLE_NULL: + clear_ID( itemA ) + +#################################################################################################### +# Functions Called in the Spell +#################################################################################################### + +def FindFamiliarProto( master, x ): +# Returns either the familiar creature's proto ID ( x = 1 ) or the familiar inventory object ( x = 0 ) + for f,p in familiar_table.items(): + itemC = master.item_find_by_proto( f ) + if ( itemC != OBJ_HANDLE_NULL ): + if x : + return p + else: + return f + return 0 + +def GetFamiliarHandle( spell, familiar_proto_id ): +# Returns a handle that can be used to manipulate the familiar creature object + for npc in game.obj_list_vicinity( spell.target_loc, OLC_CRITTERS ): + if (npc.name == familiar_proto_id): + if get_ID( npc ) == 0: + return npc + return OBJ_HANDLE_NULL + +def get_ID(obj): +# Returns embedded ID number + return obj.obj_get_int(obj_f_secretdoor_dc) + +def set_ID( obj, val ): +# Embeds ID number into mobile object. Returns ID number. + obj.obj_set_int( obj_f_secretdoor_dc, val ) + return obj.obj_get_int( obj_f_secretdoor_dc ) + +def clear_ID( obj ): +# Clears embedded ID number from mobile object + obj.obj_set_int( obj_f_secretdoor_dc, 0 ) + +def FindMaster( npc ): +# Not actually used in the spell, but could be handy in the future. Returns the character that is the master for a given summoned familiar ( npc ) + for p_master in game.obj_list_vicinity( npc.location, OLC_CRITTERS ): + for x,y in familiar_table.items(): + item = p_master.item_find_by_proto( x ) + if (item != OBJ_HANDLE_NULL): + if ( get_ID(item) == get_ID( npc ) ): + return p_master + return OBJ_HANDLE_NULL + +def GetLevel( npc ): +# Returns characters combined sorcerer and wizard levels + level = npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard) + return level + +def Fortitude( npc ): +# Returns Fortitude Save Bonus for all the casters class levels + bonus = 0 + level = npc.stat_level_get(stat_level_barbarian) + npc.stat_level_get(stat_level_cleric) + npc.stat_level_get(stat_level_druid) + npc.stat_level_get(stat_level_fighter) + npc.stat_level_get(stat_level_paladin) + npc.stat_level_get(stat_level_ranger) + npc.stat_level_get(stat_level_monk) + if ( level != 0 ): + bonus = ( ( level / 2 ) + 2 ) + level = npc.stat_level_get(stat_level_bard) + npc.stat_level_get(stat_level_rogue) + npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard) + if ( level != 0 ): + bonus = bonus + ( level / 3 ) + return bonus + +def Reflex( npc ): +# Returns Reflex Save Bonus for all the casters class levels + bonus = 0 + level = npc.stat_level_get(stat_level_barbarian) + npc.stat_level_get(stat_level_cleric) + npc.stat_level_get(stat_level_druid) + npc.stat_level_get(stat_level_fighter) + npc.stat_level_get(stat_level_paladin) + npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard) + if ( level != 0 ): + bonus = ( level / 3 ) + level = npc.stat_level_get(stat_level_ranger) + npc.stat_level_get(stat_level_rogue) + npc.stat_level_get(stat_level_monk) + npc.stat_level_get(stat_level_bard) + if ( level != 0 ): + bonus = bonus + ( ( level / 2 ) + 2 ) + return bonus + +def Will( npc ): +# Returns Will Save Bonus for all the casters class levels + bonus = 0 + level = npc.stat_level_get(stat_level_bard) + npc.stat_level_get(stat_level_cleric) + npc.stat_level_get(stat_level_druid) + npc.stat_level_get(stat_level_monk) + npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard) + if ( level != 0 ): + bonus = ( ( level / 2 ) + 2 ) + level = npc.stat_level_get(stat_level_barbarian) + npc.stat_level_get(stat_level_fighter) + npc.stat_level_get(stat_level_paladin) + npc.stat_level_get(stat_level_ranger) + npc.stat_level_get(stat_level_rogue) + if ( level != 0 ): + bonus = bonus + ( level / 3 ) + return bonus + +def RemoveDead(npc, critter): + if critter.stat_level_get(stat_hp_current) <= -10: + npc.follower_remove(critter) + return diff --git a/tpdatasrc/palcov/scr/Spell761 - Extraplanar Chest.py b/tpdatasrc/palcov/scr/Spell761 - Extraplanar Chest.py new file mode 100644 index 000000000..cf1e2ad35 --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell761 - Extraplanar Chest.py @@ -0,0 +1,321 @@ +from toee import * +from utilities import * +from scripts import readMes, writeMes, Timed_Destroy, End_Spell + +## Writen By Cerulean the Blue +# Modified by Sitra Achara 04-2011 + +# Miniature Chest internal flags: +# obj_f_item_pad_i_2 - miniature chest ID +# obj_f_item_pad_i_3 - indicates whether the chest can be summoned ("chest is in the Ethereal Plane (1) or in the Prime Plane (0) ") +# obj_f_item_pad_i_4 - Map # where the chest was summoned + +def OnBeginSpellCast( spell ): + print " Extraplanar Chest OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + game.particles( "sp-conjuration-conjure", spell.caster ) + +def OnSpellEffect ( spell ): + + print " Extraplanar Chest OnSpellEffect" + spell.duration = 1 + bgfilename = 'Bag_of_Holding.mes' + proto = 1100 + + mini = spell.caster.item_find(12901) + + if mini == OBJ_HANDLE_NULL: # Caster hasn't used spell before. Create miniature chest and subtract 5050 gold from caster + + if spell.caster.money_get() >= 505000: + mini = create_item_in_inventory( 12901, spell.caster ) + set_flag(mini, 0) # sets flag for chest on the Prime Material Plane + mini.item_flag_set( OIF_IDENTIFIED ) # Makes the mini identified. + spell.caster.money_adj(-505000) + chest = game.obj_create(proto, spell.caster.location) + create_item_in_inventory(11300, chest) # Create Leomund's Secret Chest note in new chest + game.particles( 'Orb-Summon-Balor', chest ) + bagnum = boh_newbag() # boh-newbag() is in Co8.py + Set_ID(mini, chest, bagnum) + else: + game.particles( 'Fizzle', spell.caster ) + + elif (Get_ID_Mini(mini) == 0): # Miniature found but never used before + + set_flag(mini, 0) # sets flag for chest on the Prime Material Plane + + bagnum = boh_newbag() # boh-newbag() is in Co8.py + chest = game.obj_create(proto, spell.caster.location) + create_item_in_inventory(11300, chest) # Create Leomund's Secret Chest note in new chest + game.particles( 'Orb-Summon-Balor', chest ) + Set_ID(mini, chest, bagnum) + set_mini_map(mini, chest) # record map where the chest was summoned - for forgetful players + + else: + + # Mini found and has been used before. + chest_here = 0 # flag for whether or not the right chest is in the casters vicinity + for chest in game.obj_list_vicinity( spell.caster.location, OLC_CONTAINER ): + # Find correct chest for that mini + if (chest.name == 1100 and Compare_ID(mini, chest)): + chest_here = 1 + cxx, cyy = location_to_axis(chest.location) + game.particles( 'Orb-Summon-Balor', chest ) + allBagDict = readMes(bgfilename) # readMes is in Co8.py. + bagnum = boh_newbag() # boh-newbag() is in Co8.py + Set_ID_Mini(mini, bagnum) + contents = GetContents(chest) + allBagDict[bagnum] = contents + writeMes(bgfilename, allBagDict) # writeMes is in Co8.py + set_flag(mini, 1) # Sets fkag flag for chest on Ethereal Plane + + # Time event added for chest destruction to allow time for game particles to fire + Timed_Destroy(chest, 500) # 500 = 1/2 second + + if ( not (chest_here) and get_flag(mini) ): # Chest not on this plane: create chest and fill it. + chest = game.obj_create(proto, spell.caster.location) + bagnum = Get_ID_Mini(mini) + Set_ID(mini, chest, bagnum) + set_flag(mini, 0) # sets flag for chest on the Prime Material Plane + set_mini_map(mini, chest) # record map where the chest was summoned - for forgetful players + + game.particles( 'Orb-Summon-Balor', chest ) + contents = boh_getContents(bagnum) # boh_getContents is in Co8.py + Create_Contents(contents, chest) + + elif ( not (chest_here) and not get_flag(mini) ): + miniature_chest_map_number = get_mini_map(mini) # retrieve map where the chest was summoned - for forgetful players + + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16015, 1 ) # "Chest left at:" + spell.caster.float_mesfile_line( 'mes\\map_names.mes', miniature_chest_map_number, 1 ) + spell.caster.float_mesfile_line( 'mes\\map_numbers.mes', miniature_chest_map_number, 1 ) + # failsaife: + # if you are on the same map, and your X,Y coordinates are close enough to where the chest was supposed to be, yet no chest was found, then it's probably a bug - reset the miniature to "Ethereal Plane" + # likewise, if for some reason the chest has no recorded X,Y at all, allow respawning it (mainly catering to r0gershrubber here :) ) + pxx, pyy = location_to_axis(spell.caster.location) + cxx, cyy = get_mini_xy(mini) + if ( ((pxx-cxx)**2) + ( (pyy-cyy)**2 )< 81 or cxx == 0 ) and game.leader.map == miniature_chest_map_number: + set_flag(mini, 1) + # error try again message + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16017, 1 ) # "Failsafe activated!" + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16018, 1 ) # "Try again." + elif miniature_chest_map_number in range(5070, 5079): + # lastly, if you lost it in the wilds, here's your second chance (exploitable, but it's easy enough to cheat in this game anyway) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16016, 1 ) # "LOST IN WILDERNESS!" + if not game.leader.map == miniature_chest_map_number: + set_flag(mini, 1) + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16017, 1 ) # "Failsafe activated!" + spell.caster.float_mesfile_line( 'mes\\spell.mes', 16018, 1 ) # "Try again." + + game.particles( 'Fizzle', spell.caster ) + + else: + game.particles( 'Fizzle', spell.caster ) + + End_Spell(spell) + + spell.spell_end(spell.id, 1) # fix - adding the endDespiteTargetList flag to force the spell_end and prevent the spell trigger from going on indefinitely + +def OnBeginRound( spell ): + print " Extraplanar Chest OnBeginRound" + return + +def OnEndSpellCast( spell ): + print " Extraplanar Chest OnEndSpellCast" + +def GetContents(chest): + # Gets contents of the chest by proto number and adds them to an ordered list. The list format is dynamic. + # Reads Exclude_List.mes. Items in the exclude list are not preserved in the contents of the chest. + # This is to prevent charged magic items from being recharged by being in the chest. Such items are lost if sent to the Ethereal Plane in the chest. + # Exclued list is not decoded because we only care about the dictionary keys (proto numbers). There is no need to decode the descriptions in the dictionary entries. + ExcludeDict = readMes('Exclude_List.mes') + exclude_list = ExcludeDict.keys() + contents = [] + # Look for proto number 4000-12999. These are the proto numbers for items that could be in the chest. + num = 4000 + while num <= 12999 : + # Check if proto number is on the exclude list + if num not in exclude_list: + item = chest.item_find_by_proto(num) + # Loop finding item to check for multiple occurences of the same item + while (item != OBJ_HANDLE_NULL): + # add the item to the list of contents + contents.append(num) + # check if item is stackable, and if so get the quantity stacked + quantity = 0 + type = item.type + if (type == obj_t_ammo): + quantity = item.obj_get_int(obj_f_ammo_quantity) + else: + quantity = item.obj_get_int(obj_f_item_quantity) + # if there is more than one in the stack, add the quantity to the contents list. Max quantity 3999 to keep quantity from matching any proto number in the list. + if ( quantity > 1 ): + if quantity >= 4000: + quantity = 3999 + contents.append(quantity) + # check to see if item is identified. If so, add the identified flag 1 to the list. + FLAGS = item.item_flags_get() + if (FLAGS & OIF_IDENTIFIED): + contents.append(1) + # destroy the item and check if there is another with the same proto number + item.destroy() + item = chest.item_find_by_proto(num) + num += 1 + # add "end of list" number to the end of the list. + contents.append(99999) + return contents + +def Create_Contents(contents, chest): + # Recreates the contents of the chest from the ordered list. + # Uses a "while" statement rather than a "for" statement in order to be able to step through the dynamic list. + i = 0 + while i in range(len(contents)): + # check to make sure we are looking at a proto number and not a quantity, identified flag, or end of list marker. + if (contents[i] >= 4000 and contents[i] != 99999): + #create item in chest + item = create_item_in_inventory( contents[i], chest ) + # step to the next number on the list + i += 1 + if i in range(len(contents)): # probably not necessary here, but keeps us safe. + # check to see if next number on the list is a quantity or identified flag + if contents[i] < 4000: + quantity = contents[i] + # check if item is ammo + if item.type == obj_t_ammo: + # check if "quantity" is actually a quantity and not an identified flag + if quantity > 1: + # "quantity" is a quantity, Set item quantity and step to next number on the list + item.obj_set_int(obj_f_ammo_quantity, quantity) + i += 1 + else: + # "quantity" is an identified flag. Set item quantity to 1. + item.obj_set_int(obj_f_ammo_quantity, 1) + # check if item is a potion, scroll or other stackable item. + else: + # check if "quantity" is actually a quantity and not an identified flag + if quantity > 1: + # "quantity" is a quantity, Set item quantity and step to next number on the list + item.obj_set_int(obj_f_item_quantity, quantity) + i += 1 + else: + # "quantity" is an identified flag. Set item quantity to 1. + item.obj_set_int(obj_f_item_quantity, 1) + if i in range(len(contents)): # is necessary here + # check if contents[i] is an identified flag. + if contents[i] == 1: + # flag item as identified and step to next number on the list. + item.item_flag_set( OIF_IDENTIFIED ) + i += 1 + else: + i += 1 + return + +def Set_ID(mini, chest, num): # Generates a random number and sets a field in the item, chest and caster to that number. + # ID_number = game.random_range( 1,2147483647 ) + # ID_number = ID_number^game.random_range( 1,2147483647 )#xor with next "random" number in line, should be more random + mini.obj_set_int(obj_f_item_pad_i_2, num) + chest.obj_set_int(obj_f_container_pad_i_1, num) + return num + +def Set_ID_Mini(mini, num): + mini.obj_set_int(obj_f_item_pad_i_2, num) + return mini.obj_get_int(obj_f_item_pad_i_2) + +def Get_ID_Mini(mini): # Reads the ID number of the miniature chest. + return mini.obj_get_int(obj_f_item_pad_i_2) + +def Compare_ID(mini, chest): # Compares the ID number of the large chest and the miniature chest. Returns 1 if they match, otherwise returns o. + if (mini.obj_get_int(obj_f_item_pad_i_2) == chest.obj_get_int(obj_f_container_pad_i_1)): + return 1 + else: + return 0 + +def set_flag(mini, x): # Store a flag in a field of the miniature chest. 1 means on the Ethereal Plane, 0 means on the Prime Material Plane. + mini.obj_set_int( obj_f_item_pad_i_3, x ) + return mini.obj_get_int( obj_f_item_pad_i_3 ) + +def get_flag(mini): # Reads a flag from a field of the miniature chest. + return mini.obj_get_int( obj_f_item_pad_i_3 ) + +def set_mini_map(mini, chest): + cxx, cyy = location_to_axis(chest.location) + mini.obj_set_int( obj_f_item_pad_i_4, mini.map ) + mini.obj_set_int( obj_f_item_pad_i_5, (cxx + (cyy << 10) ) ) + return mini.obj_get_int( obj_f_item_pad_i_4 ) + +def get_mini_map(mini): + return mini.obj_get_int( obj_f_item_pad_i_4 ) + +def get_mini_xy(mini): + return ( mini.obj_get_int( obj_f_item_pad_i_5 )>>10 , mini.obj_get_int( obj_f_item_pad_i_5 ) & ((2**10) -1) ) + + + +#------------------------------------------------------------------------------ +# Originally in Co8.py +#------------------------------------------------------------------------------ + +################################################################### +### (18:55 20/04/06) A script written by Glen Wheeler (Ugignadl) for manipulating ToEE files. +### Requested by Cerulean the Blue from Co8. +## +### (13:05 22/04/06) Added a few functions which should enable the implementation of a bag of +### holding. Some of them use the already written functions here (just import this scripts as a library). +################################################################### + +def boh_newbag(bagcontents=[11300], bagnum=0, bgfilename='Bag_of_Holding.mes'): + """ This function only takes keyword arguments. bagnum of 0 will ask the function to use the lowest available, otherwise will use that number. If it already exists the game will crash (deliberately, I can change that behaviour). bgfilename is the filename for all the bags. The contents should be a list (or tuple) of integers. Also, if you want each BOH to start with something inside them here is where you can do it (say with a note on how to use them, about the charged things being broken and crafted stuff etc). """ + # So we read in all the bags. + allBagDict = readMes(bgfilename) + # Then insert the new bag. + linenumbers = allBagDict.keys() + if bagnum: + if bagnum in allBagDict: + raise 'BadbagnumError' + else: + bagnum = 1 + while bagnum in linenumbers: + bagnum += 1 + + allBagDict[bagnum] = bagcontents + # Then write it all back again. + # writeMes(bgfilename, allBagDict) + # print 'New Bag' + return bagnum + +def boh_getContents(bagnum, bgfilename='Bag_of_Holding.mes'): + """ This can be called when opening the bag. The bag filename is (I am assuming) fixed, but can be set by passing a keyword argument. bagnum is the line number to use for that bag in the bgfilename. """ + allBagDict = readMes(bgfilename) + # Note: If bagnum is not an integer we will have a CTD. I can fix this if it is the case by coercing the datatype. + contents = __boh_decode(allBagDict[bagnum]) + # contents will be an ordered list of integers, ready to be turned into objects. + # print ' Get Contents' + return contents + +def __boh_decode(bohcontents): + """ bohcontents should just be a comma delimited series of integers. We don't have any more support than that (CB: if we have more complex data types in the bag in future then this is the function to be changed.) Sub-bags (i.e. BOH within BOH) could be implemented by decoding lists within lists. However I'm not even sure that is in accordance with the rules. """ + # [0] is there to comply with the output of the readMes function. + l = bohcontents[0].split(', ') + for i in range(len(l)): + # This should cause a crash, but I am testing with non-integers. If you want to be hardcore then just remove the try--except. + try: + l[i] = int(l[i]) + except: + print "WARNING: NON-INTEGER FOUND IN BAG OF HOLDING!" + print 'Non-integer found is', l[i] + # print 'Decoded' + return l + +def _boh_removeitem(bagnum, itemnum, bgfilename='Bag_of_Holding.mes'): + """ Remove the item itemnum from the bag bagnum. If it's not in there we get a (deliberate) crash. """ + allBagDict = readMes(bgfilename) + contents.remove(itemnum) + allBagDict[bagnum] = contents + writeMes(bgfilename, allBagDict) + +def _boh_insertitem(bagnum, itemnum, bgfilename='Bag_of_Holding.mes'): + """ This function will insert the integer itemnum at the end of the list associated with bagnum in bgfilename. """ + allBagDict = readMes(bgfilename) + contents.append(itemnum) + allBagDict[bagnum] = contents + writeMes(bgfilename, allBagDict) diff --git a/tpdatasrc/palcov/scr/Spell775 - Resonance.py b/tpdatasrc/palcov/scr/Spell775 - Resonance.py new file mode 100644 index 000000000..e17a1f45e --- /dev/null +++ b/tpdatasrc/palcov/scr/Spell775 - Resonance.py @@ -0,0 +1,37 @@ +from toee import * +from utilities import * + +def OnBeginSpellCast( spell ): + print "Resonance OnBeginSpellCast" + print "spell.target_list=", spell.target_list + print "spell.caster=", spell.caster, " caster.level= ", spell.caster_level + +def OnSpellEffect( spell ): + print "Resonance OnSpellEffect" + target_item = spell.target_list[0] + caster = spell.caster + + isValid = 0 + if caster.stat_level_get(stat_level_wizard) >= 1: + caster.spells_pending_to_memorized(stat_level_wizard) + isValid = 1 + if caster.stat_level_get(stat_level_bard) >= 1: + caster.spells_cast_reset(stat_level_bard) + isValid = 1 + if caster.stat_level_get(stat_level_sorcerer) >= 1: + caster.spells_cast_reset(stat_level_sorcerer) + isValid = 1 + + if isValid: + print "doing spells pending to memorized for spell caster" + game.particles( 'sp-Read Magic', caster ) + else: + game.particles( 'Fizzle', caster ) + spell.target_list.remove_target( target_item.obj ) + spell.spell_end( spell.id ) + +def OnBeginRound( spell ): + print "Resonance OnBeginRound" + +def OnEndSpellCast( spell ): + print "Resonance OnEndSpellCast"