/**************************************************************************/
// magic_da.cpp - spells/skills written for Dawn by anyone
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with all the licenses *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
#include "include.h"
#include "magic.h"
DECLARE_DO_FUN(do_bug);
/**************************************************************************/
// By Thaddeus
void do_lay_on_hands(char_data * ch, char * argument)
{
int heal;
int skill;
char arg[MIL];
char_data *victim;
one_argument( argument, arg );
if ( IS_OOC( ch )) {
ch->printf( "Not in an OOC room.\r\n" );
return;
}
if ( arg[0] == '\0' )
{
ch->printf( "Lay your hands on whom?\r\n" );
return;
}
if ( ( victim = get_char_room( ch, arg ) ) == NULL )
{
ch->printf( "You don't see anyone like that here.\r\n" );
return;
}
if ( !IS_IMMORTAL( ch ))
WAIT_STATE( ch, skill_table[gsn_lay_on_hands].beats );
// dont spam message
if (ch->desc && ch->desc->repeat>8)
{
ch->printf( "The lay on hands skill has no effect when used on yourself.\r\n" );
ch->printf( "(learn to read the help files - read help lay)\r\n" );
return;
}
if ( (victim == ch) )
{
act("$n lays $s hands on $mself.", ch, NULL,NULL, TO_ROOM);
act("You lay your hands on yourself.", ch, NULL, NULL, TO_CHAR);
return;
}
act("$n lays $s hands on $N.", ch, NULL, victim, TO_NOTVICT);
act("You lay your hands on $N.", ch, NULL, victim, TO_CHAR);
act("$n lays $s hands on you.", ch, NULL, victim, TO_VICT);
if (!(skill=get_skill(ch,gsn_lay_on_hands)))
return;
if (IS_NPC(ch))
return;
if (ch->pcdata->lays<=0)
return;
ch->pcdata->lays--;
heal = UMAX(number_range(1,(ch->level/10)+1),
number_range(1,(ch->level/10)+1));
heal=(heal * skill)/100;
victim->hit = UMIN( victim->hit + heal, victim->max_hit );
update_pos( victim );
victim->printf( "You feel better!\r\n" );
ch->printf( "Your hands glow softly as a sense of divine power travels through you.\r\n" );
check_improve( ch, gsn_lay_on_hands, true, 1 );
return;
}
/**************************************************************************/
// By Kirion and Kalahn
SPRESULT spell_mindspeak( int, int, char_data *ch, void *, int )
{
static int mindspeakmon=0;
char arg[MIL],buf[MSL],buf2[MSL];
char tellname[MIL];
char *argument;
char_data *victim;
// unswitched mobs can't send mindspeaks
if (IS_UNSWITCHED_MOB(ch))
{
return NO_MANA;
}
target_name = one_argument( target_name, arg );
argument = target_name;
if ( arg[0] == '\0' || argument[0] == '\0' )
{
ch->printf( "Mindspeak whom what?\r\n" );
return NO_MANA;
}
// remove a , from the name field if required
if (arg[str_len(arg)-1]==','){
arg[str_len(arg)-1]=0;
}
// cannot send mindspeaks to mobs or to players which are not logged or are inside of ooc rooms
if (( victim = get_whovis_player_world( ch, arg ))==NULL
|| IS_NPC(victim)
|| IS_SET(victim->in_room->room_flags, ROOM_OOC))
{
ch->printf( "Their mind is unreachable.\r\n" );
return NO_MANA;
}
//cannot mindspeak to yourself
if (victim==ch)
{
ch->printf( "You are always mindspeaking to yourself!\r\n");
return NO_MANA;
}
//cannot mindspeak while with a pkill-norecall, pkill-ool or pkill-noquit timer
if((ch->pknorecall>0) || (ch->pknoquit>0) || (ch->pkool>2000))
{
ch->printf( "Your mind is too troubled for you to focus on any one idea.\r\n" );
return HALF_MANA;
}
// Mindspeaking to asleep people, or people affected with cause fear
if ( (!IS_AWAKE(victim)) || (IS_AFFECTED(victim, AFF_FEAR)) ||
(IS_AFFECTED2(victim, AFF2_FEAR_MAGIC)) )
{
act( "Your thoughts could not remain in $S mind for long.", ch, 0, victim, TO_CHAR );
return HALF_MANA;
}
// If caster is invisible, target receives it as a someone, instead of his desc
sprintf (tellname,(can_see_who(TRUE_CH(victim), TRUE_CH(ch))?
TRUE_CH(ch)->name:"someone"));
// Mortals cannot mindspeak if AFK
if (IS_SET(ch->comm,COMM_AFK) && !IS_IMMORTAL(ch))
{
ch->printf( "You can't mindspeak while AFK!\r\n" );
return NO_MANA;
}
// cannot mindspeak to an AFK victim, but immortals get it nevertheless
if (IS_SET(victim->comm,COMM_AFK))
{
act("$E is AFK, and thus, unable to receive mindspeaks",ch,NULL,victim,TO_CHAR);
if IS_IMMORTAL(victim)
{
victim->printf( "%s just tried to mindspeak you '%s' "
"(you are marked as afk)`x\r\n",
PERS(ch, victim), argument);
return NO_MANA;
}
return NO_MANA;
}
// wiznet mindspeak - needed to monitor possible abuses
if (!IS_NPC(ch))
{
if (!IS_OOC(ch))
{
mindspeakmon++;
if (mindspeakmon>=10)
{
sprintf (buf2, "Wiznet mindspeak: %s mindspeaked `s'%s'`x to %s",
ch->name, argument, victim->name);
wiznet(buf2,ch,NULL,WIZ_QUESTING,0,get_trust(ch));
mindspeakmon=0;
}
ch->pcdata->did_ic=true;
}
}
//Check to see if the next char is a '!' or a ',' , in which case, does a Mental emote
if ((argument[0]=='!') || (argument[0]==','))
{
argument++;
if (argument[0]==' ') argument++;
if(!IS_NPC(ch)) ch->pcdata->did_ooc=true;
ch->printf( "`bWithin the mind of %s, your image %s`x\r\n",
PERS(victim, ch), argument);
victim->printf( "`bWithin your mind. the image of %s %s`x\r\n",
PERS(ch, victim), argument);
return FULL_MANA;
}
// Languages still influence mindspeaks, you think in a specific language, so
// mindspeaks cannot be used for universal communication.
translate_language(ch->language, false, ch, victim, argument, buf);
//At last! The Mindspeak.
if(!IS_NPC(ch)){
ch->pcdata->did_ooc=true;
}
ch->printf( "`BYou speak your thoughts into the mind of %s: "
"'%s`B'`x\r\n", PERS(victim, ch), argument);
victim->printf( "`BYou hear the voice of %s within your mind: "
"'%s`B'`x\r\n", PERS(ch, victim), buf);
return FULL_MANA;
}
/**************************************************************************/
SPRESULT spell_naturespeak( int, int, char_data *ch, void *, int ) //Kirion with slight tweaks by Ker
{
static int naturespeakmon=0;
char arg[MIL],buf[MSL],buf2[MSL];
char tellname[MIL];
char *argument;
char_data *victim, *to;
// unswitched mobs can't naturespeak
if (IS_UNSWITCHED_MOB(ch))
{
ch->printf( "Unswitched mobs cannot naturespeak." );
return NO_MANA;
}
target_name = one_argument( target_name, arg );
argument = target_name;
if ( arg[0] == '\0' || argument[0] == '\0' )
{
ch->printf( "Deliver which message, and to whom?\r\n" );
return NO_MANA;
}
// remove a , from the name field if required
if (arg[str_len(arg)-1]==',') arg[str_len(arg)-1]=0;
// cannot naturespeak to mobs or to players which are not logged or are inside of ooc rooms
if (( victim = get_whovis_player_world( ch, arg ))==NULL
|| IS_NPC(victim)
|| IS_SET(victim->in_room->room_flags, ROOM_OOC))
{
ch->printf( "They are nowhere to be found.\r\n" );
return NO_MANA;
}
//cannot mindcast to yourself
if (victim==ch)
{
ch->printf( "You think of a message and mentally say it to yourself.\r\n");
return NO_MANA;
}
//cannot naturespeak while with a pkill-norecall, pkill-ool or pkill-noquit timer
if((ch->pknorecall>0) || (ch->pknoquit>0) || (ch->pkool>0))
{
ch->printf( "You can't seem to focus enough to naturespeak.\r\n" );
return HALF_MANA;
}
// Naturespeaking to asleep people, or people affected with cause fear
if ( (!IS_AWAKE(victim)) || (IS_AFFECTED(victim, AFF_FEAR))
|| (IS_AFFECTED2(victim, AFF2_FEAR_MAGIC)) )
{
act( "$S mind is drifting aimessly, you can't lock onto it.", ch, 0, victim, TO_CHAR );
return HALF_MANA;
}
// If caster is invisible, target receives it as a someone, instead of his desc
sprintf (tellname,(can_see_who(TRUE_CH(victim), TRUE_CH(ch)) ?
TRUE_CH(ch)->name:"someone"));
// Mortals cannot naturespeak if AFK
if (IS_SET(ch->comm,COMM_AFK))
if (!IS_IMMORTAL(ch))
{
ch->printf( "You can't naturespeak while AFK!\r\n" );
return NO_MANA;
}
// cannot naturespeak to an AFK victim, but immortals get it nevertheless
if (IS_SET(victim->comm,COMM_AFK))
{
act("$E is AFK, and thus, unable to receive a naturespeak.",ch,NULL,victim,TO_CHAR);
if IS_IMMORTAL(victim)
{
victim->printf( "%s just tried to naturespeak to you '%s' (you are marked as afk)`x\r\n",
PERS(ch, victim), argument);
return NO_MANA;
}
return NO_MANA;
}
// wiznet NATURESPEAK - needed to monitor possible abuses
if (!IS_NPC(ch))
{
if (!IS_OOC(ch))
{
naturespeakmon++;
if (naturespeakmon>=10)
{
sprintf (buf2, "Wiznet naturespeaks: %s naturespoke `s'%s'`x to %s", ch->name, argument, victim->name);
wiznet(buf2,ch,NULL,WIZ_QUESTING,0,get_trust(ch));
naturespeakmon=0;
buf2[0]='\0';
}
ch->pcdata->did_ic=true;
}
}
// Caster feedback
switch ( victim->in_room->sector_type )
{
case SECT_UNDERWATER:
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_SWAMP:
ch->println( "The spirits of water, the undines, have answered your call.");
break;
case SECT_CAVE:
case SECT_MOUNTAIN:
case SECT_CITY:
case SECT_HILLS:
ch->println( "The spirits of earth, the grendels, have answered your call.");
break;
case SECT_DESERT:
ch->println( "The spirits of fire, the salamanders, have answered your call.");
break;
case SECT_AIR:
ch->println( "The spirits of air, the sylphs, have answered your call.");
break;
case SECT_FOREST:
case SECT_FIELD:
ch->println( "The spirits of nature, the dryads, have answered your call.");
break;
default:
ch->println( "No spirit could reach the target.");
return NO_MANA;
break;
}
buf2[0]='\0';
//At last! The Naturespeak.
if(!IS_NPC(ch)) ch->pcdata->did_ooc=true;
switch ( victim->in_room->sector_type )
{
case SECT_FOREST:
strcat(buf2, "`gA nearby tree takes the shape of");
break;
case SECT_HILLS:
strcat(buf2, "`sA group of stones and grasses rise in the shape of");
break;
case SECT_FIELD:
strcat(buf2, "`sA nearby bush shifts into the form of");
break;
case SECT_MOUNTAIN:
strcat(buf2, "`sA large boulder shifts into the form of");
break;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
strcat(buf2, "`bA column of water rises in the form of");
break;
case SECT_SWAMP:
strcat(buf2, "`mA pool of mud grows into the shape of");
break;
case SECT_AIR:
strcat(buf2, "`cA small cloud forms, resembling");
break;
case SECT_DESERT:
strcat(buf2, "`yA small dune shapes into the form of");
break;
case SECT_CAVE:
strcat(buf2, "`rA nearby stone morphs into the form of");
break;
case SECT_UNDERWATER:
strcat(buf2, "`BBubbles form in the water on the shape of");
break;
case SECT_CITY:
strcat(buf2, "`wStones from a nearby wall morphs into the shape of");
break;
default:
strcat(buf2, "`wVapour from nowhere appears in the shape of");
break;
}
for( to = victim->in_room->people; to ; to = to->next_in_room )
{
//Check to see if the next char is a '!' or a ',' , in which case, does a nature emote
if ((argument[0]=='!') || (argument[0]==','))
{
argument++;
if (argument[0]==' ') argument++;
if(!IS_NPC(ch)) ch->pcdata->did_ooc=true;
to->printf( "%s %s and %s`x\r\n", buf2, PERS (ch, to), argument);
}
else
{
// Languages still influence naturespeaks
translate_language(ch->language, false, ch, victim, argument, buf);
to->printf( "%s %s and says to %s:'%s'`x\r\n", buf2, PERS (ch, to),
YOU_PERS(victim, to), buf);
}
}
return FULL_MANA;
}
/***************************************************************************
* Cause Headache - Adds -20 to SD *
* By Ylerin, February 1999 *
***************************************************************************/
SPRESULT spell_cause_headache(int sn,int level,char_data *ch,void *vo,int )
{
char_data *victim = (char_data *) vo;
AFFECT_DATA af;
if ( is_affected( victim, sn ))
{
if (victim == ch)
ch->printf( "Your head already aches tremendously! You surely don't want to increase it.\r\n" );
else
act("$N already suffers from a terrible headache. Have a bit of pity on $m.",ch,NULL,victim,TO_CHAR);
return HALF_MANA;
}
af.where = WHERE_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level;
af.location = APPLY_SD;
af.modifier = - level/5;
af.bitvector = 0;
affect_to_char( victim, &af );
victim->printf( "Your head seems to explode with a sudden wave of indescribable pain!\r\n" );
act("$n grimaces in pain.",victim,NULL,NULL,TO_ROOM);
return FULL_MANA;
}
/***************************************************************************
* Cure Headache - Cures headache :p *
* By Ylerin, Auguts 1999 *
***************************************************************************/
SPRESULT spell_cure_headache( int , int level, char_data *ch, void *vo,int )
{
char_data *victim = (char_data *) vo;
if ( !is_affected( victim, gsn_cause_headache ) )
{
if (victim == ch)
ch->printf( "You don't have a headache.\r\n" );
else
act("$N appears to be well.",ch,NULL,victim,TO_CHAR);
return HALF_MANA;
}
if (check_dispel(level,victim,gsn_cause_headache))
{
victim->printf( "Your headache is gone, what a relief!\r\n" );
act("$n looks much relieved.",victim,NULL,NULL,TO_ROOM);
}
else
ch->printf( "Your spell failed.\r\n" );
return FULL_MANA;
}
/**************************************************************************/
// Kal
SPRESULT spell_restore_mana( int, int level, char_data *ch, void *vo,int)
{
char_data *victim = (char_data *) vo;
victim->mana = UMIN( victim->mana + UMIN(number_range(level, level*3),150), victim->max_mana );
victim->println( "A warm glow passes through you.");
if ( ch != victim ){
ch->println( "Ok.");
}
return FULL_MANA;
}
/**************************************************************************/
// balo
SPRESULT spell_remove_alignment( int sn, int level, char_data *ch, void *vo,int target)
{
OBJ_DATA *obj = (OBJ_DATA *) vo;
int result, fail;
AFFECT_DATA *paf;
if (obj->wear_loc != -1)
{
ch->println("The item must be carried to remove it's alignment.");
return NO_MANA;
}
if ((!IS_OBJ_STAT(obj,OBJEXTRA_ANTI_GOOD))
&& (!IS_OBJ_STAT(obj,OBJEXTRA_ANTI_EVIL))
&& (!IS_OBJ_STAT(obj,OBJEXTRA_ANTI_NEUTRAL)))
{
ch->println("The item has no alignment.");
return HALF_MANA;
}
fail = 25; // base 25% chance of failure
// find the bonuses (Its harder to remove align from a powerful object)
if (!obj->affected) // enchanted dosn`t seem to exist ? (!obj->enchanted)
for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
{
fail += 20;
}
for ( paf = obj->affected; paf != NULL; paf = paf->next )
{
fail += 20;
}
// apply other modifiers
fail += obj->level;
fail -= 3 * level / 2;
// harder to remove align from objects inherently blessed or evil
if (IS_OBJ_STAT(obj,OBJEXTRA_BLESS)){
fail += 5;
}
if (IS_OBJ_STAT(obj,OBJEXTRA_EVIL)){
fail += 5;
}
fail = URANGE(5,fail,90);
result = number_percent();
// the moment of truth
if (result < (fail / 5)) // item destroyed
{
act("$p shivers and shudders... then implodes!",ch,obj,NULL,TO_CHAR);
act("$p shivers and shudders... then implodes!",ch,obj,NULL,TO_ROOM);
extract_obj(obj);
return FULL_MANA;
}
if ( result <= fail ) // failed, no bad result
{
ch->printf("Nothing seemed to happen.\n\r");
return FULL_MANA;
}
// Success! Remove the item's alignment
REMOVE_BIT(obj->extra_flags,OBJEXTRA_ANTI_EVIL);
REMOVE_BIT(obj->extra_flags,OBJEXTRA_ANTI_GOOD);
REMOVE_BIT(obj->extra_flags,OBJEXTRA_ANTI_NEUTRAL);
act("You remove $p's alignment!",ch,obj,NULL,TO_CHAR);
act("$n removes $p's alignment!",ch,obj,NULL,TO_ROOM);
return FULL_MANA;
}
/***************************************************************************/
SPRESULT spell_enchant_item(int sn,int level, char_data *ch, void *vo,int )
{
OBJ_DATA *obj = (OBJ_DATA *) vo;
AFFECT_DATA *paf;
int result, fail;
int added;
bool hit_found = false, dam_found = false;
// do standard checks - if spell can be cast
if ((obj->item_type != ITEM_LIGHT) && (obj->item_type != ITEM_TREASURE)
&& (obj->item_type != ITEM_CLOTHING) && (obj->item_type != ITEM_CONTAINER)
&& (obj->item_type != ITEM_GEM) && (obj->item_type != ITEM_JEWELRY))
{
ch->println( "That isn't enchantable." );
return NO_MANA;
}
if(obj->wear_loc!=-1){
ch->printf( "The item must be carried to be enchanted.\r\n" );
return NO_MANA;
}
fail = 25; // base 25% chance of failure
// find the current bonuses - affect success
for (paf=OBJECT_AFFECTS(obj); paf; paf=paf->next )
{
if ( paf->location == APPLY_HITROLL ){
hit_found = true;
fail += 2 * paf->modifier * paf->modifier;
if (paf->duration == -1) // can't add to a perm weapon enchant
{
ch->printf( "%s starts to pulsate then it dissolves before your eyes!!!",
capitalize(format_obj_to_char(obj, ch, true)));
extract_obj(obj);
return FULL_MANA;
}
}else if (paf->location == APPLY_DAMROLL ){
dam_found = true;
fail += 2 * paf->modifier * paf->modifier;
if (paf->duration == -1) // can't add to a perm weapon enchant
{
ch->printf( "%s starts to pulsate then it dissolves before your eyes!!!\r\n",
format_obj_to_char(obj, ch, true));
extract_obj(obj);
return FULL_MANA;
}
}else{
fail += 20;
}
}
// apply other modifiers
fail -= 3 * level/2;
if (IS_OBJ_STAT(obj,OBJEXTRA_BLESS)){
fail -= 15;
}if (IS_OBJ_STAT(obj,OBJEXTRA_GLOW)){
fail -= 5;
}
fail = URANGE(5,fail,95);
result = number_percent();
// the moment of truth
if (result < (fail / 5)){ // item destroyed
act("$p shivers violently and explodes!",ch,obj,NULL,TO_CHAR);
act("$p shivers violently and explodes!",ch,obj,NULL,TO_ROOM);
extract_obj(obj);
return FULL_MANA;
}
if (result < (fail / 2)){ // item disenchanted
AFFECT_DATA *paf_next;
act("$p glows brightly, then fades...oops.",ch,obj,NULL,TO_CHAR);
act("$p glows brightly, then fades.",ch,obj,NULL,TO_ROOM);
// free all affects
for (paf = obj->affected; paf; paf = paf_next)
{
paf_next = paf->next;
free_affect(paf);
}
obj->affected = NULL;
obj->no_affects = true; // flag the object as no_affects so
// the olc template's affects arent used.
// clear all flags
obj->extra_flags = 0;
return FULL_MANA;
}
if ( result <= fail ) // failed, no bad result
{
ch->printf( "Nothing seemed to happen.\r\n" );
return FULL_MANA;
}
// **** ALL SUCCESSFUL ENCHANTS BELOW HERE ****
// now setup all the enchants:
// - if it enchants, weren't stored on the object, copy the enchants
// from the object vnums enchants.
affects_from_template_to_obj(obj);
if (result <= (100 - level/5)){ // success!
act("$p glows blue.",ch,obj,NULL,TO_CHAR);
act("$p glows blue.",ch,obj,NULL,TO_ROOM);
SET_BIT(obj->extra_flags, OBJEXTRA_MAGIC);
added = 1;
}else{ // exceptional enchant
act("$p glows a brillant blue!",ch,obj,NULL,TO_CHAR);
act("$p glows a brillant blue!",ch,obj,NULL,TO_ROOM);
SET_BIT(obj->extra_flags,OBJEXTRA_MAGIC);
SET_BIT(obj->extra_flags,OBJEXTRA_GLOW);
added = 2;
}
// now add the enchantments
if (dam_found){
for ( paf = obj->affected; paf != NULL; paf = paf->next)
{
if ( paf->location == APPLY_DAMROLL)
{
paf->type = sn;
paf->modifier += added;
if (ch->level>paf->level) // up the level if caster is higher
paf->level = ch->level;
if (paf->modifier > 4 && (number_range(1,100)<95))
SET_BIT(obj->extra_flags,OBJEXTRA_HUM);
}
}
}else{ // add a new damroll affect
paf = new_affect();
paf->where = WHERE_OBJEXTRA;
paf->type = sn;
paf->level = ch->level;
paf->duration = level * 20;
paf->location = APPLY_DAMROLL;
paf->modifier = added;
paf->bitvector = 0;
paf->next = obj->affected;
obj->affected = paf;
}
if (hit_found){
for ( paf = obj->affected; paf != NULL; paf = paf->next)
{
if ( paf->location == APPLY_HITROLL)
{
paf->type = sn;
paf->modifier += added;
paf->level = UMAX(paf->level,level)/2;
if (paf->modifier > 4){
SET_BIT(obj->extra_flags,OBJEXTRA_HUM);
}
}
}
}else{ // add a new affect
paf = new_affect();
paf->type = sn;
paf->level = ch->level;
paf->duration = level * 20;
paf->location = APPLY_HITROLL;
paf->modifier = added;
paf->bitvector = 0;
paf->next = obj->affected;
obj->affected = paf;
}
return FULL_MANA;
}
/**************************************************************************/
/**************************************************************************/