/* Flode - 1997
*
* Taniwha, stripped back to some basic checks which we'll run on all
* commands. They are parsed differently from spells to the
* set_prop has 2 arguments:
* 1st: name of property
* 2nd: error message when you haven't got the property
*
* Malik, Sept 97, Major slashing, hacking and reworking.
* should do what it needs to now.
*
* flags:
* 1: allowed on yourself | allow_yourself()
* 2: allowed on dead | allow_dead()
* 4: allowed on pacified | allow_pacify()
* 8: allowed on creators | allow_creator()
* 16: allowed on things | allow_thing()
* 32: ONLY in combat | only_combat()
* 64: NEVER in combat | never_combat()
*/
inherit "/std/commands/target.c";
mapping guilds = ([]);
mapping races = ([]);
int flags;
int prior;
int lockout;
int sec_lockout;
string mess;
string sec_lock_prop;
string help_string;
string target_type;
string command_name;
object *target = ({});
void create(){
seteuid("/secure/master"->creator_file(file_name(this_object())));
lockout = 1;
this_object()->setup();
}
void allow_yourself() { flags |= 1; }
void allow_dead() { flags |= 2; }
void allow_pacify() { flags |= 4; }
void allow_creator() { flags |= 8; }
void allow_thing() { flags |= 16; }
void only_combat() { flags |= 32; flags &= ~64; }
void never_combat() { flags |= 64; flags &= ~32; }
void set_flags(int i) { flags = i; }
void set_command_name(string str){
command_name = str;
}
object *aquire_target(string str,string target_type,object doer){
object *ob;
string str1,str2;
object inwho;
if(flags & 16){
/* needless to say. having more than one of 'on, in or from' is bad */
if(strsrch(str," on ") >= 0) // it's an item in someone/something
sscanf(str,"%s on %s",str1,str2);
if(strsrch(str," in ") >= 0)
sscanf(str,"%s in %s",str1,str2);
if(strsrch(str," from ") >= 0)
sscanf(str,"%s from %s",str1,str2);
}
if(target_type == "one"){
if(!(flags & 16)){
ob = find_one_match(str, doer);
if(!sizeof(ob))
ob = find_one_match(str, environment(doer));
}
if(flags & 16){
inwho = find_one_match(str2,environment(doer));
if(inwho)
ob = find_one_match(str1,inwho);
}
}
if(target_type == "many"){
ob = find_unique_match(str, doer);
if(!sizeof(ob)){
ob = find_unique_match(str, environment(doer));
}
}
return ob;
} /* aquire_target() */
int exec_command(string str, object doer){
object env;
int i;
doer = doer ? doer:this_player();
env = environment(doer);
if(!env){
tell_object(doer,"You're nowhere and can't do much right now.\n");
return 1;
}
// No need to check the syntax if we're doing other commands
/* was a syntax check in here before, not needed now I hope */
if(doer->query_property("comm_lockout")||
doer->query_property(sec_lock_prop)){
tell_object(doer,"You are not calm enough.\n");
return 1;
}
if(doer->query_property("noguild") ||
environment(doer)->query_property("noguild") ||
doer->query_property("passed out")){
tell_object(doer,"You cannot do this right now.\n");
return 1;
}
doer->add_timed_property("comm_lockout",
({env,doer->query_hb_counter()}),lockout );
if(sec_lock_prop){
doer->add_timed_property(sec_lock_prop,1,sec_lockout);
}
if(target_type == "pass"){
return this_object()->do_command(str,doer);
}
target = aquire_target(str, target_type, doer);
for(i=0;i<sizeof(target);i++){
if(living(target[i])){
if(target[i]->query_hide_shadow()||target[i]->query_invis()){
target[i] = 0;
}
}
}
target -= ({0});
prior = 0;
mess = "";
if(!sizeof(doer->query_attacker_list()) && (flags & 32)){
mess = "You have no opponent in front of you.\n";
target = ({});
}
if(sizeof(doer->query_attacker_list()) && (flags & 64)){
mess = "You are fighting right now.\n";
target = ({});
}
for(i=0;i<sizeof(target);i++){
if(target[i] == doer && !(flags & 1)){
if(prior < 2){
mess = "That could hurt.\n";
prior = 2;
}
target[i] = 0;
continue;
}
if(target[i]->query_dead() && interactive(target[i]) && !(flags & 2)){
if(prior < 1){
mess = target[i]->query_cap_name()+" is dead.\n";
prior = 1;
}
target[i] = 0;
continue;
}
if(!(flags & 4)){
if(target[i]->query_property("pacify_on")){
if(prior < 1){
mess = target[i]->query_cap_name()+" is harmless.\n";
prior = 1;
}
target[i] = 0;
continue;
}
if(doer->query_property("pacify_on")){
if(prior < 2){
mess = "You feel too peaceful to do anything at all.\n";
prior = 2;
}
target[i] = 0;
continue;
}
}
if(!doer->query_creator() && target[i]->query_creator() &&
!(flags & 8)){
if(prior < 2){
mess = "How dare you attempt this on the immortal "
+target[i]->query_cap_name()+"!\n";
prior = 2;
}
target[i] = 0;
continue;
}
if(!living(target[i]) && !(flags & 16)){
if(prior < 1){
mess = "Try to find something alive.\n";
prior = 1;
}
target[i] = 0;
continue;
}
}
target -= ({0});
if(sizeof(target)){
if(target_type == "one")
return this_object()->do_command(target[0],doer);
if(target_type == "many")
return this_object()->do_command(target,doer);
}
if(strlen(mess)){
tell_object(doer,mess);
return 1;
}
else{
tell_object(doer,""
+((flags & 16)?"Nothing ":"Noone ")+"here going by that name.\n");
doer->adjust_gp(-1);
return 1;
}
} /* exec_command() */
int adjust_for_skills(int i, object user){
string *list;
/* if it's guild only, guilds["default"]
has the penalty to be applied to guilds not listed
note if you use guilds, put in a default for other
guilds. lack of a "default" will make non-listed
guilds have a multiplier of 0. ie none */
if(sizeof(guilds)){
list = keys(guilds);
if(member_array(user->query_guild_name(),list) == -1){
i = i * guilds["default"] / 100;
}
else{
i = i*guilds[user->query_guild_name()]/100;
}
}
/* same for races as guilds */
if(sizeof(races)){
list = keys(races);
if(member_array(user->query_race_name(),list) == -1){
i = i*races["default"]/100;
}
else{
i = i*races[user->query_race_name()]/100;
}
}
return i;
} /* adjust_for_skills() */
int command_damage(int damage,object attacker,object victim){
damage = adjust_for_skills(damage,attacker);
// need this be automated? - malik
// damage = property_checks(properties,attacker,victim,damage);
// will put this in soon for priests i assume. - malik
// damage = align_checks(attacker,victim,damage);
if(damage < 0) victim->attack_by(attacker);
victim->adjust_hp(damage,attacker);
return damage;
} /* command_damage() */
int command_cost(int cost, object doer){
if(doer->query_gp()<cost){
doer->set_gp(0);
return 0;
}
doer->adjust_gp(-cost);
return 1;
} /* command_cost() */
int command_experience(int xp, object doer){
int val;
val = doer->adjust_xp(xp,doer);
} /* command_experience() */
void setup_hb_command(object doer, int rnds, mixed *params){
doer->add_spell_effect(rnds,
"command",
command_name,
this_object(),
"hb_command_check",
params);
} /* setup_hb_command() */
int hb_command_check(object doer, mixed *params, int time){
if(doer->query_property("noguild") ||
environment(doer)->query_property("noguild"))
return 0;
return this_object()->hb_command(doer, params, time);
} /* hb_command_check() */
/* NOTICE: if you call end_hb_command. USE CALL_OUT!!!!! */
/* something about deleting effects before they've ended */
void end_hb_command(object doer){
if(doer->query_spell_effect("command"))
doer->remove_spell_effect(command_name);
} /* end_hb_command() */
/* Returns 1 if circle is possible,
* 2 if nothing is possible,
* 0 if normal backstab possible
* also used by ambush
*/
int already_attacking(object me,object victim){
if(member_array(me,victim->query_attacker_list()) != -1)
return 1;
if(member_array(me,victim->query_call_outed()) != -1)
return 1;
if(sizeof(me->query_attacker_list()))
return 2;
return 0;
} /* already_attacking() */
void set_help_string(string str){
help_string = str;
} /* set_help_string() */
string help(){
return help_string;
} /* help() */