/* mmm, now I start to see the advantage with shadows... */ inherit "/std/object"; inherit "/inherit/gender"; inherit "/inherit/property"; inherit "/inherit/msg"; inherit "/inherit/money"; int spell_points,max_spell_points; int hit_points,max_hit_points; string name,full_name; int life_count; int skin_armour; string short_desc; string long_desc; string msgin="\b1PRON arrives.\n"; string msgout="\b1PRON leaves \bWHERE.\n"; string mmsgin="\b1PRON arrives in a puff of smoke.\n"; string mmsgout="\b1PRON dissappears in a puff of smoke.\n"; static list armours; static int armour_class=-1; static object *wielded=({}); static object *followers=({}); static object attacker,alt_attacker; static int attacker_life_count,alt_attacker_life_count; static int local_weight=0; mapping magic_protection=([]); int Dex,Str,Int,Con; string short() { return short_desc; } void set_short(string s) { short_desc=s; } string query_long() { return long_desc; } void set_long(string s) { long_desc=s; } int query_get() { return 0; } void say(string s) { tell_room(environment(),s,({this_object()})); } int add_weight(int w) { if(local_weight+w>Str+10) return 0; local_weight+=w; return 1; } void attack(); int check_attacker(); #define ARMOUR_TYPES (<"armour","ring","helmet","glove","boot","pants","cloak">) void create() { enable_commands(); } string query_name() { return full_name; } string query_real_name() { return name; } int id(string s) { return full_name && s==lower_case(full_name); } void query_life_count() { return life_count; } list query_worn() { return armours; } object query_attacker() { return attacker; } object query_alt_attacker() { return alt_attacker; } int query_attacker_life_count() { return attacker_life_count; } int query_alt_attacker_life_count() { return alt_attacker_life_count; } int query_hit_points() { return hit_points; } int query_spell_points() { return spell_points; } int reduce_hit_points(int pts) { return hit_points-pts; } int reduce_spell_points(int pts) { return spell_points-pts; } int query_living() { return 1; } /* yes, this is a living */ int calculate_armour_class() { object o; armours-=(<0>); armour_class=0; foreach(indices(armours),o) armour_class+=o->query_class(); armour_class/=3; /* ? */ return armour_class; } void die() /* redefine this when you inherit */ { object o,oo; msg("\b1PRON die$.\n"); life_count++; o=clone_object("/obj/corpse"); foreach(all_inventory(),oo) { if(!oo->query_drop(1)) continue; oo->move(o); } o->set_name(query_real_name()); o->move(environment()); } int is_attacking(object ob) { if(ob==attacker && ob->query_life_count()==attacker_life_count) return 1; if(ob==alt_attacker && ob->query_life_count()==alt_attacker_life_count) return 1; return 0; } void attack_object(object o) { set_heart_beat(1); if(is_attacking(o)) return; alt_attacker=o; alt_attacker_life_count=o->query_life_count(); if(!o->is_attacking(this_object())) attack(); } int hit_player(int damage) { if(armours[0] || armour_class<0) calculate_armour_class(); if(this_player()!=this_object()) attack_object(this_player()); damage-=random((Dex+armour_class*2)/3); if(damage<=0) return 0; hit_points-=damage; if(hit_points<0) die(); return damage; } /* let's do one attack for every wielded weapon... */ void physical_attack() { object o; if(!check_attacker()) return; wielded-=({0}); foreach(wielded,o) { int force,dam; if(o->do_attack(attacker)) continue; force=random((Dex+o->query_weapon_class()*2)/3); dam=attacker->hit_player(force); if(!o->message(force,dam)) { switch(dam) { case 0: switch(force) { case 0..5: msg("\b1PRON missed \b2OBJ.\n",this_object(),attacker); break; default: msg("\b2PRON dodge$ \b1POSS attack.\n",this_object(),attacker); } break; case 1..2: msg("\b1PRON tickle$ \b2OBJ in the stomach.\n",this_object(),attacker); break; case 3..5: msg("\b1PRON graze$ \b2OBJ.\n",this_object(),attacker); break; case 6..10: msg("\b1PRON hit$ \b2OBJ.\n",this_object(),attacker); break; case 11..15: msg("\b1PRON hit$ \b2OBJ hard.\n",this_object(),attacker); break; case 16..20: msg("\b1PRON hit$ \b2OBJ very hard.\n",this_object(),attacker); break; case 21..25: msg("\b1PRON hit$ \b2OBJ with a bonecrushing sound.\n",this_object(),attacker); break; case 26..40: msg("\b1PRON massacer$ \b2OBJ to small fragments.\n",this_object(),attacker); break; default: msg("\b1PRON nuke$ \b2OBJ to vapours.\n",this_object(),attacker); break; } } } } void look(string s) {} /* stubs routine */ void alert_followers(object from,string how,object dest) { object o; followers-=({0}); followers&=all_inventory(from); map_array(followers,"do_follow",how,dest); } int move_player(string how,mixed dest) { object e; string in,out; e=environment(); if(!dest) sscanf(how,"%s#%s",how,dest); dest=(object)dest; e=environment(); if(e->player_leave(how,dest)) return 0; if(how=="X") { out=mmsgout; in=mmsgin; }else{ out=replace(msgout,"\bWHERE",how); in=msgin; } move_object(dest); tell_room(e,replace(out,"\b1PRON",query_name())); tell_room(environment(),replace(msgin,"\b1PRON",query_name()),({this_player()})); if(how!="X") alert_followers(e,how,dest); map_array(all_inventory(environment())-({this_object()}),"living_arrives",this_object()); } void living_arrives(object who) { if(who==alt_attacker) { swap(attacker,alt_attacker); swap(attacker_life_count,alt_attacker_life_count); } if(who==attacker) attack(); } int do_follow(string how,object dest) { return move_player(how,dest); } int check_attacker() { if(!attacker) { attacker=alt_attacker; attacker_life_count=alt_attacker_life_count; alt_attacker=0; } if(!attacker) return; if(environment(attacker)!=environment()) { if(alt_attacker && environment(alt_attacker)==environment()) { swap(attacker,alt_attacker); swap(attacker_life_count,alt_attacker_life_count); }else{ return; } } if(attacker->query_life_count!=attacker_life_count) { attacker=0; return check_attacker(); /* tailrecurse */ } return 1; } int spell_cost; mixed spell_mess,spell_dam; string magic_type; void magical_attack() { if(!check_attacker()) return; if(spell_points>=spell_cost) { int dam; spell_points-=spell_cost; if(intp(spell_dam)) { dam=attacker->magic_hit(spell_dam,magic_type); if(functionp(spell_mess)) { spell_mess(dam); }else{ msg(spell_mess,this_object(),attacker); switch(dam) { case -10000..1: msg("\b1PRON are unaffected.\n|\b1PRON is unaffected.\n",attacker); break; case 2..8: msg("\b1PRON are slightly shook.\n|\b1PRON looks slightly shaken.\n",attacker); break; case 9..20: msg("\b1PRON are damaged.\n|\b1PRON looks damaged.\n",attacker); break; case 21..40: msg("\b1PRON are seriously hit.\n|\b1PRON is seriously hit.\n",attacker); break; default: msg("\b1PRON are fundamentally destroyed.\n|\b1PRON is fundamentally destroyed.\n",attacker); break; } } }else{ spell_dam(attacker); /* do it yourself */ } } spell_mess=spell_dam=spell_cost=0; } int magical_hit(int power,string type) { power-=random(magic_protection[type]); if(power<=0) return 0; hit_points-=power; if(hit_points<0) die(); return power; } void set_spell(int cost,mixed dam,mixed mess,string type) { spell_cost=cost; spell_dam=dam; spell_mess=mess; magic_type=type; } void attack() { set_heart_beat(1); magical_attack(); physical_attack(); } void heart_beat() { attack(); set_heart_beat(check_attacker()); } /* money stuff */ int money; void add_money(int m) { money+=m; } int query_money() { return money; } int check_money(int m) { if(money>=m) { money-=m; return 1; } return 0; } int silent_unwield(object o,int mode) { if(o->do_unwield(this_object())) return 0; wielded-=({o}); return 1; } int unwield(object o,int mode) { if(-1==member_array(o,wielded)) { if(mode) return 1; tell_object(this_object(),"You're not wielding "+o->short()+".\n"); return 0; } if(!silent_unwield(o,mode)) return 0; tell_object(this_object(),"You unwield "+o->short()+".\n"); tell_room(environment(),query_name()+" wields "+o->short()+".\n",({this_object()})); return 1; } int silent_wield(object o,int mode) { if(o->do_wield(this_object())) return 0; wielded+=({o}); return 1; } int wield(object o,int mode) { if(-1!=member_array(o,wielded)) { if(mode) return 1; tell_object(this_object(),"You're already wielding "+o->short()+".\n"); return 0; } while(sizeof(wielded)) if(!unwield(wielded[0],0)) return 0; if(!silent_wield(o,mode)) return 0; tell_object(this_object(),"You wield "+o->short()+".\n"); tell_room(environment(),query_name()+" wields "+o->short()+".\n",({this_object()})); return 1; }