/*************************************************************************** * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills and Dug Michael. * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ #include "emud.h" /* Wiped clean from old stuff, asuming it will be stored somewhere in a backup file or something - Scandum */ /* predeclarations */ bool cast_spell args( (CHAR_DATA *ch,char *spell) ); void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void do_kill args( ( CHAR_DATA *ch, char *argument ) ); /* 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 ); struct spec_fun_type { char *name; SPEC_FUN *function; }; const struct spec_fun_type spec_fun[]= { {"spec_guard", spec_guard}, {"", NULL} }; /* Given a name, Return the appropriate spec fun. */ SPEC_FUN *spec_lookup( const char *name ) { int i; push_call("spec_lookup(%p)",name); for (i = 0 ; spec_fun[i].name != "" ; i++) { if (strcmp(name, spec_fun[i].name)) { pop_call(); return spec_fun[i].function; } } pop_call(); return NULL; } /* Given a spec function, Return the appropriate name. */ char *spec_name_lookup( SPEC_FUN *fun ) { int i; push_call("spec_name(%p)",fun); for (i = 0 ; spec_fun[i].name != "" ; i++) { if (spec_fun[i].function == fun) { pop_call(); return spec_fun[i].name; } } pop_call(); return 0; } /* Core procedure for dragons. */ bool dragon( CHAR_DATA *ch, char *spell_name ) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn; push_call("dragon(%p,%p)",ch,spell_name); if (ch->position != POS_FIGHTING || (number_bits(3) != 0)) { pop_call(); return FALSE; } for (victim = ch->in_room->first_person ; victim != NULL ; victim = v_next) { v_next = victim->next_in_room; if (victim->fighting && victim->fighting->who == ch && number_bits(2) == 0) { break; } } if (victim == NULL) { pop_call(); return FALSE; } if ((sn = skill_lookup(spell_name)) < 0) { pop_call(); return FALSE; } (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, 0 ); pop_call(); return TRUE; } /* Special procedures for mobiles. */ bool spec_breath_any( CHAR_DATA *ch ) { push_call("spec_breath_any(%p)",ch); if (ch->position != POS_FIGHTING || (number_bits(2) != 0)) { pop_call(); return FALSE; } switch (number_range(1, 5)) { case 1: pop_call(); return spec_breath_fire(ch); case 2: pop_call(); return spec_breath_lightning(ch); case 3: pop_call(); return spec_breath_gas(ch); case 4: pop_call(); return spec_breath_acid(ch); case 5: pop_call(); return spec_breath_frost(ch); } pop_call(); return FALSE; } bool spec_breath_acid( CHAR_DATA *ch ) { push_call("spec_breath_acid)",ch); pop_call(); return dragon( ch, "acid breath" ); } bool spec_breath_fire( CHAR_DATA *ch ) { push_call("spec_breath_fire(%p)",ch); pop_call(); return dragon( ch, "fire breath" ); } bool spec_breath_frost( CHAR_DATA *ch ) { push_call("spec_breath_frost(%p)",ch); pop_call(); return dragon( ch, "frost breath" ); } bool spec_breath_gas( CHAR_DATA *ch ) { push_call("spec_breath_gas(%p)",ch); pop_call(); return dragon( ch, "gas breath" ); } bool spec_breath_lightning( CHAR_DATA *ch ) { push_call("spec_breath_lightning(%p)",ch); pop_call(); return dragon( ch, "lightning breath" ); } bool spec_cast_healer( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; if ( !IS_AWAKE(ch) ) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC(victim) && victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 ) { break; } } if ( victim == NULL ) { pop_call(); return FALSE; } switch ( number_bits( 3 ) ) { case 0: act( "$n utters the word 'romra'.", ch, NULL, NULL, TO_ROOM ); spell_armor( skill_lookup( "armor" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 1: act( "$n utters the word 'ewnam'.", ch, NULL, NULL, TO_ROOM ); spell_bless( skill_lookup( "bless" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 2: act( "$n utters the word 'tolecnal'.", ch, NULL, NULL, TO_ROOM ); spell_cure_blindness( skill_lookup( "cure blindness" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 3: act( "$n utters the word 'lydnelle'.", ch, NULL, NULL, TO_ROOM ); spell_cure_light( skill_lookup( "cure light" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 4: act( "$n utters the word 'aiag'.", ch, NULL, NULL, TO_ROOM ); spell_cure_poison( skill_lookup( "cure poison" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 5: act( "$n utters the word 'sonpyh'.", ch, NULL, NULL, TO_ROOM ); spell_refresh( skill_lookup( "refresh" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 6: act( "$n utters the word 'esimed'.", ch, NULL, NULL, TO_ROOM); spell_refresh( skill_lookup( "refresh" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; } pop_call(); return FALSE; } bool spec_cast_adept( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; push_call("spec_cast_adept(%p)",ch); if ( !IS_AWAKE(ch) ) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 ) { break; } } if ( victim == NULL ) { pop_call(); return FALSE; } switch ( number_bits( 3 ) ) { case 0: act( "$n utters the word 'aiag'.", ch, NULL, NULL, TO_ROOM ); spell_armor( skill_lookup( "armor" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 1: act( "$n utters the word 'sopnyh'.", ch, NULL, NULL, TO_ROOM ); spell_bless( skill_lookup( "bless" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 2: act( "$n utters the word 'suirauqa'.", ch, NULL, NULL, TO_ROOM ); spell_cure_blindness( skill_lookup( "cure blindness" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 3: act( "$n utters the word 'esimed'.", ch, NULL, NULL, TO_ROOM ); spell_cure_light( skill_lookup( "cure light" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 4: act( "$n utters the word 'faldnag'.", ch, NULL, NULL, TO_ROOM ); spell_cure_poison( skill_lookup( "cure poison" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 5: act( "$n utters the word 'ewnam'.", ch, NULL, NULL, TO_ROOM ); spell_refresh( skill_lookup( "refresh" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; case 6: act( "$n utters the word 'madrettor'.", ch, NULL, NULL, TO_ROOM); spell_giant_strength( skill_lookup( "giant strength" ), ch->level, ch, victim, 0 ); pop_call(); return TRUE; } pop_call(); return FALSE; } bool spec_cast_cleric( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; push_call("spec_cast_cleric(%p)",ch); if ( ch->position != POS_FIGHTING ||(number_bits(2)!=0)) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting && victim->fighting->who == ch && number_bits( 2 ) == 0 ) { break; } } if ( victim == NULL ) { pop_call(); 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; default: min_level = 16; spell = "dispel magic"; break; } if ( ch->level >= min_level ) { break; } } if ( ( sn = skill_lookup( spell ) ) < 0 ) { pop_call(); return FALSE; } (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, 0 ); pop_call(); return TRUE; } bool spec_cast_judge( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; push_call("spec_cast_judge(%p)",ch); if ( ch->position != POS_FIGHTING ||(number_bits(2)!=0)) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting && victim->fighting->who == ch && number_bits( 2 ) == 0 ) { break; } } if ( victim == NULL ) { pop_call(); return FALSE; } spell = "high explosive"; if ( ( sn = skill_lookup( spell ) ) < 0 ) { pop_call(); return FALSE; } (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, 0 ); pop_call(); return TRUE; } bool spec_cast_mage( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; push_call("spec_cast_mage(%p)",ch); if ( ch->position != POS_FIGHTING ||(number_bits(2)!=0)) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting && victim->fighting->who == ch && number_bits( 2 ) == 0 ) { break; } } if ( victim == NULL ) { pop_call(); 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 = "color 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; default: min_level = 20; spell = "acid blast"; break; } if ( ch->level >= min_level ) { break; } } if ( ( sn = skill_lookup( spell ) ) < 0 ) { pop_call(); return FALSE; } (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, 0 ); pop_call(); return TRUE; } bool spec_cast_undead( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; push_call("spec_cast_undead(%p)",ch); if ( ch->position != POS_FIGHTING ||(number_bits(2)!=0)) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting && victim->fighting->who == ch && number_bits( 2 ) == 0 ) { break; } } if ( victim == NULL ) { pop_call(); 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 = "burning hands"; 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 = 31; spell = "mage blast"; break; default: min_level = 54; spell = "vampiric touch"; break; } if ( ch->level >= min_level ) { break; } } if ( ( sn = skill_lookup( spell ) ) < 0 ) { pop_call(); return FALSE; } (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, 0 ); pop_call(); 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 || IS_SET( ch->in_room->room_flags, ROOM_SAFE)) { pop_call(); return FALSE; } crime = ""; for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER) ) { crime = "MURDERER"; break; } if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_THIEF) ) { crime = "THIEF"; break; } } if ( victim == NULL ) { pop_call(); return FALSE; } sprintf( buf, "%s is a %s! PROTECT THE INNOCENT! MORE BLOOOOD!!!", victim->name, crime ); do_shout( ch, buf ); multi_hit( ch, victim, TYPE_UNDEFINED ); pop_call(); return TRUE; } bool spec_fido( CHAR_DATA *ch ) { OBJ_DATA *corpse; if (!IS_AWAKE(ch)) { pop_call(); return FALSE; } for (corpse = ch->in_room->first_content ; corpse ; corpse = corpse->next_content) { if (corpse->item_type != ITEM_CORPSE_NPC) { continue; } act("$n savagely devours a corpse.", ch, NULL, NULL, TO_ROOM); while (corpse->first_content) { corpse->first_content->sac_timer = OBJ_SAC_TIME; obj_to_room(corpse->first_content, ch->in_room->vnum); } junk_obj( corpse ); pop_call(); return TRUE; } pop_call(); 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; push_call("spec_guard(%p)",ch); if (!IS_AWAKE(ch) || ch->fighting != NULL || IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { pop_call(); return FALSE; } max_evil = 300; ech = NULL; crime = ""; for (victim = ch->in_room->first_person ; victim ; victim = v_next) { v_next = victim->next_in_room; if (!IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER) ) { if (!IS_AFFECTED(victim, AFF_SNEAK)) { if (!IS_AFFECTED(victim, AFF_STEALTH)) { if (number_percent() < 20) { crime = "MURDERER"; if (victim->level > (10*(int)ch->level)/6) { int scale, divisor, level; /* scale the guard UP to 60% of the victim's level */ level=victim->level; scale=6 * level; level=ch->pIndexData->level; divisor = 10 * level; level=level*scale/divisor; ch->level= (char)level; ch->hit= 1+dice(ch->pIndexData->hitnodice*scale/divisor, ch->pIndexData->hitsizedice*scale/divisor)+ ch->pIndexData->hitplus*scale/divisor; ch->max_hit= ch->hit; ch->npcdata->damnodice= ch->pIndexData->damnodice*scale/divisor; ch->npcdata->damsizedice= ch->pIndexData->damsizedice*scale/divisor; ch->npcdata->damplus= ch->pIndexData->damplus*scale/divisor+1; } break; } } } } if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_THIEF) ) { if(!IS_AFFECTED(victim,AFF_SNEAK)) { if(!IS_AFFECTED(victim,AFF_STEALTH)) { if(number_percent()<20) { crime = "THIEF"; break; } } } } if ( victim->fighting != NULL && victim->fighting->who != ch && victim->alignment < max_evil ) { max_evil = victim->alignment; ech = victim; } } if ( victim != NULL ) { sprintf( buf, "%s is a %s! PROTECT THE INNOCENT!! BANZAI!!", victim->name, crime ); act("$n screams '$T'",ch,NULL,buf,TO_ROOM); multi_hit( ch, victim, TYPE_UNDEFINED ); pop_call(); return TRUE; } if ( ech != NULL ) { if((number_percent()<75)&&(max_evil>-300)&&ech->fighting && (ech->fighting->who->alignment<300)) { act("$n says 'Alright you guys, break it up! NOW!'", ch,NULL,NULL,TO_ROOM); for(victim=ch->in_room->first_person;victim!=NULL;victim=v_next) { v_next = victim->next_in_room; if(!(IS_NPC(victim) && (ch->pIndexData->vnum==victim->pIndexData->vnum))) { stop_fighting(victim,FALSE); } } pop_call(); return TRUE; } act( "$n screams 'PROTECT THE INNOCENT!! BANZAI!!", ch, NULL, NULL, TO_ROOM ); multi_hit( ch, ech, TYPE_UNDEFINED ); pop_call(); return TRUE; } pop_call(); return FALSE; } bool spec_janitor( CHAR_DATA *ch ) { OBJ_DATA *trash; OBJ_DATA *trash_next; push_call("spec_janitor(%p)",ch); if ( !IS_AWAKE(ch) ) { pop_call(); return FALSE; } for ( trash = ch->in_room->first_content; trash != NULL; trash = trash_next ) { trash_next = trash->next_content; if ( !IS_SET( trash->wear_flags, ITEM_TAKE ) ) { continue; } if ( trash->item_type == ITEM_DRINK_CON || trash->item_type == ITEM_TRASH || trash->cost < 101 ) { act( "$n picks up some trash.", ch, NULL, NULL, TO_ROOM ); obj_from_room( trash ); obj_to_char( trash, ch ); pop_call(); return TRUE; } } pop_call(); return FALSE; } bool spec_poison( CHAR_DATA *ch ) { CHAR_DATA *victim; push_call("spec_poison(%p)",ch); if ( ch->position != POS_FIGHTING || ( victim = who_fighting(ch) ) == NULL || number_percent( ) > 2 * ch->level || victim->in_room != ch->in_room ) { pop_call(); 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, skill_table[gsn_poison].target ); pop_call(); return TRUE; } bool spec_thief( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; int gold; push_call("spec_thief(%p)",ch); if ( ch->position != POS_STANDING ) { pop_call(); return FALSE; } for ( victim = ch->in_room->first_person; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( IS_NPC(victim) || victim->level >= LEVEL_IMMORTAL || number_bits( 2 ) != 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 ); pop_call(); return TRUE; } else { gold = victim->gold * number_range( 1, 5 ) / 100; gold = UMIN( gold , 500 ); /* Chaos 10/5/93 */ ch->gold += 7 * gold / 8; victim->gold -= gold; pop_call(); return TRUE; } } pop_call(); return FALSE; }