/* ************************************************************************ * File: spells.c Part of CircleMUD * * Usage: Implementation of "manual spells". Circle 2.2 spell compat. * * * * All rights reserved. See license.doc for complete information. * * * * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * ************************************************************************ */ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "spells.h" #include "handler.h" #include "db.h" #include "interpreter.h" #include "house.h" extern int arena_zone; extern int arena_preproom; extern int arena_observeroom; extern int arena_combatant; extern int arena_observer; extern int arena_flee_timeout; extern struct char_data *arenamaster; extern struct room_data *world; extern struct obj_data *object_list; extern struct char_data *character_list; extern struct cha_app_type cha_app[]; extern struct int_app_type int_app[]; extern struct index_data *obj_index; extern struct descriptor_data *descriptor_list; extern struct zone_data *zone_table; struct house_control_rec house_control[MAX_HOUSES]; int num_of_houses; extern int mini_mud; extern int pk_allowed; extern struct default_mobile_stats *mob_defaults; extern char weapon_verbs[]; extern int *max_ac_applys; extern struct apply_mod_defaults *apmd; extern char *dirs[]; void clearMemory (struct char_data *ch); void act (char *str, int i, struct char_data *c, struct obj_data *o, void *vict_obj, int j); void damage (struct char_data *ch, struct char_data *victim, int damage, int weapontype); void match_over(struct char_data *, struct char_data *, char *, int); void weight_change_object (struct obj_data *obj, int weight); void add_follower (struct char_data *ch, struct char_data *leader); int mag_savingthrow (struct char_data *ch, struct char_data *victim); char* numdisplay(int); int find_house (room_vnum vnum); /* * Special spells appear below. */ ASPELL (spell_create_water) { int water; void name_to_drinkcon (struct obj_data *obj, int type); void name_from_drinkcon (struct obj_data *obj); if (ch == NULL || obj == NULL) return; level = MAX (MIN (level, LVL_IMPL), 1); if (GET_OBJ_TYPE (obj) == ITEM_DRINKCON) { if ((GET_OBJ_VAL (obj, 2) != LIQ_WATER) && (GET_OBJ_VAL (obj, 1) != 0)) { name_from_drinkcon (obj); GET_OBJ_VAL (obj, 2) = LIQ_SLIME; name_to_drinkcon (obj, LIQ_SLIME); } else { water = MAX (GET_OBJ_VAL (obj, 0) - GET_OBJ_VAL (obj, 1), 0); if (water > 0) { if (GET_OBJ_VAL (obj, 1) >= 0) name_from_drinkcon (obj); GET_OBJ_VAL (obj, 2) = LIQ_WATER; GET_OBJ_VAL (obj, 1) += water; name_to_drinkcon (obj, LIQ_WATER); weight_change_object (obj, water); act ("$p is filled.", FALSE, ch, obj, 0, TO_CHAR); } } } } ASPELL (spell_recall) { extern long mortal_start_room[NUM_STARTROOMS + 1]; /* extern long r_mortal_start_room[NUM_STARTROOMS + 1]; */ char mybuf[1024]; struct char_data *victor; int home; home = GET_HOME(ch); if (!(home >= 1 && home <= NUM_STARTROOMS)){ sprintf(mybuf, "DEBUG: Recall Trigger - %s GET_HOME is %d (invalid)", GET_NAME(ch), home); mudlog(mybuf, NRM, LVL_GRGOD, TRUE); home = 0; } if (victim == NULL || IS_NPC (victim)) return; if (RIDING(victim) || RIDDEN_BY(victim)) { send_to_char("The spell fails because your victim is atop a mount.\r\n", ch); return; } act ("$n disappears.", TRUE, victim, 0, 0, TO_ROOM); if (IS_ARENACOMBATANT(victim)){ victor = FIGHTING(victim); sprintf(mybuf, "(Recalled)"); if (GET_ARENAFLEETIMER(victim) >= 1 && GET_ARENAFLEETIMER(victim) <= 1+arena_flee_timeout){ victor = LASTFIGHTING(victim); send_to_char("You recalled before the flee-recall timer expired.\r\n" "You have conceded the match!\r\n", victim); sprintf(mybuf, "(Fled & Recalled)"); GET_ARENAFLEETIMER(victim) = 0; } match_over(victor, victim, mybuf, FALSE); char_from_room (victim); char_to_room (victim, real_room (arena_preproom)); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); return; } char_from_room (victim); if (GET_ARENASTAT(victim) == ARENA_OBSERVER){ char_to_room (victim, real_room (arena_observeroom)); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); return; } if (home == 0) { char_to_room (victim, real_room (mortal_start_room[1])); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); } else { char_to_room (victim, real_room (mortal_start_room[home])); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); } } ASPELL (spell_teleport) { int to_room; extern int top_of_world; if (victim != NULL) return; do { to_room = number (0, top_of_world); } while (ROOM_FLAGGED (to_room, ROOM_PRIVATE | ROOM_DEATH)); act ("$n slowly fades out of existence and is gone.", FALSE, victim, 0, 0, TO_ROOM); char_from_room (victim); char_to_room (victim, to_room); act ("$n slowly fades into existence.", FALSE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); } #define SUMMON_FAIL "You failed.\r\n" ASPELL (spell_summon) { extern int real_zone(int number); extern struct index_data *mob_index; if (ch == NULL || victim == NULL) return; if (GET_LEVEL (victim) > MIN (LVL_IMMORT - 1, level + 3)) { send_to_char (SUMMON_FAIL, ch); return; } if (IS_NPC(victim)) if (real_zone(GET_MOB_VNUM(victim))!=-1) if (zone_table[real_zone(GET_MOB_VNUM(victim))].status_mode==0) { send_to_char(SUMMON_FAIL, ch); return; } if (GET_ARENASTAT(victim) != ARENA_NOT && GET_ARENASTAT(ch) == ARENA_NOT){ send_to_char ("Your target is in the arena right now.\r\n" "Eldrich magic obstructs thee!\r\n", ch); return; } if (GET_ARENASTAT(victim) == ARENA_NOT && GET_ARENASTAT(ch) != ARENA_NOT){ send_to_char ("You're in the arena right now whereas your target is not.\r\n" "Eldrich magic obstructs thee!\r\n", ch); return; } /* if (!pk_allowed) * { */ if (MOB_FLAGGED (victim, MOB_AGGRESSIVE)) { act ("As the words escape your lips and $N travels\r\n" "through time and space towards you, you realize that $E is\r\n" "aggressive and might harm you, so you wisely send $M back.", FALSE, ch, 0, victim, TO_CHAR); return; } if (!IS_NPC (victim) && !PRF_FLAGGED (victim, PRF_SUMMONABLE)) /* && !PLR_FLAGGED (victim, PLR_KILLER)) */ { sprintf (buf, "%s just tried to summon you to: %s.\r\n" "%s failed because you have summon protection on.\r\n" "Type NOSUMMON to allow other players to summon you.\r\n", GET_NAME (ch), world[ch->in_room].name, (ch->player.sex == SEX_MALE) ? "He" : "She"); send_to_char (buf, victim); sprintf (buf, "You failed because %s has summon protection on.\r\n", GET_NAME (victim)); send_to_char (buf, ch); sprintf (buf, "%s failed summoning %s to %s.", GET_NAME (ch), GET_NAME (victim), world[ch->in_room].name); mudlog (buf, BRF, LVL_IMMORT, TRUE); return; /* } */ } if (MOB_FLAGGED (victim, MOB_NOSUMMON) || (IS_NPC (victim) && mag_savingthrow (ch, victim))) { send_to_char (SUMMON_FAIL, ch); return; } act ("$n disappears suddenly.", TRUE, victim, 0, 0, TO_ROOM); char_from_room (victim); char_to_room (victim, ch->in_room); act ("$n arrives suddenly.", TRUE, victim, 0, 0, TO_ROOM); act ("$n has summoned you!", FALSE, ch, 0, victim, TO_VICT); look_at_room (victim, 0); } ASPELL (spell_locate_object) { struct obj_data *i; char name[MAX_INPUT_LENGTH]; int j; strcpy (name, fname (obj->name)); j = level >> 1; for (i = object_list; i && (j > 0); i = i->next) { if (!is_name (name, i->name)) continue; if (i->carried_by) sprintf (buf, "%s is being carried by %s.\n\r", i->short_description, PERS (i->carried_by, ch)); else if (i->in_room != NOWHERE) sprintf (buf, "%s is in %s.\n\r", i->short_description, world[i->in_room].name); else if (i->in_obj) sprintf (buf, "%s is in %s.\n\r", i->short_description, i->in_obj->short_description); else if (i->worn_by) sprintf (buf, "%s is being worn by %s.\n\r", i->short_description, PERS (i->worn_by, ch)); else sprintf (buf, "%s's location is uncertain.\n\r", i->short_description); CAP (buf); send_to_char (buf, ch); j--; } if (j == level >> 1) send_to_char ("You sense nothing.\n\r", ch); } ASPELL (spell_charm) { struct affected_type af; if (victim == NULL || ch == NULL) return; if (victim == ch) send_to_char ("You like yourself even better!\r\n", ch); else if (!IS_NPC (victim) && !PRF_FLAGGED (victim, PRF_SUMMONABLE)) send_to_char ("You fail because SUMMON protection is on!\r\n", ch); else if (IS_AFFECTED (victim, AFF_SANCTUARY)) send_to_char ("Your victim is protected by sanctuary!\r\n", ch); else if (MOB_FLAGGED (victim, MOB_NOCHARM)) send_to_char ("Your victim resists!\r\n", ch); else if (IS_AFFECTED (ch, AFF_CHARM)) send_to_char ("You can't have any followers of your own!\r\n", ch); else if (IS_AFFECTED (victim, AFF_CHARM) || level < GET_LEVEL (victim)) send_to_char ("You fail.\r\n", ch); /* player charming another player - no legal reason for this */ else if (!pk_allowed && !IS_NPC (victim)) send_to_char ("You fail - shouldn't be doing it anyway.\r\n", ch); else if (circle_follow (victim, ch)) send_to_char ("Sorry, following in circles can not be allowed.\r\n", ch); else if (mag_savingthrow (ch, victim)) send_to_char ("Your victim resists!\r\n", ch); else { if (victim->master) stop_follower (victim); add_follower (victim, ch); af.type = SPELL_CHARM; if (GET_INT (victim)) af.duration = 24 * MAX_PLAYER_STAT / GET_INT (victim); else af.duration = 24 * MAX_PLAYER_STAT; af.modifier = 0; af.location = 0; af.bitvector = AFF_CHARM; affect_to_char (victim, &af); act ("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT); if (IS_NPC (victim)) { REMOVE_BIT (MOB_FLAGS (victim), MOB_AGGRESSIVE); REMOVE_BIT (MOB_FLAGS (victim), MOB_SPEC); } } } ASPELL (spell_identify) { int i; int found; int condition; struct time_info_data age (struct char_data *ch); extern char *spells[]; extern char *item_types[]; extern char *extra_bits[]; extern char *apply_types[]; extern char *affected_bits[]; if (obj) { send_to_char ("You feel informed:\r\n", ch); sprintf (buf, "Object '%s', Item type: ", obj->short_description); sprinttype (GET_OBJ_TYPE (obj), (const char **) item_types, buf2); strcat (buf, buf2); strcat (buf, "\r\n"); send_to_char (buf, ch); if (obj->obj_flags.bitvector) { send_to_char ("Item will give you following abilities: ", ch); sprintbit (obj->obj_flags.bitvector, (const char **) affected_bits, buf); strcat (buf, "\r\n"); send_to_char (buf, ch); } send_to_char ("Item is: ", ch); sprintbit (GET_OBJ_EXTRA (obj), (const char **) extra_bits, buf); strcat (buf, "\r\n"); send_to_char (buf, ch); sprintf (buf, "Weight: %s, ", numdisplay(GET_OBJ_WEIGHT (obj))); sprintf (buf, "%sValue: %s, ", buf, numdisplay(GET_OBJ_COST (obj))); sprintf (buf, "%sRent: %s\r\n", buf, numdisplay(GET_OBJ_RENT (obj))); send_to_char(buf, ch); if (GET_OBJ_TSLOTS(obj)) condition = (GET_OBJ_CSLOTS(obj) * 100)/GET_OBJ_TSLOTS(obj); else condition = 0; if ((GET_OBJ_CSLOTS(obj) == 0) && (GET_OBJ_TSLOTS(obj) == 0)) { sprintf(buf, "Quality: INDESTRUCTABLE\r\n"); send_to_char(buf, ch); } else if ((GET_LEVEL(ch) >= LVL_HERO)) { sprintf(buf, "Quality: %d/%d\r\nCondition: %d percent\r\n", GET_OBJ_CSLOTS(obj), GET_OBJ_TSLOTS(obj), condition); send_to_char(buf, ch); } else if ((condition <= 10)) { sprintf(buf, "Quality: Extremley Poor\r\n"); send_to_char(buf, ch); } else if ((condition <= 20)) { sprintf(buf, "Quality: Poor\r\n"); send_to_char(buf, ch); } else if ((condition <= 30)) { sprintf(buf, "Quality: Fair\r\n"); send_to_char(buf, ch); } else if ((condition <= 40)) { sprintf(buf, "Quality: Moderate\r\n"); send_to_char(buf, ch); } else if ((condition <= 50)) { sprintf(buf, "Quality: Good\r\n"); send_to_char(buf, ch); } else if ((condition <= 60)) { sprintf(buf, "Quality: Very Good\r\n"); send_to_char(buf, ch); } else if ((condition <= 70)) { sprintf(buf, "Quality: Excellent\r\n"); send_to_char(buf, ch); } else if ((condition <= 80)) { sprintf(buf, "Quality: Superior\r\n"); send_to_char(buf, ch); } else if ((condition <= 90)) { sprintf(buf, "Quality: Extremely Superior\r\n"); send_to_char(buf, ch); } else if ((condition <= 100)) { sprintf(buf, "Quality: Brand New\r\n"); send_to_char(buf, ch); } switch (GET_OBJ_TYPE (obj)) { case ITEM_SCROLL: case ITEM_POTION: sprintf (buf, "This %s casts: ", item_types[(int) GET_OBJ_TYPE (obj)]); if (GET_OBJ_VAL (obj, 1) >= 1) sprintf (buf, "%s %s", buf, spells[GET_OBJ_VAL (obj, 1)]); if (GET_OBJ_VAL (obj, 2) >= 1) sprintf (buf, "%s %s", buf, spells[GET_OBJ_VAL (obj, 2)]); if (GET_OBJ_VAL (obj, 3) >= 1) sprintf (buf, "%s %s", buf, spells[GET_OBJ_VAL (obj, 3)]); sprintf (buf, "%s\r\n", buf); send_to_char (buf, ch); break; case ITEM_WAND: case ITEM_STAFF: sprintf (buf, "This %s casts: ", item_types[(int) GET_OBJ_TYPE (obj)]); sprintf (buf, "%s %s\r\n", buf, spells[GET_OBJ_VAL (obj, 3)]); sprintf (buf, "%sIt has %d maximum charge%s and %d remaining.\r\n", buf, GET_OBJ_VAL (obj, 1), GET_OBJ_VAL (obj, 1) == 1 ? "" : "s", GET_OBJ_VAL (obj, 2)); send_to_char (buf, ch); break; case ITEM_WEAPON: sprintf (buf, "Damage Dice is '%dD%d'", GET_OBJ_VAL (obj, 1), GET_OBJ_VAL (obj, 2)); sprintf (buf, "%s for an average per-round damage of %.1f.\r\n", buf, (((GET_OBJ_VAL (obj, 2) + 1) / 2.0) * GET_OBJ_VAL (obj, 1))); send_to_char (buf, ch); break; case ITEM_ARMOR: sprintf (buf, "Defense apply is %d\r\n", GET_OBJ_VAL (obj, 0)); send_to_char (buf, ch); break; } found = FALSE; for (i = 0; i < MAX_OBJ_AFFECT; i++) { if ((obj->affected[i].location != APPLY_NONE) && (obj->affected[i].modifier != 0)) { if (!found) { send_to_char ("Can affect you as :\r\n", ch); found = TRUE; } sprinttype (obj->affected[i].location, (const char **) apply_types, buf2); sprintf (buf, " Affects: %s By %d\r\n", buf2, obj->affected[i].modifier); send_to_char (buf, ch); } } } else if (victim) { /* victim */ sprintf (buf, "Name: %s\r\n", GET_NAME (victim)); send_to_char (buf, ch); if (!IS_NPC (victim)) { sprintf (buf, "%s is %d years, %d months, %d days and %d hours old.\r\n", GET_NAME (victim), (int) age (victim).year, (int) age (victim).month, (int) age (victim).day, age (victim).hours); send_to_char (buf, ch); } sprintf (buf, "Height %d cm, Weight %d pounds\r\n", GET_HEIGHT (victim), GET_WEIGHT (victim)); sprintf (buf, "%sLevel: %d, Hits: %d, Mana: %d\r\n", buf, GET_LEVEL (victim), (int) GET_HIT (victim), (int) GET_MANA (victim)); sprintf (buf, "%sPower: %d, Magic Power: %d, Defense: %d, Magic Defense: %d, Technique: %d\r\n", buf, GET_POWER (victim), GET_MPOWER (victim), GET_DEFENSE (victim), GET_MDEFENSE(victim), GET_TECHNIQUE(victim)); sprintf (buf, "%sStr: %d/%d, Int: %d, Wis: %d, Dex: %d, Con: %d, Cha: %d\r\n", buf, GET_STR (victim), GET_ADD (victim), GET_INT (victim), GET_WIS (victim), GET_DEX (victim), GET_CON (victim), GET_CHA (victim)); send_to_char (buf, ch); } } ASPELL (spell_enchant_weapon) { int i; if (ch == NULL || obj == NULL) return; if ((GET_OBJ_TYPE (obj) == ITEM_WEAPON) && !IS_SET (GET_OBJ_EXTRA (obj), ITEM_MAGIC)) { for (i = 0; i < MAX_OBJ_AFFECT; i++) if (obj->affected[i].location != APPLY_NONE) return; SET_BIT (GET_OBJ_EXTRA (obj), ITEM_MAGIC); obj->affected[0].location = APPLY_POWER; obj->affected[0].modifier = 1 + (level >= MAX_PLAYER_STAT); obj->affected[1].location = APPLY_TECHNIQUE; obj->affected[1].modifier = 1 + (level >= MAX_PLAYER_STAT); if (IS_GOOD (ch)) { SET_BIT (GET_OBJ_EXTRA (obj), ITEM_ANTI_EVIL); act ("$p glows blue.", FALSE, ch, obj, 0, TO_CHAR); } else if (IS_EVIL (ch)) { SET_BIT (GET_OBJ_EXTRA (obj), ITEM_ANTI_GOOD); act ("$p glows red.", FALSE, ch, obj, 0, TO_CHAR); } else { act ("$p glows yellow.", FALSE, ch, obj, 0, TO_CHAR); } } } ASPELL (spell_detect_poison) { if (victim) { if (victim == ch) { if (IS_AFFECTED (victim, AFF_POISON)) send_to_char ("You can sense poison in your blood.\r\n", ch); else send_to_char ("You feel healthy.\r\n", ch); } else { if (IS_AFFECTED (victim, AFF_POISON)) act ("You sense that $E is poisoned.", FALSE, ch, 0, victim, TO_CHAR); else act ("You sense that $E is healthy.", FALSE, ch, 0, victim, TO_CHAR); } } if (obj) { switch (GET_OBJ_TYPE (obj)) { case ITEM_DRINKCON: case ITEM_FOUNTAIN: case ITEM_FOOD: if (GET_OBJ_VAL (obj, 3)) act ("You sense that $p has been contaminated.", FALSE, ch, obj, 0, TO_CHAR); else act ("You sense that $p is safe for consumption.", FALSE, ch, obj, 0, TO_CHAR); break; default: send_to_char ("You sense that it should not be consumed.\r\n", ch); } } } ASPELL (spell_fear) { struct char_data *target = (struct char_data *) victim; struct char_data *next_target; int rooms_to_flee = 0; ACMD (do_flee); if (ch == NULL) return; send_to_char ("You radiate an aura of fear into the room!\r\n", ch); act ("$n is surrounded by an aura of fear!", TRUE, ch, 0, 0, TO_ROOM); for (target = world[ch->in_room].people; target; target = next_target) { next_target = target->next_in_room; if (target == NULL) return; if (target == ch) continue; if (GET_LEVEL (target) >= LVL_IMMORT) continue; if (mag_savingthrow (ch, target)) { sprintf (buf, "%s is unaffected by the fear!\r\n", GET_NAME (target)); act (buf, TRUE, ch, 0, 0, TO_ROOM); send_to_char ("Your victim is not afraid of the likes of you!\r\n", ch); if (IS_NPC (target)) hit (target, ch, TYPE_UNDEFINED); } else { for (rooms_to_flee = level / 10; rooms_to_flee > 0; rooms_to_flee--) { send_to_char ("You flee in terror!\r\n", target); do_flee (target, "", 0, 0); } } } } ASPELL (spell_recharge) { int restored_charges = 0, explode = 0; if (ch == NULL || obj == NULL) return; /* This is on my mud, comment off on yours * if (GET_OBJ_EXTRA(obj) == ITEM_NO_RECHARGE) { * send_to_char("This item cannot be recharged.\r\n", ch); return; } */ if (GET_OBJ_TYPE (obj) == ITEM_WAND) { if (GET_OBJ_VAL (obj, 2) < GET_OBJ_VAL (obj, 1)) { send_to_char ("You attempt to recharge the wand.\r\n", ch); restored_charges = number (1, 5); GET_OBJ_VAL (obj, 2) += restored_charges; if (GET_OBJ_VAL (obj, 2) > GET_OBJ_VAL (obj, 1)) { send_to_char ("The wand is overcharged and explodes!\r\n", ch); sprintf (buf, "%s overcharges %s and it explodes!\r\n", GET_NAME (ch), obj->name); act (buf, TRUE, 0, 0, 0, TO_NOTVICT); explode = dice (GET_OBJ_VAL (obj, 2), 2); GET_HIT (ch) -= explode; update_pos (ch); extract_obj (obj); return; } else { sprintf (buf, "You restore %d charges to the wand.\r\n", restored_charges); send_to_char (buf, ch); return; } } else { send_to_char ("That item is already at full charges!\r\n", ch); return; } } else if (GET_OBJ_TYPE (obj) == ITEM_STAFF) { if (GET_OBJ_VAL (obj, 2) < GET_OBJ_VAL (obj, 1)) { send_to_char ("You attempt to recharge the staff.\r\n", ch); restored_charges = number (1, 3); GET_OBJ_VAL (obj, 2) += restored_charges; if (GET_OBJ_VAL (obj, 2) > GET_OBJ_VAL (obj, 1)) { send_to_char ("The staff is overcharged and explodes!\r\n", ch); sprintf (buf, "%s overcharges %s and it explodes!\r\n", GET_NAME (ch), obj->name); act (buf, TRUE, 0, 0, 0, TO_NOTVICT); explode = dice (GET_OBJ_VAL (obj, 2), 3); GET_HIT (ch) -= explode; update_pos (ch); extract_obj (obj); return; } else { sprintf (buf, "You restore %d charges to the staff.\r\n", restored_charges); send_to_char (buf, ch); return; } } else { send_to_char ("That item is already at full charges!\r\n", ch); return; } } } #define PORTAL 20 ASPELL(spell_portal) { /* create a magic portal */ struct obj_data *tmp_obj, *tmp_obj2; struct extra_descr_data *ed; struct room_data *rp, *nrp; struct char_data *tmp_ch = (struct char_data *) victim; char buf[512]; assert(ch); assert((level >= 0) && (level <= LVL_IMPL)); /* check target room for legality. */ rp = &world[ch->in_room]; tmp_obj = read_object(PORTAL, VIRTUAL); if (!rp || !tmp_obj) { send_to_char("The magic fails.\n\r", ch); extract_obj(tmp_obj); return; } if (IS_SET(rp->room_flags, ROOM_NOMAGIC) || (PRF2_FLAGGED(victim, PRF2_INTANGIBLE) && (GET_LEVEL(ch)<LVL_IMMORT || IS_NPC(ch)))) { send_to_char("Eldritch wizardry obstructs thee.\n\r", ch); extract_obj(tmp_obj); return; } if (IS_SET(rp->room_flags, ROOM_TUNNEL)) { send_to_char("There is no room in here to summon!\n\r", ch); extract_obj(tmp_obj); return; } if (!(nrp = &world[tmp_ch->in_room])) { char str[180]; sprintf(str, "%s tried to portal to %s but target not in any room!", GET_NAME(ch), GET_NAME(tmp_ch)); log(str); send_to_char("The magic cannot locate the target.\n", ch); extract_obj(tmp_obj); return; } if (IS_NPC(tmp_ch) && GET_LEVEL(ch) < LVL_IMMORT) { send_to_char("The magic cannot locate the target.\n", ch); extract_obj(tmp_obj); return; } if (tmp_ch->in_room == ch->in_room) { send_to_char("You are already at the target area.\n", ch); extract_obj(tmp_obj); return; } if ((GET_LEVEL(tmp_ch) >= LVL_IMMORT) && (GET_LEVEL(ch) < LVL_IMMORT)) { send_to_char("You cannot travel to the gods!\n", ch); extract_obj(tmp_obj); return; } if (GET_ARENASTAT(tmp_ch) != ARENA_NOT && GET_ARENASTAT(ch) == ARENA_NOT){ send_to_char ("Your target is in the arena right now.\r\n" "Eldrich magic obstructs thee!\r\n", ch); extract_obj(tmp_obj); return; } if (GET_ARENASTAT(tmp_ch) == ARENA_NOT && GET_ARENASTAT(ch) != ARENA_NOT){ send_to_char ("You're in the arena right now whereas your target is not.\r\n" "Eldrich magic obstructs thee!\r\n", ch); extract_obj(tmp_obj); return; } if (ROOM_FLAGGED(tmp_ch->in_room, ROOM_NOMAGIC)) { send_to_char("Your target is protected against your magic.\n\r", ch); extract_obj(tmp_obj); return; } if (ROOM_FLAGGED(tmp_ch->in_room, ROOM_HOUSE) || ROOM_FLAGGED(tmp_ch->in_room, ROOM_HOUSE_CRASH)) { if (find_house(world[tmp_ch->in_room].number) != GET_IDNUM(ch)) { send_to_char("Your target is protected against your magic.\n\r", ch); extract_obj(tmp_obj); return; } } if (ROOM_FLAGGED(tmp_ch->in_room, ROOM_PRIVATE)) { send_to_char("Your target is protected against your magic.\n\r", ch); extract_obj(tmp_obj); return; } if (ROOM_FLAGGED(tmp_ch->in_room, ROOM_TUNNEL)) { send_to_char("There is not enough room there to portal!\n\r", ch); extract_obj(tmp_obj); return; } if (IS_AFFECTED (tmp_ch, AFF_NOPORTAL)) { send_to_char("Your target's magic resists your portal attempt.\r\n", ch); extract_obj(tmp_obj); return; } sprintf(buf, "Through the mists of the portal, you can faintly see %s", nrp->name); CREATE(ed , struct extra_descr_data, 1); ed->next = tmp_obj->ex_description; tmp_obj->ex_description = ed; CREATE(ed->keyword, char, strlen(tmp_obj->name) + 1); strcpy(ed->keyword, tmp_obj->name); ed->description = str_dup(buf); tmp_obj->obj_flags.value[0] = 1; tmp_obj->obj_flags.value[1] = tmp_ch->in_room; if (GET_LEVEL(ch) < LVL_IMMORT) GET_OBJ_TIMER(tmp_obj)=1; else GET_OBJ_TIMER(tmp_obj)=-1; // Never dissapear. obj_to_room(tmp_obj,ch->in_room); act("$p suddenly appears.",TRUE,ch,tmp_obj,0,TO_ROOM); act("$p suddenly appears.",TRUE,ch,tmp_obj,0,TO_CHAR); /* Portal at other side */ rp = &world[ch->in_room]; tmp_obj2 = read_object(PORTAL, VIRTUAL); if (!rp || !tmp_obj2) { send_to_char("The magic fails.\n\r", ch); extract_obj(tmp_obj2); return; } sprintf(buf, "Through the mists of the portal, you can faintly see %s", rp->name); CREATE(ed , struct extra_descr_data, 1); ed->next = tmp_obj2->ex_description; tmp_obj2->ex_description = ed; CREATE(ed->keyword, char, strlen(tmp_obj2->name) + 1); strcpy(ed->keyword, tmp_obj2->name); ed->description = str_dup(buf); tmp_obj2->obj_flags.value[0] = 1; tmp_obj2->obj_flags.value[1] = ch->in_room; if (GET_LEVEL(ch) < LVL_IMMORT) GET_OBJ_TIMER(tmp_obj2)=1; else GET_OBJ_TIMER(tmp_obj2)=-1; // Never dissapear. obj_to_room(tmp_obj2,tmp_ch->in_room); act("$p suddenly appears.",TRUE,tmp_ch,tmp_obj2,0,TO_ROOM); act("$p suddenly appears.",TRUE,tmp_ch,tmp_obj2,0,TO_CHAR); } ASPELL(spell_locate_target) { struct char_data *i; char name[MAX_INPUT_LENGTH]; int j; strcpy(name, fname(victim->player.name)); j = level >> 1; for (i = character_list; i && (j > 0); i = i->next) { if (!is_name(name, i->player.name)) continue; if (i->in_room != NOWHERE) sprintf(buf, "%s is in %s.\n\r", IS_NPC(i) ? i->player.short_descr : i->player.name, world[i->in_room].name); else sprintf(buf, "%s's location is uncertain.\r\n", IS_NPC(i) ? i->player.short_descr : i->player.name); CAP(buf); send_to_char(buf, ch); j--; } if (j == level >> 1) send_to_char("You sense nothing.\n\r", ch); } ACMD(do_speed) { if (GET_SKILL(ch, SKILL_SPEED) == 0) { send_to_char("You have no idea how to speed.\r\n", ch); return; } if (GET_MANA(ch) == GET_MAX_MANA(ch)) { send_to_char("You retract and flex your muscles with strength.\r\n", ch); GET_MANA(ch) = 0; GET_MOVE(ch) = GET_MAX_MOVE(ch); send_to_char("You feel revived and ready to move again.\r\n", ch); } else { send_to_char("You must have full mana in order to speed!\r\n", ch); return; } } #define CAN_LISTEN_BEHIND_DOOR(ch,dir) \ (GET_CLASS(ch) == CLASS_THIEF) && \ (EXIT(ch, dir) && EXIT(ch, dir)->to_room != NOWHERE && \ IS_SET(EXIT(ch, dir)->exit_info, EX_CLOSED))) ACMD(do_listen) { struct char_data *tch, *tch_next; int dir, percent, found = 0; char *heard_nothing = "You don't hear anything unusual.\r\n"; char *room_spiel = "$n seems to listen intently for something."; percent = number(1,101); if(GET_SKILL(ch, SKILL_LISTEN) < percent) { send_to_char(heard_nothing, ch); return; } one_argument(argument, buf); if(!*buf) { /* no argument means that the character is listening for * hidden or invisible beings in the room he/she is in */ for(tch = world[ch->in_room].people; tch; tch = tch_next) { tch_next = tch->next_in_room; if((tch != ch) && !CAN_SEE(ch, tch) && (GET_LEVEL(tch) < LVL_IMMORT)) found++; } if(found) { if(GET_LEVEL(ch) >= 15) { /* being a higher level is better */ sprintf(buf, "You hear what might be %d creatures invisible, or hiding.\r\n", \ MAX(1,(found+number(0,1)-number(0,1)))); } else sprintf(buf, "You hear an odd rustling in the immediate area.\r\n"); send_to_char(buf, ch); } else send_to_char(heard_nothing, ch); act(room_spiel, TRUE, ch, 0, 0, TO_ROOM); return; } else { /* the argument must be one of the cardinal directions: north, * south, etc. */ for(dir = 0; dir < NUM_OF_DIRS; dir++) { if(!strncmp(buf, dirs[dir], strlen(buf))) break; } if (dir == NUM_OF_DIRS) { send_to_char("Listen where?\r\n", ch); return; } if((CAN_GO(ch, dir)) || (CAN_LISTEN_BEHIND_DOOR(ch, dir)) { for(tch = world[EXIT(ch, dir)->to_room].people; tch; tch=tch_next) { tch_next = tch->next_in_room; found++; } if(found) { if(GET_LEVEL(ch) >= 15) { sprintf(buf, "You hear what might be %d creatures %s%s.\r\n", \ MAX(1,(found+number(0,1)-number(0,1))), ((dir==5)?"below":(dir==4)?"above": "to the "), ((dir==5)?"":(dir==4)?"":dirs[dir])); } else sprintf(buf, "You hear sounds from %s%s.\r\n", \ ((dir==5)?"below":(dir==4)?"above": "the "), ((dir==5)?"":(dir==4)?"":dirs[dir])); send_to_char(buf, ch); } else send_to_char(heard_nothing, ch); act(room_spiel, TRUE, ch, 0, 0, TO_ROOM); return; } else send_to_char("You can't listen in that direction.\r\n", ch); return; } return; } ASPELL(spell_home) { extern long mortal_start_room[NUM_STARTROOMS + 1]; int i, homenum = 0, loadrm = -1; char mybuf[1024]; struct char_data *victor; for (i = 0; i < num_of_houses; i++) if (house_control[i].owner == GET_IDNUM(ch)) homenum = house_control[i].vnum; if (homenum == 0){ send_to_char("The spell fails because you don't own a house!\r\n", ch); return; } if (RIDING(victim) || RIDDEN_BY(victim)) { send_to_char("The spell fails because your victim is atop a mount.\r\n", ch); return; } loadrm = GET_HOME(ch); if (!(loadrm >= 1 && loadrm <= NUM_STARTROOMS)){ sprintf(buf, "DEBUG: Home Recall Trigger - %s GET_HOME is %d (invalid)", GET_NAME(ch), loadrm); mudlog(buf, NRM, LVL_GRGOD, TRUE); loadrm = 1; } loadrm = real_room(mortal_start_room[loadrm]); if (ch->in_room == real_room(homenum)){ send_to_char("The spell fails because you're already at home!\r\n", ch); return; } if (IS_ARENACOMBATANT(victim)){ victor = FIGHTING(victim); sprintf(mybuf, "(Recalled)"); if (GET_ARENAFLEETIMER(victim) >= 1 && GET_ARENAFLEETIMER(victim) <= 1+arena_flee_timeout){ victor = LASTFIGHTING(victim); send_to_char("You recalled before the flee-recall timer expired.\r\n" "You have conceded the match!\r\n", victim); sprintf(mybuf, "(Fled & Recalled)"); GET_ARENAFLEETIMER(victim) = 0; } match_over(victor, victim, mybuf, FALSE); char_from_room (victim); char_to_room (victim, real_room (arena_preproom)); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); return; } act ("$n magically teleports out.", FALSE, ch, 0, 0, TO_ROOM); char_from_room(ch); if (GET_ARENASTAT(victim) == ARENA_OBSERVER){ char_to_room (victim, real_room (arena_observeroom)); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); return; } char_to_room(ch, real_room(homenum)); act("$n suddenly appears in the room.", FALSE, ch, 0, 0, TO_ROOM); look_at_room(ch, 0); send_to_char("\r\nAhhhh... Home Sweet Home!\r\n", ch); } ASPELL (spell_retreat) { int load_room = 0; char mybuf[1024]; struct char_data *victor; if (victim == NULL || IS_NPC (victim)) return; if ((load_room == NOWHERE || load_room == 0 || !load_room)) { send_to_char("You must rent somewhere before you can retreat!\r\n", ch); return; } if (RIDING(victim) || RIDDEN_BY(victim)) { send_to_char("The spell fails because your victim is atop a mount.\r\n", ch); return; } act ("$n disappears.", TRUE, victim, 0, 0, TO_ROOM); if (IS_ARENACOMBATANT(victim)){ victor = FIGHTING(victim); sprintf(mybuf, "(Recalled)"); if (GET_ARENAFLEETIMER(victim) >= 1 && GET_ARENAFLEETIMER(victim) <= 1+arena_flee_timeout){ victor = LASTFIGHTING(victim); send_to_char("You recalled before the flee-recall timer expired.\r\n" "You have conceded the match!\r\n", victim); sprintf(mybuf, "(Fled & Recalled)"); GET_ARENAFLEETIMER(victim) = 0; } match_over(victor, victim, mybuf, FALSE); char_from_room (victim); char_to_room (victim, real_room (arena_preproom)); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); return; } char_from_room (victim); if (GET_ARENASTAT(victim) == ARENA_OBSERVER){ char_to_room (victim, real_room (arena_observeroom)); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); return; } char_to_room (victim, real_room(GET_LOADROOM(victim))); act ("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM); look_at_room (victim, 0); }