/* player.c */
#include <secure.h>
#include <sys.h>
#include <weapon.h>
#include <combat_def.h>
#include <flags.h>
#include <armor.h>
#define TP(X) tell_player(this_object(),(X))
#define TPE(X) tell_room_except(location(this_object()),this_object(),(X))
#define TPE2(X) tell_room_except2(location(this_object()),this_object(), \
is_attacking,(X))
object me;
object is_attacking;
string name;
string low_name;
string password;
int alive,hp,max_hp,xp,level,flags,special,gold,armor_dam,armor_hit,is_healing;
object weapon,possessor;
object armor_worn[NUM_PROT];
add_gold(arg) { gold+=arg; return 1; }
static autoheal() {
hp+=HEAL_AMOUNT;
if (hp>=max_hp) {
hp=max_hp;
is_healing=0;
} else
alarm(HEAL_DELAY,"autoheal");
}
static do_exits(arg) {
object curr;
int count,pos;
string ename;
if (location(this_object())) curr=contents(location(this_object()));
while (curr) {
if (call_other(curr,"get_type")==TYPE_EXIT)
if (!(call_other(curr,"get_flags") & F_DARK)) {
if (!count) write("Obvious exits:");
ename=call_other(curr,"get_name");
pos=instr(ename,1,";");
if (pos)
write(" "+leftstr(ename,pos-1));
else
write(" "+ename);
count++;
}
curr=next_object(curr);
}
if (!count)
write("There are no obvious exits\n");
else
write("\n");
return 1;
}
static do_wear(arg) {
string w_name;
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,this_object());
if (!arg) {
write("You don't have that.\n");
return 1;
}
if (call_other(arg,"get_type")!=TYPE_ARMOR) {
write("You can't wear that.\n");
return 1;
}
if (armor_worn[call_other(arg,"get_protection")]) {
write("You're already wearing something on your "+
make_prot(call_other(arg,"get_protection"))+".\n");
return 1;
}
w_name=call_other(arg,"get_short");
if (!call_other(arg,"wear")) {
write("You can't wear that.\n");
return 1;
}
write("You wear "+w_name+".\n");
TPE(get_short()+" wears "+w_name+".\n");
armor_worn[call_other(arg,"get_protection")]=arg;
recalc_armor();
return 1;
}
recalc_armor() {
int loop;
armor_hit=0;
armor_dam=0;
loop=0;
while (loop<NUM_PROT) {
if (armor_worn[loop]) {
armor_hit+=call_other(armor_worn[loop],"get_hitreduce");
armor_dam+=call_other(armor_worn[loop],"get_damreduce");
}
loop++;
}
}
force_unwear(p) {
if (armor_worn[p]!=caller_object()) return;
armor_worn[p]=0;
recalc_armor();
}
static do_unwear(arg) {
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,this_object());
if (call_other(arg,"get_type")!=TYPE_ARMOR) {
write("You're not wearing that.\n");
return 1;
}
if (armor_worn[call_other(arg,"get_protection")]!=arg) {
write("You're not wearing that.\n");
return 1;
}
if (call_other(arg,"unwear")) {
write("You can't unwear that.\n");
return 1;
}
armor_worn[call_other(arg,"get_protection")]=0;
recalc_armor();
write("You unwear "+call_other(arg,"get_short")+".\n");
TPE(get_short()+" unwears "+call_other(arg,"get_short")+".\n");
return 1;
}
stat() {
tell_player(this_player(),"Object Type: PLAYER\n");
if (flags) tell_player(this_player(),"Flags: "+make_flags(flags)+"\n");
if (special) tell_player(this_player(),"Special: "+itoa(special)+"\n");
if (name)
tell_player(this_player(),"Name: "+name+"\n");
if (alive)
tell_player(this_player(),"HP: "+itoa(hp)+"/"+itoa(max_hp)+
" XP: "+itoa(xp)+" Level: "+itoa(level)+"\n");
else
tell_player(this_player(),"HP: DEAD/"+itoa(max_hp)+" XP: "+
itoa(xp)+" Level: "+itoa(level)+"\n");
tell_player(this_player(),"HitReduce: "+itoa(2*level-2)+" (With Armor: "+
itoa(armor_hit+2*level-2)+")\n");
tell_player(this_player(),"DamReduce: 0 (With Armor: "+itoa(armor_dam)+
")\n");
tell_player(this_player(),"Damage: 1d2+0 (With Weapon: "+(weapon?
call_other(weapon,"get_damage"):"1d2+0")+")\n");
tell_player(this_player(),"HitBonus: "+itoa(2*level-2)+" (With Weapon: "+
itoa(2*level-2+(weapon?call_other(weapon,"get_hit_bonus"):0))+
")\n");
if (weapon)
tell_player(this_player(),"Wielding: "+make_num(weapon)+"\n");
if (is_attacking)
tell_player(this_player(),"Is Attacking: "+make_num(is_attacking)+"\n");
if (possessor && priv(this_player()))
tell_player(this_player(),"Possessed By: "+make_num(possessor)+"\n");
return 1;
}
is_player() { return 1; }
id(arg) { return arg==name || arg==low_name; }
get_uid() { return low_name; }
set_possessor(arg) {
if (!priv(caller_object())) return 0;
if (!arg && possessor==caller_object()) {
possessor=0;
return 1;
}
if (arg!=caller_object()) return 0;
if (possessor && arg) return 0;
possessor=arg;
return 1;
}
force_disconnect() {
if (!priv(caller_object())) return 0;
disconnect_device();
disconnect();
return 1;
}
force(arg) {
command(arg);
return 1;
}
set_name(arg) {
if (prototype(this_object())) return;
if (name) return;
name=arg;
low_name=downcase(arg);
return 1;
}
set_password(arg) {
if (!arg) return;
if (prototype(this_object())) return;
if (!priv(caller_object())) return;
password=arg;
return 1;
}
set_flags(f) { flags=f; return 1; }
set_special(s) { special=s; return 1; }
get_flags() { return flags; }
get_special() { return special; }
static do_password(arg) {
string p1,p2;
int pos;
pos=instr(arg,1," ");
p1=leftstr(arg,pos-1);
p2=rightstr(arg,strlen(arg)-pos);
if (!p1 || !p2) {
write("usage: password oldpass newpass\n");
return 1;
}
if (p1!=password) {
write("Wrong password.\n");
return 1;
}
password=p2;
write("Password changed.\n");
return 1;
}
do_say(arg) {
write("You say \""+arg+"\"\n");
TPE(get_short()+" says \""+arg+"\"\n");
return 1;
}
do_pose(arg) {
write(get_short()+" "+arg+"\n");
TPE(get_short()+" "+arg+"\n");
return 1;
}
check_password(arg) {
if (!priv(caller_object())) return 0;
return password==arg;
}
add_xp(arg) {
int new_level,new_xp;
xp+=arg;
if (xp<(new_xp=1000)) new_level=1;
else if (xp<(new_xp=2000)) new_level=2;
else if (xp<(new_xp=3500)) new_level=3;
else if (xp<(new_xp=7000)) new_level=4;
else if (xp<(new_xp=10000)) new_level=5;
else if (xp<(new_xp=14000)) new_level=6;
else if (xp<(new_xp=20000)) new_level=7;
else if (xp<(new_xp=30000)) new_level=8;
else if (xp<(new_xp=60000)) new_level=9;
else if (xp<(new_xp=100000)) new_level=10;
else if (xp<(new_xp=160000)) new_level=11;
else if (xp<(new_xp=250000)) new_level=12;
else if (xp<(new_xp=380000)) new_level=13;
else if (xp<(new_xp=600000)) new_level=14;
else new_level=15;
if (arg) write("You gain "+itoa(arg)+" XP.\n");
if (new_level!=level) {
level=new_level;
recalc_max_hp();
write("You are now level "+itoa(level)+". ");
if (new_level<15) write("Next level at "+itoa(new_xp)+" XP.\n");
else write("\n");
}
}
recalc_max_hp() {
max_hp=10+4*level;
if (max_hp>hp && !is_healing) {
is_healing=1;
alarm(HEAL_DELAY,"autoheal");
} else
hp=max_hp;
}
impending_attack() {
if (is_attacking) return (xp/20);
is_attacking=caller_object();
attack(0);
return (xp/20);
}
get_name() {
return name;
}
get_hit_msg1(intensity) {
string s;
if (weapon) s=call_other(weapon,"get_hit_msg1",intensity);
if (!s) s=get_def_hit_msg1(intensity);
return s;
}
get_hit_msg2(intensity) {
string s;
if (weapon) s=call_other(weapon,"get_hit_msg2",intensity);
if (!s) s=get_def_hit_msg2(intensity);
return s;
}
get_hit_msg3(intensity) {
string s;
if (weapon) s=call_other(weapon,"get_hit_msg3",intensity);
if (!s) s=get_def_hit_msg3(intensity);
return s;
}
get_hit_msg4(intensity) {
string s;
if (weapon) s=call_other(weapon,"get_hit_msg4",intensity);
if (!s) s=get_def_hit_msg4(intensity);
return s;
}
get_hit_msg5(intensity) {
string s;
if (weapon) s=call_other(weapon,"get_hit_msg5",intensity);
if (!s) s=get_def_hit_msg5(intensity);
return s;
}
get_long() {
if (alive)
return "This is the player "+name;
else
return "This is the insubstantial ghost of the player "+name;
}
move_player(dest,direction) {
if (location(this_object()))
TPE(get_short()+" goes "+direction+".\n");
move_object(this_object(),dest);
look(0);
if (dest)
TPE(get_short()+" has arrived.\n");
return 1;
}
look(arg) {
int contents_printed,curr;
string oname,t;
contents_printed=0;
t=arg;
if (arg) {
arg=present(arg,location(this_object()));
if (!arg) arg=present(t,this_object());
if (!arg && t=="me") arg=this_object();
if (!arg && t=="here") arg=this_object();
} else
if (!location(this_object())) {
write("You are in the void.\n");
return 1;
} else
arg=location(this_object());
if (!arg) {
write("You don't see that here.\n");
return 1;
}
if (arg==location(this_object())) {
oname=call_other(arg,"get_short");
if (oname) write(oname+"\n");
}
oname=call_other(arg,"get_long");
if (oname) write(oname+"\n");
curr=contents(arg);
if (!(call_other(arg,"get_flags") & F_DARK))
while (curr) {
if (curr!=this_object()) {
oname=call_other(curr,"get_short");
if (oname) {
if (!contents_printed) {
write("Contents:\n");
contents_printed=1;
}
write(oname+"\n");
}
}
curr=next_object(curr);
}
return 1;
}
get_type() { return TYPE_PLAYER; }
find_enemy() { is_attacking=0; }
is_living() { return alive; }
get_short() { return alive ? name:"Ghost of "+name; }
to_hit_bonus() {
int bonus;
if (weapon)
bonus=call_other(weapon,"get_hit_bonus",is_attacking);
else
bonus=0;
return bonus+2*level-2;
}
damage_bonus() {
int bonus;
if (weapon)
bonus=call_other(weapon,"get_damage_bonus",is_attacking);
else
bonus=random(2)+1;
return bonus;
}
static do_kill(arg) {
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,location(this_object()));
if (!arg) {
write("You don't see that here.\n");
return 1;
}
if (!call_other(arg,"is_living")) {
write("You can't kill that, you bonehead.\n");
return 1;
}
if (arg==this_object()) {
write("PLEASE try to control your suicidal impulses.\n");
return 1;
}
if (arg==is_attacking) {
write("You're already attacking that. Chill.\n");
return 1;
}
write("You start attacking "+call_other(arg,"get_short")+".\n");
tell_player(arg,name+" starts attacking you.\n");
tell_room_except2(location(this_object()),arg,this_object(),name+
" starts attacking "+call_other(arg,"get_short")+".\n");
attack(arg);
return 1;
}
do_damage(amount) {
int retval,intensity;
object curr,next;
amount-=armor_dam;
if (amount<0) amount=0;
if (!is_healing) {
is_healing=1;
alarm(HEAL_DELAY,"autoheal");
}
retval=(amount>hp)?hp:amount;
hp-=amount;
if (amount<I_PUNY_AMT)
intensity=I_PUNY;
else if (amount<I_WEAK_AMT)
intensity=I_WEAK;
else if (amount<I_POOR_AMT)
intensity=I_POOR;
else if (amount<I_AVERAGE_AMT)
intensity=I_AVERAGE;
else if (amount<I_GOOD_AMT)
intensity=I_GOOD;
else if (amount<I_VERYGOOD_AMT)
intensity=I_VERYGOOD;
else intensity=I_MASSACRE;
write(call_other(caller_object(),"get_short")+" "+
call_other(caller_object(),"get_hit_msg3",intensity)+"\n");
write("You have "+itoa((hp>0)?hp:0)+" hit points left.\n");
if (hp<1) {
write("You have died. Your ghost now hovers around uselessly.\n");
hp=0;
alive=0;
is_attacking=0;
curr=clone_object("/obj/corpse");
call_other(curr,"set_name",name);
move_object(curr,location(this_object()));
if (gold>0) {
curr=clone_object("/obj/coins");
call_other(curr,"set_value",gold);
move_object(curr,location(this_object()));
gold=0;
}
curr=contents(this_object());
while (curr) {
next=next_object(curr);
if (call_other(curr,"drop")) {
if (!call_other(curr,"dead_drop"))
move_object(curr,location(this_object()));
} else
move_object(curr,location(this_object()));
curr=next;
}
}
return retval;
}
static do_reincarnate(arg) {
if (alive)
write("Idiot, you haven't DIED yet.\n");
else {
if (!location(this_object())) {
write("You're not in a temple, you're in the hideous void.\n");
return 1;
}
if (!(call_other(location(this_object()),"get_flags") & F_TEMPLE)) {
write("You're not in a temple.\n");
return 1;
}
hp=1;
alive=1;
is_healing=1;
xp=xp/2;
add_xp(0);
alarm(HEAL_DELAY,"autoheal");
write("You come back to life, you hot ticket.\n");
TPE(name+" stops being a ghost, regains flesh, etc.\n");
}
return 1;
}
attempt_hit(chance) {
return chance+52-armor_hit-(2*level)>random(100);
}
get_hitreduce() { return armor_hit; }
get_damreduce() { return armor_dam; }
attack(enemy) {
int enemy_xp,intensity,dmg,tmp;
string ename;
if (enemy==this_object()) return;
if (is_attacking==this_object()) {
is_attacking=0;
return;
}
if (!alive) {
is_attacking=0;
return;
}
if (enemy)
if (is_attacking) {
is_attacking=enemy;
return;
} else
is_attacking=enemy;
if (!is_attacking)
find_enemy();
if (!is_attacking) return;
if (!call_other(is_attacking,"is_living")) find_enemy();
if (!is_attacking) return;
if (location(is_attacking)!=location(this_object()))
find_enemy();
if (!is_attacking) return;
ename=call_other(is_attacking,"get_short");
enemy_xp=call_other(is_attacking,"impending_attack");
if (!alive) return;
if (call_other(is_attacking,"attempt_hit",to_hit_bonus())) {
dmg=damage_bonus();
tmp=call_other(is_attacking,"do_damage",dmg);
if (dmg<I_PUNY_AMT) {
intensity=I_PUNY;
} else if (dmg<I_WEAK_AMT) {
intensity=I_WEAK;
} else if (dmg<I_POOR_AMT) {
intensity=I_POOR;
} else if (dmg<I_AVERAGE_AMT) {
intensity=I_AVERAGE;
} else if (dmg<I_GOOD_AMT) {
intensity=I_GOOD;
} else if (dmg<I_VERYGOOD_AMT) {
intensity=I_VERYGOOD;
} else {
intensity=I_MASSACRE;
}
TP(get_hit_msg1(intensity)+ename+get_hit_msg2(intensity)+"\n");
TPE2(get_short()+" "+get_hit_msg4(intensity)+ename+get_hit_msg5(intensity)
+"\n");
if (!call_other(is_attacking,"is_living")) {
TP("You have killed "+ename+"!\n");
TPE2(get_short()+" has killed "+ename+"!\n");
add_xp(enemy_xp);
find_enemy();
}
} else {
TP("You missed "+ename+".\n");
tell_player(is_attacking,get_short()+" misses you.\n");
TPE2(get_short()+" misses "+ename+".\n");
}
alarm(3,"attack");
}
do_quit(arg) {
TPE(get_short()+" has disconnected.\n");
disconnect_device();
return 1;
}
static do_inventory(arg) {
int count;
object curr;
string oname;
count=0;
curr=contents(this_object());
while (curr) {
oname=call_other(curr,"get_short");
if (oname) {
if (!count) {
write("You are carrying:\n");
}
count++;
write(oname+"\n");
}
curr=next_object(curr);
}
if (gold) write("You have "+itoa(gold)+" gold coins.\n");
if (!count && !gold)
write("You are empty-handed.\n");
return 1;
}
get_gold() { return gold; }
static do_score(arg) {
if (alive) {
write("HP: "+itoa(hp)+"/"+itoa(max_hp)+" Level: "+itoa(level)+
" XP: "+itoa(xp)+" Gold: "+itoa(gold)+"\n");
} else
write("You are dead. This implies your score kinda SUCKS.\n");
return 1;
}
static do_help(arg) {
object curr,found;
string s;
if (arg) {
curr=next_child(atoo("/sys/help1"));
while (curr && !found) {
if (call_other(curr,"get_topic")==arg) found=curr;
curr=next_child(curr);
}
if (!found) {
write("There is no help available on that topic.\n");
return 1;
}
s=(call_other(found,"get_text"));
if (s) write("\n"+s+"\n");
else write("Help has not been entered for that topic.\n");
return 1;
}
write("\nHelp available for the following:\n");
write("---------------------------------\n");
curr=next_child(atoo("/sys/help1"));
while (curr) {
write(call_other(curr,"get_topic")+" ");
curr=next_child(curr);
}
write("\n\n");
return 1;
}
static banner() {
cat("/motd");
look(0);
}
connect() {
TPE(get_short()+" has connected.\n");
alarm(0,"banner");
}
static do_huh(arg) {
write(HUH_STRING);
}
static do_quit(arg) {
write("Bye!\n");
disconnect_device();
disconnect();
return 1;
}
static do_who(arg) {
who_list();
return 1;
}
static do_get(arg) {
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,location(this_object()));
if (!arg) {
write("You don't see that here.\n");
return 1;
}
if (!call_other(arg,"get")) {
write("You can't get "+call_other(arg,"get_short")+".\n");
return 1;
}
move_object(arg,this_object());
write("You get "+call_other(arg,"get_short")+".\n");
TPE(get_short()+" gets "+call_other(arg,"get_short")+"\n");
move_object(arg,this_object());
return 1;
}
static do_drop(arg) {
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,(this_object()));
if (!arg) {
write("You don't have that.\n");
return 1;
}
if (call_other(arg,"drop")) {
write("You can't drop "+call_other(arg,"get_short")+".\n");
return 1;
}
write("You drop "+call_other(arg,"get_short")+".\n");
TPE(get_short()+" drops "+call_other(arg,"get_short")+"\n");
move_object(arg,location(this_object()));
return 1;
}
static do_wield(arg) {
string w_name;
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,this_object());
if (!arg) {
write("You don't have that.\n");
return 1;
}
if (weapon) {
write("You are already wielding a weapon.\n");
return 1;
}
w_name=call_other(arg,"get_short");
if (!call_other(arg,"wield")) {
write("You can't wield that.\n");
return 1;
}
write("You wield "+w_name+".\n");
TPE(get_short()+" wields "+w_name+".\n");
weapon=arg;
return 1;
}
force_unwield() {
if (weapon!=caller_object()) return;
weapon=0;
}
static do_unwield(arg) {
if (!alive) {
write("You're too dead.\n");
return 1;
}
arg=present(arg,this_object());
if (arg!=weapon) {
write("You aren't wielding that.\n");
return 1;
}
if (call_other(arg,"unwield")) {
write("You can't unwield "+call_other(arg,"get_short")+".\n");
return 1;
}
weapon=0;
write("You unwield "+call_other(arg,"get_short")+".\n");
TPE(get_short()+" unwields "+call_other(arg,"get_short")+".\n");
return 1;
}
disconnect() {
TPE(get_short()+" has disconnected.\n");
}
static init() {
check_secure(SECURE_PRIV,"");
alive=1;
set_interactive();
max_hp=14;
hp=max_hp;
xp=0;
level=1;
me=this_object();
if (!prototype(me)) return;
add_xverb("","do_huh");
add_verb("say","do_say");
add_verb("pose","do_pose");
add_xverb(":","do_pose");
add_xverb("\"","do_say");
add_verb("help","do_help");
add_verb("?","do_help");
add_verb("i","do_inventory");
add_verb("inventory","do_inventory");
add_verb("l","look");
add_verb("look","look");
add_verb("drop","do_drop");
add_verb("get","do_get");
add_verb("take","do_take");
add_verb("wield","do_wield");
add_verb("unwield","do_unwield");
add_verb("who","do_who");
add_verb("quit","do_quit");
add_verb("reincarnate","do_reincarnate");
add_verb("kill","do_kill");
add_verb("score","do_score");
add_verb("QUIT","do_quit");
add_verb("WHO","do_who");
add_verb("password","do_password");
add_verb("exits","do_exits");
add_verb("wear","do_wear");
add_verb("unwear","do_unwear");
}
listen(arg) {
send_device(arg);
if (possessor) call_other(possessor,"possession_report",arg);
}