/*************************************************************************** * 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. * ***************************************************************************/ /********************************************************** *************** S U N D E R M U D *** 2 . 0 ************** ********************************************************** * The unique portions of the SunderMud code as well as * * the integration efforts for code from other sources is * * based primarily on the efforts of: * * * * Lotherius <aelfwyne@operamail.com> (Alvin W. Brinson) * * and many others, see "help sundermud" in the mud. * **********************************************************/ #include "everything.h" #include "magic.h" #include "interp.h" /* command procedures needed */ /* Got tired of declaring dofuns, so I included interp.h. booya. */ /* * The following special functions are available for mobiles. */ DECLARE_SPEC_FUN ( spec_breath_any ); DECLARE_SPEC_FUN ( spec_breath_acid ); DECLARE_SPEC_FUN ( spec_breath_fire ); DECLARE_SPEC_FUN ( spec_breath_frost ); DECLARE_SPEC_FUN ( spec_breath_gas ); DECLARE_SPEC_FUN ( spec_breath_lightning ); DECLARE_SPEC_FUN ( spec_cast_adept ); DECLARE_SPEC_FUN ( spec_cast_cleric ); DECLARE_SPEC_FUN ( spec_cast_judge ); DECLARE_SPEC_FUN ( spec_cast_mage ); DECLARE_SPEC_FUN ( spec_cast_undead ); DECLARE_SPEC_FUN ( spec_executioner ); DECLARE_SPEC_FUN ( spec_fido ); DECLARE_SPEC_FUN ( spec_guard ); DECLARE_SPEC_FUN ( spec_janitor ); DECLARE_SPEC_FUN ( spec_poison ); DECLARE_SPEC_FUN ( spec_thief ); //DECLARE_SPEC_FUN ( spec_puff ); /* Removed because it was so damn buggy DECLARE_SPEC_FUN ( spec_questmaster ); /* Vassago */ DECLARE_SPEC_FUN ( spec_crier ); /* Lotherius town crier */ //DECLARE_SPEC_FUN ( spec_metamob ); /* * Special Functions Table. OLC */ const struct spec_type spec_table[] = { /* * Special function commands. */ {"spec_breath_any", spec_breath_any}, {"spec_breath_acid", spec_breath_acid}, {"spec_breath_fire", spec_breath_fire}, {"spec_breath_frost", spec_breath_frost}, {"spec_breath_gas", spec_breath_gas}, {"spec_breath_lightning", spec_breath_lightning}, {"spec_cast_adept", spec_cast_adept}, {"spec_cast_cleric", spec_cast_cleric}, {"spec_cast_judge", spec_cast_judge}, {"spec_cast_mage", spec_cast_mage}, {"spec_cast_undead", spec_cast_undead}, {"spec_executioner", spec_executioner}, {"spec_fido", spec_fido}, {"spec_guard", spec_guard}, {"spec_janitor", spec_janitor}, {"spec_poison", spec_poison}, {"spec_thief", spec_thief}, {"spec_questmaster", spec_questmaster}, /* Vassago */ {"spec_crier", spec_crier}, // {"spec_metamob", spec_metamob }, /* * End of list. */ {"", 0} }; /***************************************************************************** Name: spec_lookup Purpose: Given a name, return the appropriate spec fun. Called by: do_mset(act_wiz.c) load_specials,reset_area(db.c) ****************************************************************************/ SPEC_FUN *spec_lookup ( const char *name ) /* OLC */ { int cmd; for ( cmd = 0; spec_table[cmd].spec_name[0] != '\0'; cmd++ ) if ( !str_cmp ( name, spec_table[cmd].spec_name ) ) return spec_table[cmd].spec_fun; return 0; } /* * Core procedure for dragons. */ bool dragon ( CHAR_DATA * ch, char *spell_name ) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits ( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; if ( ( sn = skill_lookup ( spell_name ) ) < 0 ) return FALSE; ( *skill_table[sn].spell_fun ) ( sn, ch->level, ch, victim ); return TRUE; } /***************************************************************************** Name: spec_string Purpose: Given a function, return the appropriate name. Called by: <???> ****************************************************************************/ char *spec_string ( SPEC_FUN * fun ) /* OLC */ { int cmd; for ( cmd = 0; spec_table[cmd].spec_name[0] != '\0'; cmd++ ) if ( fun == spec_table[cmd].spec_fun ) return spec_table[cmd].spec_name; return 0; } /* * Special procedures for mobiles. */ bool spec_breath_any ( CHAR_DATA * ch ) { if ( ch->position != POS_FIGHTING ) return FALSE; switch ( number_bits ( 3 ) ) { case 0: return spec_breath_fire ( ch ); case 1: case 2: return spec_breath_lightning ( ch ); case 3: return spec_breath_gas ( ch ); case 4: return spec_breath_acid ( ch ); case 5: case 6: case 7: return spec_breath_frost ( ch ); } return FALSE; } bool spec_breath_acid ( CHAR_DATA * ch ) { return dragon ( ch, "acid breath" ); } bool spec_breath_fire ( CHAR_DATA * ch ) { return dragon ( ch, "fire breath" ); } bool spec_questmaster ( CHAR_DATA * ch ) { if ( ch->fighting != NULL ) return spec_cast_mage ( ch ); return FALSE; } bool spec_breath_frost ( CHAR_DATA * ch ) { return dragon ( ch, "frost breath" ); } bool spec_breath_gas ( CHAR_DATA * ch ) { int sn; if ( ch->position != POS_FIGHTING ) return FALSE; if ( ( sn = skill_lookup ( "gas breath" ) ) < 0 ) return FALSE; ( *skill_table[sn].spell_fun ) ( sn, ch->level, ch, NULL ); return TRUE; } bool spec_breath_lightning ( CHAR_DATA * ch ) { return dragon ( ch, "lightning breath" ); } bool spec_crier ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; struct crier_type *tmp = NULL; char outbuf[MAX_STRING_LENGTH]; int i, count = 0; /* First off, let's do adept since all criers are adept */ spec_cast_adept ( ch ); /* Adjust this number for more or less cries */ if ( number_range ( 1, 10 ) < 7 ) return FALSE; /* Get a count */ for ( tmp = crier_list; tmp != NULL; tmp = tmp->next ) { count++; } tmp = NULL; /* Now do the crying! */ if ( !IS_AWAKE ( ch ) ) return FALSE; if ( is_affected ( ch, skill_lookup ( "mute" ) ) && !is_affected ( ch, skill_lookup ( "vocalize" ) ) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; /* Look for any target that can see the crier. One is good enough. */ if ( victim != ch && can_see ( ch, victim ) && number_bits ( 1 ) == 0 && !IS_NPC ( victim ) ) { /* Select a random cry to shout */ i = number_range ( 1, count ); /* Get # to stop on */ count = 1; /* Reset Count */ for ( tmp = crier_list; tmp != NULL; tmp = tmp->next ) { if ( count == i ) { /* Display a cry */ SNP ( outbuf, "{c$n cries out '{W%s{c'{w\r\n", tmp->text ); act ( outbuf, ch, NULL, NULL, TO_ROOM ); /* sends it to just this room */ /* In future, have newbie and area cries too. */ return TRUE; } else { count++; } } /* End of crier_list */ } /* End of looking for a victim that can see. */ } /* No victims if code reaches here. */ return FALSE; } bool spec_cast_adept ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; if ( !IS_AWAKE ( ch ) ) return FALSE; if ( is_affected ( ch, skill_lookup ( "mute" ) ) && !is_affected ( ch, skill_lookup ( "vocalize" ) ) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim != ch && can_see ( ch, victim ) && number_bits ( 1 ) == 0 && !IS_NPC ( victim ) && victim->level < 11 ) break; } if ( victim == NULL ) return FALSE; switch ( number_bits ( 4 ) ) { case 0: act ( "$n utters the word 'abrazak'.", ch, NULL, NULL, TO_ROOM ); spell_armor ( skill_lookup ( "armor" ), ch->level, ch, victim ); return TRUE; case 1: act ( "$n utters the word 'fido'.", ch, NULL, NULL, TO_ROOM ); spell_bless ( skill_lookup ( "bless" ), ch->level, ch, victim ); return TRUE; case 2: act ( "$n utters the word 'judicandus noselacri'.", ch, NULL, NULL, TO_ROOM ); spell_cure_blindness ( skill_lookup ( "cure blindness" ), ch->level, ch, victim ); return TRUE; case 3: act ( "$n utters the word 'judicandus dies'.", ch, NULL, NULL, TO_ROOM ); spell_cure_light ( skill_lookup ( "cure light" ), ch->level, ch, victim ); return TRUE; case 4: act ( "$n utters the words 'judicandus sausabru'.", ch, NULL, NULL, TO_ROOM ); spell_cure_poison ( skill_lookup ( "cure poison" ), ch->level, ch, victim ); return TRUE; case 5: act ( "$n utters the words 'candusima'.", ch, NULL, NULL, TO_ROOM ); spell_refresh ( skill_lookup ( "refresh" ), ch->level, ch, victim ); return TRUE; } return FALSE; } bool spec_cast_cleric ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; if ( is_affected ( ch, skill_lookup ( "mute" ) ) && !is_affected ( ch, skill_lookup ( "vocalize" ) ) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits ( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_bits ( 4 ) ) { case 0: min_level = 0; spell = "blindness"; break; case 1: min_level = 3; spell = "cause serious"; break; case 2: min_level = 7; spell = "earthquake"; break; case 3: min_level = 9; spell = "cause critical"; break; case 4: min_level = 10; spell = "dispel evil"; break; case 5: min_level = 12; spell = "curse"; break; case 6: min_level = 12; spell = "change sex"; break; case 7: min_level = 13; spell = "flamestrike"; break; case 8: case 9: case 10: min_level = 15; spell = "harm"; break; case 11: min_level = 15; spell = "plague"; break; case 12: case 13: case 14: min_level = 34; spell = ( IS_EVIL ( ch ) ? "demonfire" : "exorcism" ); break; default: min_level = 16; spell = "dispel magic"; break; } if ( ch->hit < ( ch->max_hit / 5 ) && ch->level > 13 ) { spell = "cure critical"; victim = ch; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup ( spell ) ) < 0 ) return FALSE; if ( ch->mana < skill_table[sn].min_mana ) return FALSE; ( *skill_table[sn].spell_fun ) ( sn, ch->level, ch, victim ); ch->mana -= skill_table[sn].min_mana; return TRUE; } bool spec_cast_judge ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; if ( is_affected ( ch, skill_lookup ( "mute" ) ) && !is_affected ( ch, skill_lookup ( "vocalize" ) ) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits ( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; spell = "high explosive"; if ( ( sn = skill_lookup ( spell ) ) < 0 ) return FALSE; ( *skill_table[sn].spell_fun ) ( sn, ch->level, ch, victim ); return TRUE; } bool spec_cast_mage ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; if ( is_affected ( ch, skill_lookup ( "mute" ) ) && !is_affected ( ch, skill_lookup ( "vocalize" ) ) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits ( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_bits ( 4 ) ) { case 0: min_level = 0; spell = "blindness"; break; case 1: min_level = 3; spell = "chill touch"; break; case 2: min_level = 7; spell = "weaken"; break; case 3: min_level = 8; spell = "teleport"; break; case 4: min_level = 11; spell = "colour spray"; break; case 5: min_level = 12; spell = "change sex"; break; case 6: min_level = 13; spell = "energy drain"; break; case 7: case 8: case 9: min_level = 15; spell = "fireball"; break; case 10: min_level = 20; spell = "plague"; break; default: min_level = 20; spell = "acid blast"; break; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup ( spell ) ) < 0 ) return FALSE; ( *skill_table[sn].spell_fun ) ( sn, ch->level, ch, victim ); return TRUE; } bool spec_cast_undead ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; if ( is_affected ( ch, skill_lookup ( "mute" ) ) && !is_affected ( ch, skill_lookup ( "vocalize" ) ) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits ( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_bits ( 4 ) ) { case 0: min_level = 0; spell = "curse"; break; case 1: min_level = 3; spell = "weaken"; break; case 2: min_level = 6; spell = "chill touch"; break; case 3: min_level = 9; spell = "blindness"; break; case 4: min_level = 12; spell = "poison"; break; case 5: min_level = 15; spell = "energy drain"; break; case 6: min_level = 18; spell = "harm"; break; case 7: min_level = 21; spell = "teleport"; break; case 8: min_level = 20; spell = "plague"; break; default: min_level = 18; spell = "harm"; break; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup ( spell ) ) < 0 ) return FALSE; ( *skill_table[sn].spell_fun ) ( sn, ch->level, ch, victim ); return TRUE; } bool spec_executioner ( CHAR_DATA * ch ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; CHAR_DATA *v_next; char *crime; if ( !IS_AWAKE ( ch ) || ch->fighting != NULL ) return FALSE; crime = ""; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC ( victim ) && IS_SET ( victim->act, PLR_KILLER ) ) { crime = "KILLER"; break; } if ( !IS_NPC ( victim ) && IS_SET ( victim->act, PLR_THIEF ) ) { crime = "THIEF"; break; } } if ( victim == NULL ) return FALSE; /* Why have one default mob_cityuard vnum when we have different cityguards? */ SNP ( buf, "%s is a %s! PROTECT THE INNOCENT! MORE BLOOOOD!!!", victim->name, crime ); do_yell ( ch, buf ); multi_hit ( ch, victim, TYPE_UNDEFINED ); char_to_room ( create_mobile ( get_mob_index ( ch->pIndexData->vnum ) ), ch->in_room ); char_to_room ( create_mobile ( get_mob_index ( ch->pIndexData->vnum ) ), ch->in_room ); return TRUE; } bool spec_fido ( CHAR_DATA * ch ) { OBJ_DATA *corpse; OBJ_DATA *c_next; OBJ_DATA *obj; OBJ_DATA *obj_next; if ( !IS_AWAKE ( ch ) ) return FALSE; for ( corpse = ch->in_room->contents; corpse != NULL; corpse = c_next ) { c_next = corpse->next_content; if ( corpse->item_type != ITEM_CORPSE_NPC ) continue; act ( "$n savagely devours a corpse.", ch, NULL, NULL, TO_ROOM ); for ( obj = corpse->contains; obj; obj = obj_next ) { obj_next = obj->next_content; obj_from_obj ( obj ); obj_to_room ( obj, ch->in_room ); } extract_obj ( corpse ); return TRUE; } return FALSE; } bool spec_guard ( CHAR_DATA * ch ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; CHAR_DATA *v_next; CHAR_DATA *ech; char *crime; int max_evil; if ( !IS_AWAKE ( ch ) || ch->fighting != NULL ) return FALSE; max_evil = 300; ech = NULL; crime = ""; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC ( victim ) && IS_SET ( victim->act, PLR_KILLER ) ) { crime = "KILLER"; break; } if ( !IS_NPC ( victim ) && IS_SET ( victim->act, PLR_THIEF ) ) { crime = "THIEF"; break; } if ( victim->fighting != NULL && victim->fighting != ch && victim->alignment < max_evil ) { max_evil = victim->alignment; ech = victim; } } if ( victim != NULL ) { SNP ( buf, "%s is a %s! PROTECT THE INNOCENT!! BANZAI!!", victim->name, crime ); do_yell ( ch, buf ); multi_hit ( ch, victim, TYPE_UNDEFINED ); return TRUE; } if ( ech != NULL ) { act ( "$n screams 'PROTECT THE INNOCENT!! BANZAI!!", ch, NULL, NULL, TO_ROOM ); multi_hit ( ch, ech, TYPE_UNDEFINED ); return TRUE; } return FALSE; } bool spec_janitor ( CHAR_DATA * ch ) { OBJ_DATA *trash; OBJ_DATA *trash_next; if ( !IS_AWAKE ( ch ) ) return FALSE; for ( trash = ch->in_room->contents; trash != NULL; trash = trash_next ) { trash_next = trash->next_content; if ( !IS_SET ( trash->wear_flags, ITEM_TAKE ) || trash->owner || !can_loot ( ch, trash ) ) continue; if ( trash->item_type == ITEM_DRINK_CON || trash->item_type == ITEM_TRASH || trash->cost < 10 ) { act ( "$n picks up some trash.", ch, NULL, NULL, TO_ROOM ); obj_from_room ( trash ); obj_to_char ( trash, ch ); return TRUE; } } return FALSE; } bool spec_poison ( CHAR_DATA * ch ) { CHAR_DATA *victim; if ( ch->position != POS_FIGHTING || ( victim = ch->fighting ) == NULL || number_percent ( ) > 2 * ch->level ) return FALSE; act ( "You bite $N!", ch, NULL, victim, TO_CHAR ); act ( "$n bites $N!", ch, NULL, victim, TO_NOTVICT ); act ( "$n bites you!", ch, NULL, victim, TO_VICT ); spell_poison ( gsn_poison, ch->level, ch, victim ); return TRUE; } // Meta Mob includes just about everything we can think of for a mob to do, // when it is pretending to be a player. // Metamobs disabled till more work can be done on them. /* bool spec_metamob ( CHAR_DATA *ch ) { CHAR_DATA *victim; EXIT_DATA *pexit; ROOM_INDEX_DATA *location; bool rv = FALSE; int door, sn; switch ( ch->position ) { case POS_DEAD: case POS_MORTAL: case POS_INCAP: case POS_STUNNED: break; case POS_SLEEPING: case POS_RESTING: case POS_SITTING: if ( ch->hit >= ch->max_hit ) { do_stand ( ch, "" ); if ( chance ( 25 ) && IS_SET ( ch->act, ACT_WARRIOR ) ) act ( "$n checks $s armor carefully.", ch, NULL, NULL, TO_ROOM ); else if ( chance ( 25 ) ) act ( "$n yawns.", ch, NULL, NULL, TO_ROOM ); rv = TRUE; } break; case POS_STANDING: // Find something to fight or move. if ( chance ( 75 ) && ( ch->hit > ( ch->max_hit / 2 ) ) ) { for ( victim = ch->in_room->people; victim != NULL; victim = victim->next_in_room ) { if ( is_safe ( ch, victim, TRUE ) ) continue; if ( !IS_NPC ( victim ) ) { if ( IS_SET ( victim->act, PLR_THIEF ) ) { do_say ( ch, "You dirty rotten THIEF!\n\r" ); multi_hit ( ch, victim, TYPE_UNDEFINED ); rv = TRUE; break; } else if ( IS_SET ( victim->act, PLR_KILLER ) ) { int domsg; domsg = ( number_range ( 1, 3 ) ); switch ( domsg ) { case 1: do_say ( ch, "Hey! I think you killed my cousin!\n\r" ); break; case 2: do_say ( ch, "Die before my blade!\n\r" ); break; case 3: do_say ( ch, "You know, I really don't like your type.\n\r" ); break; } multi_hit ( ch, victim, TYPE_UNDEFINED ); rv = TRUE; break; } } // Else NPC else { // We're going to make the metamob more selective until this spec function is more // intelligent :) if ( victim->level > ( ch->level +1 ) || victim->level < ( ch->level-5 ) ) continue; // Very simple alignment routines here, could get more complicated if we want. We don't. if ( ch->alignment < -250 && victim->alignment < -250 ) continue; if ( ch->alignment > 250 && victim->alignment > 250 ) continue; do_say ( ch, "Bonzai!!!" ); rv = TRUE; multi_hit ( ch, victim, TYPE_UNDEFINED ); break; } } // End of FOR loop if ( rv ) break; } if ( ch->hit < (ch->max_hit / 2 ) ) // Even mobs have to rest.... { do_sleep ( ch, "" ); rv = TRUE; break; } // Okay if we got here, we didn't start a fight. Look for an exit. // MetaMobs don't get blocked by NO_MOB rooms but other rules apply. if ( !IS_SET ( ch->act, ACT_SENTINEL ) && ( door = number_bits ( 5 ) ) <= 5 && ( pexit = ch->in_room->exit[door] ) != NULL && pexit->u1.to_room != NULL && ( !IS_SET ( ch->act, ACT_STAY_AREA ) || pexit->u1.to_room->area == ch->in_room->area ) ) { do_unlock ( ch, dir_name[door] ); // Unlock and Open do_open ( ch, dir_name[door] ); // May not have they and may not even be a door, just to make sure. move_char ( ch, door, FALSE ); rv = TRUE; break; } // If the char wasn't able to find a door to try, then try to recall sometimes. if ( chance ( 1 ) && !IS_AFFECTED ( ch, AFF_CURSE ) ) { location = get_room_index ( ROOM_VNUM_TEMPLE ); if ( ch->in_room == location ) break; act ( "$n prays for transportation!", ch, 0, 0, TO_ROOM ); act ( "$n disappears.", ch, NULL, NULL, TO_ROOM ); char_from_room ( ch ); char_to_room ( ch, location ); act ( "$n appears in the room.", ch, NULL, NULL, TO_ROOM ); rv = TRUE; break; } break; case POS_FIGHTING: if ( ch->hit < ( ch->max_hit / 5 ) ) { do_flee ( ch, "" ); rv = TRUE; } else if ( IS_SET ( ch->act, ACT_WARRIOR ) ) { int wdo; if ( chance ( 20 ) ) // 20% of rounds won't do any action. break; wdo = number_range ( 1, 5 ); switch (wdo) { case 1: if ( ( sn = skill_lookup ( "disarm" ) ) > 0 ) do_disarm ( ch, "" ); rv = TRUE; break; case 2: if ( ( sn = skill_lookup ( "bash" ) ) > 0 ) do_bash ( ch, "" ); rv = TRUE; break; case 3: case 4: if ( ( sn = skill_lookup ( "dirt kicking" ) ) > 0 ) do_dirt ( ch, "" ); rv = TRUE; break; case 5: if ( ( sn = skill_lookup ( "kick" ) ) > 0 ) do_kick ( ch, "" ); rv = TRUE; } if ( !rv ) // Whatever we tried to do didn't have a valid skill, this is our failsafe { if ( ( sn = skill_lookup ( "kick" ) ) > 0 ) do_kick ( ch, "" ); } } else if ( IS_SET ( ch->act, ACT_CLERIC ) ) { rv = spec_cast_cleric ( ch ); // Do some other stuff here if spec_cast_cleric returned FALSE } else if ( IS_SET ( ch->act, ACT_MAGE ) ) { rv = spec_cast_mage ( ch ); // Do some other stuff here if spec_cast_mage returned FALSE } else if ( IS_SET ( ch->act, ACT_THIEF ) ) tail_chain (); // Just here as a null function till I write the thief function. break; default: bugf ("Invalid position on spec_metamob." ); break; } return rv; } */ bool spec_thief ( CHAR_DATA * ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; long gold; if ( ch->position != POS_STANDING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( IS_NPC ( victim ) || victim->level >= LEVEL_IMMORTAL || number_bits ( 5 ) != 0 || !can_see ( ch, victim ) ) continue; if ( IS_AWAKE ( victim ) && number_range ( 0, ch->level ) == 0 ) { act ( "You discover $n's hands in your wallet!", ch, NULL, victim, TO_VICT ); act ( "$N discovers $n's hands in $S wallet!", ch, NULL, victim, TO_NOTVICT ); return TRUE; } else { gold = victim->gold * UMIN ( number_range ( 1, 20 ), ch->level ) / 100; gold = UMIN ( gold, ch->level * ch->level * 20 ); ch->gold += gold; victim->gold -= gold; return TRUE; } } return FALSE; } /* Healer code written for Merc 2.0 muds by Alander direct questions or comments to rtaylor@cie-2.uoregon.edu any use of this code must include this header */ void do_heal ( CHAR_DATA * ch, char *argument ) { CHAR_DATA *mob; char arg[MAX_INPUT_LENGTH]; int cost, sn; SPELL_FUN *spell; char *words; /* check for healer */ for ( mob = ch->in_room->people; mob; mob = mob->next_in_room ) { if ( IS_NPC ( mob ) && IS_SET ( mob->act, ACT_IS_HEALER ) ) break; } if ( mob == NULL ) { send_to_char ( "You can't do that here.\n\r", ch ); return; } one_argument ( argument, arg ); if ( arg[0] == '\0' ) { /* display price list */ act ( "$N says 'I offer the following spells:'", ch, NULL, mob, TO_CHAR ); send_to_char ( " light: cure light wounds 30 gold\n\r", ch ); send_to_char ( " serious: cure serious wounds 50 gold\n\r", ch ); send_to_char ( " critic: cure critical wounds 100 gold\n\r", ch ); send_to_char ( " heal: healing spell 1000 gold\n\r", ch ); send_to_char ( " blind: cure blindness 300 gold\n\r", ch ); send_to_char ( " disease: cure disease 1000 gold\n\r", ch ); send_to_char ( " poison: cure poison 300 gold\n\r", ch ); send_to_char ( " uncurse: remove curse 2000 gold\n\r", ch ); send_to_char ( " refresh: restore movement 500 gold\n\r", ch ); send_to_char ( " mana: restore mana 1000 gold\n\r", ch ); send_to_char ( " {gfull{x: all mana, hp, movement 50000 gold\n\r", ch ); send_to_char ( " Type heal <type> to be healed.\n\r", ch ); return; } switch ( arg[0] ) { case 'l': spell = spell_cure_light; sn = skill_lookup ( "cure light" ); words = "judicandus dies"; cost = 30; break; case 's': spell = spell_cure_serious; sn = skill_lookup ( "cure serious" ); words = "judicandus gzfuajg"; cost = 50; break; case 'c': spell = spell_cure_critical; sn = skill_lookup ( "cure critical" ); words = "judicandus qfuhuqar"; cost = 100; break; case 'h': spell = spell_heal; sn = skill_lookup ( "heal" ); words = "pzar"; cost = 1000; break; case 'b': spell = spell_cure_blindness; sn = skill_lookup ( "cure blindness" ); words = "judicandus noselacri"; cost = 300; break; case 'd': spell = spell_cure_disease; sn = skill_lookup ( "cure disease" ); words = "judicandus eugzagz"; cost = 1000; break; case 'p': spell = spell_cure_poison; sn = skill_lookup ( "cure poison" ); words = "judicandus sausabru"; cost = 300; break; case 'u': spell = spell_remove_curse; sn = skill_lookup ( "remove curse" ); words = "candussido judifgz"; cost = 2000; break; case 'r': spell = spell_refresh; sn = skill_lookup ( "refresh" ); words = "candusima"; cost = 500; break; case 'm': spell = NULL; sn = -1; words = "energizer"; cost = 1000; break; case 'f': spell = NULL; sn = -1; words = "{rSim{gsal{ybim{wbam{cba {bsal{ga{ydu {Gsal{Ya{Rdim{m!{x"; cost = 50000; break; default: act ( "$N says 'Type 'heal' for a list of spells.'", ch, NULL, mob, TO_CHAR ); return; } if ( cost > ch->gold ) { act ( "$N says 'You do not have enough gold for my services.'", ch, NULL, mob, TO_CHAR ); return; } WAIT_STATE ( ch, PULSE_VIOLENCE ); ch->gold -= cost; mob->gold += cost; act ( "$n utters the words '$T'.", mob, NULL, words, TO_ROOM ); if ( ( spell == NULL ) && ( arg[0] == 'm' ) ) /* restore mana trap...kinda hackish */ { ch->mana += dice ( 100, 2 ) + mob->level / 4; ch->mana = UMIN ( ch->mana, ch->max_mana ); send_to_char ( "A warm glow passes through you.\n\r", ch ); return; } else if ( ( spell == NULL ) && ( arg[0] == 'f' ) ) { ch->mana = ch->max_mana; ch->hit = ch->max_hit; ch->move = ch->max_move; send_to_char ( "The {gpower{x of the {rg{go{yd{cs{x flows into you!\n\r", ch ); return; } if ( sn == -1 ) return; spell ( sn, mob->level, mob, ch ); }