/***************************************************************************
* STAR WARS REALITY 1.0 *
*--------------------------------------------------------------------------*
* Star Wars Reality Code Additions and changes from the Smaug Code *
* copyright (c) 1997 by Sean Cooper *
* -------------------------------------------------------------------------*
* Starwars and Starwars Names copyright(c) Lucasfilm Ltd. *
*--------------------------------------------------------------------------*
* SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* New Star Wars Skills Unit *
****************************************************************************/
#include <math.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"
ch_ret one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) );
ROOM_INDEX_DATA *generate_exit( ROOM_INDEX_DATA *in_room, EXIT_DATA **pexit );
CHAR_DATA *get_char_room_mp( CHAR_DATA *ch, char *argument );
ch_ret noparry_damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt);
extern int top_affect;
void do_mine( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
char logbuf[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
bool shovel;
sh_int move;
if ( ch->pcdata->learned[gsn_mine] <= 0 )
{
ch_printf( ch, "You have no idea how to do that.\n\r" );
return;
}
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "And what will you mine the room with?\n\r", ch );
return;
}
if ( ms_find_obj(ch) )
return;
shovel = FALSE;
for ( obj = ch->first_carrying; obj; obj = obj->next_content )
if ( obj->item_type == ITEM_SHOVEL )
{
shovel = TRUE;
break;
}
obj = get_obj_list_rev( ch, arg, ch->in_room->last_content );
if ( !obj )
{
send_to_char( "You don't see on here.\n\r", ch );
return;
}
separate_obj(obj);
if ( obj->item_type != ITEM_LANDMINE )
{
act( AT_PLAIN, "That's not a landmine!", ch, obj, 0, TO_CHAR );
return;
}
if ( !CAN_WEAR(obj, ITEM_TAKE) )
{
act( AT_PLAIN, "You cannot bury $p.", ch, obj, 0, TO_CHAR );
return;
}
switch( ch->in_room->sector_type )
{
case SECT_INSIDE:
send_to_char( "The floor is too hard to dig through.\n\r", ch );
return;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_UNDERWATER:
send_to_char( "You cannot bury a mine in the water.\n\r", ch );
return;
case SECT_AIR:
send_to_char( "What? Bury a mine in the air?!\n\r", ch );
return;
}
if ( obj->weight > (UMAX(5, (can_carry_w(ch) / 10)))
&& !shovel )
{
send_to_char( "You'd need a shovel to bury something that big.\n\r", ch );
return;
}
move = (obj->weight * 50 * (shovel ? 1 : 5)) / UMAX(1, can_carry_w(ch));
move = URANGE( 2, move, 1000 );
if ( move > ch->move )
{
send_to_char( "You don't have the energy to bury something of that size.\n\r", ch );
return;
}
ch->move -= move;
SET_BIT( obj->extra_flags, ITEM_BURRIED );
WAIT_STATE( ch, URANGE( 10, move / 2, 100 ) );
STRFREE ( obj->armed_by );
obj->armed_by = STRALLOC ( ch->name );
ch_printf( ch, "You arm and bury %s.\n\r", obj->short_descr );
act( AT_PLAIN, "$n arms and buries $p.", ch, obj, NULL, TO_ROOM );
sprintf ( logbuf, "%s has laid a mine in room %d", ch->name, ch->in_room->vnum );
log_string (logbuf);
learn_from_success( ch, gsn_mine );
return;
}
void do_snipe( CHAR_DATA *ch, char *argument )
{
OBJ_DATA * wield;
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
sh_int dir, dist;
sh_int max_dist = 3;
EXIT_DATA * pexit;
ROOM_INDEX_DATA * was_in_room;
ROOM_INDEX_DATA * to_room;
CHAR_DATA * victim;
int chance;
ch_ret dummy;
char buf[MAX_STRING_LENGTH];
bool pfound = FALSE;
if(!IS_NPC(ch))
{
if(IS_SET(ch->pcdata->flags, PCFLAG_BOUND))
{
send_to_char("Not when you are bound up.\n\r", ch);
return;
}
}
if ( ch->subclass == SUBCLASS_SNIPER)
max_dist = 10;
if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "You'll have to do that elswhere.\n\r", ch );
return;
}
if ( get_eq_char( ch, WEAR_DUAL_WIELD ) != NULL )
{
send_to_char( "You can't do that while wielding two weapons.",ch );
return;
}
wield = get_eq_char( ch, WEAR_WIELD );
if ( !wield || wield->item_type != ITEM_WEAPON || (
wield->value[3] != WEAPON_BLASTER && wield->value[3] != WEAPON_SLUGTHROWER && wield->value[3] != WEAPON_BOWCASTER ))
{
send_to_char( "You don't seem to be holding a projectile weapon.",ch );
return;
}
argument = one_argument( argument, arg );
argument = one_argument( argument, arg2 );
if ( ( dir = get_door( arg ) ) == -1 || arg2[0] == '\0' )
{
send_to_char( "Usage: snipe <dir> <target>\n\r", ch );
return;
}
if ( ( pexit = get_exit( ch->in_room, dir ) ) == NULL )
{
send_to_char( "Are you expecting to fire through a wall!?\n\r", ch );
return;
}
if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
{
send_to_char( "Are you expecting to fire through a door!?\n\r", ch );
return;
}
was_in_room = ch->in_room;
for ( dist = 0; dist <= max_dist; dist++ )
{
if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
break;
if ( !pexit->to_room )
break;
to_room = NULL;
if ( pexit->distance > 1 )
to_room = generate_exit( ch->in_room , &pexit );
if ( to_room == NULL )
to_room = pexit->to_room;
char_from_room( ch );
char_to_room( ch, to_room );
if ( IS_NPC(ch) && ( victim = get_char_room_mp( ch, arg2 ) ) != NULL )
{
pfound = TRUE;
break;
}
else if ( !IS_NPC(ch) && ( victim = get_char_room( ch, arg2 ) ) != NULL )
{
pfound = TRUE;
break;
}
if ( ( pexit = get_exit( ch->in_room, dir ) ) == NULL )
break;
}
char_from_room( ch );
char_to_room( ch, was_in_room );
if ( !pfound )
{
ch_printf( ch, "You don't see that person to the %s!\n\r", dir_name[dir] );
char_from_room( ch );
char_to_room( ch, was_in_room );
return;
}
if ( victim == ch )
{
send_to_char( "Shoot yourself ... really?\n\r", ch );
return;
}
if ( IS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "You can't shoot them there.\n\r", ch );
return;
}
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
act( AT_PLAIN, "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
return;
}
if ( ch->position == POS_FIGHTING )
{
send_to_char( "You do the best you can!\n\r", ch );
return;
}
if ( !IS_NPC( victim ) && IS_SET( ch->act, PLR_NICE ) )
{
send_to_char( "You feel too nice to do that!\n\r", ch );
return;
}
chance = IS_NPC(ch) ? 100
: (int) (ch->pcdata->learned[gsn_snipe]) ;
switch ( dir )
{
case 0:
case 1:
dir += 2;
break;
case 2:
case 3:
dir -= 2;
break;
case 4:
case 7:
dir += 1;
break;
case 5:
case 8:
dir -= 1;
break;
case 6:
dir += 3;
break;
case 9:
dir -=3;
break;
}
char_from_room( ch );
char_to_room( ch, victim->in_room );
if ( number_percent() < chance )
{
if (ch->subclass != SUBCLASS_SNIPER )
{
sprintf( buf , "A blaster shot fires at you from the %s." , dir_name[dir] );
act( AT_ACTION, buf , victim, NULL, ch, TO_CHAR );
act( AT_ACTION, "You fire at $N.", ch, NULL, victim, TO_CHAR );
sprintf( buf, "A blaster shot fires at $N from the %s." , dir_name[dir] );
act( AT_ACTION, buf, ch, NULL, victim, TO_NOTVICT );
one_hit( ch, victim, TYPE_UNDEFINED );
} else
{
if (ch->sniperweapon != 0 && number_percent() <= 5)
{
act( AT_ACTION, "You Whisper, one Shot, One Kill as you line $N in your scope.",ch,NULL,victim,TO_CHAR);
if (!IS_IMMORTAL(victim))
raw_kill(ch, victim);
else
dummy = noparry_damage (ch, victim, 32700, TYPE_HIT + wield->value[3]);
char_from_room( ch );
char_to_room( ch, was_in_room );
return;
}
sprintf( buf , "A flurry of shots fire at you from the %s." , dir_name[dir] );
act( AT_ACTION, buf , victim, NULL, ch, TO_CHAR );
act( AT_ACTION, "You squeeze three shots off at $N.", ch, NULL, victim, TO_CHAR );
sprintf( buf, "A trio of shots fires at $N from the %s." , dir_name[dir] );
act( AT_ACTION, buf, ch, NULL, victim, TO_NOTVICT );
one_hit( ch, victim, TYPE_UNDEFINED );
one_hit( ch, victim, TYPE_UNDEFINED );
one_hit( ch, victim, TYPE_UNDEFINED );
}
if ( char_died(ch) )
return;
stop_fighting( ch , TRUE );
learn_from_success( ch, gsn_snipe );
}
else
{
act( AT_ACTION, "You fire at $N but don't even come close.", ch, NULL, victim, TO_CHAR );
sprintf( buf, "A blaster shot fired from the %s barely misses you." , dir_name[dir] );
act( AT_ACTION, buf, ch, NULL, victim, TO_ROOM );
learn_from_failure( ch, gsn_snipe );
}
char_from_room( ch );
char_to_room( ch, was_in_room );
if ( IS_NPC(ch) )
WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
else
{
if ( number_percent() < ch->pcdata->learned[gsn_third_attack] )
WAIT_STATE( ch, 1 * PULSE_PER_SECOND );
else if ( number_percent() < ch->pcdata->learned[gsn_second_attack] )
WAIT_STATE( ch, 2 * PULSE_PER_SECOND );
else
WAIT_STATE( ch, 3 * PULSE_PER_SECOND );
}
if ( IS_NPC( victim ) && !char_died(victim) )
{
if ( IS_SET( victim->act , ACT_SENTINEL ) )
{
victim->was_sentinel = victim->in_room;
REMOVE_BIT( victim->act, ACT_SENTINEL );
}
start_hating( victim , ch );
start_hunting( victim, ch );
}
}
/* syntax throw <obj> [direction] [target] */
void do_throw( CHAR_DATA *ch, char *argument )
{
OBJ_DATA * obj;
OBJ_DATA * tmpobj;
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
sh_int dir;
EXIT_DATA * pexit;
ROOM_INDEX_DATA * was_in_room;
ROOM_INDEX_DATA * to_room;
CHAR_DATA * victim;
char buf[MAX_STRING_LENGTH];
argument = one_argument( argument, arg );
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
was_in_room = ch->in_room;
if ( arg[0] == '\0' )
{
send_to_char( "Usage: throw <object> [direction] [target]\n\r", ch );
return;
}
obj = get_eq_char( ch, WEAR_MISSILE_WIELD );
if ( !obj || !nifty_is_name( arg, obj->name ) )
obj = get_eq_char( ch, WEAR_HOLD );
if ( !obj || !nifty_is_name( arg, obj->name ) )
obj = get_eq_char( ch, WEAR_WIELD );
if ( !obj || !nifty_is_name( arg, obj->name ) )
obj = get_eq_char( ch, WEAR_DUAL_WIELD );
if ( !obj || !nifty_is_name( arg, obj->name ) )
if ( !obj || !nifty_is_name_prefix( arg, obj->name ) )
obj = get_eq_char( ch, WEAR_HOLD );
if ( !obj || !nifty_is_name_prefix( arg, obj->name ) )
obj = get_eq_char( ch, WEAR_WIELD );
if ( !obj || !nifty_is_name_prefix( arg, obj->name ) )
obj = get_eq_char( ch, WEAR_DUAL_WIELD );
if ( !obj || !nifty_is_name_prefix( arg, obj->name ) )
{
ch_printf( ch, "You don't seem to be holding or wielding %s.\n\r", arg );
return;
}
if ( IS_OBJ_STAT(obj, ITEM_NOREMOVE) )
{
act( AT_PLAIN, "You can't throw $p.", ch, obj, NULL, TO_CHAR );
return;
}
if ( ch->position == POS_FIGHTING )
{
victim = who_fighting( ch );
if ( char_died ( victim ) )
return;
act( AT_ACTION, "You throw $p at $N.", ch, obj, victim, TO_CHAR );
act( AT_ACTION, "$n throws $p at $N.", ch, obj, victim, TO_NOTVICT );
act( AT_ACTION, "$n throw $p at you.", ch, obj, victim, TO_VICT );
}
else if ( arg2[0] == '\0' )
{
sprintf( buf, "$n throws %s at the floor." , obj->short_descr );
act( AT_ACTION, buf, ch, NULL, NULL, TO_ROOM );
ch_printf( ch, "You throw %s at the floor.\n\r", obj->short_descr );
victim = NULL;
}
else if ( ( dir = get_door( arg2 ) ) != -1 )
{
if ( ( pexit = get_exit( ch->in_room, dir ) ) == NULL )
{
send_to_char( "Are you expecting to throw it through a wall!?\n\r", ch );
return;
}
if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
{
send_to_char( "Are you expecting to throw it through a door!?\n\r", ch );
return;
}
switch ( dir )
{
case 0:
case 1:
dir += 2;
break;
case 2:
case 3:
dir -= 2;
break;
case 4:
case 7:
dir += 1;
break;
case 5:
case 8:
dir -= 1;
break;
case 6:
dir += 3;
break;
case 9:
dir -=3;
break;
}
to_room = NULL;
if ( pexit->distance > 1 )
to_room = generate_exit( ch->in_room , &pexit );
if ( to_room == NULL )
to_room = pexit->to_room;
char_from_room( ch );
char_to_room( ch, to_room );
victim = get_char_room( ch, arg3 );
if ( victim )
{
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
act( AT_PLAIN, "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
return;
}
if ( !IS_NPC( victim ) && IS_SET( ch->act, PLR_NICE ) )
{
send_to_char( "You feel too nice to do that!\n\r", ch );
return;
}
char_from_room( ch );
char_to_room( ch, was_in_room );
if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "You'll have to do that elswhere.\n\r", ch );
return;
}
to_room = NULL;
if ( pexit->distance > 1 )
to_room = generate_exit( ch->in_room , &pexit );
if ( to_room == NULL )
to_room = pexit->to_room;
char_from_room( ch );
char_to_room( ch, to_room );
sprintf( buf , "Someone throws %s at you from the %s." , obj->short_descr , dir_name[dir] );
act( AT_ACTION, buf , victim, NULL, ch, TO_CHAR );
act( AT_ACTION, "You throw $p at $N.", ch, obj, victim, TO_CHAR );
sprintf( buf, "%s is thrown at $N from the %s." , obj->short_descr , dir_name[dir] );
act( AT_ACTION, buf, ch, NULL, victim, TO_NOTVICT );
}
else
{
ch_printf( ch, "You throw %s %s.\n\r", obj->short_descr , dir_name[get_dir( arg2 )] );
sprintf( buf, "%s is thrown from the %s." , obj->short_descr , dir_name[dir] );
act( AT_ACTION, buf, ch, NULL, NULL, TO_ROOM );
}
}
else if ( ( victim = get_char_room( ch, arg2 ) ) != NULL )
{
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
act( AT_PLAIN, "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
return;
}
if ( !IS_NPC( victim ) && IS_SET( ch->act, PLR_NICE ) )
{
send_to_char( "You feel too nice to do that!\n\r", ch );
return;
}
}
else
{
ch_printf( ch, "They don't seem to be here!\n\r");
return;
}
if ( obj == get_eq_char( ch, WEAR_WIELD )
&& ( tmpobj = get_eq_char( ch, WEAR_DUAL_WIELD)) != NULL )
tmpobj->wear_loc = WEAR_WIELD;
unequip_char( ch, obj );
separate_obj( obj );
obj_from_char( obj );
obj = obj_to_room( obj, ch->in_room );
if ( obj->item_type != ITEM_GRENADE )
damage_obj ( obj );
/* NOT NEEDED UNLESS REFERING TO OBJECT AGAIN
if( obj_extracted(obj) )
return;
*/
if ( ch->in_room != was_in_room )
{
char_from_room( ch );
char_to_room( ch, was_in_room );
}
if ( !victim || char_died( victim ) )
learn_from_failure( ch, gsn_throw );
else
{
WAIT_STATE( ch, skill_table[gsn_throw]->beats );
if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_throw] )
{
learn_from_success( ch, gsn_throw );
global_retcode = damage( ch, victim, number_range( obj->weight*2 , (obj->weight*2 + ch->perm_str) ), TYPE_HIT );
}
else
{
learn_from_failure( ch, gsn_throw );
global_retcode = damage( ch, victim, 0, TYPE_HIT );
}
if ( IS_NPC( victim ) && !char_died ( victim) )
{
if ( IS_SET( victim->act , ACT_SENTINEL ) )
{
victim->was_sentinel = victim->in_room;
REMOVE_BIT( victim->act, ACT_SENTINEL );
}
start_hating( victim , ch );
start_hunting( victim, ch );
}
}
return;
}
void do_slice( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg1 [MAX_INPUT_LENGTH];
OBJ_DATA *obj;
if ( IS_NPC(ch) )
return;
if ( ch->subclass != SUBCLASS_BLADEMASTER )
{
send_to_char( "Only Swordsmen can execute a proper slice attack!!\n\r" , ch );
return;
}
argument = one_argument( argument, arg1 );
if ( arg1[0] == '\0' )
{
send_to_char( "Slice whom?\n\r", ch );
return;
}
if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if ( victim == ch )
{
send_to_char( "That's pointless.\n\r", ch );
return;
}
if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "This isn't a good place to do that.\n\r", ch );
return;
}
if ( ch->position <= POS_SLEEPING )
{
send_to_char( "In your dreams or what?\n\r" , ch );
return;
}
if( (obj = get_eq_char(ch, WEAR_WIELD)) == NULL)
{
send_to_char("With what weapon?\n\r", ch);
return;
}
else
{
if(obj->value[3] != WEAPON_SWORD && obj->value[3] != WEAPON_LIGHTSABER && obj->value[3] != WEAPON_VIBRO_SWORD )
{
send_to_char("You can only slice with a lightsaber or a sword.\n\r", ch);
return;
}
}
global_retcode = multi_hit( ch, victim, gsn_slice );
WAIT_STATE(ch, PULSE_VIOLENCE);
return;
}