/***************************************************************************
* 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 */
/***************************************************************************/
/* */
/* 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_DART 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;
outside = 0; /* used to make mob move */
one_argument (argument, arg);
if (arg[0] == '\0' && ch->fighting == NULL)
{
send_to_char ("You could throw at them, but no one is there!\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 != WEAPON_DART )
{
send_to_char( "You can throw only a throwing weapon.\n\r", ch );
return;
}*/
if (arg[0] == '\0')
{
if (ch->fighting != NULL)
{
victim = ch->fighting;
}
else
{
send_to_char ("Throw at 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, NULL, 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, NULL, 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 avoids 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);
sprintf (buf, "You don't have %s to throw.\n\r", obj->short_descr);
/* ITEM THROWING */
if (obj->item_type != 0)
{
/* check if there is a victim */
if (victim != NULL)
{
act ("$n throw $p at $N.", ch, obj, victim, TO_NOTVICT);
act ("You throw $p at $N.", ch, obj, victim, TO_CHAR);
act ("$n throws $p at 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 and miss your target.",
ch, obj, NULL, TO_CHAR);
act ("$n throws $p aimlessly and misses their target.",
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 object of the same key_word and that is a throwing */
for (obj_next = ch->carrying; obj_next != NULL
&& ((obj_next->item_type != ITEM_DART)
|| (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 makes 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, "Something comes flying in from NORTH!!!\n\r");
break;
case 1:
sprintf (buf, "Something comes flying in from EAST!!!\n\r");
break;
case 2:
sprintf (buf, "Something comes flying in from SOUTH!!!\n\r");
break;
case 3:
sprintf (buf, "Something comes flying in from WEST!!!\n\r");
break;
case 4:
sprintf (buf, "Something comes flying in from ABOVE!!!\n\r");
break;
case 5:
sprintf (buf, "Something comes flying in from BELOW!!!\n\r");
break;
default:
sprintf (buf,
"Throw ERROR, congratulate Xeric for messing up again.\n\r");
break;
}
send_to_char (buf, victim);
}
}
return;
}