#include "../shifter.h"
#include <classes.h>
#define SIZES ({ \
({"medium"}), \
({"small", "big"}), \
({"small","medium", "big"}), \
({"small", "medium", "big", "biggest"}), \
({"smallest", "small", "medium", "big", "biggest"}) \
})
#define ORDER ({"primary","second","third","fourth","fifth","sixth"})
inherit "/obj/treasure";
inherit PATH+"help";
#define SAVE(X) save_forms(X);
#define RESTORE restore_forms();
void stop_casting(object ob);
int check_previous();
void save_forms(string who);
void restore_forms(string who);
void save_form_settings(object ob);
void set_form_settings(object ob);
int query_time(string shape);
int query_size(string shape);
int clear_info();
int query_maxtime_modifier(string form,int maxmod);
int query_clan_index(string clan);
int query_modifier(string clan);
void add_kills(string form);
static string current_form;
static string final_form;
string pendant_shape;
static int busy;
static int new_size;
mapping info;
mapping learning;
mapping base_duration;
mapping base_xp;
mapping kills;
mapping form_exp;
mapping misc;
static int restored; // Static so we dont load it up again
int feeling_toggle;
mapping form_settings;
create() {
::create();
if (!is_clone()) return;
set_name("pendant");
set_short("a small pendant");
set_alias(({"shapeshifters pendant"}));
set_long("The pendant is made of a small block of wood. "+
" It seems to be waiting to be carved into a shape.");
current_form = "basic";
busy = 0;
learning = ([ ]);
base_duration = ([ ]);
base_xp = ([ ]);
kills = ([ ]);
form_exp = ([ ]);
misc = ([ ]);
feeling_toggle = 1;
form_settings = ([]);
call_out("restore_forms",0);
}
short() {
mixed clan;
string first_clan;
if (!pendant_shape && environment()) {
clan = this_object()->query_clan_order();
if (clan != -1 && pointerp(clan) && sizeof(clan) > 0 ) {
first_clan = clan[0];
switch(first_clan) {
case "reptile" : pendant_shape = "a reptile";break;
case "forest" : pendant_shape = "a tree";break;
case "feline" : pendant_shape = "a cat";break;
case "earth" : pendant_shape = "a pebble";break;
}
return "a small pendant in the shape of "+pendant_shape;
}
return "a small pendant";
}
return "a small pendant in the shape of "+pendant_shape;
}
long() {
string long_string;
mixed clan;
string first_clan;
long_string = "It symbolises that you are a member of the shapeshifters "+
"enclave. Its shape represents your primary clan.\n "+
"see 'help clan' and 'help change'.";
if (!pendant_shape && environment()) {
clan = this_object()->query_clan_order();
if (clan != -1 && pointerp(clan) && sizeof(clan) > 0 ) {
first_clan = clan[0];
switch(first_clan) {
case "reptile" : pendant_shape = "a small reptile";break;
case "forest" : pendant_shape = "a small tree";break;
case "feline" : pendant_shape = "a small cat";break;
case "earth" : pendant_shape = "a small pebble";break;
}
writef("This is a small wooden pendant, that has been carved into "+
"the shape of "+pendant_shape+". "+long_string);
return;
}
writef("This is a small block of wood waiting to be carved into a "+
"clan symbol. "+long_string);
return;
}
writef("This is a small wooden pendant, that has been carved into the "+
"shape of "+pendant_shape+". "+long_string);
}
int check_kill(int arg) {
object env;
object att;
env = environment(this_object());
if (env && att = env->query_attack()) {
if (environment(env) == environment(att) &&
current_form != "basic") {
this_object()->add_kills(current_form);
}
}
return 0;
}
void set_kill_hook(object ob) {
// use align_bonus because its the only hook guaranteed to be called.
// owner_killer() is a present so it will be first ob only!
ob->remove_hook("align_bonus");
ob->add_hook("align_bonus", ({ "check_kill" }) );
}
init() {
::init();
if (environment(this_object()) != TP) return;
help::init();
add_action("change","change");
add_action("do_form", "form");
add_action("do_shapes", "shapes");
add_action("ctitle","ctitle");
add_action("do_shift","shift");
set_kill_hook(TP);
// incase of LD
stop_casting(TP);
call_out("check_earth",0);
}
// Incase players have rock and no earth clan
// Add it as the next clan
check_earth() {
while (remove_call_out("check_earth")!=-1);
// Check for info since it may not have restored yet
if (!info) {
call_out("check_earth",2);
}
if (this_object()->query_size("rock") &&
member_array("earth",this_object()->query_clan_order())==-1)
this_object()->add_clan("earth");
}
do_shapes(str) {
mapping data;
string *form, *form2, *clans;
int size, maxsize;
int i, c;
if (str) {
notify_fail("Usage: shapes\n");
return 0;
}
data = info;
if (!data) {
write("You do not know any forms!\n");
return 1;
}
form = m_indices(data);
form = filter_array(form, "query_form", FORMS);
clans = this_object()->query_clan_order();
form2 = filter_array(form,
lambda(({'form}),
({#'<=, ({ #'sizeof, ({ #'call_other, FORMS, "query_form",
({ #'call_other, FORMS, "query_form", 'form })
})
}), 2}) ) );
// should get non-clan forms
if (!pointerp(form2) || !sizeof(form2)) {
write("You do not know any forms.\n");
return 1;
}
write("Basic forms:\n");
form2 -= ({"opossum"});
size = this_object()->query_size("opossum");
write(" "+capitalize(FORMS->query_form_shape("opossum", size))+
" ("+SIZES[4][size-1]+" opossum)\n");
for (i=0;i<sizeof(form2);i++) {
size = this_object()->query_size(form2[i]);
maxsize = sizeof(FORMS->query_form_shapes()[form2[i]]);
write(" "+capitalize(FORMS->query_form_shape(form2[i], size))+
" ("+SIZES[maxsize-1][size-1]+" "+form2[i]+")\n");
}
if (pointerp(clans)) {
for (i=0;i<sizeof(clans);i++) {
write(capitalize(clans[i])+" forms ("+ORDER[i]+" clan):\n");
form2 = FORMS->query_form(clans[i]);
for (c=1;c<sizeof(form2);c++) {
if (size = this_object()->query_size(form2[c])) {
maxsize = sizeof(FORMS->query_form_shapes()[form2[c]]);
write(" "+capitalize(FORMS->query_form_shape(form2[c], size))+
" ("+SIZES[maxsize-1][size-1]+" "+form2[c]+")\n");
}
}
}
}
return 1;
}
do_form(str) {
object form_shape;
string form;
string shape;
int size;
if (str) { // no arg wanted...
notify_fail("Usage: form (no argument)\n");
return 0;
}
if (final_form) {
if (final_form == "basic") {
write("You are currently changing into "+(TP->query_real_race()?TP->query_real_race():TP->query_race())+" form.\n");
} else {
write("You are currently changing into "+final_form+" form.\n");
}
return 1;
}
form = query_current_form();
if (form == "basic") {
write("You are currently "+a_an_string((TP->query_real_race()?TP->query_real_race():TP->query_race()))+".\n");
} else {
form_shape = present(form+"_shape",TP);
if (form_shape)
size = form_shape->query_size();
if (!size) size=1;
shape = FORMS->query_form_shape(form,size);
write("You are currently "+a_an_string(shape)+" in "+form+" form.\n");
}
return 1;
}
find_cursed_items(ob) {
closure mine;
mine = lambda(({'x}),
({ #'&&, ({ #'&&, ({ #'||, ({ #'&&, ({ #'call_other, 'x, "query_is_weapon" }),
({ #'call_other, 'x, "query_wielded" })
}),
({ #'&&, ({ #'call_other, 'x, "query_is_armour" }),
({ #'call_other, 'x, "query_worn" })
})
}),
({ #'||, ({ #'call_other, 'x, "query_cursed"}),
({ #'call_other, 'x, "drop", 1 })
})
}),
({ #'!, ({ #'call_other, 'x, "query_is_shifter_item"})
})
})
);
return sizeof(filter_array(all_inventory(ob), mine));
}
change(string str) {
int x;
if (!str) {
notify_fail("Change [into] <what>?\n");
return 0;
}
if (TP->query_ghost()) {
notify_fail(get_f_string("You cannot change your physical form when "+
"you do not have one?\n"));
return 0;
}
if (busy) {
notify_fail("You are in the middle of a lesson! You cannot change now!.\n");
return 0;
}
if (query_current_form() == "basic" && find_cursed_items(TP)) {
write("Your equipment impedes your transformation.\n");
return 1;
}
sscanf(str,"into %s",str);
if ((sscanf(str,"%s %d",str,x) == 2) && x > 0)
new_size = x;
else
new_size = 0;
if ((stringp(FORMS->query_form(str)) &&
this_object()->query_size(str)) ||
str == "back")
return change_form(str);
write("Change [into] what?\n");
write("Choices :"+list_choices()+"\n");
return 1;
}
do_shift(string str) {
object who;
string *opt;
string *cur_opt;
string fm;
int x;
who = this_player();
// No message until you have all forms
if (! (MAX_FOREST && MAX_FELINE && MAX_REPTILE &&
MAX_ROCK && MAX_FORM("frog") &&
MAX_FORM("opossum")) ) {
return 0;
}
if (!str) {
notify_fail("Shift [into] <what>?\n");
return 0;
}
if (TP->query_ghost()) {
notify_fail(get_f_string("You cannot shift your physical form when "+
"you do not have one?\n"));
return 0;
}
if (busy) {
notify_fail("You are in the middle of a lesson! You cannot change now!.\n");
return 0;
}
if (current_form=="basic") {
notify_fail("You can only shift between max forms in primary clans.\n");
return 0;
}
sscanf(str,"into %s",str);
if ((sscanf(str,"%s %d",str,x) == 2) && x > 0)
new_size = x;
else
new_size = 0;
if ( (fm = FORMS->query_form(str)) && query_size(str)) {
opt = FORMS->query_form(fm);
if (sizeof(opt)==4 && opt[3]==str) {
fm = FORMS->query_form(current_form);
cur_opt = FORMS->query_form(fm);
if (sizeof(cur_opt)==4 && cur_opt[3]==current_form) {
return shift_form(str);
} else {
notify_fail("You are not in a final primary form to shift.\n");
return 0;
}
} else {
notify_fail("You can only shift to a final primary form.\n");
return 0;
}
}
notify_fail("Shift into what?\n");
return 0;
}
stop_change(val) {
busy = val;
}
string list_choices() {
string *forms;
string list;
int i;
list ="";
forms = m_indices(info);
forms = filter_array(forms, "query_form", FORMS);
for(i=0;i<sizeof(forms);i++) {
if (stringp(FORMS->query_forms()[forms[i]]) &&
CLASSOB(TP)->query_current_form() != forms[i] ){
list += " "+forms[i];
list += ((i==sizeof(forms)-1) &&
CLASSOB(TP)->query_current_form() == "basic") ? "." : ",";
}
}
if (CLASSOB(TP)->query_current_form() != "basic") list += " back.";
return get_f_string(list, 67, 10);
}
change_form(string form) {
object ob;
object env;
string next_form,form_type,start_msg;
string *all_forms;
string *dramas;
int delay,pos1,pos2,i;
int prevdelay,tmpdelay, modifier;
env = environment(this_object());
if (form == "back") form = "basic";
if (current_form == form) {
if (form == "basic")
write("You are already "+a_an_string((env->query_real_race()?env->query_real_race():env->query_race()))+".\n");
else
write("You are already "+a_an_string(form)+"!\n");
return 1;
}
if (final_form) {
if (final_form == "basic")
write("You are already changing into "+a_an_string((env->query_real_race()?env->query_real_race():env->query_race()))+"!\n");
else
write("You are already changing into "+a_an_string(final_form)+"!\n");
return 1;
}
form_type = FORMS->query_forms()[form];
if (!form_type)
form_type = FORMS->query_forms()[current_form];
if (!form_type) {
write("You are already "+a_an_string((env->query_real_race()?env->query_real_race():env->query_race()))+", you do not need to change!\n");
return 1;
}
if (form_type != FORMS->query_forms()[current_form] &&
FORMS->query_forms()[current_form]) {
write("You need to change back to "+(env->query_real_race()?env->query_real_race():env->query_race())+" before changing types of form.\n");
return 1;
}
// DEBUG("ChangeForm Form "+form+" Cur: "+current_form+" Type: "+form_type+"\n");
start_casting(env);
final_form = form;
all_forms = FORMS->query_forms()[form_type];
pos1 = member_array(form,all_forms);
pos2 = member_array(current_form,all_forms);
modifier = query_modifier(form_type);
delay = 0;
prevdelay = 0;
if (pos1 > pos2) {
next_form = all_forms[pos2 + 1];
if (call_other((OBJ+next_form),"query_cost") > env->query_sp()) {
write("You do not have the power to change!\n");
stop_casting(env);
return 1;
}
if (call_other((OBJ+next_form),"query_fail_change_requirement",env)) {
stop_casting(env);
return 1;
}
start_msg = call_other((OBJ+next_form),"query_start_change_message");
for(i=1;i<(pos1-pos2+1);i++) {
tmpdelay = check_delay(modifier,all_forms[(pos2+i)],form_type);
// tmpdelay = (modifier * call_other((OBJ+all_forms[(pos2+i-1)]),"query_delay"))/2;
delay += tmpdelay;
dramas = call_other((OBJ+all_forms[(pos2+i)]),"query_change_drama");
call_out("change_into",delay,all_forms[(pos2+i)]);
call_out("display_change_drama",prevdelay,dramas,tmpdelay);
prevdelay = delay;
}
} else {
next_form = all_forms[pos2 - 1];
if (call_other((OBJ+next_form),"query_cost") > environment(this_object())->query_sp()) {
write("You do not have the power to change!\n");
stop_casting(environment(this_object()));
return 1;
}
if (call_other((OBJ+next_form),"query_fail_change_requirement",environment(this_object()))) {
stop_casting(environment(this_object()));
return 1;
}
start_msg = call_other((OBJ+next_form),"query_change_back_message");
for(i=1;i<(pos2-pos1+1);i++) {
tmpdelay = check_delay(modifier,all_forms[(pos2-i+1)],form_type);
// tmpdelay = modifier * call_other((OBJ+all_forms[(pos2-i+1)]),"query_back_delay")/2;
delay += tmpdelay;
dramas = call_other((OBJ+all_forms[(pos2-i+1)]),"query_change_back_drama");
call_out("change_into",delay,all_forms[(pos2-i)]);
call_out("display_change_drama",prevdelay,dramas,tmpdelay);
prevdelay = delay;
}
}
if (next_form == current_form) next_form = form;
if (start_msg) {
write(start_msg[0]+"\n");
say(start_msg[1]+"\n");
} else {
if (form != "basic")
write("You start to change into "+a_an_string(next_form)+".\n");
else
write("You start to change back to normal.\n");
}
return 1;
}
shift_form(string form) {
object ob;
object env;
string next_form,form_type,start_msg;
string *all_forms;
string *dramas;
int delay,pos1,pos2,i;
int prevdelay,tmpdelay, modifier;
env = environment(this_object());
if (current_form == form) {
write("You are already "+a_an_string(form)+"!\n");
return 1;
}
if (final_form) {
write("You are already changing into "+a_an_string(final_form)+"!\n");
return 1;
}
form_type = FORMS->query_forms()[form];
if (!form_type)
form_type = FORMS->query_forms()[current_form];
start_casting(env);
final_form = form;
all_forms = FORMS->query_forms()[form_type];
modifier = query_modifier(form_type);
delay = 0;
prevdelay = 0;
if (call_other((OBJ+form),"query_cost") > env->query_sp()) {
write("You do not have the power to change!\n");
stop_casting(env);
return 1;
}
if (call_other((OBJ+form),"query_fail_change_requirement",env)) {
stop_casting(env);
return 1;
}
// Out of change_form. First Change 'back' then change forward
start_msg = call_other((OBJ+current_form),"query_shift_back_message");
tmpdelay = check_delay(modifier,current_form,form_type);
delay += tmpdelay;
dramas = call_other((OBJ+current_form),"query_shift_back_drama");
call_out("display_change_drama",prevdelay,dramas,tmpdelay);
prevdelay = delay;
if (start_msg) {
writef(start_msg[0]);
sayf(start_msg[1]);
}
tmpdelay = 2*modifier-query_maxtime_modifier(form,10);
if (tmpdelay < 2) tmpdelay=1+delay%2;
delay += tmpdelay/2;
start_msg = call_other((OBJ+form),"query_start_shift_message");
if (start_msg) {
call_out("delay_message",delay,start_msg[0],start_msg[1]);
}
delay += (tmpdelay -tmpdelay/2);
tmpdelay = check_delay(modifier,form,form_type);
delay += tmpdelay;
dramas = call_other((OBJ+form),"query_shift_drama");
call_out("change_into",delay,form,1);
call_out("display_change_drama",prevdelay,dramas,tmpdelay);
prevdelay = delay;
return 1;
}
int delay_message(string msg1, string msg2) {
writef(msg1);
sayf(msg2);
return 1;
}
int check_delay(int modifier, string form, string form_type) {
int tmpdelay;
int max_time;
int delay;
int form_delay_mod;
int min_mod;
int i;
string *all_forms;
int maxsize;
all_forms = FORMS->query_forms()[form_type];
all_forms -= ({ "basic" });
min_mod = 5;
// for each form in the list, check modifier
// allow higher forms to be sped up, but min at
// current rate. So no doubling effect on
// single forms or primary clan.
// Take off time to get the form, so this is bonus time only
for(i=0;i<sizeof(all_forms);i++) {
form_delay_mod = query_maxtime_modifier(all_forms[i],10)/2;
if (form_delay_mod < min_mod) min_mod = form_delay_mod;
//DEBUG("Max ("+all_forms[i]+") "+max_time+" "+form_delay_mod+" "+
// query_time(all_forms[i])+" "+maxsize);
}
form_delay_mod = query_maxtime_modifier(form,10)/2;
modifier -= min_mod;
if (modifier < 2) modifier = 2;
delay = call_other((OBJ+form),"query_delay") - form_delay_mod;
tmpdelay = (modifier * delay)/2;
//DEBUG("Delay: "+form+" "+tmpdelay+" "+modifier+" "+delay+" "+form_delay_mod+" "+
// min_mod+" "+max_time+" "+query_time(form));
return tmpdelay;
}
int query_maxtime_modifier(string form,int maxmod) {
string form_type;
int maxsize;
int max_time;
int mod;
int modifier;
form_type = FORMS->query_form(form);
if (!form_type) return 0;
modifier = query_modifier(form_type);
maxsize = sizeof(FORMS->query_form_shapes()[form]);
max_time = (modifier*(int)FORMS->query_duration(form,0,maxsize-2,
environment()->query_real_name()))/2;
return MOD_D->query_maxtime_modifier(form,max_time,query_time(form),maxmod);
}
display_change_drama(string *dramas,int tottime) {
int spacing1,spacing2;
if (!dramas || !pointerp(dramas)) return 0;
spacing1 = tottime/4;
spacing2 = 3*tottime/4;
call_out("do_message",spacing1,dramas[0],dramas[1]);
call_out("do_message",spacing2,dramas[2],dramas[3]);
}
do_message(string str1,string str2) {
tell_object(environment(),get_f_string(str1));
tell_room(environment(environment()),get_f_string(str2),({environment() }) );
}
change_into(string form,int shift) {
object env;
object ob;
string new_type;
int cost;
string *group, *order;
int p,q;
env = environment(this_object());
if (current_form!="basic" && !shift) {
group = FORMS->query_form(current_form); // the clan of current form
order = FORMS->query_form(group); // get the list of forms
p = member_array(current_form, order);
q = member_array(form,order);
if (p == -1 || q == -1) {
stop_casting(env);
raise_error("Missing "+current_form+" or "+form+" shape in form daemon\n");
}
}
if (p <= q) {
cost = (OBJ+form)->query_cost();
} else {
cost = 0;
}
if (env->query_sp() < cost) {
tell_object(env,"You do not have the power to change to "+a_an_string(form)+".\n");
stop_casting(env);
return 1;
}
if (WIZSPCHECK(env,50))
env->reduce_spell_points(cost);
if (current_form != "basic") {
ob = present(current_form+"_shape",env);
if (ob) {
save_form_settings(ob);
destruct(ob);
}
}
current_form = form;
if (form != "basic") {
ob = clone_object(OBJ+form);
ob->initialise(environment(),new_size);
set_form_settings(ob);
ob->move(env);
new_type = ob->query_type();
tell_object(env,"You change into "+a_an_string(new_type)+".\n");
say(env->query_name()+" changes into "+a_an_string(new_type)+".\n",env);
} else {
tell_object(env,"You change back to normal.\n");
say(env->query_name()+" changes into "+a_an_string((env->query_real_race()?env->query_real_race():env->query_race()))+"!\n",env);
}
if (final_form == form)
stop_casting(env);
SAVE(0);
return 1;
}
start_casting(object ob) {
ob->remove_hook("move_player");
ob->add_hook("move_player", ({ "check_movement" }) );
}
stop_casting(object ob) {
while(remove_call_out("change_into") != -1);
while(remove_call_out("do_message") != -1);
while(remove_call_out("display_change_drama") != -1);
ob->remove_hook("move_player");
final_form = 0;
}
owner_died() {
stop_casting(previous_object());
set_current_form("basic");
}
check_movement(dir,dest) {
int i;
i = remove_call_out("change_into");
if (i != -1) {
write("The movement disrupts your transformation.\n");
}
stop_casting(TP);
}
lose_form() {
string *order;
string group;
int p;
object nwob, form;
if (current_form == "basic") return;
group = FORMS->query_form(current_form); // the clan of current form
order = FORMS->query_form(group); // get the list of forms
p = member_array(current_form, order);
if (p==-1) {
raise_error("Missing "+current_form+" shape in form daemon\n");
return;
}
if (order[p-1] == "basic") {
set_current_form("basic");
tell_object(environment(), "You change into "+
a_an_string((environment()->query_real_race()?environment()->query_real_race():environment()->query_race()))+".\n");
return;
}
if (nwob = clone_object(OBJ+order[p-1])) {
if (form = present(current_form+"_shape", environment()))
destruct(form);
set_current_form(order[p-1]);
nwob->initialise(environment());
nwob->move(environment());
tell_object(environment(), "You change into "+
a_an_string(nwob->query_type())+".\n");
}
else {
raise_error("Missing shape file "+OBJ+order[p-1]+".c\n");
}
}
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;
}
set_current_form(string form) {
current_form = form;
}
query_current_form() { return current_form; }
drop() { return 1; }
ctitle(str) {
string cform;
int csize;
int plevel, pgender, forms;
mapping pdata;
string *clans,form_list;
string pclan,form_type;
string ntitle;
object who;
who = this_player();
clans = this_object()->query_clan_order();
if (clans != ({ }) && clans != -1)
pclan = clans[0];
else
pclan = "";
pdata = query_info();
forms = sizeof(m_indices(pdata));
pgender = (int)who->query_gender();
// Dont have all forms. Dont get the command
if (forms != (TOT_FORMS+1)) {
return 0;
}
// Havent maxed them all
if (! (MAX_FOREST && MAX_FELINE && MAX_REPTILE &&
MAX_ROCK && MAX_FORM("frog") &&
MAX_FORM("opossum")) ) {
return 0;
}
#ifndef TESTMUD
if (this_player()->query_guild()) {
notify_fail("You cannot use this command while in a guild.\n");
return 0;
}
#endif
if (!str) {
ntitle = (TP->query_class())->query_class_title(TP);
TP->set_title(ntitle);
write("You become: "+TP->query_name()+" "+ntitle+"\n");
return 1;
}
if (sscanf(str,"%s %d",cform,csize) != 2) {
notify_fail("Usage: ctitle <form> <size>\n");
return 0;
}
if (csize < 1) {
write("You do not get that small in "+cform+".\n");
return 1;
}
if (csize > 5) {
write("You do not get that large in "+cform+".\n");
return 1;
}
form_type = FORMS->query_forms()[cform];
if (!form_type || !stringp(form_type)) {
notify_fail("You do not know the form "+cform+".\n");
return 0;
}
form_list = FORMS->query_forms()[form_type];
if (sizeof(form_list) > 2 &&
form_type != pclan) {
notify_fail("You can only change your title to a basic form "+
"or one in your primary clan.\n");
return 0;
}
ntitle = SHIFTER->query_form_title(pgender,cform,csize);
// ntitle = (this_player()->query_class())->query_form_title(pgender,cform,csize);
if (!ntitle) {
write("Something errored in "+cform+". Notify Paldin\n");
return 1;
}
write("You become: "+this_player()->query_name()+" "+ntitle+"\n");
this_player()->set_title(ntitle);
return 1;
}
/* ######################################### */
// Query Functions for single save
void restore_forms(string who) {
mapping tmpinfo;
object form_ob;
string savefile;
if (!check_previous()) return;
if (!who) {
// If we dont have an environment and no one
// specific .. then drop out
if (!environment(this_object())) return;
who = environment(this_object())->query_real_name();
if (!who) return;
}
info = 0;
savefile = SAVE_PATH+"/"+who[0..0]+"/"+who;
if (file_size(savefile+".o") > 0) {
restore_object(savefile);
}
// If were missing the info get it from the old save daemon
if (!info) {
tmpinfo = OLD_INFO->query_info()[who];
if (tmpinfo && sizeof(m_indices(tmpinfo))) {
info = tmpinfo;
}
}
if (!info)
this_object()->set_start_xp_info(SHIFTER->total_xp(environment(this_object())) );
if (environment(this_object())) {
form_ob = present(current_form+"_shape", environment(this_object()));
if (form_ob)
set_form_settings(form_ob);
}
restored = 1;
}
varargs void save_forms(string who) {
object form_ob;
if (!check_previous()) return;
if (!who)
if (environment())
who = environment(this_object())->query_real_name();
if (!who || who!=environment(this_object())->query_real_name() ) return;
if (!restored) return;
form_ob = present(current_form+"_shape", environment());
if (form_ob)
save_form_settings(form_ob);
save_object(SAVE_PATH+"/"+who[0..0]+"/"+who);
}
mapping query_info() {
if (!check_previous()) return 0;
return info;
}
query_form_info(string shape) {
if (!check_previous()) return 0;
if (info && info[shape])
return info[shape];
return 0;
}
int query_start_xp() {
if (!check_previous()) return 0;
if (info && info["info"])
return info["info"][0][0];
return -1;
}
int query_xp_used() {
if (!check_previous()) return 0;
if (info && info["info"] )
return info["info"][0][1];
return -1;
}
mixed query_clan_order() {
if (!check_previous()) return 0;
if (info && sizeof(info["info"]) > 1) {
return info["info"][1];
}
return -1;
}
int query_clan_index(string clan) {
int val;
if (!check_previous()) return 0;
if (info && sizeof(info["info"]) > 1) {
val = member_array(clan,info["info"][1]);
if (val == -1) {
if (pointerp(FORMS->query_form(clan)) && sizeof(FORMS->query_form(clan)) > 2)
return sizeof(info["info"][1]);
else
return 0;
}
return val;
}
return -2;
}
int query_modifier(string clan) {
mixed ret;
int mod;
ret = FORMS->query_form(clan);
if (pointerp(ret))
mod = query_clan_index(clan)+2;
else
mod = query_clan_index(ret)+2;
return mod;
}
int query_size(string shape) {
if (!check_previous()) return 0;
if (info)
if (info[shape])
return info[shape][1];
}
int query_time(string shape) {
if (!check_previous()) return 0;
if (info)
if (info[shape])
return info[shape][0];
}
void add_shape(string shape) {
if (!check_previous()) return;
if (!info) {
info = ([ shape : ({ 0, 1 }) ]);
} else {
if (!info[shape])
info += ([ shape : ({ 0, 1 }) ]);
}
SAVE(0);
}
void delete_shape(string shape) {
if (!check_previous()) return;
if (!info) return;
m_delete(info,shape);
SAVE(0);
}
void add_time(string shape, int amt) {
if (!check_previous()) return;
if (amt > 5400) {
log_file(LOG+"time.log", environment()->query_name()+" ("+TP->query_real_name()+") spent "+amt+
" beats in "+shape+" form.\n");
}
if (!info) {
info = ([ shape : ({ amt, 1 }) ]);
} else {
if (!info[shape]) {
info += ([ shape : ({ amt, 1 }) ]);
} else {
info[shape][0] += amt;
}
}
SAVE(0);
}
void add_size(string shape, int amt) {
if (!check_previous()) return;
if (!info) {
info = ([ shape : ({ 0, amt }) ]);
} else {
if (!info[shape]) {
info += ([ shape : ({ 0, amt }) ]);
} else {
info[shape][1] += amt;
}
}
SAVE(0);
}
void set_start_xp_info(int xp) {
if (!check_previous()) return;
if (!info) {
info = ([ "info" : ({ ({ xp,0 }), ({ }) })]);
} else {
clear_info();
if (info["info"])
info["info"][0][0] = xp;
else
info["info"] = ({ ({ xp,0 }), ({ }) });
}
SAVE(0);
}
void add_xp_used(int xp) {
if (!check_previous()) return;
if (!info) { /* Should never be called */
info = ([ "info" : ({ ({ 0,xp }) ,({ }) })]);
} else {
if (info["info"]) /* Only one that *should* be called */
info["info"][0][1] += xp;
else
info["info"] = ({ ({ 0,xp }), ({ }) });
}
SAVE(0);
}
void set_clan_order(string *order) {
if (!check_previous()) return;
if (!info) { /* shouldnt happen */
info = ([ "info" : ({ ({ 0, 0 }) , order }) ]);
} else {
if (!info["info"]) { /* shouldnt happen either */
info += ([ "info" : ({ ({ 0, 0 }) , order }) ]);
} else {
info["info"][1] = order;
}
}
SAVE(0);
}
void add_clan(string clan) {
if (!check_previous()) return;
if (!info) { /* shouldnt happen */
info = ([ "info" : ({ ({ 0, 0 }) , ({ clan }) }) ]);
} else {
if (!info["info"]) { /* shouldnt happen either */
info += ([ "info" : ({ ({ 0, 0 }) , ({ clan }) }) ]);
} else if (member_array(clan, info["info"][1]) == -1) {
info["info"][1] += ({ clan });
}
}
SAVE(0);
}
int clear_info() {
if (!check_previous()) return 0;
info = ([ ]);
SAVE(0);
return 1;
}
void add_learning(string str) {
if (!check_previous()) return 0;
if (!learning) {
learning = ([ str : 1 ]);
} else {
if (!learning[str])
learning += ([ str : 1 ]);
else
learning[str]++;
}
SAVE(0);
}
mapping query_kills() {
if (!check_previous()) return 0;
return kills;
}
void add_kills(string form) {
if (!check_previous()) return 0;
if (!kills) {
kills = ([ form : 1 ]);
} else {
if (!kills[form])
kills += ([ form : 1 ]);
else
kills[form]++;
}
SAVE(0);
}
int query_learning_modifier(string form, string ability, int max) {
int mod, mod2;
if (!check_previous()) return 0;
mod2 = query_modifier(form);
mod = MOD_D->query_learning_mod(ability, mod2, this_object()->query_learning(ability));
if (mod > max) mod = max;
return mod;
}
int query_learning(string str) {
if (!check_previous()) return 0;
if (!learning) return 0;
return learning[str];
}
mapping query_all_learning() {
if (!check_previous()) return 0;
if (!learning) return 0;
return learning;
}
int query_duration_modifier(string who, string type, int dur) {
if (!check_previous()) return 0;
if (!environment(this_object()) || !environment(this_object())->query_is_player()) restore_forms(who);
if (!base_duration) {
base_duration = ([ type : random(20)+1 ]);
SAVE(0);
} else {
if (!base_duration[type]) {
base_duration += ([ type : random(20)+1 ]);
SAVE(0);
}
}
dur += MOD_D->duration_mod(type,dur,base_duration[type],learning,kills);
return dur;
}
mapping query_form_exp() {
if (!check_previous()) return 0;
return form_exp;
}
void add_exp(string form,int amt) {
if (!check_previous()) return 0;
if (!form_exp) {
form_exp = ([ form : amt ]);
} else {
if (!form_exp[form])
form_exp += ([ form : amt ]);
else
form_exp[form]+=amt;
}
SAVE(0);
}
int query_exp_modifier(string who, string type, int xp) {
if (!check_previous()) return 0;
if (!environment(this_object()) || !environment(this_object())->query_is_player()) restore_forms(who);
if (!base_xp) {
base_xp = ([ type : random(20)+1 ]);
SAVE(0);
} else {
if (!base_xp[type]) {
base_xp += ([ type : random(20)+1 ]);
SAVE(0);
}
}
xp += MOD_D->exp_mod(type,xp,base_xp[type],learning,kills);
return xp;
}
int set_base_xp(string type, int xp) {
if (!check_previous()) return 0;
base_xp[type] = xp;
SAVE(0);
}
int set_base_duration(string type, int dur) {
if (!check_previous()) return 0;
base_duration[type] = dur;
SAVE(0);
}
void add_misc(string ref, int val) {
if (!check_previous()) return 0;
if (!misc) misc = ([]);
if (!misc[ref])
misc += ([ref : val]);
else
misc[ref] += val;
}
int query_misc(string ref) {
if (!check_previous()) return 0;
if (!misc) return 0;
return misc[ref];
}
// Make it !feeling_toggle to default to on
int query_toggle() {
if (!restored) return 0; // If it hasnt loaded up turn them off by default
return feeling_toggle;
}
int set_toggle(int s) { feeling_toggle = s; SAVE(0); }
int check_previous() {
if (geteuid(previous_object()) != "Shifters" &&
geteuid(previous_object()) != "paldin" &&
geteuid(previous_object()) != "serf") return 0;
return 1;
}
// query_auto_load so when saving to quit force
// the pendant to save
query_auto_load() { SAVE(0); }
void save_form_settings(object ob) {
mapping FS;
string *ind;
string fname;
int i;
if (!form_settings) form_settings = ([]);
if (!ob) return;
fname = ob->query_form();
FS = FORM_SETTINGS[fname];
if (!FS) return;
ind = m_indices(FS);
for(i=0;i<sizeof(ind);i++) {
if (!member(form_settings, ind[i])) {
form_settings += ([ ind[i] : call_other(ob, FS[ind[i], 0]) ]);
} else {
form_settings[ind[i]] = call_other(ob, FS[ind[i], 0]);
}
}
}
void set_form_settings(object ob) {
mapping FS;
string *ind;
string fname;
int i;
if (!form_settings) form_settings = ([]);
if (!ob) return;
fname = ob->query_form();
FS = FORM_SETTINGS[fname];
if (!FS) return;
ind = m_indices(FS);
for(i=0;i<sizeof(ind);i++) {
call_other(ob, FS[ind[i], 1], form_settings[ind[i]]);
}
}
mapping query_form_settings() { return copy_mapping(form_settings); }