""" #************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ #************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #*********** * Ported to Python by Davion of MudBytes.net * Using Miniboa https://code.google.com/p/miniboa/ * Now using Python 3 version https://code.google.com/p/miniboa-py3/ ************/ """ from merc import * from handler import * from fight import update_pos, is_safe, is_safe_spell, check_killer, multi_hit from skills import check_improve import const def say_spell(ch, spell): syl_dict = {"ar":"abra", "au":"kada", "bless":"fido", "blind":"nose", "bur":"mosa", "cu":"judi", "de":"oculo", "en":"unso", "light":"dies", "lo":"hi", "mor":"zak", "move":"sido", "ness":"lacri", "ning":"illa", "per":"duda", "ra":"gru", "fresh":"ima", "re":"candus", "son":"sabru", "tect":"infra", "tri":"cula", "ven":"nofo", "a":"a", "b":"b", "c":"q", "d":"e", "e":"z", "f":"y", "g":"o", "h":"p", "i":"u", "j":"y", "k":"t", "l":"r", "m":"w", "n":"i", "o":"a", "p":"s", "q":"d", "r":"f", "s":"g", "t":"h", "u":"j", "v":"z", "w":"x", "x":"n", "y":"l", "z": "k" } incantation = mass_replace(spell.name, syl_dict) buf = "$n utters the words, '%s'." % incantation buf2 = "$n utters the words, '%s'." % spell.name for rch in ch.in_room.people: send = buf2 if ch.guild==rch.guild else buf act(send, ch, None, rch, TO_VICT) def saves_spell(level, victim, dam_type): save = 50 + ( victim.level - level) * 5 - victim.saving_throw * 2 if IS_AFFECTED(victim, AFF_BERSERK): save += victim.level//2 immunity = victim.check_immune(dam_type) if immunity == IS_IMMUNE: return True elif immunity == IS_RESISTANT: save += 2 elif immunity == IS_VULNERABLE: save -= 2 if not IS_NPC(victim) and victim.guild.fMana: save = 9 * save // 10 save = max( 5, min(save, 95 ) ) return random.randint(1,99) < save def saves_dispel(dis_level, spell_level, duration): if duration == -1: spell_level += 5 # very hard to dispel permanent effects */ save = 50 + (spell_level - dis_level) * 5 save = max( 5, min(save, 95 ) ) return random.randint(1,99) < save def check_dispel(dis_level, victim, skill): if is_affected(victim, skill): for af in victim.affected[:]: if af.type == skill: if not saves_dispel(dis_level,af.level,af.duration): victim.affect_strip(sn) if skill.msg_off: victim.send(const._table[sn].msg_off + "\n") return True else: af.level -= 1 return False # for finding mana costs -- temporary version */ def mana_cost (ch, min_mana, level): if ch.level + 2 == level: return 1000 return max(min_mana, (100 // (2 + ch.level - level))) def find_spell(ch, name): #* finds a spell the character can cast if possible */ found = -1 if IS_NPC(ch): return prefix_lookup(const.skill_table,name) for key, sn in const.skill_table.items(): if sn.name.lower().startswith(name.lower()): if found == -1: found = sn if ch.level >= sn.skill_level[ch.guild.name] and key in ch.pcdata.learned: return sn return found target_name = '' def do_cast(ch, argument): #* Switched NPC's can cast spells, but others can't. global target_name if IS_NPC(ch) and not ch.desc: return target_name, arg1 = read_word(argument) holder, arg2 = read_word(target_name) if not arg1: ch.send("Cast which what where?\n") return sn = find_spell(ch,arg1) if not sn or sn.spell_fun == spell_null \ or (not IS_NPC(ch) and (ch.level < sn.skill_level[ch.guild.name] \ or ch.pcdata.learned[sn.name] == 0)): ch.send("You don't know any spells of that name.\n") return if ch.position < sn.minimum_position: ch.send("You can't concentrate enough.\n") return if ch.level + 2 == sn.skill_level[ch.guild.name]: mana = 50 else: mana = max(sn.min_mana, 100 // (2 + ch.level - sn.skill_level[ch.guild.name])) # Locate targets. victim=None obj=None vo=None target=TARGET_NONE if sn.target == TAR_IGNORE: pass elif sn.target == TAR_CHAR_OFFENSIVE: if not arg2: victim = ch.fighting if not victim: ch.send("Cast the spell on whom?\n") return else: victim = ch.get_char_room(target_name) if not victim: ch.send("They aren't here.\n") return # if ch == victim: # ch.send("You can't do that to yourself.\n") # return if not IS_NPC(ch): if is_safe(ch,victim) and victim != ch: ch.send("Not on that target.\n") return check_killer(ch,victim) if IS_AFFECTED(ch, AFF_CHARM) and ch.master == victim: ch.send("You can't do that on your own follower.\n") return vo = victim target = TARGET_CHAR elif sn.target == TAR_CHAR_DEFENSIVE: if not arg2: victim = ch else: victim = ch.get_char_room(target_name) if not victim: ch.send("They aren't here.\n") return vo = victim target = TARGET_CHAR elif sn.target == TAR_CHAR_SELF: if arg2 and target_name not in ch.name.lower(): ch.send("You can! cast this spell on a!her.\n") return vo = ch target = TARGET_CHAR elif sn.target == TAR_OBJ_INV: if not arg2: ch.send("What should the spell be cast upon?\n") return obj = ch.get_obj_carry(target_name, ch) if not obj: ch.send("You are not carrying that.\n") return vo = obj target = TARGET_OBJ elif sn.target == TAR_OBJ_CHAR_OFF: if not arg2: victim = ch.fighting if not victim: ch.send("Cast the spell on whom or what?\n") return target = TARGET_CHAR else: victim = ch.get_char_room(target_name) obj = ch.get_obj_here(target_name) if victim: target = TARGET_CHAR # check the sanity of the attack */ if is_safe_spell(ch,victim,False) and victim != ch: ch.send("Not on that target.\n") return if IS_AFFECTED(ch, AFF_CHARM) and ch.master == victim: ch.send("You can't do that on your own follower.\n") return if not IS_NPC(ch): check_killer(ch,victim) vo = victim elif obj: vo = obj target = TARGET_OBJ else: ch.send("You don't see that here.\n") return elif sn.target == TAR_OBJ_CHAR_DEF: if not arg2: vo = ch target = TARGET_CHAR else: victim = ch.get_char_room(target_name) obj = ch.get_obj_carry(target_name, ch) if not victim: vo = victim target = TARGET_CHAR elif not obj: vo = obj target = TARGET_OBJ else: ch.send("You don't see that here.\n") return else: print ("BUG: Do_cast: bad target for sn %s." % sn) return if not IS_NPC(ch) and ch.mana < mana: ch.send("You don't have enough mana.\n") return if sn.name != "ventriloquate": say_spell(ch, sn) WAIT_STATE(ch, sn.beats) if random.randint(1,99) > ch.get_skill(sn.name): ch.send("You lost your concentration.\n") check_improve(ch,sn,False,1) ch.mana -= mana // 2 else: ch.mana -= mana if IS_NPC(ch) or ch.guild.fMana: # class has spells */ sn.spell_fun( sn, ch.level, ch, vo,target) else: sn.spell_fun(sn, 3 * ch.level // 4, ch, vo,target) check_improve(ch,sn,True,1) if (sn.target == TAR_CHAR_OFFENSIVE or (sn.target == TAR_OBJ_CHAR_OFF and target == TARGET_CHAR)) \ and victim != ch and victim.master != ch: for vch in ch.in_room.people[:]: if victim == vch and not victim.fighting: check_killer(victim,ch) multi_hit(victim, ch, TYPE_UNDEFINED) break return # * Spell functions. def spell_acid_blast(sn, level, ch, victim, target): dam = dice( level, 12 ) if saves_spell( level, victim, DAM_ACID ): dam = dam//2 damage( ch, victim, dam, sn, DAM_ACID, True) def spell_armor(sn, level, ch, victim, target): if is_affected( victim, sn ): if victim == ch: ch.send("You are already armored.\n") else: act("$N is already armored.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 24 af.modifier = -20 af.location = APPLY_AC af.bitvector = 0 victim.affect_add(af) victim.send( "You feel someone protecting you.\n") if ch is not victim: act("$N is protected by your magic.",ch,None,victim,TO_CHAR) def spell_bless(sn, level, ch, victim, target): # deal with the object case first */ if target == TARGET_OBJ: obj = victim if IS_OBJ_STAT(obj,ITEM_BLESS): act("$p is already blessed.",ch,obj,target=TO_CHAR) return if IS_OBJ_STAT(obj,ITEM_EVIL): paf = affect_find(obj.affected,"curse") level = obj.level if paf: level = paf.level if not saves_dispel(level,level,0): if paf: obj.affect_remove(paf) act("$p glows a pale blue.",ch,obj,None,TO_ALL) REMOVE_BIT(obj.extra_flags,ITEM_EVIL) return else: act("The evil of $p is too powerful for you to overcome.", ch,obj,target=TO_CHAR) return af = AFFECT_DATA() af.where = TO_OBJECT af.type = sn af.level = level af.duration = 6 + level af.location = APPLY_SAVES af.modifier = -1 af.bitvector = ITEM_BLESS obj.affect_add(af) act("$p glows with a holy aura.",ch,obj,target=TO_ALL) if obj.wear_loc != WEAR_NONE: ch.saving_throw = ch.saving_throw-1 return # character target */ if victim.position == POS_FIGHTING or is_affected( victim, sn ): if victim == ch: ch.send("You are already blessed.\n") else: act("$N already has divine favor.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 6+level af.location = APPLY_HITROLL af.modifier = level // 8 af.bitvector = 0 victim.affect_add(af) af.location = APPLY_SAVING_SPELL af.modifier = 0 - level // 8 victim.affect_add(af) victim.send( "You feel righteous.\n") if ch is not victim: act("You grant $N the favor of your god.",ch,None,victim,TO_CHAR) def spell_blindness( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_BLIND) or saves_spell(level,victim,DAM_OTHER): return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.location = APPLY_HITROLL af.modifier = -4 af.duration = 1+level af.bitvector = AFF_BLIND victim.affect_add(af) victim.send( "You are blinded! \n") act("$n appears to be blinded.",victim,target=TO_ROOM) def spell_burning_hands( sn, level, ch, victim, target ): dam_each = [ 0, 0, 0, 0, 0, 14, 17, 20, 23, 26, 29, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if saves_spell( level, victim,DAM_FIRE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_FIRE,True) def spell_call_lightning( sn, level, ch, victim, target ): if not IS_OUTSIDE(ch): ch.send("You must be out of doors.\n") return if weather_info.sky < SKY_RAINING: ch.send("You need bad weather.\n") return dam = dice(level//2, 8) ch.send("Mota's lightning strikes your foes! \n") act( "$n calls Mota's lightning to strike $s foes! ", ch, None, None, TO_ROOM ) for vch in char_list[:]: if vch.in_room == None: continue if vch.in_room == ch.in_room: if vch is not ch and ( not IS_NPC(vch) if IS_NPC(ch) else IS_NPC(vch) ): damage( ch, vch, dam//2 if saves_spell( level,vch,DAM_LIGHTNING) else dam, sn,DAM_LIGHTNING,True) continue if vch.in_room.area == ch.in_room.area and IS_OUTSIDE(vch) and IS_AWAKE(vch): vch.send("Lightning flashes in the sky.\n") # RT calm spell stops all fighting in the room */ def spell_calm( sn, level, ch, victim, target ): # get sum of all mobile levels in the room */ count=0 mlevel=0 for vch in ch.in_room.people: if vch.position == POS_FIGHTING: count=count+1 if IS_NPC(vch): mlevel += vch.level else: mlevel += vch.level//2 high_level = max(high_level,vch.level) # compute chance of stopping combat */ chance = 4 * level - high_level + 2 * count if IS_IMMORTAL(ch): # always works */ mlevel = 0 if random.randint(0, chance) >= mlevel: # hard to stop large fights */ for vch in ch.in_room.people: if IS_NPC(vch) and (IS_SET(vch.imm_flags,IMM_MAGIC) or IS_SET(vch.act,ACT_UNDEAD)): return if IS_AFFECTED(vch,AFF_CALM) or IS_AFFECTED(vch,AFF_BERSERK) or is_affected(vch,const.skill_table['frenzy']): return vch.send("A wave of calm passes over you.\n") if vch.fighting or vch.position == POS_FIGHTING: stop_fighting(vch,False) af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level//4 af.location = APPLY_HITROLL if not IS_NPC(vch): af.modifier = -5 else: af.modifier = -2 af.bitvector = AFF_CALM vch.affect_add(af) af.location = APPLY_DAMROLL vch.affect_add(af) def spell_cancellation( sn, level, ch, victim, target ): found = False level += 2 if (not IS_NPC(ch) and IS_NPC(victim) and not (IS_AFFECTED(ch, AFF_CHARM) and ch.master == victim) ) or (IS_NPC(ch) and not IS_NPC(victim)): ch.send("You failed, try dispel magic.\n") return # unlike dispel magic, the victim gets NO save */ # begin running through the spells */ spells = { 'armor':None, 'bless':None, 'blindness': '$n is no longer blinded', 'calm': '$n no longer looks so peaceful...', 'change sex': '$n looks more like $mself again.', 'charm person': '$n regains $s free will.', 'chill touch': '$n looks warmer', 'curse':None, 'detect evil':None, 'detect good':None, 'detect hidden':None, 'detect invis':None, 'detect magic':None, 'faerie fire':"$n's outline fades", 'fly':'$n falls to the ground! ', 'frenzy': "$n no longer looks so wild.", 'giant strength': "$n no longer looks so mighty.", 'haste': '$n is no longer moving so quickly', 'infravision':None, 'invis':'$n fades into existence.', 'mass invis': '$n fades into existence', 'pass door': None, 'protection evil': None, 'protection good': None, 'sanctuary': "The white aura around $n's body vanishes.", 'shield': 'The shield protecting $n vanishes', 'sleep': None, 'slow': '$n is no longer moving so slowly.', 'stone skin': "$n's skin regains its normal texture.", 'weaken': "$n looks stronger." } for k,v in spells.items(): if check_dispel(level,victim,const.skill_table[k]): if v: act(v,victim,None,None,TO_ROOM) found = True if found: ch.send("Ok.\n") else: ch.send("Spell failed.\n") def spell_cause_light( sn, level, ch, victim, target ): damage( ch,victim, dice(1, 8) + level // 3, sn,DAM_HARM,True) return def spell_cause_critical( sn, level, ch, victim, target ): damage( ch, victim, dice(3, 8) + level - 6, sn,DAM_HARM,True) return def spell_cause_serious( sn, level, ch, victim, target ): damage( ch, victim, dice(2, 8) + level // 2, sn,DAM_HARM,True) return def spell_chain_lightning( sn, level, ch, victim, target ): #H first strike */ act("A lightning bolt leaps from $n's hand and arcs to $N.",ch,None,victim,TO_ROOM) act("A lightning bolt leaps from your hand and arcs to $N.",ch,None,victim,TO_CHAR) act("A lightning bolt leaps from $n's hand and hits you! ",ch,None,victim,TO_VICT) dam = dice(level,6) if saves_spell(level,victim,DAM_LIGHTNING): dam = dam//3 damage(ch,victim,dam,sn,DAM_LIGHTNING,True) last_vict = victim level = level-4 # decrement damage */ # new targets */ while level > 0: found = False for tmp_vict in ch.in_room.people: if not is_safe_spell(ch,tmp_vict,True) and tmp_vict is not last_vict: found = True last_vict = tmp_vict act("The bolt arcs to $n! ",tmp_vict,None,None,TO_ROOM) act("The bolt hits you! ",tmp_vict,None,None,TO_CHAR) dam = dice(level,6) if saves_spell(level,tmp_vict,DAM_LIGHTNING): dam = dam//3 damage(ch,tmp_vict,dam,sn,DAM_LIGHTNING,True) level = level-4 # decrement damage */ if not found: # no target found, hit the caster */ if ch == None: return if last_vict == ch: # no double hits */ act("The bolt seems to have fizzled out.",ch,None,None,TO_ROOM) act("The bolt grounds out through your body.", ch,None,None,TO_CHAR) return last_vict = ch act("The bolt arcs to $n...whoops! ",ch,None,None,TO_ROOM) ch.send("You are struck by your own lightning! \n") dam = dice(level,6) if saves_spell(level,ch,DAM_LIGHTNING): dam = dam // 3 damage(ch,ch,dam,sn,DAM_LIGHTNING,True) level = level-4 # decrement damage */ if ch == None: return def spell_change_sex( sn, level, ch, victim, target ): if is_affected( victim, sn ): if victim == ch: ch.send("You've already been changed.\n") else: act("$N has already had $s(?) sex changed.",ch,None,victim,TO_CHAR) return if saves_spell(level , victim,DAM_OTHER): return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 2 * level af.location = APPLY_SEX while af.modifier == 0: af.modifier = random.randint( 0, 2 ) - victim.sex af.bitvector = 0 victim.affect_add(af) victim.send("You feel different.\n") act("$n doesn't look like $mself anymore...",victim,None,None,TO_ROOM) def spell_charm_person( sn, level, ch, victim, target ): if is_safe(ch,victim): return if victim == ch: ch.send("You like yourself even better! \n") return if ( IS_AFFECTED(victim, AFF_CHARM) \ or IS_AFFECTED(ch, AFF_CHARM) \ or level < victim.level \ or IS_SET(victim.imm_flags,IMM_CHARM) \ or saves_spell( level, victim,DAM_CHARM) ): return if IS_SET(victim.in_room.room_flags,ROOM_LAW): ch.send("The mayor does not allow charming in the city limits.\n") return if victim.master: stop_follower( victim ) add_follower( victim, ch ) victim.leader = ch af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = number_fuzzy( level // 4 ) af.location = 0 af.modifier = 0 af.bitvector = AFF_CHARM victim.affect_add(af) act( "Isn't $n just so nice?", ch, None, victim, TO_VICT ) if ch is not victim: act("$N looks at you with adoring eyes.",ch,None,victim,TO_CHAR) def spell_chill_touch( sn, level, ch, victim, target ): dam_each=[ 0, 0, 0, 6, 7, 8, 9, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if not saves_spell( level, victim,DAM_COLD ): act("$n turns blue and shivers.",victim,None,None,TO_ROOM) af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 6 af.location = APPLY_STR af.modifier = -1 af.bitvector = 0 victim.affect_join(af) else: dam = dam//2 damage( ch, victim, dam, sn, DAM_COLD,True ) def spell_colour_spray( sn, level, ch, victim, target ): dam_each = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 35, 40, 45, 50, 55, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 64, 64, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 73, 73, 74, 75, 76, 76, 77, 78, 79, 79 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if saves_spell( level, victim,DAM_LIGHT): dam = dam//2 else: spell_blindness(const.skill_table["blindness"], level//2,ch,victim,TARGET_CHAR) damage( ch, victim, dam, sn, DAM_LIGHT,True ) def spell_continual_light( sn, level, ch, victim, target ): if victim: # do a glow on some object */ light = ch.get_obj_carry(victim, ch) if not light: ch.send("You don't see that here.\n") return if IS_OBJ_STAT(light,ITEM_GLOW): act("$p is already glowing.",ch,light,None,TO_CHAR) return SET_BIT(light.extra_flags,ITEM_GLOW) act("$p glows with a white light.",ch,light,None,TO_ALL) return light = create_object( obj_index_hash[OBJ_VNUM_LIGHT_BALL], 0 ) light.to_room(ch.in_room) act( "$n twiddles $s thumbs and $p appears.", ch, light, None, TO_ROOM ) act( "You twiddle your thumbs and $p appears.", ch, light, None, TO_CHAR ) def spell_control_weather( sn, level, ch, victim, target ): if victim.lower() == "better": weather_info.change += dice( level // 3, 4 ) elif victim.lower() == "worse": weather_info.change -= dice( level // 3, 4 ) else: ch.send("Do you want it to get better or worse?\n") ch.send("Ok.\n") return def spell_create_food( sn, level, ch, victim, target ): mushroom = create_object( obj_index_hash[OBJ_VNUM_MUSHROOM], 0 ) mushroom.value[0] = level // 2 mushroom.value[1] = level mushroom.to_room(ch.in_room) act( "$p suddenly appears.", ch, mushroom, None, TO_ROOM ) act( "$p suddenly appears.", ch, mushroom, None, TO_CHAR ) return def spell_create_rose( sn, level, ch, victim, target ): rose = create_object(obj_index_hash[OBJ_VNUM_ROSE], 0) act("$n has created a beautiful red rose.",ch,rose,None,TO_ROOM) ch.send("You create a beautiful red rose.\n") rose.to_char(ch) def spell_create_spring( sn, level, ch, victim, target ): spring = create_object( obj_index_hash[OBJ_VNUM_SPRING], 0 ) spring.timer = level spring.to_room(ch.in_room) act( "$p flows from the ground.", ch, spring, None, TO_ROOM ) act( "$p flows from the ground.", ch, spring, None, TO_CHAR ) def spell_create_water( sn, level, ch, victim, target ): if obj.item_type != ITEM_DRINK_CON: ch.send("It is unable to hold water.\n") return if obj.value[2] != LIQ_WATER and obj.value[1] != 0: ch.send("It contains some other liquid.\n") return water = min( level * (4 if weather_info.sky >= SKY_RAINING else 2), obj.value[0] - obj.value[1] ) if water > 0: obj.value[2] = LIQ_WATER obj.value[1] += water if "water" in obj.name.lower(): obj.name = "%s water" % obj.name act( "$p is filled.", ch, obj, None, TO_CHAR ) def spell_cure_blindness( sn, level, ch, victim, target ): if not is_affected( victim, const.skill_table['blindness'] ): if victim == ch: ch.send("You aren't blind.\n") else: act("$N doesn't appear to be blinded.",ch,None,victim,TO_CHAR) return if check_dispel(level,victim,const.skill_table['blindness']): victim.send("Your vision returns! \n") act("$n is no longer blinded.",victim,None,None,TO_ROOM) else: ch.send("Spell failed.\n") def spell_cure_critical( sn, level, ch, victim, target ): heal = dice(3, 8) + level - 6 victim.hit = min( victim.hit + heal, victim.max_hit ) update_pos( victim ) victim.send("You feel better! \n") if ch != victim: ch.send("Ok.\n") # RT added to cure plague */ def spell_cure_disease( sn, level, ch, victim, target ): if not is_affected( victim, const.skill_table['plague'] ): if victim == ch: ch.send("You aren't ill.\n") else: act("$N doesn't appear to be diseased.",ch,None,victim,TO_CHAR) return if check_dispel(level,victim,const.skill_table['plague']): victim.send("Your sores vanish.\n") act("$n looks relieved as $s sores vanish.",victim,None,None,TO_ROOM) return ch.send("Spell failed.\n") def spell_cure_light( sn, level, ch, victim, target ): heal = dice(1, 8) + level // 3 victim.hit = min( victim.hit + heal, victim.max_hit ) update_pos( victim ) victim.send("You feel better! \n") if ch != victim: ch.send("Ok.\n") return def spell_cure_poison( sn, level, ch, victim, target ): if not is_affected( victim, const.skill_table['poison'] ): if victim == ch: ch.send("You aren't poisoned.\n") else: act("$N doesn't appear to be poisoned.",ch,None,victim,TO_CHAR) return if check_dispel(level,victim,const.skill_table['poison']): victim.send("A warm feeling runs through your body.\n") act("$n looks much better.",victim,None,None,TO_ROOM) return ch.send("Spell failed.\n") def spell_cure_serious( sn, level, ch, victim, target ): heal = dice(2, 8) + level //2 victim.hit = min( victim.hit + heal, victim.max_hit ) update_pos( victim ) victim.send("You feel better! \n") if ch != victim: ch.send("Ok.\n") def spell_curse( sn, level, ch, victim, target ): # deal with the object case first */ if target == TARGET_OBJ: obj = victim if IS_OBJ_STAT(obj,ITEM_EVIL): act("$p is already filled with evil.",ch,obj,None,TO_CHAR) return if IS_OBJ_STAT(obj,ITEM_BLESS): paf = affect_find(obj.affected, const.skill_table["bless"]) if not saves_dispel(level, paf.level if paf != None else obj.level, 0): if paf: obj.affect_remove(paf) act("$p glows with a red aura.", ch, obj, None, TO_ALL) REMOVE_BIT(obj.extra_flags, ITEM_BLESS) return else: act("The holy aura of $p is too powerful for you to overcome.", ch, obj, None, TO_CHAR) return af = AFFECT_DATA() af.where = TO_OBJECT af.type = sn af.level = level af.duration = 2 * level af.location = APPLY_SAVES af.modifier = +1 af.bitvector = ITEM_EVIL obj.affect_add(af) act("$p glows with a malevolent aura.",ch,obj,None,TO_ALL) if obj.wear_loc != WEAR_NONE: ch.saving_throw += 1 return # character curses */ if IS_AFFECTED(victim,AFF_CURSE) or saves_spell(level,victim,DAM_NEGATIVE): return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 2*level af.location = APPLY_HITROLL af.modifier = -1 * (level // 8) af.bitvector = AFF_CURSE victim.affect_add(af) af.location = APPLY_SAVING_SPELL af.modifier = level // 8 victim.affect_add(af) victim.send("You feel unclean.\n") if ch != victim: act("$N looks very uncomfortable.",ch,None,victim,TO_CHAR) # RT replacement demonfire spell */ def spell_demonfire( sn, level, ch, victim, target ): if not IS_NPC(ch) and not IS_EVIL(ch): victim = ch ch.send("The demons turn upon you! \n") ch.alignment = max(-1000, ch.alignment - 50) if victim != ch: act("$n calls forth the demons of Hell upon $N! ", ch,None,victim,TO_ROOM) act("$n has assailed you with the demons of Hell! ", ch,None,victim,TO_VICT) ch.send("You conjure forth the demons of hell! \n") dam = dice( level, 10 ) if saves_spell( level, victim,DAM_NEGATIVE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_NEGATIVE ,True) spell_curse(const.skill_table['curse'], 3 * level // 4, ch, victim,TARGET_CHAR) def spell_detect_evil( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_DETECT_EVIL): if victim == ch: ch.send("You can already sense evil.\n") else: act("$N can already detect evil.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.modifier = 0 af.location = APPLY_NONE af.bitvector = AFF_DETECT_EVIL victim.affect_add(af) victim.send("Your eyes tingle.\n") if ch != victim: ch.send("Ok.\n") def spell_detect_good( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_DETECT_GOOD): if victim == ch: ch.send("You can already sense good.\n") else: act("$N can already detect good.",ch,None,victim,TO_CHAR) return af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.modifier = 0 af.location = APPLY_NONE af.bitvector = AFF_DETECT_GOOD victim.affect_add(af) victim.send("Your eyes tingle.\n") if ch != victim: ch.send("Ok.\n") def spell_detect_hidden( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_DETECT_HIDDEN): if victim == ch: ch.send("You are already as alert as you can be. \n") else: act("$N can already sense hidden lifeforms.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_DETECT_HIDDEN victim.affect_add(af) victim.send("Your awareness improves.\n") if ch != victim: ch.send("Ok.\n") def spell_detect_invis( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_DETECT_INVIS): if victim == ch: ch.send("You can already see invisible.\n") else: act("$N can already see invisible things.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.modifier = 0 af.location = APPLY_NONE af.bitvector = AFF_DETECT_INVIS victim.affect_add(af) victim.send("Your eyes tingle.\n") if ch != victim: ch.send("Ok.\n") def spell_detect_magic( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_DETECT_MAGIC): if victim == ch: ch.send("You can already sense magical auras.\n") else: act("$N can already detect magic.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.modifier = 0 af.location = APPLY_NONE af.bitvector = AFF_DETECT_MAGIC victim.affect_add(af) victim.send("Your eyes tingle.\n") if ch != victim: ch.send("Ok.\n") def spell_detect_poison( sn, level, ch, victim, target ): if victim.item_type == ITEM_DRINK_CON or obj.item_type == ITEM_FOOD: if obj.value[3] != 0: ch.send("You smell poisonous fumes.\n") else: ch.send("It looks delicious.\n") else: ch.send("It doesn't look poisoned.\n") return def spell_dispel_evil( sn, level, ch, victim, target ): if not IS_NPC(ch) and IS_EVIL(ch): victim = ch if IS_GOOD(victim): act( "Mota protects $N.", ch, None, victim, TO_ROOM ) return if IS_NEUTRAL(victim): act( "$N does not seem to be affected.", ch, None, victim, TO_CHAR ) return if victim.hit > (ch.level * 4): dam = dice( level, 4 ) else: dam = max(victim.hit, dice(level,4)) if saves_spell( level, victim,DAM_HOLY): dam = dam // 2 damage( ch, victim, dam, sn, DAM_HOLY ,True) def spell_dispel_good( sn, level, ch, victim, target ): if not IS_NPC(ch) and IS_GOOD(ch): victim = ch if IS_EVIL(victim): act( "$N is protected by $S evil.", ch, None, victim, TO_ROOM ) return if IS_NEUTRAL(victim): act( "$N does not seem to be affected.", ch, None, victim, TO_CHAR ) return if victim.hit > (ch.level * 4): dam = dice( level, 4 ) else: dam = max(victim.hit, dice(level,4)) if saves_spell( level, victim,DAM_NEGATIVE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_NEGATIVE ,True) # modified for enhanced use */ def spell_dispel_magic( sn, level, ch, victim, target ): if saves_spell(level, victim,DAM_OTHER): victim.send("You feel a brief tingling sensation.\n") ch.send("You failed.\n") return spells = { 'armor':None, 'bless':None, 'blindness': '$n is no longer blinded', 'calm': '$n no longer looks so peaceful...', 'change sex': '$n looks more like $mself again.', 'charm person': '$n regains $s free will.', 'chill touch': '$n looks warmer', 'curse':None, 'detect evil':None, 'detect good':None, 'detect hidden':None, 'detect invis':None, 'detect magic':None, 'faerie fire':"$n's outline fades", 'fly':'$n falls to the ground! ', 'frenzy': "$n no longer looks so wild.", 'giant strength': "$n no longer looks so mighty.", 'haste': '$n is no longer moving so quickly', 'infravision':None, 'invis':'$n fades into existence.', 'mass invis': '$n fades into existence', 'pass door': None, 'protection evil': None, 'protection good': None, 'sanctuary': "The white aura around $n's body vanishes.", 'shield': 'The shield protecting $n vanishes', 'sleep': None, 'slow': '$n is no longer moving so slowly.', 'stone skin': "$n's skin regains its normal texture.", 'weaken': "$n looks stronger." } for k,v in spells.items(): if check_dispel(level,victim,const.skill_table[k]): if v: act(v,victim,None,None,TO_ROOM) found = True if IS_AFFECTED(victim,AFF_SANCTUARY) and not saves_dispel(level, victim.level,-1) and not is_affected(victim,const.skill_table["sanctuary"]): REMOVE_BIT(victim.affected_by,AFF_SANCTUARY) act("The white aura around $n's body vanishes.", victim,None,None,TO_ROOM) found = True if found: ch.send("Ok.\n") else: ch.send("Spell failed.\n") def spell_earthquake( sn, level, ch, victim, target ): ch.send("The earth trembles beneath your feet! \n") act( "$n makes the earth tremble and shiver.", ch, None, None, TO_ROOM ) for vch in char_list[:]: if not vch.in_room: continue if vch.in_room == ch.in_room: if vch != ch and not is_safe_spell(ch,vch,True): if IS_AFFECTED(vch,AFF_FLYING): damage(ch,vch,0,sn,DAM_BASH,True) else: damage( ch,vch,level + dice(2, 8), sn, DAM_BASH,True) continue if vch.in_room.area == ch.in_room.area: vch.send("The earth trembles and shivers.\n") def spell_enchant_armor( sn, level, ch, victim, target ): obj = victim if obj.item_type != ITEM_ARMOR: ch.send("That isn't an armor.\n") return if obj.wear_loc != -1: ch.send("The item must be carried to be enchanted.\n") return # this means they have no bonus */ ac_bonus = 0 ac_found = False fail = 25 # base 25% chance of failure */ affected = obj.affected # find the bonuses */ if not obj.enchanted: affected = obj.pIndexData.affected for paf in affected: if paf.location == APPLY_AC: ac_bonus = paf.modifier ac_found = True fail += 5 * (ac_bonus * ac_bonus) else: # things get a little harder */ fail += 20 # apply other modifiers */ fail -= level if IS_OBJ_STAT(obj,ITEM_BLESS): fail -= 15 if IS_OBJ_STAT(obj,ITEM_GLOW): fail -= 5 fail = max(5,min(fail,85)) result = random.randint(1,99) # the moment of truth */ if result < (fail // 5): # item destroyed */ act("$p flares blindingly... and evaporates! ",ch,obj,None,TO_CHAR) act("$p flares blindingly... and evaporates! ",ch,obj,None,TO_ROOM) obj.extract() if result < (fail // 3): # item disenchanted */ act("$p glows brightly, then fades...oops.",ch,obj,None,TO_CHAR) act("$p glows brightly, then fades.",ch,obj,None,TO_ROOM) obj.enchanted = True # remove all affects */ obj.affected[:] = [] # clear all flags */ obj.extra_flags = 0 return if result <= fail: # failed, no bad result */ ch.send("Nothing seemed to happen.\n") return # okay, move all the old flags into new vectors if we have to */ if not obj.enchanted: obj.enchanted = True for paf in obj.pIndexData.affected: af_new = AFFECT_DATA() af_new.where = paf.where af_new.type = max(0,paf.type) af_new.level = paf.level af_new.duration = paf.duration af_new.location = paf.location af_new.modifier = paf.modifier af_new.bitvector = paf.bitvector obj.affected.append(af_new) if result <= (90 - level//5): # success! */ act("$p shimmers with a gold aura.",ch,obj,None,TO_CHAR) act("$p shimmers with a gold aura.",ch,obj,None,TO_ROOM) SET_BIT(obj.extra_flags, ITEM_MAGIC) added = -1 else: # exceptional enchant */ act("$p glows a brillant gold! ",ch,obj,None,TO_CHAR) act("$p glows a brillant gold! ",ch,obj,None,TO_ROOM) SET_BIT(obj.extra_flags,ITEM_MAGIC) SET_BIT(obj.extra_flags,ITEM_GLOW) added = -2 # now add the enchantments */ if obj.level < LEVEL_HERO: obj.level = min(LEVEL_HERO - 1,obj.level + 1) if ac_found: for paf in obj.affected: if paf.location == APPLY_AC: paf.type = sn paf.modifier += added paf.level = max(paf.level,level) else: # add a new affect */ paf = AFFECT_DATA() paf.where = TO_OBJECT paf.type = sn paf.level = level paf.duration = -1 paf.location = APPLY_AC paf.modifier = added paf.bitvector = 0 obj.affected.append(paf) def spell_enchant_weapon( sn, level, ch, victim, target ): obj = victim if obj.item_type != ITEM_WEAPON: ch.send("That isn't a weapon.\n") return if obj.wear_loc != -1: ch.send("The item must be carried to be enchanted.\n") return # this means they have no bonus */ hit_bonus = 0 dam_bonus = 0 fail = 25 # base 25% chance of failure */ dam_found = False hit_found = False # find the bonuses */ affected = obj.affected if not obj.enchanted: affected = obj.pIndexData.affected for paf in affected: if paf.location == APPLY_HITROLL: hit_bonus = paf.modifier hit_found = True fail += 2 * (hit_bonus * hit_bonus) elif paf.location == APPLY_DAMROLL: dam_bonus = paf.modifier dam_found = True fail += 2 * (dam_bonus * dam_bonus) else: # things get a little harder */ fail += 25 # apply other modifiers */ fail -= 3 * level//2 if IS_OBJ_STAT(obj,ITEM_BLESS): fail -= 15 if IS_OBJ_STAT(obj,ITEM_GLOW): fail -= 5 fail = max(5,min(fail,95)) result = random.randint(1,99) # the moment of truth */ if result < (fail // 5): # item destroyed */ act("$p shivers violently and explodes! ",ch,obj,None,TO_CHAR) act("$p shivers violently and explodeds! ",ch,obj,None,TO_ROOM) obj.extract() return if result < (fail // 2): # item disenchanted */ act("$p glows brightly, then fades...oops.",ch,obj,None,TO_CHAR) act("$p glows brightly, then fades.",ch,obj,None,TO_ROOM) obj.enchanted = True # remove all affects */ obj.affected[:] = [] # clear all flags */ obj.extra_flags = 0 return if result <= fail: # failed, no bad result */ ch.send("Nothing seemed to happen.\n") return # okay, move all the old flags into new vectors if we have to */ if not obj.enchanted: obj.enchanted = True for paf in obj.pIndexData.affected: af_new = AFFECT_DATA() af_new.where = paf.where af_new.type = max(0,paf.type) af_new.level = paf.level af_new.duration = paf.duration affect_loc_nameew.location = paf.location af_new.modifier = paf.modifier af_new.bitvector = paf.bitvector obj.affected.append(af_new) if result <= (100 - level//5): # success! */ act("$p glows blue.",ch,obj,None,TO_CHAR) act("$p glows blue.",ch,obj,None,TO_ROOM) SET_BIT(obj.extra_flags, ITEM_MAGIC) added = 1 else: # exceptional enchant */ act("$p glows a brillant blue! ",ch,obj,None,TO_CHAR) act("$p glows a brillant blue! ",ch,obj,None,TO_ROOM) SET_BIT(obj.extra_flags,ITEM_MAGIC) SET_BIT(obj.extra_flags,ITEM_GLOW) added = 2 # now add the enchantments */ if obj.level < LEVEL_HERO - 1: obj.level = min(LEVEL_HERO - 1,obj.level + 1) if dam_found: for paf in obj.affected: if paf.location == APPLY_DAMROLL: paf.type = sn paf.modifier += added paf.level = max(paf.level,level) if paf.modifier > 4: SET_BIT(obj.extra_flags,ITEM_HUM) else: # add a new affect */ paf = AFFECT_DATA() paf.where = TO_OBJECT paf.type = sn paf.level = level paf.duration = -1 paf.location = APPLY_DAMROLL paf.modifier = added paf.bitvector = 0 obj.affected.append(paf) if hit_found: for paf in obj.affected: if paf.location == APPLY_HITROLL: paf.type = sn paf.modifier += added paf.level = max(paf.level,level) if paf.modifier > 4: SET_BIT(obj.extra_flags,ITEM_HUM) else: # add a new affect */ paf = AFFECT_DATA() paf.type = sn paf.level = level paf.duration = -1 paf.location = APPLY_HITROLL paf.modifier = added paf.bitvector = 0 obj.affected.append( paf ) # # Drain XP, MANA, HP. # Caster gains HP. def spell_energy_drain( sn, level, ch, victim, target ): if victim != ch: ch.alignment = max(-1000, ch.alignment - 50) if saves_spell( level, victim,DAM_NEGATIVE): victim.send("You feel a momentary chill.\n") return if victim.level <= 2: dam = ch.hit + 1 else: gain_exp( victim, 0 - random.randint( level//2, 3 * level // 2 ) ) victim.mana //= 2 victim.move //= 2 dam = dice(1, level) ch.hit += dam victim.send("You feel your life slipping away! \n") ch.send("Wow....what a rush! \n") damage( ch, victim, dam, sn, DAM_NEGATIVE ,True) def spell_fireball( sn, level, ch, victim, target ): dam_each = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if saves_spell( level, victim, DAM_FIRE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_FIRE ,True) def spell_fireproof( sn, level, ch, victim, target ): if IS_OBJ_STAT(obj,ITEM_BURN_PROOF): act("$p is already protected from burning.",ch,obj,None,TO_CHAR) return af = AFFECT_DATA() af.where = TO_OBJECT af.type = sn af.level = level af.duration = number_fuzzy(level // 4) af.location = APPLY_NONE af.modifier = 0 af.bitvector = ITEM_BURN_PROOF obj.affect_add(af) act("You protect $p from fire.",ch,obj,None,TO_CHAR) act("$p is surrounded by a protective aura.",ch,obj,None,TO_ROOM) def spell_flamestrike( sn, level, ch, victim, target ): dam = dice(6 + level // 2, 8) if saves_spell( level, victim,DAM_FIRE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_FIRE ,True) def spell_faerie_fire( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_FAERIE_FIRE): return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.location = APPLY_AC af.modifier = 2 * level af.bitvector = AFF_FAERIE_FIRE victim.affect_add(af) victim.send("You are surrounded by a pink outline.\n") act( "$n is surrounded by a pink outline.", victim, None, None, TO_ROOM ) def spell_faerie_fog( sn, level, ch, victim, target ): act( "$n conjures a cloud of purple smoke.", ch, None, None, TO_ROOM ) ch.send("You conjure a cloud of purple smoke.\n") for ich in ch.in_room.people: if ich.invis_level > 0: continue if ich == ch or saves_spell( level, ich,DAM_OTHER): continue ich.affect_strip('invis') ich.affect_strip('mass_invis') ich.affect_strip('sneak') REMOVE_BIT(ich.affected_by, AFF_HIDE) REMOVE_BIT(ich.affected_by, AFF_INVISIBLE) REMOVE_BIT(ich.affected_by, AFF_SNEAK) act("$n is revealed! ", ich, None, None, TO_ROOM) ich.send("You are revealed! \n") def spell_floating_disc( sn, level, ch, victim, target ): floating = ch.get_eq(WEAR_FLOAT) if floating and IS_OBJ_STAT(floating,ITEM_NOREMOVE): act("You can't remove $p.",ch,floating,None,TO_CHAR) return disc = create_object(obj_index_hash[OBJ_VNUM_DISC], 0) disc.value[0] = ch.level * 10 # 10 pounds per level capacity */ disc.value[3] = ch.level * 5 # 5 pounds per level max per item */ disc.timer = ch.level * 2 - random.randint(0,level // 2) act("$n has created a floating black disc.",ch,None,None,TO_ROOM) ch.send("You create a floating disc.\n") disc.to_char(ch) wear_obj(ch,disc,True) def spell_fly( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_FLYING): if victim == ch: ch.send("You are already airborne.\n") else: act("$N doesn't need your help to fly.",ch,None,victim,TO_CHAR) return af = AFFECDT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level + 3 af.location = 0 af.modifier = 0 af.bitvector = AFF_FLYING victim.affect_add(af) victim.send("Your feet rise off the ground.\n") act( "$n's feet rise off the ground.", victim, None, None, TO_ROOM ) return # RT clerical berserking spell */ def spell_frenzy( sn, level, ch, victim, target ): if is_affected(victim,sn) or IS_AFFECTED(victim,AFF_BERSERK): if victim == ch: ch.send("You are already in a frenzy.\n") else: act("$N is already in a frenzy.",ch,None,victim,TO_CHAR) return if is_affected(victim,const.skill_table['calm']): if victim == ch: ch.send("Why don't you just relax for a while?\n") else: act("$N doesn't look like $e wants to fight anymore.", ch,None,victim,TO_CHAR) return if (IS_GOOD(ch) and not IS_GOOD(victim)) or \ (IS_NEUTRAL(ch) and not IS_NEUTRAL(victim)) or \ (IS_EVIL(ch) and not IS_EVIL(victim)): act("Your god doesn't seem to like $N",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level // 3 af.modifier = level // 6 af.bitvector = 0 af.location = APPLY_HITROLL victim.affect_add(af) af.location = APPLY_DAMROLL victim.affect_add(af) af.modifier = 10 * (level // 12) af.location = APPLY_AC victim.affect_add(af) victim.send("You are filled with holy wrath! \n") act("$n gets a wild look in $s eyes! ",victim,None,None,TO_ROOM) # RT ROM-style gate */ def spell_gate( sn, level, ch, victim, target ): victim = ch.get_char_world(target_name) if not victim \ or victim == ch \ or victim.in_room == None \ or not ch.can_see_room(victim.in_room) \ or IS_SET(victim.in_room.room_flags, ROOM_SAFE) \ or IS_SET(victim.in_room.room_flags, ROOM_PRIVATE) \ or IS_SET(victim.in_room.room_flags, ROOM_SOLITARY) \ or IS_SET(victim.in_room.room_flags, ROOM_NO_RECALL) \ or IS_SET(ch.in_room.room_flags, ROOM_NO_RECALL) \ or victim.level >= level + 3 \ or (victim.is_clan() and not ch.is_same_clan(victim)) \ or (not IS_NPC(victim) and victim.level >= LEVEL_HERO) \ or (IS_NPC(victim) and IS_SET(victim.imm_flags,IMM_SUMMON)) \ or (IS_NPC(victim) and saves_spell( level, victim,DAM_OTHER) ): ch.send("You failed.\n") return if ch.pet and ch.in_room == ch.pet.in_room: gate_pet = True else: gate_pet = False act("$n steps through a gate and vanishes.",ch,None,None,TO_ROOM) ch.send("You step through a gate and vanish.\n") ch.from_room() ch.to_room(victim.in_room) act("$n has arrived through a gate.",ch,None,None,TO_ROOM) ch.do_look("auto") if gate_pet: act("$n steps through a gate and vanishes.",ch.pet,None,None,TO_ROOM) send_to_char("You step through a gate and vanish.\n",ch.pet) ch.pet.from_room() ch.pet.to_room(victim.in_room) act("$n has arrived through a gate.",ch.pet,None,None,TO_ROOM) ch.pet.do_look("auto") def spell_giant_strength( sn, level, ch, victim, target ): if is_affected( victim, sn ): if victim == ch: ch.send("You are already as strong as you can get! \n") else: act("$N can't get any stronger.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.location = APPLY_STR af.modifier = 1 + (level >= 18) + (level >= 25) + (level >= 32) af.bitvector = 0 victim.affect_add(af) victim.send("Your muscles surge with heightened power! \n") act("$n's muscles surge with heightened power.",victim,None,None,TO_ROOM) def spell_harm( sn, level, ch, victim, target ): dam = max( 20, victim.hit - dice(1,4) ) if saves_spell( level, victim,DAM_HARM): dam = min( 50, dam // 2 ) dam = min( 100, dam ) damage( ch, victim, dam, sn, DAM_HARM ,True) # RT haste spell */ def spell_haste( sn, level, ch, victim, target ): if is_affected( victim, sn ) or IS_AFFECTED(victim,AFF_HASTE) or IS_SET(victim.off_flags,OFF_FAST): if victim == ch: ch.send("You can't move any faster! \n") else: act("$N is already moving as fast as $E can.", ch,None,victim,TO_CHAR) return if IS_AFFECTED(victim,AFF_SLOW): if not check_dispel(level,victim,const.skill_table["slow"]): if victim != ch: ch.send("Spell failed.\n") victim.send("You feel momentarily faster.\n") return act("$n is moving less slowly.",victim,None,None,TO_ROOM) return af.where = TO_AFFECTS af.type = sn af.level = level if victim == ch: af.duration = level//2 else: af.duration = level//4 af.location = APPLY_DEX af.modifier = 1 + (level >= 18) + (level >= 25) + (level >= 32) af.bitvector = AFF_HASTE victim.affect_add(af) victim.send("You feel yourself moving more quickly.\n") act("$n is moving more quickly.",victim,None,None,TO_ROOM) if ch != victim: ch.send("Ok.\n") def spell_heal( sn, level, ch, victim, target ): victim.hit = min( victim.hit + 100, victim.max_hit ) update_pos( victim ) victim.send("A warm feeling fills your body.\n") if ch != victim: ch.send("Ok.\n") return def spell_heat_metal( sn, level, ch, victim, target ): fail = True if not saves_spell(level + 2,victim,DAM_FIRE) and not IS_SET(victim.imm_flags,IMM_FIRE): for obj_lose in victim.carrying[:]: if random.randint(1,2 * level) > obj_lose.level \ and not saves_spell(level,victim,DAM_FIRE) \ and not IS_OBJ_STAT(obj_lose,ITEM_NONMETAL) \ and not IS_OBJ_STAT(obj_lose,ITEM_BURN_PROOF): if obj_lose.item_type == ITEM_ARMOR: if obj_lose.wear_loc != -1: # remove the item */ if victim.can_drop_obj(obj_lose) \ and (obj_lose.weight // 10) < random.randint(1,2 * victim.get_curr_stat(STAT_DEX)) \ and remove_obj( victim, obj_lose.wear_loc, True ): act("$n yelps and throws $p to the ground! ", victim,obj_lose,None,TO_ROOM) act("You remove and drop $p before it burns you.", victim,obj_lose,None,TO_CHAR) dam += (random.randint(1,obj_lose.level) // 3) obj_lose.from_char() obj_lose.to_room(victim.in_room) fail = False else: # stuck on the body! ouch! */ act("Your skin is seared by $p! ", victim,obj_lose,None,TO_CHAR) dam += (random.randint(1,obj_lose.level)) fail = False else: # drop it if we can */ if victim.can_drop_obj(obj_lose): act("$n yelps and throws $p to the ground! ", victim,obj_lose,None,TO_ROOM) act("You and drop $p before it burns you.", victim,obj_lose,None,TO_CHAR) dam += (random.randint(1,obj_lose.level) // 6) obj_lose.from_char() obj_lose.to_room(victim.in_room) fail = False else: # can! drop */ act("Your skin is seared by $p! ", victim,obj_lose,None,TO_CHAR) dam += (random.randint(1,obj_lose.level) // 2) fail = False if obj_lose.item_type == ITEM_WEAPON: if obj_lose.wear_loc != -1: # try to drop it */ if IS_WEAPON_STAT(obj_lose,WEAPON_FLAMING): continue if victim.can_drop_obj(obj_lose) and remove_obj(victim,obj_lose.wear_loc,True): act("$n is burned by $p, and throws it to the ground.", victim,obj_lose,None,TO_ROOM) victim.send("You throw your red-hot weapon to the ground! \n") dam += 1 obj_lose.from_char() obj_lose.to_room(victim.in_room) fail = False else: # YOWCH! */ victim.send("Your weapon sears your flesh! \n") dam += random.randint(1,obj_lose.level) fail = False else: # drop it if we can */ if victim.can_drop_obj(obj_lose): act("$n throws a burning hot $p to the ground! ", victim,obj_lose,None,TO_ROOM) act("You and drop $p before it burns you.", victim,obj_lose,None,TO_CHAR) dam += (random.randint(1,obj_lose.level) // 6) obj_lose.from_char() obj_lose.to_room(victim.in_room) fail = False else: # can! drop */ act("Your skin is seared by $p! ", victim,obj_lose,None,TO_CHAR) dam += (random.randint(1,obj_lose.level) // 2) fail = False if fail: ch.send("Your spell had no effect.\n") victim.send("You feel momentarily warmer.\n") else: # damage! */ if saves_spell(level,victim,DAM_FIRE): dam = 2 * dam // 3 damage(ch,victim,dam,sn,DAM_FIRE,True) # RT really nasty high-level attack spell */ def spell_holy_word( sn, level, ch, victim, target ): bless_num = const.skill_table['bless'] curse_num = const.skill_table['curse'] frenzy_num = const.skill_table['frenzy'] act("$n utters a word of divine power! ",ch,None,None,TO_ROOM) ch.send("You utter a word of divine power.\n") for vch in ch.in_room.people[:]: if(IS_GOOD(ch) and IS_GOOD(vch)) or (IS_EVIL(ch) and IS_EVIL(vch)) or (IS_NEUTRAL(ch) and IS_NEUTRAL(vch)): vch.send("You feel full more powerful.\n") spell_frenzy(frenzy_num,level,ch,vch,TARGET_CHAR) spell_bless(bless_num,level,ch,vch,TARGET_CHAR) elif (IS_GOOD(ch) and IS_EVIL(vch)) or (IS_EVIL(ch) and IS_GOOD(vch)): if not is_safe_spell(ch,vch,True): spell_curse(curse_num,level,ch,vch,TARGET_CHAR) vch.send("You are struck down! \n") dam = dice(level,6) damage(ch,vch,dam,sn,DAM_ENERGY,True) elif IS_NEUTRAL(ch): if not is_safe_spell(ch,vch,True): spell_curse(curse_num,level//2,ch,vch,TARGET_CHAR) vch.send("You are struck down! \n") dam = dice(level,4) damage(ch,vch,dam,sn,DAM_ENERGY,True) ch.send("You feel drained.\n") ch.move = 0 ch.hit = hit // 2 def spell_identify( sn, level, ch, victim, target ): ch.send("Object '%s' is type %s, extra flags %s.\nWeight is %d, value is %d, level is %d.\n" % ( obj.name, item_name(obj.item_type), extra_bit_name( obj.extra_flags ), obj.weight // 10, obj.cost, obj.level ) ) if obj.item_type == ITEM_SCROLL or obj.item_type == ITEM_POTION or obj.item_type == ITEM_PILL: ch.send("Level %d spells of:" % obj.value[0] ) for i in obj.value: if i >= 0 and i < MAX_SKILL: ch.send(" '%s'" % const.skill_table[i].name) ch.send(".\n") elif obj.item_type == ITEM_WAND or obj.item_type == ITEM_STAFF: ch.send("Has %d charges of level %d" % ( obj.value[2], obj.value[0] ) ) if obj.value[3] >= 0 and obj.value[3] < MAX_SKILL: ch.send( "' %s'" % const.skill_table[obj.value[3]].name) ch.send(".\n") elif obj.item_type == ITEM_DRINK_CON: ch.send("It holds %s-colored %s.\n" % ( liq_table[obj.value[2]].liq_color, liq_table[obj.value[2]].liq_name) ) send_to_char(buf,ch) elif obj.item_type == ITEM_CONTAINER: ch.send("Capacity: %d# Maximum weight: %d# flags: %s\n" % (obj.value[0], obj.value[3], cont_bit_name(obj.value[1]))) if obj.value[4] != 100: ch.send("Weight multiplier: %d%%\n" % obj.value[4]) elif obj.item_type == ITEM_WEAPON: ch.send("Weapon type is ") weapons = { WEAPON_EXOTIC:"exotic", WEAPON_SWORD:"sword", WEAPON_DAGGER:"dagger", WEAPON_SPEAR:"spear//staff", WEAPON_MACE:"mace//club", WEAPON_AXE:"axe", WEAPON_FLAIL:"flail", WEAPON_WHIP:"whip", WEAPON_POLEARM:"polearm" } if obj.value[0] not in weapons: ch.send("unknown") else: ch.send(weapons[obj.value[0]]) if obj.pIndexData.new_format: ch.send("Damage is %dd%d (average %d).\n" % ( obj.value[1],obj.value[2], (1 + obj.value[2]) * obj.value[1] // 2) ) else: ch.send("Damage is %d to %d (average %d).\n" % ( obj.value[1], obj.value[2], ( obj.value[1] + obj.value[2] ) // 2 ) ) if obj.value[4]: # weapon flags */ ch.send("Weapons flags: %s\n" % weapon_bit_name(obj.value[4])) elif obj.item_type == ITEM_ARMOR: ch.send("Armor class is %d pierce, %d bash, %d slash, and %d vs. magic.\n" % ( obj.value[0], obj.value[1], obj.value[2], obj.value[3] ) ) affected = obj.affected if not obj.enchanted: affected.extend(obj.pIndexData.affected) for paf in affected: if paf.location != APPLY_NONE and paf.modifier != 0: ch.send("Affects %s by %d.\n" % ( affect_loc_name( paf.location ), paf.modifier ) ) if paf.bitvector: if paf.where == TO_AFFECTS: ch.send("Adds %s affect.\n" % affect_bit_name(paf.bitvector)) elif paf.where == TO_OBJECT: ch.send("Adds %s object flag.\n" % extra_bit_name(paf.bitvector)) elif paf.where == TO_IMMUNE: ch.send("Adds immunity to %s.\n" % imm_bit_name(paf.bitvector)) elif paf.where == TO_RESIST: ch.send("Adds resistance to %s.\n" % imm_bit_name(paf.bitvector)) elif paf.where == TO_VULN: ch.send("Adds vulnerability to %s.\n" % imm_bit_name(paf.bitvector)) else: ch.send("Unknown bit %d: %d\n" % (paf.where,paf.bitvector)) def spell_infravision( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_INFRARED): if victim == ch: ch.send("You can already see in the dark.\n") else: act("$N already has infravision.\n",ch,None,victim,TO_CHAR) return act( "$n's eyes glow red.\n", ch, None, None, TO_ROOM ) af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 2 * level af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_INFRARED victim.affect_add(af) victim.send("Your eyes glow red.\n") return def spell_invis( sn, level, ch, victim, target ): # object invisibility */ if target == TARGET_OBJ: obj = victim if IS_OBJ_STAT(obj,ITEM_INVIS): act("$p is already invisible.",ch,obj,None,TO_CHAR) return af = AFFECT_DATA() af.where = TO_OBJECT af.type = sn af.level = level af.duration = level + 12 af.location = APPLY_NONE af.modifier = 0 af.bitvector = ITEM_INVIS obj.affect_add(af) act("$p fades out of sight.",ch,obj,None,TO_ALL) return # character invisibility */ if IS_AFFECTED(victim, AFF_INVISIBLE): return act( "$n fades out of existence.", victim, None, None, TO_ROOM ) af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level + 12 af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_INVISIBLE victim.affect_add(af) victim.send("You fade out of existence.\n") return def spell_know_alignment( sn, level, ch, victim, target ): ap = victim.alignment if ap > 700: msg = "$N has a pure and good aura." elif ap > 350: msg = "$N is of excellent moral character." elif ap > 100: msg = "$N is often kind and thoughtful." elif ap > -100: msg = "$N doesn't have a firm moral commitment." elif ap > -350: msg = "$N lies to $S friends." elif ap > -700: msg = "$N is a black-hearted murderer." else: msg = "$N is the embodiment of pure evil! ." act( msg, ch, None, victim, TO_CHAR ) return def spell_lightning_bolt( sn, level, ch, victim, target ): dam_each = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 28, 31, 34, 37, 40, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 50, 51, 52, 52, 53, 54, 54, 55, 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 64 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if saves_spell( level, victim,DAM_LIGHTNING): dam = dam // 2 damage( ch, victim, dam, sn, DAM_LIGHTNING ,True) def spell_locate_object( sn, level, ch, victim, target ): found = False number = 0 max_found = 200 if IS_IMMORTAL(ch) else 2 * level for obj in object_list: if not ch.can_see_obj(obj) or not is_name( target_name, obj.name ) \ or IS_OBJ_STAT(obj,ITEM_NOLOCATE) or random.randint(1,99) > 2 * level \ or ch.level < obj.level: continue found = True number=number+1 in_obj = obj while in_obj.in_obj: in_obj = in_obj.in_obj if in_obj.carried_by and ch.can_see(in_obj.carried_by): ch.send("one is carried by %s\n" % PERS(in_obj.carried_by, ch) ) else: if IS_IMMORTAL(ch) and in_obj.in_room != None: ch.send("one is in %s [Room %d]\n" % (in_obj.in_room.name, in_obj.in_room.vnum) ) else: ch.send("one is in %s\n" % ( "somewhere" if in_obj.in_room == None else in_obj.in_room.name ) ) if number >= max_found: break if not found: ch.send("Nothing like that in heaven or earth.\n") def spell_magic_missile( sn, level, ch, victim, target ): dam_each = [ 0, 3, 3, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if saves_spell( level, victim,DAM_ENERGY): dam = dam // 2 damage( ch, victim, dam, sn, DAM_ENERGY ,True) def spell_mass_healing( sn, level, ch, victim, target ): heal_num = const.skill_table['heal'] refresh_num = const.skill_table['refresh'] for gch in ch.in_room.people: if (IS_NPC(ch) and IS_NPC(gch) ) or ( not IS_NPC(ch) and not IS_NPC(gch)): spell_heal(heal_num,level,ch,gch,TARGET_CHAR) spell_refresh(refresh_num,level,ch,gch,TARGET_CHAR) def spell_mass_invis( sn, level, ch, victim, target ): for gch in ch.in_room.people: if not gch.is_same_group(ch) or IS_AFFECTED(gch, AFF_INVISIBLE): continue act( "$n slowly fades out of existence.", gch, None, None, TO_ROOM ) gch.send("You slowly fade out of existence.\n") af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level//2 af.duration = 24 af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_INVISIBLE gch.affect_add(af) ch.send("Ok.\n") def spell_null( sn, level, ch, victim, target ): ch.send("That's not a spell! \n") return def spell_pass_door( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_PASS_DOOR): if victim == ch: ch.send("You are already out of phase.\n") else: act("$N is already shifted out of phase.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = number_fuzzy( level // 4 ) af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_PASS_DOOR victim.affect_add(af) act( "$n turns translucent.", victim, None, None, TO_ROOM ) victim.send("You turn translucent.\n") # RT plague spell, very nasty */ def spell_plague( sn, level, ch, victim, target ): if saves_spell(level,victim,DAM_DISEASE) or (IS_NPC(victim) and IS_SET(victim.act,ACT_UNDEAD)): if ch == victim: ch.send("You feel momentarily ill, but it passes.\n") else: act("$N seems to be unaffected.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level * 3//4 af.duration = level af.location = APPLY_STR af.modifier = -5 af.bitvector = AFF_PLAGUE victim.affect_join(af) victim.send("You scream in agony as plague sores erupt from your skin.\n") act("$n screams in agony as plague sores erupt from $s skin.", victim,None,None,TO_ROOM) def spell_poison( sn, level, ch, victim, target ): if target == TARGET_OBJ: obj = victim if obj.item_type == ITEM_FOOD or obj.item_type == ITEM_DRINK_CON: if IS_OBJ_STAT(obj,ITEM_BLESS) or IS_OBJ_STAT(obj,ITEM_BURN_PROOF): act("Your spell fails to corrupt $p.",ch,obj,None,TO_CHAR) return obj.value[3] = 1 act("$p is infused with poisonous vapors.",ch,obj,None,TO_ALL) return if obj.item_type == ITEM_WEAPON: if IS_WEAPON_STAT(obj,WEAPON_FLAMING) \ or IS_WEAPON_STAT(obj,WEAPON_FROST) \ or IS_WEAPON_STAT(obj,WEAPON_VAMPIRIC) \ or IS_WEAPON_STAT(obj,WEAPON_SHARP) \ or IS_WEAPON_STAT(obj,WEAPON_VORPAL) \ or IS_WEAPON_STAT(obj,WEAPON_SHOCKING) \ or IS_OBJ_STAT(obj,ITEM_BLESS) \ or IS_OBJ_STAT(obj,ITEM_BURN_PROOF): act("You can't seem to envenom $p.",ch,obj,None,TO_CHAR) return if IS_WEAPON_STAT(obj,WEAPON_POISON): act("$p is already envenomed.",ch,obj,None,TO_CHAR) return af = AFFECT_DATA() af.where = TO_WEAPON af.type = sn af.level = level // 2 af.duration = level//8 af.location = 0 af.modifier = 0 af.bitvector = WEAPON_POISON obj.affect_add(af) act("$p is coated with deadly venom.",ch,obj,None,TO_ALL) return act("You can't poison $p.",ch,obj,None,TO_CHAR) return if saves_spell( level, victim,DAM_POISON): act("$n turns slightly green, but it passes.",victim,None,None,TO_ROOM) victim.send("You feel momentarily ill, but it passes.\n") return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.location = APPLY_STR af.modifier = -2 af.bitvector = AFF_POISON victim.affect_join(af) victim.send("You feel very sick.\n") act("$n looks very ill.",victim,None,None,TO_ROOM) def spell_protection_evil( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_PROTECT_EVIL) or IS_AFFECTED(victim, AFF_PROTECT_GOOD): if victim == ch: ch.send("You are already protected.\n") else: act("$N is already protected.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 24 af.location = APPLY_SAVING_SPELL af.modifier = -1 af.bitvector = AFF_PROTECT_EVIL victim.affect_add(af) victim.send("You feel holy and pure.\n") if ch != victim: act("$N is protected from evil.",ch,None,victim,TO_CHAR) def spell_protection_good( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_PROTECT_GOOD) or IS_AFFECTED(victim, AFF_PROTECT_EVIL): if victim == ch: ch.send("You are already protected.\n") else: act("$N is already protected.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 24 af.location = APPLY_SAVING_SPELL af.modifier = -1 af.bitvector = AFF_PROTECT_GOOD victim.affect_add(af) victim.send("You feel aligned with darkness.\n") if ch != victim: act("$N is protected from good.",ch,None,victim,TO_CHAR) def spell_ray_of_truth(sn, level, ch, victim, target): if IS_EVIL(ch): victim = ch ch.send("The energy explodes inside you! \n") if victim != ch: act("$n raises $s hand, and a blinding ray of light shoots forth! ", ch,None,None,TO_ROOM) ch.send("You raise your hand and a blinding ray of light shoots forth! \n") if IS_GOOD(victim): act("$n seems unharmed by the light.",victim,None,victim,TO_ROOM) victim.send("The light seems powerless to affect you.\n") return dam = dice( level, 10 ) if saves_spell( level, victim,DAM_HOLY): dam = dam // 2 align = victim.alignment align -= 350 if align < -1000: align = -1000 + (align + 1000) // 3 dam = (dam * align * align) // 1000000 damage( ch, victim, dam, sn, DAM_HOLY ,True) spell_blindness(const.skill_table['blindness'], 3 * level // 4, ch, victim,TARGET_CHAR) def spell_recharge( sn, level, ch, victim, target ): obj = victim if obj.item_type != ITEM_WAND and obj.item_type != ITEM_STAFF: ch.send("That item does not carry charges.\n") return if obj.value[3] >= 3 * level // 2: ch.send("Your skills are not great enough for that.\n") return if obj.value[1] == 0: ch.send("That item has already been recharged once.\n") return chance = 40 + 2 * level chance -= obj.value[3] # harder to do high-level spells */ chance -= (obj.value[1] - obj.value[2]) * (obj.value[1] - obj.value[2]) chance = max(level//2,chance) percent = random.randint(1,99) if percent < chance // 2: act("$p glows softly.",ch,obj,None,TO_CHAR) act("$p glows softly.",ch,obj,None,TO_ROOM) obj.value[2] = max(obj.value[1],obj.value[2]) obj.value[1] = 0 return elif percent <= chance: act("$p glows softly.",ch,obj,None,TO_CHAR) act("$p glows softly.",ch,obj,None,TO_CHAR) chargemax = obj.value[1] - obj.value[2] if chargemax > 0: chargeback = max(1,chargemax * percent // 100) else: chargeback = 0 obj.value[2] += chargeback obj.value[1] = 0 return elif percent <= min(95, 3 * chance // 2): ch.send("Nothing seems to happen.\n") if obj.value[1] > 1: obj.value[1] -= 1 return else: # whoops! */ act("$p glows brightly and explodes! ",ch,obj,None,TO_CHAR) act("$p glows brightly and explodes! ",ch,obj,None,TO_ROOM) obj.extract() def spell_refresh( sn, level, ch, victim, target ): victim.move = min( victim.move + level, victim.max_move ) if victim.max_move == victim.move: victim.send("You feel fully refreshed! \n") else: victim.send("You feel less tired.\n") if ch != victim: ch.send("Ok.\n") return def spell_remove_curse( sn, level, ch, victim, target ): found = False # do object cases first */ if target == TARGET_OBJ: obj = victim if IS_OBJ_STAT(obj,ITEM_NODROP) or IS_OBJ_STAT(obj,ITEM_NOREMOVE): if not IS_OBJ_STAT(obj,ITEM_NOUNCURSE) and not saves_dispel(level + 2,obj.level,0): REMOVE_BIT(obj.extra_flags,ITEM_NODROP) REMOVE_BIT(obj.extra_flags,ITEM_NOREMOVE) act("$p glows blue.",ch,obj,None,TO_ALL) return act("The curse on $p is beyond your power.",ch,obj,None,TO_CHAR) return act("There doesn't seem to be a curse on $p.",ch,obj,None,TO_CHAR) return # characters */ if check_dispel(level,victim,const.skill_table['curse']): victim.send("You feel better.\n") act("$n looks more relaxed.",victim,None,None,TO_ROOM) for obj in victim.carrying: if (IS_OBJ_STAT(obj,ITEM_NODROP) or IS_OBJ_STAT(obj,ITEM_NOREMOVE)) and not IS_OBJ_STAT(obj,ITEM_NOUNCURSE): # attempt to remove curse */ if not saves_dispel(level,obj.level,0): REMOVE_BIT(obj.extra_flags,ITEM_NODROP) REMOVE_BIT(obj.extra_flags,ITEM_NOREMOVE) act("Your $p glows blue.",victim,obj,None,TO_CHAR) act("$n's $p glows blue.",victim,obj,None,TO_ROOM) break def spell_sanctuary( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_SANCTUARY): if victim == ch: ch.send("You are already in sanctuary.\n") else: act("$N is already in sanctuary.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level // 6 af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_SANCTUARY victim.affect_add(af) act( "$n is surrounded by a white aura.", victim, None, None, TO_ROOM ) victim.send("You are surrounded by a white aura.\n") def spell_shield( sn, level, ch, victim, target ): if is_affected( victim, sn ): if victim == ch: ch.send("You are already shielded from harm.\n") else: act("$N is already protected by a shield.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 8 + level af.location = APPLY_AC af.modifier = -20 af.bitvector = 0 victim.affect_add(af) act( "$n is surrounded by a force shield.", victim, None, None, TO_ROOM ) victim.send("You are surrounded by a force shield.\n") return def spell_shocking_grasp( sn, level, ch, victim, target ): dam_each = [ 0, 0, 0, 0, 0, 0, 0, 20, 25, 29, 33, 36, 39, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57 ] level = min(level, len(dam_each)-1) level = max(0, level) dam = random.randint( dam_each[level] // 2, dam_each[level] * 2 ) if saves_spell( level, victim,DAM_LIGHTNING): dam = dam // 2 damage( ch, victim, dam, sn, DAM_LIGHTNING ,True) def spell_sleep( sn, level, ch, victim, target ): if IS_AFFECTED(victim, AFF_SLEEP) \ or (IS_NPC(victim) and IS_SET(victim.act,ACT_UNDEAD)) \ or (level + 2) < victim.level \ or saves_spell( level-4, victim,DAM_CHARM): return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = 4 + level af.location = APPLY_NONE af.modifier = 0 af.bitvector = AFF_SLEEP victim.affect_join(af) if IS_AWAKE(victim): victim.send("You feel very sleepy ..... zzzzzz.\n") act( "$n goes to sleep.", victim, None, None, TO_ROOM ) victim.position = POS_SLEEPING def spell_slow( sn, level, ch, victim, target ): if is_affected( victim, sn ) or IS_AFFECTED(victim,AFF_SLOW): if victim == ch: ch.send("You can't move any slower! \n") else: act("$N can't get any slower than that.", ch,None,victim,TO_CHAR) return if saves_spell(level,victim,DAM_OTHER) or IS_SET(victim.imm_flags,IMM_MAGIC): if victim != ch: ch.send("Nothing seemed to happen.\n") victim.send("You feel momentarily lethargic.\n") return if IS_AFFECTED(victim,AFF_HASTE): if not check_dispel(level,victim,const.skill_table['haste']): if victim != ch: ch.send("Spell failed.\n") victim.send("You feel momentarily slower.\n") return act("$n is moving less quickly.",victim,None,None,TO_ROOM) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level//2 af.location = APPLY_DEX af.modifier = -1 - (level >= 18) - (level >= 25) - (level >= 32) af.bitvector = AFF_SLOW victim.affect_add(af) victim.send("You feel yourself slowing d o w n...\n") act("$n starts to move in slow motion.",victim,None,None,TO_ROOM) def spell_stone_skin( sn, level, ch, victim, target ): if is_affected( ch, sn ): if victim == ch: ch.send("Your skin is already as hard as a rock.\n") else: act("$N is already as hard as can be.",ch,None,victim,TO_CHAR) return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level af.location = APPLY_AC af.modifier = -40 af.bitvector = 0 victim.affect_add(af) act( "$n's skin turns to stone.", victim, None, None, TO_ROOM ) victim.send("Your skin turns to stone.\n") def spell_summon( sn, level, ch, victim, target ): victim = ch.get_char_world(target_name) if not victim \ or victim == ch \ or victim.in_room == None \ or IS_SET(ch.in_room.room_flags, ROOM_SAFE) \ or IS_SET(victim.in_room.room_flags, ROOM_SAFE) \ or IS_SET(victim.in_room.room_flags, ROOM_PRIVATE) \ or IS_SET(victim.in_room.room_flags, ROOM_SOLITARY) \ or IS_SET(victim.in_room.room_flags, ROOM_NO_RECALL) \ or (IS_NPC(victim) and IS_SET(victim.act,ACT_AGGRESSIVE)) \ or victim.level >= level + 3 \ or (not IS_NPC(victim) and victim.level >= LEVEL_IMMORTAL) \ or victim.fighting != None \ or (IS_NPC(victim) and IS_SET(victim.imm_flags,IMM_SUMMON)) \ or (IS_NPC(victim) and victim.pIndexData.pShop != None) \ or (not IS_NPC(victim) and IS_SET(victim.act,PLR_NOSUMMON)) \ or (IS_NPC(victim) and saves_spell( level, victim,DAM_OTHER)): ch.send("You failed.\n") return act( "$n disappears suddenly.", victim, None, None, TO_ROOM ) victim.from_room() victim.to_room(ch.in_room) act( "$n arrives suddenly.", victim, None, None, TO_ROOM ) act( "$n has summoned you! ", ch, None, victim, TO_VICT ) victim.do_look("auto") def spell_teleport( sn, level, ch, victim, target ): if victim.in_room == None \ or IS_SET(victim.in_room.room_flags, ROOM_NO_RECALL) \ or ( victim != ch and IS_SET(victim.imm_flags,IMM_SUMMON)) \ or ( not IS_NPC(ch) and victim.fighting != None ) \ or ( victim != ch \ and ( saves_spell( level - 5, victim,DAM_OTHER))): ch.send("You failed.\n") return pRoomIndex = get_random_room(victim) if victim != ch: victim.send("You have been teleported! \n") act( "$n vanishes! ", victim, None, None, TO_ROOM ) victim.from_room() victim.to_room(pRoomIndex) act( "$n slowly fades into existence.", victim, None, None, TO_ROOM ) victim.do_look( "auto" ) def spell_ventriloquate( sn, level, ch, victim, target ): target_name, speaker = read_word( target_name ) buf1 = "%s says '%s'.\n" % ( speaker.capitalize(), target_name ) buf2 = "Someone makes %s say '%s'.\n" % ( speaker, target_name ) for vch in ch.in_room.people: if not is_exact_name( speaker, vch.name) and IS_AWAKE(vch): vch.send( buf2 if saves_spell(level,vch,DAM_OTHER) else buf1) def spell_weaken( sn, level, ch, victim, target ): if is_affected( victim, sn ) or saves_spell( level, victim,DAM_OTHER): return af = AFFECT_DATA() af.where = TO_AFFECTS af.type = sn af.level = level af.duration = level // 2 af.location = APPLY_STR af.modifier = -1 * (level // 5) af.bitvector = AFF_WEAKEN victim.affect_add(af) victim.send("You feel your strength slip away.\n") act("$n looks tired and weak.",victim,None,None,TO_ROOM) # RT recall spell is back */ def spell_word_of_recall( sn, level, ch, victim, target ): if IS_NPC(victim): return if ROOM_VNUM_TEMPLE not in room_index_hash: victim.send("You are completely lost.\n") return location = room_index_hash[ROOM_VNUM_TEMPLE] if IS_SET(victim.in_room.room_flags,ROOM_NO_RECALL) or IS_AFFECTED(victim,AFF_CURSE): victim.send("Spell failed.\n") return if victim.fighting: stop_fighting(victim,True) ch.move = move // 2 act("$n disappears.",victim,None,None,TO_ROOM) victim.from_room() victim.to_room(location) act("$n appears in the room.",victim,None,None,TO_ROOM) victim.do_look("auto") # NPC spells. def spell_acid_breath( sn, level, ch, victim, target ): act("$n spits acid at $N.",ch,None,victim,TO_NOTVICT) act("$n spits a stream of corrosive acid at you.",ch,None,victim,TO_VICT) act("You spit acid at $N.",ch,None,victim,TO_CHAR) hpch = max(12,ch.hit) hp_dam = random.randint(hpch//11 + 1, hpch//6) dice_dam = dice(level,16) dam = max(hp_dam + dice_dam//10,dice_dam + hp_dam//10) if saves_spell(level,victim,DAM_ACID): acid_effect(victim,level//2,dam//4,TARGET_CHAR) damage(ch,victim,dam//2,sn,DAM_ACID,True) else: acid_effect(victim,level,dam,TARGET_CHAR) damage(ch,victim,dam,sn,DAM_ACID,True) def spell_fire_breath( sn, level, ch, victim, target ): act("$n breathes forth a cone of fire.",ch,None,victim,TO_NOTVICT) act("$n breathes a cone of hot fire over you! ",ch,None,victim,TO_VICT) act("You breath forth a cone of fire.",ch,None,None,TO_CHAR) hpch = max( 10, ch.hit ) hp_dam = random.randint( hpch//9+1, hpch//5 ) dice_dam = dice(level,20) dam = max(hp_dam + dice_dam //10, dice_dam + hp_dam // 10) fire_effect(victim.in_room,level,dam//2,TARGET_ROOM) for vch in victim.in_room.people[:]: if is_safe_spell(ch,vch,True) or (IS_NPC(vch) and IS_NPC(ch) and (ch.fighting != vch or vch.fighting != ch)): continue if vch == victim: # full damage */ if saves_spell(level,vch,DAM_FIRE): fire_effect(vch,level//2,dam//4,TARGET_CHAR) damage(ch,vch,dam//2,sn,DAM_FIRE,True) else: fire_effect(vch,level,dam,TARGET_CHAR) damage(ch,vch,dam,sn,DAM_FIRE,True) else: # partial damage */ if saves_spell(level - 2,vch,DAM_FIRE): fire_effect(vch,level//4,dam//8,TARGET_CHAR) damage(ch,vch,dam//4,sn,DAM_FIRE,True) else: fire_effect(vch,level//2,dam//4,TARGET_CHAR) damage(ch,vch,dam//2,sn,DAM_FIRE,True) def spell_frost_breath( sn, level, ch, victim, target ): act("$n breathes out a freezing cone of frost! ",ch,None,victim,TO_NOTVICT) act("$n breathes a freezing cone of frost over you! ", ch,None,victim,TO_VICT) act("You breath out a cone of frost.",ch,None,None,TO_CHAR) hpch = max(12,ch.hit) hp_dam = random.randint(hpch//11 + 1, hpch//6) dice_dam = dice(level,16) dam = max(hp_dam + dice_dam//10,dice_dam + hp_dam//10) cold_effect(victim.in_room,level,dam//2,TARGET_ROOM) for vch in victim.in_room.people[:]: if is_safe_spell(ch,vch,True) or (IS_NPC(vch) and IS_NPC(ch) and (ch.fighting != vch or vch.fighting != ch)): continue if vch == victim: # full damage */ if saves_spell(level,vch,DAM_COLD): cold_effect(vch,level//2,dam//4,TARGET_CHAR) damage(ch,vch,dam//2,sn,DAM_COLD,True) else: cold_effect(vch,level,dam,TARGET_CHAR) damage(ch,vch,dam,sn,DAM_COLD,True) else: if saves_spell(level - 2,vch,DAM_COLD): cold_effect(vch,level//4,dam//8,TARGET_CHAR) damage(ch,vch,dam//4,sn,DAM_COLD,True) else: cold_effect(vch,level//2,dam//4,TARGET_CHAR) damage(ch,vch,dam//2,sn,DAM_COLD,True) def spell_gas_breath( sn, level, ch, victim, target ): act("$n breathes out a cloud of poisonous gas! ",ch,None,None,TO_ROOM) act("You breath out a cloud of poisonous gas.",ch,None,None,TO_CHAR) hpch = max(16,ch.hit) hp_dam = random.randint(hpch//15+1,8) dice_dam = dice(level,12) dam = max(hp_dam + dice_dam//10,dice_dam + hp_dam//10) poison_effect(ch.in_room,level,dam,TARGET_ROOM) for vch in ch.in_room.people[:]: if is_safe_spell(ch,vch,True) or (IS_NPC(ch) and IS_NPC(vch) and (ch.fighting == vch or vch.fighting == ch)): continue if saves_spell(level,vch,DAM_POISON): poison_effect(vch,level//2,dam//4,TARGET_CHAR) damage(ch,vch,dam//2,sn,DAM_POISON,True) else: poison_effect(vch,level,dam,TARGET_CHAR) damage(ch,vch,dam,sn,DAM_POISON,True) def spell_lightning_breath( sn, level, ch, victim, target ): act("$n breathes a bolt of lightning at $N.",ch,None,victim,TO_NOTVICT) act("$n breathes a bolt of lightning at you! ",ch,None,victim,TO_VICT) act("You breathe a bolt of lightning at $N.",ch,None,victim,TO_CHAR) hpch = max(10,ch.hit) hp_dam = random.randint(hpch//9+1,hpch//5) dice_dam = dice(level,20) dam = max(hp_dam + dice_dam//10,dice_dam + hp_dam//10) if saves_spell(level,victim,DAM_LIGHTNING): shock_effect(victim,level//2,dam//4,TARGET_CHAR) damage(ch,victim,dam//2,sn,DAM_LIGHTNING,True) else: shock_effect(victim,level,dam,TARGET_CHAR) damage(ch,victim,dam,sn,DAM_LIGHTNING,True) # #* Spells for mega1.are from Glop//Erkenbrand. def spell_general_purpose( sn, level, ch, victim, target ): dam = random.randint( 25, 100 ) if saves_spell( level, victim, DAM_PIERCE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_PIERCE ,True) return def spell_high_explosive( sn, level, ch, victim, target ): dam = random.randint( 30, 120 ) if saves_spell( level, victim, DAM_PIERCE): dam = dam // 2 damage( ch, victim, dam, sn, DAM_PIERCE ,True) #### #### What was Magic2.c def spell_farsight(sn, level, ch, victim, target): if IS_AFFECTED(ch,AFF_BLIND): ch.send("Maybe it would help if you could see?\n") return ch.do_scan(target_name) def spell_portal( sn, level, ch, victim, target): victim = ch.get_char_world(target_name) if not victim \ or victim == ch \ or victim.in_room == None \ or not ch.can_see_room(victim.in_room) \ or IS_SET(victim.in_room.room_flags, ROOM_SAFE) \ or IS_SET(victim.in_room.room_flags, ROOM_PRIVATE) \ or IS_SET(victim.in_room.room_flags, ROOM_SOLITARY) \ or IS_SET(victim.in_room.room_flags, ROOM_NO_RECALL) \ or IS_SET(ch.in_room.room_flags, ROOM_NO_RECALL) \ or victim.level >= level + 3 \ or (not IS_NPC(victim) and victim.level >= LEVEL_HERO) \ or (IS_NPC(victim) and IS_SET(victim.imm_flags,IMM_SUMMON)) \ or (IS_NPC(victim) and saves_spell( level, victim,DAM_NONE) ) \ or (victim.is_clan() and not ch.is_same_clan(victim)): ch.send( "You failed.\n") return stone = ch.get_eq(WEAR_HOLD) if not IS_IMMORTAL(ch) and (stone == None or stone.item_type != ITEM_WARP_STONE): ch.send("You lack the proper component for this spell.\n") return if stone and stone.item_type == ITEM_WARP_STONE: act("You draw upon the power of $p.",ch,stone,None,TO_CHAR) act("It flares brightly and vanishes! ",ch,stone,None,TO_CHAR) stone.extract() portal = create_object(obj_index_hash[OBJ_VNUM_PORTAL],0) portal.timer = 2 + level // 25 portal.value[3] = victim.in_room.vnum portal.to_room(ch.in_room) act("$p rises up from the ground.",ch,portal,None,TO_ROOM) act("$p rises up before you.",ch,portal,None,TO_CHAR) def spell_nexus( sn, level, ch, victim, target): from_room = ch.in_room victim = ch.get_char_world(target_name) to_room = victim.in_room if not victim \ or victim == ch \ or not to_room \ or not ch.can_see_room(to_room) or not ch.can_see_room(from_room) \ or IS_SET(to_room.room_flags, ROOM_SAFE) \ or IS_SET(from_room.room_flags,ROOM_SAFE) \ or IS_SET(to_room.room_flags, ROOM_PRIVATE) \ or IS_SET(to_room.room_flags, ROOM_SOLITARY) \ or IS_SET(to_room.room_flags, ROOM_NO_RECALL) \ or IS_SET(from_room.room_flags,ROOM_NO_RECALL) \ or victim.level >= level + 3 \ or (not IS_NPC(victim) and victim.level >= LEVEL_HERO) \ or (IS_NPC(victim) and IS_SET(victim.imm_flags,IMM_SUMMON)) \ or (IS_NPC(victim) and saves_spell( level, victim,DAM_NONE) ) \ or (victim.is_clan() and not ch.is_same_clan(victim)): ch.send("You failed.\n") return stone = ch.get_eq(WEAR_HOLD) if not IS_IMMORTAL(ch) and (stone == None or stone.item_type != ITEM_WARP_STONE): ch.send("You lack the proper component for this spell.\n") return if stone and stone.item_type == ITEM_WARP_STONE: act("You draw upon the power of $p.",ch,stone,None,TO_CHAR) act("It flares brightly and vanishes! ",ch,stone,None,TO_CHAR) stone.extract() # portal one */ portal = create_object(obj_index_hash[OBJ_VNUM_PORTAL],0) portal.timer = 1 + level // 10 portal.value[3] = to_room.vnum portal.to_room(from_room) act("$p rises up from the ground.",ch,portal,None,TO_ROOM) act("$p rises up before you.",ch,portal,None,TO_CHAR) # no second portal if rooms are the same */ if to_room == from_room: return # portal two */ portal = create_object(obj_index_hash[OBJ_VNUM_PORTAL],0) portal.timer = 1 + level//10 portal.value[3] = from_room.vnum portal.to_room(to_room) if to_room.people: act("$p rises up from the ground.",to_room.people[0],portal,None,TO_ROOM) act("$p rises up from the ground.",to_room.people[0],portal,None,TO_CHAR)