#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include "structs.h"
#include "awake.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "interpreter.h"
#include "db.h"
#include "screen.h"
#include "newmagic.h"
#include "constants.h"
#include "config.h"
#include "memory.h"
#include "newmatrix.h"
#include "newmagic.h"
/* Structures */
struct char_data *combat_list = NULL; /* head of l-list of fighting chars */
struct char_data *next_combat_list = NULL;
/* External structures */
extern struct message_list fight_messages[MAX_MESSAGES];
int find_sight(struct char_data *ch);
void damage_door(struct char_data *ch, int room, int dir, int power, int type);
void damage_obj(struct char_data *ch, struct obj_data *obj, int power, int type);
void mount_fire(struct char_data *ch);
/* External procedures */
char *fread_action(FILE * fl, int nr);
char *fread_string(FILE * fl, char *error);
void stop_follower(struct char_data * ch);
ACMD(do_assist);
ACMD(do_flee);
ACMD(do_action);
void docwagon(struct char_data *ch);
void roll_individual_initiative(struct char_data *ch);
void ranged_response(struct char_data *ch, struct char_data *vict);
int find_weapon_range(struct char_data *ch, struct obj_data *weapon);
void weapon_scatter(struct char_data *ch, struct char_data *victim,
struct obj_data *weapon);
void explode(struct char_data *ch, struct obj_data *weapon, int room);
void target_explode(struct char_data *ch, struct obj_data *weapon,
int room, int mode);
void forget(struct char_data * ch, struct char_data * victim);
void remember(struct char_data * ch, struct char_data * victim);
void order_list(bool first,...);
extern int success_test(int number, int target);
extern int resisted_test(int num_for_ch, int tar_for_ch, int num_for_vict,
int tar_for_vict);
extern int modify_target(struct char_data *ch);
extern int skill_web (struct char_data *ch, int skillnumber);
extern bool attempt_reload(struct char_data *mob, int pos);
extern void switch_weapons(struct char_data *mob, int pos);
extern void hunt_victim(struct char_data * ch);
extern void matrix_fight(struct char_data *ch, struct char_data *victim);
extern void check_quest_kill(struct char_data *ch, struct char_data *victim);
extern void check_quest_destroy(struct char_data *ch, struct obj_data *obj);
extern int return_general(int);
extern struct zone_data *zone_table;
extern void perform_tell(struct char_data *, struct char_data *, char *);
extern int can_wield_both(struct char_data *, struct obj_data *, struct obj_data *);
extern void draw_weapon(struct char_data *);
extern void crash_test(struct char_data *ch);
extern int modify_veh(struct veh_data *veh);
extern SPECIAL(shop_keeper);
extern void mob_magic(struct char_data *ch);
/* Weapon attack texts */
struct attack_hit_type attack_hit_text[] =
{
{"hit", "hits", "hit"
}
, /* 0 */
{"sting", "stings", "sting"},
{"whip", "whips", "whip"},
{"slash", "slashes", "slash"},
{"bite", "bites", "bite"},
{"bludgeon", "bludgeons", "bludgeon"}, /* 5 */
{"crush", "crushes", "crush"},
{"pound", "pounds", "pound"},
{"claw", "claws", "claw"},
{"maul", "mauls", "maul"},
{"thrash", "thrashes", "thrash"}, /* 10 */
{"pierce", "pierces", "pierce"},
{"punch", "punches", "punch"},
{"stab", "stabs", "stab"},
{"shock", "shocks", "shock"},
{"shuriken", "shurikens", "shuriken"}, /* 15 */
{"pierce", "pierces", "pierce"},
{"pierce", "pierces", "pierce"},
{"grenade", "grenades", "grenade"},
{"grenade", "grenades", "grenade"},
{"rocket", "rockets", "rocket"}, /* 20 */
{"shoot", "shoots", "shot"},
{"blast", "blasts", "blast"},
{"shoot", "shoots", "shot"},
{"blast", "blasts", "blast"},
{"blast", "blasts", "burst fire"}, /* 25 */
{"blast", "blasts", "blast"},
{"bifurcate", "bifurcates", "BIFURCATION"}
};
void set_attacking(struct char_data *ch, struct char_data *vict, const char *file, int line)
{
//ch->char_specials.fightList.ADD(vict);
//vict->char_specials.defendList.ADD(ch);
}
/* The Fight related routines */
void appear(struct char_data * ch)
{
AFF_FLAGS(ch).RemoveBits(AFF_IMP_INVIS,
AFF_INVISIBLE,
AFF_HIDE, ENDBIT);
if (!IS_SENATOR(ch))
act("$n slowly fades into existence.", FALSE, ch, 0, 0, TO_ROOM);
else
act("You feel a strange presence as $n appears, seemingly from nowhere.",
FALSE, ch, 0, 0, TO_ROOM);
}
void load_messages(void)
{
FILE *fl;
int i, type;
struct message_type *messages;
char chk[128];
if (!(fl = fopen(MESS_FILE, "r"))) {
sprintf(buf2, "Error reading combat message file %s", MESS_FILE);
perror(buf2);
shutdown();
}
for (i = 0; i < MAX_MESSAGES; i++) {
fight_messages[i].a_type = 0;
fight_messages[i].number_of_attacks = 0;
fight_messages[i].msg = 0;
}
fgets(chk, 128, fl);
while (!feof(fl) && (*chk == '\n' || *chk == '*'))
fgets(chk, 128, fl);
while (*chk == 'M') {
fgets(chk, 128, fl);
sscanf(chk, " %d\n", &type);
for (i = 0; (i < MAX_MESSAGES) && (fight_messages[i].a_type != type) &&
(fight_messages[i].a_type); i++)
;
if (i >= MAX_MESSAGES) {
fprintf(stderr, "Too many combat messages. Increase MAX_MESSAGES and recompile.");
shutdown();
}
messages = new message_type;
fight_messages[i].number_of_attacks++;
fight_messages[i].a_type = type;
messages->next = fight_messages[i].msg;
fight_messages[i].msg = messages;
messages->die_msg.attacker_msg = fread_action(fl, i);
messages->die_msg.victim_msg = fread_action(fl, i);
messages->die_msg.room_msg = fread_action(fl, i);
messages->miss_msg.attacker_msg = fread_action(fl, i);
messages->miss_msg.victim_msg = fread_action(fl, i);
messages->miss_msg.room_msg = fread_action(fl, i);
messages->hit_msg.attacker_msg = fread_action(fl, i);
messages->hit_msg.victim_msg = fread_action(fl, i);
messages->hit_msg.room_msg = fread_action(fl, i);
messages->god_msg.attacker_msg = fread_action(fl, i);
messages->god_msg.victim_msg = fread_action(fl, i);
messages->god_msg.room_msg = fread_action(fl, i);
fgets(chk, 128, fl);
while (!feof(fl) && (*chk == '\n' || *chk == '*'))
fgets(chk, 128, fl);
}
fclose(fl);
}
void update_pos(struct char_data * victim)
{
if ((GET_MENTAL(victim) < 100) && (GET_PHYSICAL(victim) >= 100))
{
for (struct obj_data *bio = victim->bioware; bio; bio = bio->next_content)
if (GET_OBJ_VAL(bio, 0) == BIO_PAINEDITOR && GET_OBJ_VAL(bio, 3))
return;
GET_POS(victim) = POS_STUNNED;
GET_INIT_ROLL(victim) = 0;
return;
}
if ((GET_PHYSICAL(victim) >= 100) && (GET_POS(victim) > POS_STUNNED))
return;
else if (GET_PHYSICAL(victim) >= 100)
{
GET_POS(victim) = POS_STANDING;
return;
} else if ((int)(GET_PHYSICAL(victim) / 100) <= -GET_REAL_BOD(victim) + (GET_BIOOVER(victim) > 0 ? GET_BIOOVER(victim) : 0))
GET_POS(victim) = POS_DEAD;
else
GET_POS(victim) = POS_MORTALLYW;
GET_INIT_ROLL(victim) = 0;
}
/* blood blood blood, root */
void increase_blood(int rm)
{
RM_BLOOD(rm) = MIN(RM_BLOOD(rm) + 1, 10);
}
void check_killer(struct char_data * ch, struct char_data * vict)
{
char_data *attacker;
char buf[256];
if (IS_NPC(ch) && (ch->desc == NULL || ch->desc->original == NULL))
return;
if (!IS_NPC(ch))
attacker = ch;
else
attacker = ch->desc->original;
if (!IS_NPC(vict) &&
!PLR_FLAGS(vict).AreAnySet(PLR_KILLER, ENDBIT) &&
!(ROOM_FLAGGED(ch->in_room, ROOM_ARENA) && ROOM_FLAGGED(vict->in_room, ROOM_ARENA)) &&
(!PRF_FLAGGED(attacker, PRF_PKER) || !PRF_FLAGGED(vict, PRF_PKER)) &&
!PLR_FLAGGED(attacker, PLR_KILLER) && attacker != vict && !IS_SENATOR(attacker))
{
PLR_FLAGS(attacker).SetBit(PLR_KILLER);
sprintf(buf, "PC Killer bit set on %s for initiating attack on %s at %s.",
GET_CHAR_NAME(attacker),
GET_CHAR_NAME(vict), world[vict->in_room].name);
mudlog(buf, ch, LOG_MISCLOG, TRUE);
send_to_char("If you want to be a PLAYER KILLER, so be it...\r\n", ch);
}
}
/* start one char fighting another (yes, it is horrible, I know... ) */
void set_fighting(struct char_data * ch, struct char_data * vict, ...)
{
struct follow_type *k;
if (ch == vict)
return;
if (FIGHTING(ch) || FIGHTING_VEH(ch))
return;
ch->next_fighting = combat_list;
combat_list = ch;
roll_individual_initiative(ch);
FIGHTING(ch) = vict;
GET_POS(ch) = POS_FIGHTING;
if (!(AFF_FLAGGED(ch, AFF_MANNING) || PLR_FLAGGED(ch, PLR_REMOTE) || AFF_FLAGGED(ch, AFF_RIG)))
{
if (!(GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0)) &&
!(GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1)))
draw_weapon(ch);
if (GET_EQ(ch, WEAR_WIELD))
if (!IS_GUN(GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 3)) &&
GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 3) != TYPE_ARROW)
AFF_FLAGS(ch).SetBit(AFF_APPROACH);
if (GET_EQ(ch, WEAR_HOLD))
if (!IS_GUN(GET_OBJ_VAL(GET_EQ(ch, WEAR_HOLD), 3)) &&
GET_OBJ_VAL(GET_EQ(ch, WEAR_HOLD), 3) != TYPE_ARROW)
AFF_FLAGS(ch).SetBit(AFF_APPROACH);
if (!GET_EQ(ch, WEAR_WIELD) && !GET_EQ(ch, WEAR_HOLD))
AFF_FLAGS(ch).SetBit(AFF_APPROACH);
}
check_killer(ch, vict);
if (IS_NPC(ch))
strcpy(buf, GET_NAME(ch));
else
strcpy(buf, GET_CHAR_NAME(ch));
if (!ch->in_veh) {
if (ch->followers)
for (k = ch->followers; k; k = k->next)
if (PRF_FLAGGED(k->follower, PRF_ASSIST) && k->follower->in_room == ch->in_room && !k->follower->in_veh &&
!FIGHTING(k->follower) && AWAKE(k->follower))
do_assist(k->follower, buf, 0, 0);
if (ch->master)
{
if (PRF_FLAGGED(ch->master, PRF_ASSIST) && ch->master->in_room == ch->in_room && !ch->master->in_veh &&
!FIGHTING(ch->master) && AWAKE(ch->master))
do_assist(ch->master, buf, 0, 0);
for (k = ch->master->followers; k; k = k->next)
if (PRF_FLAGGED(k->follower, PRF_ASSIST) && k->follower->in_room == ch->in_room && !k->follower->in_veh
&& k->follower != ch && !FIGHTING(k->follower) && AWAKE(k->follower))
do_assist(k->follower, buf, 0, 0);
}
}
}
void set_fighting(struct char_data * ch, struct veh_data * vict)
{
struct follow_type *k;
if (FIGHTING(ch) || FIGHTING_VEH(ch))
return;
ch->next_fighting = combat_list;
combat_list = ch;
roll_individual_initiative(ch);
FIGHTING_VEH(ch) = vict;
GET_POS(ch) = POS_FIGHTING;
if (!(GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0)) &&
!(GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1)))
draw_weapon(ch);
if (IS_NPC(ch))
strcpy(buf, GET_NAME(ch));
else
strcpy(buf, GET_CHAR_NAME(ch));
if (ch->followers)
for (k = ch->followers; k; k = k->next)
if (PRF_FLAGGED(k->follower, PRF_ASSIST) && k->follower->in_room == ch->in_room &&
!FIGHTING(k->follower) && AWAKE(k->follower))
do_assist(k->follower, buf, 0, 0);
if (ch->master)
{
if (PRF_FLAGGED(ch->master, PRF_ASSIST) && ch->master->in_room == ch->in_room &&
!FIGHTING(ch->master) && AWAKE(ch->master))
do_assist(ch->master, buf, 0, 0);
for (k = ch->master->followers; k; k = k->next)
if (PRF_FLAGGED(k->follower, PRF_ASSIST) && k->follower->in_room == ch->in_room
&& k->follower != ch && !FIGHTING(k->follower) && AWAKE(k->follower))
do_assist(k->follower, buf, 0, 0);
}
}
/* remove a char from the list of fighting chars */
void stop_fighting(struct char_data * ch)
{
struct char_data *temp;
if (ch == next_combat_list)
next_combat_list = ch->next_fighting;
if (IS_AFFECTED(ch, AFF_APPROACH))
AFF_FLAGS(ch).RemoveBit(AFF_APPROACH);
REMOVE_FROM_LIST(ch, combat_list, next_fighting);
FIGHTING(ch) = NULL;
FIGHTING_VEH(ch) = NULL;
ch->next_fighting = NULL;
GET_POS(ch) = POS_STANDING;
update_pos(ch);
GET_INIT_ROLL(ch) = 0;
}
void make_corpse(struct char_data * ch)
{
struct obj_data *create_nuyen(int amount);
struct obj_data *create_credstick(struct char_data *ch, int amount);
struct obj_data *corpse, *o, *obj;
struct obj_data *money;
int i, nuyen, credits, corpse_value = 0;
if (PLR_FLAGGED(ch, PLR_NEWBIE))
return;
corpse = create_obj();
corpse->item_number = NOTHING;
corpse->in_room = NOWHERE;
if (IS_NPC(ch))
{
sprintf(buf, "corpse %s", ch->player.physical_text.keywords);
sprintf(buf1, "^rThe corpse of %s is lying here.^n", GET_NAME(ch));
sprintf(buf2, "^rthe corpse of %s^n", GET_NAME(ch));
} else
{
sprintf(buf, "belongings %s", ch->player.physical_text.keywords);
sprintf(buf1, "^rThe belongings of %s are lying here.^n", GET_NAME(ch));
sprintf(buf2, "^rthe belongings of %s^n", GET_NAME(ch));
}
corpse->text.keywords = str_dup(buf);
corpse->text.room_desc = str_dup(buf1);
corpse->text.name = str_dup(buf2);
corpse->text.look_desc = str_dup("What once was living is no longer. Poor sap.\r\n");
GET_OBJ_TYPE(corpse) = ITEM_CONTAINER;
(corpse)->obj_flags.wear_flags.SetBits(ITEM_WEAR_TAKE, ENDBIT);
(corpse)->obj_flags.extra_flags.SetBits(ITEM_NODONATE, ITEM_NORENT,
ITEM_CORPSE, ENDBIT);
GET_OBJ_VAL(corpse, 0) = 0; /* You can't store stuff in a corpse */
GET_OBJ_VAL(corpse, 4) = 1; /* corpse identifier */
GET_OBJ_WEIGHT(corpse) = MAX(100, GET_WEIGHT(ch)) + IS_CARRYING_W(ch);
if (IS_NPC(ch))
{
GET_OBJ_TIMER(corpse) = max_npc_corpse_time;
GET_OBJ_VAL(corpse, 4) = 0;
GET_OBJ_VAL(corpse, 5) = ch->nr;
} else
{
GET_OBJ_TIMER(corpse) = max_pc_corpse_time;
/* if (PRF_FLAGGED(ch, PRF_PKER))
GET_OBJ_VAL(corpse, 4) = 2;
else*/
GET_OBJ_VAL(corpse, 4) = 1;
GET_OBJ_VAL(corpse, 5) = GET_IDNUM(ch);
/* make 'em bullet proof...(anti-twink measure) */
GET_OBJ_BARRIER(corpse) = 75;
}
/* transfer character's inventory to the corpse */
for (o = ch->carrying; o; o = obj)
{
obj = o->next_content;
obj_from_char(o);
obj_to_obj(o, corpse);
corpse_value += GET_OBJ_COST( o );
}
/* transfer character's equipment to the corpse */
for (i = 0; i < NUM_WEARS; i++)
{
if (ch->equipment[i]) {
corpse_value += GET_OBJ_COST( ch->equipment[i] );
obj_to_obj(unequip_char(ch, i, TRUE), corpse);
}
}
/* transfer nuyen & credstick */
if (IS_NPC(ch))
{
nuyen = (int)(GET_NUYEN(ch) / 10);
nuyen = number(GET_NUYEN(ch) - nuyen, GET_NUYEN(ch) + nuyen);
credits = (int)(GET_BANK(ch) / 10);
credits = number(GET_BANK(ch) - credits, GET_BANK(ch) + credits);
} else
{
nuyen = GET_NUYEN(ch);
credits = 0;
}
if (IS_NPC(ch) && (nuyen > 0 || credits > 0))
if (from_ip_zone(GET_MOB_VNUM(ch)))
{
nuyen = 0;
credits = 0;
}
if (nuyen > 0)
{
money = create_nuyen(nuyen);
obj_to_obj(money, corpse);
GET_NUYEN(ch) = 0;
}
if (credits > 0)
{
money = create_credstick(ch, credits);
obj_to_obj(money, corpse);
}
if ( IS_NPC(ch) )
{
extern struct char_data *mob_proto;
mob_proto[GET_MOB_RNUM(ch)].mob_specials.value_death_nuyen += credits + nuyen;
mob_proto[GET_MOB_RNUM(ch)].mob_specials.value_death_items += corpse_value;
}
ch->carrying = NULL;
IS_CARRYING_N(ch) = 0;
IS_CARRYING_W(ch) = 0;
if (ch->in_veh) {
obj_to_veh(corpse, ch->in_veh);
corpse->vfront = ch->vfront;
} else
obj_to_room(corpse, ch->in_room);
}
void death_cry(struct char_data * ch)
{
int door, was_in;
act("$n cries out $s last breath as $e dies!", FALSE, ch, 0, 0, TO_ROOM);
was_in = ch->in_room;
for (door = 0; door < NUM_OF_DIRS; door++)
{
if (CAN_GO(ch, door)) {
ch->in_room = world[was_in].dir_option[door]->to_room;
act("Somewhere close, you hear someone's death cry!", FALSE, ch, 0, 0, TO_ROOM);
ch->in_room = was_in;
}
}
}
void raw_kill(struct char_data * ch)
{
struct obj_data *bio, *obj, *o;
long i;
if (FIGHTING(ch))
stop_fighting(ch);
if (IS_ELEMENTAL(ch) && GET_ACTIVE(ch))
{
for (struct descriptor_data *d = descriptor_list; d; d = d->next)
if (d->character && GET_IDNUM(d->character) == GET_ACTIVE(ch)) {
for (struct spirit_data *spirit = GET_SPIRIT(d->character); spirit; spirit = spirit->next)
if (spirit->id == GET_GRADE(ch)) {
spirit->called = FALSE;
}
send_to_char(d->character, "%s is disrupted and returns to the metaplanes to heal.\r\n", CAP(GET_NAME(ch)));
break;
}
}
if (IS_ASTRAL(ch))
{
act("$n vanishes.", FALSE, ch, 0, 0, TO_ROOM);
for (i = 0; i < NUM_WEARS; i++)
if (GET_EQ(ch, i))
extract_obj(GET_EQ(ch, i));
for (obj = ch->carrying; obj; obj = o) {
o = obj->next_content;
extract_obj(obj);
}
} else
{
death_cry(ch);
if (!(IS_SPIRIT(ch) || IS_ELEMENTAL(ch)))
make_corpse(ch);
if (!IS_NPC(ch)) {
for (bio = ch->bioware; bio; bio = bio->next_content)
switch (GET_OBJ_VAL(bio, 0)) {
case BIO_ADRENALPUMP:
if (GET_OBJ_VAL(bio, 5) > 0) {
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(ch,
bio->affected[i].location,
bio->affected[i].modifier,
bio->obj_flags.bitvector, FALSE);
GET_OBJ_VAL(bio, 5) = 0;
}
break;
case BIO_PAINEDITOR:
GET_OBJ_VAL(bio, 3) = 0;
break;
}
GET_DRUG_AFFECT(ch) = GET_DRUG_DURATION(ch) = GET_DRUG_STAGE(ch) = 0;
if (PLR_FLAGGED(ch, PLR_AUTH))
i = real_room(60500);
else if (zone_table[world[ch->in_room].zone].juridiction > 0)
i = real_room(14709);
else
i = real_room(16295);
char_from_room(ch);
char_to_room(ch, i);
PLR_FLAGS(ch).SetBit(PLR_JUST_DIED);
}
}
if (IS_SPIRIT(ch) && GET_ACTIVE(ch))
end_spirit_existance(ch, TRUE);
else extract_char(ch);
}
void death_penalty(struct char_data *ch)
{
int attribute = 0;
int old_rep = GET_TKE( ch );
if(!IS_NPC(ch)
&& !PLR_FLAGGED(ch, PLR_NEWBIE)
&& GET_REAL_BOD(ch) > 1
&& !(success_test(GET_REAL_BOD(ch),4) >= 1 ))
{
do {
attribute = number(0,5);
} while (attribute == CHA);
GET_TKE(ch) -= 2*GET_REAL_ATT(ch, attribute);
GET_REAL_ATT(ch, attribute)--;
sprintf(buf,"%s lost a point of attribute %d. Total Karma Earned from %d to %d.",
GET_CHAR_NAME(ch), attribute, old_rep, GET_TKE( ch ) );
mudlog(buf, ch, LOG_DEATHLOG, TRUE);
}
}
void die(struct char_data * ch)
{
if (!((IS_NPC(ch) && MOB_FLAGGED(ch, MOB_INANIMATE)) || IS_PROJECT(ch))) {
increase_blood(ch->in_room);
act("^rBlood splatters everywhere!^n", FALSE, ch, 0, 0, TO_ROOM);
if (!world[ch->in_room].background[0] || world[ch->in_room].background[1] == AURA_PLAYERCOMBAT) {
world[ch->in_room].background[0] = 1;
world[ch->in_room].background[1] = AURA_PLAYERDEATH;
}
}
if (!IS_NPC(ch))
{
death_penalty(ch);
PLR_FLAGS(ch).RemoveBit(PLR_WANTED);
}
raw_kill(ch);
}
/*
* Lets the player give up and die if they're at 0 or less
* physical points.
*/
ACMD(do_die)
{
char buf[100];
/* If they're still okay... */
if ( GET_PHYSICAL(ch) >= 100 ) {
send_to_char("Your mother would be so sad.. :(\n\r",ch);
return;
}
send_to_char("You give up the will to live..\n\r",ch);
/* log it */
sprintf(buf,"%s gave up the will to live. {%s (%ld)}",
GET_CHAR_NAME(ch),
world[ch->in_room].name, world[ch->in_room].number );
mudlog(buf, ch, LOG_DEATHLOG, TRUE);
/* Now we just kill them, MuHahAhAhahhaAHhaAHaA!!...or something */
die(ch);
return;
}
int calc_karma(struct char_data *ch, struct char_data *vict)
{
int base = 0, i, bonus_karma;
if (!vict || !IS_NPC(vict))
return 0;
if (ch && IS_PROJECT(ch))
ch = ch->desc->original;
if (ch && (GET_RACE(vict) == RACE_SPIRIT || GET_RACE(vict) == RACE_ELEMENTAL) && GET_IDNUM(ch) == GET_ACTIVE(vict))
return 0;
base = (int)((1.2 * (GET_REAL_BOD(vict) + GET_BALLISTIC(vict) + GET_IMPACT(vict))) +
(GET_REAL_QUI(vict) + (int)(vict->real_abils.mag / 100) +
GET_REAL_STR(vict) + GET_REAL_WIL(vict) + GET_REAL_REA(vict)));
for (i = 0; i <= MAX_SKILLS; i++)
if (GET_SKILL(vict, i) > 0)
{
if (i == SKILL_SORCERY && GET_MAG(vict) > 0)
base += (int)(1.15 * GET_SKILL(vict, i));
else if (return_general(i) == SKILL_FIREARMS ||
return_general(i) == SKILL_UNARMED_COMBAT ||
return_general(i) == SKILL_ARMED_COMBAT)
base += (int)(1.4 * GET_SKILL(vict, i));
}
if (IS_NPC(vict) && (GET_RACE(vict) == RACE_SPIRIT || GET_RACE(vict) == RACE_ELEMENTAL))
base = (int)(base * 1.15);
if (IS_NPC(vict))
bonus_karma = GET_KARMA(vict);
else
bonus_karma = 0;
bonus_karma = MIN( bonus_karma, base );
base += bonus_karma;
if (ch && !IS_NPC(ch))
{
if (PLR_FLAGGED(ch, PLR_NEWBIE))
base -= (int)(GET_TKE(ch) / 5);
else
base -= (int)(GET_TKE(ch) / 3);
}
//now to randomize it a bit
base += (!ch ? 0 : (!number(0,2) ? number(0,5) :
0 - number(0,5)));
base = (ch ? MIN(max_exp_gain, base) : base);
base = MAX(base, 1);
if (ch && !IS_NPC(ch) && !IS_SENATOR(ch) && IS_NPC(vict))
if (from_ip_zone(GET_MOB_VNUM(vict)))
base = 0;
return base;
}
void perform_group_gain(struct char_data * ch, int base, struct char_data * victim)
{
int share;
share = MIN(max_exp_gain, MAX(1, base));
if (!IS_NPC(ch))
share = MIN(base, (PLR_FLAGGED(ch, PLR_NEWBIE) ? 20 : GET_TKE(ch) * 2));
/* psuedo-fix of the group with a newbie to get more exp exploit */
if ( !PLR_FLAGGED(ch, PLR_NEWBIE) )
share /= 2;
share = gain_exp(ch, share, 0);
if ( share >= 100 || access_level(ch, LVL_BUILDER) )
{
sprintf(buf,"%s gains %.2f karma from killing %s.", GET_CHAR_NAME(ch),
(double)share/100.0, GET_CHAR_NAME(victim));
mudlog(buf, ch, LOG_DEATHLOG, TRUE);
}
if ( IS_NPC( victim ) )
{
extern struct char_data *mob_proto;
mob_proto[GET_MOB_RNUM(victim)].mob_specials.value_death_karma += share;
}
send_to_char(ch, "You receive your share of %0.2f karma.\r\n", ((float)share / 100));
}
void group_gain(struct char_data * ch, struct char_data * victim)
{
int tot_members, base;
struct char_data *k;
struct follow_type *f;
if (!(k = ch->master))
k = ch;
if (IS_AFFECTED(k, AFF_GROUP) && (k->in_room == ch->in_room))
tot_members = 1;
else
tot_members = 0;
for (f = k->followers; f; f = f->next)
if (IS_AFFECTED(f->follower, AFF_GROUP)
&& f->follower->in_room == ch->in_room)
tot_members++;
base = calc_karma(k, victim) / tot_members + 1;
if (tot_members >= 1)
base = MAX(1, (base / tot_members));
else
base = 0;
if (IS_AFFECTED(k, AFF_GROUP) && k->in_room == ch->in_room)
perform_group_gain(k, base, victim);
for (f = k->followers; f; f = f->next)
if (IS_AFFECTED(f->follower, AFF_GROUP) && f->follower->in_room == ch->in_room)
perform_group_gain(f->follower, base, victim);
}
char *replace_string(char *str, char *weapon_singular, char *weapon_plural,
char *weapon_different)
{
static char buf[256];
char *cp;
cp = buf;
for (; *str; str++) {
if (*str == '#') {
switch (*(++str)) {
case 'W':
for (; *weapon_plural; *(cp++) = *(weapon_plural++))
;
break;
case 'w':
for (; *weapon_singular; *(cp++) = *(weapon_singular++))
;
break;
case 'd':
for (; *weapon_different; *(cp++) = *(weapon_different++))
;
break;
default:
*(cp++) = '#';
break;
}
} else
*(cp++) = *str;
*cp = 0;
} /* For */
return (buf);
}
#define SENDOK(ch) ((ch)->desc && AWAKE(ch) && !(PLR_FLAGGED((ch), PLR_WRITING) || PLR_FLAGGED((ch), PLR_EDITING) || PLR_FLAGGED((ch), PLR_MAILING) || PLR_FLAGGED((ch), PLR_CUSTOMIZE)) && (STATE(ch->desc) != CON_SPELL_CREATE))
/* message for doing damage with a weapon */
void dam_message(int dam, struct char_data * ch, struct char_data * victim, int w_type)
{
char *buf;
int msgnum;
struct char_data *witness;
int was_in = 0, door1, door2, door3, room1 = 0, room2 = 0, room3 = 0;
char been_heard[MAX_STRING_LENGTH];
char temp[20];
long rnum = 0;
static struct dam_weapon_type
{
char *to_room;
char *to_char;
char *to_victim;
}
dam_weapons[] = {
{
"$n tries to #w $N, but misses.", /* 0: 0 */
"You try to #w $N, but miss.",
"$n tries to #w you, but misses."
},
{
"$n grazes $N as $e #W $M.", /* 1: 1..2 */
"You graze $N as you #w $M.",
"$n grazes you as $e #W you."
},
{
"$n barely #W $N.", /* 2: 3..4 */
"You barely #w $N.",
"$n barely #W you."
},
{
"$n #W $N.", /* 3: 5..6 */
"You #w $N.",
"$n #W you."
},
{
"$n #W $N hard.", /* 4: 7..10 */
"You #w $N hard.",
"$n #W you hard."
},
{
"$n #W $N very hard.", /* 5: 11..14 */
"You #w $N very hard.",
"$n #W you very hard."
},
{
"$n #W $N extremely hard.", /* 6: 15..19 */
"You #w $N extremely hard.",
"$n #W you extremely hard."
},
{
"$n massacres $N to small fragments with $s #d.", /* 7: 19..23 */
"You massacre $N to small fragments with your #d.",
"$n massacres you to small fragments with $s #d."
},
{
"$n demolishes $N with $s deadly #d!", /* 8: > 23 */
"You demolish $N with your deadly #d!",
"$n demolishes you with $s deadly #d!"
},
{
"$n pulverizes $N with $s incredibly powerful #d!!",
"You pulverize $N with your incredibly powerful #d!!",
"$n pulverizes you with $s incredibly powerful #d!!",
},
{
"$n sublimates $N with an ultimate #d!!!",
"You sublimate $N with an ultimate #d!!!",
"$n sublimates you with an ultimate #d!!!",
}
};
w_type -= TYPE_HIT; /* Change to base of table with text */
if (dam < 0)
msgnum = 0;
else if (dam == 0)
{
switch(number(0,1)) {
case 0:
msgnum = 1;
break;
case 1:
msgnum = 2;
break;
default:
msgnum = 0;
break;
}
} else if (dam <= 1)
msgnum = 3;
else if (dam <= 3)
msgnum = 5;
else if (dam <= 6)
msgnum = 7;
else if (dam <= 10)
msgnum = 8;
else if (dam <= 13)
msgnum = 9;
else
msgnum = 10;
/* damage message to onlookers */
buf = replace_string(dam_weapons[msgnum].to_room,
attack_hit_text[w_type].singular, attack_hit_text[w_type].plural,
attack_hit_text[w_type].different);
for (witness = world[victim->in_room].people; witness; witness = witness->next_in_room)
if (witness != ch && witness != victim && !PRF_FLAGGED(witness, PRF_FIGHTGAG) && SENDOK(witness))
perform_act(buf, ch, NULL, victim, witness);
if (ch->in_room != victim->in_room && !PLR_FLAGGED(ch, PLR_REMOTE))
for (witness = world[ch->in_room].people; witness; witness = witness->next_in_room)
if (witness != ch && witness != victim && !PRF_FLAGGED(witness, PRF_FIGHTGAG) && SENDOK(witness))
perform_act(buf, ch, NULL, victim, witness);
/* damage message to damager */
strcpy(buf1, "^y");
buf = replace_string(dam_weapons[msgnum].to_char,
attack_hit_text[w_type].singular, attack_hit_text[w_type].plural,
attack_hit_text[w_type].different);
strcat(buf1, buf);
if (SENDOK(ch))
perform_act(buf1, ch, NULL, victim, ch);
/* damage message to damagee */
strcpy(buf1, "^r");
buf = replace_string(dam_weapons[msgnum].to_victim,
attack_hit_text[w_type].singular, attack_hit_text[w_type].plural,
attack_hit_text[w_type].different);
strcat(buf1, buf);
act(buf1, FALSE, ch, NULL, victim, TO_VICT | TO_SLEEP);
/* Hear gunshots even if not in the room */
if (w_type >= 21 && w_type <= 26)
{
for (int i = 7; i < 10; i++) {
struct obj_data *obj = NULL;
if (GET_EQ(ch, WEAR_WIELD) && GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), i) > 0 &&
(rnum = real_object(GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), i))) > -1 &&
(obj = &obj_proto[rnum]) && GET_OBJ_TYPE(obj) == ITEM_GUN_ACCESSORY)
if (GET_OBJ_VAL(obj, 1) == 5)
return;
}
if (world[ch->in_room].silence[0])
return;
was_in = ch->in_room;
/* Make sure the sound doesn't 'echo' back */
sprintf( been_heard, "%ld", ch->in_room );
for (door1 = 0; door1 < NUM_OF_DIRS; door1++ ) {
if ( EXIT( ch, door1 ) ) {
if ( (room1 = EXIT( ch, door1 )->to_room) == was_in || world[EXIT(ch, door1)->to_room].silence[0])
continue;
for ( door2 = 0; door2 < NUM_OF_DIRS; door2++ ) {
if ( EXIT( ch, door2 ) ) {
if ( (room2 = EXIT( ch, door2 )->to_room) == room1 || world[EXIT(ch, door2)->to_room].silence[0])
continue;
for ( door3 = 0; door3 < NUM_OF_DIRS; door3++ ) {
if ( EXIT( ch, door3 ) ) {
if ( (room3 = EXIT( ch, door3 )->to_room) == room2 || world[EXIT(ch, door3)->to_room].silence[0])
continue;
ch->in_room = room3;
sprintf( temp, "%ld", ch->in_room );
if ( !strstr( been_heard, temp ) ) {
act("You hear gunshots nearby!", FALSE, ch, 0, 0, TO_ROOM);
for (struct char_data *tch = world[ch->in_room].people; tch; tch = tch->next_in_room)
if (IS_NPC(tch))
if ((MOB_FLAGGED(tch, MOB_GUARD) || MOB_FLAGGED(tch, MOB_HELPER))
&& number(0, 6) >= 2 && (IS_NPC(ch) && !IS_NPC(tch))) {
ch->in_room = was_in;
ranged_response(ch, tch);
ch->in_room = room3;
}
strcat( been_heard, temp );
}
ch->in_room = room2;
}
}
ch->in_room = room2;
sprintf( temp, "%ld", ch->in_room );
if ( !strstr( been_heard, temp ) ) {
act("You hear gunshots not far off.", FALSE, ch, 0, 0, TO_ROOM);
for (struct char_data *tch = world[ch->in_room].people; tch; tch = tch->next_in_room)
if (IS_NPC(tch))
if ((MOB_FLAGGED(tch, MOB_GUARD) || MOB_FLAGGED(tch, MOB_HELPER))
&& number(0, 6) >= 2 && (IS_NPC(ch) && !IS_NPC(tch))) {
ch->in_room = was_in;
ranged_response(ch, tch);
ch->in_room = room2;
}
strcat( been_heard, temp );
}
ch->in_room = room1;
}
}
ch->in_room = room1;
sprintf( temp, "%ld", ch->in_room );
if ( !strstr( been_heard, temp ) ) {
act("You hear gunshots in the distance.", FALSE, ch, 0, 0, TO_ROOM);
for (struct char_data *tch = world[ch->in_room].people; tch; tch = tch->next_in_room)
if (IS_NPC(tch))
if ((MOB_FLAGGED(tch, MOB_GUARD) || MOB_FLAGGED(tch, MOB_HELPER))
&& number(0, 6) >= 2 && (IS_NPC(ch) && !IS_NPC(tch))) {
ch->in_room = was_in;
ranged_response(ch, tch);
ch->in_room = room1;
}
strcat( been_heard, temp );
}
ch->in_room = was_in;
}
}
ch->in_room = was_in;
}
}
#undef SENDOK
/*
* message for doing damage with a spell or skill
* C3.0: Also used for weapon damage on miss and death blows
*/
bool skill_message(int dam, struct char_data * ch, struct char_data * vict, int attacktype)
{
int i, j, nr;
struct message_type *msg;
struct obj_data *weap = ch->equipment[WEAR_WIELD];
for (i = 0; i < MAX_MESSAGES; i++)
{
if (fight_messages[i].a_type == attacktype) {
nr = dice(1, fight_messages[i].number_of_attacks);
for (j = 1, msg = fight_messages[i].msg; (j < nr) && msg; j++)
msg = msg->next;
if (!IS_NPC(vict) && (IS_SENATOR(vict)) && dam < 1) {
act(msg->god_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
act(msg->god_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT);
act(msg->god_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
} else if (dam > 0) {
if (GET_POS(vict) == POS_DEAD) {
send_to_char(CCYEL(ch, C_CMP), ch);
act(msg->die_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
send_to_char(CCNRM(ch, C_CMP), ch);
send_to_char(CCRED(vict, C_CMP), vict);
act(msg->die_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
send_to_char(CCNRM(vict, C_CMP), vict);
act(msg->die_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
} else {
send_to_char(CCYEL(ch, C_CMP), ch);
act(msg->hit_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
send_to_char(CCNRM(ch, C_CMP), ch);
send_to_char(CCRED(vict, C_CMP), vict);
act(msg->hit_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
send_to_char(CCNRM(vict, C_CMP), vict);
act(msg->hit_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
}
} else if ((ch != vict) && (dam <= 0)) { /* Dam == 0 */
send_to_char(CCYEL(ch, C_CMP), ch);
act(msg->miss_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
send_to_char(CCNRM(ch, C_CMP), ch);
send_to_char(CCRED(vict, C_CMP), vict);
act(msg->miss_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
send_to_char(CCNRM(vict, C_CMP), vict);
act(msg->miss_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
}
return 1;
}
}
return 0;
}
int find_orig_dir(struct char_data *ch, struct char_data *victim)
{
struct char_data *vict;
int nextroom, dir, dist, room;
for (dir = 0; dir < NUM_OF_DIRS; dir++)
{
room = victim->in_room;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
for (dist = 1; nextroom != NOWHERE && dist <= 4; dist++) {
for (vict = world[nextroom].people; vict; vict = vict->next_in_room)
if (vict == ch)
return (rev_dir[dir]);
room = nextroom;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
}
}
return -1;
}
void weapon_scatter(struct char_data *ch, struct char_data *victim, struct obj_data *weapon)
{
struct char_data *vict;
char ammo_type[20];
int damage_total, power, total = 0, door = 0, dir[3], i;
if (!ch || !victim || !weapon)
return;
dir[1] = find_orig_dir(ch, victim);
if (dir[1] >= NORTH && dir[1] <= NORTHWEST)
{
if (dir[1] == NORTH)
dir[0] = NORTHWEST;
else
dir[0] = dir[1] - 1;
if (dir[1] == NORTHWEST)
dir[2] = NORTH;
else
dir[2] = dir[1] + 1;
} else
dir[0] = dir[2] = -1;
for (vict = world[victim->in_room].people; vict; vict = vict->next_in_room)
if (vict != victim && !IS_ASTRAL(vict) && GET_POS(vict) > POS_SLEEPING)
total++;
for (i = 0; i < 3; i++)
if (dir[i] != -1 && EXIT(victim, dir[i]) &&
IS_SET(EXIT(victim, dir[i])->exit_info, EX_CLOSED))
door += 2;
switch(GET_OBJ_VAL(weapon, 3))
{
case TYPE_SHOTGUN:
sprintf(ammo_type, "horde of pellets");
break;
case TYPE_MACHINE_GUN:
sprintf(ammo_type, "stream of bullets");
break;
case TYPE_CANNON:
sprintf(ammo_type, "shell");
break;
case TYPE_ROCKET:
sprintf(ammo_type, "rocket");
break;
default:
sprintf(ammo_type, "bullet");
break;
}
i = number(1, MAX(20, total + door + 2));
if (i <= total)
{ // hits a victim
for (vict = world[victim->in_room].people; vict; vict = vict->next_in_room)
if (vict != victim && !IS_ASTRAL(vict) && GET_POS(vict) > POS_SLEEPING &&
!number(0, total - 1))
break;
if (vict && (IS_NPC(vict) || (!IS_NPC(vict) && vict->desc))) {
sprintf(buf, "A %s flies in from nowhere, hitting you!", ammo_type);
act(buf, FALSE, vict, 0, 0, TO_CHAR);
sprintf(buf, "A %s hums into the room and hits $n!", ammo_type);
act(buf, FALSE, vict, 0, 0, TO_ROOM);
power = MAX(GET_OBJ_VAL(weapon, 0) - GET_BALLISTIC(vict) - 3, 2);
damage_total = MAX(1, GET_OBJ_VAL(weapon, 1));
damage_total = convert_damage(stage((2 - success_test(GET_BOD(vict) + GET_BODY(vict), power +
modify_target(vict))), damage_total));
damage(ch, vict, damage_total, TYPE_SCATTERING, PHYSICAL);
return;
}
} else if (i > (MAX(20, total + door + 2) - door))
{ // hits a door
for (i = 0; i < 3; i++)
if (dir[i] != -1 && EXIT(victim, dir[i]) && !number(0, door - 1) &&
IS_SET(EXIT(victim, dir[i])->exit_info, EX_CLOSED))
break;
if (i < 3) {
sprintf(buf, "A %s hums into the room and hits the %s!", ammo_type,
fname(EXIT(victim, dir[i])->keyword));
act(buf, FALSE, victim, 0, 0, TO_ROOM);
act(buf, FALSE, victim, 0, 0, TO_CHAR);
damage_door(NULL, victim->in_room, dir[i], GET_OBJ_VAL(weapon, 0), DAMOBJ_PROJECTILE);
return;
}
}
// if it's reached this point, it's harmless
sprintf(buf, "A %s hums harmlessly through the room.", ammo_type);
act(buf, FALSE, victim, 0, 0, TO_ROOM);
act(buf, FALSE, victim, 0, 0, TO_CHAR);
}
void damage_equip(struct char_data *ch, struct char_data *victim, int power,
int attacktype)
{
int i = number(0, attacktype == TYPE_FIRE || attacktype == TYPE_ACID ? NUM_WEARS : 60);
if (i >= WEAR_PATCH || !GET_EQ(victim, i))
return;
if (attacktype == TYPE_FIRE)
damage_obj(ch, GET_EQ(victim, i), power, DAMOBJ_FIRE);
if (attacktype == TYPE_ACID)
{
int x = 10;
while (!GET_EQ(victim, i) && x > 0) {
i = number(0, NUM_WEARS);
x--;
}
damage_obj(ch, GET_EQ(victim, i), power, DAMOBJ_ACID);
}
if (attacktype >= TYPE_PISTOL && attacktype <= TYPE_BIFURCATE)
{
damage_obj(ch, GET_EQ(victim, i), power, DAMOBJ_PROJECTILE);
}
switch (attacktype)
{
case TYPE_PIERCE:
case TYPE_STAB:
case TYPE_SHURIKEN:
damage_obj(ch, GET_EQ(victim, i), power, DAMOBJ_PIERCE);
break;
case TYPE_STING:
case TYPE_SLASH:
case TYPE_CLAW:
case TYPE_THRASH:
case TYPE_ARROW:
case TYPE_THROWING_KNIFE:
damage_obj(ch, GET_EQ(victim, i), power, DAMOBJ_SLASH);
break;
case TYPE_HIT:
case TYPE_BLUDGEON:
case TYPE_POUND:
case TYPE_MAUL:
case TYPE_PUNCH:
damage_obj(ch, GET_EQ(victim, i), power, DAMOBJ_CRUSH);
break;
}
}
float power_multiplier(int type, int material)
{
switch (type) {
case DAMOBJ_ACID:
switch (material) {
case 6:
case 7:
case 10:
case 11:
return 1.2;
case 13:
return 2.0;
}
break;
case DAMOBJ_AIR:
switch (material) {
case 2:
return 2.0;
case 5:
case 8:
case 14:
case 15:
case 16:
return 0.4;
default:
return 0.8;
}
break;
case DAMOBJ_EARTH:
switch (material) {
case 2:
return 2.0;
default:
return 0.9;
}
break;
case DAMOBJ_FIRE:
switch (material) {
case 0:
case 1:
case 3:
return 1.5;
case 4:
case 6:
case 7:
return 1.1;
default:
return 0.8;
}
break;
case DAMOBJ_ICE:
switch (material) {
case 3:
case 4:
return 1.2;
default:
return 0.9;
}
break;
case DAMOBJ_LIGHTNING:
switch (material) {
case 8:
return 2.0;
case 10:
case 11:
return 5.0;
default:
return 0.7;
}
break;
case DAMOBJ_WATER:
switch (material) {
case 10:
case 11:
return 3.0;
default:
return 0.5;
}
break;
case DAMOBJ_EXPLODE:
switch (material) {
case 0:
case 1:
case 3:
case 4:
case 13:
return 1.3;
case 2:
return 3.0;
default:
return 1.1;
}
break;
case DAMOBJ_PROJECTILE:
switch (material) {
case 2:
return 3.0;
case 10:
case 11:
return 1.1;
default:
return 0.8;
}
break;
case DAMOBJ_CRUSH:
switch (material) {
case 1:
case 6:
case 7:
return 1.4;
case 2:
return 4.0;
case 5:
case 14:
case 15:
case 16:
return 1.0;
default:
return 0.7;
}
break;
case DAMOBJ_SLASH:
switch (material) {
case 0:
case 3:
case 4:
case 13:
return 1.4;
case 5:
case 14:
case 15:
case 16:
return 0.3;
default:
return 0.6;
}
break;
case DAMOBJ_PIERCE:
switch (material) {
case 0:
case 3:
case 4:
case 13:
return 1.0;
case 5:
case 8:
case 14:
case 15:
case 16:
return 0.1;
default:
return 0.3;
}
break;
}
return 1.0;
}
void damage_door(struct char_data *ch, int room, int dir, int power, int type)
{
if (room < 0 || room > top_of_world || dir < NORTH || dir > DOWN ||
!world[room].dir_option[dir] || !world[room].dir_option[dir]->keyword ||
!IS_SET(world[room].dir_option[dir]->exit_info, EX_CLOSED))
return;
int rating, half, opposite, rev, ok = 0;
opposite = world[room].dir_option[dir]->to_room;
rev = rev_dir[dir];
if (opposite > -1 && world[opposite].dir_option[rev] &&
world[opposite].dir_option[rev]->to_room == room)
ok = TRUE;
if (IS_SET(type, DAMOBJ_MANIPULATION))
{
rating = world[room].dir_option[dir]->barrier;
REMOVE_BIT(type, DAMOBJ_MANIPULATION);
} else
rating = world[room].dir_option[dir]->barrier * 2;
half = MAX(1, rating >> 1);
if (ch && IS_SET(type, DAMOBJ_CRUSH) && GET_TRADITION(ch) == TRAD_ADEPT && GET_POWER(ch, ADEPT_SMASHING_BLOW))
power += MAX(0, success_test(GET_POWER(ch, ADEPT_SMASHING_BLOW), 4));
if (IS_GUN(type))
sprintf(buf, "You hear gunshots and the sound of bullets impacting the %s.\r\n", fname(world[room].dir_option[dir]->keyword));
else
sprintf(buf, "Someone bashes on the %s from the other side.\r\n", fname(world[room].dir_option[dir]->keyword));
send_to_room(buf, opposite);
if (power < half)
{
sprintf(buf, "The %s remains undamaged.\r\n", fname(world[room].dir_option[dir]->keyword));
send_to_room(buf, room);
if (ch && ch->in_room != room)
send_to_char(buf, ch);
return;
} else if (power < rating)
{
sprintf(buf, "The %s has been slightly damaged.\r\n",
fname(world[room].dir_option[dir]->keyword));
send_to_room(buf, room);
if (ch && ch->in_room != room)
send_to_char(buf, ch);
world[room].dir_option[dir]->condition--;
} else
{
sprintf(buf, "The %s has been damaged!\r\n", fname(world[room].dir_option[dir]->keyword));
send_to_room(buf, room);
if (ch && ch->in_room != room)
send_to_char(buf, ch);
world[room].dir_option[dir]->condition -= 1 + (power - rating) / half;
}
if (ok)
world[opposite].dir_option[rev]->condition = world[room].dir_option[dir]->condition;
if (world[room].dir_option[dir]->condition <= 0)
{
sprintf(buf, "The %s has been destroyed!\r\n", fname(world[room].dir_option[dir]->keyword));
send_to_room(buf, room);
if (ch && ch->in_room != room)
send_to_char(buf, ch);
REMOVE_BIT(world[room].dir_option[dir]->exit_info, EX_CLOSED);
REMOVE_BIT(world[room].dir_option[dir]->exit_info, EX_LOCKED);
SET_BIT(world[room].dir_option[dir]->exit_info, EX_DESTROYED);
if (ok) {
sprintf(buf, "The %s is destroyed from the other side!\r\n",
fname(world[room].dir_option[dir]->keyword));
send_to_room(buf, opposite);
REMOVE_BIT(world[opposite].dir_option[rev]->exit_info, EX_CLOSED);
REMOVE_BIT(world[opposite].dir_option[rev]->exit_info, EX_LOCKED);
SET_BIT(world[opposite].dir_option[rev]->exit_info, EX_DESTROYED);
}
}
}
// damage_obj does what its name says, it figures out effects of successes
// damage, applies that damage to that object, and sends messages to the player
void damage_obj(struct char_data *ch, struct obj_data *obj, int power, int type)
{
if (!obj)
return;
if (power <= 0)
return;
int success, modifier, dam, target, rating, half;
struct char_data *vict = (obj->worn_by ? obj->worn_by : obj->carried_by);
struct obj_data *temp, *next;
// PC corpses are indestructable by normal means
if ( IS_OBJ_STAT(obj, ITEM_CORPSE) && GET_OBJ_VAL(obj, 4) == 1 )
{
if ( ch != NULL )
send_to_char("Nuh uh fuck nut.\n\r",ch);
return;
}
if (IS_SET(type, DAMOBJ_MANIPULATION))
{
rating = GET_OBJ_BARRIER(obj);
modifier = 2;
REMOVE_BIT(type, DAMOBJ_MANIPULATION);
} else
{
rating = GET_OBJ_BARRIER(obj) << 1;
modifier = 4;
}
half = MAX(1, rating >> 1);
modifier -= power >> 2;
success = success_test(2, MAX(2, material_ratings[(int)GET_OBJ_MATERIAL(obj)] + modifier));
if (success > 0)
{
for (struct obj_data *cont = obj->contains; cont; cont = cont->next_content)
damage_obj(ch, cont, power, type);
switch (type) {
case DAMOBJ_ACID:
if ((GET_OBJ_TYPE(obj) == ITEM_GYRO || GET_OBJ_TYPE(obj) == ITEM_WORN) && success == 2)
switch (number(0, 4)) {
case 0:
GET_OBJ_VAL(obj, 5) = MAX(GET_OBJ_VAL(obj, 0) - 1, 0);
GET_OBJ_VAL(obj, 6) = MAX(GET_OBJ_VAL(obj, 1) - 1, 0);
break;
case 1:
case 2:
GET_OBJ_VAL(obj, 5) = MAX(GET_OBJ_VAL(obj, 0) - 1, 0);
break;
case 3:
case 4:
GET_OBJ_VAL(obj, 6) = MAX(GET_OBJ_VAL(obj, 1) - 1, 0);
break;
}
break;
case DAMOBJ_FIRE:
case DAMOBJ_EXPLODE:
if (GET_OBJ_TYPE(obj) == ITEM_GUN_CLIP && success == 2 && vict) {
act("$p ignites, spraying bullets about!", FALSE, vict, obj, 0, TO_CHAR);
act("One of $n's clips ignites, spraying bullets about!",
FALSE, vict, obj, 0, TO_ROOM);
target = (int)(GET_OBJ_VAL(obj, 0) / 4);
switch (GET_OBJ_VAL(obj, 1) + 300) {
case TYPE_ROCKET:
dam = DEADLY;
break;
case TYPE_GRENADE_LAUNCHER:
case TYPE_CANNON:
dam = SERIOUS;
break;
case TYPE_SHOTGUN:
case TYPE_MACHINE_GUN:
case TYPE_RIFLE:
dam = MODERATE;
break;
default:
dam = LIGHT;
}
dam = convert_damage(stage(-success_test(GET_BOD(vict) + GET_BODY(vict),
target + modify_target(vict)), dam));
damage(vict, vict, dam, TYPE_SCATTERING, TRUE);
extract_obj(obj);
return;
}
if (GET_OBJ_TYPE(obj) == ITEM_WEAPON && success == 2 &&
GET_OBJ_VAL(obj, 3) == TYPE_HAND_GRENADE) {
if (vict) {
act("$p is set off by the fire!", FALSE, vict, obj, 0, TO_CHAR);
act("A $p carried by $n is set off by the fire!", FALSE, vict, obj, 0, TO_ROOM);
explode(NULL, obj, obj->in_room);
} else if (obj->in_room != NOWHERE) {
sprintf(buf, "%s is set off by the flames!",
CAP(obj->text.name));
send_to_room(buf, obj->in_room);
explode(NULL, obj, obj->in_room);
}
return;
}
break;
}
power = (int)(power * power_multiplier(type, GET_OBJ_MATERIAL(obj)));
}
if (power < half)
{
if (ch)
send_to_char(ch, "%s remains undamaged.\r\n",
CAP(GET_OBJ_NAME(obj)));
return;
} else if (power < rating)
{
if (ch)
send_to_char(ch, "%s has been slightly damaged.\r\n",
CAP(GET_OBJ_NAME(obj)));
if (vict && vict != ch)
send_to_char(vict, "%s has been slightly damaged.\r\n",
CAP(GET_OBJ_NAME(obj)));
GET_OBJ_CONDITION(obj)--;
} else
{
if (ch)
send_to_char(ch, "%s has been damaged!\r\n",
CAP(GET_OBJ_NAME(obj)));
if (vict && vict != ch)
send_to_char(vict, "%s has been damaged!\r\n",
CAP(GET_OBJ_NAME(obj)));
GET_OBJ_CONDITION(obj) -= 1 + (power - rating) / half;
}
// if the end result is that the object condition rating is 0 or less
// it is destroyed -- a good reason to keep objects in good repair
if (GET_OBJ_CONDITION(obj) <= 0)
{
if (ch)
send_to_char(ch, "%s has been destroyed!\r\n",
CAP(GET_OBJ_NAME(obj)));
if (vict && vict != ch)
send_to_char(vict, "%s has been destroyed!\r\n",
CAP(GET_OBJ_NAME(obj)));
if (ch && !IS_NPC(ch) && GET_QUEST(ch))
check_quest_destroy(ch, obj);
else if (ch && AFF_FLAGGED(ch, AFF_GROUP) && ch->master &&
!IS_NPC(ch->master) && GET_QUEST(ch->master))
check_quest_destroy(ch->master, obj);
for (temp = obj->contains; temp; temp = next) {
next = temp->next_content;
obj_from_obj(temp);
if ((IS_OBJ_STAT(obj, ITEM_CORPSE) && !GET_OBJ_VAL(obj, 4) &&
GET_OBJ_TYPE(temp) != ITEM_MONEY) || GET_OBJ_VNUM(obj) == 118)
extract_obj(temp);
else if (vict)
obj_to_char(temp, vict);
else if (obj->in_room != NOWHERE)
obj_to_room(temp, obj->in_room);
else
extract_obj(temp);
}
extract_obj(obj);
}
}
void docwagon_message(struct char_data *ch)
{
char buf[MAX_STRING_LENGTH];
switch (SECT(ch->in_room))
{
case SPIRIT_HEARTH:
sprintf(buf,"A DocWagon employee suddenly appears, transports %s's body to\r\nsafety, and rushes away.", GET_NAME(ch));
act(buf,FALSE, ch, 0, 0, TO_ROOM);
sprintf(buf,"A DocWagon employee suddenly appears, transports %s's body to\r\nsafety, and rushes away.", GET_CHAR_NAME(ch));
break;
case SPIRIT_LAKE:
case SPIRIT_RIVER:
case SPIRIT_SEA:
sprintf(buf,"A DocWagon armored speedboat arrives, loading %s's body on\r\nboard before leaving.", GET_NAME(ch));
act(buf, FALSE, ch, 0, 0, TO_ROOM);
sprintf(buf,"A DocWagon armored speedboat arrives, loading %s's body on\r\nboard before leaving.", GET_CHAR_NAME(ch));
break;
default:
sprintf(buf,"A DocWagon helicopter flies in, taking %s's body to safety.", GET_NAME(ch));
act(buf, FALSE, ch, 0, 0, TO_ROOM);
sprintf(buf,"A DocWagon helicopter flies in, taking %s's body to safety.", GET_CHAR_NAME(ch));
break;
}
mudlog(buf, ch, LOG_DEATHLOG, TRUE);
}
void docwagon(struct char_data *ch)
{
int i, creds;
struct obj_data *docwagon = NULL;
if (IS_NPC(ch))
return;
for (i = 0; (i < NUM_WEARS && !docwagon); i++)
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_DOCWAGON && GET_OBJ_VAL(GET_EQ(ch, i), 1) == GET_IDNUM(ch))
docwagon = GET_EQ(ch, i);
if (!docwagon || PLR_FLAGGED(ch, PLR_AUTH))
return;
if (success_test(GET_OBJ_VAL(docwagon, 0),
MAX(zone_table[world[ch->in_room].zone].security, 4)) > 0)
{
if (FIGHTING(ch) && FIGHTING(FIGHTING(ch)) == ch)
stop_fighting(FIGHTING(ch));
if (FIGHTING(ch))
stop_fighting(ch);
if (GET_SUSTAINED(ch)) {
struct sustain_data *next;
for (struct sustain_data *sust = GET_SUSTAINED(ch); sust; sust = next) {
next = sust->next;
if (next && sust->idnum == next->idnum)
next = next->next;
end_sustained_spell(ch, sust);
}
}
if (ch->persona)
{
sprintf(buf, "%s depixelizes and vanishes from the host.\r\n", ch->persona->name);
send_to_host(ch->persona->in_host, buf, ch->persona, TRUE);
extract_icon(ch->persona);
ch->persona = NULL;
PLR_FLAGS(ch).RemoveBit(PLR_MATRIX);
} else if (PLR_FLAGGED(ch, PLR_MATRIX))
for (struct char_data *temp = world[ch->in_room].people; temp; temp = temp->next_in_room)
if (PLR_FLAGGED(temp, PLR_MATRIX))
temp->persona->decker->hitcher = NULL;
docwagon_message(ch);
death_penalty(ch); /* Penalty for deadly wounds */
GET_PHYSICAL(ch) = 400;
GET_MENTAL(ch) = 0;
GET_POS(ch) = POS_STUNNED;
for (struct obj_data *bio = ch->bioware; bio; bio = bio->next_content)
switch (GET_OBJ_VAL(bio, 0)) {
case BIO_ADRENALPUMP:
if (GET_OBJ_VAL(bio, 5) > 0) {
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(ch,
bio->affected[i].location,
bio->affected[i].modifier,
bio->obj_flags.bitvector, FALSE);
GET_OBJ_VAL(bio, 5) = 0;
}
break;
case BIO_PAINEDITOR:
GET_OBJ_VAL(bio, 3) = 0;
break;
}
ch->points.fire[0] = 0;
send_to_char("\r\n\r\nYour last conscious memory is the arrival of a DocWagon.\r\n", ch);
if (zone_table[world[ch->in_room].zone].juridiction > 0)
i = real_room(14709);
else
i = real_room(16295);
char_from_room(ch);
char_to_room(ch, i);
creds = MAX((number(8, 12) * 500 / GET_OBJ_VAL(docwagon, 0)), (int)(GET_NUYEN(ch) / 10));
if ((GET_NUYEN(ch) + GET_BANK(ch)) < creds) {
send_to_char("Not finding sufficient payment, your DocWagon contract was retracted.\r\n", ch);
extract_obj(docwagon);
} else if (GET_BANK(ch) < creds) {
GET_NUYEN(ch) -= (creds - GET_BANK(ch));
GET_BANK(ch) = 0;
} else
GET_BANK(ch) -= creds;
}
return;
}
void check_adrenaline(struct char_data *ch, int mode)
{
int i, dam;
struct obj_data *pump = NULL;
for (pump = ch->bioware; pump && GET_OBJ_VAL(pump, 2) != 4; pump = pump->next_content)
;
if (!pump)
return;
if (GET_OBJ_VAL(pump, 5) == 0 && mode == 1)
{
GET_OBJ_VAL(pump, 5) = dice(GET_OBJ_VAL(pump, 0), 6);
GET_OBJ_VAL(pump, 6) = GET_OBJ_VAL(pump, 5);
send_to_char("Your body is wracked with renewed vitality as adrenaline "
"pumps into your\r\nbloodstream.\r\n", ch);
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(ch,
pump->affected[i].location,
pump->affected[i].modifier,
pump->obj_flags.bitvector, TRUE);
} else if (GET_OBJ_VAL(pump, 5) > 0 && !mode)
{
GET_OBJ_VAL(pump, 5)--;
if (GET_OBJ_VAL(pump, 5) == 0) {
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(ch,
pump->affected[i].location,
pump->affected[i].modifier,
pump->obj_flags.bitvector, FALSE);
GET_OBJ_VAL(pump, 5) = -number(168, 180);
send_to_char("Your body softens and relaxes as the adrenaline wears off.\r\n", ch);
dam = convert_damage(stage(-success_test(GET_BOD(ch) + GET_BODY(ch),
(int)(GET_OBJ_VAL(pump, 6) / 2) + modify_target(ch)), DEADLY));
GET_OBJ_VAL(pump, 6) = 0;
damage(ch, ch, dam, TYPE_BIOWARE, FALSE);
}
} else if (GET_OBJ_VAL(pump, 5) < 0 && !mode)
GET_OBJ_VAL(pump, 5)++;
}
void gen_death_msg(struct char_data *ch, struct char_data *vict, int attacktype)
{
switch (attacktype)
{
case TYPE_SUFFERING:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "%s died (no blood, it seems). {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s's brain ran out of oxygen {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "%s simply ran out of blood. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "%s unwittingly committed suicide. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "Bloodlack stole %s's life. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
}
break;
case TYPE_EXPLOSION:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "%s blew %s to pieces. {%s (%ld)}", ch == vict ? "???"
: GET_NAME(ch), GET_CHAR_NAME(vict),
world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s was blown to bits. [%s] {%s (%ld)}",
GET_CHAR_NAME(vict), ch == vict ? "???" : GET_NAME(ch),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "%s got vaporized by %s. {%s (%ld)}",
GET_CHAR_NAME(vict), ch == vict ? "???" : GET_NAME(ch),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "%s was incinerated by an explosion. [%s] {%s (%ld)}",
GET_CHAR_NAME(vict), ch == vict ? "???" : GET_NAME(ch),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "%s got blown to hell by %s. {%s (%ld)}",
GET_CHAR_NAME(vict), ch == vict ? "???" : GET_NAME(ch),
world[vict->in_room].name, world[vict->in_room].number);
break;
}
break;
case TYPE_SCATTERING:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "%s accidentally (?) killed by %s. {%s (%ld)}",
GET_CHAR_NAME(vict), GET_NAME(ch),
world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "Shouldn't have been standing there, should you %s? "
"[%s] {%s (%ld)}", GET_CHAR_NAME(vict), GET_NAME(ch),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "Oops....%s just blew %s's head off. {%s (%ld)}",
GET_NAME(ch), GET_CHAR_NAME(vict),
world[vict->in_room].name,
world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "%s's stray bullet caught %s in the heart. "
"What a shame. {%s (%ld)}",
GET_NAME(ch), GET_CHAR_NAME(vict),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "A random bullet killed a random person -- poor %s. "
"[%s] {%s (%ld)}", GET_CHAR_NAME(vict), GET_NAME(ch),
world[vict->in_room].name, world[vict->in_room].number);
break;
}
break;
case TYPE_FALL:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "%s died on impact. {%s (%ld)}", GET_CHAR_NAME(vict),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s failed to miss the ground. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "Life's a bitch, %s. So's concrete. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "What %s wouldn't have given for a safety net... "
"{%s (%ld)}", GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "The ground can be such an unforgiving thing. "
"Right, %s? {%s (%ld)}", GET_CHAR_NAME(vict),
world[vict->in_room].name, world[vict->in_room].number);
break;
}
break;
case TYPE_DROWN:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "%s drank way, way, WAY too much. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s sleeps with the fishes. Involuntarily. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "The water had a fight with %s's lungs. "
"The water won. {%s (%ld)}", GET_CHAR_NAME(vict),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "Water doesn't seem so harmless now, does it %s? "
"{%s (%ld)}", GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "%s didn't float. {%s (%ld)}", GET_CHAR_NAME(vict),
world[vict->in_room].name, world[vict->in_room].number);
break;
}
break;
case TYPE_BIOWARE:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "%s just hasn't been taking %s medication. Oops. "
"{%s (%ld)}", GET_CHAR_NAME(vict), GET_SEX(vict) == SEX_MALE ?
"his" : (GET_SEX(vict) == SEX_FEMALE ? "her" : "its"),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s was killed in a bioware rebellion. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "%s has a fatal heart attack. Wuss. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "Still think the bioware was worth it, %s?. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "Maybe %s got a defective piece of bioware... {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
}
break;
case TYPE_RECOIL:
switch (number(0, 4)) {
case 0:
sprintf(buf2, "You're meant to hit *other* people with that whip, "
"%s. {%s (%ld)}", GET_CHAR_NAME(vict),
world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s lopped off %s own head. Oops. {%s (%ld)}",
GET_CHAR_NAME(vict), GET_SEX(vict) == SEX_MALE ? "his" :
(GET_SEX(vict) == SEX_FEMALE ? "her" : "its"),
world[vict->in_room].name, world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "%s, watch out for your whi....nevermind. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "THWAP! Wait.....was that *your* whip, %s?!? "
"{%s (%ld)}", GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "%s's whip didn't agree with %s. {%s (%ld)}",
GET_CHAR_NAME(vict), GET_SEX(vict) == SEX_MALE ? "his" :
(GET_SEX(vict) == SEX_FEMALE ? "her" : "its"),
world[vict->in_room].name, world[vict->in_room].number);
break;
}
break;
case TYPE_RAM:
sprintf(buf2, "%s was made a hood ornament. {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case TYPE_DUMPSHOCK:
sprintf(buf2, "%s couldn't quite manage a graceful logoff. { %s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case TYPE_BLACKIC:
sprintf(buf2, "%s couldn't haxor the gibson. { %s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case TYPE_POLTERGEIST:
sprintf(buf2, "%s is a pansy who got killed by the poltergeist spell. { %s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case TYPE_CRASH:
switch(number(0, 1)) {
case 0:
sprintf(buf2, "%s forgot to wear his seatbelt. { %s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s become one with the dashboard. { %s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
}
break;
default:
if (ch == vict)
sprintf(buf2, "%s died (cause uncertain). {%s (%ld)}",
GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
else
switch (number(0, 5)) {
case 0:
sprintf(buf2, "%s killed by %s. {%s (%ld)}", GET_CHAR_NAME(vict),
GET_CHAR_NAME(ch), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 1:
sprintf(buf2, "%s wiped %s out of existence. {%s (%ld)}",
GET_CHAR_NAME(ch), GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 2:
sprintf(buf2, "%s's life terminated by %s. {%s (%ld)}",
GET_CHAR_NAME(vict), GET_CHAR_NAME(ch), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 3:
sprintf(buf2, "%s flatlined %s. {%s (%ld)}",
GET_CHAR_NAME(ch), GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 4:
sprintf(buf2, "%s transformed %s into a corpse. {%s (%ld)}",
GET_CHAR_NAME(ch), GET_CHAR_NAME(vict), world[vict->in_room].name,
world[vict->in_room].number);
break;
case 5:
sprintf(buf2, "%s got geeked by %s. {%s (%ld)}",
GET_CHAR_NAME(vict), GET_CHAR_NAME(ch), world[vict->in_room].name,
world[vict->in_room].number);
break;
}
break;
}
mudlog(buf2, vict, LOG_DEATHLOG, TRUE);
}
#define IS_RANGED(eq) (GET_OBJ_TYPE(eq) == ITEM_FIREWEAPON || \
(GET_OBJ_TYPE(eq) == ITEM_WEAPON && \
(GET_OBJ_VAL(eq, 3) == TYPE_SHURIKEN || \
GET_OBJ_VAL(eq, 3) == TYPE_THROWING_KNIFE || \
GET_OBJ_VAL(eq, 3) >= TYPE_PISTOL)))
#define RANGE_OK(ch) ((GET_WIELDED(ch, 0) && GET_EQ(ch, WEAR_WIELD) && \
IS_RANGED(GET_EQ(ch, WEAR_WIELD))) || (GET_WIELDED(ch, 1) && \
GET_EQ(ch, WEAR_HOLD) && IS_RANGED(GET_EQ(ch, WEAR_HOLD))))
#define IS_BURST(eq) (GET_OBJ_TYPE(eq) == ITEM_WEAPON && \
(GET_OBJ_VAL(eq, 3) == TYPE_MACHINE_GUN || \
(GET_OBJ_VAL(eq, 3) == TYPE_RIFLE && \
GET_OBJ_VAL(eq, 4) == SKILL_ASSAULT_RIFLES)))
// return 1 if victim died, 0 otherwise
bool damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype,
bool is_physical)
{
char rbuf[MAX_STRING_LENGTH];
int exp;
bool total_miss = FALSE, awake = TRUE;
struct obj_data *bio;
ACMD(do_disconnect);
ACMD(do_return);
if (GET_POS(victim) <= POS_DEAD)
{
log("SYSERR: Attempt to damage a corpse.");
return 0; /* -je, 7/7/92 */
}
sprintf(rbuf,"Damage: ");
if (( (!IS_NPC(ch)
&& IS_SENATOR(ch)
&& !access_level(ch, LVL_ADMIN))
|| (IS_NPC(ch)
&& ch->master
&& AFF_FLAGGED(ch, AFF_CHARM)
&& !IS_NPC(ch->master)
&& IS_SENATOR(ch->master)
&& !access_level(ch->master, LVL_ADMIN)))
&& IS_NPC(victim)
&& dam > 0
&& !from_ip_zone(GET_MOB_VNUM(victim)))
{
dam = -1;
buf_mod(rbuf,"Invalid",dam);
}
/* shopkeeper protection */
if (mob_index[GET_MOB_RNUM(victim)].func == shop_keeper)
{
dam = -1;
buf_mod(rbuf,"Keeper",dam);
}
if(IS_NPC(victim) && MOB_FLAGGED(victim,MOB_NOKILL))
{
dam =-1;
buf_mod(rbuf,"Nokill",dam);
}
if (victim != ch)
{
if (GET_POS(ch) > POS_STUNNED && attacktype < TYPE_SUFFERING) {
if (!FIGHTING(ch) && !ch->in_veh)
set_fighting(ch, victim);
if (!IS_NPC(ch) && IS_NPC(victim) && victim->master && !number(0, 10) &&
IS_AFFECTED(victim, AFF_CHARM) && (victim->master->in_room == ch->in_room) &&
!(ch->master && ch->master == victim->master)) {
if (FIGHTING(ch))
stop_fighting(ch);
set_fighting(ch, victim->master);
if (!FIGHTING(victim->master))
set_fighting(victim->master, ch);
return 0;
}
}
if (GET_POS(victim) > POS_STUNNED && !FIGHTING(victim)) {
if (victim->in_room == ch->in_room)
set_fighting(victim, ch);
if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch) &&
(!IS_SENATOR(ch)))
remember(victim, ch);
}
}
if (victim->master && victim->master == ch)
stop_follower(victim);
if (IS_AFFECTED(ch, AFF_HIDE))
appear(ch);
/* stop sneaking if it's the case */
if (IS_AFFECTED(ch, AFF_SNEAK))
AFF_FLAGS(ch).RemoveBit(AFF_SNEAK);
if (PLR_FLAGGED(victim, PLR_PROJECT) && ch != victim)
{
do_return(victim, "", 0, 0);
WAIT_STATE(victim, PULSE_VIOLENCE);
}
/* Firgure out how to do WANTED flag*/
if (ch != victim)
{
check_killer(ch, victim);
}
if (PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(victim))
{
dam = -1;
buf_mod(rbuf,"No-PK",dam);
}
if (attacktype == TYPE_EXPLOSION && (IS_ASTRAL(victim) || MOB_FLAGGED(victim, MOB_IMMEXPLODE)))
{
dam = -1;
buf_mod(rbuf,"ImmExplode",dam);
}
act(rbuf, 0, ch, 0, victim, TO_ROLLS);
if (dam == -1)
{
total_miss = TRUE;
}
if (ch != victim && !IS_NPC(victim) && !(victim->desc))
{
if (!FIGHTING(victim)) {
act("$n is rescued by divine forces.", FALSE, victim, 0, 0, TO_ROOM);
GET_WAS_IN(victim) = victim->in_room;
GET_PHYSICAL(victim) = MAX(100, GET_PHYSICAL(victim) -
(int)(GET_MAX_PHYSICAL(victim) / 2));
GET_MENTAL(victim) = MAX(100, GET_MENTAL(victim) -
(int)(GET_MAX_MENTAL(victim) / 2));
char_from_room(victim);
char_to_room(victim, 0);
}
return 0;
}
int comp = 0;
bool trauma = FALSE, pain = FALSE;
if (attacktype != TYPE_BIOWARE)
for (bio = ch->bioware; bio; bio = bio->next_content)
if (GET_OBJ_VAL(bio, 0) == BIO_PLATELETFACTORY && dam >= 3 && is_physical)
dam--;
else if (GET_OBJ_VAL(bio, 0) == BIO_DAMAGECOMPENSATOR)
comp = GET_OBJ_VAL(bio, 1) * 100;
else if (GET_OBJ_VAL(bio, 0) == BIO_TRAUMADAMPNER && GET_MENTAL(ch) > 0)
trauma = TRUE;
else if (GET_OBJ_VAL(bio, 0) == BIO_PAINEDITOR && GET_OBJ_VAL(bio, 3))
pain = TRUE;
if (GET_PHYSICAL(victim) > 0)
awake = FALSE;
if (!total_miss)
if (is_physical) {
GET_PHYSICAL(victim) -= MAX(dam * 100, 0);
if (!pain && trauma && (!comp || (comp && GET_MENTAL(victim) > 0 && 1000 - GET_PHYSICAL(victim) > comp))) {
GET_PHYSICAL(victim) += 100;
GET_MENTAL(victim) -= 100;
}
AFF_FLAGS(victim).SetBit(AFF_DAMAGED);
if (IS_PROJECT(victim)) {
GET_PHYSICAL(victim->desc->original) -= MAX(dam * 100, 0);
AFF_FLAGS(victim->desc->original).SetBit(AFF_DAMAGED);
}
} else if (((int)(GET_MENTAL(victim) / 100) - dam) < 0 ) {
int physdam = dam - (int)(GET_MENTAL(victim) / 100);
GET_MENTAL(victim) = 0;
GET_PHYSICAL(victim) -= MAX(physdam * 100, 0);
AFF_FLAGS(victim).SetBit(AFF_DAMAGED);
if (IS_PROJECT(victim)) {
GET_MENTAL(victim->desc->original) = 0;
GET_PHYSICAL(victim->desc->original) -= MAX(physdam * 100, 0);
AFF_FLAGS(victim->desc->original).SetBit(AFF_DAMAGED);
}
} else {
GET_MENTAL(victim) -= MAX(dam * 100, 0);
if (!pain && trauma && (!comp || (comp && GET_MENTAL(victim) > 0 && 1000 - GET_MENTAL(victim) > comp)))
GET_MENTAL(victim) += 100;
if (IS_PROJECT(victim))
GET_MENTAL(victim->desc->original) -= MAX(dam * 100, 0);
}
if (!awake && GET_PHYSICAL(victim) <= 0)
victim->points.lastdamage = time(0);
update_pos(victim);
if (GET_SUSTAINED_NUM(victim))
{
struct sustain_data *next;
if (GET_POS(victim) < POS_LYING) {
for (struct sustain_data *sust = GET_SUSTAINED(victim); sust; sust = next) {
next = sust->next;
if (sust->caster && !sust->focus && !sust->spirit) {
if (next && sust->idnum == next->idnum)
next = next->next;
end_sustained_spell(victim, sust);
}
}
} else if (dam > 0) {
for (struct sustain_data *sust = GET_SUSTAINED(victim); sust; sust = next) {
next = sust->next;
if (sust->caster && !sust->focus && !sust->spirit)
if (success_test(GET_SKILL(victim, SKILL_SORCERY), sust->force + damage_modifier(victim, buf)) < 1)
end_sustained_spell(victim, sust);
}
}
}
/*
* skill_message sends a message from the messages file in lib/misc.
* dam_message just sends a generic "You hit $n extremely hard.".
* skill_message is preferable to dam_message because it is more
* descriptive.
*
* If we are _not_ attacking with a weapon (i.e. a spell), always use
* skill_message. If we are attacking with a weapon: If this is a miss or a
* death blow, send a skill_message if one exists; if not, default to a
* dam_message. Otherwise, always send a dam_message.
*/
if (attacktype > 0 && ch != victim && attacktype < TYPE_SUFFERING)
{
if (!IS_WEAPON(attacktype)) {
skill_message(dam, ch, victim, attacktype);
} else {
if (GET_POS(victim) == POS_DEAD) {
if (!skill_message(dam, ch, victim, attacktype))
dam_message(dam, ch, victim, attacktype);
} else
dam_message(dam, ch, victim, attacktype);
}
}
if ((ch->in_room != victim->in_room) && total_miss && attacktype < TYPE_SUFFERING &&
attacktype >= TYPE_PISTOL)
weapon_scatter(ch, victim, GET_EQ(ch, WEAR_WIELD));
if (victim->bioware && GET_POS(victim) > POS_STUNNED && dam > 0 && ch != victim)
check_adrenaline(victim, 1);
if (ch != victim && dam > 0 && attacktype >= TYPE_HIT)
damage_equip(ch, victim, dam, attacktype);
/* Use send_to_char -- act() doesn't send message if you are DEAD. */
switch (GET_POS(victim))
{
case POS_MORTALLYW:
act("$n is mortally wounded, and will die soon, if not aided.",
TRUE, victim, 0, 0, TO_ROOM);
if (!PLR_FLAGGED(victim, PLR_MATRIX)) {
send_to_char("You are mortally wounded, and will die soon, if not "
"aided.\r\n", victim);
}
if (!IS_NPC(victim))
docwagon(victim);
break;
case POS_STUNNED:
act("$n is stunned, but will probably regain consciousness again.",
TRUE, victim, 0, 0, TO_ROOM);
if (!PLR_FLAGGED(victim, PLR_MATRIX)) {
send_to_char("You're stunned, but will probably regain consciousness "
"again.\r\n", victim);
}
break;
case POS_DEAD:
if (IS_NPC(victim))
act("$n is dead! R.I.P.", FALSE, victim, 0, 0, TO_ROOM);
else
act("$n slumps in a pile. You hear sirens as docwagon rush in and grab $m.", FALSE, victim, 0, 0, TO_ROOM);
send_to_char("You feel the world slip in to darkness, you better hope a wandering Docwagon finds you.\r\n", victim);
break;
default: /* >= POSITION SLEEPING */
if (dam > ((int)(GET_MAX_PHYSICAL(victim) / 100) >> 2))
act("^RThat really did HURT!^n", FALSE, victim, 0, 0, TO_CHAR);
if (GET_PHYSICAL(victim) < (GET_MAX_PHYSICAL(victim) >> 2))
send_to_char(victim, "%sYou wish that your wounds would stop "
"^RBLEEDING^n so much!%s\r\n", CCRED(victim, C_SPR),
CCNRM(victim, C_SPR));
if (MOB_FLAGGED(victim, MOB_WIMPY) && ch != victim &&
GET_PHYSICAL(victim) < (GET_MAX_PHYSICAL(victim) >> 2))
do_flee(victim, "", 0, 0);
if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && victim != ch &&
(int)(GET_PHYSICAL(victim) / 100) < GET_WIMP_LEV(victim)) {
send_to_char("You ^Ywimp^n out, and attempt to flee!\r\n", victim);
do_flee(victim, "", 0, 0);
}
break;
}
if (GET_MENTAL(victim) < 100 || GET_PHYSICAL(victim) < 0)
if (FIGHTING(ch) == victim)
stop_fighting(ch);
if (!AWAKE(victim))
if (FIGHTING(victim))
stop_fighting(victim);
if (GET_POS(victim) == POS_DEAD)
{
if (ch != victim && !IS_NPC(ch) && GET_QUEST(ch) && IS_NPC(victim))
check_quest_kill(ch, victim);
else if (ch != victim && AFF_FLAGGED(ch, AFF_GROUP) && ch->master &&
!IS_NPC(ch->master) && GET_QUEST(ch->master) && IS_NPC(victim))
check_quest_kill(ch->master, victim);
if ((IS_NPC(victim) || victim->desc) && ch != victim &&
attacktype != TYPE_EXPLOSION) {
if ( IS_NPC( victim ) ) {
extern struct char_data *mob_proto;
mob_proto[GET_MOB_RNUM(victim)].mob_specials.count_death++;
}
if (IS_AFFECTED(ch, AFF_GROUP)) {
group_gain(ch, victim);
} else {
exp = calc_karma(ch, victim);
exp = gain_exp(ch, exp, 0);
if ( exp >= 100 || access_level(ch, LVL_BUILDER) ) {
sprintf(buf,"%s gains %.2f karma from killing %s.",
IS_NPC(ch) ? GET_NAME(ch) : GET_CHAR_NAME(ch),
(double)exp/100.0, GET_NAME(victim));
mudlog(buf, ch, LOG_DEATHLOG, TRUE);
}
if ( IS_NPC( victim ) ) {
extern struct char_data *mob_proto;
mob_proto[GET_MOB_RNUM(victim)].mob_specials.value_death_karma += exp;
}
send_to_char(ch, "You receive %0.2f karma.\r\n", ((float)exp / 100));
}
}
if (!IS_NPC(victim)) {
gen_death_msg(ch, victim, attacktype);
if (MOB_FLAGGED(ch, MOB_MEMORY) && !IS_NPC(victim))
forget(ch, victim);
}
die(victim);
return 1;
}
return 0;
}
bool has_ammo(struct char_data *ch, struct obj_data *wielded)
{
int i;
bool found = FALSE;
struct obj_data *obj, *cont;
if (wielded && GET_OBJ_TYPE(wielded) == ITEM_FIREWEAPON)
{
for (i = 0; i < NUM_WEARS; i++) {
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_QUIVER)
for (obj = GET_EQ(ch, i)->contains; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_MISSILE && GET_OBJ_VAL(obj, 0) == GET_OBJ_VAL(wielded, 5)) {
GET_OBJ_VAL(GET_EQ(ch, i), 2)--;
extract_obj(obj);
found = TRUE;
}
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_WORN)
for (cont = GET_EQ(ch,i)->contains; cont; cont = cont->next_content)
if (GET_OBJ_TYPE(cont) == ITEM_QUIVER)
for (obj = cont->contains; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_MISSILE && GET_OBJ_VAL(obj, 0) == GET_OBJ_VAL(wielded, 5)) {
GET_OBJ_VAL(cont, 2)--;
extract_obj(obj);
found = TRUE;
}
}
if (found)
return TRUE;
else {
if (IS_NPC(ch)) {
switch_weapons(ch, wielded->worn_on);
return TRUE;
} else {
send_to_char("You're out of arrows!\r\n", ch);
stop_fighting(ch);
return FALSE;
}
}
}
if (wielded && (GET_OBJ_VAL(wielded, 5) > 0))
{
if (IS_NPC(ch)) {
if (GET_OBJ_VAL(wielded, 6) > 0) {
GET_OBJ_VAL(wielded, 6)--;
if (wielded->contains)
GET_OBJ_VAL(wielded->contains, 9)--;
return TRUE;
} else
// make the mob do something (intelligent hopefully)
if (!attempt_reload(ch, wielded->worn_on))
switch_weapons(ch, wielded->worn_on);
return TRUE;
} else {
if (wielded->contains && GET_OBJ_VAL(wielded->contains, 9) > 0) {
if (wielded->contains)
GET_OBJ_VAL(wielded->contains, 9)--;
return TRUE;
} else {
send_to_char("*Click*\r\n", ch);
return FALSE;
}
}
} else
return TRUE;
}
int check_smartlink(struct char_data *ch, struct obj_data *weapon)
{
struct obj_data *obj, *access = NULL;
int i, mod = 0;
// are they wielding two weapons?
if (GET_EQ(ch, WEAR_WIELD) && GET_EQ(ch, WEAR_HOLD) &&
CAN_WEAR(GET_EQ(ch, WEAR_HOLD), ITEM_WEAR_WIELD))
return 0;
for (i = 7; !mod && i < 10; i++)
{
if (GET_OBJ_VAL(weapon, i) > 0
&& real_object(GET_OBJ_VAL(weapon, i)) > 0
&& (access = &obj_proto[real_object(GET_OBJ_VAL(weapon, i))])
&& GET_OBJ_VAL(access, 1) == 1) {
for (obj = ch->cyberware; !mod && obj; obj = obj->next_content)
if (GET_OBJ_VAL(obj, 0) == CYB_SMARTLINK)
if (GET_OBJ_VAL(obj, 1) == 1 || GET_OBJ_VAL(access, 2) < 2)
mod = 2;
else
mod = 4;
if (!mod && GET_EQ(ch, WEAR_EYES) && GET_OBJ_TYPE(GET_EQ(ch, WEAR_EYES)) == ITEM_GUN_ACCESSORY &&
GET_OBJ_VAL(GET_EQ(ch, WEAR_EYES), 1) == 7)
mod = 1;
access = NULL;
}
}
if (mod < 1 && AFF_FLAGGED(ch, AFF_LASER_SIGHT))
mod = 1;
return mod;
}
int check_recoil(struct char_data *ch, struct obj_data *gun)
{
struct obj_data *obj;
int i, rnum, comp = 0;
if (!gun || GET_OBJ_TYPE(gun) != ITEM_WEAPON)
return 0;
for (i = 7; i < 10; i++)
{
obj = NULL;
if (GET_OBJ_VAL(gun, i) > 0 &&
(rnum = real_object(GET_OBJ_VAL(gun, i))) > -1 &&
(obj = &obj_proto[rnum]) && GET_OBJ_TYPE(obj) == ITEM_GUN_ACCESSORY) {
if (GET_OBJ_VAL(obj, 1) == 3)
comp += 0 - GET_OBJ_VAL(obj, 2);
else if (GET_OBJ_VAL(obj, 1) == 4)
comp++;
}
}
for (obj = ch->cyberware; obj; obj = obj->next_content)
if (GET_OBJ_VAL(obj, 0) == CYB_FOOTANCHOR && !GET_OBJ_VAL(obj, 9))
comp++;
return comp;
}
void astral_fight(struct char_data *ch, struct char_data *vict)
{
int w_type, dam, power, attack_success, newskill, skill_total, base_target;
bool focus = FALSE, is_physical;
struct obj_data *wielded = ch->equipment[WEAR_WIELD];
if (ch->in_room != vict->in_room)
{
stop_fighting(ch);
if (FIGHTING(vict) == ch)
stop_fighting(vict);
return;
}
if ((IS_PROJECT(ch) || PLR_FLAGGED(ch, PLR_PERCEIVE))
&& wielded
&& GET_OBJ_TYPE(wielded) == ITEM_WEAPON
&& GET_OBJ_VAL(wielded, 3) < TYPE_TASER
&& GET_OBJ_VAL(wielded, 7)
&& GET_OBJ_VAL(wielded, 8)
&& GET_OBJ_VAL(wielded, 9) == GET_IDNUM(ch))
focus = TRUE;
else if (wielded)
{
stop_fighting(ch);
return;
}
if (IS_PROJECT(ch) && (ch != vict) && PLR_FLAGGED(vict, PLR_PERCEIVE) &&
!PLR_FLAGGED(vict, PLR_KILLER) && !PLR_FLAGGED(vict,PLR_WANTED) &&
(!PRF_FLAGGED(ch, PRF_PKER) || !PRF_FLAGGED(vict, PRF_PKER)) &&
!PLR_FLAGGED(ch->desc->original, PLR_KILLER))
{
PLR_FLAGS(ch->desc->original).SetBit(PLR_KILLER);
sprintf(buf, "PC Killer bit set on %s (astral) for initiating attack on %s at %s.",
GET_CHAR_NAME(ch), GET_CHAR_NAME(vict), world[vict->in_room].name);
mudlog(buf, ch, LOG_MISCLOG, TRUE);
send_to_char("If you want to be a PLAYER KILLER, so be it...\r\n", ch);
}
if (GET_POS(vict) <= POS_DEAD)
{
log("SYSERR: Attempt to damage a corpse.");
return; /* -je, 7/7/92 */
}
if (wielded)
w_type = GET_OBJ_VAL(wielded, 3);
else
{
if (ch->mob_specials.attack_type != 0)
w_type = ch->mob_specials.attack_type;
else
w_type = TYPE_HIT;
}
if (((w_type == TYPE_HIT) || (w_type == TYPE_BLUDGEON) || (w_type == TYPE_PUNCH) ||
(w_type == TYPE_TASER) || (w_type == TYPE_CRUSH) || (w_type == TYPE_POUND)) &&
(GET_MENTAL(vict) >= 100))
is_physical = FALSE;
else
is_physical = TRUE;
base_target = 4 + modify_target(ch);
if (!AWAKE(vict))
base_target -= 2;
if ((w_type != TYPE_HIT) && wielded)
{
power = (GET_OBJ_VAL(wielded, 0) ? GET_OBJ_VAL(wielded, 0) : GET_STR(ch)) +
GET_OBJ_VAL(wielded, 2);
if (focus)
power += GET_OBJ_VAL(wielded, 8);
power -= GET_IMPACT(vict);
dam = MODERATE;
if (IS_SPIRIT(vict) || IS_ELEMENTAL(vict))
skill_total = GET_WIL(ch);
else if (GET_SKILL(ch, GET_OBJ_VAL(wielded, 4)) < 1) {
newskill = return_general(GET_OBJ_VAL(wielded, 4));
skill_total = get_skill(ch, newskill, base_target);
} else
skill_total = GET_SKILL(ch, GET_OBJ_VAL(wielded, 4));
} else
{
power = GET_STR(ch) - GET_IMPACT(vict);
if (IS_PROJECT(ch) || PLR_FLAGGED(ch, PLR_PERCEIVE))
dam = LIGHT;
else
dam = MODERATE;
if (IS_SPIRIT(vict) || IS_ELEMENTAL(vict))
skill_total = GET_WIL(ch);
else if (GET_SKILL(ch, SKILL_UNARMED_COMBAT) < 1) {
if (GET_SKILL(ch, SKILL_SORCERY) < 1) {
newskill = SKILL_UNARMED_COMBAT;
skill_total = get_skill(ch, newskill, base_target);
} else
skill_total = GET_SKILL(ch, SKILL_SORCERY);
} else
skill_total = MAX(GET_SKILL(ch, SKILL_UNARMED_COMBAT),
GET_SKILL(ch, SKILL_SORCERY));
}
skill_total += (int)(GET_ASTRAL(ch) / 2);
if (power < 2)
{
skill_total = MAX(0, skill_total - (2 - power));
power = 2;
}
if (AWAKE(vict))
attack_success = resisted_test(skill_total, base_target,
(int)(GET_ASTRAL(vict) / 2), power + modify_target(vict));
else
attack_success = success_test(skill_total, base_target);
if (attack_success < 1)
{
if (!AFF_FLAGGED(ch, AFF_COUNTER_ATT)) {
if ((GET_ASTRAL(vict) > 0) && (attack_success < 0)
&& FIGHTING(vict) == ch && GET_POS(vict) <= POS_SLEEPING) {
send_to_char(ch, "%s counters your attack!\r\n", GET_NAME(vict));
send_to_char(vict, "You counter %s's attack!\r\n", GET_NAME(ch));
AFF_FLAGS(vict).SetBit(AFF_COUNTER_ATT);
astral_fight(vict, ch);
}
return;
} else {
AFF_FLAGS(ch).RemoveBit(AFF_COUNTER_ATT);
return;
}
} else if (AFF_FLAGGED(ch, AFF_COUNTER_ATT))
AFF_FLAGS(ch).RemoveBit(AFF_COUNTER_ATT);
attack_success -= success_test(GET_BOD(vict) + GET_BODY(vict), power);
dam = convert_damage(stage(attack_success, dam));
if (IS_PROJECT(ch) && PLR_FLAGGED(ch->desc->original, PLR_KILLER))
dam = 0;
damage(ch, vict, dam, w_type, is_physical);
if (IS_PROJECT(vict) && dam > 0)
damage(vict->desc->original, vict->desc->original, dam, 0, is_physical);
}
void remove_throwing(struct char_data *ch)
{
struct obj_data *obj = NULL;
int i, pos, type;
for (pos = WEAR_WIELD; pos <= WEAR_HOLD; pos++)
if (GET_EQ(ch, pos))
{
type = GET_OBJ_VAL(GET_EQ(ch, pos), 3);
if (type == TYPE_SHURIKEN || type == TYPE_THROWING_KNIFE) {
extract_obj(unequip_char(ch, pos, TRUE));
for (i = 0; i < NUM_WEARS; i++)
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_QUIVER)
for (obj = GET_EQ(ch, i)->contains; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_WEAPON && GET_OBJ_VAL(obj, 3) == type) {
obj_from_obj(obj);
equip_char(ch, obj, WEAR_WIELD);
return;
}
return;
}
}
}
void hit(struct char_data *ch, struct char_data *victim, struct obj_data *weapon, struct obj_data *vict_weapon)
{
char rbuf[MAX_STRING_LENGTH];
int type, vtype;
struct veh_data *veh = NULL;
struct obj_data *clip = NULL;
bool is_physical = TRUE, v_is_physical = TRUE, melee = FALSE, vtall = TRUE, ctall = TRUE;
int tdistance = 0, recoil = 0, tdualwield = 0, burst = 0, tawake = 0, tsmartlink = 0, tsight = 0, tsleep = 0, tcansee = 0;
int power = 0, damage_total = 0, base_target = 0, skill_total = 0, recoilcomp = 0, modtarget = 0, success = 0;
if (!AWAKE(ch) || GET_QUI(ch) <= 0 || (weapon && GET_OBJ_TYPE(weapon) != ITEM_WEAPON))
return;
if (IS_ASTRAL(victim)) {
if (IS_DUAL(ch) || IS_ASTRAL(ch))
astral_fight(ch, victim);
return;
}
if (!ROOM_FLAGGED(victim->in_room, ROOM_INDOORS) || (ROOM_FLAGGED(victim->in_room, ROOM_INDOORS) && (float)(GET_HEIGHT(victim) / 100) < world[victim->in_room].z))
vtall = FALSE;
if (!ROOM_FLAGGED(ch->in_room, ROOM_INDOORS) || (ROOM_FLAGGED(ch->in_room, ROOM_INDOORS) && (float)(GET_HEIGHT(ch) / 100) < world[ch->in_room].z))
ctall = FALSE;
if (IS_NERVE(ch) && !weapon)
{
int total = 4 + GET_IMPACT(victim);
skill_total = get_skill(ch, SKILL_UNARMED_COMBAT, total) + MIN(GET_OFFENSE(ch), GET_SKILL(ch, SKILL_UNARMED_COMBAT)) + modify_target(ch);
if (GET_QUI(victim) <= 0)
success = 0;
else success = success_test(skill_total, total);
if (success > 0) {
GET_TEMP_QUI_LOSS(victim) += success * 2;
affect_total(victim);
if (GET_QUI(victim) <= 0) {
act("You hit $N's pressure points succesfully, $e is paralyzed!", FALSE, ch, 0, victim, TO_CHAR);
act("As $n hits you, you feel your body freeze up!", FALSE, ch, 0, victim, TO_VICT);
act("$N freezes as $n's attack lands successfully!", FALSE, ch, 0, victim, TO_NOTVICT);
} else {
act("You hit $N's pressure points succesfully, $e seems to slow down!", FALSE, ch, 0, victim, TO_CHAR);
act("$n's blows seem to bring great pain and you find yourself moving slower!", FALSE, ch, 0, victim, TO_VICT);
act("$n's attack hits $N, who seems to move slower afterwards.", FALSE, ch, 0, victim, TO_NOTVICT);
}
} else {
act("You fail to hit any of the needed pressure points on $N.", FALSE, ch, 0, victim, TO_CHAR);
act("$n fails to land any blows on you.", FALSE, ch, 0, victim, TO_VICT);
act("$n's unarmed attack misses $N completely.", TRUE, ch, 0, victim, TO_NOTVICT);
}
return;
}
RIG_VEH(ch, veh);
if (weapon)
type = GET_OBJ_VAL(weapon, 3);
else
type = TYPE_HIT;
if (!IS_GUN(type))
melee = TRUE;
else {
if (GET_RACE(ch) == RACE_CYCLOPS)
tdistance += 2;
if (!has_ammo(ch, weapon))
return;
clip = weapon->contains;
}
if ((type == TYPE_HIT || type == TYPE_BLUDGEON || type == TYPE_PUNCH ||
type == TYPE_TASER || type == TYPE_CRUSH || type == TYPE_POUND))
is_physical = FALSE;
if (melee) {
if (ch->in_room != victim->in_room) {
stop_fighting(ch);
return;
}
if (vict_weapon)
vtype = GET_OBJ_VAL(vict_weapon, 3);
else
vtype = TYPE_HIT;
if (IS_GUN(vtype))
vtype = TYPE_BLUDGEON;
if ((vtype == TYPE_HIT || vtype == TYPE_BLUDGEON || vtype == TYPE_PUNCH ||
vtype == TYPE_TASER || vtype == TYPE_CRUSH || vtype == TYPE_POUND))
v_is_physical = FALSE;
} else {
if (type == TYPE_MACHINE_GUN)
if (!IS_NPC(ch) && !clip) {
if (GET_OBJ_VAL(weapon, 6) >= 2) {
burst = 3;
GET_OBJ_VAL(weapon, 6) -= 2;
} else if (GET_OBJ_VAL(weapon, 6) == 1) {
burst = 2;
GET_OBJ_VAL(weapon, 6)--;
}
} else if (clip) {
if (GET_OBJ_VAL(clip, 9) >= 2) {
burst = 3;
GET_OBJ_VAL(clip, 9) -= 2;
} else if (GET_OBJ_VAL(clip, 9) == 1) {
burst = 2;
GET_OBJ_VAL(clip, 9)--;
}
}
if (GET_OBJ_VAL(weapon, 4) == SKILL_ASSAULT_CANNON ||
GET_OBJ_VAL(weapon, 4) == SKILL_MACHINE_GUNS)
burst *= 2;
recoil = MAX(0, burst - (recoilcomp = check_recoil(ch, weapon)));
if (veh) {
if (AFF_FLAGGED(ch, AFF_MANNING) || AFF_FLAGGED(ch, AFF_RIG))
recoil = MAX(0, recoil - 2);
else if (get_speed(veh) > 0) {
if (get_speed(veh) < 60)
recoil++;
else if (get_speed(veh) < 120)
recoil += 2;
else if (get_speed(veh) < 200)
recoil += 3;
else
recoil += 4;
}
}
if (GET_EQ(ch, WEAR_WIELD) && GET_EQ(ch, WEAR_HOLD))
tdualwield += 2;
else tsmartlink -= check_smartlink(ch, weapon);
if (IS_OBJ_STAT(weapon, ITEM_SNIPER) && ch->in_room == victim->in_room)
tdistance += 6;
if (!AWAKE(victim))
tawake -= 2;
if (ch->in_room != victim->in_room && !veh) {
struct char_data *vict;
bool vict_found = FALSE;
int dir, range, distance;
long room, nextroom;
if (weapon && IS_RANGED(weapon)) {
range = MIN(find_sight(ch), find_weapon_range(ch, weapon));
for (dir = 0; dir < NUM_OF_DIRS && !vict_found; dir++) {
room = ch->in_room;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
for (distance = 1; (nextroom != NOWHERE) && (distance <= range) &&
!vict_found; distance++) {
for (vict = world[nextroom].people; vict;
vict = vict->next_in_room)
if (vict == victim) {
tdistance += 2 * distance;
vict_found = TRUE;
break;
}
room = nextroom;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
}
}
}
if (!vict_found) {
stop_fighting(ch);
return;
}
}
}
if (!CAN_SEE(ch, victim) && !(ch->in_veh || PLR_FLAGGED(ch, PLR_REMOTE) || AFF_FLAGGED(ch, AFF_MANNING))) {
tsight = 8;
if (AFF_FLAGGED(ch, AFF_DETECT_INVIS) || GET_POWER(ch, ADEPT_BLIND_FIGHTING))
tsight /= 2;
}
sprintf( rbuf, "%s", GET_CHAR_NAME( ch ) );
rbuf[3] = 0;
sprintf( rbuf+strlen(rbuf), "|%s", GET_CHAR_NAME( victim ) );
rbuf[7] = 0;
sprintf( rbuf+strlen(rbuf),
">Targ: (b/r %d-%d) ",
burst, recoilcomp );
modtarget = modify_target_rbuf(ch, rbuf);
buf_mod( rbuf, "Recoil", recoil);
buf_mod( rbuf, "Sleep", tsleep);
buf_mod( rbuf, "Cansee", tcansee);
buf_mod( rbuf, "2Weap", tdualwield);
buf_mod( rbuf, "Smart", tsmartlink);
buf_mod( rbuf, "Distance", tdistance);
buf_mod( rbuf, "Sight", tsight);
buf_mod( rbuf, "Awake", tawake);
base_target = 4 + modtarget + recoil + tsleep + tcansee
+ tdualwield + tsmartlink + tdistance + tsight + tawake;
buf_roll( rbuf, "Total", base_target);
act( rbuf, 1, ch, NULL, NULL, TO_ROLLS );
if (melee) {
int reach = GET_REACH(victim) - GET_REACH(ch);
int victtarget = 4 + modify_target(victim) + (CAN_SEE(victim, ch) ? 0 :
((AFF_FLAGGED(victim, AFF_DETECT_INVIS) || GET_POWER(victim, ADEPT_BLIND_FIGHTING)) ? 4 : 8)) - (reach > 0 ?
reach : 0);
int vict_skill = SKILL_UNARMED_COMBAT;
if (IS_SPIRIT(victim) || IS_ELEMENTAL(victim)) {
skill_total = GET_WIL(ch);
vict_skill = GET_REA(victim);
} else if (IS_SPIRIT(ch) || IS_ELEMENTAL(ch)) {
skill_total = GET_REA(ch);
vict_skill = GET_WIL(victim);
} else {
if (vict_weapon) {
if (IS_GUN(GET_OBJ_VAL(vict_weapon, 3)))
vict_skill = SKILL_CLUBS;
else vict_skill = GET_OBJ_VAL(vict_weapon, 4);
}
vict_skill = get_skill(victim, vict_skill, victtarget) + (vtall ? 0 : MIN(GET_SKILL(victim, vict_skill), GET_OFFENSE(victim)));
int skillnum = SKILL_UNARMED_COMBAT;
if (AFF_FLAGGED(ch, AFF_MANNING) || PLR_FLAGGED(ch, PLR_REMOTE) || AFF_FLAGGED(ch, AFF_RIG))
skillnum = SKILL_GUNNERY;
else if (weapon)
skillnum = GET_OBJ_VAL(weapon, 4);
skill_total = get_skill(ch, skillnum, base_target) +
MIN(GET_SKILL(ch, skillnum), GET_OFFENSE(ch));
}
if (reach < 0)
base_target += reach;
if (AWAKE(victim))
success = success_test(skill_total, base_target) - success_test(vict_skill, victtarget);
else success = MAX(1, success_test(skill_total, base_target));
act("$n clashes with $N in melee combat.", FALSE, ch, 0, victim, TO_ROOM);
act("You clash with $N in melee combat.", FALSE, ch, 0, victim, TO_CHAR);
sprintf(rbuf, "%s> sk %d targ %d\r\n"
"%s> sk %d targ %d\r\n Reach %c%d Success %d", GET_CHAR_NAME(ch), skill_total, base_target,
GET_CHAR_NAME(victim), vict_skill, victtarget, reach > 0 ? 'b' : 't', reach < 0 ? -reach : reach, success);
act( rbuf, 1, ch, NULL, NULL, TO_ROLLS );
if (success < 0) {
weapon = vict_weapon;
type = vtype;
struct char_data *temp = ch;
ch = victim;
victim = temp;
bool ttall = vtall;
vtall = ctall;
ctall = ttall;
success *= -1;
}
} else {
skill_total = get_skill(ch, GET_OBJ_VAL(weapon, 4), base_target) + (ctall ? 0 : MIN(GET_SKILL(ch, GET_OBJ_VAL(weapon, 4)), GET_OFFENSE(ch)));
success = success_test(skill_total, base_target);
int total = 0;
if (GET_TOTALBAL(victim) > GET_QUI(victim))
total += GET_TOTALBAL(victim) - GET_QUI(victim);
if (GET_TOTALIMP(victim) > GET_QUI(victim))
total += GET_TOTALIMP(victim) - GET_QUI(victim);
int anchor = 0;
for (struct obj_data *cyber = ch->cyberware; cyber; cyber = cyber->next_content)
if (GET_OBJ_VAL(cyber, 0) == CYB_FOOTANCHOR && !GET_OBJ_VAL(cyber, 9))
anchor++;
if (AWAKE(victim) && total < GET_QUI(victim) && !vtall)
success -= success_test(GET_DEFENSE(victim) + (GET_DEFENSE(victim) ? GET_POWER(victim, ADEPT_SIDESTEP) : 0), 4 + damage_modifier(victim, buf) + (burst == 3 ? 1 : 0) + anchor);
else
success = MAX(success, 1);
if (success < 1) {
damage(ch, victim, -1, type, 0);
return;
}
}
if (weapon) {
power = (IS_GUN(type) ? GET_OBJ_VAL(weapon, 0) : GET_OBJ_VAL(weapon, 2) + GET_STR(ch)) + burst;
if (IS_GUN(type)) {
if (clip)
switch (GET_OBJ_VAL(clip, 2)) {
case AMMO_APDS:
power -= (int)(GET_BALLISTIC(victim) / 2);
break;
case AMMO_EX:
power++;
case AMMO_EXPLOSIVE:
power -= GET_BALLISTIC(victim) - 1;
break;
case AMMO_FLECHETTE:
if (!GET_IMPACT(victim) && !GET_BALLISTIC(victim))
damage_total++;
else
power -= MAX(GET_BALLISTIC(victim), GET_IMPACT(victim) * 2);
break;
case AMMO_GEL:
power -= GET_BALLISTIC(victim) + 2;
break;
default:
power -= GET_BALLISTIC(victim);
}
else
power -= GET_BALLISTIC(victim);
} else power -= GET_IMPACT(ch);
damage_total = GET_OBJ_VAL(weapon, 1) + (burst == 3 ? 1 : 0);
} else {
power = GET_STR(ch);
if (GET_POWER(ch, ADEPT_PENETRATINGSTRIKE) && !GET_POWER(ch, ADEPT_DISTANCE_STRIKE))
power -= MAX(0, GET_IMPACT(victim) - GET_POWER(ch, ADEPT_PENETRATINGSTRIKE));
else power -= GET_IMPACT(victim);
if (GET_POWER(ch, ADEPT_KILLING_HANDS)) {
damage_total = GET_POWER(ch, ADEPT_KILLING_HANDS);
is_physical = TRUE;
} else {
for (struct obj_data *obj = ch->cyberware;
obj && !damage_total;
obj = obj->next_content)
if (!GET_OBJ_VAL(obj, 9))
switch (GET_OBJ_VAL(obj, 0)) {
case CYB_HANDBLADE:
damage_total = LIGHT;
power += 3;
type = TYPE_STAB;
is_physical = TRUE;
break;
case CYB_HANDRAZOR:
damage_total = LIGHT;
is_physical = TRUE;
type = TYPE_SLASH;
if (IS_SET(GET_OBJ_VAL(obj, 3), CYBERWEAPON_IMPROVED))
power += 2;
break;
case CYB_FIN:
damage_total = LIGHT;
is_physical = TRUE;
type = TYPE_SLASH;
power--;
break;
case CYB_FOOTANCHOR:
damage_total = MODERATE;
is_physical = TRUE;
type = TYPE_STAB;
power--;
break;
case CYB_HANDSPUR:
is_physical = TRUE;
type = TYPE_SLASH;
damage_total = MODERATE;
break;
}
else if (GET_OBJ_VAL(obj, 0) == CYB_BONELACING) {
switch (GET_OBJ_VAL(obj, 3)) {
case BONE_PLASTIC:
power += 2;
break;
case BONE_ALUMINIUM:
case BONE_CERAMIC:
power += 3;
break;
case BONE_TITANIUM:
power += 4;
break;
}
damage_total = MODERATE;
break;
}
}
if (!damage_total)
damage_total = MODERATE;
}
int bod_success=0, bod = GET_BOD(victim) + (vtall ? 0 : GET_BODY(victim));
if (IS_SPIRIT(ch) && GET_MAG(victim) > 0 && GET_SKILL(victim, SKILL_CONJURING))
bod_success = success_test(MAX(bod, GET_SKILL(victim, SKILL_CONJURING)), power);
else if (!AWAKE(victim))
bod_success = 0;
else
bod_success = success_test(bod, power);
success -= bod_success;
int old_damage_total = damage_total;
int staged_damage = stage(success, damage_total);
damage_total = convert_damage(staged_damage);
sprintf(rbuf, "Fight: Bod %d+%d, Pow %d, Suc %d. %s(%d)->%d. %d%c.",
GET_BOD(victim), (vtall ? 0 : GET_BODY(victim)), power, bod_success,
wound_name[old_damage_total], success, staged_damage, damage_total, is_physical ? 'P' : 'M');
act( rbuf, 1, ch, NULL, NULL, TO_ROLLS );
damage(ch, victim, damage_total, type, is_physical);
if (weapon && GET_OBJ_VAL(weapon, 4) >= SKILL_MACHINE_GUNS && GET_OBJ_VAL(weapon, 4) <= SKILL_ASSAULT_CANNON &&
!(PLR_FLAGGED(ch, PLR_REMOTE) || AFF_FLAGGED(ch, AFF_RIG) || AFF_FLAGGED(ch, AFF_MANNING)))
{
for (int i = 0; i < (NUM_WEARS - 1); i++)
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_GYRO)
return;
damage(ch, ch, convert_damage(stage(-success_test(GET_BOD(ch) + GET_BODY(ch), GET_OBJ_VAL(weapon, 0) / 2 + modify_target(ch)), LIGHT))
, TYPE_HIT, FALSE);
}
if (ch->in_room && !world[ch->in_room].background[0]) {
world[ch->in_room].background[0] = 1;
world[ch->in_room].background[1] = AURA_PLAYERCOMBAT;
}
}
int find_sight(struct char_data *ch)
{
int sight;
if ((!IS_NPC(ch) && access_level(ch, LVL_VICEPRES)) || AFF_FLAGGED(ch, AFF_VISION_MAG_3))
sight = 4;
else if (AFF_FLAGGED(ch, AFF_VISION_MAG_2))
sight = 3;
else if (AFF_FLAGGED(ch, AFF_VISION_MAG_1))
sight = 2;
else
sight = 1;
/* add more weather conditions here to affect scan */
if (SECT(ch->in_room) != SPIRIT_HEARTH && (IS_NPC(ch) || !access_level(ch, LVL_VICEPRES)))
switch (weather_info.sky)
{
case SKY_RAINING:
sight -= 1;
break;
case SKY_LIGHTNING:
sight -= 2;
break;
}
sight = MIN(4, MAX(1, sight));
return sight;
}
int find_weapon_range(struct char_data *ch, struct obj_data *weapon)
{
int temp;
if ( weapon == NULL )
return 0;
if (GET_OBJ_TYPE(weapon) == ITEM_FIREWEAPON)
{
temp = MIN(MAX(1, ((int)(GET_STR(ch)/3))), 4);
return temp;
}
switch(GET_OBJ_VAL(weapon, 3))
{
case TYPE_SHURIKEN:
case TYPE_THROWING_KNIFE:
case TYPE_HAND_GRENADE:
case TYPE_PISTOL:
case TYPE_SHOTGUN:
case TYPE_BLAST:
return 1;
case TYPE_GRENADE_LAUNCHER:
case TYPE_BIFURCATE:
return 2;
case TYPE_RIFLE:
case TYPE_MACHINE_GUN:
return 3;
case TYPE_CANNON:
case TYPE_ROCKET:
return 4;
default:
return 0;
}
}
void ranged_response(struct char_data *ch, struct char_data *vict)
{
int range, sight, distance, dir, found = 0;
long room, nextroom = NOWHERE;
struct char_data *temp;
if (!vict || ch->in_room == vict->in_room ||
GET_POS(vict) <= POS_STUNNED || vict->in_room == NOWHERE)
return;
if (IS_NPC(vict) && (MOB_FLAGGED(vict, MOB_INANIMATE) || MOB_FLAGGED(vict, MOB_NOKILL)))
return;
if (GET_POS(vict) < POS_FIGHTING)
GET_POS(vict) = POS_STANDING;
if (MOB_FLAGGED(vict, MOB_WIMPY))
do_flee(vict, "", 0, 0);
else if (RANGE_OK(vict) && !FIGHTING(vict))
{
sight = find_sight(vict);
range = find_weapon_range(vict, GET_EQ(vict, WEAR_WIELD));
for (dir = 0; dir < NUM_OF_DIRS && !found; dir++) {
room = vict->in_room;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
for (distance = 1; !found && ((nextroom != NOWHERE) && (distance <= 4)); distance++) {
for (temp = world[nextroom].people; !found && temp; temp = temp->next_in_room)
if (temp == ch && (distance > range || distance > sight)) {
act("$n runs after $s distant attacker.", TRUE, vict, 0, 0, TO_ROOM);
act("You charge after $N.", FALSE, vict, 0, ch, TO_CHAR);
char_from_room(vict);
char_to_room(vict, EXIT2(room, rev_dir[dir])->to_room);
set_fighting(vict, ch);
found = 1;
if (vict->in_room == ch->in_room) {
act("$n arrives in a rush of fury, immediately attacking $N!",
TRUE, vict, 0, ch, TO_NOTVICT);
act("$n arrives in a rush of fury, rushing straight towards you!",
FALSE, vict, 0, ch, TO_VICT);
}
}
room = nextroom;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
}
}
if (!found)
set_fighting(vict, ch);
} else if (!FIGHTING(vict))
{
for (dir = 0; dir < NUM_OF_DIRS && !found; dir++) {
if (CAN_GO2(vict->in_room, dir) && EXIT2(vict->in_room, dir)->to_room == ch->in_room) {
act("$n runs after $s distant attacker.", TRUE, vict, 0, 0, TO_ROOM);
act("You charge after $N.", FALSE, vict, 0, ch, TO_CHAR);
char_from_room(vict);
char_to_room(vict, ch->in_room);
set_fighting(vict, ch);
act("$n arrives in a rush of fury, immediately attacking $N!", TRUE, vict, 0, ch, TO_NOTVICT);
act("$n arrives in a rush of fury, rushing straight towards you!", FALSE, vict, 0, ch, TO_VICT);
}
}
}
return;
}
void explode(struct char_data *ch, struct obj_data *weapon, int room)
{
int damage_total, i, power, level;
struct char_data *victim, *next_vict;
struct obj_data *obj, *next;
power = GET_OBJ_VAL(weapon, 0);
level = GET_OBJ_VAL(weapon, 1);
extract_obj(weapon);
if (world[room].people)
{
act("The room is lit by an explosion!", FALSE, world[room].people, 0, 0, TO_ROOM);
act("The room is lit by an explosion!", FALSE, world[room].people, 0, 0, TO_CHAR);
}
for (obj = world[room].contents; obj; obj = next)
{
next = obj->next_content;
damage_obj(NULL, obj, level * 2 + (int)(power / 6), DAMOBJ_EXPLODE);
}
for (victim = world[room].people; victim; victim = next_vict)
{
next_vict = victim->next_in_room;
if (IS_ASTRAL(victim))
continue;
act("You are hit by the flames!", FALSE, victim, 0, 0, TO_CHAR);
for (obj = victim->carrying; obj; obj = next) {
next = obj->next_content;
if (number(1, 100) < 50)
damage_obj(NULL, obj, level * 2 + (int)(power / 6), DAMOBJ_EXPLODE);
}
for (i = 0; i < (NUM_WEARS - 1); i++)
if (GET_EQ(victim, i) && number(1, 100) < 100)
damage_obj(NULL, GET_EQ(victim, i), level * 2 + (int)(power / 6),
DAMOBJ_EXPLODE);
if (IS_NPC(victim) && !FIGHTING(victim)) {
GET_DEFENSE(victim) = GET_COMBAT(victim);
GET_OFFENSE(victim) = 0;
}
damage_total =
convert_damage(stage((number(1, 3) - success_test(GET_BOD(victim) +
GET_BODY(victim), MAX(2, (power -
(int)(GET_IMPACT(victim) / 2))) + modify_target(victim))),
level));
if (!ch)
damage(victim, victim, damage_total, TYPE_EXPLOSION, PHYSICAL);
else
damage(ch, victim, damage_total, TYPE_EXPLOSION, PHYSICAL);
}
for (i = 0; i < NUM_OF_DIRS; i++)
if (world[room].dir_option[i] && IS_SET(world[room].dir_option[i]->exit_info, EX_CLOSED))
damage_door(NULL, room, i, level * 2 + (int)(power / 6), DAMOBJ_EXPLODE);
}
void target_explode(struct char_data *ch, struct obj_data *weapon, int room, int mode)
{
int damage_total, i;
struct char_data *victim, *next_vict;
struct obj_data *obj, *next;
sprintf(buf, "The room is lit by a%s explosion!",
(GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET ? " massive" : "n"));
if (world[room].people)
{
act(buf, FALSE, world[room].people, 0, 0, TO_ROOM);
act(buf, FALSE, world[room].people, 0, 0, TO_CHAR);
}
for (obj = world[room].contents; obj; obj = next)
{
next = obj->next_content;
damage_obj(NULL, obj, GET_OBJ_VAL(weapon, 1) * 2 +
(int)(GET_OBJ_VAL(weapon, 0) / 6), DAMOBJ_EXPLODE);
}
for (victim = world[room].people; victim; victim = next_vict)
{
next_vict = victim->next_in_room;
if (IS_ASTRAL(victim))
continue;
act("You are hit by the flames!", FALSE, victim, 0, 0, TO_CHAR);
for (obj = victim->carrying; obj; obj = next) {
next = obj->next_content;
if (number(1, 100) < 50)
damage_obj(NULL, obj, GET_OBJ_VAL(weapon, 1) * 2 +
(int)(GET_OBJ_VAL(weapon, 0) / 6), DAMOBJ_EXPLODE);
}
for (i = 0; i < (NUM_WEARS - 1); i++)
if (GET_EQ(victim, i) && number(1, 100) < 100)
damage_obj(NULL, GET_EQ(victim, i), GET_OBJ_VAL(weapon, 1) * 2 +
(int)(GET_OBJ_VAL(weapon, 0) / 6), DAMOBJ_EXPLODE);
if (IS_NPC(victim) && !FIGHTING(victim)) {
GET_DEFENSE(victim) = GET_COMBAT(victim);
GET_OFFENSE(victim) = 0;
}
if (!mode) {
if (GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET)
damage_total = convert_damage(stage((number(3,6) - success_test(GET_BOD(victim) + GET_BODY(victim),
MAX(2, (GET_OBJ_VAL(weapon, 0) - (int)(GET_IMPACT(victim) / 2))) +
modify_target(victim))), GET_OBJ_VAL(weapon, 1)));
else
damage_total = convert_damage(stage((number(2,5) - success_test(GET_BOD(victim) + GET_BODY(victim),
MAX(2, (GET_OBJ_VAL(weapon, 0) - (int)(GET_IMPACT(victim) / 2))) +
modify_target(victim))), GET_OBJ_VAL(weapon, 1)));
} else
damage_total = convert_damage(stage((number(2,5) - success_test(GET_BOD(victim) + GET_BODY(victim),
MAX(2, (GET_OBJ_VAL(weapon, 0) - 4 - (int)(GET_IMPACT(victim) / 2))) +
modify_target(victim))), GET_OBJ_VAL(weapon, 1) - 1));
damage(ch, victim, damage_total, TYPE_EXPLOSION, PHYSICAL);
}
if (!mode)
for (i = 0; i < NUM_OF_DIRS; i++)
if (world[room].dir_option[i] &&
IS_SET(world[room].dir_option[i]->exit_info, EX_CLOSED))
damage_door(NULL, room, i, GET_OBJ_VAL(weapon, 1) * 2 +
(int)(GET_OBJ_VAL(weapon, 0) / 6), DAMOBJ_EXPLODE);
}
void range_combat(struct char_data *ch, char *target, struct obj_data *weapon,
int range, int dir)
{
int room, nextroom, distance, sight, temp, temp2, left, right, scatter[4];
int power, level;
struct char_data *vict = NULL;
if (world[ch->in_room].peaceful)
{
send_to_char("This room just has a peaceful, easy feeling...\r\n", ch);
return;
}
sight = find_sight(ch);
if (CAN_GO2(ch->in_room, dir))
nextroom = EXIT2(ch->in_room, dir)->to_room;
else
nextroom = NOWHERE;
if (GET_OBJ_TYPE(weapon) == ITEM_WEAPON && GET_OBJ_VAL(weapon, 3) == TYPE_HAND_GRENADE)
{
if (nextroom == NOWHERE) {
send_to_char("There seems to be something in the way...\r\n", ch);
return;
}
if (world[nextroom].peaceful) {
send_to_char("Nah - leave them in peace.\r\n", ch);
return;
}
power = GET_OBJ_VAL(weapon, 0);
level = GET_OBJ_VAL(weapon, 1);
if (FIGHTING(ch))
stop_fighting(ch);
act("You pull the pin and throw $p!", FALSE, ch, weapon, 0, TO_CHAR);
act("$n pulls the pin and throws $p!", FALSE, ch, weapon, 0, TO_ROOM);
WAIT_STATE(ch, PULSE_VIOLENCE);
temp = MAX(1, GET_SKILL(ch, SKILL_THROWING_WEAPONS));
if (!number(0, 2)) {
sprintf(buf, "A defective grenade lands on the floor.\r\n");
if (world[nextroom].people) {
act(buf, FALSE, world[nextroom].people, 0, 0, TO_ROOM);
act(buf, FALSE, world[nextroom].people, 0, 0, TO_CHAR);
}
return;
} else if (!success_test(temp+GET_OFFENSE(ch), 5) < 2) {
left = -1;
right = -1;
if (dir < UP) {
if ((dir - 1) < NORTH)
left = NORTHWEST;
else
left = dir - 1;
if ((dir + 1) > NORTHWEST)
right = NORTH;
else
right = dir + 1;
}
scatter[0] = ch->in_room;
if (left > 0 && CAN_GO(ch, left))
scatter[1] = EXIT(ch, left)->to_room;
else
scatter[1] = NOWHERE;
if (right > 0 && CAN_GO(ch, right))
scatter[2] = EXIT(ch, right)->to_room;
else
scatter[2] = NOWHERE;
if (CAN_GO2(nextroom, dir))
scatter[3] = EXIT2(nextroom, dir)->to_room;
else
scatter[3] = NOWHERE;
for (temp = 0, temp2 = 0; temp2 < 4; temp2++)
if (scatter[temp2] != NOWHERE)
temp++;
for (temp2 = 0; temp2 < 4; temp2++)
if (scatter[temp2] != NOWHERE && !number(0, temp-1)) {
if (temp2 == 0) {
act("$p deflects due to $n's poor accuracy, landing at $s feet.",
FALSE, ch, weapon, 0, TO_ROOM);
sprintf(buf, "Your realize your aim must've been off-target as "
"$p lands at your feet.");
} else if (temp2 == 3)
sprintf(buf, "Your aim is slightly off, going past its target.");
else
sprintf(buf, "Your aim is slightly off, and $p veers to the %s.",
dirs[temp2 == 1 ? left : right]);
act(buf, FALSE, ch, weapon, 0, TO_CHAR);
explode(ch, weapon, scatter[temp2]);
return;
}
}
explode(ch, weapon, nextroom);
return;
}
for (distance = 1; ((nextroom != NOWHERE) && (distance <= sight)); distance++)
{
if ((vict = get_char_room(target, nextroom)) && vict != ch &&
CAN_SEE(ch, vict))
break;
vict = NULL;
room = nextroom;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
}
if (vict)
{
if (vict == FIGHTING(ch)) {
send_to_char("You're doing the best you can!\r\n", ch);
return;
} else if (world[vict->in_room].peaceful) {
send_to_char("Nah - leave them in peace.\r\n", ch);
return;
} else if (distance > range) {
act("$N seems to be out of $p's range.", FALSE, ch, weapon, vict, TO_CHAR);
return;
} else if (mob_index[GET_MOB_RNUM(vict)].func == shop_keeper) {
send_to_char("Maybe that's not such a good idea.\r\n", ch);
return;
}
if (GET_OBJ_TYPE(weapon) == ITEM_FIREWEAPON) {
act("$n draws $p and fires into the distance!", TRUE, ch, weapon, 0, TO_ROOM);
act("You draw $p, aim it at $N and fire!", FALSE, ch, weapon, vict, TO_CHAR);
check_killer(ch, vict);
if (IS_NPC(vict) && !IS_PROJECT(vict) && !FIGHTING(vict)) {
GET_DEFENSE(vict) = GET_COMBAT(vict);
GET_OFFENSE(vict) = 0;
}
if (FIGHTING(ch))
stop_fighting(ch);
hit(ch, vict, (GET_EQ(ch, WEAR_WIELD) ? GET_EQ(ch, WEAR_WIELD) : GET_EQ(ch, WEAR_HOLD)), (GET_EQ(vict, WEAR_WIELD) ? GET_EQ(vict, WEAR_WIELD) : GET_EQ(vict, WEAR_HOLD)));
WAIT_STATE(ch, 2 * PULSE_VIOLENCE);
return;
}
switch(GET_OBJ_VAL(weapon, 3)) {
case TYPE_SHURIKEN:
case TYPE_THROWING_KNIFE:
act("$n throws $p at something in the distance!", TRUE, ch, weapon, 0, TO_ROOM);
act("You throw $p at $N!", FALSE, ch, weapon, vict, TO_CHAR);
break;
default:
act("$n aims $p and fires into the distance!", TRUE, ch, weapon, 0, TO_ROOM);
act("You aim $p at $N and fire!", FALSE, ch, weapon, vict, TO_CHAR);
break;
}
if (GET_OBJ_VAL(weapon, 3) >= TYPE_PISTOL
|| GET_OBJ_VAL(weapon, 3) == TYPE_SHURIKEN
|| GET_OBJ_VAL(weapon, 3) == TYPE_THROWING_KNIFE) {
check_killer(ch, vict);
if (GET_OBJ_VAL(weapon, 3) < TYPE_PISTOL
|| GET_OBJ_VAL(weapon, 6) > 0) {
if (IS_NPC(vict) && !IS_PROJECT(vict) && !FIGHTING(vict)) {
GET_DEFENSE(vict) = GET_COMBAT(vict);
GET_OFFENSE(vict) = 0;
}
if (FIGHTING(ch))
stop_fighting(ch);
hit(ch, vict, (GET_EQ(ch, WEAR_WIELD) ? GET_EQ(ch, WEAR_WIELD) : GET_EQ(ch, WEAR_HOLD)), (GET_EQ(vict, WEAR_WIELD) ? GET_EQ(vict, WEAR_WIELD) : GET_EQ(vict, WEAR_HOLD)));
ranged_response(ch, vict);
} else
send_to_char("*Click*\r\n", ch);
WAIT_STATE(ch, 2 * PULSE_VIOLENCE);
} else {
if (!has_ammo(ch, weapon))
return;
stop_fighting(ch);
if (GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET) {
if (!GET_SKILL(ch, SKILL_MISSILE_LAUNCHERS))
temp = MAX(1, GET_SKILL(ch, SKILL_GUNNERY));
else
temp = GET_SKILL(ch, SKILL_MISSILE_LAUNCHERS);
} else {
if (!GET_SKILL(ch, SKILL_GRENADE_LAUNCHERS))
temp = MAX(1, GET_SKILL(ch, SKILL_FIREARMS));
else
temp = GET_SKILL(ch, SKILL_GRENADE_LAUNCHERS);
}
WAIT_STATE(ch, 2 * PULSE_VIOLENCE);
if (!number(0,49)) {
sprintf(buf, "A defective %s lands on the floor.",
(GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET ? "rocket" : "grenade"));
act(buf, TRUE, vict, 0, 0, TO_ROOM);
act(buf, TRUE, vict, 0, 0, TO_CHAR);
return;
} else if (!success_test(temp + GET_OFFENSE(ch), 6)) {
left = -1;
right = -1;
if (dir < UP) {
if ((dir - 1) < NORTH)
left = NORTHWEST;
else
left = dir - 1;
if ((dir + 1) > NORTHWEST)
right = NORTH;
else
right = dir + 1;
}
scatter[0] = ch->in_room;
if (left > 0 && CAN_GO(ch, left))
scatter[1] = EXIT(ch, left)->to_room;
else
scatter[1] = NOWHERE;
if (right > 0 && CAN_GO(ch, right))
scatter[2] = EXIT(ch, right)->to_room;
else
scatter[2] = NOWHERE;
if (CAN_GO2(nextroom, dir))
scatter[3] = EXIT2(nextroom, dir)->to_room;
else
scatter[3] = NOWHERE;
for (temp = 0, temp2 = 0; temp2 < 4; temp2++)
if (scatter[temp2] != NOWHERE)
temp++;
for (temp2 = 0; temp2 < 4; temp2++)
if (scatter[temp2] != NOWHERE && !number(0, temp-1)) {
if (temp2 == 0) {
act("$p's trajectory is slightly off...", FALSE, ch, weapon, 0, TO_ROOM);
sprintf(buf, "Your arm jerks just before you fire...");
} else if (temp2 == 3)
sprintf(buf, "Your aim is slightly off, going past $N.");
else
sprintf(buf, "Your aim is slightly off, the %s veering to the %s.",
(GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET ? "rocket" : "grenade"),
dirs[temp2 == 1 ? left : right]);
act(buf, FALSE, ch, weapon, vict, TO_CHAR);
target_explode(ch, weapon, scatter[temp2], 0);
if (GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET)
for (temp = 0; temp < NUM_OF_DIRS; temp++)
if (CAN_GO2(scatter[temp2], temp))
target_explode(ch, weapon, EXIT2(scatter[temp2], temp)->to_room, 1);
return;
}
}
temp2 = vict->in_room;
target_explode(ch, weapon, vict->in_room, 0);
if (GET_OBJ_VAL(weapon, 3) == TYPE_ROCKET)
for (temp = 0; temp < NUM_OF_DIRS; temp++)
if (CAN_GO2(temp2, temp))
target_explode(ch, weapon, EXIT2(temp2, temp)->to_room, 1);
}
return;
}
bool found = FALSE;
if (CAN_GO2(ch->in_room, dir))
nextroom = EXIT2(ch->in_room, dir)->to_room;
else
nextroom = NOWHERE;
// now we search for a door by the given name
for (distance = 1; nextroom != NOWHERE && distance <= sight; distance++)
{
if (EXIT2(nextroom, dir) && EXIT2(nextroom, dir)->keyword &&
isname(target, EXIT2(nextroom, dir)->keyword) &&
!IS_SET(EXIT2(nextroom, dir)->exit_info, EX_DESTROYED) &&
(PRF_FLAGGED(ch, PRF_HOLYLIGHT) || CURRENT_VISION(ch) == THERMOGRAPHIC ||
light_level(nextroom) <= LIGHT_NORMALNOLIT ||
((light_level(nextroom) == LIGHT_MINLIGHT || light_level(nextroom) == LIGHT_PARTLIGHT) &&
CURRENT_VISION(ch) == LOWLIGHT))) {
found = TRUE;
break;
}
room = nextroom;
if (CAN_GO2(room, dir))
nextroom = EXIT2(room, dir)->to_room;
else
nextroom = NOWHERE;
}
if (found)
{
if (FIGHTING(ch)) {
send_to_char("Maybe you'd better wait...\r\n", ch);
return;
} else if (!IS_SET(EXIT2(nextroom, dir)->exit_info, EX_CLOSED) && isname(target, EXIT2(nextroom, dir)->keyword) ) {
send_to_char("You can only damage closed doors!\r\n", ch);
return;
} else if (world[nextroom].peaceful) {
send_to_char("Nah - leave it in peace.\r\n", ch);
return;
} else if (distance > range) {
send_to_char(ch, "The %s seems to be out of %s's range.\r\n",
CAP(fname(EXIT2(nextroom, dir)->keyword)),
weapon->text.name);
return;
}
if (GET_OBJ_TYPE(weapon) == ITEM_FIREWEAPON) {
act("$n draws $p and fires into the distance!", TRUE, ch, weapon, 0, TO_ROOM);
sprintf(buf, "You draw $p, aim it at the %s and fire!",
fname(EXIT2(nextroom, dir)->keyword));
act(buf, FALSE, ch, weapon, vict, TO_CHAR);
} else {
switch(GET_OBJ_VAL(weapon, 3)) {
case TYPE_SHURIKEN:
case TYPE_THROWING_KNIFE:
act("$n throws $p at something in the distance!", TRUE, ch, weapon, 0, TO_ROOM);
sprintf(buf, "You throw $p at the %s!", fname(EXIT2(nextroom, dir)->keyword));
act(buf, FALSE, ch, weapon, vict, TO_CHAR);
break;
default:
act("$n aims $p and fires into the distance!", TRUE, ch, weapon, 0, TO_ROOM);
sprintf(buf, "You aim $p at the %s and fire!",
fname(EXIT2(nextroom, dir)->keyword));
act(buf, FALSE, ch, weapon, vict, TO_CHAR);
break;
}
if (GET_OBJ_VAL(weapon, 3) >= TYPE_PISTOL)
if (!has_ammo(ch, weapon))
return;
}
switch (GET_OBJ_VAL(weapon, 3)) {
case TYPE_SHURIKEN:
case TYPE_THROWING_KNIFE:
case TYPE_ARROW:
damage_door(ch, nextroom, dir, GET_OBJ_VAL(weapon, 0), DAMOBJ_PIERCE);
break;
case TYPE_GRENADE_LAUNCHER:
target_explode(ch, weapon, nextroom, 0);
break;
case TYPE_ROCKET:
target_explode(ch, weapon, nextroom, 0);
for (temp = 0; temp < NUM_OF_DIRS; temp++)
if (CAN_GO2(nextroom, temp))
target_explode(ch, weapon, EXIT2(nextroom, temp)->to_room, 1);
break;
default:
damage_door(ch, nextroom, dir, GET_OBJ_VAL(weapon, 0), DAMOBJ_PROJECTILE);
break;
}
WAIT_STATE(ch, 2 * PULSE_VIOLENCE);
return;
}
sprintf(buf, "You can't see any %s there.\r\n", target);
send_to_char(buf, ch);
return;
}
void roll_individual_initiative(struct char_data *ch)
{
if (AWAKE(ch))
{
if (AFF_FLAGGED(ch, AFF_PILOT))
GET_INIT_ROLL(ch) = dice(1, 6) + GET_REA(ch);
else
GET_INIT_ROLL(ch) = dice(1 + GET_INIT_DICE(ch), 6) + GET_REA(ch);
GET_INIT_ROLL(ch) -= damage_modifier(ch, buf);
if (AFF_FLAGGED(ch, AFF_ACTION)) {
GET_INIT_ROLL(ch) -= 10;
AFF_FLAGS(ch).RemoveBit(AFF_ACTION);
}
if (IS_SPIRIT(ch) || IS_ELEMENTAL(ch)) {
if (IS_DUAL(ch))
GET_INIT_ROLL(ch) += 10;
else
GET_INIT_ROLL(ch) += 20;
}
}
if (1)
{
char rbuf[MAX_STRING_LENGTH];
sprintf(rbuf,"Init: %2d %s",
GET_INIT_ROLL(ch), GET_NAME(ch));
act(rbuf,TRUE,ch,NULL,NULL,TO_ROLLS);
}
if (AFF_FLAGGED(ch, AFF_ACID))
AFF_FLAGS(ch).RemoveBit(AFF_ACID);
}
void decide_combat_pool(void)
{
struct char_data *ch;
for (ch = combat_list; ch; ch = ch->next_fighting) {
if (ch->bioware)
check_adrenaline(ch, 0);
if (IS_NPC(ch) && !IS_PROJECT(ch) && FIGHTING(ch)) {
if (GET_INIT_ROLL(ch) == GET_INIT_ROLL(FIGHTING(ch)))
GET_OFFENSE(ch) = GET_COMBAT(ch) >> 1;
else if (GET_INIT_ROLL(ch) > GET_INIT_ROLL(FIGHTING(ch)))
GET_OFFENSE(ch) = (int)(GET_COMBAT(ch) * .75);
else
GET_OFFENSE(ch) = (int)(GET_COMBAT(ch) / 4);
GET_DEFENSE(ch) = GET_COMBAT(ch) - GET_OFFENSE(ch);
if (GET_IMPACT(ch) > 6 || GET_BALLISTIC(ch) > 6) {
GET_BODY(ch) = (int)(GET_DEFENSE(ch) * .75);
GET_DEFENSE(ch) -= GET_BODY(ch);
}
}
}
}
void roll_initiative(void)
{
struct char_data *ch, *next_combat_list = NULL;
for (ch = combat_list; ch; ch = next_combat_list) {
next_combat_list = ch->next_fighting;
roll_individual_initiative(ch);
if (ch->in_room && world[ch->in_room].poltergeist[0]) {
int dam = convert_damage(stage(-success_test(GET_QUI(ch), world[ch->in_room].poltergeist[1] - GET_IMPACT(ch)), LIGHT));
if (dam > 0) {
act("You are hit by flying objects!\r\n", FALSE, ch, 0, 0, TO_CHAR);
damage(ch, ch, dam, TYPE_POLTERGEIST, MENTAL);
}
}
}
return;
}
/* control the fights going on. Called every 2 seconds from comm.c. */
void perform_violence(void)
{
struct char_data *ch;
extern struct index_data *mob_index;
if (combat_list) {
if (GET_INIT_ROLL(combat_list) <= 0) {
roll_initiative();
order_list(TRUE);
}
}
for (ch = combat_list; ch; ch = next_combat_list) {
bool engulfed = FALSE;
next_combat_list = ch->next_fighting;
if (!(FIGHTING(ch) || FIGHTING_VEH(ch)) || !AWAKE(ch))
stop_fighting(ch);
else if (GET_INIT_ROLL(ch) > 0) {
GET_INIT_ROLL(ch) -= 10;
for (struct spirit_sustained *ssust = SPIRIT_SUST(ch); ssust; ssust = ssust->next)
if (ssust->type == ENGULF) {
if (ssust->caster) {
int dam;
if (IS_SPIRIT(ch) || (IS_ELEMENTAL(ch) && GET_SPARE1(ch) == ELEM_WATER)) {
dam = convert_damage(stage(-success_test(GET_BOD(ssust->target), GET_SPARE2(ch) + GET_EXTRA(ssust->target)), MODERATE));
act("$n can contorts in pain as the water engulfs $m!", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The water crushes you and leaves you unable to breath!\r\n", ssust->target);
if (dam > 0)
damage(ch, ssust->target, dam, TYPE_FUMES, MENTAL);
GET_EXTRA(ssust->target)++;
} else
switch (GET_SPARE1(ch)) {
case ELEM_FIRE:
dam = convert_damage(stage(-success_test(GET_BOD(ssust->target), GET_SPARE2(ch) - GET_IMPACT(ssust->target) + MOB_FLAGGED(ch, MOB_FLAMEAURA) ? 2 : 0), MODERATE));
act("$n can be heard screaming from inside $s prison of flames!", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The flames continue to burn you, causing horrendous pain!\r\n", ssust->target);
if (dam > 0)
damage(ch, ssust->target, dam, TYPE_FUMES, PHYSICAL);
break;
case ELEM_EARTH:
dam = convert_damage(stage(-success_test(GET_BOD(ssust->target), GET_SPARE2(ch) - GET_IMPACT(ssust->target)), SERIOUS));
act("$n can be heard screaming from inside $s earthen prison.", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The earth around you compresses against you, causing you great pain.\r\n", ssust->target);
if (dam > 0)
damage(ch, ssust->target, dam, TYPE_FUMES, PHYSICAL);
break;
case ELEM_AIR:
dam = convert_damage(stage(-success_test(MAX(GET_WIL(ssust->target), GET_BOD(ssust->target)), GET_SPARE2(ch)), SERIOUS));
act("$n chokes and coughs.", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("Noxious fumes fill your throat and lungs, causing your vision to swim.\r\n", ssust->target);
if (dam > 0)
damage(ch, ssust->target, dam, TYPE_FUMES, MENTAL);
break;
}
} else {
if (success_test(GET_STR(ch), GET_LEVEL(ssust->target)) - success_test(GET_LEVEL(ssust->target), GET_STR(ch)) > 0)
stop_spirit_power(ssust->target, ENGULF);
else {
act("$n struggles against the spirit engulfing $m!", FALSE, ch, 0, 0, TO_ROOM);
act("You struggle against $n's engulfment!", FALSE, ssust->target, 0, ch, TO_VICT);
}
}
engulfed = TRUE;
break;
}
if (ch->points.fire[0] > 0 && success_test(GET_WIL(ch), 6) < 0 || engulfed)
continue;
if (IS_AFFECTED(ch, AFF_BANISH) && GET_EXTRA(ch)) {
struct char_data *spirit, *mage;
if (IS_NPC(ch)) {
spirit = ch;
mage = FIGHTING(ch);
} else {
spirit = FIGHTING(ch);
mage = ch;
}
int skill = GET_SKILL(mage, SKILL_CONJURING);
for (int i = 0; i < NUM_WEARS; i++)
if (GET_EQ(mage, i) && GET_OBJ_TYPE(GET_EQ(mage, i)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(mage, i), 0) == FOCI_SPIRIT
&& GET_OBJ_VAL(GET_EQ(mage, i), 2) == GET_IDNUM(mage) && GET_OBJ_VAL(GET_EQ(mage, i), 3) == GET_SPARE1(spirit)
&& GET_OBJ_VAL(GET_EQ(mage, i), 4)) {
skill += GET_OBJ_VAL(GET_EQ(mage, i), 1);
break;
}
if (GET_ACTIVE(spirit) == GET_IDNUM(mage))
skill += GET_CHA(mage);
int success = resisted_test(skill, GET_LEVEL(spirit), GET_LEVEL(spirit), GET_MAG(mage) / 100);
if (success < 0) {
GET_EXTRA(mage) = 0;
GET_EXTRA(spirit) = 1;
GET_TEMP_MAGIC_LOSS(mage) += success;
send_to_char(mage, "You lock minds with %s but are beaten back by it's force!\r\n", GET_NAME(spirit));
} else if (success == 0) {
send_to_char(mage, "You lock minds with %s but fail to gain any ground.\r\n",
GET_NAME(spirit));
} else {
GET_EXTRA(mage) = 1;
GET_EXTRA(spirit) = 0;
send_to_char(mage, "You lock minds with %s and succeed in weakening it!\r\n", GET_NAME(spirit));
GET_LEVEL(spirit) -= success;
}
affect_total(mage);
affect_total(spirit);
if (GET_LEVEL(spirit) < 1) {
send_to_char(mage, "You drain %s off the last of its magical force, banishing it to the metaplanes!\r\n", GET_NAME(spirit));
act("$N is banished to the metaplanes as $n drains the last of it's magical force.", FALSE, mage, 0, spirit, TO_ROOM);
stop_fighting(spirit);
stop_fighting(mage);
end_spirit_existance(spirit, TRUE);
AFF_FLAGS(mage).RemoveBit(AFF_BANISH);
} else if (GET_MAG(mage) < 1) {
send_to_char(mage, "Your magic spent from your battle with %s, you fall unconcious.\r\n", GET_NAME(spirit));
act("$n falls unconcious, drained by magical combat.", FALSE, mage, 0, 0, TO_ROOM);
damage(mage, spirit, TYPE_DRAIN, DEADLY, MENTAL);
stop_fighting(spirit);
stop_fighting(mage);
update_pos(mage);
AFF_FLAGS(mage).RemoveBit(AFF_BANISH);
AFF_FLAGS(spirit).RemoveBit(AFF_BANISH);
}
continue;
} else if (IS_AFFECTED(ch, AFF_APPROACH)) {
if (IS_AFFECTED(FIGHTING(ch), AFF_APPROACH) || GET_POS(FIGHTING(ch)) < POS_FIGHTING ||
(GET_EQ(ch, WEAR_WIELD) && (IS_GUN(GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 3)) ||
GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 3) == TYPE_ARROW)) ||
(GET_EQ(ch, WEAR_HOLD) && (IS_GUN(GET_OBJ_VAL(GET_EQ(ch, WEAR_HOLD), 3)) ||
GET_OBJ_VAL(GET_EQ(ch, WEAR_HOLD), 3) == TYPE_ARROW)) ||
(GET_EQ(FIGHTING(ch), WEAR_WIELD) && !(IS_GUN(GET_OBJ_VAL(GET_EQ(FIGHTING(ch), WEAR_WIELD), 3)))) ||
(GET_EQ(FIGHTING(ch), WEAR_HOLD) && !(IS_GUN(GET_OBJ_VAL(GET_EQ(FIGHTING(ch), WEAR_HOLD), 3))))) {
AFF_FLAGS(ch).RemoveBit(AFF_APPROACH);
AFF_FLAGS(FIGHTING(ch)).RemoveBit(AFF_APPROACH);
} else {
int target = 8, quickness = GET_QUI(ch);
bool footanchor = FALSE;
if (GET_TOTALBAL(ch) > GET_QUI(ch))
quickness -= GET_TOTALBAL(ch) - GET_QUI(ch);
if (GET_TOTALIMP(ch) > GET_QUI(ch))
quickness -= GET_TOTALIMP(ch) - GET_QUI(ch);
if (GET_TRADITION(ch) == TRAD_ADEPT && GET_POWER(ch, ADEPT_DISTANCE_STRIKE) && !(GET_EQ(ch, WEAR_WIELD) || GET_EQ(ch, WEAR_HOLD)))
target -= (int)GET_REAL_MAG(ch) / 150;
for (struct obj_data *cyber = ch->cyberware; cyber; cyber = cyber->next_content)
if (GET_OBJ_VAL(cyber, 0) == CYB_HYDRAULICJACK)
quickness += GET_OBJ_VAL(cyber, 1);
else if (GET_OBJ_VAL(cyber, 0) == CYB_FOOTANCHOR && !GET_OBJ_VAL(cyber, 9))
footanchor = TRUE;
for (struct spirit_sustained *ssust = SPIRIT_SUST(ch); ssust; ssust = ssust->next)
if (ssust->type == MOVEMENTUP && ssust->caster == FALSE && GET_LEVEL(ssust->target))
quickness *= GET_LEVEL(ssust->target);
else if (ssust->type == MOVEMENTDOWN && ssust->caster == FALSE && GET_LEVEL(ssust->target))
quickness /= GET_LEVEL(ssust->target);
if (AFF_FLAGGED(ch, AFF_BINDING))
quickness = 0;
if (footanchor)
quickness /= 2;
if (ROOM_FLAGGED(ch->in_room, ROOM_INDOORS) && (float)(GET_HEIGHT(ch)/100) > world[ch->in_room].z) {
if ((float)(GET_HEIGHT(ch)/100) > world[ch->in_room].z * 2)
quickness = 0;
else quickness /= 2;
}
if (quickness > 0 && success_test(quickness, target) > 1) {
send_to_char(ch, "You close the distance and strike!\r\n");
act("$n closes the distance and strikes.", FALSE, ch, 0, 0, TO_ROOM);
AFF_FLAGS(ch).RemoveBit(AFF_APPROACH);
} else {
send_to_char(ch, "You attempt to close the distance!\r\n");
act("$n charges towards $N.", FALSE, ch, 0, FIGHTING(ch), TO_ROOM);
GET_INIT_ROLL(ch) -= 10;
continue;
}
}
}
if (AFF_FLAGGED(ch, AFF_MANNING) || PLR_FLAGGED(ch, PLR_REMOTE) || AFF_FLAGGED(ch, AFF_RIG))
mount_fire(ch);
else if (FIGHTING_VEH(ch)) {
if (ch->in_room != FIGHTING_VEH(ch)->in_room)
stop_fighting(ch);
else
vcombat(ch, FIGHTING_VEH(ch));
} else if (IS_NPC(ch) && !ch->desc && GET_SKILL(ch, SKILL_SORCERY) > 0 && GET_MENTAL(ch) > 400 && ch->in_room == FIGHTING(ch)->in_room && success_test(1, 8 - GET_SKILL(ch, SKILL_SORCERY)))
mob_magic(ch);
else {
hit(ch, FIGHTING(ch), (GET_EQ(ch, WEAR_WIELD) ? GET_EQ(ch, WEAR_WIELD) : GET_EQ(ch, WEAR_HOLD)),
(GET_EQ(FIGHTING(ch), WEAR_WIELD) ? GET_EQ(FIGHTING(ch), WEAR_WIELD) : GET_EQ(FIGHTING(ch), WEAR_HOLD)));
if (GET_EQ(ch, WEAR_WIELD) && GET_EQ(ch, WEAR_HOLD) && FIGHTING(ch))
hit(ch, FIGHTING(ch), GET_EQ(ch, WEAR_HOLD), GET_EQ(FIGHTING(ch), WEAR_WIELD));
}
if (MOB_FLAGGED(ch, MOB_SPEC) &&
mob_index[GET_MOB_RNUM(ch)].func != NULL)
(mob_index[GET_MOB_RNUM(ch)].func) (ch, ch, 0, "");
}
}
}
void order_list(bool first, ...)
{
register struct char_data *one, *two = combat_list, *next, *previous = NULL, *temp;
if (combat_list == NULL)
return;
for (one = two; one; previous = NULL, one = next) {
next = one->next_fighting;
for (two = combat_list; two && two->next_fighting; previous = two,
two = two->next_fighting) {
if (GET_INIT_ROLL(two->next_fighting) > GET_INIT_ROLL(two)) {
if (previous)
previous->next_fighting = two->next_fighting;
else
combat_list = two->next_fighting;
temp = two->next_fighting->next_fighting;
two->next_fighting->next_fighting = two;
two->next_fighting = temp;
}
}
}
if (first)
for (one = combat_list; one; one = next) {
next = one->next_fighting;
two = one;
if (GET_TRADITION(one) == TRAD_ADEPT && GET_POWER(one, ADEPT_QUICK_STRIKE)) {
REMOVE_FROM_LIST(one, combat_list, next_fighting);
one->next_fighting = combat_list;
combat_list = one;
}
}
}
void order_list(struct char_data *start)
{
register struct char_data *one, *two, *next, *previous = NULL, *temp;
for (one = start; one; previous = NULL, one = next)
{
next = one->next_fighting;
for (two = start; two && two->next_fighting; previous = two,
two = two->next_fighting) {
if (GET_INIT_ROLL(two->next_fighting) > GET_INIT_ROLL(two)) {
if (previous)
previous->next_fighting = two->next_fighting;
else
start = two->next_fighting;
temp = two->next_fighting->next_fighting;
two->next_fighting->next_fighting = two;
two->next_fighting = temp;
}
}
}
}
void order_list(struct matrix_icon *start)
{
register struct matrix_icon *one, *two, *next, *previous = NULL, *temp;
for (one = start; one; previous = NULL, one = next)
{
next = one->next_fighting;
for (two = start; two && two->next_fighting; previous = two,
two = two->next_fighting) {
if (two->next_fighting->initiative > two->initiative) {
if (previous)
previous->next_fighting = two->next_fighting;
else
start = two->next_fighting;
temp = two->next_fighting->next_fighting;
two->next_fighting->next_fighting = two;
two->next_fighting = temp;
}
}
}
matrix[start->in_host].fighting = start;
}
void chkdmg(struct veh_data * veh)
{
if (veh->damage <= 1)
{
send_to_veh("A scratch appears on the paintwork.\r\n", veh, NULL, TRUE);
} else if (veh->damage <= 3)
{
send_to_veh("You see some dings and scratches appear on the paintwork.\r\n", veh, NULL, TRUE);
} else if (veh->damage <= 6)
{
send_to_veh("The wind screen shatters and the bumper falls off.\r\n", veh, NULL, TRUE);
} else if (veh->damage < 10)
{
send_to_veh("The engine starts spewing smoke and flames.\r\n", veh, NULL, TRUE);
} else
{
struct char_data *i, *next;
struct obj_data *obj, *nextobj;
int dam;
if (veh->cspeed >= SPEED_IDLE) {
stop_chase(veh);
send_to_veh("You are hurled into the street as your ride is wrecked!\r\n", veh, NULL, TRUE);
sprintf(buf, "%s careens off the road, it's occupants hurled to the street.!\r\n", GET_VEH_NAME(veh));
send_to_room(buf, veh->in_room);
veh->cspeed = SPEED_OFF;
veh->dest = 0;
if (veh->towing) {
veh_to_room(veh->towing, veh->in_room);
veh->towing = NULL;
}
if (veh->rigger) {
send_to_char("Your mind is blasted with pain as your vehicle is wrecked.\r\n", veh->rigger);
damage(veh->rigger, veh->rigger, convert_damage(stage(-success_test(GET_WIL(veh->rigger),
6), SERIOUS)), TYPE_CRASH, MENTAL);
veh->rigger->char_specials.rigging = NULL;
PLR_FLAGS(veh->rigger).RemoveBit(PLR_REMOTE);
veh->rigger = NULL;
}
for (i = veh->people; i; i = next) {
next = i->next_in_veh;
char_from_room(i);
char_to_room(i, veh->in_room);
if (AFF_FLAGGED(i, AFF_MANNING))
for (struct obj_data *mount = veh->mount; mount; mount = mount->next_content)
if (mount->worn_by == i) {
mount->worn_by = NULL;
break;
}
AFF_FLAGS(i).RemoveBits(AFF_PILOT, AFF_RIG, AFF_MANNING, ENDBIT);
dam = convert_damage(stage(-success_test(GET_BOD(i), 8), SERIOUS));
damage(i, i, dam, TYPE_CRASH, PHYSICAL);
}
for (obj = veh->contents; obj; obj = nextobj) {
nextobj = obj->next_content;
switch(number(0, 2)) {
case 1:
obj_from_room(obj);
obj_to_room(obj, veh->in_room);
break;
case 2:
extract_obj(obj);
break;
}
}
} else {
send_to_veh("You scramble into the street as your ride is wrecked!\r\n", veh, NULL, TRUE);
struct char_data *next;
for (i = veh->people; i; i = next) {
next = i->next_in_veh;
char_from_room(i);
char_to_room(i, veh->in_room);
if (AFF_FLAGGED(i, AFF_MANNING))
for (struct obj_data *mount = veh->mount; mount; mount = mount->next_content)
if (mount->worn_by == i) {
mount->worn_by = NULL;
break;
}
AFF_FLAGS(i).RemoveBits(AFF_PILOT, AFF_RIG, AFF_MANNING, ENDBIT);
dam = convert_damage(stage(-success_test(GET_BOD(i), 4), MODERATE));
damage(i, i, dam, TYPE_CRASH, PHYSICAL);
}
for (obj = veh->contents; obj; obj = nextobj) {
nextobj = obj->next_content;
switch(number(0, 2)) {
case 1:
obj_from_room(obj);
obj_to_room(obj, veh->in_room);
break;
case 2:
extract_obj(obj);
break;
}
}
}
}
return;
}
void vram(struct veh_data * veh, struct char_data * ch, struct veh_data * tveh)
{
int power, damage_total = 0, veh_dam = 0;
int veh_resist = 0, ch_resist = 0, modbod = 0;
if (ch)
{
power = (int)(get_speed(veh) / 10);
if (GET_BOD(ch) < 8)
modbod = 1;
else
modbod = 2;
if (modbod > (veh->body * 2)) {
damage_total = LIGHT;
veh_dam = DEADLY;
} else if (modbod > veh->body) {
damage_total = MODERATE;
veh_dam = SERIOUS;
} else if (modbod == veh->body) {
damage_total = SERIOUS;
veh_dam = MODERATE;
} else if (modbod < veh->body) {
damage_total = DEADLY;
veh_dam = LIGHT;
}
ch_resist = 0 - success_test(GET_BOD(ch) + GET_BODY(ch), power);
int staged_damage = stage(ch_resist, damage_total);
damage_total = convert_damage(staged_damage);
veh_resist = success_test(veh->body, power);
veh_dam -= veh_resist;
if (veh_dam > 0) {
veh->damage += veh_dam;
send_to_veh("THUMP!\r\n", veh, NULL, TRUE);
sprintf(buf, "You run %s down!\r\n", thrdgenders[(int)GET_SEX(ch)]);
sprintf(buf1, "%s runs $n down!", GET_VEH_NAME(veh));
sprintf(buf2, "%s runs you down!", GET_VEH_NAME(veh));
send_to_driver(buf, veh);
chkdmg(veh);
} else {
send_to_veh("THUTHUMP!\r\n", veh, NULL, TRUE);
sprintf(buf, "You roll right over %s!\r\n", thrdgenders[(int)GET_SEX(ch)]);
sprintf(buf1, "%s rolls right over $n!", GET_VEH_NAME(veh));
sprintf(buf2, "%s runs right over you!", GET_VEH_NAME(veh));
send_to_driver(buf, veh);
}
act(buf1, FALSE, ch, 0, 0, TO_ROOM);
act(buf2, FALSE, ch, 0, 0, TO_CHAR);
damage(ch, ch, damage_total, TYPE_RAM, PHYSICAL);
} else
{
power = veh->cspeed - tveh->cspeed;
if (power < 0)
power = -power;
power = (int)(ceil((float)power / 10));
if (tveh->body > (veh->body * 2)) {
damage_total = LIGHT;
veh_dam = DEADLY;
} else if (tveh->body > veh->body) {
damage_total = MODERATE;
veh_dam = SERIOUS;
} else if (tveh->body == veh->body) {
damage_total = SERIOUS;
veh_dam = MODERATE;
} else if ((tveh->body * 2) < veh->body) {
damage_total = DEADLY;
veh_dam = LIGHT;
} else if (tveh->body < veh->body) {
damage_total = SERIOUS;
veh_dam = MODERATE;
}
ch_resist = 0 - success_test(tveh->body, power);
int staged_damage = stage(ch_resist, damage_total);
damage_total = convert_damage(staged_damage);
tveh->damage += damage_total;
sprintf(buf, "A %s rams into you!\r\n", GET_VEH_NAME(veh));
send_to_veh(buf, tveh, NULL, TRUE);
if (tveh->cspeed > SPEED_IDLE)
switch (damage_total) {
case MODERATE:
case LIGHT:
tveh->cspeed = SPEED_CRUISING;
send_to_veh("You lose some speed.\r\n", tveh, NULL, TRUE);
break;
case SERIOUS:
tveh->cspeed = SPEED_CRUISING;
if (tveh->rigger)
crash_test(tveh->rigger);
else
for (struct char_data *pilot = tveh->people; pilot; pilot = pilot->next_in_veh)
if (AFF_FLAGGED(pilot, AFF_PILOT))
crash_test(pilot);
break;
}
chkdmg(tveh);
veh_resist = 0 - success_test(veh->body, power);
staged_damage = stage(veh_resist, veh_dam);
damage_total = convert_damage(staged_damage);
veh->damage += damage_total;
sprintf(buf, "You ram a %s!\r\n", GET_VEH_NAME(tveh));
sprintf(buf1, "%s rams straight into your ride!\r\n", GET_VEH_NAME(veh));
sprintf(buf2, "%s rams straight into %s!\r\n", GET_VEH_NAME(veh), GET_VEH_NAME(tveh));
send_to_veh(buf, veh, NULL, TRUE);
send_to_veh(buf1, tveh, NULL, TRUE);
send_to_room(buf2, veh->in_room);
if (veh->cspeed > SPEED_IDLE)
switch (damage_total) {
case MODERATE:
case LIGHT:
veh->cspeed = SPEED_CRUISING;
send_to_veh("You lose some speed.\r\n", tveh, NULL, TRUE);
break;
case SERIOUS:
veh->cspeed = SPEED_CRUISING;
if (veh->rigger)
crash_test(veh->rigger);
else
for (struct char_data *pilot = veh->people; pilot; pilot = pilot->next_in_veh)
if (AFF_FLAGGED(pilot, AFF_PILOT))
crash_test(pilot);
break;
}
chkdmg(veh);
}
}
void vcombat(struct char_data * ch, struct veh_data * veh)
{
char ammo_type[20];
static struct obj_data *wielded, *obj;
static int base_target, power, damage_total;
int attack_success = 0, attack_resist=0, skill_total = 1;
int recoil=0, burst=0, recoil_comp=0, newskill, modtarget = 0;
if (IS_AFFECTED(ch, AFF_PETRIFY))
return;
if (veh->damage > 9)
{
stop_fighting(ch);
return;
}
wielded = GET_EQ(ch, WEAR_WIELD);
if (get_speed(veh) > 10 && !AFF_FLAGGED(ch, AFF_COUNTER_ATT) && ((!wielded || !IS_GUN(GET_OBJ_VAL(wielded, 3)))))
{
vram(veh, ch, NULL);
return;
}
if (wielded)
{
switch(GET_OBJ_VAL(wielded, 3)) {
case TYPE_SHOTGUN:
sprintf(ammo_type, "horde of pellets");
break;
case TYPE_MACHINE_GUN:
sprintf(ammo_type, "stream of bullets");
break;
case TYPE_CANNON:
sprintf(ammo_type, "shell");
break;
case TYPE_ROCKET:
sprintf(ammo_type, "rocket");
break;
default:
sprintf(ammo_type, "bullet");
break;
}
if (!has_ammo(ch, wielded))
return;
if (IS_BURST(wielded)) {
if (GET_OBJ_VAL(wielded, 6) >= 2) {
burst = 3;
GET_OBJ_VAL(wielded, 6) -= 2;
} else if (GET_OBJ_VAL(wielded, 6) == 1) {
burst = 2;
GET_OBJ_VAL(wielded, 6)--;
} else
burst = 0;
}
if (IS_GUN(GET_OBJ_VAL(wielded, 3)))
power = GET_OBJ_VAL(wielded, 0);
else
power = GET_STR(ch) + GET_OBJ_VAL(wielded, 2);
damage_total = GET_OBJ_VAL(wielded, 1);
} else
{
power = GET_STR(ch);
strcpy(ammo_type, "blow");
for (obj = ch->cyberware;
obj && !damage_total;
obj = obj->next_content)
switch (GET_OBJ_VAL(obj, 2) && GET_OBJ_VAL(obj, 9) == 1) {
case 19:
damage_total = LIGHT;
break;
case 29:
power += GET_OBJ_VAL(obj, 0);
case 21:
damage_total = MODERATE;
break;
}
if (!damage_total)
damage_total = MODERATE;
}
power = (int)(power / 2);
damage_total--;
if (power <= veh->armor || !damage_total)
{
sprintf(buf, "A %s ricochets off of %s.", ammo_type, GET_VEH_NAME(veh));
sprintf(buf2, "Your attack ricochets off of %s.", GET_VEH_NAME(veh));
act(buf, FALSE, ch, NULL, NULL, TO_ROOM);
act(buf2, FALSE, ch, NULL, NULL, TO_CHAR);
sprintf(buf, "A %s ricochets off of your ride.\r\n", ammo_type);
send_to_veh(buf, veh, 0, TRUE);
return;
} else
power -= veh->armor;
if (wielded)
recoil_comp = check_recoil(ch, wielded);
recoil = MAX(0, burst - recoil_comp);
if (AFF_FLAGGED(ch, AFF_RIG) || AFF_FLAGGED(ch, AFF_MANNING))
recoil = MAX(0, recoil - 2);
if (get_speed(veh) > 10)
if (get_speed(veh) < 60)
modtarget++;
else if (get_speed(veh) < 120)
modtarget += 2;
else if (get_speed(veh) < 200)
modtarget += 2;
else if (get_speed(veh) >= 200)
modtarget += 3;
if (wielded)
modtarget -= check_smartlink(ch, wielded);
if (wielded && IS_OBJ_STAT(wielded, ITEM_SNIPER) && ch->in_room == veh->in_room)
modtarget += 6;
if (GET_WIELDED(ch, 0) && GET_WIELDED(ch, 1))
modtarget++;
if (AFF_FLAGGED(ch, AFF_RIG) || AFF_FLAGGED(ch, AFF_MANNING) || PLR_FLAGGED(ch, PLR_REMOTE))
{
skill_total = get_skill(ch, SKILL_GUNNERY, base_target);
} else if (wielded && GET_SKILL(ch, GET_OBJ_VAL(wielded, 4)) < 1)
{
newskill = return_general(GET_OBJ_VAL(wielded, 4));
skill_total = get_skill(ch, newskill, base_target);
} else if (!wielded)
{
if (GET_SKILL(ch, SKILL_UNARMED_COMBAT) < 1) {
newskill = SKILL_UNARMED_COMBAT;
skill_total = get_skill(ch, newskill, base_target);
} else
skill_total = get_skill(ch, SKILL_UNARMED_COMBAT, base_target);
} else
skill_total = get_skill(ch, GET_OBJ_VAL(wielded, 4), base_target);
base_target = 4 + modtarget + recoil;
attack_success = success_test(skill_total, base_target);
if (attack_success < 1)
{
if (wielded) {
sprintf(buf, "$n fires his $o at %s, but misses.", GET_VEH_NAME(veh));
sprintf(buf1, "You fire your $o at %s, but miss.", GET_VEH_NAME(veh));
sprintf(buf2, "%s's %s misses you completly.\r\n", GET_NAME(ch), ammo_type);
} else {
sprintf(buf, "$n swings at %s, but misses.", GET_VEH_NAME(veh));
sprintf(buf1, "You swing at %s, but miss.", GET_VEH_NAME(veh));
sprintf(buf2, "%s's %s misses you completly.\r\n", GET_NAME(ch), ammo_type);
}
act(buf, FALSE, ch, wielded, 0, TO_NOTVICT);
act(buf1, FALSE, ch, wielded, 0, TO_CHAR);
send_to_veh(buf2, veh, 0, TRUE);
weapon_scatter(ch, ch, wielded);
return;
}
attack_resist = success_test(veh->body, power + modify_veh(veh));
attack_success -= attack_resist;
int staged_damage = stage(attack_success, damage_total);
damage_total = convert_damage(staged_damage);
if (damage_total < LIGHT)
{
sprintf(buf, "$n's %s ricochets off of %s.", ammo_type, GET_VEH_NAME(veh));
sprintf(buf1, "Your attack ricochets off of %s.", GET_VEH_NAME(veh));
sprintf(buf2, "A %s ricochets off of your ride.\r\n", ammo_type);
} else if (damage_total == LIGHT)
{
sprintf(buf, "$n's %s causes extensive damage to %s paintwork.", ammo_type, GET_VEH_NAME(veh));
sprintf(buf1, "Your attack causes extensive damage to %s paintwork.", GET_VEH_NAME(veh));
sprintf(buf2, "A %s scratches your paintjob.\r\n", ammo_type);
} else if (damage_total == MODERATE)
{
sprintf(buf, "$n's %s leaves %s riddled with holes.", ammo_type, GET_VEH_NAME(veh));
sprintf(buf1, "Your attack leave %s riddled with holes.", GET_VEH_NAME(veh));
sprintf(buf2, "A %s leaves your ride full of holes.\r\n", ammo_type);
} else if (damage_total == SERIOUS)
{
sprintf(buf, "$n's %s obliterates %s.", ammo_type, GET_VEH_NAME(veh));
sprintf(buf1, "You obliterate %s with your attack.", GET_VEH_NAME(veh));
sprintf(buf2, "A %s obliterates your ride.\r\n", ammo_type);
} else if (damage_total >= DEADLY)
{
sprintf(buf, "$n's %s completly destroys %s.", ammo_type, GET_VEH_NAME(veh));
sprintf(buf1, "Your attack completly destroys %s.", GET_VEH_NAME(veh));
sprintf(buf2, "A %s completly destroys your ride.\r\n", ammo_type);
}
act(buf, FALSE, ch, NULL, NULL, TO_ROOM);
act(buf1, FALSE, ch, NULL, NULL, TO_CHAR);
send_to_veh(buf2, veh, 0, TRUE);
veh->damage += damage_total;
if (veh->owner && !IS_NPC(ch))
{
sprintf(buf, "%s attacked vehicle (%s) owned by player.", GET_CHAR_NAME(ch), veh->name);
mudlog(buf, ch, LOG_WRECKLOG, TRUE);
}
chkdmg(veh);
}
void mount_fire(struct char_data *ch)
{
struct veh_data *veh;
struct obj_data *mount;
RIG_VEH(ch, veh);
if (AFF_FLAGGED(ch, AFF_MANNING)) {
for (mount = veh->mount; mount; mount = mount->next_content)
if (mount->worn_by == ch)
break;
if (!(mount->targ || mount->tveh))
return;
if (mount->targ)
hit(ch, mount->targ, mount->contains, NULL);
else
vcombat(ch, mount->tveh);
} else if (ch->char_specials.rigging || AFF_FLAGGED(ch, AFF_RIG)) {
for (mount = veh->mount; mount; mount = mount->next_content)
if (!mount->worn_by && mount->contains && ((mount->targ && FIGHTING(ch) == mount->targ) || (mount->tveh && FIGHTING_VEH(ch) == mount->tveh))) {
if (mount->targ && FIGHTING(ch) == mount->targ)
hit(ch, mount->targ, mount->contains, NULL);
else
vcombat(ch, mount->tveh);
}
}
}