#include <mudlib.h>
#define NAME (string)environment()->query_name()
#define DEX (int)environment()->query_dexterity()
#define ARROW_DMG 40 /* well... u only have limited shots! */
#define ELF_BONUS 2
#define BOWYER_MOD 3
#define MOD 4 /* prof mod from living.c, make sure its the same */
#define CHANCE_TO_BREAK 15 /* 1 in 15 chance */
inherit WEAPON;
static int dmg;
static mixed *last_arrow;
static string ammunition;
void find_fate_of_last_arrow(object ob, int i);
string set_ammunition(string str) { return ammunition = str; }
void reset(status arg) {
if(arg) return;
set_name("longbow");
set_alias("bow");
set_wc(0);
set_ammunition("arrow");
set_length(10000);
set_type("missile");
set_weapon_strength(100000000000); /* lasts longer 'cause we don't use it
for actual damage in combat! */
set_short("A fine longbow");
set_long(
"This fine longbow is made in the traditional elvish design.\n");
set_info(
"A bow requires "+ammunition+"s in a quiver.\n");
set_weight( 5);
set_value(1100);
set_hit_func(this_object());
set_attack_msg(({
"missed", "",
"grazed", "lightly with an "+ammunition+" shot",
"pierced", "with an "+ammunition+"",
"pierced", "deeply with an "+ammunition+"",
"expertly hit", "with an "+ammunition+"",
"hit", "with an expert "+ammunition+" shot",
}));
}
int weapon_hit(object target) {
object obj;
int i;
object *inv;
status shotArrow;
int bonus;
inv = all_inventory(environment());
obj = present("quiver", environment());
for(i=1; (obj = present("quiver "+i, environment())); i++) {
obj = present(ammunition, obj);
if(obj) {
switch(ammunition) {
case "arrow" :
tell_object(environment(), "You nock an arrow.\n");
break;
default :
tell_object(environment(), "You load a "+ammunition+".\n");
break;
}
bonus = ((int)obj->query_ammunition_bonus() + ARROW_DMG);
environment(obj)->add_weight(-(int)obj->query_weight());
shotArrow = 1;
find_fate_of_last_arrow(obj, bonus);
return bonus;
}
}
if(!shotArrow) {
tell_object(environment(), "You have run out of "+ammunition+"s!\n");
say(NAME+" fumbles around for some "+ammunition+"s, but can't find any!\n",
environment());
return -100000; /* don't want to do ANY damage! */
}
}
void find_fate_of_last_arrow(object obj, int bonus) {
last_arrow = ({ obj, bonus, });
}
int query_dam(int damage, object attacker) {
object *env, ob;
string message;
if(!attacker) return 1;
if(!last_arrow[0]) return 1;
env = all_inventory(environment(environment()));
if(!damage) {
if(!last_arrow[0]) return 1;
/* you shoot someone else */
if(!random(DEX)) {
ob = env[random(sizeof(env))];
if(ob == attacker) ob = environment();
ob -> hit_player(random(damage));
if(ob == environment()) {
tell_object(environment(), "You shoot yourself in the foot!\n");
say(NAME+" shoots "+environment()->query_objective()+"self "+
"in the foot!\n");
}
tell_object(environment(), "You shoot "+ob->query_name()+
" by accident!\n");
say(NAME+" shoots "+ob->query_name()+" by accient!\n");
if(last_arrow[1] > ARROW_DMG) {
message = ""+ammunition+" explodes!";
tell_object(environment(), "Your "+message+".\n");
say(NAME+"'s "+message+".\n", environment());
destruct(last_arrow[0]);
return 1;
}
if(!random(CHANCE_TO_BREAK)) {
message = ""+ammunition+" shatters!";
tell_object(environment(), "Your "+message+"\n");
say(NAME+"'s "+message+"\n", environment());
destruct(last_arrow[0]);
move_object(clone_object("objects/bits"), ob);
return 1;
}
move_object(last_arrow[0], ob);
return 1;
}
/* if you dont hit someone else, you must hit the ground hu?! */
message = ""+ammunition+" hits the ground and ";
if(last_arrow[1] > ARROW_DMG) {
message += "explodes, leaving a scorch mark";
destruct(last_arrow[0]);
}
else {
if(!random(CHANCE_TO_BREAK)) {
message += "shatters!";
move_object(clone_object("objects/bits"),environment(environment()));
destruct(last_arrow[0]);
}
else {
message += "stays there";
move_object(last_arrow[0], environment(environment()));
}
}
tell_object(environment(), "Your "+message+"\n");
say(NAME+"s "+message+".\n", environment());
return 1;
}
/* "+ammunition+" did hit, but what happened?! */
if(last_arrow[1] > ARROW_DMG) {
message = ""+ammunition+" explodes on impact!";
tell_object(environment(), "Your "+message+".\n");
say(NAME+"s "+message+".\n", environment());
destruct(last_arrow[0]);
return 1;
}
if(!random(CHANCE_TO_BREAK)) {
message = ""+ammunition+" breaks as it hits!";
tell_object(environment(), "Your "+message+".\n");
say(NAME+"'s "+message+".\n", environment());
destruct(last_arrow[0]);
move_object(clone_object("objects/bits"), attacker);
return 1;
}
message = ""+ammunition+" sticks into "+attacker->query_name();
tell_object(environment(), "Your "+message+".\n");
say(NAME+"'s "+message+".\n", environment());
move_object(last_arrow[0], attacker);
return 1;
}
int right_weapon_class_bonus() {
string tmp1, tmp2;
int tmpBonus;
string race;
race = (string)environment()->query_race();
if(query_wielded()) {
if(sscanf(race, "%self%s", tmp1, tmp2) &&
race != "dark elf") {
tmpBonus += ELF_BONUS;
}
}
tmpBonus += (int)environment()->query_bowyer() / BOWYER_MOD;
tmpBonus += (int)environment()->query_weapon_proficiency(query_name())/MOD;
return tmpBonus;
}