// $Id: script.cc,v 1.14.2.6 2000/03/24 01:53:50 justin Exp $
// $Revision: 1.14.2.6 $ $Author: justin $ $Date: 2000/03/24 01:53:50 $
//
//ScryMUD Server Code
//Copyright (C) 1998 Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred)
// greearb@agcs.com
//
///********************** script.cc ******************************///
// This file contains methods pertaining to mob scripting. This is where
// new conditional statements, and other modifications should go.
//
#include "commands.h"
#include "command2.h"
#include "command3.h"
#include "command4.h"
#include "command5.h"
#include "misc.h"
#include "misc2.h"
#include <stdio.h>
#include "classes.h"
#include "battle.h"
#include "spec_prc.h"
#include "spells.h"
#include "skills.h"
#include <fstream.h>
#include "batl_prc.h"
#include <PtrArray.h>
#include <unistd.h>
#include "load_wld.h"
#include <KVPair.h>
// initialize static variable.
int ScriptCmd::_cnt = 0;
/** This will not kill, but can set HP to 1 in worst case. */
int affect_crit_stat(StatTypeE ste, String& up_down, int i_th,
String* victim, int dice_cnt, int dice_sides,
room* rm, critter* caller = NULL) {
critter* crit_ptr;
String buf(100);
if (caller &&
(caller->isCharmed() ||
(caller->isPc() && (caller->getImmLevel() < 7)))) {
caller->show("Huh??\n");
return -1;
}
crit_ptr = rm->haveCritNamed(i_th, victim, ~0);
if (!crit_ptr) {
return -1;
}//if
if (crit_ptr->isMob()) {
crit_ptr = mob_to_smob(*crit_ptr, rm->getIdNum(), TRUE, i_th,
victim, ~0);
}//if
switch (ste)
{
case STAT_HP: {
if (strcasecmp(up_down, "up") == 0) {
crit_ptr->setHP(crit_ptr->getHP() + d(dice_cnt, dice_sides));
}
else {
crit_ptr->setHP(max(crit_ptr->getHP() - d(dice_cnt, dice_sides), 1));
}
return crit_ptr->getHP();
}
case STAT_MANA: {
if (strcasecmp(up_down, "up") == 0) {
crit_ptr->setMana(crit_ptr->getMana() + d(dice_cnt, dice_sides));
}
else {
crit_ptr->setMana(max(crit_ptr->getMana() - d(dice_cnt, dice_sides), 1));
}
return crit_ptr->getMana();
}
case STAT_MOV: {
if (strcasecmp(up_down, "up") == 0) {
crit_ptr->setMov(crit_ptr->getMov() + d(dice_cnt, dice_sides));
}
else {
crit_ptr->setMov(max(crit_ptr->getMov() - d(dice_cnt, dice_sides), 1));
}
return crit_ptr->getMov();
}
default:
return -1;
}//switch
}//affect_crit_stat
/** Exact some damage. */
int exact_damage(int dice_cnt, int dice_sides, String& msg, critter& pc) {
if (pc.isMob()) {
mudlog << "ERROR: MOB sent to exact_damage, should be pc or SMOB.\n";
return -1;
}
dice_cnt = bound(0, 20, dice_cnt);
dice_sides = bound(0, 100, dice_sides);
pc.emote(msg);
exact_raw_damage(d(dice_cnt, dice_sides), NORMAL, pc);
if (pc.HP < 0) { //was a fatality
agg_kills_vict(&pc, pc);
}
return 0;
}//exact_damage
/** Used to provide branching in scripts.. The lengths of the
* cooked* arrays passed in are directly related to the cooked*
* arrays found in parse.cc.
*/
int script_jump_true(String* cooked_strs, int* cooked_ints,
critter& script_targ, critter* c_script_owner,
room* r_script_owner, int sanity) {
return script_jump(TRUE, cooked_strs, cooked_ints, script_targ,
c_script_owner, r_script_owner, sanity);
}//script_jump_true
int script_jump_false(String* cooked_strs, int* cooked_ints,
critter& script_targ, critter* c_script_owner,
room* r_script_owner, int sanity) {
return script_jump(FALSE, cooked_strs, cooked_ints, script_targ,
c_script_owner, r_script_owner, sanity);
}
/** Does a great many comparisons. Supported fields are:
* HP, MANA, MOV, ALIGN
*/
int is_equal_to(int i_th, const String& rhs_critter,
const String& field, critter& pc) {
return do_mob_comparison(i_th, rhs_critter, field, pc, CT_EQUALS);
}//is_equal_to
/** Does a great many comparisons. Supported fields are:
* HP, MANA, MOV, ALIGN
*/
int is_greater_than(int i_th, const String& rhs_critter,
const String& field, critter& pc) {
return do_mob_comparison(i_th, rhs_critter, field, pc, CT_GT);
}//isGreaterThan
/** Does a great many comparisons. Supported fields are:
* HP, MANA, MOV, ALIGN
*/
int is_less_than(int i_th, const String& rhs_critter,
const String& field, critter& pc) {
return do_mob_comparison(i_th, rhs_critter, field, pc, CT_LT);
}//isLessThan
int do_mob_comparison(int i_th, const String& rhs_critter,
const String& field, critter& pc, ComparisonTypeE ct) {
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "do_mob_comparison, i_th: " << i_th << " rhs_critter: "
<< rhs_critter << " field: " << field
<< " ComparisonTypeE: " << (int)ct << endl;
}
critter* crit_ptr = ROOM.haveCritNamed(i_th, &rhs_critter, ~0);
int rhs_val;
int pc_val;
if (!crit_ptr) {
if (mudlog.ofLevel(ERROR)) {
mudlog << "ERROR: Couldn't find crit_ptr, i_th: " << i_th
<< " rhs -:" << rhs_critter << ":-\n";
}
return 0;
}
if (pc.isImmort() || (pc.isSmob() && !pc.isCharmed())) {
rhs_val = crit_ptr->getFieldValue(field);
pc_val = pc.getFieldValue(field);
switch (ct)
{
case CT_EQUALS:
return (rhs_val == pc_val);
case CT_GT:
return (pc_val > rhs_val);
case CT_LT:
return (pc_val < rhs_val);
}
}
return 0;
}
int is_in_posn(String& str, critter& pc) {
if (isnum(str)) {
return pc.POS == atoi(str);
}
else {
int posn = bound(0, POS_HIGH_VAL, pc.POS);
if (strncasecmp(str, PcPositionStrings[posn],
strlen(PcPositionStrings[posn])) == 0) {
return TRUE;
}//if
else {
return FALSE;
}
}//else
}//is_in_posn
/* used for random branching in scripts */
int chance(int cnt, int sides, int val) {
return (val >= d(cnt,sides));
}//chance
/** Used to provide branching in scripts.. The lengths of the
* cooked* arrays passed in are directly related to the cooked*
* arrays found in parse.cc.
*/
int script_jump(int on_test, String* cooked_strs, int* cooked_ints,
critter& test_targ, critter* c_code_owner,
room* r_code_owner, int sanity) {
//Conditional command is second cooked_str
// offset is the first cooked int.
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "script_jump, on_test: " << on_test << " c_owner: "
<< c_code_owner << " r_owner: " << r_code_owner
<< " sanity: " << sanity << endl;
}
int offset = cooked_ints[1];
String cmd = cooked_strs[1];
// First make sure we are a mob with a mob script. May add pc
// functionality later??
int test = !on_test;
if ((c_code_owner && c_code_owner->isInProcNow()) ||
(r_code_owner && r_code_owner->isInProcNow())) {
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "had an owner, and was inProcNow()" << endl;
}
if (strcasecmp(cmd, "TRUE") == 0) {
test = TRUE;
}
else if (strcasecmp(cmd, "FALSE") == 0) {
test = FALSE;
}
else {
// The + 1 steps past the first command, which was script_jump_***
test = test_targ.executeCommand(cooked_strs + 1, cooked_ints + 1,
sanity, c_code_owner, r_code_owner,
FALSE,/* do_sub */
FALSE/* was_ordered*/);
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "script_jump, test is: " << test << " on test: "
<< on_test << endl;
}
if (test < 0) {
if (c_code_owner) {
if (mudlog.ofLevel(WRN)) {
mudlog << "WARNING: Script is funky for test_targ: "
<< *(test_targ.getName()) << " code_owner: "
<< *(c_code_owner->getName()) << " failed conditional: "
<< cmd << " error: " << test << endl;
}//if
}//if
else if (r_code_owner) {
if (mudlog.ofLevel(WRN)) {
mudlog << "WARNING: Script is funky for test_targ: "
<< *(test_targ.getName()) << " code_owner: "
<< r_code_owner->getIdNum() << " failed conditional: "
<< cmd << " error: " << test << endl;
}
}//if
test = FALSE;
}//if
}//else
if ((test && on_test) || (!test && !on_test)) {
if (c_code_owner)
c_code_owner->doScriptJump(offset);
else if (r_code_owner)
r_code_owner->doScriptJump(offset);
}//if
}//if in proc
else {
if (mudlog.ofLevel(WRN)) {
if (c_code_owner)
mudlog << "WARNING: Mob is not scripting in script_jump, code_owner: "
<< *(c_code_owner->getName()) << endl;
else if (r_code_owner)
mudlog << "WARNING: Mob is not scripting in script_jump, code_owner: "
<< r_code_owner->getIdNum() << endl;
}//if
}//else
return 0;
}//script_jump
//used in mob scripts primarily.
int does_own(critter& pc, int obj1, int obj2, int obj3, int obj4,
int obj5, int obj6) {
//figure out if the player owns all the objects in question.
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "In does_own, critter: " << *(pc.getName())
<< " obj1: " << obj1 << " obj2: " << obj2
<< " obj3: " << obj3 << " obj4: " << obj4 << " obj5: "
<< obj5 << " obj6: " << obj6 << endl;
}//if
int count1 = 1;
int count2 = 1;
int count3 = 1;
int count4 = 1;
int count5 = 1;
int count6 = 1;
// Get the count for object 1
if (obj2 == obj1) {
count1++;
obj2 = 0;
}
if (obj3 == obj1) {
count1++;
obj3 = 0;
}
if (obj4 == obj1) {
count1++;
obj4 = 0;
}
if (obj5 == obj1) {
count1++;
obj5 = 0;
}
if (obj6 == obj1) {
count1++;
obj6 = 0;
}
// Get the count for object 2
if (obj3 == obj2) {
count2++;
obj3 = 0;
}
if (obj4 == obj2) {
count2++;
obj4 = 0;
}
if (obj5 == obj2) {
count2++;
obj5 = 0;
}
if (obj6 == obj2) {
count2++;
obj6 = 0;
}
// Get the count for object 3
if (obj4 == obj3) {
count3++;
obj4 = 0;
}
if (obj5 == obj3) {
count3++;
obj5 = 0;
}
if (obj6 == obj3) {
count3++;
obj6 = 0;
}
// Get the count for object 4
if (obj5 == obj4) {
count4++;
obj5 = 0;
}
if (obj6 == obj4) {
count4++;
obj6 = 0;
}
// Get the count for object 5
if (obj6 == obj5) {
count5++;
obj6 = 0;
}
if ((obj1 <= 1) || (pc.haveObjNumbered(count1, obj1))) {
if ((obj2 <= 1) || (pc.haveObjNumbered(count2, obj2))) {
if ((obj3 <= 1) || (pc.haveObjNumbered(count3, obj3))) {
if ((obj4 <= 1) ||
(pc.haveObjNumbered(count4, obj4))) {
if ((obj5 <= 1) ||
(pc.haveObjNumbered(count5, obj5))) {
if ((obj6 <= 1) ||
(pc.haveObjNumbered(count6, obj6))) {
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "Returning TRUE" << endl;
}
return TRUE;
}//if
}//if
}//if
}//if
}//if
}//if
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "Returning FALSE" << endl;
}
return FALSE;
}//if_owns
///*********************************************************************///
////*********************** GenScript ****************************///
///*********************************************************************///
int GenScript::_cnt = 0;
GenScript::GenScript() {
_cnt++;
stack_ptr = -1;
target = -1;
actor = -1;
precedence = 0;
needs_compiling = TRUE;
next_lbl_num = 0;
}
GenScript::GenScript(String& trig, int targ, int act, String& discriminator,
int prec) {
_cnt++;
trigger_cmd = trig;
target = targ;
actor = act;
stack_ptr = -1;
needs_compiling = TRUE;
next_lbl_num = 0;
trig_discriminator = discriminator;
if (trig_discriminator.Strlen() > 0) {
trig_discriminator.Strip();
trig_discriminator.Prepend(" ");
trig_discriminator.Append(" ");
}
precedence = prec;
}//Full constructor
GenScript::GenScript(const GenScript& src) {
_cnt++;
*this = src;
}
void GenScript::doScriptJump(int abs_offset) {
if ((abs_offset < compiled_cmds.getCurLen()) &&
(abs_offset >= 0)) {
stack_ptr = abs_offset;
}//if
else {
stack_ptr = -1; //all done
mudlog << "ERROR: Script jump out of range." << endl;
}
}//doScriptJump
const ScriptCmd* GenScript::getNextCommand() {
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "GenScript::getNextCommand, stack_ptr: " << stack_ptr
<< endl << getRunningScript() << endl;
}
if (stack_ptr >= 0) {
int tmp = stack_ptr;
stack_ptr++;
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "GenScript::getNextCommand, tmp: " << tmp << endl;
if (running_cmds[tmp])
mudlog << " returning: " << running_cmds[tmp]->getCommand() << endl;
}
return running_cmds[tmp];
}//if
else {
if (mudlog.ofLevel(SCRIPT)) {
mudlog << "GenScript::getNextCommand, stack_ptr: " << stack_ptr
<< " returning NULL" << endl;
}
return NULL;
}
}//getNextCommand
/** This txt_ is really a long glob of commands, seperated by
* semi-colons.
*/
void GenScript::setScript(const String& txt_) {
mudlog.log(DBG, "In setScript.");
String txt(txt_);
String* tmp_str;
//mudlog.log(DBG, txt);
//mudlog.log(DBG, "About to clear ptr list.");
script_cmds.clearAndDestroy();
//mudlog.log(DBG, "Going into while loop.");
while ((tmp_str = txt.getUntil(';'))) {
appendCmd(*tmp_str);
delete tmp_str;
}//while
stack_ptr = -1;
needs_compiling = TRUE;
compile(); //Compile into script assembly code
//mudlog.log(DBG, "Done w/addScript.");
}//addScript
GenScript& GenScript::operator=(const GenScript& src) {
if (this == &src)
return *this;
//mudlog.log("In GenScript::operator=");
trigger_cmd = src.trigger_cmd;
trig_discriminator = src.trig_discriminator;
stack_ptr = src.stack_ptr;
needs_compiling = src.needs_compiling;
script_cmds.becomeDeepCopyOf(src.script_cmds);
compiled_cmds.becomeDeepCopyOf(src.compiled_cmds);
running_cmds.becomeDeepCopyOf(src.running_cmds);
target = src.target;
actor = src.actor;
precedence = src.precedence;
return *this;
}//operator=
GenScript::~GenScript() {
_cnt--;
clear();
}
// Static Class Data
char* GenScript::triggers[] = {
"break", "close", "discuss", "donate",
"drop", "eat", "enter", "examine", "exit", "fill", "flip", "follow",
"get", "give", "grab", "group",
"hit", "insert", "junk", "list", "lock", "look", "meditate", "nod",
"open", "order", "pay", "pick", "prone", "pull", "push", "put",
"remove", "rest", "say", "shake", "shoot", "sit", "slap", "sleep", "stand",
"tell", "throw", "turn", "twist", "ungroup", "unlock", "wake", "wear",
"wield", "yell", NULL };
// Static function, maybe should really check it in the future!
int GenScript::checkScript(const String& str) {
return str.Strlen();
}
// Static function
int GenScript::validTrigger(const char* trig) {
int cmp;
for (int i = 0; triggers[i]; i++) {
cmp = strcasecmp(triggers[i], trig);
if (cmp == 0) {
return TRUE;
}
else if (cmp > 0) { //already past it
return FALSE;
}
}//for
return FALSE;
}//validTrigger
String GenScript::toStringBrief(int client_format, int mob_num,
entity_type entity, int idx) {
String buf(100);
if (client_format) {
String tmp_d;
if (trig_discriminator.Strlen() == 0)
tmp_d = "NA";
else
tmp_d = trig_discriminator;
String tmp(100);
if (entity == ENTITY_CRITTER) {
Sprintf(buf, "<MOB_SCRIPT %S %i %i %i %i %i>", &trigger_cmd,
mob_num, actor, target, precedence, idx);
}
else if (entity == ENTITY_ROOM) {
Sprintf(buf, "<ROOM_SCRIPT %S %i %i %i %i %i>", &trigger_cmd,
mob_num, actor, target, precedence, idx);
}
else if (entity == ENTITY_OBJECT) {
Sprintf(buf, "<OBJ_SCRIPT %S %i %i %i %i %i>", &trigger_cmd,
mob_num, actor, target, precedence, idx);
}
Sprintf(tmp, "<DISCRIM %S>", &tmp_d);
buf.Append(tmp);
return buf;
}
else {
Sprintf(buf, "Trigger: %S Actor Mob: %i Target #: %i Precedence: %i\n\tDiscriminator: %S.\n",
&trigger_cmd, actor, target, precedence, &trig_discriminator);
}
return buf;
}//toStringBrief
/** This gives the non-compiled, non-running version. Think of it
* as source code!
*/
String GenScript::getScript() {
String buf(1024);
for (int i = 0; i<script_cmds.getCurLen(); i++) {
if (script_cmds.constElementAt(i)) {
buf.Append(script_cmds.constElementAt(i)->getTarget());
buf.Append(" ");
buf.Append(script_cmds.constElementAt(i)->getCommand());
buf.Append(";;\n");
}//if
}//while
return buf;
}//getScript
/** This gives the compiled, non-running version. Think of it
* as assembly code!
*/
String GenScript::getCompiledScript() {
String buf(1024);
String tmp(100);
String targ(50);
String cmd(100);
for (int i = 0; i < compiled_cmds.getCurLen(); i++) {
if (compiled_cmds.constElementAt(i)) {
targ = compiled_cmds.constElementAt(i)->getTarget();
cmd = compiled_cmds.constElementAt(i)->getCommand();
Sprintf(tmp, "[%i] %S %S\n", i, &targ, &cmd);
buf.Append(tmp);
}//if
}//while
return buf;
}//getCompiledScript
/** This gives the compiled, running version. Think of it
* as machine code!
*/
String GenScript::getRunningScript() {
String buf(1024);
String tmp(100);
//mudlog << "getRunningScript, cur_len: " << running_cmds.getCurLen()
// << endl;
String targ(50);
String cmd(100);
for (int i = 0; i<running_cmds.getCurLen(); i++) {
if (running_cmds.constElementAt(i)) {
targ = running_cmds.constElementAt(i)->getTarget();
cmd = running_cmds.constElementAt(i)->getCommand();
Sprintf(tmp, "[%i] %S %S\n", i, &targ, &cmd);
buf.Append(tmp);
}//if
}//while
return buf;
}//getRunningScript
/** Should these arguments trigger this command? */
int GenScript::matches(const String& cmd, String& arg1, critter& act,
int targ, int obj_actor_num = -1) {
if (mudlog.ofLevel(DBG)) {
mudlog << "GenScript::Matches(args....)" << endl;
mudlog << "Cmd: " << cmd << " arg1 -:" << arg1 << ":- act: "
<< *(name_of_crit(act, ~0))
<< " targ: " << targ << " obj_actor_num: "
<< obj_actor_num << endl;
mudlog << "this: " << toStringBrief(0, 0, ENTITY_ROOM, 0) << endl;
}
if (strcasecmp(cmd, trigger_cmd) == 0) {
mudlog.log("commands are equal...");
// now check to see if arg1 is found ANYWHERE in the
// discriminator (if it exists)
if (trig_discriminator.Strlen() > 0) {
arg1.Tolower();
// Do special checks (but not for say, discuss, yell, or tell)
if (strcasecmp(cmd, "say") && strcasecmp(cmd, "yell")
&& strcasecmp(cmd, "tell") && strcasecmp(cmd, "discuss")) {
//if we're not communications..
if (strcasecmp(cmd, "give") == 0) { //if we are give cmd
int obj_num = atoi(arg1);
if ((obj_num > 0) && (obj_num < NUMBER_OF_ITEMS)) {
if (!strstr(trig_discriminator, arg1)) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, give, target not right."
<< endl;
}
return FALSE;
}//if
}//if
}//if
else if (strcasecmp(cmd, "enter") == 0) {
if (!strstr(trig_discriminator, arg1)) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, enter, descrim wrong."
<< endl;
}
return FALSE;
}
}//else
else if (strcasecmp(cmd, "put") == 0) {
int obj_num = atoi(arg1); //bag
if ((obj_num > 1) && (obj_num < NUMBER_OF_ITEMS)) {
if (!strstr(trig_discriminator, arg1)) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, put, descrim wrong."
<< endl;
}
return FALSE;
}//if
}//if
}
else if ((strcasecmp(cmd, "pull") == 0) ||
(strcasecmp(cmd, "push") == 0)) {
if (!strstr(trig_discriminator, arg1)) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, put, descrim wrong."
<< endl;
}
return FALSE;
}//if
}
// Checks for normal discriminators.
if (strstr(trig_discriminator, "FEM")) {
if (!act.isFemale()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not FEMALE" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "MALE")) {
if (!act.isMale()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not MALE" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "NEUTER")) {
if (!act.isNeuter()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not MALE" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "BARD")) {
if (!act.isBard()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not BARD" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "WARRIOR")) {
if (!act.isWarrior()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not Warrior" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "SAGE")) {
if (!act.isSage()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not SAGE" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "WIZARD")) {
if (!act.isWizard()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not wizard" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "THIEF")) {
if (!act.isThief()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not THIEF" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "ALCHEMIST")) {
if (!act.isAlchemist()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not ALCHEMIST" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "CLERIC")) {
if (!act.isCleric()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not CLERIC" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "HUMAN")) {
if (!act.isHuman()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not Human" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "ANITRE")) {
if (!act.isAnitre()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not ANITRE" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "DARKLING")) {
if (!act.isDarkling()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not DARKLING" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "DRAGON")) {
if (!act.isDragon()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not DRAGON" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "DWARF")) {
if (!act.isDwarf()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not DWARF" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "OGRUE")) {
if (!act.isOgrue()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not OGRUE" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "ELF")) {
if (!act.isElf()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not ELF" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "UNDEAD")) {
if (!act.isUndead()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not UNDEAD" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "ANIMAL")) {
if (!act.isAnimal()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not ANIMAL" << endl;
}
return FALSE;
}//if
}//if
if (strstr(trig_discriminator, "MONSTER")) {
if (!act.isMonster()) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, not MONSTER" << endl;
}
return FALSE;
}//if
}//if
}//if we're not say, discuss, yell, or tell
else {
// Don't just let them guess letters...
if (trig_discriminator.Strlen() >= 5) {
if (arg1.Strlen() < 3) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, arg1.strlen < 3" << endl;
}
return FALSE;
}
}
// Look for substring (trig_discriminator) in arg1
// haystack, needle
//mudlog << "Discrim -:" << trig_discriminator << ":- arg1 -:"
// << arg1 << ":-" << endl;
if (!strstr(arg1, trig_discriminator)) {
String tmp_arg1(arg1.Strlen() + 5);
tmp_arg1.Append(" ");
tmp_arg1.Append(arg1);
tmp_arg1.Append(" ");
//mudlog << "Discrim -:" << trig_discriminator << ":- arg1 -:"
// << tmp_arg1 << ":-" << endl;
if (!strstr(tmp_arg1, trig_discriminator)) {
//now try turning all punctuation to spaces...
for (int i = 0; i<tmp_arg1.Strlen(); i++) {
if (ispunct(tmp_arg1.charAt(i))) {
tmp_arg1.setCharAt(i, ' ');
}//if
}//for
if (!strstr(tmp_arg1, trig_discriminator)) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, discrim, strstr failed."
<< endl;
}
return FALSE;
}//if
}//if
}//if
}//else
}//if, check the discriminator
// Now, other special checks
// Should we check targets??
if (target > 1) {
if (targ != target) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, target != targ" << endl;
}
return FALSE;
}//if
}
if (actor > 1) {
// Objects can be the 'actor' for object scripts (only)
if (obj_actor_num > 0) {
if (obj_actor_num != actor) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, OBJ_NUM != actor" << endl;
}
return FALSE;
}
}
else {
if (act.MOB_NUM != actor) {
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning false, MOB_NUM != actor" << endl;
}
return FALSE;
}
}//else
}//if
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning TRUE" << endl;
}
return TRUE;
}//if
if (mudlog.ofLevel(DBG)) {
mudlog << "Returning FALSE, commands not equal." << endl;
}
return FALSE;
}//matches
// Consider this a weaker == operator (don't compare actuall script)
int GenScript::matches(const GenScript& src) {
if (strcasecmp(trig_discriminator, src.trig_discriminator) != 0)
return FALSE;
if (strcasecmp(trigger_cmd, src.trigger_cmd) != 0)
return FALSE;
if (actor != src.actor)
return FALSE;
if (target != src.target)
return FALSE;
return TRUE;
}//Matches (GenScript)
void GenScript::clean() {
running_cmds.clearAndDestroy();
resetStackPtr();
}
void GenScript::clear() {
trigger_cmd.Clear();
trig_discriminator.Clear();
script_cmds.clearAndDestroy();
compiled_cmds.clearAndDestroy();
running_cmds.clearAndDestroy();
target = actor = -1;
precedence = 0;
stack_ptr = -1;
needs_compiling = TRUE;
next_lbl_num = 0;
}//clear
int MobScript::_cnt = 0;
int MobScript::parseScriptCommand(ScriptCmd& cmd, critter& owner, int& obj_was_deleted) {
// Look at first command and see if it has non-standard actors.
obj_was_deleted = FALSE;
critter* script_actor = NULL;
object* obj_script_actor = NULL;
//Sprintf(tmp_buf, "**M@%ul_%i ", (unsigned int)(&act), rm.getIdNum());
String targ(100);
targ = cmd.getTarget();
if (targ.Strlen() && strncmp("**M@", targ, 4) == 0) {
//we will assume it's right, make the compiler fix it otherwise.
char* foo = (char*)((const char*)targ); //do type conversion.
foo[12] = 0;
unsigned int mob_ptr = strtoul(foo + 4, NULL, 16);
foo[12] = '_'; //put it back like it was, for now
int rm_num = strtol(foo + 13, NULL, 10);
if (mob_ptr != 0) {
rm_num = bound(0, NUMBER_OF_ROOMS, rm_num);
script_actor = room_list[rm_num].haveCritter((critter*)(mob_ptr));
}
}//if
else if (targ.Strlen() && strncmp("**O@", targ, 4) == 0) {
//we will assume it's right, make the compiler fix it otherwise.
char* foo = (char*)((const char*)targ); //do type conversion.
foo[12] = 0;
unsigned int obj_ptr = strtoul(foo + 4, NULL, 16);
foo[12] = '_'; //put it back like it was, for now
int rm_num = strtol(foo + 13, NULL, 10);
if (obj_ptr != 0) {
rm_num = bound(0, NUMBER_OF_ROOMS, rm_num);
obj_script_actor = room_list[rm_num].haveObject((object*)(obj_ptr));
}
}//if
if (obj_script_actor) {
mudlog.log("Had an obj_script_actor.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return obj_script_actor->processInput(targ, room_list[obj_script_actor->getCurRoomNum()],
obj_was_deleted);
}
else if (!script_actor) {
script_actor = &owner;
}//if
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return script_actor->processInput(targ, FALSE, TRUE, &owner, NULL);
}//parseScriptCommand
/** compile() must be called after all appends have been
* completed. It is most definately DOES MODIFY it's argument str.
*/
void GenScript::appendCmd(String& str) {
str.Strip();
if (str.Strlen() > 0) {
String targ(30);
short a,b;
if (strncmp("**%", str, 3) == 0) {
targ = str.Get_Command(a,b); //pop it off the front of the string
}//if
else {
targ = "";
}
script_cmds.appendShallowCopy(new ScriptCmd(targ, str));
}//if
needs_compiling = TRUE;
}//AppendCmd
/** Do all the substitution needed... Be sure to reset the
* stack_ptr after doing this... TODO: Do it here??
* Also
*/
void GenScript::generateScript(String& cmd, String& arg1, critter& act,
int targ, room& rm, critter* script_owner,
object* object_owner = NULL) {
//mudlog << "GenScript::generateScript, compiled_cmds.cur_len: "
// << compiled_cmds.getCurLen() << endl;
if (needs_compiling)
compile();
critter* targ_crit = NULL;
object* targ_obj = NULL;
if (targ > 0) {
// first, generate a critter if possible
if (check_l_range(targ, 0, NUMBER_OF_MOBS, act, FALSE)) {
if (mob_list[targ].CRIT_FLAGS.get(18))
targ_crit = &(mob_list[targ]);
}
if (check_l_range(targ, 0, NUMBER_OF_ITEMS, act, FALSE)) {
if (obj_list[targ].OBJ_FLAGS.get(10))
targ_obj = &(obj_list[targ]);
}
}
int len;
ScriptCmd tmp_cmd;
String cmd_str(50);
String targ_str(50);
String buf(500);
char tmp_buf[100];
char ch;
running_cmds.clearAndDestroy(); //null out entire array.
for (int idx = 0; idx < compiled_cmds.getCurLen(); idx++) {
if (compiled_cmds[idx]) {
tmp_cmd = *(compiled_cmds[idx]);
}
else {
mudlog << "ERROR: idx[" << idx
<< "] Got a null cmd when generating script." << endl;
continue;
}
// First, take care of special case where we are specifying the
// actor with the first command of: **%M
targ_str = tmp_cmd.getTarget();
if (strncmp("**%M", targ_str, 4) == 0) { //actor
sprintf(tmp_buf, "**M@%8X_%i ", (unsigned int)(&act), rm.getIdNum());
targ_str = tmp_buf;
}//if
else if (strncmp("**%m", targ_str, 4) == 0) { //target
sprintf(tmp_buf, "**M@%8X_%i ", (unsigned int)(targ_crit),
rm.getIdNum());
targ_str = tmp_buf;
}//if
else if (strncmp("**%S", targ_str, 4) == 0) { //script owner, default
if (object_owner) {
// For Object Scripts
sprintf(tmp_buf, "**O@%8X_%i ", (unsigned int)(object_owner),
rm.getIdNum());
}
else {
sprintf(tmp_buf, "**M@%8X_%i ", (unsigned int)(script_owner),
rm.getIdNum());
}
targ_str = tmp_buf;
}//if
else if (strncmp("**%o", targ_str, 4) == 0) { //target
sprintf(tmp_buf, "**O@%8X_%i ", (unsigned int)(targ_obj),
rm.getIdNum());
targ_str = tmp_buf;
}//if
else {
targ_str = "";
}
cmd_str = tmp_cmd.getCommand();
// ok, got a command, now lets do substitutions.
// buf accumulates the new command string.
buf.Clear();
len = cmd_str.Strlen();
for (int i = 0; i<len; i++) {
ch = cmd_str[i];
//mudlog << "i: " << i << " ch: " << ch << endl;
if (ch == '%') {
i++;
if (i >= len)
break;
// If here, then check the next char to determine action.
ch = cmd_str[i];
//mudlog << "Before switch: i: " << i << " ch: " << ch << endl;
switch (ch) {
case '%':
buf.Append("%");
break;
case 'M': //ACTOR
buf.Append(*(act.getShortName(~0)));
break;
case 'm': //target
if (targ_crit) {
buf.Append(*(targ_crit->getShortName(~0)));
}
break;
case 'o': //target
if (targ_obj) { //this is the short name, btw
buf.Append(*(targ_obj->getName(~0)));
}
break;
case 'S': // one running script, if mob
if (script_owner) {
buf.Append(*(script_owner->getName(~0)));
}//if
else if (object_owner) {
buf.Append(*(object_owner->getName(~0)));
}
break;
default:
buf.Append("__PARSE ERROR__");
}//switch
}//if we found a % sign
else if (ch == '\n') {
buf.Append(' ');
}
else {
buf.Append(ch);
}
}//for
// When here, we have a command, ready to be put onto the queue.
//mudlog << "Setting running_cmds[" << idx << "] " << buf << endl;
// No need to set and destroy because we cleared earlier.
running_cmds.set(new ScriptCmd(targ_str, buf), idx);
//mudlog << "Running_cmds.curlen: " << running_cmds.getCurLen()
// << endl;
//mudlog << getRunningScript() << endl;
}//for
}//GenerateScript
void GenScript::compile() { //compile into script assembly...
// The trick will be to turn the normal script into something
// more easily understood and dealt with by the computer. For
// now, we will parse if-then-else statements, and compute labels.
// First, walk the entire set of commands, translating high level
// constructs into label jumps. Later, will translate label jumps
// into index jumps.
//mudlog << "In GenScript::compile" << endl;
compiled_cmds.clearAndDestroy();
PtrArray<ScriptCmd> first_pass(100); //will hold first pass compile results
int i = 0;
//mudlog << "About to parse Block" << endl;
parseBlockFP(i, script_cmds, first_pass);
//mudlog << "About to optimize labels." << endl;
optimizeLabels(first_pass, compiled_cmds);
if (mudlog.ofLevel(DBG)) {
//mudlog << "All done compiling, compiled_cmds:" << endl;
//for (int z = 0; z<compiled_cmds.getCurLen(); z++) {
// mudlog << *(compiled_cmds.constElementAt(z)) << endl;
//}//for
}//if
first_pass.clearAndDestroy();
needs_compiling = FALSE;
}//compile
int GenScript::findOffset(List<KVPair<String, int>*>& lst,
const String& str) {
Cell<KVPair<String, int>*> cll(lst);
KVPair<String, int>* ptr;
// Key is label, val is the index.
while ((ptr = cll.next())) {
if (strcmp(ptr->key, str) == 0) {
return ptr->val;
}//if
}//while
return -1;
}
void GenScript::optimizeLabels(const PtrArray<ScriptCmd>& incomming,
PtrArray<ScriptCmd>& rslts) {
short eos, tbp; //not really using these...
//mudlog << "In optimize Labels" << endl;
List<KVPair<String, int>*> labels;
rslts.clearAndDestroy();
//find all labels and compute their offsets.
String first_cmd;
String cmd_str(100);
String new_cmd(200);
String buf(200);
int offset;
for (int i = 0; i<incomming.getCurLen(); i++) {
cmd_str = incomming.constElementAt(i)->getCommand();
first_cmd = cmd_str.Look_Command();
if (strcasecmp(first_cmd, "label:") == 0) {
//mudlog << "Found a label on line: " << i << " -:"
// << *(incomming.constElementAt(i)) << endl;
//we don't care what this responds..it's a label cmd, just want to
// strip it off of the string.
cmd_str.Get_Command(eos, tbp);
cmd_str.Strip();
// Makes a copy of incomming data, btw.
labels.append(new KVPair<String, int>(cmd_str, i));
}//if
}//for
// So now, we have all the labels... Now lets translate the script_goto's
// into script_jumps.
//mudlog << "Optimize Labels: translating script_goto's into script_jumps"
// << endl;
String tmp_cmd(50);
for (int i = 0; i<incomming.getCurLen(); i++) {
cmd_str = incomming.constElementAt(i)->getCommand();
first_cmd = cmd_str.Look_Command();
//mudlog << "Line[" << i << "] " << *(incomming.constElementAt(i))
// << endl;
if (strncasecmp(first_cmd, "script_goto", strlen("script_goto")) == 0) {
//mudlog << "Found script_goto on line: " << i << endl;
tmp_cmd = cmd_str.Get_Command(eos, tbp); //grab first one again
tmp_cmd = cmd_str.Get_Command(eos, tbp); //grab second one (label)
tmp_cmd.Strip();
offset = findOffset(labels, tmp_cmd);
if (offset < 0) {
mudlog << "ERROR: got a -1 for findOffset for label -:"
<< tmp_cmd << ":-" << endl;
}
cmd_str.Strip();
if (strncasecmp(first_cmd, "script_goto_false",
strlen("script_goto_false")) == 0) {
Sprintf(buf, "script_jump_false %i %S", offset, &cmd_str);
}
else {
Sprintf(buf, "script_jump_true %i %S", offset, &cmd_str);
}
rslts.appendShallowCopy(new ScriptCmd(incomming.constElementAt(i)->getTarget(), buf));
}//if
else {
rslts.appendShallowCopy(new ScriptCmd(*(incomming.constElementAt(i))));
}//for
}//for
}//optimizeLabels
String GenScript::getNextLabel() {
String retval(30);
Sprintf(retval, "LaBeL__%i", next_lbl_num);
next_lbl_num++;
return retval;
}
void GenScript::parseBlockFP(int& start_idx,
const PtrArray<ScriptCmd>& incomming,
PtrArray<ScriptCmd>& rslts) {
short eos, tbp; //not really using these...
String first_cmd;
String cmd_str(100);
String new_cmd(200);
String tmp2(100);
int i;
//mudlog << "In parseBlockFP: idx: " << start_idx << endl;
for (i = start_idx; i<incomming.getCurLen(); i++) {
cmd_str = incomming.constElementAt(i)->getCommand();
// lets look at the command, and deal with it.
first_cmd = cmd_str.Look_Command();
//mudlog << "Incomming[" << i << "] " << *(incomming.constElementAt(i))
// << " FirstCommand: " << first_cmd << endl;
if (strcasecmp(first_cmd, "if") == 0) {
//mudlog << "Was an 'if'" << endl;
//insert a label jump in rslts.
cmd_str.Get_Command(eos, tbp); //strip first "if" cmd off of it
// Now get next two labels.
String lbl_false = getNextLabel();
Sprintf(new_cmd, "script_goto_false %S %S", &lbl_false, &cmd_str);
rslts.appendShallowCopy(new ScriptCmd(incomming.constElementAt(i)->getTarget(), new_cmd));
//if it's true, then just fall through...
// Now, get all stuff up to the else (or end)
PtrArray<ScriptCmd> internal_block;
// recurse
i++;
parseBlockFP(i, incomming, internal_block);
// we grab pointers, shallow copy, so there is no need to
// delete the new data allocated for internal_block
rslts.appendShallowCopy(internal_block);
// Now do the second block, the else.
internal_block.clear(); //don't delete ptrs
// We want to jump over the 'else' part if we ran the first
// part, so make a jump to the end of the entire "if".
String lbl_eo_if = getNextLabel();
Sprintf(new_cmd, "script_goto_true %S TRUE", &lbl_eo_if);
rslts.appendShallowCopy(new ScriptCmd(NULL_STRING, new_cmd));
// Now append the false label from above.
Sprintf(tmp2, "label: %S", &lbl_false);
rslts.appendShallowCopy(new ScriptCmd(NULL_STRING, tmp2));
parseBlockFP(i, incomming, internal_block);
i--; //parseBlock sets to next one, and for loop increments as well.
// So, decrement it by one to negate for-loop increment in this case.
rslts.appendShallowCopy(internal_block);
internal_block.clear(); //just null out ptrs, don't delete data
Sprintf(tmp2, "label: %S", &lbl_eo_if);
rslts.appendShallowCopy(new ScriptCmd(NULL_STRING, tmp2));
// Now, increment i (automatically, and continue!
}//if it was an if statement
else if (strcasecmp(first_cmd, "else") == 0) {
//then done with a block.
start_idx = i + 1;
return;
}
else if (strcasecmp(first_cmd, "end") == 0) {
//then done with a block.
start_idx = i + 1;
return;
}
else {
rslts.appendShallowCopy(new ScriptCmd(*(incomming.constElementAt(i))));
}//else
}//for
start_idx = i + 1;
}//parseBlockFP
void GenScript::read(ifstream& da_file) {
char buf[100];
clear();
mudlog.log(DB, "in GenScript::Read()");
if (!da_file) {
if (mudlog.ofLevel(ERROR)) {
mudlog << "ERROR: da_file FALSE in GenScript read." << endl;
}
return;
}
da_file >> buf;
trigger_cmd = buf;
if (mudlog.ofLevel(DB))
mudlog << "Trigger: -:" << trigger_cmd << ":-" << endl << flush;
da_file >> target >> actor >> precedence;
if (mudlog.ofLevel(DB))
mudlog << "Target: " << target << " actor: " << actor << " takes_prec: "
<< precedence << endl;
da_file.getline(buf, 80);
if (mudlog.ofLevel(DB))
mudlog << "Rest of line -:" << buf << ":-" << endl;
trig_discriminator.Getline(da_file, 80);
if (mudlog.ofLevel(DB))
mudlog << "Trig_discriminator -:" << trig_discriminator << ":-" << endl;
if (trig_discriminator.Strlen() > 0) {
trig_discriminator.Strip();
trig_discriminator.Prepend(" ");
trig_discriminator.Append(" ");
}
// now, read in the command script
// It will be one large chuck of text, which will be parsed
// and put into the queue.
String sbuf(1024);
sbuf.Termed_Read(da_file);
if (mudlog.ofLevel(DB)) {
mudlog << "Script read: Termed Read: -:" << sbuf << ":-\n" << endl;
}
String* tmp_str;
while ((tmp_str = sbuf.getUntil(';'))) {
if (mudlog.ofLevel(DB)) {
mudlog << "Script read: Get Until: -:" << *tmp_str << ":-" << endl;
}
appendCmd(*tmp_str);
delete tmp_str;
}
compile(); //Compile into script assembly code
}//Read
void GenScript::write(ofstream& da_file) const {
da_file << trigger_cmd << " " << target
<< " " << actor << " " << precedence
<< "\t Trigger Command, targ, actor \n";
da_file << trig_discriminator << endl;
String output(1024);
for (int i = 0; i<script_cmds.getCurLen(); i++) {
if (script_cmds.constElementAt(i)) {
output.Append(script_cmds.constElementAt(i)->getTarget());
output.Append(" ");
output.Append(script_cmds.constElementAt(i)->getCommand());
output.Append(";\n");
}//if
}//for
da_file << output << "\n~\n";
}//Write
int RoomScript::_cnt = 0;
int RoomScript::parseScriptCommand(ScriptCmd& cmd, room& owner, int& obj_was_deleted) {
obj_was_deleted = FALSE;
if (mudlog.ofLevel(DBG)) {
mudlog << "RoomScript::parseScriptCommand, target -:"
<< cmd.getTarget() << ":- cmd -:"
<< cmd.getCommand() << ":- owner id: "
<< owner.getIdNum() << endl;
}
String command(cmd.getCommand());
// Look at first command and see if it has non-standard actors.
critter* script_actor = NULL;
object* obj_script_actor = NULL;
// This is how the target is created, btw.
//Sprintf(tmp_buf, "**M@%ul_%i ", (unsigned int)(&act), rm.getIdNum());
String targ(50);
targ = cmd.getTarget();
if (targ.Strlen() && strncmp("**M@", targ, 4) == 0) {
//we will assume it's right, make the compiler fix it otherwise.
char* foo = (char*)((const char*)targ); //do type conversion.
foo[12] = 0;
unsigned int mob_ptr = strtoul(foo + 4, NULL, 16);
foo[12] = '_'; //put it back like it was, for now
int rm_num = strtol(foo + 13, NULL, 10);
if (mob_ptr != 0) {
rm_num = bound(0, NUMBER_OF_ROOMS, rm_num);
script_actor = room_list[rm_num].haveCritter((critter*)(mob_ptr));
}
}//if
else if (targ.Strlen() && strncmp("**O@", targ, 4) == 0) {
//we will assume it's right, make the compiler fix it otherwise.
char* foo = (char*)((const char*)targ); //do type conversion.
foo[12] = 0;
unsigned int obj_ptr = strtoul(foo + 4, NULL, 16);
foo[12] = '_'; //put it back like it was, for now
int rm_num = strtol(foo + 13, NULL, 10);
if (obj_ptr != 0) {
rm_num = bound(0, NUMBER_OF_ROOMS, rm_num);
obj_script_actor = room_list[rm_num].haveObject((object*)(obj_ptr));
}
}//if
if (obj_script_actor) {
mudlog.log("Had an obj_script_actor.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return obj_script_actor->processInput(targ, room_list[obj_script_actor->getCurRoomNum()],
obj_was_deleted);
}
else if (script_actor) {
mudlog.log("Had a script_actor.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return script_actor->processInput(targ, FALSE, TRUE, NULL, &owner);
}
else {
mudlog.log("Room was the owner.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return owner.processInput(targ);
}
}//parseScriptCommand
int ObjectScript::_cnt = 0;
int ObjectScript::parseScriptCommand(ScriptCmd& cmd, object& owner, int& obj_was_deleted) {
obj_was_deleted = FALSE;
if (mudlog.ofLevel(DBG)) {
mudlog << "ObjectScript::parseScriptCommand, target -:"
<< cmd.getTarget() << ":- cmd -:"
<< cmd.getCommand() << ":- owner id: "
<< owner.getIdNum() << " obj_cur_room# " << owner.getCurRoomNum()
<< endl;
}
String command(cmd.getCommand());
// Look at first command and see if it has non-standard actors.
critter* script_actor = NULL;
object* obj_script_actor = NULL;
// This is how the target is created, btw.
//Sprintf(tmp_buf, "**M@%ul_%i ", (unsigned int)(&act), rm.getIdNum());
String targ(50);
targ = cmd.getTarget();
if (targ.Strlen() && strncmp("**M@", targ, 4) == 0) {
//we will assume it's right, make the compiler fix it otherwise.
char* foo = (char*)((const char*)targ); //do type conversion.
foo[12] = 0;
unsigned int mob_ptr = strtoul(foo + 4, NULL, 16);
foo[12] = '_'; //put it back like it was, for now
int rm_num = strtol(foo + 13, NULL, 10);
if (mob_ptr != 0) {
rm_num = bound(0, NUMBER_OF_ROOMS, rm_num);
script_actor = room_list[rm_num].haveCritter((critter*)(mob_ptr));
}
}//if
else if (targ.Strlen() && strncmp("**O@", targ, 4) == 0) {
//we will assume it's right, make the compiler fix it otherwise.
char* foo = (char*)((const char*)targ); //do type conversion.
foo[12] = 0;
unsigned int obj_ptr = strtoul(foo + 4, NULL, 16);
foo[12] = '_'; //put it back like it was, for now
int rm_num = strtol(foo + 13, NULL, 10);
if (obj_ptr != 0) {
rm_num = bound(0, NUMBER_OF_ROOMS, rm_num);
obj_script_actor = room_list[rm_num].haveObject((object*)(obj_ptr));
}
}//if
if (obj_script_actor) {
mudlog.log("Had an obj_script_actor.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return obj_script_actor->processInput(targ, room_list[obj_script_actor->getCurRoomNum()],
obj_was_deleted);
}
else if (script_actor) {
mudlog.log("Had a script_actor.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return script_actor->processInput(targ, FALSE, TRUE, NULL,
&(room_list[owner.getCurRoomNum()]));
}
else {
mudlog.log("Room was the owner.\n");
targ = cmd.getCommand(); //reuse targ, it should contain the command now.
return owner.processInput(targ, room_list[owner.getCurRoomNum()],
obj_was_deleted);
}
}//parseScriptCommand