/***************************************************************************
* FALLEN ANGELS mud is protected by french law of intelectual *
* property. we share freely all we have coded *
* provided this message isn't removed from the *
* files and you respect the name of all the *
* coders,area builders, and all the Diku,Merc, *
* Rom licences. *
* *
* Thank to : ROM consortium . *
* Big thank to : Gary Gygax !!!!!!!!!!!!!! *
* *
* Fallen Angel project by : Loran ( laurent zilbert ) *
* Silfen or *
* Gwendoline ( jerome despret ) *
* *
* Despret@ecoledoc.lip6.fr ... *
***************************************************************************/
/***************************************************************************
* *
* To use this snipet you must set the following line in the "throw" help *
* *
* Coded for Fallen Angels by : Zilber laurent,Despret jerome. *
* *
* And send a mail to say you use it ( feel free to comment ) at : *
* *
* [despret@ecoledoc.lip6.fr] or/and at [loran@hotmail.com] *
****************************************************************************/
/***************************************************************************
* *
* If you want to put this snipet on your web site you are allowed to but *
* the file must remain unchanged and you have to send us a mail at : *
* *
* [despret@ecoledoc.lip6.fr] or/and at [loran@hotmail.com] *
* with the site URL. *
* *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "db.h"
#include "recycle.h"
#include "magic.h"
/* command procedures needed */
DECLARE_DO_FUN(do_say );
void wear_obj args( (CHAR_DATA *ch, OBJ_DATA *obj, bool fReplace ) );
/***************************************************************************/
/* */
/* One ROOM RANGED ATTACK system ( the throw ) */
/* */
/***************************************************************************/
/* _________________________________________________________________________
Of course you have to create a gsn_throw and associate it to do_throw then:
You have to create an ITEM_THROWING item type it should look like the
following example :
#10002
dart~
a strange dart~
You see a little dart here.~
wood~
throwing 0 AO
5 6 pierce 15 'fireball'
0 10 210 P
v0: is the number of dice dammage
v1: is the number of side of each dice
v3: the type of dammage ( same as weapon's ones )
v4: usualy filled with a 0 but hightly powered dart can be filled with
a spell effect if so this hold the level of the spell.
v5: hold the spell, if you wanna make a clumsy dart fill it with
a benefit spell.. would you throw a spear that make a heal on
the victim... dart and flask are't the same on our mud
flask are more powerful, but dart is more a warrior skill to make
distant attack however both use throw command... the code make
the difference between classes using flask and throwing weapon.
_________________________________________________________________________ */
/***************************************************************************
The throwing code allow now a one room ranged target.
following things are tested and forbid.
throw trought a closed door
targeting a sentinel mob
targeting a mob that isn't allowed to enter the ch room
targeting a mob in another area ( specialy for frontier )
****************************************************************************/
void do_throw( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj,*obj_next;
ROOM_INDEX_DATA *was_in_room;
EXIT_DATA *pexit;
char buf[256];
int damm,damm_type,door,outside,i;
outside=0; /* used to make mob move */
one_argument( argument, arg );
if ( arg[0] == '\0' && ch->fighting == NULL )
{
send_to_char( "Throw on whom or what?\n\r", ch );
return;
}
if ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
{
send_to_char( "You hold nothing in your hand.\n\r", ch );
return;
}
if ( obj->item_type != ITEM_THROWING )
{
send_to_char( "You can throw only a throwing weapons.\n\r", ch );
return;
}
if ( arg[0] == '\0' )
{
if ( ch->fighting != NULL )
{
victim = ch->fighting;
}
else
{
send_to_char( "Throw on whom or what?\n\r", ch );
return;
}
}
else
{
/* try to use 1 range victim allowance */
/* look if victim is in the room if note look the suroundings rooms */
if ( ( victim = get_char_room ( ch, arg ) ) == NULL)
{
was_in_room=ch->in_room;
for( door=0 ; door<=5 && victim==NULL ; door++ )
{
if ( ( pexit = was_in_room->exit[door] ) != NULL
&& pexit->u1.to_room != NULL
&& pexit->u1.to_room != was_in_room
&& !strcmp( pexit->u1.to_room->area->name ,
was_in_room->area->name ) )
{
ch->in_room = pexit->u1.to_room;
victim = get_char_room ( ch, arg );
}
}
ch->in_room=was_in_room;
if(victim==NULL)
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
else
{ if(IS_SET(pexit->exit_info,EX_CLOSED))
{ send_to_char("You can't throw through a door !!",ch);
return;
}
outside=1; /* target was outside of the room */
/* forbid target that cannot move back to revenge on
the thrower */
if(IS_NPC(victim))
{
if ( IS_SET(victim->act, ACT_SENTINEL)
|| IS_SET(ch->in_room->room_flags, ROOM_NO_MOB)
|| ( IS_SET(victim->act, ACT_OUTDOORS)
&& IS_SET(ch->in_room->room_flags,ROOM_INDOORS))
|| ( IS_SET(victim->act, ACT_INDOORS)
&& IS_SET(ch->in_room->room_flags,ROOM_INDOORS)))
{
act("$N avoid your deadly throw !!!",ch,obj,victim,TO_CHAR);
was_in_room=ch->in_room;
ch->in_room=victim->in_room;
act("$N avoid $p thrown by $n.",ch,obj,victim,TO_NOTVICT);
act("You avoid $p thrown by $n.",ch,obj,victim,TO_VICT);
ch->in_room=was_in_room;
extract_obj(obj);
return;
}
}
}
}
}
/* this is a strong attack i recomande this wait state */
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
sprintf(buf,"You have no more of %s.\n\r",obj->short_descr);
/* ITEM THROWING */
if(obj->item_type== ITEM_THROWING )
{
/* check if there is a victim */
if ( victim != NULL )
{
act( "$n throw $p on $N.", ch, obj, victim, TO_NOTVICT );
act( "You throw $p on $N.", ch, obj, victim, TO_CHAR );
act( "$n throw $p on you.",ch, obj, victim, TO_VICT );
if(outside)
{ was_in_room=ch->in_room;
ch->in_room=victim->in_room;
act( "$n throw $p on $N.", ch, obj, victim, TO_NOTVICT );
ch->in_room=was_in_room;
}
}
/* throw the dices :) */
if (ch->level < obj->level
|| number_percent() >= 20 + get_skill(ch,gsn_throw) * 4/5 - (10 * outside) )
{
/* it is a normal miss */
act( "You throw $p aimlessly on the ground and it broke up.",
ch, obj,NULL,TO_CHAR);
act( "$n throw $p aimlessly on the ground and it broke up.",
ch, obj,NULL,TO_ROOM);
check_improve(ch,gsn_throw,FALSE,2);
}
else
{
/* it is a success hit the target */
damm = dice(obj->value[0],obj->value[1]);
damm_type = TYPE_HIT;
damm_type += attack_table[obj->value[2]].damage;
damage( ch, victim, damm, damm_type,gsn_throw,TRUE);
if( (obj->value[3] != 0)
&& (obj->value[4] != 0)
&& (victim->position > POS_DEAD) )
obj_cast_spell( obj->value[4], obj->value[3], ch, victim, obj);
check_improve(ch,gsn_throw,TRUE,2);
}
/* look in the inventory for an objet of the same key_word and that is a throwing */
for(obj_next=ch->carrying; obj_next != NULL
&& ( (obj_next->item_type != ITEM_THROWING )
|| ( obj == obj_next )
|| (strcmp(obj->name, obj_next->name) ) );
obj_next=obj_next->next_content );
extract_obj(obj);
/* if found equip the ch with */
if ( obj_next == NULL )
{
send_to_char( buf, ch );
}
else
{
wear_obj( ch, obj_next, TRUE );
}
}
/* Routine that make a ranged mob moving 50%
to attack the aggressor ..... i m looking for a way
to make the mob wait a little before doing it */
if( outside
&& (victim != NULL )
&& (victim->position > POS_STUNNED) )
{
pexit = victim->in_room->exit[0];
for( door=0 ; door<=5 ; door++ )
{
pexit = victim->in_room->exit[door];
if( pexit != NULL
&& (pexit->u1.to_room == ch->in_room) )
break;
}
if(door>=6)
{
bug("no back way in throw....",0);
return;
}
if(IS_NPC(victim) && (number_percent() > 50 ) )
{
if ( !IS_SET(ch->act, ACT_SENTINEL)
&& ( pexit = victim->in_room->exit[door] ) != NULL
&& pexit->u1.to_room != NULL
&& !IS_SET(pexit->exit_info, EX_CLOSED)
&& !IS_SET(pexit->u1.to_room->room_flags, ROOM_NO_MOB)
&& ( !IS_SET(victim->act, ACT_OUTDOORS)
|| !IS_SET(pexit->u1.to_room->room_flags,ROOM_INDOORS))
&& ( !IS_SET(victim->act, ACT_INDOORS)
|| IS_SET(pexit->u1.to_room->room_flags,ROOM_INDOORS))
&& ( IS_NPC(victim) )
&& ( (victim->position != POS_FIGHTING)
|| ( victim->fighting == ch ) ) )
{
if( (victim->position == POS_FIGHTING)
&& ( victim->fighting == ch ) )
{ stop_fighting( victim, TRUE );
}
move_char( victim, door, FALSE );
(victim)->wait = UMAX((victim)->wait, (8));
act("$N scream and attack $n !!!",ch,NULL,victim,TO_NOTVICT);
act("$N scream and attack You !!!",ch,NULL,victim,TO_CHAR);
multi_hit( victim, ch, TYPE_UNDEFINED );
}
}
else
{
switch(door)
{ case 0 : sprintf(buf,"The throw came from NORTH !!!\n\r");
break;
case 1 : sprintf(buf,"The throw came from EAST !!!\n\r");
break;
case 2 : sprintf(buf,"The throw came from SOUTH !!!\n\r");
break;
case 3 : sprintf(buf,"The throw came from WEST !!!\n\r");
break;
case 4 : sprintf(buf,"The throw came from UP !!!\n\r");
break;
case 5 : sprintf(buf,"The throw came from DOWN !!!\n\r");
break;
default : sprintf(buf,"Throw ERROR award an IMM\n\r");
break;
}
send_to_char(buf,victim);
}
}
return;
}