/***************************************************************************
* 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. *
* *
* Thanks to abaddon for proof-reading our comm.c and pointing out bugs. *
* Any remaining bugs are, of course, our work, not his. :) *
* *
* 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-1996 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Tartarus/doc/rom.license *
***************************************************************************/
/***************************************************************************
* Tartarus code is copyright (C) 1997-1998 by Daniel Graham *
* In using this code you agree to comply with the Tartarus license *
* found in the file /Tartarus/doc/tartarus.doc *
***************************************************************************/
#include "include.h"
char *target_name;
void do_supps( CHAR_DATA *ch, char *argument )
{
BUFFER *buffer;
char arg[MAX_INPUT_LENGTH];
char spell_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
char spell_columns[LEVEL_HERO + 1];
int sn, level, min_lev = 1, max_lev = LEVEL_HERO, mana;
bool fAll = FALSE, found = FALSE;
char buf[MAX_STRING_LENGTH];
if (IS_NPC(ch))
return;
if(class_table[ch->class].ctype!=CLASS_COMMUNER && !IS_IMMORTAL(ch))
{
send_to_char("Your class knows no prayers.\n\r",ch);
return;
}
if (argument[0] != '\0')
{
fAll = TRUE;
if (str_prefix(argument,"all"))
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf(buf,"Levels must be between 1 and %d.\n\r",LEVEL_HERO);
send_to_char(buf,ch);
return;
}
if (argument[0] != '\0')
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
min_lev = max_lev;
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf(buf,
"Levels must be between 1 and %d.\n\r",LEVEL_HERO);
send_to_char(buf,ch);
return;
}
if (min_lev > max_lev)
{
send_to_char("That would be silly.\n\r",ch);
return;
}
}
}
}
/* initialize data */
for (level = 0; level < LEVEL_HERO + 1; level++)
{
spell_columns[level] = 0;
spell_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL )
break;
if ((level = skill_table[sn].skill_level[ch->class]) < LEVEL_HERO + 1
&& level >= min_lev && level <= max_lev
&& skill_table[sn].spell_fun != spell_null
&& ch->pcdata->learned[sn] > 0
&& (skill_table[sn].ctype==CMD_COMMUNE || skill_table[sn].ctype==CMD_BOTH))
{
found = TRUE;
level = skill_table[sn].skill_level[ch->class];
if (ch->level < level)
sprintf(buf,"%-18s n/a ", skill_table[sn].name);
else
{
mana = UMAX(skill_table[sn].min_mana,
100/(2 + ch->level - level));
switch (get_curr_stat(ch,STAT_INT)) {
case 25: mana = 43 * mana / 50; break;
case 24: mana = 22 * mana / 25; break;
case 23: mana = 45 * mana / 50; break;
case 22: mana = 23 * mana / 25; break;
case 21: mana = 47 * mana / 50; break;
case 20: mana = 24 * mana / 25; break;
case 19: mana = 49 * mana / 50; break;
}
sprintf(buf,"%-18s %3d mana ",skill_table[sn].name,mana);
}
if (spell_list[level][0] == '\0')
sprintf(spell_list[level],"\n\rLevel %2d: %s",level,buf);
else /* append */
{
if ( ++spell_columns[level] % 2 == 0)
strcat(spell_list[level],"\n\r ");
strcat(spell_list[level],buf);
}
}
}
/* return results */
if (!found)
{
send_to_char("No supplications found.\n\r",ch);
return;
}
buffer = new_buf();
for (level = 0; level < LEVEL_HERO + 1; level++)
if (spell_list[level][0] != '\0')
add_buf(buffer,spell_list[level]);
add_buf(buffer,"\n\r");
page_to_char(buf_string(buffer),ch);
free_buf(buffer);
}
void do_commune( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
void *vo;
int mana;
int sn;
AFFECT_DATA af;
int target;
if ( IS_NPC(ch) && ch->desc == NULL)
return;
target_name = one_argument( argument, arg1 );
one_argument( target_name, arg2 );
if(class_table[ch->class].ctype!=CLASS_COMMUNER && !IS_IMMORTAL(ch))
return send_to_char("You aren't in touch well enough with the gods to commune prayers.\n\r",ch);
if (IS_SET(ch->act,PLR_BETRAYER))
return send_to_char("Your god has forsaken you!\n\r",ch);
if(!IS_NPC(ch) && ch->pcdata->oalign==3 && ch->alignment==-1000)
return send_to_char("Your god has forsaken you!\n\r",ch);
if(is_affected(ch,gsn_worldbind))
{
send_to_char("Your prayers go unanswered.\n\r",ch);
return;
}
if ( arg1[0] == '\0' )
return send_to_char( "Commune which what where?\n\r", ch );
if ((sn = find_spell(ch,arg1)) < 1
|| skill_table[sn].spell_fun == spell_null
|| (!IS_NPC(ch) && get_skill(ch,sn) < 5)
|| (!IS_NPC(ch) && ch->pcdata->learned[sn] == 0))
return send_to_char( "You don't know any prayers of that name.\n\r", ch );
// if(skill_table[sn].skill_level[ch->class]>=51 && !IS_SET(ch->act,PLR_EMPOWERED) && !IS_IMMORTAL(ch))
// return send_to_char("The gods do not find you worthy of a prayer of that magnitude.\n\r",ch);
if ( ch->position < skill_table[sn].minimum_position )
return send_to_char( "You can't concentrate enough.\n\r", ch );
if((skill_table[sn].ctype==CMD_SPELL
|| skill_table[sn].ctype==CMD_POWER)
&& !IS_IMMORTAL(ch))
return send_to_char("You can't commune that.\n\r",ch);
if (ch->level + 2 == skill_table[sn].skill_level[ch->class])
mana = 50;
else
{
if(is_affected(ch,gsn_garble))
{
mana = UMAX(
(skill_table[sn].min_mana*2),
100 / ( 2 + ch->level - skill_table[sn].skill_level[ch->class] ) );
switch (get_curr_stat(ch,STAT_INT)) {
case 25: mana = 43 * mana / 50; break;
case 24: mana = 22 * mana / 25; break;
case 23: mana = 45 * mana / 50; break;
case 22: mana = 23 * mana / 25; break;
case 21: mana = 47 * mana / 50; break;
case 20: mana = 24 * mana / 25; break;
case 19: mana = 49 * mana / 50; break;
}
}
else
{
mana = UMAX(
skill_table[sn].min_mana,
100 / ( 2 + ch->level - skill_table[sn].skill_level[ch->class] ) );
switch (get_curr_stat(ch,STAT_INT)) {
case 25: mana = 43 * mana / 50; break;
case 24: mana = 22 * mana / 25; break;
case 23: mana = 45 * mana / 50; break;
case 22: mana = 23 * mana / 25; break;
case 21: mana = 47 * mana / 50; break;
case 20: mana = 24 * mana / 25; break;
case 19: mana = 49 * mana / 50; break;
}
}
}
/*
* Locate targets.
*/
victim = NULL;
obj = NULL;
vo = NULL;
target = TARGET_NONE;
af.aftype = AFT_COMMUNE;
switch ( skill_table[sn].target )
{
default:
bug( "Do_cast: bad target for sn %d.", sn );
return;
case TAR_IGNORE:
break;
case TAR_CHAR_OFFENSIVE:
if ( arg2[0] == '\0' )
{
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "Commune the prayer on whom?\n\r", ch );
return;
}
}
else
{
if ( ( victim = get_char_room( ch, target_name ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
if ( !IS_NPC(ch) )
{
check_killer(ch,victim);
}
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
send_to_char( "You can't do that on your own master.\n\r",
ch );
return;
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_DEFENSIVE:
if ( arg2[0] == '\0' )
{
victim = ch;
}
else
{
if ( ( victim = get_char_room( ch, target_name ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_SELF:
if ( arg2[0] != '\0' && !is_name( target_name, ch->name ) )
{
send_to_char( "You cannot commune this prayer on another.\n\r", ch );
return;
}
vo = (void *) ch;
target = TARGET_CHAR;
break;
case TAR_OBJ_INV:
if ( arg2[0] == '\0' )
{
send_to_char( "What should the prayer be communed upon?\n\r", ch );
return;
}
if ( ( obj = get_obj_carry( ch, target_name, ch ) ) == NULL )
{
send_to_char( "You are not carrying that.\n\r", ch );
return;
}
vo = (void *) obj;
target = TARGET_OBJ;
break;
case TAR_OBJ_CHAR_OFF:
if (arg2[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
{
send_to_char("Commune the prayer on whom or what?\n\r",ch);
return;
}
target = TARGET_CHAR;
}
else if ((victim = get_char_room(ch,target_name)) != NULL)
{
target = TARGET_CHAR;
}
if (target == TARGET_CHAR) /* check the sanity of the attack */
{
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
return send_to_char( "You can't do that on your own follower.\n\r", ch );
if (!IS_NPC(ch))
check_killer(ch,victim);
vo = (void *) victim;
}
else if ((obj = get_obj_here(ch,target_name)) != NULL)
{
vo = (void *) obj;
target = TARGET_OBJ;
}
else
return send_to_char("You don't see that here.\n\r",ch);
break;
case TAR_OBJ_CHAR_DEF:
if (arg2[0] == '\0')
{
vo = (void *) ch;
target = TARGET_CHAR;
}
else if ((victim = get_char_room(ch,target_name)) != NULL)
{
vo = (void *) victim;
target = TARGET_CHAR;
}
else if ((obj = get_obj_carry(ch,target_name,ch)) != NULL)
{
vo = (void *) obj;
target = TARGET_OBJ;
}
else
return send_to_char("You don't see that here.\n\r",ch);
break;
}
if ( !IS_NPC(ch) && ch->mana < mana )
return send_to_char( "You don't have enough mana.\n\r", ch );
WAIT_STATE( ch, skill_table[sn].beats );
if ( !IS_NPC(ch) && (number_percent( ) > get_skill(ch,sn)))
{
send_to_char( "You lost your concentration.\n\r", ch );
check_improve(ch,sn,FALSE,1);
ch->mana -= mana / 2;
}
else
{
ch->mana -= mana;
if (skill_table[sn].target == TAR_CHAR_OFFENSIVE
&& is_safe(ch,victim))
return;
if (skill_table[sn].target == TAR_CHAR_OFFENSIVE)
{
if (!IS_NPC(ch) && !IS_NPC(victim)
&& (ch->fighting == NULL || victim->fighting == NULL))
{
switch(number_range(0,2))
{
case (0):
case (1):
sprintf(buf,"Die, %s you filthy dog!",PERS(ch,victim));
break;
case (2):
sprintf(buf,"Help! %s is communing a supplication on me!",PERS(ch,victim));
}
if (victim != ch && !IS_NPC(ch))
do_myell(victim,buf);
}
}
if(skill_table[sn].target==TAR_CHAR_OFFENSIVE && victim!=ch)
{
act("You narrow your eyes and glare in $N's direction.",ch,0,victim,TO_CHAR);
act("$n narrows $s eyes and glares in $N's direction.",ch,0,victim,TO_NOTVICT);
act("$n narrows $s eyes and glares in your direction.",ch,0,victim,TO_VICT);
}
if(skill_table[sn].target==TAR_CHAR_SELF || skill_table[sn].target==TAR_IGNORE ||
skill_table[sn].target==TAR_OBJ_CHAR_DEF || skill_table[sn].target==TAR_OBJ_CHAR_OFF ||
(skill_table[sn].target==TAR_CHAR_DEFENSIVE && victim==ch))
{
act("You close your eyes and concentrate for a moment.",ch,0,0,TO_CHAR);
act("$n closes $s eyes with a look of concentration for a moment.",ch,0,0,TO_ROOM);
}
if(skill_table[sn].target==TAR_CHAR_DEFENSIVE && victim!=ch)
{
act("You close your eyes for a moment and nod at $N.",ch,0,victim,TO_CHAR);
act("$n closes $s eyes for a moment and nods at $N.",ch,0,victim,TO_NOTVICT);
act("$n closes $s eyes for a moment and nods at you.",ch,0,victim,TO_VICT);
}
if(skill_table[sn].target==TAR_OBJ_INV)
{
act("You furrow your brow as you look through your possessions.",ch,0,0,TO_CHAR);
act("$n furrows $s brow as $e looks through $s possessions.",ch,0,0,TO_ROOM);
}
(*skill_table[sn].spell_fun) ( sn, ch->level + GET_HITROLL(ch)/20, ch, vo,target);
check_improve(ch,sn,TRUE,1);
}
if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE
|| (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR))
&& victim != ch
&& victim->master != ch)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
for ( vch = ch->in_room->people; vch; vch = vch_next )
{
vch_next = vch->next_in_room;
if ( victim == vch && victim->fighting == NULL )
{ check_killer(victim,ch);
multi_hit( victim, ch, TYPE_UNDEFINED );
break;
}
}
}
return;
}
void spell_healing_sleep( int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if(victim == NULL)
victim = ch;
if (IS_NPC(victim))
return send_to_char( "You may only commune this supplication on real people.\n\r", ch );
if (!is_same_group(victim,ch))
return send_to_char( "You may only commune this supplication on group members.\n\r", ch );
if (victim->position == POS_FIGHTING)
return send_to_char( "You may not commune this supplication on somebody while they are fighting.\n\r", ch );
if (( IS_AFFECTED(victim, AFF_SLEEP))
|| !IS_AWAKE(victim))
{
act("$N is already asleep.",ch,0,victim,TO_CHAR);
return;
}
init_affect(&af);
af.where = TO_AFFECTS;
af.aftype = AFT_COMMUNE;
af.type = gsn_healing_sleep;
af.level = level;
af.duration = 3;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_SLEEP;
affect_to_char(victim,&af);
act("You put $N into a deep healing sleep.",ch,0,victim,TO_CHAR);
act("$n puts you into a deep healing sleep.",ch,0,victim,TO_VICT);
victim->position = POS_SLEEPING;
return;
}
void spell_righteousness( int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
AFFECT_DATA af;
CHAR_DATA *victim = (CHAR_DATA *) vo;
if (ch != victim)
{
send_to_char("You cannot commune this supplication on another.\n\r",ch);
return;
}
if (is_affected(ch, sn))
{
send_to_char("You're already feeling righteous.\n\r",ch);
return;
}
init_affect(&af);
af.where = TO_IMMUNE;
af.aftype = AFT_COMMUNE;
af.type = sn;
af.level = level;
af.duration = 8;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = IMM_HOLY;
affect_to_char( victim, &af );
send_to_char( "You feel righteous.\n\r", victim );
return;
}
void spell_blade_barrier(int sn,int level,CHAR_DATA *ch,void *vo,int target)
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam, spins;
int chance, i;
chance = 100;
if (get_skill(ch,skill_lookup("blade mastery")) < 0) {
dam = dice(level, 2);
spins = number_range(2,3);
dam *= 9;
dam /= 10;
}
else {
dam = dice (level, 3);
spins = number_range(4,5);
}
if (number_percent() > chance || victim == ch)
{
act("$n creates a whirlwind of spinning blades which turn and strike $m down!",ch,0,0,TO_ROOM);
act("Your blade barrier turns and strikes you down!",ch,0,0,TO_CHAR);
dam /= 2;
damage_old(ch,ch,dam,sn,DAM_SLASH,TRUE);
for (i = 0; i < spins; i++)
{
if (ch->ghost > 0)
return;
if (saves_spell(level,ch,DAM_SLASH))
dam /= 2;
dam *= 3;
dam /=2;
act("The blades spin and slice away at $n.",ch,0,0,TO_ROOM);
act("The blades spin and slice away at you.",ch,0,0,TO_CHAR);
damage_old(ch,ch,dam,sn,DAM_SLASH,TRUE);
}
}
else
{
act("You create a whirlwind of spinning blades to strike down $N!",ch,0,victim,TO_CHAR);
act("$n creates a deadly blade barrier that tears into $N!",ch,0,victim,TO_NOTVICT);
act("$n creates a deadly blade barrier that tears into you!",ch,0,victim,TO_VICT);
if (get_skill(ch,skill_lookup("blade mastery")) > 0) {
act("Your blade mastery drives the blades to strike true!",ch,0,victim,TO_CHAR);
act("$n's blade mastery drives the blades to strike true!",ch,0,victim,TO_NOTVICT);
act("$n's blade mastery drives the blades to strike true!",ch,0,victim,TO_VICT);
}
damage_old(ch,victim,dam,sn,DAM_SLASH,TRUE);
for (i = 0; i < spins; i++)
{
if (victim->ghost > 0 || (victim->in_room != ch->in_room))
return;
if (saves_spell(level,victim,DAM_SLASH))
dam /= 2;
if (get_skill(ch,skill_lookup("blade mastery")) < 0) {
dam *= 3;
dam /=4;
}
else {
dam *= 17;
dam /= 20;
}
act("The blades spin and slice away at $n.",victim,0,0,TO_ROOM);
act("The blades spin and slice away at you.",victim,0,0,TO_CHAR);
if (victim->ghost > 0)
return;
damage_old(ch,victim,dam,sn,DAM_SLASH,TRUE);
}
}
act("The blade barrier fades away.",ch,0,0,TO_ROOM);
act("Your blade barrier fades away.",ch,0,0,TO_CHAR);
return;
}
void spell_holy_word(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
int dam, bless_num, curse_num, frenzy_num,sanc_num, wrath_num;
if (IS_GOOD(ch))
wrath_num = skill_lookup("wrath");
else
wrath_num = skill_lookup("dark wrath");
sanc_num = skill_lookup("sanctuary");
bless_num = skill_lookup("bless");
curse_num = skill_lookup("curse");
frenzy_num = skill_lookup("frenzy");
if (IS_EVIL(ch)) {
act("$n utters a word of unholy power!",ch,NULL,NULL,TO_ROOM);
send_to_char("You utter a word of unholy power.\n\r",ch);
} else {
act("$n utters a word of divine power!",ch,NULL,NULL,TO_ROOM);
send_to_char("You utter a word of divine power.\n\r",ch);
}
for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
{
vch_next = vch->next_in_room;
if(vch->invis_level>LEVEL_HERO)
continue;
if ((IS_GOOD(ch) && IS_GOOD(vch)) || (IS_EVIL(ch) && IS_EVIL(vch)) || ((IS_NEUTRAL(ch) && IS_NEUTRAL(vch)) && (ch==vch)))
{
send_to_char("You feel more powerful.\n\r",vch);
spell_frenzy(frenzy_num,60,ch,(void *) vch,TARGET_CHAR);
spell_bless(bless_num,60,ch,(void *) vch,TARGET_CHAR);
spell_sanctuary(sanc_num,60,ch,(void *) vch,TARGET_CHAR);
}
else if ((IS_GOOD(ch) && IS_EVIL(vch)) || (IS_EVIL(ch) && IS_GOOD(vch)) )
{
if (!is_safe_spell(ch,vch,TRUE))
{
spell_curse(curse_num,level*2,ch,(void *) vch,TARGET_CHAR);
send_to_char("You are struck down!\n\r",vch);
if (IS_GOOD(ch))
spell_wrath(wrath_num,level*2,ch,(void *) vch,TARGET_CHAR);
else
spell_dark_wrath(wrath_num,level*2,ch,(void *) vch,TARGET_CHAR);
}
}
else if (IS_NEUTRAL(ch))
{
if (!is_safe_spell(ch,vch,TRUE))
{
spell_curse(curse_num,level/2,ch,(void *) vch,TARGET_CHAR);
send_to_char("You are struck down!\n\r",vch);
dam = dice(level,8);
damage_old(ch,vch,dam,sn,DAM_ENERGY,TRUE);
}
}
}
send_to_char("You feel drained.\n\r",ch);
ch->move /= 2;
ch->mana /= 2;
ch->hit /= 2;
}