/***************************************************************************
* 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) Lucas Film 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. *
* ------------------------------------------------------------------------ *
* Battle & death module *
****************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include "mud.h"
extern char lastplayercmd[MAX_INPUT_LENGTH];
extern CHAR_DATA *gch_prev;
/* From Skills.c */
int ris_save( CHAR_DATA * ch, int schance, int ris );
/*
* Local functions.
*/
void dam_message args( ( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt ) );
void group_gain args( ( CHAR_DATA * ch, CHAR_DATA * victim ) );
int xp_compute args( ( CHAR_DATA * gch, CHAR_DATA * victim ) );
int align_compute args( ( CHAR_DATA * gch, CHAR_DATA * victim ) );
ch_ret one_hit args( ( CHAR_DATA * ch, CHAR_DATA * victim, int dt ) );
int obj_hitroll args( ( OBJ_DATA * obj ) );
bool get_cover( CHAR_DATA * ch );
bool dual_flip = FALSE;
bool loot_coins_from_corpse( CHAR_DATA *ch, OBJ_DATA *corpse )
{
OBJ_DATA *content, *content_next;
int oldgold = ch->gold;
for( content = corpse->first_content; content; content = content_next )
{
content_next = content->next_content;
if( content->item_type != ITEM_MONEY )
continue;
if( !can_see_obj( ch, content ) )
continue;
if( !CAN_WEAR( content, ITEM_TAKE ) && ch->top_level < sysdata.level_getobjnotake )
continue;
if( IS_OBJ_STAT( content, ITEM_PROTOTYPE ) && !can_take_proto( ch ) )
continue;
act( AT_ACTION, "You get $p from $P", ch, content, corpse, TO_CHAR );
act( AT_ACTION, "$n gets $p from $P", ch, content, corpse, TO_ROOM );
obj_from_obj( content );
check_for_trap( ch, content, TRAP_GET );
if( char_died( ch ) )
return FALSE;
oprog_get_trigger( ch, content );
if( char_died( ch ) )
return FALSE;
ch->gold += content->value[0] * content->count;
extract_obj( content );
}
if( ch->gold - oldgold > 1 && ch->position > POS_SLEEPING )
{
char buf[MAX_INPUT_LENGTH];
snprintf( buf, MAX_INPUT_LENGTH, "%d", ch->gold - oldgold );
do_split( ch, buf );
}
return TRUE;
}
/*
* Check to see if weapon is poisoned.
*/
bool is_wielding_poisoned( CHAR_DATA * ch )
{
OBJ_DATA *obj;
if( ( obj = get_eq_char( ch, WEAR_WIELD ) ) && ( IS_SET( obj->extra_flags, ITEM_POISONED ) ) )
return TRUE;
return FALSE;
}
/*
* hunting, hating and fearing code -Thoric
*/
bool is_hunting( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( !ch->hunting || ch->hunting->who != victim )
return FALSE;
return TRUE;
}
bool is_hating( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( !ch->hating || ch->hating->who != victim )
return FALSE;
return TRUE;
}
bool is_fearing( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( !ch->fearing || ch->fearing->who != victim )
return FALSE;
return TRUE;
}
void stop_hunting( CHAR_DATA * ch )
{
if( ch->hunting )
{
STRFREE( ch->hunting->name );
DISPOSE( ch->hunting );
ch->hunting = NULL;
}
return;
}
void stop_hating( CHAR_DATA * ch )
{
if( ch->hating )
{
STRFREE( ch->hating->name );
DISPOSE( ch->hating );
ch->hating = NULL;
}
return;
}
void stop_fearing( CHAR_DATA * ch )
{
if( ch->fearing )
{
STRFREE( ch->fearing->name );
DISPOSE( ch->fearing );
ch->fearing = NULL;
}
return;
}
void start_hunting( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( ch->hunting )
stop_hunting( ch );
CREATE( ch->hunting, HHF_DATA, 1 );
ch->hunting->name = QUICKLINK( victim->name );
ch->hunting->who = victim;
return;
}
void start_hating( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( ch->hating )
stop_hating( ch );
CREATE( ch->hating, HHF_DATA, 1 );
ch->hating->name = QUICKLINK( victim->name );
ch->hating->who = victim;
return;
}
void start_fearing( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( ch->fearing )
stop_fearing( ch );
CREATE( ch->fearing, HHF_DATA, 1 );
ch->fearing->name = QUICKLINK( victim->name );
ch->fearing->who = victim;
return;
}
int max_fight( CHAR_DATA * ch )
{
return 8;
}
/*
* Control the fights going on.
* Called periodically by update_handler.
* Many hours spent fixing bugs in here by Thoric, as noted by residual
* debugging checks. If you never get any of these error messages again
* in your logs... then you can comment out some of the checks without
* worry.
*/
void violence_update( void )
{
char buf[MAX_STRING_LENGTH];
CHAR_DATA *ch;
CHAR_DATA *lst_ch;
CHAR_DATA *victim;
CHAR_DATA *rch, *rch_next;
AFFECT_DATA *paf, *paf_next;
TIMER *timer, *timer_next;
ch_ret retcode;
SKILLTYPE *skill;
lst_ch = NULL;
for( ch = last_char; ch; lst_ch = ch, ch = gch_prev )
{
set_cur_char( ch );
if( ch == first_char && ch->prev )
{
bug( "ERROR: first_char->prev != NULL, fixing...", 0 );
ch->prev = NULL;
}
gch_prev = ch->prev;
if( gch_prev && gch_prev->next != ch )
{
sprintf( buf, "FATAL: violence_update: %s->prev->next doesn't point to ch.", ch->name );
bug( buf, 0 );
bug( "Short-cutting here", 0 );
ch->prev = NULL;
gch_prev = NULL;
do_shout( ch, "Thoric says, 'Prepare for the worst!'" );
}
/*
* See if we got a pointer to someone who recently died...
* if so, either the pointer is bad... or it's a player who
* "died", and is back at the healer...
* Since he/she's in the char_list, it's likely to be the later...
* and should not already be in another fight already
*/
if( char_died( ch ) )
continue;
/*
* See if we got a pointer to some bad looking data...
*/
if( !ch->in_room || !ch->name )
{
log_string( "violence_update: bad ch record! (Shortcutting.)" );
sprintf( buf, "ch: %ld ch->in_room: %ld ch->prev: %ld ch->next: %ld",
( long )ch, ( long )ch->in_room, ( long )ch->prev, ( long )ch->next );
log_string( buf );
log_string( lastplayercmd );
if( lst_ch )
sprintf( buf, "lst_ch: %ld lst_ch->prev: %ld lst_ch->next: %ld",
( long )lst_ch, ( long )lst_ch->prev, ( long )lst_ch->next );
else
strcpy( buf, "lst_ch: NULL" );
log_string( buf );
gch_prev = NULL;
continue;
}
/*
* Experience gained during battle deceases as battle drags on
*/
if( ch->fighting )
if( ( ++ch->fighting->duration % 24 ) == 0 )
ch->fighting->xp = ( ( ch->fighting->xp * 9 ) / 10 );
for( timer = ch->first_timer; timer; timer = timer_next )
{
timer_next = timer->next;
if( --timer->count <= 0 )
{
if( timer->type == TIMER_DO_FUN )
{
int tempsub;
tempsub = ch->substate;
ch->substate = timer->value;
( timer->do_fun ) ( ch, "" );
if( char_died( ch ) )
break;
ch->substate = tempsub;
}
extract_timer( ch, timer );
}
}
if( char_died( ch ) )
continue;
/*
* We need spells that have shorter durations than an hour.
* So a melee round sounds good to me... -Thoric
*/
for( paf = ch->first_affect; paf; paf = paf_next )
{
paf_next = paf->next;
if( paf->duration > 0 )
paf->duration--;
else if( paf->duration < 0 )
;
else
{
if( !paf_next || paf_next->type != paf->type || paf_next->duration > 0 )
{
skill = get_skilltype( paf->type );
if( paf->type > 0 && skill && skill->msg_off )
{
set_char_color( AT_WEAROFF, ch );
send_to_char( skill->msg_off, ch );
send_to_char( "\r\n", ch );
}
}
if( paf->type == gsn_possess )
{
ch->desc->character = ch->desc->original;
ch->desc->original = NULL;
ch->desc->character->desc = ch->desc;
ch->desc->character->switched = NULL;
ch->desc = NULL;
}
affect_remove( ch, paf );
}
}
if( ( victim = who_fighting( ch ) ) == NULL || IS_AFFECTED( ch, AFF_PARALYSIS ) )
continue;
retcode = rNONE;
if( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
{
sprintf( buf, "violence_update: %s fighting %s in a SAFE room.", ch->name, victim->name );
log_string( buf );
stop_fighting( ch, TRUE );
}
else if( IS_AWAKE( ch ) && ch->in_room == victim->in_room )
retcode = multi_hit( ch, victim, TYPE_UNDEFINED );
else
stop_fighting( ch, FALSE );
if( char_died( ch ) )
continue;
if( retcode == rCHAR_DIED || ( victim = who_fighting( ch ) ) == NULL )
continue;
/*
* Mob triggers
*/
rprog_rfight_trigger( ch );
if( char_died( ch ) )
continue;
mprog_hitprcnt_trigger( ch, victim );
if( char_died( ch ) )
continue;
mprog_fight_trigger( ch, victim );
if( char_died( ch ) )
continue;
/*
* Fun for the whole family!
*/
for( rch = ch->in_room->first_person; rch; rch = rch_next )
{
rch_next = rch->next_in_room;
if( IS_AWAKE( rch ) && !rch->fighting )
{
/*
* PC's auto-assist others in their group.
*/
if( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) )
{
if( ( !IS_NPC( rch ) || IS_AFFECTED( rch, AFF_CHARM ) ) && is_same_group( ch, rch ) )
multi_hit( rch, victim, TYPE_UNDEFINED );
continue;
}
/*
* NPC's assist NPC's of same type or 12.5% schance regardless.
*/
if( IS_NPC( rch ) && !IS_AFFECTED( rch, AFF_CHARM ) && !IS_SET( rch->act, ACT_NOASSIST ) )
{
if( char_died( ch ) )
break;
if( rch->pIndexData == ch->pIndexData || number_bits( 3 ) == 0 )
{
CHAR_DATA *vch;
CHAR_DATA *target;
int number;
target = NULL;
number = 0;
for( vch = ch->in_room->first_person; vch; vch = vch->next )
{
if( can_see( rch, vch ) && is_same_group( vch, victim ) && number_range( 0, number ) == 0 )
{
target = vch;
number++;
}
}
if( target )
multi_hit( rch, target, TYPE_UNDEFINED );
}
}
}
}
}
return;
}
/*
* Do one group of attacks.
*/
ch_ret multi_hit( CHAR_DATA * ch, CHAR_DATA * victim, int dt )
{
int schance;
int dual_bonus;
ch_ret retcode;
/*
* add timer if player is attacking another player
*/
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
add_timer( ch, TIMER_RECENTFIGHT, 20, NULL, 0 );
if( !IS_NPC( ch ) && IS_SET( ch->act, PLR_NICE ) && !IS_NPC( victim ) )
return rNONE;
if( ( retcode = one_hit( ch, victim, dt ) ) != rNONE )
return retcode;
if( who_fighting( ch ) != victim || dt == gsn_backstab || dt == gsn_circle )
return rNONE;
/*
* Very high schance of hitting compared to schance of going berserk
*/
/*
* 40% or higher is always hit.. don't learn anything here though.
*/
/*
* -- Altrag
*/
schance = IS_NPC( ch ) ? 100 : ( ch->pcdata->learned[gsn_berserk] * 5 / 2 );
if( IS_AFFECTED( ch, AFF_BERSERK ) && number_percent( ) < schance )
if( ( retcode = one_hit( ch, victim, dt ) ) != rNONE || who_fighting( ch ) != victim )
return retcode;
if( get_eq_char( ch, WEAR_DUAL_WIELD ) )
{
dual_bonus = IS_NPC( ch ) ? ( ch->skill_level[COMBAT_ABILITY] / 10 ) : ( ch->pcdata->learned[gsn_dual_wield] / 10 );
schance = IS_NPC( ch ) ? ch->top_level : ch->pcdata->learned[gsn_dual_wield];
if( number_percent( ) < schance )
{
learn_from_success( ch, gsn_dual_wield );
retcode = one_hit( ch, victim, dt );
if( retcode != rNONE || who_fighting( ch ) != victim )
return retcode;
}
else
learn_from_failure( ch, gsn_dual_wield );
}
else
dual_bonus = 0;
if( ch->move < 10 )
dual_bonus = -20;
/*
* NPC predetermined number of attacks -Thoric
*/
if( IS_NPC( ch ) && ch->numattacks > 0 )
{
for( schance = 0; schance <= ch->numattacks; schance++ )
{
retcode = one_hit( ch, victim, dt );
if( retcode != rNONE || who_fighting( ch ) != victim )
return retcode;
}
return retcode;
}
schance = IS_NPC( ch ) ? ch->top_level : ( int )( ( ch->pcdata->learned[gsn_second_attack] + dual_bonus ) / 1.5 );
if( number_percent( ) < schance )
{
learn_from_success( ch, gsn_second_attack );
retcode = one_hit( ch, victim, dt );
if( retcode != rNONE || who_fighting( ch ) != victim )
return retcode;
}
else
learn_from_failure( ch, gsn_second_attack );
schance = IS_NPC( ch ) ? ch->top_level : ( int )( ( ch->pcdata->learned[gsn_third_attack] + ( dual_bonus * 1.5 ) ) / 2 );
if( number_percent( ) < schance )
{
learn_from_success( ch, gsn_third_attack );
retcode = one_hit( ch, victim, dt );
if( retcode != rNONE || who_fighting( ch ) != victim )
return retcode;
}
else
learn_from_failure( ch, gsn_third_attack );
retcode = rNONE;
schance = IS_NPC( ch ) ? ( int )( ch->top_level / 4 ) : 0;
if( number_percent( ) < schance )
retcode = one_hit( ch, victim, dt );
if( retcode == rNONE )
{
int move;
if( !IS_AFFECTED( ch, AFF_FLYING ) && !IS_AFFECTED( ch, AFF_FLOATING ) )
move = encumbrance( ch, movement_loss[UMIN( SECT_MAX - 1, ch->in_room->sector_type )] );
else
move = encumbrance( ch, 1 );
if( ch->move )
ch->move = UMAX( 0, ch->move - move );
}
return retcode;
}
/*
* Weapon types, haus
*/
int weapon_prof_bonus_check( CHAR_DATA * ch, OBJ_DATA * wield, int *gsn_ptr )
{
int bonus;
bonus = 0;
*gsn_ptr = -1;
if( !IS_NPC( ch ) && wield )
{
switch ( wield->value[3] )
{
default:
*gsn_ptr = -1;
break;
case 3:
*gsn_ptr = gsn_lightsabers;
break;
case 2:
*gsn_ptr = gsn_vibro_blades;
break;
case 4:
*gsn_ptr = gsn_flexible_arms;
break;
case 5:
*gsn_ptr = gsn_talonous_arms;
break;
case 6:
*gsn_ptr = gsn_blasters;
break;
case 8:
*gsn_ptr = gsn_bludgeons;
break;
case 9:
*gsn_ptr = gsn_bowcasters;
break;
case 11:
*gsn_ptr = gsn_force_pikes;
break;
}
if( *gsn_ptr != -1 )
bonus = ( int )( ch->pcdata->learned[*gsn_ptr] );
}
if( IS_NPC( ch ) && wield )
bonus = get_trust( ch );
return bonus;
}
/*
* Calculate the tohit bonus on the object and return RIS values.
* -- Altrag
*/
int obj_hitroll( OBJ_DATA * obj )
{
int tohit = 0;
AFFECT_DATA *paf;
for( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
if( paf->location == APPLY_HITROLL )
tohit += paf->modifier;
for( paf = obj->first_affect; paf; paf = paf->next )
if( paf->location == APPLY_HITROLL )
tohit += paf->modifier;
return tohit;
}
/*
* Offensive shield level modifier
*/
short off_shld_lvl( CHAR_DATA * ch, CHAR_DATA * victim )
{
short lvl;
if( !IS_NPC( ch ) ) /* players get much less effect */
{
lvl = UMAX( 1, ( ch->skill_level[FORCE_ABILITY] ) );
if( number_percent( ) + ( victim->skill_level[COMBAT_ABILITY] - lvl ) < 35 )
return lvl;
else
return 0;
}
else
{
lvl = ch->top_level;
if( number_percent( ) + ( victim->skill_level[COMBAT_ABILITY] - lvl ) < 70 )
return lvl;
else
return 0;
}
}
/*
* Hit one guy once.
*/
ch_ret one_hit( CHAR_DATA * ch, CHAR_DATA * victim, int dt )
{
OBJ_DATA *wield;
int victim_ac;
int thac0;
int thac0_00;
int thac0_32;
int plusris;
int dam, x;
int diceroll;
int attacktype, cnt;
int prof_bonus;
int prof_gsn;
ch_ret retcode = rNONE;
int schance;
bool fail;
AFFECT_DATA af;
/*
* Can't beat a dead char!
* Guard against weird room-leavings.
*/
if( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return rVICT_DIED;
/*
* Figure out the weapon doing the damage -Thoric
*/
if( ( wield = get_eq_char( ch, WEAR_DUAL_WIELD ) ) != NULL )
{
if( dual_flip == FALSE )
{
dual_flip = TRUE;
wield = get_eq_char( ch, WEAR_WIELD );
}
else
dual_flip = FALSE;
}
else
wield = get_eq_char( ch, WEAR_WIELD );
prof_bonus = weapon_prof_bonus_check( ch, wield, &prof_gsn );
if( ch->fighting /* make sure fight is already started */
&& dt == TYPE_UNDEFINED && IS_NPC( ch ) && ch->attacks != 0 )
{
cnt = 0;
for( ;; )
{
x = number_range( 0, 6 );
attacktype = 1 << x;
if( IS_SET( ch->attacks, attacktype ) )
break;
if( cnt++ > 16 )
{
attacktype = 0;
break;
}
}
if( attacktype == ATCK_BACKSTAB )
attacktype = 0;
if( wield && number_percent( ) > 25 )
attacktype = 0;
switch ( attacktype )
{
default:
break;
case ATCK_BITE:
do_bite( ch, "" );
retcode = global_retcode;
break;
case ATCK_CLAWS:
do_claw( ch, "" );
retcode = global_retcode;
break;
case ATCK_TAIL:
do_tail( ch, "" );
retcode = global_retcode;
break;
case ATCK_STING:
do_sting( ch, "" );
retcode = global_retcode;
break;
case ATCK_PUNCH:
do_punch( ch, "" );
retcode = global_retcode;
break;
case ATCK_KICK:
do_kick( ch, "" );
retcode = global_retcode;
break;
case ATCK_TRIP:
attacktype = 0;
break;
}
if( attacktype )
return retcode;
}
if( dt == TYPE_UNDEFINED )
{
dt = TYPE_HIT;
if( wield && wield->item_type == ITEM_WEAPON )
dt += wield->value[3];
}
/*
* Calculate to-hit-armor-class-0 versus armor.
*/
thac0_00 = 20;
thac0_32 = 10;
thac0 = interpolate( ch->skill_level[COMBAT_ABILITY], thac0_00, thac0_32 ) - GET_HITROLL( ch );
victim_ac = ( int )( GET_AC( victim ) / 10 );
/*
* if you can't see what's coming...
*/
if( wield && !can_see_obj( victim, wield ) )
victim_ac += 1;
if( !can_see( ch, victim ) )
victim_ac -= 4;
if( ch->race == RACE_DEFEL )
victim_ac += 2;
if( !IS_AWAKE( victim ) )
victim_ac += 5;
/*
* Weapon proficiency bonus
*/
victim_ac += prof_bonus / 20;
/*
* The moment of excitement!
*/
diceroll = number_range( 1, 20 );
if( diceroll == 1 || ( diceroll < 20 && diceroll < thac0 - victim_ac ) )
{
/*
* Miss.
*/
if( prof_gsn != -1 )
learn_from_failure( ch, prof_gsn );
damage( ch, victim, 0, dt );
tail_chain( );
return rNONE;
}
/*
* Hit.
* Calc damage.
*/
if( !wield ) /* dice formula fixed by Thoric */
dam = number_range( ch->barenumdie, ch->baresizedie * ch->barenumdie ) + ch->damplus;
else
dam = number_range( wield->value[1], wield->value[2] );
/*
* Bonuses.
*/
dam += GET_DAMROLL( ch );
if( prof_bonus )
dam *= ( 1 + prof_bonus / 100 );
if( !IS_NPC( ch ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
{
dam += ( int )( dam * ch->pcdata->learned[gsn_enhanced_damage] / 120 );
learn_from_success( ch, gsn_enhanced_damage );
}
if( !IS_AWAKE( victim ) )
dam *= 2;
if( dt == gsn_backstab )
dam *= ( 2 + URANGE( 2, ch->skill_level[HUNTING_ABILITY] - ( victim->skill_level[COMBAT_ABILITY] / 4 ), 30 ) / 8 );
if( dt == gsn_circle )
dam *= ( 2 + URANGE( 2, ch->skill_level[HUNTING_ABILITY] - ( victim->skill_level[COMBAT_ABILITY] / 4 ), 30 ) / 16 );
plusris = 0;
if( wield )
{
if( IS_SET( wield->extra_flags, ITEM_MAGIC ) )
dam = ris_damage( victim, dam, RIS_MAGIC );
else
dam = ris_damage( victim, dam, RIS_NONMAGIC );
/*
* Handle PLUS1 - PLUS6 ris bits vs. weapon hitroll -Thoric
*/
plusris = obj_hitroll( wield );
}
else
dam = ris_damage( victim, dam, RIS_NONMAGIC );
/*
* check for RIS_PLUSx -Thoric
*/
if( dam )
{
int xx, res, imm, sus, mod;
if( plusris )
plusris = RIS_PLUS1 << UMIN( plusris, 7 );
/*
* initialize values to handle a zero plusris
*/
imm = res = -1;
sus = 1;
/*
* find high ris
*/
for( xx = RIS_PLUS1; xx <= RIS_PLUS6; xx <<= 1 )
{
if( IS_SET( victim->immune, xx ) )
imm = xx;
if( IS_SET( victim->resistant, xx ) )
res = xx;
if( IS_SET( victim->susceptible, xx ) )
sus = xx;
}
mod = 10;
if( imm >= plusris )
mod -= 10;
if( res >= plusris )
mod -= 2;
if( sus <= plusris )
mod += 2;
/*
* check if immune
*/
if( mod <= 0 )
dam = -1;
if( mod != 10 )
dam = ( dam * mod ) / 10;
}
/*
* race modifier
*/
if( victim->race == RACE_DUINUOGWUIN )
dam /= 5;
/*
* check to see if weapon is charged
*/
if( dt == ( TYPE_HIT + WEAPON_BLASTER ) && wield && wield->item_type == ITEM_WEAPON )
{
if( wield->value[4] < 1 )
{
act( AT_YELLOW, "$n points their blaster at you but nothing happens.", ch, NULL, victim, TO_VICT );
act( AT_YELLOW, "*CLICK* ... your blaster needs a new ammunition cell!", ch, NULL, victim, TO_CHAR );
if( IS_NPC( ch ) )
{
do_remove( ch, wield->name );
}
return rNONE;
}
else if( wield->blaster_setting == BLASTER_FULL && wield->value[4] >= 5 )
{
dam *= 1.5;
wield->value[4] -= 5;
}
else if( wield->blaster_setting == BLASTER_HIGH && wield->value[4] >= 4 )
{
dam *= 1.25;
wield->value[4] -= 4;
}
else if( wield->blaster_setting == BLASTER_NORMAL && wield->value[4] >= 3 )
{
wield->value[4] -= 3;
}
else if( wield->blaster_setting == BLASTER_STUN && wield->value[4] >= 5 )
{
dam /= 10;
wield->value[4] -= 3;
fail = FALSE;
schance = ris_save( victim, ch->skill_level[COMBAT_ABILITY], RIS_PARALYSIS );
if( schance == 1000 )
fail = TRUE;
else
fail = saves_para_petri( schance, victim );
if( victim->was_stunned > 0 )
{
fail = TRUE;
victim->was_stunned--;
}
schance = 100 - get_curr_con( victim ) - victim->skill_level[COMBAT_ABILITY] / 2;
/*
* harder for player to stun another player
*/
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
schance -= sysdata.stun_plr_vs_plr;
else
schance -= sysdata.stun_regular;
schance = URANGE( 5, schance, 95 );
if( !fail && number_percent( ) < schance )
{
WAIT_STATE( victim, PULSE_VIOLENCE );
act( AT_BLUE, "Blue rings of energy from $N's blaster knock you down leaving you stunned!", victim, NULL, ch,
TO_CHAR );
act( AT_BLUE, "Blue rings of energy from your blaster strike $N, leaving $M stunned!", ch, NULL, victim,
TO_CHAR );
act( AT_BLUE, "Blue rings of energy from $n's blaster hit $N, leaving $M stunned!", ch, NULL, victim,
TO_NOTVICT );
stop_fighting( victim, TRUE );
if( !IS_AFFECTED( victim, AFF_PARALYSIS ) )
{
af.type = gsn_stun;
af.location = APPLY_AC;
af.modifier = 20;
af.duration = 7;
af.bitvector = AFF_PARALYSIS;
affect_to_char( victim, &af );
update_pos( victim );
if( IS_NPC( victim ) )
{
start_hating( victim, ch );
start_hunting( victim, ch );
victim->was_stunned = 10;
}
}
}
else
{
act( AT_BLUE, "Blue rings of energy from $N's blaster hit you but have little effect", victim, NULL, ch,
TO_CHAR );
act( AT_BLUE, "Blue rings of energy from your blaster hit $N, but nothing seems to happen!", ch, NULL, victim,
TO_CHAR );
act( AT_BLUE, "Blue rings of energy from $n's blaster hit $N, but nothing seems to happen!", ch, NULL, victim,
TO_NOTVICT );
}
}
else if( wield->blaster_setting == BLASTER_HALF && wield->value[4] >= 2 )
{
dam *= 0.75;
wield->value[4] -= 2;
}
else
{
dam *= 0.5;
wield->value[4] -= 1;
}
}
else if( dt == ( TYPE_HIT + WEAPON_VIBRO_BLADE ) && wield && wield->item_type == ITEM_WEAPON )
{
if( wield->value[4] < 1 )
{
act( AT_YELLOW, "Your vibro-blade needs recharging ...", ch, NULL, victim, TO_CHAR );
dam /= 3;
}
}
else if( dt == ( TYPE_HIT + WEAPON_FORCE_PIKE ) && wield && wield->item_type == ITEM_WEAPON )
{
if( wield->value[4] < 1 )
{
act( AT_YELLOW, "Your force-pike needs recharging ...", ch, NULL, victim, TO_CHAR );
dam /= 2;
}
else
wield->value[4]--;
}
else if( dt == ( TYPE_HIT + WEAPON_LIGHTSABER ) && wield && wield->item_type == ITEM_WEAPON )
{
if( wield->value[4] < 1 )
{
act( AT_YELLOW, "$n waves a dead hand grip around in the air.", ch, NULL, victim, TO_VICT );
act( AT_YELLOW, "You need to recharge your lightsaber ... it seems to be lacking a blade.", ch, NULL, victim,
TO_CHAR );
if( IS_NPC( ch ) )
{
do_remove( ch, wield->name );
}
return rNONE;
}
}
else if( dt == ( TYPE_HIT + WEAPON_BOWCASTER ) && wield && wield->item_type == ITEM_WEAPON )
{
if( wield->value[4] < 1 )
{
act( AT_YELLOW, "$n points their bowcaster at you but nothing happens.", ch, NULL, victim, TO_VICT );
act( AT_YELLOW, "*CLICK* ... your bowcaster needs a new bolt cartridge!", ch, NULL, victim, TO_CHAR );
if( IS_NPC( ch ) )
{
do_remove( ch, wield->name );
}
return rNONE;
}
else
wield->value[4]--;
}
if( dam <= 0 )
dam = 1;
if( prof_gsn != -1 )
{
if( dam > 0 )
learn_from_success( ch, prof_gsn );
else
learn_from_failure( ch, prof_gsn );
}
/*
* immune to damage
*/
if( dam == -1 )
{
if( dt >= 0 && dt < top_sn )
{
SKILLTYPE *skill = skill_table[dt];
bool found = FALSE;
if( skill->imm_char && skill->imm_char[0] != '\0' )
{
act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
found = TRUE;
}
if( skill->imm_vict && skill->imm_vict[0] != '\0' )
{
act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
found = TRUE;
}
if( skill->imm_room && skill->imm_room[0] != '\0' )
{
act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
found = TRUE;
}
if( found )
return rNONE;
}
dam = 0;
}
if( ( retcode = damage( ch, victim, dam, dt ) ) != rNONE )
return retcode;
if( char_died( ch ) )
return rCHAR_DIED;
if( char_died( victim ) )
return rVICT_DIED;
retcode = rNONE;
if( dam == 0 )
return retcode;
/* weapon spells -Thoric */
if( wield && !IS_SET( victim->immune, RIS_MAGIC ) && !IS_SET( victim->in_room->room_flags, ROOM_NO_MAGIC ) )
{
AFFECT_DATA *aff;
for( aff = wield->pIndexData->first_affect; aff; aff = aff->next )
if( aff->location == APPLY_WEAPONSPELL && IS_VALID_SN( aff->modifier ) && skill_table[aff->modifier]->spell_fun )
retcode = ( *skill_table[aff->modifier]->spell_fun ) ( aff->modifier, ( wield->level + 3 ) / 3, ch, victim );
if( retcode == rSPELL_FAILED ) retcode = rNONE; // Luc, 6/11/2007
if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
return retcode;
for( aff = wield->first_affect; aff; aff = aff->next )
if( aff->location == APPLY_WEAPONSPELL && IS_VALID_SN( aff->modifier ) && skill_table[aff->modifier]->spell_fun )
retcode = ( *skill_table[aff->modifier]->spell_fun ) ( aff->modifier, ( wield->level + 3 ) / 3, ch, victim );
if( retcode == rSPELL_FAILED ) retcode = rNONE; // Luc, 6/11/2007
if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
return retcode;
}
/*
* magic shields that retaliate -Thoric
*/
if( IS_AFFECTED( victim, AFF_FIRESHIELD ) && !IS_AFFECTED( ch, AFF_FIRESHIELD ) )
retcode = spell_fireball( gsn_fireball, off_shld_lvl( victim, ch ), victim, ch );
if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
return retcode;
if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
return retcode;
if( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) && !IS_AFFECTED( ch, AFF_SHOCKSHIELD ) )
retcode = spell_lightning_bolt( gsn_lightning_bolt, off_shld_lvl( victim, ch ), victim, ch );
if( retcode != rNONE || char_died( ch ) || char_died( victim ) )
return retcode;
/*
* folks with blasters move and snipe instead of getting neatin up in one spot.
*/
if( IS_NPC( victim ) )
{
OBJ_DATA *owield;
owield = get_eq_char( victim, WEAR_WIELD );
if( owield != NULL && owield->value[3] == WEAPON_BLASTER && get_cover( victim ) == TRUE )
{
start_hating( victim, ch );
start_hunting( victim, ch );
}
}
tail_chain( );
return retcode;
}
/*
* Calculate damage based on resistances, immunities and suceptibilities
* -Thoric
*/
short ris_damage( CHAR_DATA * ch, short dam, int ris )
{
short modifier;
modifier = 10;
if( IS_SET( ch->immune, ris ) )
modifier -= 10;
if( IS_SET( ch->resistant, ris ) )
modifier -= 2;
if( IS_SET( ch->susceptible, ris ) )
modifier += 2;
if( modifier <= 0 )
return -1;
if( modifier == 10 )
return dam;
return ( dam * modifier ) / 10;
}
/*
* Inflict damage from a hit.
*/
ch_ret damage( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt )
{
short dameq;
bool npcvict;
bool loot;
int xp_gain;
OBJ_DATA *damobj;
ch_ret retcode;
short dampmod;
retcode = rNONE;
if( !ch )
{
bug( "Damage: null ch!", 0 );
return rERROR;
}
if( !victim )
{
bug( "Damage: null victim!", 0 );
return rVICT_DIED;
}
if( victim->position == POS_DEAD )
return rVICT_DIED;
npcvict = IS_NPC( victim );
/*
* Check damage types for RIS -Thoric
*/
if( dam && dt != TYPE_UNDEFINED )
{
if( IS_FIRE( dt ) )
dam = ris_damage( victim, dam, RIS_FIRE );
else if( IS_COLD( dt ) )
dam = ris_damage( victim, dam, RIS_COLD );
else if( IS_ACID( dt ) )
dam = ris_damage( victim, dam, RIS_ACID );
else if( IS_ELECTRICITY( dt ) )
dam = ris_damage( victim, dam, RIS_ELECTRICITY );
else if( IS_ENERGY( dt ) )
dam = ris_damage( victim, dam, RIS_ENERGY );
else if( IS_DRAIN( dt ) )
dam = ris_damage( victim, dam, RIS_DRAIN );
else if( dt == gsn_poison || IS_POISON( dt ) )
dam = ris_damage( victim, dam, RIS_POISON );
else if( dt == ( TYPE_HIT + 7 ) || dt == ( TYPE_HIT + 8 ) )
dam = ris_damage( victim, dam, RIS_BLUNT );
else if( dt == ( TYPE_HIT + 2 ) || dt == ( TYPE_HIT + 11 ) || dt == ( TYPE_HIT + 10 ) )
dam = ris_damage( victim, dam, RIS_PIERCE );
else if( dt == ( TYPE_HIT + 1 ) || dt == ( TYPE_HIT + 3 ) || dt == ( TYPE_HIT + 4 ) || dt == ( TYPE_HIT + 5 ) )
dam = ris_damage( victim, dam, RIS_SLASH );
if( dam == -1 )
{
if( dt >= 0 && dt < top_sn )
{
bool found = FALSE;
SKILLTYPE *skill = skill_table[dt];
if( skill->imm_char && skill->imm_char[0] != '\0' )
{
act( AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR );
found = TRUE;
}
if( skill->imm_vict && skill->imm_vict[0] != '\0' )
{
act( AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT );
found = TRUE;
}
if( skill->imm_room && skill->imm_room[0] != '\0' )
{
act( AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT );
found = TRUE;
}
if( found )
return rNONE;
}
dam = 0;
}
}
if( dam && npcvict && ch != victim )
{
if( !IS_SET( victim->act, ACT_SENTINEL ) )
{
if( victim->hunting )
{
if( victim->hunting->who != ch )
{
STRFREE( victim->hunting->name );
victim->hunting->name = QUICKLINK( ch->name );
victim->hunting->who = ch;
}
}
else
start_hunting( victim, ch );
}
if( victim->hating )
{
if( victim->hating->who != ch )
{
STRFREE( victim->hating->name );
victim->hating->name = QUICKLINK( ch->name );
victim->hating->who = ch;
}
}
else
start_hating( victim, ch );
}
if( victim != ch )
{
/*
* Certain attacks are forbidden.
* Most other attacks are returned.
*/
if( is_safe( ch, victim ) )
return rNONE;
if( victim->position > POS_STUNNED )
{
if( !victim->fighting )
set_fighting( victim, ch );
if( victim->fighting )
victim->position = POS_FIGHTING;
}
if( victim->position > POS_STUNNED )
{
if( !ch->fighting )
set_fighting( ch, victim );
/*
* If victim is charmed, ch might attack victim's master.
*/
if( IS_NPC( ch )
&& npcvict
&& IS_AFFECTED( victim, AFF_CHARM )
&& victim->master && victim->master->in_room == ch->in_room && number_bits( 3 ) == 0 )
{
stop_fighting( ch, FALSE );
retcode = multi_hit( ch, victim->master, TYPE_UNDEFINED );
return retcode;
}
}
/*
* More charm stuff.
*/
if( victim->master == ch )
stop_follower( victim );
/*
* Inviso attacks ... not.
*/
if( IS_AFFECTED( ch, AFF_INVISIBLE ) && ch->race != RACE_DEFEL )
{
affect_strip( ch, gsn_invis );
affect_strip( ch, gsn_mass_invis );
REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
act( AT_MAGIC, "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
}
/*
* Take away Hide
*/
if( IS_AFFECTED( ch, AFF_HIDE ) )
REMOVE_BIT( ch->affected_by, AFF_HIDE );
/*
* Damage modifiers.
*/
if( IS_AFFECTED( victim, AFF_SANCTUARY ) )
dam /= 2;
if( IS_AFFECTED( victim, AFF_PROTECT ) && IS_EVIL( ch ) )
dam -= ( int )( dam / 4 );
if( dam < 0 )
dam = 0;
/*
* Check for disarm, trip, parry, and dodge.
*/
if( dt >= TYPE_HIT )
{
if( IS_NPC( ch ) && IS_SET( ch->attacks, DFND_DISARM ) && number_percent( ) < ch->skill_level[COMBAT_ABILITY] / 2 )
disarm( ch, victim );
if( IS_NPC( ch ) && IS_SET( ch->attacks, ATCK_TRIP ) && number_percent( ) < ch->skill_level[COMBAT_ABILITY] )
trip( ch, victim );
if( check_parry( ch, victim ) )
return rNONE;
if( check_dodge( ch, victim ) )
return rNONE;
}
/*
* Check control panel settings and modify damage
*/
if( IS_NPC( ch ) )
{
if( npcvict )
dampmod = sysdata.dam_mob_vs_mob;
else
dampmod = sysdata.dam_mob_vs_plr;
}
else
{
if( npcvict )
dampmod = sysdata.dam_plr_vs_mob;
else
dampmod = sysdata.dam_plr_vs_plr;
}
if( dampmod > 0 )
dam = ( dam * dampmod ) / 100;
}
/*
* Code to handle equipment getting damaged, and also support -Thoric
* bonuses/penalties for having or not having equipment where hit
*/
if( dam > 10 && dt != TYPE_UNDEFINED )
{
/*
* get a random body eq part
*/
dameq = number_range( WEAR_LIGHT, WEAR_EYES );
damobj = get_eq_char( victim, dameq );
if( damobj )
{
if( dam > get_obj_resistance( damobj ) )
{
set_cur_obj( damobj );
damage_obj( damobj );
}
dam -= 5; /* add a bonus for having something to block the blow */
}
else
dam += 5; /* add penalty for bare skin! */
}
if( ch != victim )
dam_message( ch, victim, dam, dt );
/*
* Hurt the victim.
* Inform the victim of his new state.
*/
victim->hit -= dam;
/*
* Get experience based on % of damage done -Thoric
*/
if( dam && ch != victim && !IS_NPC( ch ) && ch->fighting && ch->fighting->xp )
{
xp_gain = ( int )( xp_compute( ch, victim ) * 0.1 * dam ) / victim->max_hit;
gain_exp( ch, xp_gain, COMBAT_ABILITY );
}
if( !IS_NPC( victim ) && victim->top_level >= LEVEL_IMMORTAL && victim->hit < 1 )
victim->hit = 1;
/*
* Make sure newbies dont die
*/
if( !IS_NPC( victim ) && NOT_AUTHED( victim ) && victim->hit < 1 )
victim->hit = 1;
if( dam > 0 && dt > TYPE_HIT
&& !IS_AFFECTED( victim, AFF_POISON )
&& is_wielding_poisoned( ch )
&& !IS_SET( victim->immune, RIS_POISON ) && !saves_poison_death( ch->skill_level[COMBAT_ABILITY], victim ) )
{
AFFECT_DATA af;
af.type = gsn_poison;
af.duration = 20;
af.location = APPLY_STR;
af.modifier = -2;
af.bitvector = AFF_POISON;
affect_join( victim, &af );
victim->mental_state = URANGE( 20, victim->mental_state + 2, 100 );
}
if( !npcvict && get_trust( victim ) >= LEVEL_IMMORTAL && get_trust( ch ) >= LEVEL_IMMORTAL && victim->hit < 1 )
victim->hit = 1;
update_pos( victim );
switch ( victim->position )
{
case POS_MORTAL:
act( AT_DYING, "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM );
send_to_char( "&RYou are mortally wounded, and will die soon, if not aided.", victim );
break;
case POS_INCAP:
act( AT_DYING, "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM );
send_to_char( "&RYou are incapacitated and will slowly die, if not aided.", victim );
break;
case POS_STUNNED:
if( !IS_AFFECTED( victim, AFF_PARALYSIS ) )
{
act( AT_ACTION, "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM );
send_to_char( "&RYou are stunned, but will probably recover.", victim );
}
break;
case POS_DEAD:
if( dt >= 0 && dt < top_sn )
{
SKILLTYPE *skill = skill_table[dt];
if( skill->die_char && skill->die_char[0] != '\0' )
act( AT_DEAD, skill->die_char, ch, NULL, victim, TO_CHAR );
if( skill->die_vict && skill->die_vict[0] != '\0' )
act( AT_DEAD, skill->die_vict, ch, NULL, victim, TO_VICT );
if( skill->die_room && skill->die_room[0] != '\0' )
act( AT_DEAD, skill->die_room, ch, NULL, victim, TO_NOTVICT );
}
if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOKILL ) )
act( AT_YELLOW, "$n flees for $s life ... barely escaping certain death!", victim, 0, 0, TO_ROOM );
else if( IS_NPC( victim ) && IS_SET( victim->act, ACT_DROID ) )
act( AT_DEAD, "$n EXPLODES into many small pieces!", victim, 0, 0, TO_ROOM );
else
act( AT_DEAD, "$n is DEAD!", victim, 0, 0, TO_ROOM );
send_to_char( "&WYou have been KILLED!\r\n", victim );
break;
default:
if( dam > victim->max_hit / 4 )
{
act( AT_HURT, "That really did HURT!", victim, 0, 0, TO_CHAR );
if( number_bits( 3 ) == 0 )
worsen_mental_state( victim, 1 );
}
if( victim->hit < victim->max_hit / 4 )
{
act( AT_DANGER, "You wish that your wounds would stop BLEEDING so much!", victim, 0, 0, TO_CHAR );
if( number_bits( 2 ) == 0 )
worsen_mental_state( victim, 1 );
}
break;
}
/*
* Sleep spells and extremely wounded folks.
*/
if( !IS_AWAKE( victim ) /* lets make NPC's not slaughter PC's */
&& !IS_AFFECTED( victim, AFF_PARALYSIS ) )
{
if( victim->fighting && victim->fighting->who->hunting && victim->fighting->who->hunting->who == victim )
stop_hunting( victim->fighting->who );
if( victim->fighting && victim->fighting->who->hating && victim->fighting->who->hating->who == victim )
stop_hating( victim->fighting->who );
stop_fighting( victim, TRUE );
}
if( victim->hit <= 0 && !IS_NPC( victim ) )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
int cnt = 0;
REMOVE_BIT( victim->act, PLR_ATTACKER );
stop_fighting( victim, TRUE );
if( ( obj = get_eq_char( victim, WEAR_DUAL_WIELD ) ) != NULL )
unequip_char( victim, obj );
if( ( obj = get_eq_char( victim, WEAR_WIELD ) ) != NULL )
unequip_char( victim, obj );
if( ( obj = get_eq_char( victim, WEAR_HOLD ) ) != NULL )
unequip_char( victim, obj );
if( ( obj = get_eq_char( victim, WEAR_MISSILE_WIELD ) ) != NULL )
unequip_char( victim, obj );
if( ( obj = get_eq_char( victim, WEAR_LIGHT ) ) != NULL )
unequip_char( victim, obj );
for( obj = victim->first_carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( obj->wear_loc == WEAR_NONE )
{
if( obj->pIndexData->progtypes & DROP_PROG && obj->count > 1 )
{
++cnt;
separate_obj( obj );
obj_from_char( obj );
if( !obj_next )
obj_next = victim->first_carrying;
}
else
{
cnt += obj->count;
obj_from_char( obj );
}
act( AT_ACTION, "$n drops $p.", victim, obj, NULL, TO_ROOM );
act( AT_ACTION, "You drop $p.", victim, obj, NULL, TO_CHAR );
obj = obj_to_room( obj, victim->in_room );
}
}
if( IS_NPC( ch ) && !IS_NPC( victim ) )
{
long lose_exp;
lose_exp = UMAX( ( victim->experience[COMBAT_ABILITY] - exp_level( victim->skill_level[COMBAT_ABILITY] ) ), 0 );
ch_printf( victim, "You lose %ld experience.\r\n", lose_exp );
victim->experience[COMBAT_ABILITY] -= lose_exp;
}
add_timer( victim, TIMER_RECENTFIGHT, 100, NULL, 0 );
}
/*
* Payoff for killing things.
*/
if( victim->position == POS_DEAD )
{
CHAR_DATA *gch;
OBJ_DATA *new_corpse;
group_gain( ch, victim );
if( !npcvict )
{
sprintf( log_buf, "%s killed by %s at %d",
victim->name, ( IS_NPC( ch ) ? ch->short_descr : ch->name ), victim->in_room->vnum );
log_string( log_buf );
to_channel( log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL );
}
else if( !IS_NPC( ch ) && IS_NPC( victim ) ) /* keep track of mob vnum killed */
{
add_kill( ch, victim );
/*
* Add to kill tracker for grouped chars, as well. -Halcyon
*/
for( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
if( is_same_group( gch, ch ) && !IS_NPC( gch ) && gch != ch )
add_kill( gch, victim );
}
check_killer( ch, victim );
if( !IS_NPC( victim ) || !IS_SET( victim->act, ACT_NOKILL ) )
loot = legal_loot( ch, victim );
else
loot = FALSE;
set_cur_char( victim );
new_corpse = raw_kill( ch, victim );
victim = NULL;
if( !IS_NPC( ch ) && loot && new_corpse && new_corpse->item_type == ITEM_CORPSE_NPC
&& new_corpse->in_room == ch->in_room && can_see_obj( ch, new_corpse ) && ch->position > POS_SLEEPING )
{
/*
* Autogold by Scryn 8/12
*/
if( IS_SET( ch->act, PLR_AUTOGOLD ) && !loot_coins_from_corpse( ch, new_corpse ) )
return rBOTH_DIED;
if( new_corpse && !obj_extracted(new_corpse) && new_corpse->in_room == ch->in_room
&& ch->position > POS_SLEEPING && can_see_obj( ch, new_corpse ) )
{
if( IS_SET( ch->act, PLR_AUTOLOOT ) )
do_get( ch, "all corpse" );
else
do_look( ch, "in corpse" );
if( !char_died(ch) && IS_SET( ch->act, PLR_AUTOSAC ) && !obj_extracted(new_corpse)
&& new_corpse->in_room == ch->in_room && ch->position > POS_SLEEPING
&& can_see_obj( ch, new_corpse ) )
do_sacrifice( ch, "corpse" );
}
}
if( IS_SET( sysdata.save_flags, SV_KILL ) )
save_char_obj( ch );
return rVICT_DIED;
}
if( victim == ch )
return rNONE;
/*
* Take care of link dead people.
*/
if( !npcvict && !victim->desc && !victim->switched )
{
if( number_range( 0, victim->wait ) == 0 )
{
do_flee( victim, "" );
do_flee( victim, "" );
do_flee( victim, "" );
do_flee( victim, "" );
do_flee( victim, "" );
do_hail( victim, "" );
do_quit( victim, "" );
return rNONE;
}
}
/*
* Wimp out?
*/
if( npcvict && dam > 0 )
{
if( ( IS_SET( victim->act, ACT_WIMPY ) && number_bits( 1 ) == 0
&& victim->hit < victim->max_hit / 2 )
|| ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master && victim->master->in_room != victim->in_room ) )
{
start_fearing( victim, ch );
stop_hunting( victim );
do_flee( victim, "" );
}
}
if( !npcvict && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait == 0 )
do_flee( victim, "" );
else if( !npcvict && IS_SET( victim->act, PLR_FLEE ) )
do_flee( victim, "" );
tail_chain( );
return rNONE;
}
bool is_safe( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( !victim )
return FALSE;
/*
* Thx Josh!
*/
if( who_fighting( ch ) == ch )
return FALSE;
if( IS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "You'll have to do that elswhere.\r\n", ch );
return TRUE;
}
if( get_trust( ch ) > LEVEL_HERO )
return FALSE;
if( IS_NPC( ch ) || IS_NPC( victim ) )
return FALSE;
return FALSE;
}
/* checks is_safe but without the output
cuts out imms and safe rooms as well
for info only */
bool is_safe_nm( CHAR_DATA * ch, CHAR_DATA * victim )
{
return FALSE;
}
/*
* just verify that a corpse looting is legal
*/
bool legal_loot( CHAR_DATA * ch, CHAR_DATA * victim )
{
/*
* pc's can now loot .. why not .. death is pretty final
*/
if( !IS_NPC( ch ) )
return TRUE;
/*
* non-charmed mobs can loot anything
*/
if( IS_NPC( ch ) && !ch->master )
return TRUE;
return FALSE;
}
/*
see if an attack justifies a KILLER flag --- edited so that none do but can't
murder a no pk person. --- edited again for planetary wanted flags -- well will be soon :p
*/
void check_killer( CHAR_DATA * ch, CHAR_DATA * victim )
{
int x;
/*
* Charm-o-rama.
*/
if( IS_SET( ch->affected_by, AFF_CHARM ) )
{
if( !ch->master )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "Check_killer: %s bad AFF_CHARM", IS_NPC( ch ) ? ch->short_descr : ch->name );
bug( buf, 0 );
affect_strip( ch, gsn_charm_person );
REMOVE_BIT( ch->affected_by, AFF_CHARM );
return;
}
/*
* stop_follower( ch );
*/
if( ch->master )
check_killer( ch->master, victim );
}
if( IS_NPC( victim ) )
{
if( !IS_NPC( ch ) )
{
for( x = 0; x < 32; x++ )
{
if( IS_SET( victim->vip_flags, 1 << x ) )
{
SET_BIT( ch->pcdata->wanted_flags, 1 << x );
ch_printf( ch, "&YYou are now wanted on %s.&w\r\n", planet_flags[x], victim->short_descr );
}
}
if( ch->pcdata->clan )
ch->pcdata->clan->mkills++;
ch->pcdata->mkills++;
ch->in_room->area->mkills++;
}
return;
}
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
{
if( ch->pcdata->clan )
ch->pcdata->clan->pkills++;
ch->pcdata->pkills++;
update_pos( victim );
if( victim->pcdata->clan )
victim->pcdata->clan->pdeaths++;
}
if( IS_NPC( ch ) )
if( !IS_NPC( victim ) )
victim->in_room->area->mdeaths++;
return;
}
/*
* Set position of a victim.
*/
void update_pos( CHAR_DATA * victim )
{
if( !victim )
{
bug( "update_pos: null victim", 0 );
return;
}
if( victim->hit > 0 )
{
if( victim->position <= POS_STUNNED )
victim->position = POS_STANDING;
if( IS_AFFECTED( victim, AFF_PARALYSIS ) )
victim->position = POS_STUNNED;
return;
}
if( IS_NPC( victim ) || victim->hit <= -500 )
{
if( victim->mount )
{
act( AT_ACTION, "$n falls from $N.", victim, NULL, victim->mount, TO_ROOM );
REMOVE_BIT( victim->mount->act, ACT_MOUNTED );
victim->mount = NULL;
}
victim->position = POS_DEAD;
return;
}
if( victim->hit <= -400 )
victim->position = POS_MORTAL;
else if( victim->hit <= -200 )
victim->position = POS_INCAP;
else
victim->position = POS_STUNNED;
if( victim->position > POS_STUNNED && IS_AFFECTED( victim, AFF_PARALYSIS ) )
victim->position = POS_STUNNED;
if( victim->mount )
{
act( AT_ACTION, "$n falls unconscious from $N.", victim, NULL, victim->mount, TO_ROOM );
REMOVE_BIT( victim->mount->act, ACT_MOUNTED );
victim->mount = NULL;
}
return;
}
/*
* Start fights.
*/
void set_fighting( CHAR_DATA * ch, CHAR_DATA * victim )
{
FIGHT_DATA *fight;
if( ch->fighting )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "Set_fighting: %s -> %s (already fighting %s)", ch->name, victim->name, ch->fighting->who->name );
bug( buf, 0 );
return;
}
if( IS_AFFECTED( ch, AFF_SLEEP ) )
affect_strip( ch, gsn_sleep );
/*
* Limit attackers -Thoric
*/
if( victim->num_fighting > max_fight( victim ) )
{
send_to_char( "There are too many people fighting for you to join in.\r\n", ch );
return;
}
CREATE( fight, FIGHT_DATA, 1 );
fight->who = victim;
fight->xp = ( int )xp_compute( ch, victim );
fight->align = align_compute( ch, victim );
if( !IS_NPC( ch ) && IS_NPC( victim ) )
fight->timeskilled = times_killed( ch, victim );
ch->num_fighting = 1;
ch->fighting = fight;
ch->position = POS_FIGHTING;
victim->num_fighting++;
if( victim->switched && IS_AFFECTED( victim->switched, AFF_POSSESS ) )
{
send_to_char( "You are disturbed!\r\n", victim->switched );
do_return( victim->switched, "" );
}
return;
}
CHAR_DATA *who_fighting( CHAR_DATA * ch )
{
if( !ch )
{
bug( "who_fighting: null ch", 0 );
return NULL;
}
if( !ch->fighting )
return NULL;
return ch->fighting->who;
}
void free_fight( CHAR_DATA * ch )
{
if( !ch )
{
bug( "Free_fight: null ch!", 0 );
return;
}
if( ch->fighting )
{
if( !char_died( ch->fighting->who ) )
--ch->fighting->who->num_fighting;
DISPOSE( ch->fighting );
}
ch->fighting = NULL;
if( ch->mount )
ch->position = POS_MOUNTED;
else
ch->position = POS_STANDING;
/*
* Berserk wears off after combat. -- Altrag
*/
if( IS_AFFECTED( ch, AFF_BERSERK ) )
{
affect_strip( ch, gsn_berserk );
set_char_color( AT_WEAROFF, ch );
send_to_char( skill_table[gsn_berserk]->msg_off, ch );
send_to_char( "\r\n", ch );
}
return;
}
/*
* Stop fights.
*/
void stop_fighting( CHAR_DATA * ch, bool fBoth )
{
CHAR_DATA *fch;
free_fight( ch );
update_pos( ch );
if( !fBoth ) /* major short cut here by Thoric */
return;
for( fch = first_char; fch; fch = fch->next )
{
if( who_fighting( fch ) == ch )
{
free_fight( fch );
update_pos( fch );
}
}
return;
}
void death_cry( CHAR_DATA * ch )
{
return;
}
OBJ_DATA *raw_kill( CHAR_DATA * ch, CHAR_DATA * victim )
{
CHAR_DATA *victmp;
OBJ_DATA *corpse_to_return;
OBJ_DATA *obj, *obj_next;
SHIP_DATA *ship;
char buf[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char arg[MAX_STRING_LENGTH];
if( !victim )
{
bug( "%s: null victim!", __FUNCTION__ );
return NULL;
}
strcpy( arg, victim->name );
stop_fighting( victim, TRUE );
if( ch && !IS_NPC( ch ) && !IS_NPC( victim ) )
claim_disintigration( ch, victim );
/* Take care of polymorphed chars */
if( IS_NPC( victim ) && IS_SET( victim->act, ACT_POLYMORPHED ) )
{
char_from_room( victim->desc->original );
char_to_room( victim->desc->original, victim->in_room );
victmp = victim->desc->original;
do_revert( victim, "" );
return raw_kill( ch, victmp );
}
if( victim->in_room && IS_NPC( victim ) && victim->vip_flags != 0 && victim->in_room->area
&& victim->in_room->area->planet )
{
victim->in_room->area->planet->population--;
victim->in_room->area->planet->population = UMAX( victim->in_room->area->planet->population, 0 );
victim->in_room->area->planet->pop_support -= ( float )( 1 + 1 / ( victim->in_room->area->planet->population + 1 ) );
if( victim->in_room->area->planet->pop_support < -100 )
victim->in_room->area->planet->pop_support = -100;
}
if( !IS_NPC( victim ) || !IS_SET( victim->act, ACT_NOKILL ) )
mprog_death_trigger( ch, victim );
if( char_died( victim ) )
return NULL;
if( !IS_NPC( victim ) || !IS_SET( victim->act, ACT_NOKILL ) )
rprog_death_trigger( ch, victim );
if( char_died( victim ) )
return NULL;
if( !IS_NPC( victim ) || ( !IS_SET( victim->act, ACT_NOKILL ) && !IS_SET( victim->act, ACT_NOCORPSE ) ) )
corpse_to_return = make_corpse( victim, ch );
else
{
for( obj = victim->last_carrying; obj; obj = obj_next )
{
obj_next = obj->prev_content;
obj_from_char( obj );
extract_obj( obj );
}
}
if( IS_NPC( victim ) )
{
victim->pIndexData->killed++;
extract_char( victim, TRUE );
victim = NULL;
return corpse_to_return;
}
set_char_color( AT_DIEMSG, victim );
do_help( victim, "_DIEMSG_" );
/* swreality chnages begin here */
for( ship = first_ship; ship; ship = ship->next )
{
if( !str_cmp( ship->owner, victim->name ) )
{
STRFREE( ship->owner );
ship->owner = STRALLOC( "" );
STRFREE( ship->pilot );
ship->pilot = STRALLOC( "" );
STRFREE( ship->copilot );
ship->copilot = STRALLOC( "" );
save_ship( ship );
}
}
if( victim->plr_home )
{
ROOM_INDEX_DATA *room = victim->plr_home;
STRFREE( room->name );
room->name = STRALLOC( "An Empty Apartment" );
REMOVE_BIT( room->room_flags, ROOM_PLR_HOME );
SET_BIT( room->room_flags, ROOM_EMPTY_HOME );
fold_area( room->area, room->area->filename, FALSE );
}
if( victim->pcdata && victim->pcdata->clan )
{
if( !str_cmp( victim->name, victim->pcdata->clan->leader ) )
{
STRFREE( victim->pcdata->clan->leader );
if( victim->pcdata->clan->number1 )
{
victim->pcdata->clan->leader = STRALLOC( victim->pcdata->clan->number1 );
STRFREE( victim->pcdata->clan->number1 );
victim->pcdata->clan->number1 = STRALLOC( "" );
}
else if( victim->pcdata->clan->number2 )
{
victim->pcdata->clan->leader = STRALLOC( victim->pcdata->clan->number2 );
STRFREE( victim->pcdata->clan->number2 );
victim->pcdata->clan->number2 = STRALLOC( "" );
}
else
victim->pcdata->clan->leader = STRALLOC( "" );
}
if( !str_cmp( victim->name, victim->pcdata->clan->number1 ) )
{
STRFREE( victim->pcdata->clan->number1 );
if( victim->pcdata->clan->number2 )
{
victim->pcdata->clan->number1 = STRALLOC( victim->pcdata->clan->number2 );
STRFREE( victim->pcdata->clan->number2 );
victim->pcdata->clan->number2 = STRALLOC( "" );
}
else
victim->pcdata->clan->number1 = STRALLOC( "" );
}
if( !str_cmp( victim->name, victim->pcdata->clan->number2 ) )
{
STRFREE( victim->pcdata->clan->number2 );
victim->pcdata->clan->number1 = STRALLOC( "" );
}
victim->pcdata->clan->members--;
}
if( !victim )
{
DESCRIPTOR_DATA *d;
/*
* Make sure they aren't halfway logged in.
*/
for( d = first_descriptor; d; d = d->next )
if( ( victim = d->character ) && !IS_NPC( victim ) )
break;
if( d )
close_socket( d, TRUE );
}
else
{
int x, y;
quitting_char = victim;
save_char_obj( victim );
saving_char = NULL;
extract_char( victim, TRUE );
for( x = 0; x < MAX_WEAR; x++ )
for( y = 0; y < MAX_LAYERS; y++ )
save_equipment[x][y] = NULL;
}
sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower( arg[0] ), capitalize( arg ) );
sprintf( buf2, "%s%c/%s", BACKUP_DIR, tolower( arg[0] ), capitalize( arg ) );
rename( buf, buf2 );
sprintf( buf, "%s%c/%s.clone", PLAYER_DIR, tolower( arg[0] ), capitalize( arg ) );
sprintf( buf2, "%s%c/%s", PLAYER_DIR, tolower( arg[0] ), capitalize( arg ) );
rename( buf, buf2 );
return corpse_to_return;
}
void group_gain( CHAR_DATA * ch, CHAR_DATA * victim )
{
char buf[MAX_STRING_LENGTH];
CHAR_DATA *gch, *gch_next;
CHAR_DATA *lch;
int xp;
int members;
/*
* Monsters don't get kill xp's or alignment changes.
* Dying of mortal wounds or poison doesn't give xp to anyone!
*/
if( IS_NPC( ch ) || victim == ch )
return;
members = 0;
for( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
{
if( is_same_group( gch, ch ) )
members++;
}
if( members == 0 )
{
bug( "Group_gain: members.", members );
members = 1;
}
lch = ch->leader ? ch->leader : ch;
for( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
gch_next = gch->next_in_room;
if( !is_same_group( gch, ch ) )
continue;
xp = ( int )( xp_compute( gch, victim ) / members );
gch->alignment = align_compute( gch, victim );
if( !IS_NPC( gch ) && IS_NPC( victim ) && gch->pcdata && gch->pcdata->clan
&& !str_cmp( gch->pcdata->clan->name, victim->mob_clan ) )
{
xp = 0;
sprintf( buf, "You receive no experience for killing your organizations resources.\r\n" );
send_to_char( buf, gch );
}
else
{
sprintf( buf, "You receive %d combat experience.\r\n", xp );
send_to_char( buf, gch );
}
gain_exp( gch, xp, COMBAT_ABILITY );
if( lch == gch && members > 1 )
{
xp =
URANGE( members, xp * members,
( exp_level( gch->skill_level[LEADERSHIP_ABILITY] + 1 ) -
exp_level( gch->skill_level[LEADERSHIP_ABILITY] ) / 10 ) );
sprintf( buf, "You get %d leadership experience for leading your group to victory.\r\n", xp );
send_to_char( buf, gch );
gain_exp( gch, xp, LEADERSHIP_ABILITY );
}
for( obj = ch->first_carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( obj->wear_loc == WEAR_NONE )
continue;
if( ( IS_OBJ_STAT( obj, ITEM_ANTI_EVIL ) && IS_EVIL( gch ) ) ||
( IS_OBJ_STAT( obj, ITEM_ANTI_GOOD ) && IS_GOOD( gch ) ) ||
( IS_OBJ_STAT( obj, ITEM_ANTI_NEUTRAL ) && IS_NEUTRAL( gch ) ) )
{
act( AT_MAGIC, "You are zapped by $p.", gch, obj, NULL, TO_CHAR );
act( AT_MAGIC, "$n is zapped by $p.", gch, obj, NULL, TO_ROOM );
obj_from_char( obj );
obj = obj_to_room( obj, gch->in_room );
oprog_zap_trigger( gch, obj ); /* mudprogs */
if( char_died( gch ) )
break;
}
}
}
return;
}
int align_compute( CHAR_DATA * gch, CHAR_DATA * victim )
{
/* never cared much for this system
int align, newalign;
align = gch->alignment - victim->alignment;
if ( align > 500 )
newalign = UMIN( gch->alignment + (align-500)/4, 1000 );
else
if ( align < -500 )
newalign = UMAX( gch->alignment + (align+500)/4, -1000 );
else
newalign = gch->alignment - (int) (gch->alignment / 4);
return newalign;
make it simple instead */
return URANGE( -1000, ( int )( gch->alignment - victim->alignment / 5 ), 1000 );
}
/*
* Calculate how much XP gch should gain for killing victim
* Lots of redesigning for new exp system by Thoric
*/
int xp_compute( CHAR_DATA * gch, CHAR_DATA * victim )
{
int align;
int xp;
xp = ( get_exp_worth( victim )
* URANGE( 1, ( victim->skill_level[COMBAT_ABILITY] - gch->skill_level[COMBAT_ABILITY] ) + 10, 20 ) ) / 10;
align = gch->alignment - victim->alignment;
/*
* bonus for attacking opposite alignment
*/
if( align > 990 || align < -990 )
xp = ( xp * 5 ) >> 2;
else
/*
* penalty for good attacking same alignment
*/
if( gch->alignment > 300 && align < 250 )
xp = ( xp * 3 ) >> 2;
xp = number_range( ( xp * 3 ) >> 2, ( xp * 5 ) >> 2 );
/*
* reduce exp for killing the same mob repeatedly -Thoric
*/
if( !IS_NPC( gch ) && IS_NPC( victim ) )
{
int times = times_killed( gch, victim );
if( times >= 5 )
xp = 0;
else if( times )
xp = ( xp * ( 5 - times ) ) / 5;
}
/*
* new xp cap for swreality
*/
return URANGE( 1, xp,
( exp_level( gch->skill_level[COMBAT_ABILITY] + 1 ) - exp_level( gch->skill_level[COMBAT_ABILITY] ) ) );
}
/*
* Revamped by Thoric to be more realistic
*/
void dam_message( CHAR_DATA * ch, CHAR_DATA * victim, int dam, int dt )
{
char buf1[256], buf2[256], buf3[256];
const char *vs;
const char *vp;
const char *attack;
char punct;
int dampc;
struct skill_type *skill = NULL;
bool gcflag = FALSE;
bool gvflag = FALSE;
if( !dam )
dampc = 0;
else
dampc = ( ( dam * 1000 ) / victim->max_hit ) + ( 50 - ( ( victim->hit * 50 ) / victim->max_hit ) );
/*
* 10 * percent
*/
if( dam == 0 )
{
vs = "miss";
vp = "misses";
}
else if( dampc <= 5 )
{
vs = "barely scratch";
vp = "barely scratches";
}
else if( dampc <= 10 )
{
vs = "scratch";
vp = "scratches";
}
else if( dampc <= 20 )
{
vs = "nick";
vp = "nicks";
}
else if( dampc <= 30 )
{
vs = "graze";
vp = "grazes";
}
else if( dampc <= 40 )
{
vs = "bruise";
vp = "bruises";
}
else if( dampc <= 50 )
{
vs = "hit";
vp = "hits";
}
else if( dampc <= 60 )
{
vs = "injure";
vp = "injures";
}
else if( dampc <= 75 )
{
vs = "thrash";
vp = "thrashes";
}
else if( dampc <= 80 )
{
vs = "wound";
vp = "wounds";
}
else if( dampc <= 90 )
{
vs = "maul";
vp = "mauls";
}
else if( dampc <= 125 )
{
vs = "decimate";
vp = "decimates";
}
else if( dampc <= 150 )
{
vs = "devastate";
vp = "devastates";
}
else if( dampc <= 200 )
{
vs = "maim";
vp = "maims";
}
else if( dampc <= 300 )
{
vs = "MUTILATE";
vp = "MUTILATES";
}
else if( dampc <= 400 )
{
vs = "DISEMBOWEL";
vp = "DISEMBOWELS";
}
else if( dampc <= 500 )
{
vs = "MASSACRE";
vp = "MASSACRES";
}
else if( dampc <= 600 )
{
vs = "PULVERIZE";
vp = "PULVERIZES";
}
else if( dampc <= 750 )
{
vs = "EVISCERATE";
vp = "EVISCERATES";
}
else if( dampc <= 990 )
{
vs = "* OBLITERATE *";
vp = "* OBLITERATES *";
}
else
{
vs = "*** ANNIHILATE ***";
vp = "*** ANNIHILATES ***";
}
punct = ( dampc <= 30 ) ? '.' : '!';
if( dam == 0 && ( !IS_NPC( ch ) && ( IS_SET( ch->pcdata->flags, PCFLAG_GAG ) ) ) )
gcflag = TRUE;
if( dam == 0 && ( !IS_NPC( victim ) && ( IS_SET( victim->pcdata->flags, PCFLAG_GAG ) ) ) )
gvflag = TRUE;
if( dt >= 0 && dt < top_sn )
skill = skill_table[dt];
if( dt == ( TYPE_HIT + WEAPON_BLASTER ) )
{
char sound[MAX_STRING_LENGTH];
int vol = number_range( 20, 80 );
sprintf( sound, "!!SOUND(blaster V=%d)", vol );
sound_to_room( ch->in_room, sound );
}
if( dt == TYPE_HIT || dam == 0 )
{
sprintf( buf1, "$n %s $N%c", vp, punct );
sprintf( buf2, "You %s $N%c", vs, punct );
sprintf( buf3, "$n %s you%c", vp, punct );
}
else if( dt > TYPE_HIT && is_wielding_poisoned( ch ) )
{
if( dt < TYPE_HIT + sizeof( attack_table ) / sizeof( attack_table[0] ) )
attack = attack_table[dt - TYPE_HIT];
else
{
bug( "Dam_message: bad dt %d.", dt );
dt = TYPE_HIT;
attack = attack_table[0];
}
sprintf( buf1, "$n's poisoned %s %s $N%c", attack, vp, punct );
sprintf( buf2, "Your poisoned %s %s $N%c", attack, vp, punct );
sprintf( buf3, "$n's poisoned %s %s you%c", attack, vp, punct );
}
else
{
if( skill )
{
attack = skill->noun_damage;
if( dam == 0 )
{
bool found = FALSE;
if( skill->miss_char && skill->miss_char[0] != '\0' )
{
act( AT_HIT, skill->miss_char, ch, NULL, victim, TO_CHAR );
found = TRUE;
}
if( skill->miss_vict && skill->miss_vict[0] != '\0' )
{
act( AT_HITME, skill->miss_vict, ch, NULL, victim, TO_VICT );
found = TRUE;
}
if( skill->miss_room && skill->miss_room[0] != '\0' )
{
act( AT_ACTION, skill->miss_room, ch, NULL, victim, TO_NOTVICT );
found = TRUE;
}
if( found ) /* miss message already sent */
return;
}
else
{
if( skill->hit_char && skill->hit_char[0] != '\0' )
act( AT_HIT, skill->hit_char, ch, NULL, victim, TO_CHAR );
if( skill->hit_vict && skill->hit_vict[0] != '\0' )
act( AT_HITME, skill->hit_vict, ch, NULL, victim, TO_VICT );
if( skill->hit_room && skill->hit_room[0] != '\0' )
act( AT_ACTION, skill->hit_room, ch, NULL, victim, TO_NOTVICT );
}
}
else if( dt >= TYPE_HIT && dt < TYPE_HIT + sizeof( attack_table ) / sizeof( attack_table[0] ) )
attack = attack_table[dt - TYPE_HIT];
else
{
bug( "Dam_message: bad dt %d.", dt );
dt = TYPE_HIT;
attack = attack_table[0];
}
sprintf( buf1, "$n's %s %s $N%c", attack, vp, punct );
sprintf( buf2, "Your %s %s $N%c", attack, vp, punct );
sprintf( buf3, "$n's %s %s you%c", attack, vp, punct );
}
if( ch->skill_level[COMBAT_ABILITY] >= 100 )
sprintf( buf2, "%s You do %d points of damage.", buf2, dam );
act( AT_ACTION, buf1, ch, NULL, victim, TO_NOTVICT );
if( !gcflag )
act( AT_HIT, buf2, ch, NULL, victim, TO_CHAR );
if( !gvflag )
act( AT_HITME, buf3, ch, NULL, victim, TO_VICT );
return;
}
void do_kill( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Kill whom?\r\n", ch );
return;
}
if( ( victim = get_char_room( ch, arg ) ) == NULL )
{
send_to_char( "They aren't here.\r\n", ch );
return;
}
if( !IS_NPC( victim ) )
{
send_to_char( "You must MURDER a player.\r\n", ch );
return;
}
/*
*
else
{
if ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
{
send_to_char( "You must MURDER a charmed creature.\r\n", ch );
return;
}
}
*
*/
if( victim == ch )
{
send_to_char( "You hit yourself. Ouch!\r\n", ch );
multi_hit( ch, ch, TYPE_UNDEFINED );
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!\r\n", ch );
return;
}
if( victim->vip_flags != 0 )
ch->alignment -= 10;
WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
multi_hit( ch, victim, TYPE_UNDEFINED );
return;
}
void do_murde( CHAR_DATA * ch, char *argument )
{
send_to_char( "If you want to MURDER, spell it out.\r\n", ch );
return;
}
void do_murder( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Murder whom?\r\n", ch );
return;
}
if( ( victim = get_char_room( ch, arg ) ) == NULL )
{
send_to_char( "They aren't here.\r\n", ch );
return;
}
if( victim == ch )
{
send_to_char( "Suicide is a mortal sin.\r\n", ch );
return;
}
if( is_safe( ch, victim ) )
return;
if( IS_AFFECTED( ch, AFF_CHARM ) )
{
if( 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!\r\n", ch );
return;
}
if( !IS_NPC( victim ) && IS_SET( ch->act, PLR_NICE ) )
{
send_to_char( "You feel too nice to do that!\r\n", ch );
return;
}
ch->alignment = URANGE( -1000, ch->alignment - 10, 1000 );
WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
multi_hit( ch, victim, TYPE_UNDEFINED );
return;
}
bool in_arena( CHAR_DATA * ch )
{
if( !str_cmp( ch->in_room->area->filename, "arena.are" ) )
return TRUE;
if( ch->in_room->vnum < 29 || ch->in_room->vnum > 43 )
return FALSE;
return TRUE;
}
void do_flee( CHAR_DATA * ch, char *argument )
{
ROOM_INDEX_DATA *was_in;
ROOM_INDEX_DATA *now_in;
char buf[MAX_STRING_LENGTH];
int attempt;
short door;
EXIT_DATA *pexit;
if( !who_fighting( ch ) )
{
if( ch->position == POS_FIGHTING )
{
if( ch->mount )
ch->position = POS_MOUNTED;
else
ch->position = POS_STANDING;
}
send_to_char( "You aren't fighting anyone.\r\n", ch );
return;
}
if( ch->move <= 0 )
{
send_to_char( "You're too exhausted to flee from combat!\r\n", ch );
return;
}
/*
* No fleeing while stunned. - Narn
*/
if( ch->position < POS_FIGHTING )
return;
was_in = ch->in_room;
for( attempt = 0; attempt < 8; attempt++ )
{
door = number_door( );
if( ( pexit = get_exit( was_in, door ) ) == NULL
|| !pexit->to_room
|| ( IS_SET( pexit->exit_info, EX_CLOSED )
&& !IS_AFFECTED( ch, AFF_PASS_DOOR ) )
|| ( IS_NPC( ch ) && IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB ) ) )
continue;
affect_strip( ch, gsn_sneak );
REMOVE_BIT( ch->affected_by, AFF_SNEAK );
if( ch->mount && ch->mount->fighting )
stop_fighting( ch->mount, TRUE );
move_char( ch, pexit, 0 );
if( ( now_in = ch->in_room ) == was_in )
continue;
ch->in_room = was_in;
act( AT_FLEE, "$n runs for cover!", ch, NULL, NULL, TO_ROOM );
ch->in_room = now_in;
act( AT_FLEE, "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "You run for cover!" );
send_to_char( buf, ch );
stop_fighting( ch, TRUE );
return;
}
sprintf( buf, "You attempt to run for cover!" );
send_to_char( buf, ch );
return;
}
bool get_cover( CHAR_DATA * ch )
{
ROOM_INDEX_DATA *was_in;
ROOM_INDEX_DATA *now_in;
int attempt;
short door;
EXIT_DATA *pexit;
if( !who_fighting( ch ) )
return FALSE;
if( ch->position < POS_FIGHTING )
return FALSE;
was_in = ch->in_room;
for( attempt = 0; attempt < 10; attempt++ )
{
door = number_door( );
if( ( pexit = get_exit( was_in, door ) ) == NULL
|| !pexit->to_room
|| ( IS_SET( pexit->exit_info, EX_CLOSED )
&& !IS_AFFECTED( ch, AFF_PASS_DOOR ) )
|| ( IS_NPC( ch ) && IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB ) ) )
continue;
affect_strip( ch, gsn_sneak );
REMOVE_BIT( ch->affected_by, AFF_SNEAK );
if( ch->mount && ch->mount->fighting )
stop_fighting( ch->mount, TRUE );
move_char( ch, pexit, 0 );
if( ( now_in = ch->in_room ) == was_in )
continue;
ch->in_room = was_in;
act( AT_FLEE, "$n sprints for cover!", ch, NULL, NULL, TO_ROOM );
ch->in_room = now_in;
act( AT_FLEE, "$n spins around and takes aim.", ch, NULL, NULL, TO_ROOM );
stop_fighting( ch, TRUE );
return TRUE;
}
return FALSE;
}
void do_sla( CHAR_DATA * ch, char *argument )
{
send_to_char( "If you want to SLAY, spell it out.\r\n", ch );
return;
}
void do_slay( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
argument = one_argument( argument, arg );
one_argument( argument, arg2 );
if( arg[0] == '\0' )
{
send_to_char( "Slay whom?\r\n", ch );
return;
}
if( ( victim = get_char_room( ch, arg ) ) == NULL )
{
send_to_char( "They aren't here.\r\n", ch );
return;
}
if( ch == victim )
{
send_to_char( "Suicide is a mortal sin.\r\n", ch );
return;
}
if( !IS_NPC( victim ) && ( get_trust( victim ) == 103 || get_trust( ch ) < 103 ) )
{
send_to_char( "You failed.\r\n", ch );
return;
}
if( !str_cmp( arg2, "immolate" ) )
{
act( AT_FIRE, "Your fireball turns $N into a blazing inferno.", ch, NULL, victim, TO_CHAR );
act( AT_FIRE, "$n releases a searing fireball in your direction.", ch, NULL, victim, TO_VICT );
act( AT_FIRE, "$n points at $N, who bursts into a flaming inferno.", ch, NULL, victim, TO_NOTVICT );
}
else if( !str_cmp( arg2, "shatter" ) )
{
act( AT_LBLUE, "You freeze $N with a glance and shatter the frozen corpse into tiny shards.", ch, NULL, victim,
TO_CHAR );
act( AT_LBLUE, "$n freezes you with a glance and shatters your frozen body into tiny shards.", ch, NULL, victim,
TO_VICT );
act( AT_LBLUE, "$n freezes $N with a glance and shatters the frozen body into tiny shards.", ch, NULL, victim,
TO_NOTVICT );
}
else if( !str_cmp( arg2, "demon" ) )
{
act( AT_IMMORT, "You gesture, and a slavering demon appears. With a horrible grin, the", ch, NULL, victim, TO_CHAR );
act( AT_IMMORT, "foul creature turns on $N, who screams in panic before being eaten alive.", ch, NULL, victim,
TO_CHAR );
act( AT_IMMORT, "$n gestures, and a slavering demon appears. The foul creature turns on", ch, NULL, victim, TO_VICT );
act( AT_IMMORT, "you with a horrible grin. You scream in panic before being eaten alive.", ch, NULL, victim,
TO_VICT );
act( AT_IMMORT, "$n gestures, and a slavering demon appears. With a horrible grin, the", ch, NULL, victim,
TO_NOTVICT );
act( AT_IMMORT, "foul creature turns on $N, who screams in panic before being eaten alive.", ch, NULL, victim,
TO_NOTVICT );
}
else if( !str_cmp( arg2, "pounce" ) && get_trust( ch ) >= LEVEL_ASCENDANT )
{
act( AT_BLOOD, "Leaping upon $N with bared fangs, you tear open $S throat and toss the corpse to the ground...", ch,
NULL, victim, TO_CHAR );
act( AT_BLOOD,
"In a heartbeat, $n rips $s fangs through your throat! Your blood sprays and pours to the ground as your life ends...",
ch, NULL, victim, TO_VICT );
act( AT_BLOOD,
"Leaping suddenly, $n sinks $s fangs into $N's throat. As blood sprays and gushes to the ground, $n tosses $N's dying body away.",
ch, NULL, victim, TO_NOTVICT );
}
else if( !str_cmp( arg2, "slit" ) && get_trust( ch ) >= LEVEL_ASCENDANT )
{
act( AT_BLOOD, "You calmly slit $N's throat.", ch, NULL, victim, TO_CHAR );
act( AT_BLOOD, "$n reaches out with a clawed finger and calmly slits your throat.", ch, NULL, victim, TO_VICT );
act( AT_BLOOD, "$n calmly slits $N's throat.", ch, NULL, victim, TO_NOTVICT );
}
else
{
act( AT_IMMORT, "You slay $N in cold blood!", ch, NULL, victim, TO_CHAR );
act( AT_IMMORT, "$n slays you in cold blood!", ch, NULL, victim, TO_VICT );
act( AT_IMMORT, "$n slays $N in cold blood!", ch, NULL, victim, TO_NOTVICT );
}
set_cur_char( victim );
raw_kill( ch, victim );
return;
}