/**************************************************************************/
// magic_qu.cpp - spells/skills written by Quenrelthaer
/***************************************************************************
* 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 the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
/***************************************************************************
* FILE: magic_q.c - spells written by Quenrelthaer *
* *
* cutting_wind - air, evocation & wild magic (area attack) *
* decay - evocation & necromancy *
* downdraft - air & evocation *
* fling - air & alteration *
* shaping_the_chaos - conjuration, summoning & wild magic *
* spirit_walk - divination, summoning *
* disorientation - illusion
* *
***************************************************************************/
#include "include.h"
#include "magic.h"
/********************************/
/* START OF FUNCTION PROTOTYPES */
DECLARE_DO_FUN(do_bug);
DECLARE_DO_FUN(do_look);
/* END OF FUNCTION PROTOTYPES */
/********************************/
/***************************************************************************
* spell_cutting_wind - by Quenrelthaer August 97 - modified by kalahn *
***************************************************************************/
SPRESULT spell_cutting_wind(int sn,int level,char_data *ch,void *,int )
{
char_data *vch;
char_data *vch_next;
int dam, pdam, random;
random = dice(1,level/3)+2;
dam = dice((level/2)+1, random);
for ( vch = ch->in_room->people; vch; vch = vch_next )
{
vch_next=vch->next_in_room;
pdam = dam;
if (vch == ch)
continue;
if ( is_safe_spell(ch,vch,true))
continue;
if ( saves_spell( level, vch, DAMTYPE(sn)) )
{
pdam /= 2;
}
damage_spell( ch, vch, pdam, sn, DAMTYPE(sn),true);
}
return FULL_MANA;
}
/****************************************************************************
* spell_decay - by Quenrelthaer August 97, *
* - modified by Kalahn Nov 97, made it not destroy items inside containers *
****************************************************************************/
SPRESULT spell_decay(int sn,int level,char_data *ch,void *vo,int target)
{
OBJ_DATA *decay, *decay_next;
OBJ_DATA *obj;
OBJ_DATA *obj_next;
char_data *victim=(char_data*)vo;
int dam, random;
if (target == TARGET_OBJ)
{
decay = get_obj_carry(ch,target_name);
if (decay == NULL)
{
ch->println("You do not see that here.");
return NO_MANA;
}
if ( IS_SET( decay->extra2_flags, OBJEXTRA2_NODECAY ))
{
ch->println("Nothing seemed to happen.");
return HALF_MANA;
}
decay->timer = (30/level)+1;
act( "$p slowly starts to break apart.", ch, decay, NULL, TO_ROOM );
act( "$p slowly starts to break apart as the decay sets in.", ch, decay, NULL, TO_CHAR );
return FULL_MANA;
}
dam = dice(level, 8);
if ( saves_spell( level, victim, DAMTYPE(sn)) )
dam /= 2;
damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true);
if (dam<level*4)
{
random = dice(2,10)-1;
for ( decay = victim->carrying; decay != NULL; decay = decay_next)
{
decay_next = decay->next_content;
if (decay->wear_loc == random)
break;
}
if (decay == NULL)
return FULL_MANA;
if ( IS_SET( decay->extra2_flags, OBJEXTRA2_NODECAY ))
{
ch->println("Nothing seemed to happen.");
return HALF_MANA;
}
act("$p suddenly falls apart, decaying into dust just before it hits the ground!",ch,decay,NULL,TO_ROOM);
act("The magic sets upon $p, grinding it to dust.",ch,decay,NULL,TO_CHAR);
switch ( decay->item_type )
{
default:
extract_obj(decay);
break;
case ITEM_CAULDRON:
case ITEM_CONTAINER:
case ITEM_FLASK:
case ITEM_MORTAR:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
for ( obj = decay->contains; obj != NULL; obj = obj_next )
{
obj_next = obj->next_content;
obj_from_obj(obj);
if (number_range(1,10)==1)
{
obj_to_char( obj, ch );
act("You manage to catch $p as before it hits the ground.", ch, obj, NULL, TO_CHAR);
}
else
{
obj_to_room(obj, ch->in_room);
act("$p falls to the ground.", ch, obj, NULL, TO_ROOM);
act("The $p falls to your feet.", ch, obj, NULL, TO_CHAR);
}
}
}
obj_from_char(decay);
extract_obj(decay);
}
return FULL_MANA;
}
/****************************************************************************
* spell_disorientation - by Quenrelthaer - August 97 *
****************************************************************************/
SPRESULT spell_disorientation(int ,int ,char_data *ch,void *vo,int )
{
char_data *victim=(char_data*)vo;
ROOM_INDEX_DATA *pRoomIndex;
ROOM_INDEX_DATA *original;
OBJ_DATA *on;
pRoomIndex = get_random_room(victim);
victim->println("You have been teleported!");
act("$n looks very confused all of a sudden.", victim, ch, NULL,TO_ROOM);
if (victim != ch)
act("$n looks very confused all of a sudden.", victim, ch, NULL,TO_CHAR);
original = victim->in_room;
on = victim->on;
char_from_room( victim );
char_to_room( victim, pRoomIndex );
do_look(victim,"auto");
char_from_room( victim );
char_to_room( victim, original );
victim->on = on;
return FULL_MANA;
}
/****************************************************************************
* spell_downdraft - by Quenrelthaer August 97 *
****************************************************************************/
SPRESULT spell_downdraft(int sn,int level,char_data *ch,void *vo,int )
{
OBJ_DATA *obj, *obj_next;
char_data *victim=(char_data*)vo;
int dam, random;
dam = dice(level,3)+4;
if ( saves_spell( level, victim, DAMTYPE(sn)) )
dam /= 2;
damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true);
if (dam>level*2)
{
random = dice(2,10)-1;
for ( obj = victim->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
if (obj->wear_loc == random)
break;
}
if (obj == NULL)
return FULL_MANA;
act("The force of the wind blows $p to the ground.",ch,obj,NULL,TO_ROOM);
act("The force of the wind blows $p to the ground.",ch,obj,NULL,TO_CHAR);
obj_from_char(obj);
obj_to_room(obj,ch->in_room);
}
return FULL_MANA;
}
/****************************************************************************
* spell_fling - by Quenrelthaer August 97, updated by Kalahn Sept 97 *
****************************************************************************/
SPRESULT spell_fling(int sn,int level,char_data *ch,void *vo,int )
{
char_data *victim=(char_data*)vo;
OBJ_DATA *obj, *obj_next;
int dam, max;
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
if (obj->wear_loc != WEAR_NONE){
continue;
}
// can't fling what you can't see/tokens
if( !can_see_obj(ch, obj) || obj->item_type == ITEM_TOKEN){
continue;
}
// can't fling nodrop items to get rid of them
if ( !can_drop_obj( ch, obj ) ){
act("You can't seem to fling $p, you decide to try something else!",ch,obj,NULL,TO_CHAR);
continue;
}
// we have something potentially flingable
break;
}
if (obj == NULL)
{
ch->println("You must be carrying something to fling.");
return NO_MANA;
}
max = ((obj->weight)/10)+1;
if (max>level+5)
{
act("$p is too heavy for you to fling.",ch,obj,NULL,TO_CHAR);
return HALF_MANA;
}
act("Your magic flings $p into the air!",ch,obj,NULL,TO_CHAR);
dam = dice(max,4);
if ( saves_spell( level, victim, DAMTYPE(sn)) )
dam /= 2;
damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true);
act("$p flies up into the air, then plummets downward, striking heavily.",ch,obj,NULL,TO_ROOM);
act("$p hits the ground with a thud.",ch,obj,NULL,TO_ROOM);
act("$p hits the ground with a thud.",ch,obj,NULL,TO_CHAR);
obj_from_char( obj );
obj_to_room(obj,ch->in_room);
return FULL_MANA;
}
/****************************************************************************
* spell_shaping_the_chaos - by Quenrelthaer & Kalahn August 97 *
****************************************************************************/
SPRESULT spell_shaping_the_chaos(int ,int level,char_data *ch,void *,int )
{
OBJ_INDEX_DATA *pObjIndex;
MOB_INDEX_DATA *pMobIndex;
OBJ_DATA *obj_chaos;
char_data *mob_chaos;
char buf[MSL];
int random, max;
ch->println("You reach into the chaos with your mind and attempt\r\nto shape it into something...");
int value =0; // default type is an object
// in rooms that are 'law' objects only summoned
if(ch->in_room && !IS_SET(ch->in_room->room_flags,ROOM_LAW)){
value =number_range(0,1);
}
switch (value)
{
case 0: // CREATE CHAOS OBJECT
max = dice(1,level)+5;
if (max > SPELL_SHAPING_THE_CHAOS_NUMBER_OF_OBJECTS)
max = SPELL_SHAPING_THE_CHAOS_NUMBER_OF_OBJECTS;
random = dice(1,max);
if ((pObjIndex = // check for object vnum
get_obj_index(SPELL_SHAPING_THE_CHAOS_FIRST_OBJECT_VNUM+random)))
{
obj_chaos= create_object(pObjIndex);
obj_to_room(obj_chaos,ch->in_room);
obj_chaos->timer = (ch->level/4)+1;
act("Suddenly, $p appears in midair and falls to the ground.",ch,obj_chaos,NULL,TO_ROOM);
act("The chaos forms itself into $p, which appears in midair\r\n"
"and falls to the ground.",ch,obj_chaos,NULL,TO_CHAR);
}
else /* object with the vnum not found */
{
sprintf(buf,"BUG: in spell_shaping_the_chaos - missing object vnum %d!\r\n", 49+random);
wiznet(buf,NULL,NULL,WIZ_BUGS,0,AVATAR); /* put it on the bug wiznet channel */
log_string( buf ); /* log the bug in the logs */
do_bug ( ch, buf); /* report the bug into the bug file */
ch->printf( "%s", buf ); /* tell the char what happened */
return NO_MANA;
}
break;
case 1: /* CREATE CHAOS MOB */
max = dice(1,level)+5;
if (max > SPELL_SHAPING_THE_CHAOS_NUMBER_OF_MOBS)
max = SPELL_SHAPING_THE_CHAOS_NUMBER_OF_MOBS;
random = dice(1,max);
if ((pMobIndex = // make sure mob exists
get_mob_index(SPELL_SHAPING_THE_CHAOS_FIRST_MOB_VNUM+random)))
{
mob_chaos = create_mobile(pMobIndex,0); // create the mobile
mob_chaos->level = ch->level;
mob_chaos->no_xp = true; // can't get xp for killing it
char_to_room( mob_chaos ,ch->in_room);
act("Suddenly, $N appears in midair and falls to the ground, landing solidly.",ch,NULL,mob_chaos,TO_ROOM);
act("The chaos takes the form of $N, which appears in midair\nand falls to the ground, landing on its feet.",ch,NULL,mob_chaos,TO_CHAR);
}
else // mob with the vnum not found
{
sprintf(buf,"BUG: in spell_shaping_the_chaos - missing mob vnum %d!\r\n", 49+random);
wiznet(buf,NULL,NULL,WIZ_BUGS,0,AVATAR); // put it on the bug wiznet channel
log_string( buf ); // log the bug in the logs
do_bug ( ch, buf); // report the bug into the bug file
ch->printf( "%s", buf );
return NO_MANA;
}
break;
}
return FULL_MANA;
}
/****************************************************************************
* spell_spirit_walk - by Quenrelthaer - August 97 *
****************************************************************************/
SPRESULT spell_spirit_walk(int sn,int level,char_data *ch,void *vo,int )
{
char buf[MSL];
char_data *victim=(char_data*)vo;
char_data *spirit;
MOB_INDEX_DATA *pMobIndex;
if(IS_SWITCHED(ch)){
ch->println("You can't control two forms at once.");
return NO_MANA;
}
if ( ( victim = get_char_world( ch, target_name ) ) == NULL
|| victim->in_room == NULL
|| IS_SET(ch->in_room->room_flags, ROOM_SAFE)
|| IS_SET(victim->in_room->room_flags, ROOM_SAFE)
|| victim->level >= level + 3
|| (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL)
|| (IS_NPC(victim) && IS_SET(victim->imm_flags,IMM_SUMMON))
|| (IS_NPC(victim) && saves_spell( level, victim,DAMTYPE(sn))))
{
ch->println("You could not hold your spirit there.");
return FULL_MANA;
}
pMobIndex = get_mob_index(SPELL_SPIRIT_WALK_SPIRIT_MOB);
if (!pMobIndex) // mob with the vnum not found
{
sprintf(buf,"BUG: in spell_spirit_walk - missing host mob!!! <vnum %d>\r\n",
SPELL_SPIRIT_WALK_SPIRIT_MOB);
wiznet(buf,NULL,NULL,WIZ_BUGS,0,AVATAR); // put it on the bug wiznet channel
log_string( buf ); // log the bug in the logs
do_bug ( ch, buf); // report the bug into the bug file
ch->printf( "%s", buf );
return NO_MANA;
}
spirit = create_mobile(pMobIndex, 0);
char_to_room(spirit, victim->in_room);
ch->desc->character = spirit;
ch->desc->original = ch;
spirit->desc = ch->desc;
ch->desc = NULL;
ch->controlling = spirit; // so switched ppl aren't marked as idle/linkdead
// change communications to match
if (ch->prompt != NULL)
spirit->prompt = str_dup(ch->prompt);
spirit->comm = ch->comm;
spirit->lines = ch->lines;
spirit->timer = ch->level/40+1; //set how long the spirit will last
spirit->println("Your spirit pulls away from your body...");
spirit->println("You find yourself somewhere else...");
do_look(spirit,"auto");
return FULL_MANA;
}
/***************************************************************************/