#include <weapon_lib.h>
#include "../shifter.h"
#define MINSIZE MIN_WEAPON_SIZE
// How many swings per loss of a size
#define DAMAGE_SIZE 15
inherit OBJ+"base_mimeon_weapon";
int add_size(int x, int ignore_counter);
mixed d_types(string s);
int size;
int size_counter;
int ret_val;
int weight_bonus;
int explode;
int hand;
create() {
::create();
set_sound("You hear nothing.\n");
set_taste("You lick yourself and think you taste fine.\n");
set_touch("You give yourself a good feel, and think the weapon feels perfect.\n");
set_smell("You smell the weapon, and it smells like you need a bath.\n");
set_identify("It was made by you!");
set_material("rock");
}
int twohand(string s) {
if (!s) return 0;
s = lower_case(s);
switch (s) {
case "two handed axe" : return 1;
case "two handed sword" : return 1;
}
return 0;
}
void set_wield_hand(int s) {
hand = s;
}
int query_wield_hand() { return hand; }
void set_type(string s) {
if (!s) return;
set_weapon_type(s);
set_twohanded(twohand(s));
set_weapon(d_types(s));
set_name(lower_case(s));
set_alias(({"shifter_weapon",s}));
set_short("a small "+lower_case(s));
set_long("The "+lower_case(s)+" seems to be made of a shiny liquid metal.");
add_size(MINSIZE,0);
set_class(4);
set_parry_ac(4);
}
mixed d_types(string s) {
if (!s) return CLUB;
s = lower_case(s);
switch (s) {
case "axe" : return AXE;
case "club" : return CLUB;
case "curved blade" : return CURVED;
case "flail" : return FLAIL;
case "knife" : return KNIFE;
case "longsword" : return LONGSWORD;
case "polearm" : return POLE_BLADE;
case "rapier" : return RAPIER;
case "shortsword" : return SHORTSWORD;
case "spear" : return SPEAR;
case "staff" : return STAFF;
case "two handed axe" : return TWO_H_AXE;
case "two handed sword" : return TWO_H_SWORD;
default : return CLUB;
}
}
string a_an_string(string word) {
string letter;
if (!word) return word;
letter = extract(word,0,0);
if (letter == "a" || letter == "e" ||
letter == "i" || letter == "o" ||
letter == "u")
return "an "+word;
return "a "+word;
}
string short_size() {
switch(size) {
case 0..6 : return "small ";
case 7..9 : return "";
case 10..12 : return "medium-sized ";
case 13..15 : return "large ";
case 16..20 : return "huge ";
case 21..40 : return "enormous ";
default : return "unknown ";
}
}
void fix_short() {
set_short(a_an_string(short_size())+lower_case(query_weapon_type()));
set_long("The "+short_size()+lower_case(query_weapon_type())+" seems to be made of a shiny liquid metal.");
}
int add_weight_bonus(int x) {
weight_bonus += x;
if (weight_bonus < 0) weight_bonus=0;
set_weight(size/6+1+weight_bonus);
TP->fix_carry();
}
int add_size(int x, int ignore_counter) {
int lvl;
int mwc;
size += x;
if (!ignore_counter) {
size_counter += x*DAMAGE_SIZE;
}
if (size < MINSIZE)
size=MINSIZE;
if (size_counter < MINSIZE*DAMAGE_SIZE)
size_counter = MINSIZE*DAMAGE_SIZE;
fix_short();
ret_val = 0;
set_weight(size/6+1+weight_bonus);
mwc = this_object()->max_wc();
if (size < mwc) {
set_class(size);
} else {
set_class(mwc);
ret_val = size - mwc;
}
if (TP)
TP->fix_carry();
}
int query_hp_weight_cost(int i) {
return WEAPON_HP_WEIGHT + i*2;
}
int query_hp_cost_eq(int s) {
return 5+s*s/40;
}
int query_hp_cost() { return query_hp_cost_eq(size); }
int query_size() { return size; }
string query_form() { return ROCK3; }
int hit(object att) {
object env;
object shape;
int ret_bonus;
size_counter--;
env = environment();
if (size_counter < MINSIZE*DAMAGE_SIZE)
size_counter = MINSIZE*DAMAGE_SIZE;
if (size > size_counter/DAMAGE_SIZE) {
shape = present(ROCK3+"_shape",env);
if (shape) { // This should always be true... but just incase...
shape->add_bonus_hp(-1*query_hp_cost());
}
CLASSOB(env)->add_learning("mweapon");
add_size(-1,1);
}
if (!random(DAMAGE_SIZE) && size > MINSIZE)
tell_room(environment(att),"Small pieces break off the "+lower_case(query_weapon_type())+".\n");
ret_bonus = DAMAGE(ROCK3+"_weap",env,"mweapon",20,2,0);
return ret_val+ret_bonus;
}
int max_wc() {
return MOD_D->mimeon_max_wc(weapon_type,twohanded);
}
int query_hp_restore() {
int i;
int x;
for(i=size;i>MINSIZE;i--)
x +=query_hp_cost_eq(i);
for(i=weight_bonus;i>=0;i--)
x += query_hp_weight_cost(i);
//return (size-(MINSIZE-1))*WEAPON_HP_SIZE;
return x;
}
int query_weight_bonus() { return weight_bonus; }
// Exploding weapons!
// No ::init since we cant unwield or wield
void init() {
add_action("do_spike","spike");
if (TP==environment(this_object()))
call_out("wieldme",0,TP);
}
void wieldme(object who) {
object *inv;
int i;
int num;
int found;
inv = all_inventory(environment(this_object()));
for(i=0;i<sizeof(inv);i++) {
if (inv[i]->id(query_name()) && !found) {
num++;
}
if (inv[i] == this_object()) found=1;
}
if (who != environment()) return;
this_object()->un_wield();
explode = 0;
if (hand)
this_object()->wield(query_name()+" "+num+" in "+who->query_secondary_hand_str()+" hand");
else
if (twohanded)
this_object()->wield(query_name()+" "+num+" in both hands");
else
this_object()->wield(query_name()+" "+num);
}
int do_spike(string str) {
object *inv;
object ob;
object weap;
ob = CLASSOB(TP);
if (!ob) return 0;
if (ob->query_size("mimeon") < 4) return 0;
inv = filter_array(all_inventory(this_player()),
lambda( ({'x}),({#'call_other, 'x, "query_mimeon_shifter_item"}) )); //'
weap = SXFUN->present_array(str,inv);
if (weap != this_object()) {
notify_fail("Spike what?\n");
return 0;
}
if (explode) {
notify_fail("You are already concentrating to shoot spikes from your "+query_name()+".\n");
return 0;
}
explode = 1;
this_player()->add_hook("damage_dealt",({"my_damage_dealt"}));
write("You start concentrating on your weapon to shoot spikes out when it hits.\n");
return 1;
}
void my_damage_dealt(int dam) {
object env;
object att;
object shape;
int size_mod;
int amt,x,i;
if (!explode) return; // Shouldnt ever happen.
if (!this_object()->query_wielded()) return;
if (!dam) return;
env = environment(this_object());
if (!env) return;
att = env->query_attack();
if (!att || att->query_dead()) return;
explode = 0;
x = 0;
// for(i=size;i>MINSIZE && i>=size-2;i--)
// x +=query_hp_cost_eq(i);
if (size > MINSIZE)
x+= query_hp_cost();
if (weight_bonus)
x+= query_hp_weight_cost(weight_bonus);
amt = MOD_D->damage_function(ROCK3+"_spike",env,x,"mimeon","spike",10,1,dam);
if (att->query_is_player()) amt *=2;
env->remove_hook("damage_dealt");
if (x)
CLASSOB(env)->add_learning("spike");
tell_object(env,"You shoot spikes from your "+query_name()+" into "+att->query_name()+".\n");
tell_object(env,"The spikes break off as you pull the "+query_name()+" back.\n");
tell_room(environment(env),get_f_string(env->query_name()+" causes spikes to shoot out of "+
env->query_possessive()+" "+query_name()+"!",0,strlen(env->query_name())+1),({env,att}));
tell_object(att,get_f_string("As "+env->query_name()+"'s "+query_name()+" hits you, spikes shoot out from it, snapping off inside you!",0,0));
att->hit_player(amt);
if (size > MINSIZE)
add_size(-1,0);
if (weight_bonus)
add_weight_bonus(-1);
shape = present(ROCK3+"_shape",env);
if (shape) { // This should always be true... but just incase...
shape->add_bonus_hp(-1*x);
}
}
no_disarm() { return 1; }