/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Envy Diku Mud, you must comply with * * the original Diku license in 'license.doc', the Merc license in * * 'license.txt', as well as the Envy license in 'license.nvy'. * * In particular, you may not remove either of these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * * * * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * * * * Code Adapted and Improved by Abandoned Realms Mud * * and Aabahran: The Forsaken Lands Mud by Virigoth * * * * Continued Production of this code is available at www.flcodebase.com * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ /*************************************************************************** * * * MOBprograms for ROM 2.4 v0.98g (C) M.Nylander 1996 * * Based on MERC 2.2 MOBprograms concept by N'Atas-ha. * * Written and adapted to ROM 2.4 by * * Markku Nylander (markku.nylander@uta.fi) * * This code may be copied and distributed as per the ROM license. * * * ***************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/types.h> #include <ctype.h> #include "merc.h" #include "cabal.h" #include "clan.h" extern bool disguise_check( CHAR_DATA* ch, int iClass ); extern int flag_lookup( const char *word, const struct flag_type *flag_table ); extern void expand_arg_mob( char *buf, const char *format, CHAR_DATA *mob, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ); extern void expand_arg_other( char *buf, const char *format, OBJ_DATA *obj, ROOM_INDEX_DATA *room, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ); /* * These defines correspond to the entries in fn_keyword[] table. * If you add a new if_check, you must also add a #define here. */ #define CHK_RAND (0) #define CHK_MOBHERE (1) #define CHK_OBJHERE (2) #define CHK_MOBEXISTS (3) #define CHK_OBJEXISTS (4) #define CHK_PEOPLE (5) #define CHK_PLAYERS (6) #define CHK_MOBS (7) #define CHK_CLONES (8) #define CHK_ORDER (9) #define CHK_HOUR (10) #define CHK_ISPC (11) #define CHK_ISNPC (12) #define CHK_ISGOOD (13) #define CHK_ISEVIL (14) #define CHK_ISNEUTRAL (15) #define CHK_ISIMMORT (16) #define CHK_ISCHARM (17) #define CHK_ISFOLLOW (18) #define CHK_ISACTIVE (19) #define CHK_ISDELAY (20) #define CHK_ISVISIBLE (21) #define CHK_HASTARGET (22) #define CHK_ISTARGET (23) #define CHK_EXISTS (24) #define CHK_AFFECTED (25) #define CHK_ACT (26) #define CHK_OFF (27) #define CHK_IMM (28) #define CHK_CARRIES (29) #define CHK_WEARS (30) #define CHK_HAS (31) #define CHK_USES (32) #define CHK_NAME (33) #define CHK_POS (34) #define CHK_CABAL (35) #define CHK_RACE (36) #define CHK_CLASS (37) #define CHK_OBJTYPE (38) #define CHK_VNUM (39) #define CHK_HPCNT (40) #define CHK_ROOM (41) #define CHK_SEX (42) #define CHK_LEVEL (43) #define CHK_ALIGN (44) #define CHK_MONEY (45) #define CHK_OBJVAL0 (46) #define CHK_OBJVAL1 (47) #define CHK_OBJVAL2 (48) #define CHK_OBJVAL3 (49) #define CHK_OBJVAL4 (50) #define CHK_GRPSIZE (51) #define CHK_AFF_SPELL (52) #define CHK_GETDELAY (53) #define CHK_ISCARRIED (54) #define CHK_ISWORN (55) #define CHK_FOLLOWERS (56) #define CHK_OBJCOST (57) #define CHK_ISBLOODY (58) #define CHK_HASQUEST (59) #define CHK_ISHERE (60) #define CHK_ISCOMBAT (61) #define CHK_ISROYAL (62) #define CHK_HOMETOWN (63) #define CHK_CLAN (64) #define CHK_CRANK (65) #define CHK_ISELAWFUL (66) #define CHK_ISENEUTRAL (67) #define CHK_ISECHAOTIC (68) #define CHK_DISGUISE (69) #define CHK_CABALLY (70) #define CHK_CABENEMY (71) #define CHK_CABNEUT (72) #define CHK_AFFECTED2 (73) #define CHK_CP (74) #define CHK_SKILL (75) #define CHK_EQUIP (76) #define CHK_NCARRIES (77) #define CHK_RELIGION (78) #define CHK_MOBCOUNT (79) #define CHK_EXIT (80) #define CHK_CONTAINS (81) #define CHK_NCONTAINS (82) #define CHK_HASPATH (83) #define CHK_PATH (84) #define CHK_NOBLE (85) #define CHK_ISPOISONED (86) /* * These defines correspond to the entries in fn_evals[] table. */ #define EVAL_EQ 0 #define EVAL_GE 1 #define EVAL_LE 2 #define EVAL_GT 3 #define EVAL_LT 4 #define EVAL_NE 5 /* * if-check keywords: */ const char * fn_keyword[] = { "rand", /* if rand 30 - if random number < 30 */ "mobhere", /* if mobhere fido - is there a 'fido' here */ "objhere", /* if objhere bottle - is there a 'bottle' here */ /* if mobhere 1233 - is there mob vnum 1233 here */ /* if objhere 1233 - is there obj vnum 1233 here */ "mobexists", /* if mobexists fido - is there a fido somewhere */ "objexists", /* if objexists sword - is there a sword somewhere */ "people", /* if people > 4 - does room contain > 4 people */ "players", /* if players > 1 - does room contain > 1 pcs */ "mobs", /* if mobs > 2 - does room contain > 2 mobiles */ "clones", /* if clones > 3 - are there > 3 mobs of same vnum here */ "order", /* if order == 0 - is mob the first in room */ "hour", /* if hour > 11 - is the time > 11 o'clock */ "ispc", /* if ispc $n - is $n a pc */ "isnpc", /* if isnpc $n - is $n a mobile */ "isgood", /* if isgood $n - is $n good */ "isevil", /* if isevil $n - is $n evil */ "isneutral", /* if isneutral $n - is $n neutral */ "isimmort", /* if isimmort $n - is $n immortal */ "ischarm", /* if ischarm $n - is $n charmed */ "isfollow", /* if isfollow $n - is $n following someone */ "isactive", /* if isactive $n - is $n's position > SLEEPING */ "isdelay", /* if isdelay $i - does $i have mobprog pending */ "isvisible", /* if isvisible $n - can mob see $n */ "hastarget", /* if hastarget $i - does $i have a valid target */ "istarget", /* if istarget $n - is $n mob's target */ "exists", /* if exists $n - does $n exist somewhere */ "affected", /* if affected $n blind - is $n affected by blind */ "act", /* if act $i sentinel - is $i flagged sentinel */ "off", /* if off $i berserk - is $i flagged berserk */ "imm", /* if imm $i fire - is $i immune to fire */ "carries", /* if carries $n sword - does $n have a 'sword' */ /* if carries $n 1233 - does $n have obj vnum 1233 */ "wears", /* if wears $n lantern - is $n wearing a 'lantern' */ /* if wears $n 1233 - is $n wearing obj vnum 1233 */ "has", /* if has $n weapon - does $n have obj of type weapon */ "uses", /* if uses $n armor - is $n wearing obj of type armor */ "name", /* if name $n puff - is $n's name 'puff' */ "pos", /* if pos $n standing - is $n standing */ "cabal", /* if cabal $n 'whatever'- does $n belong to cabal 'whatever' */ "race", /* if race $n dragon - is $n of 'dragon' race */ "class", /* if class $n mage - is $n's class 'mage' */ "objtype", /* if objtype $p scroll - is $p a scroll */ "vnum", /* if vnum $i == 1233 - virtual number check */ "hpcnt", /* if hpcnt $i > 30 - hit point percent check */ "room", /* if room $i == 1233 - room virtual number */ "sex", /* if sex $i == 0 - sex check */ "level", /* if level $n < 5 - level check */ "align", /* if align $n < -1000 - alignment check */ "money", /* if money $n */ "objval0", /* if objval0 $i > 1000 - object value[] checks 0..4 */ "objval1", "objval2", "objval3", "objval4", "grpsize", /* if grpsize $n > 6 - group size check */ "affspell", /* if affspell $n 'mark of prey' - check if affected by - */ "getdelay", /* if getdelay > 1 - trigger owner has present delay*/ "iscarried", /* if iscarried $i - if $i is carried */ "isworn", /* if isworn $i - if $i is worn */ "followers", /* if followers $n > 6 - charmies check */ "objcost", /* if objcost $i > 1000 - object cost */ "isbloody", /* if isbloody $n - is char bloody */ "hasquest", /* if hasquest $n 'Slayed A Dragon' - checks for a quest */ "ishere", /* if ishere $q - is mob/pc/obj here (uses ONLY $ codes unlike mobhere) */ "iscombat", /* if iscombat $n - is $n in combat */ "isroyal", /* if isroyal $n - is $n a Royal */ "hometown", /* if hometown $n whatever - is $n from this hometown*/ "clan", /* if clan $n whatever - does $n belong to whatever*/ "crank", /* if crank $n < 5 - is n's clan rank < 5 */ "iselawful", /* if iselawful $n - is n's ethos lawful */ "iseneutral", /* if iseneutral $n - is n's ethos neutral */ "isechaotic", /* if isechaotic $n - is n's ethos chaotic */ "disguise", /* if disguise $n warrior- perform disguise check */ "cabally", /* if cabally $n justice - is $n an ally of justice (alliance) */ "cabenemy", /* if cabenemy $n justice - is $n an enemy of justice (vendetta) */ "cabneut", /* if cabneut $n justice - is $n neutral with justice (napact/none) */ "affected2", /* if affected2 $n blind - is $n affected by AFF2 bit given */ "cp", /* if cp $n < 15 checks for cabal points */ "skill", /* if skill $n <skill> checks for character having a given skill ( >= 1 ) */ "equipped", /* if equip $n <wearloc> checks char is wearing anything in given wearloc */ "ncarries", /* if ncarries $n 12 sword - does $n have 12 or more 'sword's */ /* if ncarries $n 12 300 - does $n have 12 or more vnum 300's */ "religion", /* if religion $n 'nature'- does $n follow nature */ "mobcount", /* if mobcount 121 > 4 - are there more then 4 mobs with vnum 121 in world */ "exit", /* if exit north <flag> - is the flag set on exit */ "contains", /* if contains $i sword - does $i contai a sword */ "ncontains", /* if ncontains $i 1 sword - does actor contain 1 or more swords */ "haspath", /* if haspath $n - does actor have a path set */ "path", /* if path $n == 1024 - does actor have a path set to room 1024 */ "isnoble", /* if isnoble $n - is $n a Royal */ "ispoisoned", /* if ispoisoned $n - is $n poinsed with non-self poison */ "\n" /* Table terminator */ }; const char *fn_evals[] = { "==", ">=", "<=", ">", "<", "!=", "\n" }; /* checks for not self inflicted poison */ bool check_poison( CHAR_DATA* ch ){ AFFECT_DATA* paf; if (IS_NPC(ch)) return FALSE; for (paf = ch->affected; paf; paf = paf->next ){ if (paf->type != gsn_poison ) continue; //if mob poison, then poisoned else if (IS_NULLSTR(paf->string)) return TRUE; //if pc poison not from self, then piosoned else if (str_cmp(ch->name, paf->string)) return TRUE; //otherwise self poisoned, then not poisoned else return FALSE; } return FALSE; } /* * Return a valid keyword from a keyword table */ int keyword_lookup( const char **table, char *keyword ) { register int i; for( i = 0; table[i][0] != '\n'; i++ ) if( !str_cmp( table[i], keyword ) ) return( i ); return -1; } /* * Perform numeric evaluation. * Called by cmd_eval() */ int num_eval( int lval, int oper, int rval ) { switch( oper ) { case EVAL_EQ: return ( lval == rval ); case EVAL_GE: return ( lval >= rval ); case EVAL_LE: return ( lval <= rval ); case EVAL_NE: return ( lval != rval ); case EVAL_GT: return ( lval > rval ); case EVAL_LT: return ( lval < rval ); default: bug( "num_eval: invalid oper", 0 ); return 0; } } /* * --------------------------------------------------------------------- * UTILITY FUNCTIONS USED BY CMD_EVAL() * ---------------------------------------------------------------------- */ /* * check for given number of mobs in the world */ int world_mobcount( char* argument ){ CHAR_DATA* vch; int vnum = atoi( argument ); int total = 0; for ( vch = char_list; vch != NULL ; vch = vch->next ){ if ( vch->in_room == NULL ) continue; if (vnum > 0 && IS_NPC(vch) && vch->pIndexData->vnum == vnum) total++; else if ( vnum < 1 && is_name(argument, vch->name)) total++; else continue; } return total; } /* * Get a random PC in the room (for $r parameter) */ CHAR_DATA *get_random_char( CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room ) { CHAR_DATA *vch, *victim = NULL; int now = 0, highest = 0; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "get_random_char received multiple prog types",0); return NULL; } if ( mob ) vch = mob->in_room->people; else if ( obj ) { if ( obj->in_room ) vch = obj->in_room->people; else vch = obj->carried_by->in_room->people; } else vch = room->people; for( ; vch; vch = vch->next_in_room ) { if ( mob && (mob == vch || !can_see( mob, vch )) ) continue; if (IS_NPC( vch ) ) continue; if (( now = number_percent() ) > highest ) { victim = vch; highest = now; } else if ( (now = number_percent()) > highest ) { victim = vch; highest = now; } } return victim; } /* * Get a random NPC in the room (for $R parameter) */ CHAR_DATA *get_random_mob( CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room ) { CHAR_DATA *vch, *victim = NULL; int now = 0, highest = 0; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "get_random_char received multiple prog types",0); return NULL; } if ( mob ) vch = mob->in_room->people; else if ( obj ) { if ( obj->in_room ) vch = obj->in_room->people; else vch = obj->carried_by->in_room->people; } else vch = room->people; for( ; vch; vch = vch->next_in_room ) { if (vch->invis_level > 1 || vch->incog_level > 1) continue; if ( mob && (mob == vch || !can_see( mob, vch )) ) continue; if (!IS_NPC( vch ) ) continue; if (( now = number_percent() ) > highest ) { victim = vch; highest = now; } else if ( (now = number_percent()) > highest ) { victim = vch; highest = now; } } return victim; } /* * How many other players / mobs are there in the room * iFlag: 0: all, 1: players, 2: mobiles 3: mobs w/ same vnum 4: same group */ int count_people_room( CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room, int iFlag ) { CHAR_DATA *vch; int count; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "count_people_room received multiple prog types",0); return 0; } if ( mob ) vch = mob->in_room->people; else if ( obj ) { if ( obj->in_room ) vch = obj->in_room->people; else vch = obj->carried_by->in_room->people; } else vch = room->people; for ( count = 0; vch; vch = vch->next_in_room ) { if (vch->invis_level > 1 || vch->incog_level > 1) continue; if ( mob ) { if ( mob != vch && (iFlag == 0 || (iFlag == 1 && !IS_NPC( vch )) || (iFlag == 2 && IS_NPC( vch )) || (iFlag == 3 && IS_NPC( mob ) && IS_NPC( vch ) && mob->pIndexData->vnum == vch->pIndexData->vnum ) || (iFlag == 4 && is_same_group( mob, vch )) ) ) // && can_see( mob, vch ) ) count++; } else if ( obj || room ) { if ( iFlag == 0 || (iFlag == 1 && !IS_NPC( vch )) || (iFlag == 2 && IS_NPC( vch ))) count++; } } return ( count ); } /* * Get the order of a mob in the room. Useful when several mobs in * a room have the same trigger and you want only the first of them * to act */ int get_order( CHAR_DATA *ch, OBJ_DATA *obj ) { CHAR_DATA *vch; OBJ_DATA *vobj; int i; if ( ch && obj ) { bug( "get_order received multiple prog types",0); return 0; } if ( ch && !IS_NPC(ch) ) return 0; if ( ch ) { vch = ch->in_room->people; vobj = NULL; } else { vch = NULL; if ( obj->in_room ) vobj = obj->in_room->contents; else if ( obj->carried_by->in_room->contents ) vobj = obj->carried_by->in_room->contents; else vobj = NULL; } if ( ch ) for ( i = 0; vch; vch = vch->next_in_room ) { if ( vch == ch ) return i; if ( IS_NPC(vch) && vch->pIndexData->vnum == ch->pIndexData->vnum ) i++; } else for ( i = 0; vobj; vobj = vobj->next_content ) { if ( vobj == obj ) return i; if ( vobj->pIndexData->vnum == obj->pIndexData->vnum ) i++; } return 0; } /* * Check if ch has a given item or item type * vnum: item vnum or -1 * item_type: item type or -1 * fWear: TRUE: item must be worn, FALSE: don't care */ bool has_item( CHAR_DATA *ch, sh_int vnum, sh_int item_type, bool fWear ) { OBJ_DATA *obj; for ( obj = ch->carrying; obj; obj = obj->next_content ) if ( ( vnum < 0 || obj->pIndexData->vnum == vnum ) && ( item_type < 0 || obj->pIndexData->item_type == item_type ) && ( !fWear || obj->wear_loc != WEAR_NONE ) ) return TRUE; return FALSE; } /* * Check if ch has a given item or item type of given amount syntax: <min number> <itemname/itemvnum> */ int count_item( OBJ_DATA* list, char* name, int vnum ){ OBJ_DATA* obj; int count = 0; if (list == NULL) return 0; for (obj = list; obj; obj = obj->next_content ){ if (obj->contains) count += count_item(obj->contains, name, vnum ); if ( (vnum > 0 && obj->pIndexData->vnum == vnum ) || is_name( name, obj->name) || !str_cmp(name, "*")) count++; } return count; } bool eval_exit_flag( ROOM_INDEX_DATA* room, char* direction, char* flag ){ EXIT_DATA* pe; int dir, val; if (room == NULL || IS_NULLSTR(direction) || IS_NULLSTR(flag)) return FALSE; else if ( (dir = dir_lookup(direction)) < 0) return FALSE; else if ( (pe = room->exit[dir]) == NULL) return FALSE; else if ( ( val = flag_value( exit_flags, flag ) ) == NO_FLAG ) return FALSE; else if (!IS_SET(pe->exit_info, val)) return FALSE; else return TRUE; } bool has_count_item( CHAR_DATA *ch, char* number, char* item){ int count = 0; int i = 0; int vnum = 0; count = atoi( number ); vnum = atoi( item ); i = count_item( ch->carrying, item, vnum ); return (i >= count ); } bool has_count_item_obj( OBJ_DATA *obj, char* number, char* item){ int count = 0; int i = 0; int vnum = 0; count = atoi( number ); vnum = atoi( item ); i = count_item( obj->contains, item, vnum ); return (i >= count ); } /* * Check if there's a mob with given vnum in the room */ bool get_mob_vnum_room( CHAR_DATA *ch, OBJ_DATA *obj, ROOM_INDEX_DATA *room, sh_int vnum ) { CHAR_DATA *mob; if ( (ch && obj) || (ch && room) || (obj && room) ) { bug( "get_mob_vnum_room received multiple prog types",0); return FALSE; } if ( ch ) mob = ch->in_room->people; else if ( obj ) { if ( obj->in_room ) mob = obj->in_room->people; else mob = obj->carried_by->in_room->people; } else mob = room->people; for ( ; mob; mob = mob->next_in_room ) if ( IS_NPC( mob ) && mob->pIndexData->vnum == vnum ) return TRUE; return FALSE; } /* * Check if there's an object with given vnum in the room */ bool get_obj_vnum_room( CHAR_DATA *ch, OBJ_DATA *obj, ROOM_INDEX_DATA *room, sh_int vnum ) { OBJ_DATA *vobj; if ( (ch && obj) || (ch && room) || (obj && room) ) { bug( "get_obj_vnum_room received multiple prog types",0); return FALSE; } if ( ch ) vobj = ch->in_room->contents; else if ( obj ) { if ( obj->in_room ) vobj = obj->in_room->contents; else vobj = obj->carried_by->in_room->contents; } else vobj = room->contents; for ( ; vobj; vobj = vobj->next_content ) if ( vobj->pIndexData->vnum == vnum ) return TRUE; return FALSE; } /* --------------------------------------------------------------------- * CMD_EVAL * This monster evaluates an if/or/and statement * There are five kinds of statement: * 1) keyword and value (no $-code) if random 30 * 2) keyword, comparison and value if people > 2 * 3) keyword and actor if isnpc $n * 4) keyword, actor and value if carries $n sword * 5) keyword, actor, comparison and value if level $n >= 10 * *---------------------------------------------------------------------- */ int cmd_eval_mob( sh_int vnum, char *line, int check, CHAR_DATA *mob, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ) { CHAR_DATA *lval_char = mob; CHAR_DATA *vch = (CHAR_DATA *) arg2; OBJ_DATA *obj1 = (OBJ_DATA *) arg1; OBJ_DATA *obj2 = (OBJ_DATA *) arg2; OBJ_DATA *lval_obj = NULL; char *original, buf[MAX_INPUT_LENGTH], code; char data[MSL]; char quest[MSL]; int lval = 0, oper = 0; int rval = -2; original = line; line = one_argument( line, buf ); if ( buf[0] == '\0' || mob == NULL ) return FALSE; /* * If this mobile has no target, let's assume our victim is the one */ if ( mob->mprog_target == NULL ) mob->mprog_target = ch; switch ( check ) { /* * Case 1: keyword and value */ case CHK_RAND: return( atoi( buf ) >= number_percent() ); case CHK_EXIT: return (eval_exit_flag( mob->in_room, buf, line )); case CHK_MOBHERE: if ( is_number( buf ) ) return( get_mob_vnum_room( mob, NULL, NULL, atoi(buf) ) ); else return( (bool) (get_char_room( mob, NULL, buf) != NULL) ); case CHK_OBJHERE: if ( is_number( buf ) ) return( get_obj_vnum_room( mob, NULL, NULL, atoi(buf) ) ); else return( (bool) (get_obj_here( mob, NULL, buf) != NULL) ); case CHK_MOBEXISTS: return( (bool) (get_char_world( NULL, buf) != NULL) ); case CHK_OBJEXISTS: return( (bool) (get_obj_world( mob, buf) != NULL) ); /* * Case 2 begins here: We sneakily use rval to indicate need * for numeric eval... */ case CHK_PEOPLE: rval = count_people_room( mob, NULL, NULL, 0 ); break; case CHK_PLAYERS: rval = count_people_room( mob, NULL, NULL, 1 ); break; case CHK_MOBS: rval = count_people_room( mob, NULL, NULL, 2 ); break; case CHK_CLONES: rval = count_people_room( mob, NULL, NULL, 3 ); break; case CHK_ORDER: rval = get_order( mob, NULL ); break; case CHK_HOUR: rval = mud_data.time_info.hour; break; case CHK_GETDELAY: rval = mob->mprog_delay;break; case CHK_MOBCOUNT: rval = world_mobcount( buf ); line = one_argument( line, buf ); break; default:; } /* * Case 2 continued: evaluate expression */ if ( rval >= 0 ) { if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval_mob: prog %d syntax error(2) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); lval = rval; rval = atoi( buf ); return( num_eval( lval, oper, rval ) ); } /* * Case 3,4,5: Grab actors from $* codes */ if ( buf[0] != '$' || buf[1] == '\0' ) { sprintf( buf, "Cmd_eval_mob: prog %d syntax error(3) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } else code = buf[1]; switch( code ) { case 'i': lval_char = mob; break; case 'n': lval_char = ch; break; case 't': lval_char = vch; break; case 'r': lval_char = rch == NULL ? get_random_char( mob, NULL, NULL ) : rch ; break; case 'o': lval_obj = obj1; break; case 'p': lval_obj = obj2; break; case 'q': lval_char = mob->mprog_target; break; default: sprintf( buf, "Cmd_eval_mob: prog %d syntax error(4) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } /* * From now on, we need an actor, so if none was found, bail out */ if ( lval_char == NULL && lval_obj == NULL ) return FALSE; /* * Case 3: Keyword, comparison and value */ switch( check ) { case CHK_ISPC: return( lval_char != NULL && !IS_NPC( lval_char ) ); case CHK_ISNPC: return( lval_char != NULL && IS_NPC( lval_char ) ); case CHK_ISGOOD: return( lval_char != NULL && IS_GOOD( lval_char ) ); case CHK_ISEVIL: return( lval_char != NULL && IS_EVIL( lval_char ) ); case CHK_ISNEUTRAL: return( lval_char != NULL && IS_NEUTRAL( lval_char ) ); case CHK_ISELAWFUL: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("lawful", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISENEUTRAL: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("neutral", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISECHAOTIC: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("chaotic", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISIMMORT: return( lval_char != NULL && IS_IMMORTAL( lval_char ) ); case CHK_ISBLOODY: return (lval_char != NULL && is_fight_delay(lval_char,90)); case CHK_ISPOISONED: return (lval_char != NULL && check_poison(lval_char)); case CHK_ISCHARM: /* A relic from MERC 2.2 MOBprograms */ return( lval_char != NULL && IS_AFFECTED( lval_char, AFF_CHARM ) ); case CHK_ISFOLLOW: return( lval_char != NULL && lval_char->master != NULL && lval_char->master->in_room == lval_char->in_room ); case CHK_ISACTIVE: return( lval_char != NULL && lval_char->position > POS_SLEEPING ); case CHK_ISDELAY: if (lval_char!= NULL) return( lval_char->mprog_delay > 0 ); else if (lval_obj!= NULL) return( lval_obj->oprog_delay > 0 ); case CHK_HASPATH: if (lval_char!= NULL) return( lval_char->spec_path != NULL ); case CHK_ISVISIBLE: switch( code ) { default : case 'i': case 'n': case 't': case 'r': case 'q': return( lval_char != NULL && can_see( mob, lval_char ) ); case 'o': case 'p': return( lval_obj != NULL && can_see_obj( mob, lval_obj ) ); } case CHK_HASTARGET: return( lval_char != NULL && lval_char->mprog_target != NULL); // && lval_char->in_room == lval_char->mprog_target->in_room ); case CHK_ISTARGET: return( lval_char != NULL && mob->mprog_target == lval_char ); case CHK_ISHERE: if (lval_char) return (lval_char->in_room && lval_char->in_room == mob->in_room); else if (lval_obj) return (lval_obj->in_room && lval_obj->in_room == mob->in_room); break; case CHK_ISCOMBAT: return (lval_char && lval_char->fighting); default:; } /* * Case 4: Keyword, actor and value */ one_argument_2( line, quest ); line = one_argument( line, buf ); switch( check ) { AFFECT_DATA* paf; case CHK_AFFECTED: return( lval_char != NULL && IS_SET(lval_char->affected_by, flag_lookup(buf, affect_flags))); case CHK_AFFECTED2: return( lval_char != NULL && IS_SET(lval_char->affected2_by, flag_lookup(buf, affect2_flags))); case CHK_AFF_SPELL: if (lval_char != NULL) return( is_affected(lval_char, skill_lookup(buf)) ); else if (lval_obj != NULL) return( is_affected_obj(lval_obj, skill_lookup(buf)) ); case CHK_HASQUEST: if (lval_char != NULL){ int i = 0; expand_arg_mob(data, quest, mob, lval_char, NULL, NULL, rch); while (data[i] != '\0'){ data[i] = LOWER(data[i]); i++; } return( NULL == has_quest(lval_char, data) ? FALSE : TRUE ); } case CHK_ACT: return( lval_char != NULL && IS_SET(lval_char->act, flag_lookup(buf, act_flags)) ); case CHK_IMM: return( lval_char != NULL && IS_SET(lval_char->imm_flags, flag_lookup(buf, imm_flags)) ); case CHK_ISROYAL: return( lval_char != NULL && IS_ROYAL(lval_char)); case CHK_NOBLE: return( lval_char != NULL && IS_NOBLE(lval_char)); case CHK_OFF: return( lval_char != NULL && IS_SET(lval_char->off_flags, flag_lookup(buf, off_flags)) ); case CHK_CARRIES: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, FALSE ) ); else return( lval_char != NULL && (get_obj_carry( lval_char, buf, NULL) != NULL) ); case CHK_NCARRIES: return( lval_char != NULL && has_count_item(lval_char, buf, line)); case CHK_NCONTAINS: return( lval_obj != NULL && has_count_item_obj(lval_obj, buf, line)); case CHK_WEARS: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, TRUE ) ); else return( lval_char != NULL && (get_obj_wear( lval_char, buf, NULL) != NULL) ); case CHK_HAS: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), FALSE ) ); case CHK_USES: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), TRUE ) ); case CHK_SKILL: return( lval_char != NULL && get_skill( lval_char, skill_lookup(buf)) >= 1 ); case CHK_EQUIP: return( lval_char != NULL && get_eq_char( lval_char, flag_value( wear_loc_flags, buf ))); case CHK_CONTAINS: if ( lval_obj != NULL ) return (get_obj_list( NULL, line, lval_obj->contains) != NULL); case CHK_NAME: switch( code ) { default : case 'i': case 'n': case 't': case 'r': case 'q': return( lval_char != NULL && is_name( buf, lval_char->name ) ); case 'o': case 'p': return( lval_obj != NULL && is_name( buf, lval_obj->name ) ); } case CHK_HOMETOWN: return( lval_char != NULL && lval_char->hometown == hometown_lookup( buf ) ); case CHK_CLAN: return( lval_char != NULL && HAS_CLAN(lval_char) && GET_CLAN(lval_char) == GetClanHandle( buf )); case CHK_POS: return( lval_char != NULL && lval_char->position == position_lookup( buf ) ); case CHK_CABAL: return( lval_char != NULL && ( (buf[0] == '*' && lval_char->pCabal) || (_is_cabal(lval_char->pCabal, get_cabal( buf )))) ); case CHK_RELIGION: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp(buf, deity_table[lval_char->pcdata->way].way)); case CHK_CABALLY: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_FRIEND ); case CHK_CABENEMY: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_ENEMY ); case CHK_CABNEUT: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_NEUTRAL ); case CHK_DISGUISE: return( lval_char != NULL && disguise_check(lval_char, class_lookup( buf )) ); case CHK_RACE: return( lval_char != NULL && lval_char->race == race_lookup( buf ) ); case CHK_CLASS: if ( lval_char || (paf = affect_find(lval_char->affected, gen_guise)) == NULL) return( lval_char != NULL && lval_char->class == class_lookup( buf ) ); else return( lval_char != NULL && paf->modifier == class_lookup( buf )); case CHK_OBJTYPE: return( lval_obj != NULL && lval_obj->item_type == item_lookup( buf ) ); default:; } /* * Case 5: Keyword, actor, comparison and value */ if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval_mob: prog %d syntax error(5): '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); rval = atoi( buf ); switch( check ) { case CHK_VNUM: switch( code ) { default : case 'i': case 'n': case 't': case 'r': case 'q': if( lval_char != NULL && IS_NPC( lval_char ) ) lval = lval_char->pIndexData->vnum; break; case 'o': case 'p': if ( lval_obj != NULL ) lval = lval_obj->pIndexData->vnum; } break; case CHK_HPCNT: if ( lval_char != NULL ) lval = (lval_char->hit * 100)/(UMAX(1,lval_char->max_hit)); break; case CHK_PATH: if ( lval_char != NULL ) lval = get_path_vnum( lval_char) ; break; case CHK_ROOM: if ( lval_char != NULL && lval_char->in_room != NULL ) lval = lval_char->in_room->vnum; break; case CHK_SEX: if ( lval_char != NULL ) lval = lval_char->sex; break; case CHK_LEVEL: if ( lval_char != NULL ) lval = lval_char->level; break; case CHK_ALIGN: if ( lval_char != NULL ) lval = lval_char->alignment; break; case CHK_MONEY: if ( lval_char != NULL ) /* Viri: No silver */ lval = lval_char->gold; //+ (lval_char->silver * 100); break; case CHK_CP: if ( lval_char != NULL ) lval = GET_CP(lval_char); break; case CHK_OBJVAL0: if ( lval_obj != NULL ) lval = lval_obj->value[0]; break; case CHK_OBJVAL1: if ( lval_obj != NULL ) lval = lval_obj->value[1]; break; case CHK_OBJVAL2: if ( lval_obj != NULL ) lval = lval_obj->value[2]; break; case CHK_OBJVAL3: if ( lval_obj != NULL ) lval = lval_obj->value[3]; break; case CHK_OBJVAL4: if ( lval_obj != NULL ) lval = lval_obj->value[4]; break; case CHK_OBJCOST: if ( lval_obj != NULL ) lval = lval_obj->cost; break; case CHK_GRPSIZE: if( lval_char != NULL ) lval = count_people_room( lval_char, NULL, NULL, 4 ); break; case CHK_FOLLOWERS: if( lval_char != NULL ) lval = get_charmed_by( lval_char); break; case CHK_CRANK: if( lval_char != NULL && !IS_NPC(ch)) lval = lval_char->pcdata->clan_rank; break; default: return FALSE; } return( num_eval( lval, oper, rval ) ); } int cmd_eval_obj( sh_int vnum, char *line, int check, OBJ_DATA *obj, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ) { CHAR_DATA *lval_char = NULL; CHAR_DATA *vch = (CHAR_DATA *) arg2; OBJ_DATA *obj1 = (OBJ_DATA *) arg1; OBJ_DATA *obj2 = (OBJ_DATA *) arg2; OBJ_DATA *lval_obj = obj; char *original, buf[MAX_INPUT_LENGTH], code; int lval = 0, oper = 0, rval = -1; char data[MSL]; char quest[MSL]; original = line; line = one_argument( line, buf ); if ( buf[0] == '\0' || obj == NULL ) return FALSE; /* * If this object has no target, let's assume our victim is the one */ if ( obj->oprog_target == NULL ) obj->oprog_target = ch; switch ( check ) { /* * Case 1: keyword and value */ case CHK_RAND: return( atoi( buf ) >= number_percent() ); case CHK_EXIT: return (eval_exit_flag( in_obj(obj)->in_room, buf, line )); case CHK_MOBHERE: if ( is_number( buf ) ) return( get_mob_vnum_room( NULL, obj, NULL, atoi(buf) ) ); else return( (bool) (get_char_room( NULL, (obj->in_room?obj->in_room:obj->carried_by->in_room), buf) != NULL) ); case CHK_OBJHERE: if ( is_number( buf ) ) return( get_obj_vnum_room( NULL, obj, NULL, atoi(buf) ) ); else return( (bool) (get_obj_here( NULL, (obj->in_room?obj->in_room:obj->carried_by->in_room), buf) != NULL) ); case CHK_MOBEXISTS: return( (bool) (get_char_world( NULL, buf) != NULL) ); case CHK_OBJEXISTS: return( (bool) (get_obj_world( NULL, buf) != NULL) ); /* * Case 2 begins here: We sneakily use rval to indicate need * for numeric eval... */ case CHK_PEOPLE: rval = count_people_room( NULL, obj, NULL, 0 ); break; case CHK_PLAYERS: rval = count_people_room( NULL, obj, NULL, 1 ); break; case CHK_MOBS: rval = count_people_room( NULL, obj, NULL, 2 ); break; case CHK_CLONES: bug( "cmd_eval_obj: received CHK_CLONES.",0); break; case CHK_ORDER: rval = get_order( NULL, obj ); break; case CHK_HOUR: rval = mud_data.time_info.hour; break; case CHK_GETDELAY: rval = obj->oprog_delay; break; case CHK_MOBCOUNT: rval = world_mobcount( buf ); line = one_argument( line, buf ); break; default:; } /* * Case 2 continued: evaluate expression */ if ( rval >= 0 ) { if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval_obj: prog %d syntax error(2) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); lval = rval; rval = atoi( buf ); return( num_eval( lval, oper, rval ) ); } /* * Case 3,4,5: Grab actors from $* codes */ if ( buf[0] != '$' || buf[1] == '\0' ) { sprintf( buf, "Cmd_eval_obj: prog %d syntax error(3) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } else code = buf[1]; switch( code ) { case 'i': lval_obj = obj; break; case 'f': if (ch && ch->fighting) lval_char = ch->fighting; else lval_char = NULL; break; case 'n': lval_char = ch; break; case 't': lval_char = vch; break; case 'r': lval_char = rch == NULL ? get_random_char( NULL, obj, NULL ) : rch ; break; case 'o': lval_obj = obj1; break; case 'p': lval_obj = obj2; break; case 'q': lval_char = obj->oprog_target; break; default: sprintf( buf, "Cmd_eval_obj: prog %d syntax error(4) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } /* * From now on, we need an actor, so if none was found, bail out */ if ( lval_char == NULL && lval_obj == NULL ) return FALSE; /* * Case 3: Keyword, comparison and value */ switch( check ) { case CHK_ISPC: return( lval_char != NULL && !IS_NPC( lval_char ) ); case CHK_ISNPC: return( lval_char != NULL && IS_NPC( lval_char ) ); case CHK_ISGOOD: return( lval_char != NULL && IS_GOOD( lval_char ) ); case CHK_ISEVIL: return( lval_char != NULL && IS_EVIL( lval_char ) ); case CHK_ISNEUTRAL: return( lval_char != NULL && IS_NEUTRAL( lval_char ) ); case CHK_ISELAWFUL: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("lawful", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISENEUTRAL: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("neutral", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISECHAOTIC: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("chaotic", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISIMMORT: return( lval_char != NULL && IS_IMMORTAL( lval_char ) ); case CHK_ISBLOODY: return (lval_char != NULL && is_fight_delay(lval_char,90)); case CHK_ISPOISONED: return (lval_char != NULL && check_poison(lval_char)); case CHK_ISCHARM: /* A relic from MERC 2.2 MOBprograms */ return( lval_char != NULL && IS_AFFECTED( lval_char, AFF_CHARM ) ); case CHK_ISFOLLOW: return( lval_char != NULL && lval_char->master != NULL && lval_char->master->in_room == lval_char->in_room ); case CHK_ISACTIVE: return( lval_char != NULL && lval_char->position > POS_SLEEPING ); case CHK_ISDELAY: if (lval_char!= NULL) return( lval_char->mprog_delay > 0 ); else if (lval_obj!= NULL) return( lval_obj->oprog_delay > 0 ); case CHK_HASPATH: if (lval_char!= NULL) return( lval_char->spec_path != NULL ); case CHK_HASTARGET: return( lval_obj != NULL && lval_obj->oprog_target != NULL); // && lval_obj->in_room == lval_obj->oprog_target->in_room ); case CHK_ISTARGET: return( lval_char != NULL && obj->oprog_target == lval_char ); case CHK_ISHERE: if (lval_char) return (lval_char->in_room && lval_char->in_room == obj->in_room); else if (lval_obj) return (lval_obj->in_room && lval_obj->in_room == obj->in_room); break; case CHK_ISCOMBAT: return (lval_char && lval_char->fighting); case CHK_ISCARRIED: return( lval_obj != NULL && lval_obj->carried_by && lval_obj->wear_loc == WEAR_NONE); case CHK_ISWORN: return( lval_obj != NULL && lval_obj->carried_by && lval_obj->wear_loc != WEAR_NONE); case CHK_HAS: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), FALSE ) ); case CHK_USES: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), TRUE ) ); case CHK_SKILL: return( lval_char != NULL && get_skill( lval_char, skill_lookup(buf)) >= 1 ); case CHK_EQUIP: return( lval_char != NULL && get_eq_char( lval_char, flag_value( wear_loc_flags, line ))); case CHK_CONTAINS: if ( lval_obj != NULL ) return (get_obj_list( NULL, line, lval_obj->contains) != NULL); default:; } /* * Case 4: Keyword, actor and value */ one_argument( line, quest ); line = one_argument( line, buf ); switch( check ) { AFFECT_DATA* paf; case CHK_AFFECTED: return( lval_char != NULL && IS_SET(lval_char->affected_by, flag_lookup(buf, affect_flags)) ); case CHK_AFFECTED2: return( lval_char != NULL && IS_SET(lval_char->affected2_by, flag_lookup(buf, affect2_flags))); case CHK_AFF_SPELL: if (lval_char != NULL) return( is_affected(lval_char, skill_lookup(buf)) ); else if (lval_obj != NULL) return( is_affected_obj(lval_obj, skill_lookup(buf)) ); case CHK_HASQUEST: if (lval_char != NULL){ int i = 0; expand_arg_other(data, quest, obj, NULL, lval_char, NULL, NULL, rch); while (data[i] != '\0'){ data[i] = LOWER(data[i]); i++; } return( NULL == has_quest(lval_char, data) ? FALSE : TRUE ); } case CHK_ACT: return( lval_char != NULL && IS_SET(lval_char->act, flag_lookup(buf, act_flags)) ); case CHK_IMM: return( lval_char != NULL && IS_SET(lval_char->imm_flags, flag_lookup(buf, imm_flags)) ); case CHK_ISROYAL: return( lval_char != NULL && IS_ROYAL(lval_char)); case CHK_NOBLE: return( lval_char != NULL && IS_NOBLE(lval_char)); case CHK_OFF: return( lval_char != NULL && IS_SET(lval_char->off_flags, flag_lookup(buf, off_flags)) ); case CHK_CARRIES: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, FALSE ) ); else return( lval_char != NULL && (get_obj_carry( lval_char, buf, NULL) != NULL) ); case CHK_NCARRIES: return( lval_char != NULL && has_count_item(lval_char, buf, line)); break; case CHK_NCONTAINS: return( lval_obj != NULL && has_count_item_obj(lval_obj, buf, line)); break; case CHK_WEARS: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, TRUE ) ); else return( lval_char != NULL && (get_obj_wear( lval_char, buf, NULL) != NULL) ); case CHK_HAS: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), FALSE ) ); case CHK_USES: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), TRUE ) ); case CHK_SKILL: return( lval_char != NULL && get_skill( lval_char, skill_lookup(buf)) >= 1 ); case CHK_EQUIP: return( lval_char != NULL && get_eq_char( lval_char, flag_value( wear_loc_flags, line))); case CHK_CONTAINS: if ( lval_obj != NULL ) return (get_obj_list( NULL, line, lval_obj->contains) != NULL); case CHK_NAME: switch( code ) { default : case 'n': case 't': case 'r': case 'q': return( lval_char != NULL && is_name( buf, lval_char->name ) ); case 'i': case 'o': case 'p': return( lval_obj != NULL && is_name( buf, lval_obj->name ) ); } case CHK_HOMETOWN: return( lval_char != NULL && lval_char->hometown == hometown_lookup( buf ) ); case CHK_CLAN: return( lval_char != NULL && HAS_CLAN(lval_char) && GET_CLAN(lval_char) == GetClanHandle( buf )); case CHK_POS: return( lval_char != NULL && lval_char->position == position_lookup( buf ) ); case CHK_CABAL: return( lval_char != NULL && ( (buf[0] == '*' && lval_char->pCabal) || (_is_cabal(lval_char->pCabal, get_cabal( buf )))) ); case CHK_RELIGION: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp(buf, deity_table[lval_char->pcdata->way].way)); case CHK_CABALLY: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_FRIEND ); case CHK_CABENEMY: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_ENEMY ); case CHK_CABNEUT: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_NEUTRAL ); case CHK_DISGUISE: return( lval_char != NULL && disguise_check(lval_char, class_lookup( buf )) ); case CHK_RACE: return( lval_char != NULL && lval_char->race == race_lookup( buf ) ); case CHK_CLASS: if ( lval_char || (paf = affect_find(lval_char->affected, gen_guise)) == NULL) return( lval_char != NULL && lval_char->class == class_lookup( buf ) ); else return( lval_char != NULL && paf->modifier == class_lookup( buf )); case CHK_OBJTYPE: return( lval_obj != NULL && lval_obj->item_type == item_lookup( buf ) ); default:; } /* * Case 5: Keyword, actor, comparison and value */ if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval_obj: prog %d syntax error(5): '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); rval = atoi( buf ); switch( check ) { case CHK_VNUM: switch( code ) { default : case 'n': case 't': case 'r': case 'q': if( lval_char != NULL && IS_NPC( lval_char ) ) lval = lval_char->pIndexData->vnum; break; case 'i': case 'o': case 'p': if ( lval_obj != NULL ) lval = lval_obj->pIndexData->vnum; } break; case CHK_HPCNT: if ( lval_char != NULL ) lval = (lval_char->hit * 100)/(UMAX(1,lval_char->max_hit)); break; case CHK_PATH: if ( lval_char != NULL ) lval = get_path_vnum( lval_char) ; break; case CHK_ROOM: if ( lval_char != NULL && lval_char->in_room != NULL ) lval = lval_char->in_room->vnum; else if ( lval_obj != NULL && (lval_obj->in_room != NULL || lval_obj->carried_by != NULL )) lval = lval_obj->in_room?lval_obj->in_room->vnum:lval_obj->carried_by->in_room->vnum; break; case CHK_SEX: if ( lval_char != NULL ) lval = lval_char->sex; break; case CHK_LEVEL: if ( lval_char != NULL ) lval = lval_char->level; break; case CHK_ALIGN: if ( lval_char != NULL ) lval = lval_char->alignment; break; case CHK_MONEY: /* Money is converted to silver... */ if ( lval_char != NULL ) lval = lval_char->gold;//Viri: no slilver + (lval_char->silver * 100); break; case CHK_CP: if ( lval_char != NULL ) lval = GET_CP(lval_char); break; case CHK_OBJVAL0: if ( lval_obj != NULL ) lval = lval_obj->value[0]; break; case CHK_OBJVAL1: if ( lval_obj != NULL ) lval = lval_obj->value[1]; break; case CHK_OBJVAL2: if ( lval_obj != NULL ) lval = lval_obj->value[2]; break; case CHK_OBJVAL3: if ( lval_obj != NULL ) lval = lval_obj->value[3]; break; case CHK_OBJVAL4: if ( lval_obj != NULL ) lval = lval_obj->value[4]; break; case CHK_OBJCOST: if ( lval_obj != NULL ) lval = lval_obj->cost; break; case CHK_GRPSIZE: if( lval_char != NULL ) lval = count_people_room( lval_char, NULL, NULL, 4 ); break; case CHK_FOLLOWERS: if( lval_char != NULL ) lval = get_charmed_by( lval_char); break; case CHK_CRANK: if( lval_char != NULL && !IS_NPC(ch)) lval = lval_char->pcdata->clan_rank; break; default: return FALSE; } return( num_eval( lval, oper, rval ) ); } int cmd_eval_room( sh_int vnum, char *line, int check, ROOM_INDEX_DATA *room, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ) { CHAR_DATA *lval_char = NULL; CHAR_DATA *vch = (CHAR_DATA *) arg2; OBJ_DATA *obj1 = (OBJ_DATA *) arg1; OBJ_DATA *obj2 = (OBJ_DATA *) arg2; OBJ_DATA *lval_obj = NULL; char *original, buf[MAX_INPUT_LENGTH], code; char data[MSL]; char quest[MSL]; int lval = 0, oper = 0, rval = -1; original = line; line = one_argument( line, buf ); if ( buf[0] == '\0' || room == NULL ) return FALSE; /* * If this room has no target, let's assume our victim is the one */ if ( room->rprog_target == NULL ) room->rprog_target = ch; switch ( check ) { /* * Case 1: keyword and value */ case CHK_RAND: return( atoi( buf ) >= number_percent() ); case CHK_EXIT: return (eval_exit_flag(room, buf, line )); case CHK_MOBHERE: if ( is_number( buf ) ) return( get_mob_vnum_room( NULL, NULL, room, atoi(buf) ) ); else return( (bool) (get_char_room( NULL, room, buf) != NULL) ); case CHK_OBJHERE: if ( is_number( buf ) ) return( get_obj_vnum_room( NULL, NULL, room, atoi(buf) ) ); else return( (bool) (get_obj_here( NULL, room, buf) != NULL) ); case CHK_MOBEXISTS: return( (bool) (get_char_world( NULL, buf) != NULL) ); case CHK_OBJEXISTS: return( (bool) (get_obj_world( NULL, buf) != NULL) ); /* * Case 2 begins here: We sneakily use rval to indicate need * for numeric eval... */ case CHK_PEOPLE: rval = count_people_room( NULL, NULL, room, 0 ); break; case CHK_PLAYERS: rval = count_people_room( NULL, NULL, room, 1 ); break; case CHK_MOBS: rval = count_people_room( NULL, NULL, room, 2 ); break; case CHK_CLONES: bug( "Cmd_eval_room: received CHK_CLONES.",0); break; case CHK_ORDER: bug( "Cmd_eval_room: received CHK_ORDER.",0); break; case CHK_HOUR: rval = mud_data.time_info.hour; break; case CHK_GETDELAY: rval = room->rprog_delay;break; case CHK_MOBCOUNT: rval = world_mobcount( buf ); line = one_argument( line, buf ); break; default:; } /* * Case 2 continued: evaluate expression */ if ( rval >= 0 ) { if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval_room: prog %d syntax error(2) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); lval = rval; rval = atoi( buf ); return( num_eval( lval, oper, rval ) ); } /* * Case 3,4,5: Grab actors from $* codes */ if ( buf[0] != '$' || buf[1] == '\0' ) { sprintf( buf, "Cmd_eval_room: prog %d syntax error(3) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } else code = buf[1]; switch( code ) { case 'i': bug( "Cmd_eval_room: received code case 'i'.",0); break; case 'n': lval_char = ch; break; case 't': lval_char = vch; break; case 'r': lval_char = rch == NULL ? get_random_char( NULL, NULL, room ) : rch ; break; case 'o': lval_obj = obj1; break; case 'p': lval_obj = obj2; break; case 'q': lval_char = room->rprog_target; break; default: sprintf( buf, "Cmd_eval_room: prog %d syntax error(4) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } /* * From now on, we need an actor, so if none was found, bail out */ if ( lval_char == NULL && lval_obj == NULL ) return FALSE; /* * Case 3: Keyword, comparison and value */ switch( check ) { case CHK_ISPC: return( lval_char != NULL && !IS_NPC( lval_char ) ); case CHK_ISNPC: return( lval_char != NULL && IS_NPC( lval_char ) ); case CHK_ISGOOD: return( lval_char != NULL && IS_GOOD( lval_char ) ); case CHK_ISEVIL: return( lval_char != NULL && IS_EVIL( lval_char ) ); case CHK_ISNEUTRAL: return( lval_char != NULL && IS_NEUTRAL( lval_char ) ); case CHK_ISELAWFUL: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("lawful", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISENEUTRAL: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("neutral", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISECHAOTIC: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp("chaotic", ethos_table[lval_char->pcdata->ethos].name)); case CHK_ISIMMORT: return( lval_char != NULL && IS_IMMORTAL( lval_char ) ); case CHK_ISBLOODY: return (lval_char != NULL && is_fight_delay(lval_char,90)); case CHK_ISPOISONED: return (lval_char != NULL && check_poison(lval_char)); case CHK_ISCHARM: /* A relic from MERC 2.2 MOBprograms */ return( lval_char != NULL && IS_AFFECTED( lval_char, AFF_CHARM ) ); case CHK_ISFOLLOW: return( lval_char != NULL && lval_char->master != NULL && lval_char->master->in_room == lval_char->in_room ); case CHK_ISACTIVE: return( lval_char != NULL && lval_char->position > POS_SLEEPING ); case CHK_ISDELAY: return( lval_char != NULL && lval_char->mprog_delay > 0 ); case CHK_HASPATH: if (lval_char!= NULL) return( lval_char->spec_path != NULL ); case CHK_HASTARGET: return( room->rprog_target != NULL ); // && lval_char->in_room == lval_char->mprog_target->in_room ); case CHK_ISTARGET: return( lval_char != NULL && room->rprog_target == lval_char ); case CHK_ISHERE: if (lval_char) return (lval_char->in_room && lval_char->in_room == room); else if (lval_obj) return (lval_obj->in_room && lval_obj->in_room == room); break; case CHK_ISCOMBAT: return (lval_char && lval_char->fighting); default:; } /* * Case 4: Keyword, actor and value */ one_argument( line, quest ); line = one_argument( line, buf ); switch( check ) { AFFECT_DATA* paf; case CHK_AFFECTED: return( lval_char != NULL && IS_SET(lval_char->affected_by, flag_lookup(buf, affect_flags)) ); case CHK_AFFECTED2: return( lval_char != NULL && IS_SET(lval_char->affected2_by, flag_lookup(buf, affect2_flags))); case CHK_AFF_SPELL: if (lval_char != NULL) return( is_affected(lval_char, skill_lookup(buf)) ); else if (lval_obj != NULL) return( is_affected_obj(lval_obj, skill_lookup(buf)) ); case CHK_HASQUEST: if (lval_char != NULL){ int i = 0; expand_arg_other(data, quest, NULL, room, lval_char, NULL, NULL, rch); while (data[i] != '\0'){ data[i] = LOWER(data[i]); i++; } return( NULL == has_quest(lval_char, data) ? FALSE : TRUE ); } case CHK_ACT: return( lval_char != NULL && IS_SET(lval_char->act, flag_lookup(buf, act_flags)) ); case CHK_IMM: return( lval_char != NULL && IS_SET(lval_char->imm_flags, flag_lookup(buf, imm_flags)) ); case CHK_ISROYAL: return( lval_char != NULL && IS_ROYAL(lval_char)); case CHK_NOBLE: return( lval_char != NULL && IS_NOBLE(lval_char)); case CHK_OFF: return( lval_char != NULL && IS_SET(lval_char->off_flags, flag_lookup(buf, off_flags)) ); case CHK_CARRIES: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, FALSE ) ); else return( lval_char != NULL && (get_obj_carry( lval_char, buf, NULL) != NULL) ); case CHK_WEARS: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, TRUE ) ); else return( lval_char != NULL && (get_obj_wear( lval_char, buf, NULL ) != NULL) ); case CHK_NCARRIES: return( lval_char != NULL && has_count_item(lval_char, buf, line)); break; case CHK_NCONTAINS: return( lval_obj != NULL && has_count_item_obj(lval_obj, buf, line)); break; case CHK_HAS: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), FALSE ) ); case CHK_USES: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), TRUE ) ); case CHK_NAME: switch( code ) { default : case 'n': case 't': case 'r': case 'q': return( lval_char != NULL && is_name( buf, lval_char->name ) ); case 'i': return FALSE; case 'o': case 'p': return( lval_obj != NULL && is_name( buf, lval_obj->name ) ); } case CHK_HOMETOWN: return( lval_char != NULL && lval_char->hometown == hometown_lookup( buf ) ); case CHK_CLAN: return( lval_char != NULL && HAS_CLAN(lval_char) && GET_CLAN(lval_char) == GetClanHandle( buf )); case CHK_POS: return( lval_char != NULL && lval_char->position == position_lookup( buf ) ); case CHK_CABAL: return( lval_char != NULL && ( (buf[0] == '*' && lval_char->pCabal) || (_is_cabal(lval_char->pCabal, get_cabal( buf )))) ); case CHK_RELIGION: return( lval_char != NULL && !IS_NPC(lval_char) && !str_cmp(buf, deity_table[lval_char->pcdata->way].way)); case CHK_CABALLY: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_FRIEND ); case CHK_CABENEMY: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_ENEMY ); case CHK_CABNEUT: return( lval_char != NULL && is_friendly(lval_char->pCabal, get_cabal( buf )) == CABAL_NEUTRAL ); case CHK_DISGUISE: return( lval_char != NULL && disguise_check(lval_char, class_lookup( buf )) ); case CHK_RACE: return( lval_char != NULL && lval_char->race == race_lookup( buf ) ); case CHK_CLASS: if ( lval_char || (paf = affect_find(lval_char->affected, gen_guise)) == NULL) return( lval_char != NULL && lval_char->class == class_lookup( buf ) ); else return( lval_char != NULL && paf->modifier == class_lookup( buf )); case CHK_OBJTYPE: return( lval_obj != NULL && lval_obj->item_type == item_lookup( buf ) ); default:; } /* * Case 5: Keyword, actor, comparison and value */ if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval_room: prog %d syntax error(5): '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); rval = atoi( buf ); switch( check ) { case CHK_VNUM: switch( code ) { default : case 'n': case 't': case 'r': case 'q': if( lval_char != NULL && IS_NPC( lval_char ) ) lval = lval_char->pIndexData->vnum; break; case 'i': return FALSE; case 'o': case 'p': if ( lval_obj != NULL ) lval = lval_obj->pIndexData->vnum; } break; case CHK_HPCNT: if ( lval_char != NULL ) lval = (lval_char->hit * 100)/(UMAX(1,lval_char->max_hit)); break; case CHK_PATH: if ( lval_char != NULL ) lval = get_path_vnum( lval_char) ; break; case CHK_ROOM: if ( lval_char != NULL && lval_char->in_room != NULL ) lval = lval_char->in_room->vnum; else if ( lval_obj != NULL && (lval_obj->in_room != NULL || lval_obj->carried_by != NULL ) ) lval = lval_obj->in_room?lval_obj->in_room->vnum:lval_obj->carried_by->in_room->vnum; break; case CHK_SEX: if ( lval_char != NULL ) lval = lval_char->sex; break; case CHK_LEVEL: if ( lval_char != NULL ) lval = lval_char->level; break; case CHK_ALIGN: if ( lval_char != NULL ) lval = lval_char->alignment; break; case CHK_MONEY: /* Money is converted to silver... */ if ( lval_char != NULL ) lval = lval_char->gold;//Viri: No silver + (lval_char->silver * 100); break; case CHK_CP: if ( lval_char != NULL ) lval = GET_CP(lval_char); break; case CHK_OBJVAL0: if ( lval_obj != NULL ) lval = lval_obj->value[0]; break; case CHK_OBJVAL1: if ( lval_obj != NULL ) lval = lval_obj->value[1]; break; case CHK_OBJVAL2: if ( lval_obj != NULL ) lval = lval_obj->value[2]; break; case CHK_OBJVAL3: if ( lval_obj != NULL ) lval = lval_obj->value[3]; break; case CHK_OBJVAL4: if ( lval_obj != NULL ) lval = lval_obj->value[4]; break; case CHK_OBJCOST: if ( lval_obj != NULL ) lval = lval_obj->cost; break; case CHK_GRPSIZE: if( lval_char != NULL ) lval = count_people_room( lval_char, NULL, NULL, 4 ); break; case CHK_FOLLOWERS: if( lval_char != NULL ) lval = get_charmed_by( lval_char); break; case CHK_CRANK: if( lval_char != NULL && !IS_NPC(ch)) lval = lval_char->pcdata->clan_rank; break; default: return FALSE; } return( num_eval( lval, oper, rval ) ); } /* * ------------------------------------------------------------------------ * EXPAND_ARG * These are hacks of act() in comm.c. I've added some safety guards, * so that missing or invalid $-codes do not crash the server * ------------------------------------------------------------------------ */ void expand_arg_mob( char *buf, const char *format, CHAR_DATA *mob, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ) { static char * const he_she [] = { "it", "he", "she" }; static char * const him_her [] = { "it", "him", "her" }; static char * const his_her [] = { "its", "his", "her" }; const char *someone = "someone"; const char *something = "something"; const char *someones = "someone's"; char fname[MAX_INPUT_LENGTH]; CHAR_DATA *vch = (CHAR_DATA *) arg2; OBJ_DATA *obj1 = (OBJ_DATA *) arg1; OBJ_DATA *obj2 = (OBJ_DATA *) arg2; const char *str; const char *i; char *point; /* * Discard null and zero-length messages. */ if ( format == NULL || format[0] == '\0' ) return; point = buf; str = format; while ( *str != '\0' ) { if ( *str != '$' ) { *point++ = *str++; continue; } ++str; switch ( *str ) { default: bug( "Expand_arg_mob: bad code %d.", *str ); i = " <@@@> "; break; case 'a': if ( rch == NULL ) rch = get_random_mob( mob, NULL, NULL ); i = someone; if( rch != NULL)// && can_see( mob, rch ) ) { one_argument( rch->name, fname ); i = capitalize(fname); } break; case 'A': if ( rch == NULL ) rch = get_random_mob( mob, NULL, NULL ); i = ( rch != NULL && can_see( mob, rch ) ) ? ( IS_NPC( rch ) ? rch->short_descr : rch->name ) :someone; break; case 'i': one_argument( mob->name, fname ); i = fname; break; case 'I': i = mob->short_descr; break; case 'f': i = someone; if ( ch != NULL && ch->fighting != NULL) { one_argument( ch->fighting->name, fname ); i = capitalize(fname); } break; case 'F': i = (ch != NULL && ch->fighting != NULL) ? ( IS_NPC( ch->fighting ) ? ch->fighting->short_descr : ch->fighting->name ) : someone; break; case 'n': i = someone; if ( ch != NULL)// && can_see( mob, ch ) ) { one_argument( ch->name, fname ); i = capitalize(fname); } break; case 'N': i = (ch != NULL)// && can_see( mob, ch ) ) ? ( IS_NPC( ch ) ? ch->short_descr : ch->name ) : someone; break; case 't': i = someone; if ( vch != NULL)// && can_see( mob, vch ) ) { one_argument( vch->name, fname ); i = capitalize(fname); } break; case 'T': i = (vch != NULL && can_see( mob, vch )) ? ( IS_NPC( vch ) ? vch->short_descr : vch->name ) : someone; break; case 'r': if ( rch == NULL ) rch = get_random_char( mob, NULL, NULL ); i = someone; if( rch != NULL)// && can_see( mob, rch ) ) { one_argument( rch->name, fname ); i = capitalize(fname); } break; case 'R': if ( rch == NULL ) rch = get_random_char( mob, NULL, NULL ); i = ( rch != NULL && can_see( mob, rch ) ) ? ( IS_NPC( rch ) ? rch->short_descr : rch->name ) :someone; break; case 'q': i = someone; if ( mob->mprog_target != NULL)// && can_see( mob, mob->mprog_target ) ) { one_argument( mob->mprog_target->name, fname ); i = capitalize( fname ); } break; case 'Q': i = (mob->mprog_target != NULL && can_see( mob, mob->mprog_target )) ? ( IS_NPC( mob->mprog_target ) ? mob->mprog_target->short_descr : mob->mprog_target->name ) : someone; break; case 'v': i = someone; if ( ch != NULL && IS_NPC(ch)) { sprintf(fname, "%d", ch->pIndexData->vnum); i = fname; } break; case 'V': i = someone; if ( mob != NULL && IS_NPC(mob)) { sprintf(fname, "%d", mob->pIndexData->vnum); i = fname; } break; case 'j': i = he_she [URANGE(0, mob->sex, 2)]; break; case 'e': i = (ch != NULL)// && can_see( mob, ch )) ? he_she [URANGE(0, ch->sex, 2)] : someone; break; case 'E': i = (vch != NULL)// && can_see( mob, vch )) ? he_she [URANGE(0, vch->sex, 2)] : someone; break; case 'J': i = (rch != NULL)// && can_see( mob, rch )) ? he_she [URANGE(0, rch->sex, 2)] : someone; break; case 'X': i = (mob->mprog_target != NULL)// && can_see( mob, mob->mprog_target)) ? he_she [URANGE(0, mob->mprog_target->sex, 2)] : someone; break; case 'k': i = him_her [URANGE(0, mob->sex, 2)]; break; case 'm': i = (ch != NULL)// && can_see( mob, ch )) ? him_her [URANGE(0, ch ->sex, 2)] : someone; break; case 'M': i = (vch != NULL)// && can_see( mob, vch )) ? him_her [URANGE(0, vch ->sex, 2)] : someone; break; case 'K': if ( rch == NULL ) rch = get_random_char( mob, NULL, NULL ); i = (rch != NULL)// && can_see( mob, rch )) ? him_her [URANGE(0, rch ->sex, 2)] : someone; break; case 'Y': i = (mob->mprog_target != NULL)// && can_see( mob, mob->mprog_target )) ? him_her [URANGE(0, mob->mprog_target->sex, 2)] : someone; break; case 'l': i = his_her [URANGE(0, mob ->sex, 2)]; break; case 's': i = (ch != NULL)// && can_see( mob, ch )) ? his_her [URANGE(0, ch ->sex, 2)] : someones; break; case 'S': i = (vch != NULL)// && can_see( mob, vch )) ? his_her [URANGE(0, vch ->sex, 2)] : someones; break; case 'L': if ( rch == NULL ) rch = get_random_char( mob, NULL, NULL ); i = ( rch != NULL)// && can_see( mob, rch ) ) ? his_her [URANGE(0, rch ->sex, 2)] : someones; break; case 'Z': i = (mob->mprog_target != NULL)// && can_see( mob, mob->mprog_target )) ? his_her [URANGE(0, mob->mprog_target->sex, 2)] : someones; break; case 'o': i = something; if ( obj1 != NULL)// && can_see_obj( mob, obj1 ) ) { one_argument( obj1->name, fname ); i = fname; } break; case 'O': i = (obj1 != NULL && can_see_obj( mob, obj1 )) ? obj1->short_descr : something; break; case 'p': i = something; if ( obj2 != NULL)// && can_see_obj( mob, obj2 ) ) { one_argument( obj2->name, fname ); i = fname; } break; case 'P': i = (obj2 != NULL && can_see_obj( mob, obj2 )) ? obj2->short_descr : something; break; } ++str; while ( ( *point = *i ) != '\0' ) ++point, ++i; } *point = '\0'; return; } void expand_arg_other( char *buf, const char *format, OBJ_DATA *obj, ROOM_INDEX_DATA *room, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ) { static char * const he_she [] = { "it", "he", "she" }; static char * const him_her [] = { "it", "him", "her" }; static char * const his_her [] = { "its", "his", "her" }; const char *someone = "someone"; const char *something = "something"; const char *someones = "someone's"; char fname[MAX_INPUT_LENGTH]; CHAR_DATA *vch = (CHAR_DATA *) arg2; OBJ_DATA *obj1 = (OBJ_DATA *) arg1; OBJ_DATA *obj2 = (OBJ_DATA *) arg2; const char *str; const char *i; char *point; if ( obj && room ) { bug( "expand_arg_other received a obj and a room",0); return; } /* * Discard null and zero-length messages. */ if ( format == NULL || format[0] == '\0' ) return; point = buf; str = format; while ( *str != '\0' ) { if ( *str != '$' ) { *point++ = *str++; continue; } ++str; switch ( *str ) { default: bug( "Expand_arg: bad code %d.", *str ); i = " <@@@> "; break; case 'i': if ( obj ) { one_argument( obj->name, fname ); i = fname; } else { bug( "Expand_arg_other: room had an \"i\" case.",0); i = " <@@@> "; } break; case 'I': if ( obj ) i = obj->short_descr; else { bug( "Expand_arg_other: room had an \"I\" case.",0); i = " <@@@> "; } break; case 'f': i = someone; if ( ch != NULL && ch->fighting != NULL) { one_argument( ch->fighting->name, fname ); i = capitalize(fname); } break; case 'F': i = (ch != NULL && ch->fighting != NULL) ? ( IS_NPC( ch->fighting ) ? ch->fighting->short_descr : ch->fighting->name ) : someone; break; case 'n': i = someone; if ( ch != NULL ) { one_argument( ch->name, fname ); i = capitalize(fname); } break; case 'N': i = (ch != NULL ) ? ( IS_NPC( ch ) ? ch->short_descr : ch->name ) : someone; break; case 't': i = someone; if ( vch != NULL ) { one_argument( vch->name, fname ); i = capitalize(fname); } break; case 'T': i = (vch != NULL ) ? ( IS_NPC( vch ) ? vch->short_descr : vch->name ) : someone; break; case 'r': if ( rch == NULL && obj ) rch = get_random_char( NULL, obj, NULL ); else if ( rch == NULL && room ) rch = get_random_char( NULL, NULL, room ); i = someone; if( rch != NULL ) { one_argument( rch->name, fname ); i = capitalize(fname); } break; case 'R': if ( rch == NULL && obj ) rch = get_random_char( NULL, obj, NULL ); else if ( rch == NULL && room ) rch = get_random_char( NULL, NULL, room ); i = ( rch != NULL ) ? ( IS_NPC( ch ) ? ch->short_descr : ch->name ) :someone; break; case 'q': i = someone; if ( obj && obj->oprog_target != NULL ) { one_argument( obj->oprog_target->name, fname ); i = capitalize( fname ); } else if ( room && room->rprog_target != NULL ) { one_argument( room->rprog_target->name, fname ); i = capitalize( fname ); } break; case 'Q': i = (obj && obj->oprog_target != NULL) ? ( IS_NPC( obj->oprog_target ) ? obj->oprog_target->short_descr : obj->oprog_target->name ) : (room && room->rprog_target != NULL) ? ( IS_NPC( room->rprog_target ) ? room->rprog_target->short_descr : room->rprog_target->name ) : someone; break; case 'j': bug( "Expand_arg_other: Obj/room received case 'j'",0); i = " <@@@> "; break; case 'e': i = (ch != NULL ) ? he_she [URANGE(0, ch->sex, 2)] : someone; break; case 'E': i = (vch != NULL ) ? he_she [URANGE(0, vch->sex, 2)] : someone; break; case 'J': i = (rch != NULL ) ? he_she [URANGE(0, rch->sex, 2)] : someone; break; case 'X': i = (obj && obj->oprog_target != NULL ) ? he_she [URANGE(0, obj->oprog_target->sex, 2)] : (room && room->rprog_target != NULL ) ? he_she [URANGE(0, room->rprog_target->sex, 2)] : someone; break; case 'k': bug( "Expand_arg_other: received case 'k'.",0); i = " <@@@> "; break; case 'm': i = (ch != NULL ) ? him_her [URANGE(0, ch->sex, 2)] : someone; break; case 'M': i = (vch != NULL ) ? him_her [URANGE(0, vch->sex, 2)] : someone; break; case 'K': if ( obj && rch == NULL ) rch = get_random_char( NULL, obj, NULL ); else if ( room && rch == NULL ) rch = get_random_char( NULL, NULL, room ); i = (rch != NULL) ? him_her [URANGE(0, rch ->sex, 2)] : someone; break; case 'Y': i = (obj && obj->oprog_target != NULL) ? him_her [URANGE(0, obj->oprog_target->sex, 2)] : (room && room->rprog_target != NULL) ? him_her [URANGE(0, room->rprog_target->sex, 2)] : someone; break; case 'l': bug( "Expand_arg_other: received case 'l'.",0); i = " <@@@> "; break; case 's': i = (ch != NULL ) ? his_her [URANGE(0, ch ->sex, 2)] : someones; break; case 'S': i = (vch != NULL ) ? his_her [URANGE(0, vch ->sex, 2)] : someones; break; case 'L': if ( obj && rch == NULL ) rch = get_random_char( NULL, obj, NULL ); else if ( room && rch == NULL ) rch = get_random_char( NULL, NULL, room ); i = ( rch != NULL ) ? his_her [URANGE(0, rch ->sex, 2)] : someones; break; case 'Z': i = (obj && obj->oprog_target != NULL) ? his_her [URANGE(0, obj->oprog_target->sex, 2)] : (room && room->rprog_target != NULL) ? his_her [URANGE(0, room->rprog_target->sex, 2)] : someones; break; case 'o': i = something; if ( obj1 != NULL ) { one_argument( obj1->name, fname ); i = fname; } break; case 'O': i = (obj1 != NULL) ? obj1->short_descr : something; break; case 'p': i = something; if ( obj2 != NULL ) { one_argument( obj2->name, fname ); i = fname; } break; case 'P': i = (obj2 != NULL) ? obj2->short_descr : something; break; } ++str; while ( ( *point = *i ) != '\0' ) ++point, ++i; } *point = '\0'; return; } /* * ------------------------------------------------------------------------ * PROGRAM_FLOW * This is the program driver. It parses the mob program code lines * and passes "executable" commands to interpret() * Lines beginning with 'mob' are passed to mob_interpret() to handle * special mob commands (in mob_cmds.c) *------------------------------------------------------------------------- */ #define MAX_NESTED_LEVEL 12 /* Maximum nested if-else-endif's (stack size) */ #define BEGIN_BLOCK 0 /* Flag: Begin of if-else-endif block */ #define IN_BLOCK -1 /* Flag: Executable statements */ #define END_BLOCK -2 /* Flag: End of if-else-endif block */ #define MAX_CALL_LEVEL 5 /* Maximum nested calls */ void program_flow( sh_int pvnum, /* For diagnostic purposes */ char *source, /* the actual MOBprog code */ CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room, CHAR_DATA *ch, const void *arg1, const void *arg2 ) { CHAR_DATA *rch = NULL; char *code, *line; char buf[MAX_STRING_LENGTH]; char control[MAX_INPUT_LENGTH], data[MAX_STRING_LENGTH]; char bugbuf[MAX_STRING_LENGTH]; static int call_level; /* Keep track of nested "mpcall"s */ int level, eval, check; int state[MAX_NESTED_LEVEL], /* Block state (BEGIN,IN,END) */ cond[MAX_NESTED_LEVEL]; /* Boolean value based on the last if-check */ sh_int mvnum = 0,ovnum = 0,rvnum = 0; /* safety check for charmed mobs */ if (mob && IS_AFFECTED(mob, AFF_CHARM) && !IS_SET(mob->act, ACT_PET)) return; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "PROGs: program_flow received multiple prog types.", 0 ); return; } if ( mob ){ mvnum = mob->pIndexData->vnum; if (!IS_SET(mob->act, ACT_UPDATE_ALWAYS) && ( mob->in_room == NULL || (mob->homevnum && mob->in_room->vnum != mob->homevnum )) ) return; } else if ( obj ) ovnum = obj->pIndexData->vnum; else if ( room ) rvnum = room->vnum; else { bug( "PROGs: program_flow did not receive a prog type.", 0 ); return; } if( ++call_level > MAX_CALL_LEVEL ) { if ( mob ) sprintf( bugbuf, "Progs: MAX_CALL_LEVEL exceeded, vnum %d, mprog vnum %d", mvnum, pvnum ); else if ( obj ) sprintf( bugbuf, "Progs: MAX_CALL_LEVEL exceeded, vnum %d oprog vnum %d.", ovnum, pvnum ); else sprintf( bugbuf, "Progs: MAX_CALL_LEVEL exceeded, vnum %d rprog vnum %d.", rvnum, pvnum ); bug( bugbuf, 0 ); call_level--; return; } /* * Reset "stack" */ for ( level = 0; level < MAX_NESTED_LEVEL; level++ ) { state[level] = IN_BLOCK; cond[level] = TRUE; } level = 0; code = source; /* * Parse the Prog code */ while ( *code ) { bool first_arg = TRUE; char *b = buf, *c = control, *d = data; /* * Get a command line. We sneakily get both the control word * (if/and/or) and the rest of the line in one pass. */ while( isspace( *code ) && *code ) code++; while ( *code ) { if ( *code == '\n' || *code == '\r' ) break; else if ( isspace(*code) ) { if ( first_arg ) first_arg = FALSE; else *d++ = *code; } else { if ( first_arg ) *c++ = *code; else *d++ = *code; } *b++ = *code++; } *b = *c = *d = '\0'; if ( buf[0] == '\0' ) break; if ( buf[0] == '*' ) /* Comment */ continue; line = data; /* * Match control words */ if ( !str_cmp( control, "if" ) ) { if ( state[level] == BEGIN_BLOCK ) { if ( mob ) sprintf( buf, "Mobprog: misplaced if statement, mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: misplaced if statement, obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: misplaced if statement, room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } state[level] = BEGIN_BLOCK; if ( ++level >= MAX_NESTED_LEVEL ) { if ( mob ) sprintf( buf, "Mobprog: Max nested level exceeded, mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: Max nested level exceeded, obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: Max nested level exceeded, room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) { cond[level] = FALSE; continue; } line = one_argument( line, control ); if ( mob && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { cond[level] = cmd_eval_mob( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else if ( obj && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { cond[level] = cmd_eval_obj( pvnum, line, check, obj, ch, arg1, arg2, rch ); } else if ( room && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { cond[level] = cmd_eval_room( pvnum, line, check, room, ch, arg1, arg2, rch ); } else { if ( mob ) sprintf( buf, "Mobprog: invalid if_check (if), mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: invalid if_check (if), obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: invalid if_check (if), room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } state[level] = END_BLOCK; } else if ( !str_cmp( control, "or" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { if ( mob ) sprintf( buf, "Mobprog: or without if, mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: or without if, obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: or without if, room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; line = one_argument( line, control ); if ( mob && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval_mob( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else if ( obj && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval_obj( pvnum, line, check, obj, ch, arg1, arg2, rch ); } else if ( room && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval_room( pvnum, line, check, room, ch, arg1, arg2, rch ); } else { if ( mob ) sprintf( buf, "Mobprog: invalid if_check (or), mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: invalid if_check (or), obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: invalid if_check (or), room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = (eval == TRUE) ? TRUE : cond[level]; } else if ( !str_cmp( control, "and" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { if ( mob ) sprintf( buf, "Mobprog: and without if, mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: and without if, obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: and without if, room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; line = one_argument( line, control ); if ( mob && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval_mob( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else if ( obj && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval_obj( pvnum, line, check, obj, ch, arg1, arg2, rch ); } else if ( room && ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval_room( pvnum, line, check, room, ch, arg1, arg2, rch ); } else { if ( mob ) sprintf( buf, "Mobprog: invalid if_check (and), mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: invalid if_check (and), obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: invalid if_check (and), room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = (cond[level] == TRUE) && (eval == TRUE) ? TRUE : FALSE; } else if ( !str_cmp( control, "endif" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { if ( mob ) sprintf( buf, "Mobprog: endif without if, mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: endif without if, obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: endif without if, room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); call_level--; return; } cond[level] = TRUE; state[level] = IN_BLOCK; state[--level] = END_BLOCK; } else if ( !str_cmp( control, "else" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { if ( mob ) sprintf( buf, "Mobprog: else without if, mob %d prog %d", mvnum, pvnum ); else if ( obj ) sprintf( buf, "Objprog: else without if, obj %d prog %d", ovnum, pvnum ); else sprintf( buf, "Roomprog: else without if, room %d prog %d", rvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; state[level] = IN_BLOCK; cond[level] = (cond[level] == TRUE) ? FALSE : TRUE; } else if ( cond[level] == TRUE && ( !str_cmp( control, "break" ) || !str_cmp( control, "end" ) ) ) { call_level--; return; } else if ( cond[level] == TRUE && ( !str_cmp( control, "return" ) ) ) { call_level = 0; return; } else if ( (!level || cond[level] == TRUE) && buf[0] != '\0' ) { state[level] = IN_BLOCK; if ( mob ) expand_arg_mob( data, buf, mob, ch, arg1, arg2, rch ); else if ( obj ) expand_arg_other( data, buf, obj, NULL, ch, arg1, arg2, rch ); else expand_arg_other( data, buf, NULL, room, ch, arg1, arg2, rch ); if ( !str_cmp( control, "mob" ) ) { /* * Found a mob restricted command, pass it to mob interpreter */ line = one_argument( data, control ); if ( !mob ) bug( "mob command in non MOBprog %d", pvnum); else{ mob->trust = 6969; mob_interpret( mob, line ); mob->trust = UMIN(60, mob->level); } } else if ( !str_cmp( control, "obj" ) ) { /* * Found an obj restricted command, pass it to obj interpreter */ line = one_argument( data, control ); if ( !obj ) bug( "obj command in non OBJprog %d", pvnum); else obj_interpret( obj, line ); } else if ( !str_cmp( control, "room" ) ) { /* * Found a room restricted command, pass it to room interpreter */ line = one_argument( data, control ); if ( !room ) bug( "room command in non ROOMprog %d", pvnum ); else room_interpret( room, line ); } else { /* * Found a normal mud command, pass it to interpreter */ if ( !mob ) bug( "Normal MUD command in non-MOBprog, prog vnum %d", pvnum ); else{ /* allow yells and skills */ REMOVE_BIT(mob->comm,COMM_NOCHANNELS); REMOVE_BIT(mob->comm,COMM_NOYELL); REMOVE_BIT(mob->comm,COMM_NOTELL); mob->trust = 6969; interpret( mob, data ); SET_BIT(mob->comm,COMM_NOCHANNELS); SET_BIT(mob->comm,COMM_NOYELL); SET_BIT(mob->comm,COMM_NOTELL); mob->trust = mob->level; } } } } call_level--; } /* * --------------------------------------------------------------------- * Trigger handlers. These are called from various parts of the code * when an event is triggered. * --------------------------------------------------------------------- */ /* * A general purpose string trigger. Matches argument to a string trigger * phrase. */ void p_act_trigger( char *argument, CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room, CHAR_DATA *ch, const void *arg1, const void *arg2, int type ) { PROG_LIST *prg; char buf[MIL], buf2[MIL]; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "Multiple program types in ACT trigger.", 0 ); return; } /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return; if ( mob ) { for ( prg = mob->pIndexData->mprogs; prg != NULL; prg = prg->next ) { sprintf(buf, "%s", capitalize(prg->trig_phrase)); buf[0] = LOWER(buf[0]); sprintf(buf2, "%s", capitalize(argument)); buf2[0] = LOWER(buf2[0]); if ( prg->trig_type == type && (strstr( buf2, buf ) != NULL || prg->trig_phrase[0] == '*') ) { program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, arg1, arg2 ); // break; } } } else if ( obj ) { for ( prg = obj->pIndexData->oprogs; prg != NULL; prg = prg->next ) { sprintf(buf, "%s", capitalize(prg->trig_phrase)); if ( prg->trig_type == type && (strstr( capitalize(argument), buf ) != NULL || prg->trig_phrase[0] == '*') ) { program_flow( prg->vnum, prg->code, NULL, obj, NULL, ch, arg1, arg2 ); // break; } } } else if ( room ) { for ( prg = room->rprogs; prg != NULL; prg = prg->next ) { sprintf(buf, "%s", capitalize(prg->trig_phrase)); if ( prg->trig_type == type && (strstr( capitalize(argument), buf ) != NULL || prg->trig_phrase[0] == '*') ){ program_flow( prg->vnum, prg->code, NULL, NULL, room, ch, arg1, arg2 ); // break; } } } else bug( "ACT trigger with no program type.", 0 ); return; } /* * A general purpose percentage trigger. Checks if a random percentage * number is less than trigger phrase */ bool p_percent_trigger( CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room, CHAR_DATA *ch, const void *arg1, const void *arg2, int type ) { PROG_LIST *prg; bool Ret = FALSE; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "Multiple program types in PERCENT trigger.", 0 ); return ( FALSE ); } /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return FALSE; if ( mob ) { for ( prg = mob->pIndexData->mprogs; prg != NULL; prg = prg->next ) { if ( prg->trig_type == type && number_percent() <= atoi( prg->trig_phrase ) ) { program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, arg1, arg2 ); Ret = TRUE; } } } else if ( obj ) { for ( prg = obj->pIndexData->oprogs; prg != NULL; prg = prg->next ) { if ( prg->trig_type == type && number_percent() <= atoi( prg->trig_phrase ) ) { program_flow( prg->vnum, prg->code, NULL, obj, NULL, ch, arg1, arg2 ); Ret = TRUE; } } } else if ( room ) { for ( prg = room->rprogs; prg != NULL; prg = prg->next ) { if ( prg->trig_type == type && number_percent() <= atoi( prg->trig_phrase ) ) { program_flow( prg->vnum, prg->code, NULL, NULL, room, ch, arg1, arg2 ); Ret = TRUE; } } } else bug( "PERCENT trigger missing program type.", 0 ); return ( Ret); } void p_bribe_trigger( CHAR_DATA *mob, CHAR_DATA *ch, int amount ) { const int MAX_BRIBE = 16; PROG_LIST *prg; int last = 0; int key[MAX_BRIBE]; int end_key[MAX_BRIBE]; PROG_LIST* bribes[MAX_BRIBE]; int i, j; /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return; /* we get a list of all the progs so we can sort them */ for ( prg = mob->pIndexData->mprogs; prg; prg = prg->next ){ if ( prg->trig_type == TRIG_BRIBE){ bribes[last] = prg; key[last++] = atoi( prg->trig_phrase ); if (last >= MAX_BRIBE){ last --; break; } } } /* reset end key */ for (i = 0; i < last; i++) end_key[i] = i; /* sort the list with good ole bubble sort */ for (i = 0; i < last; i ++){ for (j = 0; j < last - 1; j++){ if (key[j] < key[j + 1]){ int buf = key[j]; key[j] = key[j + 1]; key [j + 1] = buf; buf = end_key[j]; end_key[j] = end_key[j + 1]; end_key[j + 1] = buf; } } } /* check the list for the greatest matching bribe */ for(i = 0; i < last; i ++){ prg = bribes[end_key[i]]; if (atoi(prg->trig_phrase) <= amount){ if (amount) obj_to_ch(create_money(amount), mob); mob->gold -= amount; program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, NULL, NULL ); break; } } } bool p_exit_trigger( CHAR_DATA *ch, int dir, int type ) { CHAR_DATA *mob; OBJ_DATA *obj; ROOM_INDEX_DATA *room; PROG_LIST *prg; bool fRet = FALSE; /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return FALSE; if ( type == PRG_MPROG ) { for ( mob = ch->in_room->people; mob != NULL; mob = mob->next_in_room ) { if ( IS_NPC( mob ) && ( HAS_TRIGGER_MOB(mob, TRIG_EXIT) || HAS_TRIGGER_MOB(mob, TRIG_EXALL) ) ) { for ( prg = mob->pIndexData->mprogs; prg; prg = prg->next ) { /* * Exit trigger works only if the mobile is not busy * (fighting etc.). If you want to be sure all players * are caught, use ExAll trigger */ if ( (prg->trig_type == TRIG_EXIT || prg->trig_type == TRIG_EXALL) && dir == dir_lookup( prg->trig_phrase ) && mob->position == mob->pIndexData->default_pos && can_see( mob, ch ) ) { /* The AFF_FLAG can be set by a prog using "stop" command, that way we can selectivly block movement using prog command */ REMOVE_BIT(ch->affected_by, AFF_FLAG); program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, NULL, NULL ); if (IS_SET(ch->affected_by, AFF_FLAG)){ REMOVE_BIT(ch->affected_by, AFF_FLAG); fRet = TRUE; } } else if ( prg->trig_type == TRIG_EXALL && dir == dir_lookup( prg->trig_phrase ) ) { /* The AFF_FLAG can be set by a prog using "stop" command, that way we can selectivly block movement using prog command */ REMOVE_BIT(ch->affected_by, AFF_FLAG); program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, NULL, NULL ); if (IS_SET(ch->affected_by, AFF_FLAG)){ REMOVE_BIT(ch->affected_by, AFF_FLAG); fRet = TRUE; } } } } } } else if ( type == PRG_OPROG ) { for ( obj = ch->in_room->contents; obj != NULL; obj = obj->next_content ) { if ( HAS_TRIGGER_OBJ( obj, TRIG_EXALL ) ) { for ( prg = obj->pIndexData->oprogs; prg; prg = prg->next ) { if ( prg->trig_type == TRIG_EXALL && dir == dir_lookup( prg->trig_phrase ) ) { /* The AFF_FLAG can be set by a prog using "stop" command, that way we can selectivly block movement using prog command */ REMOVE_BIT(ch->affected_by, AFF_FLAG); program_flow( prg->vnum, prg->code, NULL, obj, NULL, ch, NULL, NULL ); if (IS_SET(ch->affected_by, AFF_FLAG)){ REMOVE_BIT(ch->affected_by, AFF_FLAG); fRet = TRUE; } } } } } for ( mob = ch->in_room->people; mob; mob = mob->next_in_room ) { for ( obj = mob->carrying; obj; obj = obj->next_content ) { if ( HAS_TRIGGER_OBJ( obj, TRIG_EXALL ) ) { for ( prg = obj->pIndexData->oprogs; prg; prg = prg->next ) { if ( prg->trig_type == TRIG_EXALL && dir == dir_lookup( prg->trig_phrase ) ) { /* The AFF_FLAG can be set by a prog using "stop" command, that way we can selectivly block movement using prog command */ REMOVE_BIT(ch->affected_by, AFF_FLAG); program_flow( prg->vnum, prg->code, NULL, obj, NULL, ch, NULL, NULL ); if (IS_SET(ch->affected_by, AFF_FLAG)){ REMOVE_BIT(ch->affected_by, AFF_FLAG); fRet = TRUE; } } } } } } } else if ( type == PRG_RPROG ) { room = ch->in_room; if ( HAS_TRIGGER_ROOM( room, TRIG_EXALL ) ) { for ( prg = room->rprogs; prg; prg = prg->next ) { if ( prg->trig_type == TRIG_EXALL && dir == dir_lookup( prg->trig_phrase ) ) { /* The AFF_FLAG can be set by a prog using "stop" command, that way we can selectivly block movement using prog command */ REMOVE_BIT(ch->affected_by, AFF_FLAG); program_flow( prg->vnum, prg->code, NULL, NULL, room, ch, NULL, NULL ); if (IS_SET(ch->affected_by, AFF_FLAG)){ REMOVE_BIT(ch->affected_by, AFF_FLAG); fRet = TRUE; } } } } } return fRet; } void p_give_trigger( CHAR_DATA *mob, OBJ_DATA *obj, ROOM_INDEX_DATA *room, CHAR_DATA *ch, OBJ_DATA *dropped, int type ) { char buf[MAX_INPUT_LENGTH], *p; PROG_LIST *prg; if ( (mob && obj) || (mob && room) || (obj && room) ) { bug( "Multiple program types in GIVE trigger.", 0 ); return; } /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return; if ( mob ){ for ( prg = mob->pIndexData->mprogs; prg; prg = prg->next ) if ( prg->trig_type == TRIG_GIVE ){ p = prg->trig_phrase; /* * Vnum argument */ if ( is_number( p ) ){ if ( dropped->pIndexData->vnum == atoi(p) ){ program_flow(prg->vnum, prg->code, mob, NULL, NULL, ch, (void *) dropped, NULL); return; } } /* * Dropped object name argument, e.g. 'sword' */ else{ while( *p ){ p = one_argument( p, buf ); if ( is_name( buf, dropped->name ) || !str_cmp( "all", buf ) ){ program_flow(prg->vnum, prg->code, mob, NULL, NULL, ch, (void *) dropped, NULL); return; } } } } } else if ( obj ){ for ( prg = obj->pIndexData->oprogs; prg; prg = prg->next ) if ( prg->trig_type == type ){ p = prg->trig_phrase; /* * Vnum argument */ if ( is_number( p ) ){ if ( dropped->pIndexData->vnum == atoi(p) ){ program_flow( prg->vnum, prg->code, NULL, obj, NULL, ch, (void *) dropped, NULL ); return; } } /* * Dropped object name argument, e.g. 'sword' */ else{ while( *p ){ p = one_argument( p, buf ); if ( is_name( buf, dropped->name ) || !str_cmp( "all", buf ) ){ program_flow( prg->vnum, prg->code, NULL, obj, NULL, ch, (void *) dropped, NULL ); return; } } } } } else if ( room ){ for ( prg = room->rprogs; prg; prg = prg->next ) if ( prg->trig_type == type ){ p = prg->trig_phrase; /* * Vnum argument */ if ( is_number( p ) ){ if ( dropped->pIndexData->vnum == atoi(p) ){ program_flow( prg->vnum, prg->code, NULL, NULL, room, ch, (void *) dropped, NULL ); return; } } /* * Dropped object name argument, e.g. 'sword' */ else{ while( *p ){ p = one_argument( p, buf ); if ( is_name( buf, dropped->name ) || !str_cmp( "all", buf ) ){ program_flow( prg->vnum, prg->code, NULL, NULL, room, ch, (void *) dropped, NULL ); return; } } } } } } void p_greet_trigger( CHAR_DATA *ch, int type ) { CHAR_DATA *mob, *mob_next; OBJ_DATA *obj; ROOM_INDEX_DATA *room; /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return; if ( type == PRG_MPROG ) { for ( mob = ch->in_room->people; mob != NULL; mob = mob_next) { mob_next = mob->next_in_room; if ( IS_NPC( mob ) && ( HAS_TRIGGER_MOB(mob, TRIG_GREET) || HAS_TRIGGER_MOB(mob,TRIG_GRALL) ) ) { /* * Greet trigger works only if the mobile is not busy * (fighting etc.). If you want to catch all players, use * GrAll trigger */ if ( HAS_TRIGGER_MOB( mob,TRIG_GREET ) && mob->position == mob->pIndexData->default_pos && can_see( mob, ch ) ) p_percent_trigger( mob, NULL, NULL, ch, NULL, NULL, TRIG_GREET ); if (mob == NULL || mob->in_room == NULL) continue; else if ( HAS_TRIGGER_MOB( mob, TRIG_GRALL ) ) p_percent_trigger( mob, NULL, NULL, ch, NULL, NULL, TRIG_GRALL ); } } } else if ( type == PRG_OPROG ) { for ( obj = ch->in_room->contents; obj != NULL; obj = obj->next_content ) { if ( HAS_TRIGGER_OBJ( obj, TRIG_GRALL ) ) { p_percent_trigger( NULL, obj, NULL, ch, NULL, NULL, TRIG_GRALL ); return; } } for ( mob = ch->in_room->people; mob; mob = mob->next_in_room ) { for ( obj = mob->carrying; obj; obj = obj->next_content ) { if ( HAS_TRIGGER_OBJ( obj, TRIG_GRALL ) ) { p_percent_trigger( NULL, obj, NULL, ch, NULL, NULL, TRIG_GRALL ); return; } } } } else if ( type == PRG_RPROG ) { room = ch->in_room; if ( HAS_TRIGGER_ROOM( room, TRIG_GRALL ) ) p_percent_trigger( NULL, NULL, room, ch, NULL, NULL, TRIG_GRALL ); } return; } void p_hprct_trigger( CHAR_DATA *mob, CHAR_DATA *ch ) { PROG_LIST *prg; /* invis imms should not trigger stuff */ if (ch && !IS_NPC(ch) && IS_IMMORTAL(ch) && (ch->incog_level > 1 || ch->invis_level > 1)) return; for ( prg = mob->pIndexData->mprogs; prg != NULL; prg = prg->next ) if ( ( prg->trig_type == TRIG_HPCNT ) && ( (100 * mob->hit / mob->max_hit) < atoi( prg->trig_phrase ) ) ) { program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, NULL, NULL ); break; } }