/* -*- LPC -*- */
/*
* $Locker: $
* $Id: learn.c,v 1.19 2003/01/31 06:27:31 pinkfish Exp $
*
*/
#include <skills.h>
#include <tune.h>
#include <cmds/teach.h>
#include <command.h>
inherit "/cmds/base";
#define TP this_player()
mixed cmd(string str, object *obs);
mixed cmd(string str, object *obs) {
object *diff_lvl;
object *no_xp;
object *not_offer;
object *ok;
object *moved;
object ob;
int time;
string skill;
string cmd;
string cmd_ob;
string *bits;
string levelstr;
class teaching_skill womble;
if (TP->query_property("dead")) {
notify_fail("Your dead. Your mind slips off the task and goes for "
"a wander down memory lane.\n");
return 0;
}
skill = str;
/* Figure out the skill thingy. */
bits = explode(implode(explode(skill, " "), "."), ".");
skill = SKILL_OB->query_skill(bits);
if (!skill) {
/* Ok, not a skill... Check to see if it is a command. */
ok = ({ });
cmd = str;
if (sizeof(CMD_D->GetPaths(cmd)) &&
CMD_D->GetPaths(cmd)[0]) {
cmd_ob = CMD_D->GetPaths(cmd)[0] + "/" + cmd;
foreach (ob in obs) {
bits = TP->query_respond_command(TEACH_COMMAND_TYPE, ob);
if (pointerp(bits) && member_array(cmd, bits) != -1) {
cmd_ob->teach_command(ob, this_player());
ok += ({ ob });
bits -= ({ cmd });
if (sizeof(bits)) {
TP->add_respond_command(TEACH_COMMAND_TYPE, ob, bits);
} else {
TP->remove_respond_command(TEACH_COMMAND_TYPE, ob);
}
event(environment(this_player()), "teach", "command", ob, this_player());
break;
}
}
if (sizeof(ok)) {
add_succeeded_mess("$N learn$s " + cmd + " from $I.\n", ok);
return 1;
}
add_failed_mess("The skill \"" + cmd + "\" is invalid, or $I "
"is not trying to teach you the \"" + cmd + "\" "
"command.\n");
} else {
add_failed_mess("The skill '" + cmd + "' is invalid.\n");
}
return 0;
}
moved = ok = not_offer = no_xp = diff_lvl = ({ });
foreach (ob in obs) {
womble = TP->query_respond_command(TEACH_SKILL_TYPE, ob);
if (!womble) {
not_offer += ({ ob });
continue;
}
if (skill != womble->skill) {
not_offer += ({ ob });
continue;
}
if ((int)TP->query_xp() < womble->xp ||
!womble->xp) {
no_xp += ({ ob });
continue;
}
if (TP->query_skill(womble->skill) != womble->lvl) {
diff_lvl += ({ ob });
TP->remove_respond_command(TEACH_SKILL_TYPE, womble->teacher);
continue;
}
if (sizeof(ok)) {
continue;
}
if(womble->num == 1)
levelstr = "level";
else
levelstr = "levels";
if (environment(this_player()) != womble->room) {
moved += ({ ob });
TP->remove_respond_command(TEACH_SKILL_TYPE, womble->teacher);
continue;
}
if (ob != TP) {
write(ob->short()+" starts to teach you " + womble->num + " " +
levelstr + " of " + womble->skill + " for " + womble->xp +
" xp.\n");
tell_object(ob, "You start to teach " + TP->short() +
" " + womble->num + " " + levelstr +
" of " + womble->skill +
" for " + womble->xp + " xp.\n");
say(ob->short()+" starts to teach "+TP->short()+" some skills.\n",
({ TP, ob }));
ok += ({ ob });
} else {
write("You start to teach yourself " + womble->num + " " +
levelstr + " in "+
womble->skill + " for " + womble->xp + " xp.\n");
say(TP->short()+" starts to teach " + TP->query_objective() +
"self some skills.\n", ({ TP }));
}
/*
* Ok... We now change the time on both people and wait...
* After they have both finished everything is hunky womble. If one
* types stop, we dont teach them anything...
*/
time = womble->xp / TIME_DIV;
if(time > 1000) {
time = 1000;
}
TP->adjust_time_left(-time);
womble->teacher = ob;
womble->taught = TP;
TP->set_interupt_command("stop_teaching_skills", file_name(this_object()),
womble);
if (TP != ob) {
ob->adjust_time_left(-time);
ob->set_interupt_command("stop_teaching_skills", TP, womble);
}
}
if (sizeof(not_offer)) {
if(sizeof(not_offer) == 1) {
if(not_offer[0] != this_player())
write(capitalize(query_multiple_short(not_offer)) +
" is not offering to teach you "+ skill+".\n");
else
write(capitalize(query_multiple_short(not_offer)) +
" are not offering to teach yourself "+ skill+".\n");
} else
write(capitalize(query_multiple_short(not_offer)) +
" are not offering to teach you "+ skill+".\n");
}
if (sizeof(moved)) {
write("You appear to have moved away from the excellent teaching "
"environment selected by "+
query_multiple_short(moved)+".\n");
}
if (sizeof(no_xp)) {
write("You do not have enough xp to learn "+skill+" from "+
query_multiple_short(no_xp)+".\n");
}
if (sizeof(diff_lvl)) {
write("You were a different level in "+skill+" when "+
query_multiple_short(diff_lvl)+" offered to teach you.\n");
}
if (sizeof(ok)) {
say(TP->short()+" learns some skills from "+query_multiple_short(ok)+
".\n", ok);
}
return 1;
} /* cmd() */
/**
* The method to call when we stop teaching skills. THis will stop the
* stuff being taught if the stop is successful, and only teach partial
* amounts if we are not finished yet.
* @param left the amount of time left
* @param bing the data associated with the command
*/
void stop_teaching_skills(int time_left, class teaching_skill womble,
object us, object interupter, string cmd) {
object ob;
mixed *stuff;
string levelstr;
if (time_left > 0) {
/* Someone did a stop! Naughty frogs! */
if (womble->teacher == us) {
/* Only print the messages once. */
if (womble->teacher == womble->taught) {
say(womble->taught->short() + " stops teaching " +
womble->taught->query_objective() + "self some "
"skills.\n");
} else if (us == interupter) {
ob = womble->teacher;
tell_object(ob, womble->taught->short() + " interupts your "
"training.\n");
} else {
tell_object(us, interupter->short() + " interupts your "
"training.\n");
}
say(interupter->short() + " stops teaching some skills to " +
womble->taught->short() + ".\n",
({ us, interupter }));
}
/* Interupt the other person. */
if (us == womble->teacher) {
ob = womble->taught;
} else {
ob = womble->teacher;
}
if (ob) {
stuff = ob->query_interupt_command();
if (stuff) {
if (stuff[0] == "stop_teaching_skills") {
ob->interupt_command(us);
}
}
}
us->adjust_time_left(-((int)womble->taught->query_time_left()));
us->set_interupt_command(0);
return ;
}
if (interupter != us) {
/* First make sure we dont get the level twice... */
return ;
}
if (environment(womble->taught) != environment(womble->teacher) ||
environment(womble->taught) != womble->room) {
tell_object(us, "You appear to have left your excellent "
"teaching environment, so the skill teaching failed.\n");
tell_object(womble->teacher, "You appear to have left your excellent "
"teaching environment, so the skill teaching failed.\n");
return;
}
// additional test added by ceres coz people are getting put into negative
// xp by getting taught twice somehow.
if(womble->taught->query_xp() < womble->xp) {
write("Something has gone wrong. :(\n");
return;
}
/* Ok... We did it! Finished! */
if (womble->taught != womble->teacher) {
womble->teacher->adjust_xp(womble->xp / 10);
}
womble->taught->adjust_xp(-womble->xp);
if(womble->num == 1)
levelstr = "level";
else
levelstr = "levels";
if(womble->taught->add_skill_level(womble->skill, womble->num, womble->xp))
{
if (us != womble->teacher) {
tell_object(us, "You finish learning " + womble->num +
" " + levelstr + " of "
+ womble->skill + " from " + womble->teacher->short() +
".\n");
tell_object(womble->teacher, womble->taught->short() + " finishes " +
"learning " + womble->num + " " + levelstr + " of "
+ womble->skill + " from you.\n");
say(us->short() + " finishes learning some skills "+
"from "+ womble->teacher->short()+".\n",
({ us, womble->teacher }));
} else {
tell_object(us, "You finish teaching yourself " + womble->num +
" " + levelstr + " of " +
womble->skill + ".\n");
say(us->short() + " finishes learning some skills "
"from " + us->query_objective() + "self.\n",
({ us, womble->teacher }));
}
} else {
tell_object(womble->taught, "Something went wrong learning " +
womble->skill + " from " + womble->teacher->query_short() +
".\n");
}
womble->taught->remove_respond_command(TEACH_SKILL_TYPE, womble->teacher);
} /* stop_teaching_skills() */
mixed *query_patterns() {
return ({ "<string'skill/command'> from <indirect:living>",
(: cmd($4[0], $1) :) });
} /* query_pattern() */