class EvilEye( base.Monster ): name = "Evil Eye" statline = { stats.STRENGTH: 6, stats.TOUGHNESS: 12, stats.REFLEXES: 12, \ stats.INTELLIGENCE: 10, stats.PIETY: 10, stats.CHARISMA: 2, \ stats.MAGIC_ATTACK: 20, stats.MAGIC_DEFENSE: 10 } SPRITENAME = "monster_default.png" FRAME = 18 TEMPLATES = () MOVE_POINTS = 6 VOICE = None HABITAT = ( context.HAB_CAVE, context.HAB_TUNNELS, context.SET_EVERY, context.DES_LUNAR, context.MTY_BOSS, context.MTY_BEAST, context.GEN_CHAOS ) ENC_LEVEL = 3 ATTACK = items.Attack( (2,4,0), element = stats.RESIST_LUNAR, skill_mod=stats.REFLEXES, hit_anim=animobs.PurpleExplosion, extra_effect = effects.OpposedRoll( att_stat=stats.REFLEXES, def_stat=stats.REFLEXES, on_success = ( effects.Paralyze( max_duration = 3 ) ,) ) ) TECHNIQUES = ( invocations.MPInvocation( "Evil Gaze", effects.OpposedRoll( att_stat=stats.REFLEXES, def_stat=stats.REFLEXES, att_modifier=10, on_success = ( effects.Paralyze( max_duration = 3 ) ,), on_failure = ( effects.NoEffect( anim=animobs.SmallBoom ) ,) ), com_tar=targetarea.SingleTarget(reach=4), shot_anim=animobs.PurpleVortex, ai_tar=invocations.TargetMobileEnemy(), mp_cost=3 ), ) def init_monster( self ): self.levels.append( base.Beast( 3, self ) )
class CorpseEater( base.Monster ): name = "Corpse Eater" statline = { stats.STRENGTH: 12, stats.TOUGHNESS: 14, stats.REFLEXES: 8, \ stats.INTELLIGENCE: 2, stats.PIETY: 12, stats.CHARISMA: 2 } SPRITENAME = "monster_default.png" FRAME = 13 TEMPLATES = (stats.BUG,) MOVE_POINTS = 8 VOICE = None HABITAT = ( context.HAB_EVERY, context.HAB_TUNNELS, context.SET_EVERY, context.MAP_DUNGEON, context.DES_LUNAR, context.MTY_BEAST ) ENC_LEVEL = 4 ATTACK = items.Attack( (3,4,0), element = stats.RESIST_PIERCING, extra_effect = effects.OpposedRoll( att_stat=stats.TOUGHNESS, on_success = ( effects.Paralyze( max_duration = 6 ) ,) ) ) TECHNIQUES = ( invocations.MPInvocation( "Tentacle Slime", effects.TargetIsEnemy( on_true = ( effects.OpposedRoll( anim=animobs.GreenSplat, att_stat=stats.TOUGHNESS, on_success = ( effects.Paralyze( max_duration = 3 ) ,), on_failure = ( effects.NoEffect( anim=animobs.SmallBoom ) ,) ), ) ), com_tar=targetarea.SelfCentered(radius=1,exclude_middle=True), ai_tar=invocations.TargetEnemy(), mp_cost=8 ), ) def init_monster( self ): self.levels.append( base.Beast( 4, self ) )
class CultLeader(base.Monster): name = "Cult Leader" statline = { stats.STRENGTH: 12, stats.TOUGHNESS: 12, stats.REFLEXES: 12, \ stats.INTELLIGENCE: 10, stats.PIETY: 10, stats.CHARISMA: 16, \ stats.PHYSICAL_ATTACK: 5 } SPRITENAME = "monster_chaos.png" FRAME = 2 TEMPLATES = () MOVE_POINTS = 10 HABITAT = (context.HAB_EVERY, context.HAB_BUILDING, context.SET_EVERY, context.MAP_DUNGEON, context.MTY_HUMANOID, context.MTY_PRIEST, context.GEN_CHAOS) ENC_LEVEL = 3 LONER = True TREASURE = treasuretype.High() COMPANIONS = (Cultist, Cultist, Heretic, people.NoviceWarrior) TECHNIQUES = (spells.solarspells.MODERATE_CURE, spells.lunarspells.WIZARD_MISSILE) ATTACK = items.Attack((1, 6, 0), element=stats.RESIST_CRUSHING, extra_effect=effects.OpposedRoll( on_success=(effects.Paralyze(max_duration=6), ))) def init_monster(self): self.levels.append(base.Leader(3, self))
class ShieldOfBashing(Enhancer): NAMEPAT = "{0} of Bashing" DESCPAT = "{0} It may be used to bash enemies, doing 2d6 damage and potentially stunning them." PLUSRANK = 2 AFFECTS = (SHIELD, ) TECH = (invocations.MPInvocation( "Shield Bash", effects.PhysicalAttackRoll( att_stat=stats.STRENGTH, on_success=( effects.HealthDamage((2, 6, 0), stat_bonus=stats.STRENGTH, element=stats.RESIST_CRUSHING, stat_mod=2, anim=animobs.RedBoom), effects.OpposedRoll( att_skill=stats.PHYSICAL_ATTACK, def_stat=stats.TOUGHNESS, on_success=(effects.Paralyze(max_duration=3), )), ), on_failure=(effects.NoEffect(anim=animobs.SmallBoom), )), com_tar=targetarea.SingleTarget(reach=1), ai_tar=invocations.TargetEnemy(), mp_cost=3), ) TYPE = ET_SECONDARY
class YoungCaveDragon(base.Monster): name = "Young Cave Dragon" statline = { stats.STRENGTH: 11, stats.TOUGHNESS: 13, stats.REFLEXES: 10, \ stats.INTELLIGENCE: 10, stats.PIETY: 11, stats.CHARISMA: 10, stats.RESIST_POISON: 100 } SPRITENAME = "monster_dragons.png" FRAME = 2 TEMPLATES = (stats.DRAGON, ) MOVE_POINTS = 8 VOICE = dialogue.voice.DRACONIAN HABITAT = (context.HAB_EVERY, context.SET_EVERY, context.HAB_CAVE, context.MAP_DUNGEON, context.MTY_DRAGON, context.MTY_BOSS, context.DES_EARTH, context.GEN_DRAGON) ENC_LEVEL = 4 COMBAT_AI = aibrain.BruiserAI() TREASURE = treasuretype.DragonHoard() ATTACK = items.Attack((3, 4, 0), element=stats.RESIST_SLASHING) TECHNIQUES = (invocations.MPInvocation( "Toxic Breath", effects.OpposedRoll(def_stat=stats.TOUGHNESS, anim=animobs.PoisonCloud, on_success=(effects.Paralyze(max_duration=3), )), com_tar=targetarea.Cone(reach=4), ai_tar=invocations.TargetEnemy(), mp_cost=4), ) def init_monster(self): self.levels.append(base.Terror(4, self))
class FrostWepEn( Enchantment ): NAME = "Frost Weapon" def __init__( self ): super(FrostWepEn, self).__init__(statline=stats.StatMod({stats.PHYSICAL_ATTACK:5,stats.RESIST_FIRE:5}),dispel=(COMBAT,MAGIC)) ATTACK_ON_HIT = effects.HealthDamage( (1,10,0), stat_bonus=None, element=stats.RESIST_COLD, anim=animobs.BlueExplosion, on_success=( effects.OpposedRoll( on_success = ( effects.Paralyze( max_duration = 3 ), )),) )
class Avoral(base.Monster): name = "Avoral" statline = { stats.STRENGTH: 15, stats.TOUGHNESS: 20, stats.REFLEXES: 23, \ stats.INTELLIGENCE: 15, stats.PIETY: 16, stats.CHARISMA: 16, \ stats.AWARENESS: 65, stats.MAGIC_DEFENSE: 25 } SPRITENAME = "monster_celestial.png" FRAME = 12 TEMPLATES = (stats.CELESTIAL, stats.AIR) MOVE_POINTS = 16 HABITAT = (context.SET_EVERY, context.DES_SOLAR, context.DES_AIR, context.MTY_HUMANOID, context.MTY_CELESTIAL) ENC_LEVEL = 12 COMBAT_AI = aibrain.ArcherAI() TREASURE = treasuretype.Standard() TECHNIQUES = (invocations.Invocation("Avoral Missile", effects.HealthDamage( (1, 8, 0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_LUNAR, anim=animobs.PurpleExplosion), com_tar=targetarea.SingleTarget(), shot_anim=animobs.WizardMissile, ai_tar=invocations.TargetEnemy()), invocations.Invocation( "Hold Person", effects.OpposedRoll( att_modifier=20, on_success=(effects.Paralyze(max_duration=3), ), on_failure=(effects.NoEffect( anim=animobs.SmallBoom), )), com_tar=targetarea.SingleTarget(), shot_anim=animobs.BlueComet, ai_tar=invocations.TargetMobileEnemy()), invocations.MPInvocation( "Thunder Strike", effects.OpposedRoll(on_success=(effects.HealthDamage( (3, 6, 0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_LIGHTNING, anim=animobs.Spark), ), on_failure=(effects.HealthDamage( (1, 8, 0), stat_bonus=None, element=stats.RESIST_LIGHTNING, anim=animobs.Spark), )), mp_cost=16, com_tar=targetarea.Line(), ai_tar=invocations.TargetEnemy())) ATTACK = items.Attack((2, 8, 0), element=stats.RESIST_SLASHING) def init_monster(self): self.levels.append(base.Terror(7, self))
class FrostWand(ManaWeapon): true_name = "Frost Wand" true_desc = "On a successful hit, this wand may freeze its target solid for a short time." itemtype = WAND MP_COST = 1 avatar_image = "avatar_wand.png" avatar_frame = 12 mass = 5 attackdata = Attack( (3,4,0), skill_mod=stats.REFLEXES, damage_mod=stats.INTELLIGENCE, \ element=stats.RESIST_COLD, reach=7, hit_anim=animobs.BlueExplosion, shot_anim = animobs.BlueBolt, extra_effect=effects.OpposedRoll( on_success = ( effects.Paralyze( max_duration = 3 ) ,)) )
class FreezingAmmo(Enhancer): NAMEPAT = "Freezing {0}" DESCPAT = "{0} They do an extra 1d4 cold damage and may freeze their target in place." PLUSRANK = 2 AFFECTS = (ARROW, BULLET) ATTACK_ON_HIT = effects.HealthDamage( (1, 4, 0), stat_bonus=None, element=stats.RESIST_COLD, anim=animobs.BlueExplosion, on_success=(effects.OpposedRoll( att_modifier=-20, on_success=(effects.Paralyze(max_duration=3), )), ))
class GreatCaveWyrm(base.Monster): name = "Great Cave Wyrm" statline = { stats.STRENGTH: 27, stats.TOUGHNESS: 21, stats.REFLEXES: 10, \ stats.INTELLIGENCE: 16, stats.PIETY: 17, stats.CHARISMA: 16, stats.PHYSICAL_ATTACK: 20, stats.RESIST_POISON: 100 } SPRITENAME = "monster_dragons.png" FRAME = 42 TEMPLATES = (stats.DRAGON, ) MOVE_POINTS = 10 VOICE = dialogue.voice.DRACONIAN HABITAT = (context.HAB_EVERY, context.SET_EVERY, context.HAB_CAVE, context.MAP_DUNGEON, context.MTY_LEADER, context.MTY_DRAGON, context.MTY_BOSS, context.DES_EARTH, context.GEN_DRAGON) ENC_LEVEL = 20 COMBAT_AI = aibrain.BruiserAI() TREASURE = treasuretype.DragonHoard() LONER = True COMPANIONS = ( OldCaveDragon, AncientCaveDragon, ) ATTACK = items.Attack((7, 8, 0), element=stats.RESIST_SLASHING, extra_effect=abilities.POISON_ATTACK_2d6) TECHNIQUES = (invocations.MPInvocation( "Toxic Breath", effects.OpposedRoll(def_stat=stats.TOUGHNESS, anim=None, on_success=( effects.HealthDamage( (9, 6, 0), stat_bonus=None, element=stats.RESIST_POISON, anim=animobs.PoisonCloud), effects.Paralyze(max_duration=3), effects.Enchant(enchantments.PoisonClassic, anim=animobs.DeathSparkle), ), on_failure=(effects.HealthDamage( (3, 9, 0), stat_bonus=None, element=stats.RESIST_POISON, anim=animobs.PoisonCloud), )), com_tar=targetarea.Cone(reach=8), ai_tar=invocations.TargetEnemy(), mp_cost=38), ) def init_monster(self): self.levels.append(base.Terror(28, self))
class IceFox(base.Monster): name = "Ice Fox" statline = { stats.STRENGTH: 12, stats.TOUGHNESS: 13, stats.REFLEXES: 13, \ stats.INTELLIGENCE: 3, stats.PIETY: 12, stats.CHARISMA: 15 } SPRITENAME = "monster_animals.png" FRAME = 27 TEMPLATES = (stats.ICE, ) MOVE_POINTS = 10 VOICE = None HABITAT = (context.HAB_EVERY, context.SET_EVERY, context.MAP_WILDERNESS, context.DES_ICE, context.MTY_BEAST, context.MTY_CREATURE, context.MTY_BOSS, context.GEN_NATURE) ENC_LEVEL = 4 ATTACK = items.Attack( (1, 6, 0), element=stats.RESIST_PIERCING, extra_effect=effects.OpposedRoll(att_stat=None, att_modifier=5, on_success=( effects.HealthDamage( (1, 6, 0), stat_bonus=None, element=stats.RESIST_COLD, anim=animobs.SnowCloud), effects.Paralyze(max_duration=6), ))) TECHNIQUES = (invocations.MPInvocation( "Frost Breath", effects.OpposedRoll(att_skill=stats.PHYSICAL_ATTACK, att_stat=stats.REFLEXES, def_stat=stats.REFLEXES, on_success=(effects.HealthDamage( (1, 6, 0), stat_bonus=stats.TOUGHNESS, element=stats.RESIST_COLD, anim=animobs.BlueCloud), ), on_failure=(effects.HealthDamage( (1, 3, 0), stat_bonus=None, element=stats.RESIST_COLD, anim=animobs.BlueCloud), )), com_tar=targetarea.Cone(reach=4), ai_tar=invocations.TargetEnemy(), mp_cost=3), ) def init_monster(self): self.levels.append(base.Beast(4, self))
class HolyBow(Enhancer): NAMEPAT = "Holy {0}" DESCPAT = "{0} A hit from this weapon may disrupt unholy creatures." PLUSRANK = 5 AFFECTS = (BOW, SLING) ATTACK_ON_HIT = effects.TargetIs( effects.UNHOLY, on_true=(effects.OpposedRoll( att_stat=stats.PIETY, att_modifier=-10, on_success=(effects.InstaKill(anim=animobs.CriticalHit), ), on_failure=(effects.OpposedRoll( att_modifier=10, on_success=(effects.Paralyze(max_duration=3), ), ), ), ), )) BONUSES_PER_RANK = stats.StatMod({ stats.PHYSICAL_ATTACK: 10, stats.RESIST_LUNAR: 25 }) TYPE = ET_SECONDARY
class Ghoul( base.Monster ): name = "Ghoul" statline = { stats.STRENGTH: 13, stats.TOUGHNESS: 15, stats.REFLEXES: 8, \ stats.INTELLIGENCE: 11, stats.PIETY: 10, stats.CHARISMA: 4 } SPRITENAME = "monster_undead.png" FRAME = 35 TEMPLATES = (stats.UNDEAD,stats.FLESHY) MOVE_POINTS = 8 VOICE = None HABITAT = ( context.HAB_EVERY, context.HAB_TUNNELS, context.SET_EVERY, context.MTY_UNDEAD, context.DES_LUNAR, context.GEN_UNDEAD ) ENC_LEVEL = 4 TREASURE = treasuretype.Standard() COMPANIONS = (Zombie,animals.PlagueRat) COMBAT_AI = aibrain.GhoulAI() ATTACK = items.Attack( (1,8,0), element = stats.RESIST_CRUSHING, extra_effect = effects.OpposedRoll( att_modifier=-10, on_success = ( effects.Paralyze( max_duration = 6 ) ,) ) ) def init_monster( self ): self.levels.append( base.Humanoid( 3, self ) )
class HolyWeapon(Enhancer): NAMEPAT = "Holy {0}" DESCPAT = "{0} It does an extra 1d8 holy damage and disrupts unholy creatures." PLUSRANK = 5 AFFECTS = (SWORD, AXE, MACE, DAGGER, STAFF, POLEARM, FARMTOOL, LANCE) ATTACK_ON_HIT = effects.HealthDamage( (1, 8, 0), stat_bonus=None, element=stats.RESIST_SOLAR, anim=animobs.YellowExplosion, on_success=(effects.TargetIs( effects.UNHOLY, on_true=(effects.OpposedRoll( att_stat=stats.PIETY, att_modifier=-20, on_success=(effects.InstaKill(anim=animobs.CriticalHit), ), on_failure=(effects.OpposedRoll(on_success=(effects.Paralyze( max_duration=3), ), ), )), )), )) BONUSES_PER_RANK = stats.StatMod({ stats.PHYSICAL_ATTACK: 5, stats.RESIST_LUNAR: 25 }) TYPE = ET_SECONDARY
class Beastman(base.Monster): name = "Beastman" statline = { stats.STRENGTH: 12, stats.TOUGHNESS: 14, stats.REFLEXES: 14, \ stats.INTELLIGENCE: 9, stats.PIETY: 6, stats.CHARISMA: 8 } SPRITENAME = "monster_chaos.png" FRAME = 3 TEMPLATES = () MOVE_POINTS = 12 TREASURE = treasuretype.Standard() HABITAT = (context.HAB_EVERY, context.SET_EVERY, context.MAP_WILDERNESS, context.DES_LUNAR, context.MTY_HUMANOID, context.MTY_FIGHTER, context.GEN_CHAOS) ENC_LEVEL = 4 COMPANIONS = (Hooligan, ) TECHNIQUES = (invocations.MPInvocation( "Headbutt", effects.PhysicalAttackRoll( att_stat=stats.STRENGTH, on_success=( effects.HealthDamage((1, 10, 0), stat_bonus=stats.STRENGTH, element=stats.RESIST_CRUSHING, stat_mod=2, anim=animobs.RedBoom), effects.OpposedRoll( att_skill=stats.PHYSICAL_ATTACK, def_stat=stats.TOUGHNESS, on_success=(effects.Paralyze(max_duration=3), )), ), on_failure=(effects.NoEffect(anim=animobs.SmallBoom), )), com_tar=targetarea.SingleTarget(reach=1), ai_tar=invocations.TargetEnemy(), mp_cost=5), ) ATTACK = items.Attack((1, 8, 0), element=stats.RESIST_SLASHING) def init_monster(self): self.levels.append(base.Humanoid(4, self))
class Umbull( base.Monster ): name = "Umbull" statline = { stats.STRENGTH: 23, stats.TOUGHNESS: 19, stats.REFLEXES: 13, \ stats.INTELLIGENCE: 9, stats.PIETY: 11, stats.CHARISMA: 13 } SPRITENAME = "monster_default.png" FRAME = 4 TEMPLATES = () MOVE_POINTS = 8 HABITAT = ( context.HAB_CAVE, context.SET_EVERY, context.MAP_DUNGEON, context.DES_EARTH ) ENC_LEVEL = 9 COMBAT_AI = aibrain.BruiserAI() TREASURE = treasuretype.Standard() ATTACK = items.Attack( (3,6,0), element = stats.RESIST_SLASHING ) TECHNIQUES = (invocations.Invocation( "Freezing Gaze", effects.OpposedRoll( att_modifier=20, on_success = ( effects.Paralyze( max_duration = 6 ) ,), on_failure =( effects.NoEffect( anim=animobs.SmallBoom ) ,) ), com_tar=targetarea.SingleTarget(), shot_anim=animobs.PurpleVortex, ai_tar=invocations.TargetMobileEnemy() ), ) def init_monster( self ): self.levels.append( base.Defender( 9, self ) )
self.paralysis = 0 self.confusion = 0 self.asleep = False self.silent = False self.aoo_readied = False self.attacks_so_far = 0 def can_act( self ): return self.paralysis < 1 and not self.asleep # This is a complex effect- Check if target is undead. If so, first apply an # enchantment. Then, make skill roll to cause 20-120 solar damage and paralysis. # If that skill roll fails, make an easier skill roll to just cause paralysis. HOLY_SIGN_EFFECT = effects.TargetIs( effects.UNDEAD, on_true = ( \ effects.Enchant(enchantments.HolySignMark,anim=animobs.YellowSparkle,children=( \ effects.OpposedRoll(stats.HOLY_SIGN, stats.CHARISMA, -70, stats.MAGIC_DEFENSE, stats.PIETY, on_success = ( effects.HealthDamage( (20,6,0), stats.PIETY, element=stats.RESIST_SOLAR, anim=animobs.YellowExplosion, on_success= (effects.Paralyze(max_duration=6),) ) ,), on_failure = ( effects.OpposedRoll(stats.HOLY_SIGN, stats.CHARISMA, 5, stats.MAGIC_DEFENSE, stats.PIETY, on_success = ( effects.Paralyze(max_duration=8) # Is there an obfuscated Python competition? ,)),)),)),)) class Combat( object ): def __init__( self, camp, monster_zero ): self.active = [] self.scene = camp.scene self.camp = camp self.ap_spent = collections.defaultdict( int ) self.cstat = collections.defaultdict( CombatStat ) self.no_quit = True
"Magical flames burst from an ally's weapon, causing an extra 1-6 points of damge per hit. This effect lasts until the end of combat.", effects.Enchant(enchantments.FireWepEn, anim=animobs.RedSparkle), rank=1, gems={FIRE: 1}, com_tar=targetarea.SinglePartyMember(), ai_tar=invocations.TargetAllyWithoutEnchantment(enchantments.FireWepEn)) # CIRCLE 2 BLINDING_FLASH = Spell( "Blinding Flash", "A sudden flash of light will daze, and possibly stun, all enemies within 4 tiles.", effects.TargetIsEnemy(on_true=( effects.Enchant(enchantments.BlindedEn, anim=animobs.RedSparkle), effects.OpposedRoll(att_modifier=-20, on_success=(effects.Paralyze(max_duration=2), )))), rank=2, gems={FIRE: 2}, com_tar=targetarea.SelfCentered(radius=4), ai_tar=invocations.TargetEnemy()) IGNITE = Spell( "Ignite", "You touch one opponent, causing them to burst into flame. The target suffers 2d5 fire damage and may continue burning.", effects.OpposedRoll(on_success=( effects.HealthDamage((2, 5, 0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_FIRE, anim=animobs.Ignite), effects.Enchant(enchantments.BurnLowEn), ),
"You conjure dark forces to animate a skeleton which will fight on your behaf.", effects.CallMonster( {context.MTY_UNDEAD: True, context.DES_LUNAR: context.MAYBE, context.GEN_UNDEAD: context.MAYBE}, 2, anim=animobs.PurpleSparkle ), rank=1, gems={EARTH:1,LUNAR:1}, com_tar=targetarea.SingleTarget(reach=2), ai_tar=invocations.TargetEmptySpot() ) # CIRCLE 2 RAISE_CORPSE = Spell( "Raise Corpse", "You conjure dark forces to animate a lesser undead creature which will fight on your behaf.", effects.CallMonster( {context.MTY_UNDEAD: True, context.DES_LUNAR: context.MAYBE, context.GEN_UNDEAD: context.MAYBE}, 4, anim=animobs.PurpleSparkle ), rank=2, gems={EARTH:1,LUNAR:1}, com_tar=targetarea.SingleTarget(reach=2), ai_tar=invocations.TargetEmptySpot(), mpfudge=4 ) TOUCH_OF_DEATH = Spell( "Touch of Death", "You touch one opponent, delivering the chill of the grave. The target suffers 2d5 cold damage and may be paralyzed.", effects.OpposedRoll( att_modifier=10, on_success = ( effects.HealthDamage( (2,5,0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_COLD, anim=animobs.BlueExplosion ), effects.Paralyze( max_duration = 3 ) ,), on_failure = ( effects.HealthDamage( (2,5,0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_COLD, anim=animobs.BlueExplosion ) ,) ), rank=2, gems={LUNAR:1,WATER:1}, com_tar=targetarea.SingleTarget(reach=1),ai_tar=invocations.TargetEnemy(), mpfudge=-2 ) # CIRCLE 3 ACID_CLOUD = Spell( "Acid Cloud", "Calls forth billowing clouds of acid which do 2d6 damage to all targets within 3 tiles.", effects.OpposedRoll( on_success = ( effects.HealthDamage( (2,6,0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_ACID, anim=animobs.GreenCloud ) ,), on_failure = ( effects.HealthDamage( (1,6,0), stat_bonus=None, element=stats.RESIST_ACID, anim=animobs.GreenCloud ) ,) ), rank=3, gems={EARTH:1,LUNAR:1}, com_tar=targetarea.Blast(radius=3), shot_anim=animobs.GreenComet, ai_tar=invocations.TargetEnemy(min_distance=4) )
}, com_tar=targetarea.Blast(radius=4, delay_from=1), ai_tar=invocations.TargetEnemy(min_distance=5)) DIVINE_HAMMER = Spell( "Divine Hammer", "This attack does 4d8 holy damage to a single target. Unholy creatures may be stunned.", effects.OpposedRoll( def_stat=stats.REFLEXES, on_success=( effects.HealthDamage((4, 8, 0), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_SOLAR, anim=animobs.RedBoom), effects.TargetIs(pat=effects.UNHOLY, on_true=(effects.Paralyze(max_duration=3), )), ), on_failure=(effects.HealthDamage((2, 8, 2), stat_bonus=stats.INTELLIGENCE, element=stats.RESIST_SOLAR, anim=animobs.RedBoom), )), rank=4, gems={ AIR: 1, SOLAR: 1 }, com_tar=targetarea.SingleTarget(), shot_anim=animobs.YellowVortex, ai_tar=invocations.TargetEnemy()) SANCTUARY = Spell(