/* -*- LPC -*- */ /* * $Locker: $ * $Id: coerce.c,v 1.1 1998/01/06 04:36:51 ceres Exp $ * $Log: coerce.c,v $ * Revision 1.1 1998/01/06 04:36:51 ceres * Initial revision * */ /* * coerce.c - Shadow to allow a player to command NPCs and PCs * * NOTE: This is in an extremely early stage. A number of safeguards * need to be added before this can be used in the game. * * Success depends on the player's intelligence and skill bonus * relative to the victim's intelligence. One bonus point counts as * 1/100 of an intelligence point. If the difference is less than 0, * the player always fails; if it's over 20, the player always succeeds. * Before 'coerce'ing the victim, the player must 'control' it; changing * control has a chance of causing the victim to attack. */ inherit "/std/effect_shadow"; #include <tasks.h> // In the following mappings, the key is the command. The value is a // penalty (in 1/100ths of intelligence points); this makes some commands // more difficult than others. // These are the commands that can be used on players (not yet implemented) mapping p_cmds = ([ "kiss": 0, "get": 0 ]); // These commands can be used on NPCs mapping npc_cmds = ([ "emote": 0, "get": 0, "take": 0, "drop": 0, "put": 0, "follow": 500, "unfollow": 500, "protect": 1000, "unprotect": 1000, "wear": 0, "remove": 0, "equip": 0, "say": 0, "tell": 0, "go": 0 ]); // These require special handling mapping npc_special = ([ "go": "npc_go", //"drop" : "npc_drop", //"put": "npc_put" ]); object current_slave; int skill_lvl; string skill = "magic.methods.mental.charming"; int margin = 1000; int level_factor = 2; void create() { if (clonep(this_object())) { //tell_object(this_player(), "Creating shadow...\n"); this_player()->add_command("coerce", this_object(), "%I %s"); this_player()->add_command("control", this_object(), "%I"); skill_lvl = (int)this_player()->query_int()*100 + this_player()->query_skill_bonus(skill); } } int do_control(object *slave, mixed *args_b, mixed *args_a, mixed *args) { int slave_lvl, result; if (sizeof(slave) != 1) { this_player()->add_failed_mess(0, "You can only $V one person " + "at a time.\n", 0); return 0; } if (!living(slave[0])) { this_player()->add_failed_mess(0, "You can't $V $I!\n", slave); return 0; } if (current_slave) { slave_lvl = (int)current_slave->query_int()*100 + (int)current_slave->query_level()*level_factor; if (random(2*margin) < (slave_lvl - skill_lvl + margin)) { if (!(current_slave->query_property("player"))) { // Attack player current_slave->attack_ob(this_player()); } else { tell_object(current_slave, "You feel like someone is " + "playing with your mind.\n"); tell_object(this_player(), "You feel that " + current_slave->the_short() + " suspects something.\n"); } } } current_slave = 0; slave_lvl = (int)slave[0]->query_int()*100 + (int)slave[0]->query_level()*level_factor; result = TASKER->attempt_task(slave_lvl, skill_lvl, 20, margin); if ((result == FAIL) || (result == BARF)) { if (random(2*margin) < (slave_lvl - skill_lvl + margin)) { if (!(slave[0]->query_property("player"))) { // Attack player slave[0]->attack_ob(this_player()); } else { tell_object(slave[0], "You feel like someone is playing " + "with your mind.\n"); tell_object(this_player(), "You feel that " + slave[0]->the_short() + " suspects something.\n"); } } else { write(capitalize(slave[0]->the_short()) + " looks around quizically for a moment.\n"); } } else { if (result == AWARD) { this_player()->add_skill_level(skill, 1, 0); } current_slave = slave[0]; } return 1; } int do_coerce(object *slave, mixed *args_b, mixed *args_a, mixed *args) { string cmd, rest; int result, slave_lvl, cmd_result; if (sizeof(slave) != 1) { this_player()->add_failed_mess(0, "You can only $V one person " + "at a time.\n", 0); return 0; } if (!living(slave[0])) { this_player()->add_failed_mess(0, "You can't $V $I!\n", slave); return 0; } parse_command(args[1], environment(this_player()), "%w %s", cmd, rest); if (!slave[0]) { this_player()->add_failed_mess(0, "$V who?\n"); return 0; } if (slave[0] != current_slave) { this_player()->add_failed_mess(0, "$I looks around quizzically for a moment.\n", slave); return 0; } if (!cmd) { this_player()->add_failed_mess(0, "$V $I to do what?\n", slave); return 0; } if (slave[0]->query_property("player")) { // Player commands if (undefinedp(p_cmds[cmd])) { this_player()->add_failed_mess(0, "You can't $V $I to do that!\n", slave); return 0; } // I'm not sure how to call a command on a player...maybe I can't? this_player()->add_failed_mess(0, "$V players not yet implemented.\n"); return 0; } else { // NPC commands if (undefinedp(npc_cmds[cmd])) { this_player()->add_failed_mess(0, "You can't $V $I to do that!\n", slave); return 0; } // Will probably need more checks here, as more dangerous commands // are entered. slave_lvl = (int)slave[0]->query_int()*100 + (int)slave[0]->query_level()*level_factor; result = TASKER->attempt_task(slave_lvl, (skill_lvl - npc_cmds[cmd]), 10, margin); if ((result == FAIL) || (result == BARF)) { write(capitalize(slave[0]->the_short()) + " looks at you quizzically.\n"); this_player()->add_succeeded_mess(0, 0, 0); return 1; } if (undefinedp(npc_special[cmd])) { cmd_result = slave[0]->do_command(args[1]); } else { cmd_result = call_other(this_object(), npc_special[cmd], rest); } if (!cmd_result) { write(capitalize(slave[0]->the_short()) + " looks at you quizzically.\n"); this_player()->add_succeeded_mess(0, 0, 0); return 1; } if (result == AWARD) { this_player()->add_skill_level(skill, 1, 0); } this_player()->add_succeeded_mess(0, 0, 0); return 1; } } void remove_cmd() { if (this_player()->remove_object2(this_object())) { //write("Shadow removed.\n"); } else { //write("Shadow not removed :(\n"); } } int npc_go(string dir) { // This is tricky, since there may be exits with non-standard names. mixed exits; int i; if (!environment(current_slave) || !function_exists("query_dest_dir", environment(current_slave))) { return 0; } exits = environment(current_slave)->query_dest_dir(); for (i = 0; i < sizeof(exits); i += 2) { if (exits[i] == dir) { return current_slave->do_command(dir); } } return 0; }