/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. 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 * *************************************************************************** * 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. * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" #include "tables.h" #include "prog_cmds.h" #include "recycle.h" #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_AFFECTED (24) #define CHK_ACT (25) #define CHK_OFF (26) #define CHK_IMM (27) #define CHK_CARRIES (28) #define CHK_WEARS (20) #define CHK_HAS (30) #define CHK_USES (31) #define CHK_NAME (32) #define CHK_POS (33) #define CHK_CLAN (34) #define CHK_RACE (35) #define CHK_CLASS (36) #define CHK_OBJTYPE (37) #define CHK_VNUM (38) #define CHK_HPCNT (39) #define CHK_ROOM (40) #define CHK_SEX (41) #define CHK_LEVEL (42) #define CHK_ALIGN (43) #define CHK_MONEY (44) #define CHK_OBJVAL0 (45) #define CHK_OBJVAL1 (46) #define CHK_OBJVAL2 (47) #define CHK_OBJVAL3 (48) #define CHK_OBJVAL4 (49) #define CHK_GRPSIZE (50) #define CHK_ONQUEST (52) #define CHK_HUNTER (55) #define CHK_PLR (57) #define CHK_SKILL (58) #define CHK_WEIGHT (60) #define EVAL_EQ 0 #define EVAL_GE 1 #define EVAL_LE 2 #define EVAL_GT 3 #define EVAL_LT 4 #define EVAL_NE 5 const char *fn_keyword[] = { "rand", "mobhere", "objhere", "mobexists", "objexists", "people", "players", "mobs", "clones", "order", "hour", "ispc", "isnpc", "isgood", "isevil", "isneutral", "isimmort", "ischarm", "isfollow", "isactive", "isdelay", "isvisible", "hastarget", "istarget", "affected", "act", "off", "imm", "carries", "wears", "has", "uses", "name", "pos", "clan", "race", "class", "objtype", "vnum", "hpcnt", "room", "sex", "level", "align", "money", "objval0", "objval1", "objval2", "objval3", "objval4", "grpsize", "onquest", "hunter", "plr", "skill", "weight", "\n" }; const char *fn_evals[] = { "==", ">=", "<=", ">", "<", "!=", "\n" }; 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; } 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 ("invalid oper"); return 0; } } CharData * get_random_char (CharData * mob, ObjData * obj, RoomIndex * room) { CharData *vch, *victim = NULL; int now = 0, highest = 0; if ((mob && obj) || (mob && room) || (obj && room)) { bug ("received multiple prog types"); return NULL; } if (mob) vch = mob->in_room->person_first; else if (obj) { if (obj->in_room) vch = obj->in_room->person_first; else vch = obj->carried_by->in_room->person_first; } else vch = room->person_first; for (; vch; vch = vch->next_in_room) { if (mob && mob != vch && !IsNPC (vch) && can_see (mob, vch) && (now = number_percent ()) > highest) { victim = vch; highest = now; } else if ((now = number_percent ()) > highest) { victim = vch; highest = now; } } return victim; } int count_people_room (CharData * mob, ObjData * obj, RoomIndex * room, int iFlag) { CharData *vch; int count; if ((mob && obj) || (mob && room) || (obj && room)) { bug ("received multiple prog types"); return 0; } if (mob) vch = mob->in_room->person_first; else if (obj) { if (obj->in_room) vch = obj->in_room->person_first; else vch = obj->carried_by->in_room->person_first; } else vch = room->person_first; for (count = 0; vch; vch = vch->next_in_room) { if (mob) { if (mob != vch && (iFlag == 0 || (iFlag == 1 && !IsNPC (vch)) || (iFlag == 2 && IsNPC (vch)) || (iFlag == 3 && IsNPC (mob) && IsNPC (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 && !IsNPC (vch)) || (iFlag == 2 && IsNPC (vch))) count++; } } return (count); } int get_order (CharData * ch, ObjData * obj) { CharData *vch; ObjData *vobj; int i; if (ch && obj) { bug ("received multiple prog types"); return 0; } if (ch && !IsNPC (ch)) return 0; if (ch) { vch = ch->in_room->person_first; vobj = NULL; } else { vch = NULL; if (obj->in_room) vobj = obj->in_room->content_first; else if (obj->carried_by->in_room->content_first) vobj = obj->carried_by->in_room->content_first; else vobj = NULL; } if (ch) for (i = 0; vch; vch = vch->next_in_room) { if (vch == ch) return i; if (IsNPC (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; } bool has_item (CharData * ch, vnum_t vnum, item_t pitem_type, bool fWear) { ObjData *obj; for (obj = ch->carrying_first; obj; obj = obj->next_content) if ((vnum < 0 || obj->pIndexData->vnum == vnum) && (pitem_type < 0 || obj->pIndexData->item_type == pitem_type) && (!fWear || obj->wear_loc != WEAR_NONE)) return true; return false; } bool get_mob_vnum_room (CharData * ch, ObjData * obj, RoomIndex * room, vnum_t vnum) { CharData *mob; if ((ch && obj) || (ch && room) || (obj && room)) { bug ("received multiple prog types"); return false; } if (ch) mob = ch->in_room->person_first; else if (obj) { if (obj->in_room) mob = obj->in_room->person_first; else mob = obj->carried_by->in_room->person_first; } else mob = room->person_first; for (; mob; mob = mob->next_in_room) if (IsNPC (mob) && mob->pIndexData->vnum == vnum) return true; return false; } bool get_obj_vnum_room (CharData * ch, ObjData * obj, RoomIndex * room, vnum_t vnum) { ObjData *vobj; if ((ch && obj) || (ch && room) || (obj && room)) { bug ("received multiple prog types"); return false; } if (ch) vobj = ch->in_room->content_first; else if (obj) { if (obj->in_room) vobj = obj->in_room->content_first; else vobj = obj->carried_by->in_room->content_first; } else vobj = room->content_first; for (; vobj; vobj = vobj->next_content) if (vobj->pIndexData->vnum == vnum) return true; return false; } int cmd_eval_mob (vnum_t vnum, const char *line, int check, CharData * mob, CharData * ch, const void *arg1, const void *arg2, CharData * rch) { CharData *lval_char = mob; CharData *vch = (CharData *) arg2; ObjData *obj1 = (ObjData *) arg1; ObjData *obj2 = (ObjData *) arg2; ObjData *lval_obj = NULL; const char *original; char buf[MIL], code; int lval = 0, oper = 0, rval = -1; flag_t temp; original = line; line = one_argument (line, buf); if (NullStr (buf) || mob == NULL) return false; if (mob->mprog_target == NULL) mob->mprog_target = ch; switch (check) { case CHK_RAND: return (number_percent () < atoi (buf)); case CHK_MOBHERE: if (is_number (buf)) return (get_mob_vnum_room (mob, NULL, NULL, atov (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, atov (buf))); else return ((bool) (get_obj_here (mob, NULL, buf) != NULL)); case CHK_MOBEXISTS: return ((bool) (get_char_world (mob, buf) != NULL)); case CHK_OBJEXISTS: return ((bool) (get_obj_world (mob, buf) != NULL)); 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 = time_info.hour; break; default: ; } if (rval >= 0) { if ((oper = keyword_lookup (fn_evals, buf)) < 0) { bugf ("prog %ld syntax error(2) '%s'", vnum, original); return false; } one_argument (line, buf); lval = rval; rval = atoi (buf); return (num_eval (lval, oper, rval)); } if (buf[0] != '$' || buf[1] == '\0') { bugf ("prog %ld syntax error(3) '%s'", vnum, original); 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: bugf ("prog %ld syntax error(4) '%s'", vnum, original); return false; } if (lval_char == NULL && lval_obj == NULL) return false; switch (check) { case CHK_ISPC: return (lval_char != NULL && !IsNPC (lval_char)); case CHK_ISNPC: return (lval_char != NULL && IsNPC (lval_char)); case CHK_ISGOOD: return (lval_char != NULL && IsGood (lval_char)); case CHK_ISEVIL: return (lval_char != NULL && IsEvil (lval_char)); case CHK_ISNEUTRAL: return (lval_char != NULL && IsNeutral (lval_char)); case CHK_ISIMMORT: return (lval_char != NULL && IsImmortal (lval_char)); case CHK_HUNTER: return (lval_char != NULL && lval_char->hunting == mob); case CHK_ISCHARM: return (lval_char != NULL && IsAffected (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_ONQUEST: return (lval_char != NULL && IsQuester (lval_char)); 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_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); default: ; } line = one_argument (line, buf); switch (check) { case CHK_AFFECTED: if ((temp = flag_value (affect_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsAffected (lval_char, temp)); case CHK_ACT: if ((temp = flag_value (act_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsNPC (lval_char) && IsSet (lval_char->act, temp)); case CHK_PLR: if ((temp = flag_value (plr_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && !IsNPC (lval_char) && IsSet (lval_char->act, temp)); case CHK_IMM: if ((temp = flag_value (imm_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsSet (lval_char->imm_flags, temp)); case CHK_OFF: if ((temp = flag_value (off_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsSet (lval_char->off_flags, temp)); case CHK_CARRIES: if (is_number (buf)) return (lval_char != NULL && has_item (lval_char, atov (buf), (item_t) - 1, false)); else return (lval_char != NULL && (get_obj_carry (lval_char, buf, lval_char) != NULL)); case CHK_WEARS: if (is_number (buf)) return (lval_char != NULL && has_item (lval_char, atov (buf), (item_t) - 1, true)); else return (lval_char != NULL && (get_obj_wear (lval_char, buf, true) != NULL)); case CHK_HAS: return (lval_char != NULL && has_item (lval_char, -1, (item_t) flag_value (type_flags, buf), false)); case CHK_USES: return (lval_char != NULL && has_item (lval_char, -1, (item_t) flag_value (type_flags, buf), true)); case CHK_SKILL: return (lval_char != NULL && !IsNPC (lval_char) && skill_lookup (buf) != -1 && get_skill (lval_char, skill_lookup (buf)) >= atoi (line)); 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_POS: return (lval_char != NULL && lval_char->position == flag_value (position_flags, buf)); case CHK_CLAN: return (lval_char != NULL && CharClan (lval_char) == clan_lookup (buf)); case CHK_CLASS: return (lval_char != NULL && prime_class (lval_char) == class_lookup (buf)); case CHK_RACE: return (lval_char != NULL && lval_char->race == race_lookup (buf)); case CHK_OBJTYPE: return (lval_obj != NULL && lval_obj->item_type == flag_value (type_flags, buf)); default: ; } if ((oper = keyword_lookup (fn_evals, buf)) < 0) { bugf ("prog %ld syntax error(5): '%s'", vnum, original); 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 && IsNPC (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) / (Max (1, lval_char->max_hit)); 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_WEIGHT: if (lval_char != NULL) lval = get_carry_weight (lval_char); break; case CHK_ALIGN: if (lval_char != NULL) lval = lval_char->alignment; break; case CHK_MONEY: if (lval_char != NULL) lval = lval_char->gold; 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_GRPSIZE: if (lval_char != NULL) lval = count_people_room (lval_char, NULL, NULL, 4); break; default: return false; } return (num_eval (lval, oper, rval)); } int cmd_eval_obj (vnum_t vnum, const char *line, int check, ObjData * obj, CharData * ch, const void *arg1, const void *arg2, CharData * rch) { CharData *lval_char = NULL; CharData *vch = (CharData *) arg2; ObjData *obj1 = (ObjData *) arg1; ObjData *obj2 = (ObjData *) arg2; ObjData *lval_obj = obj; const char *original; char buf[MIL], code; int lval = 0, oper = 0, rval = -1; flag_t temp; original = line; line = one_argument (line, buf); if (NullStr (buf) || obj == NULL) return false; if (obj->oprog_target == NULL) obj->oprog_target = ch; switch (check) { case CHK_RAND: return (number_percent () < atoi (buf)); case CHK_MOBHERE: if (is_number (buf)) return (get_mob_vnum_room (NULL, obj, NULL, atov (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, atov (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 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."); break; case CHK_ORDER: rval = get_order (NULL, obj); break; case CHK_HOUR: rval = time_info.hour; break; default: ; } if (rval >= 0) { if ((oper = keyword_lookup (fn_evals, buf)) < 0) { bugf ("Cmd_eval_obj: prog %ld syntax error(2) '%s'", vnum, original); return false; } one_argument (line, buf); lval = rval; rval = atoi (buf); return (num_eval (lval, oper, rval)); } if (buf[0] != '$' || buf[1] == '\0') { bugf ("Cmd_eval_obj: prog %ld syntax error(3) '%s'", vnum, original); return false; } else code = buf[1]; switch (code) { case 'i': lval_obj = obj; 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: bugf ("Cmd_eval_obj: prog %ld syntax error(4) '%s'", vnum, original); return false; } if (lval_char == NULL && lval_obj == NULL) return false; switch (check) { case CHK_ISPC: return (lval_char != NULL && !IsNPC (lval_char)); case CHK_ISNPC: return (lval_char != NULL && IsNPC (lval_char)); case CHK_ISGOOD: return (lval_char != NULL && IsGood (lval_char)); case CHK_ISEVIL: return (lval_char != NULL && IsEvil (lval_char)); case CHK_ISNEUTRAL: return (lval_char != NULL && IsNeutral (lval_char)); case CHK_ISIMMORT: return (lval_char != NULL && IsImmortal (lval_char)); case CHK_ISCHARM: return (lval_char != NULL && IsAffected (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_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 && obj->oprog_target == lval_char); default: ; } line = one_argument (line, buf); switch (check) { case CHK_AFFECTED: if ((temp = flag_value (affect_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsAffected (lval_char, temp)); case CHK_ACT: if ((temp = flag_value (act_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsNPC (lval_char) && IsSet (lval_char->act, temp)); case CHK_PLR: if ((temp = flag_value (plr_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && !IsNPC (lval_char) && IsSet (lval_char->act, temp)); case CHK_IMM: if ((temp = flag_value (imm_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsSet (lval_char->imm_flags, temp)); case CHK_OFF: if ((temp = flag_value (off_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsSet (lval_char->off_flags, temp)); case CHK_CARRIES: if (is_number (buf)) return (lval_char != NULL && has_item (lval_char, atov (buf), (item_t) - 1, false)); else return (lval_char != NULL && (get_obj_carry (lval_char, buf, lval_char) != NULL)); case CHK_WEARS: if (is_number (buf)) return (lval_char != NULL && has_item (lval_char, atov (buf), (item_t) - 1, true)); else return (lval_char != NULL && (get_obj_wear (lval_char, buf, false) != NULL)); case CHK_HAS: return (lval_char != NULL && has_item (lval_char, -1, (item_t) flag_value (type_flags, buf), false)); case CHK_USES: return (lval_char != NULL && has_item (lval_char, -1, (item_t) flag_value (type_flags, buf), true)); case CHK_SKILL: return (lval_char != NULL && !IsNPC (lval_char) && skill_lookup (buf) != -1 && get_skill (lval_char, skill_lookup (buf)) >= atoi (line)); 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_POS: return (lval_char != NULL && lval_char->position == flag_value (position_flags, buf)); case CHK_CLAN: return (lval_char != NULL && CharClan (lval_char) == clan_lookup (buf)); case CHK_CLASS: return (lval_char != NULL && prime_class (lval_char) == class_lookup (buf)); case CHK_RACE: return (lval_char != NULL && lval_char->race == race_lookup (buf)); case CHK_OBJTYPE: return (lval_obj != NULL && lval_obj->item_type == flag_value (type_flags, buf)); default: ; } if ((oper = keyword_lookup (fn_evals, buf)) < 0) { bugf ("Cmd_eval_obj: prog %ld syntax error(5): '%s'", vnum, original); 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 && IsNPC (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) / (Max (1, lval_char->max_hit)); 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_WEIGHT: if (lval_char != NULL) lval = get_carry_weight (lval_char); break; case CHK_ALIGN: if (lval_char != NULL) lval = lval_char->alignment; break; case CHK_MONEY: if (lval_char != NULL) lval = lval_char->gold; 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_GRPSIZE: if (lval_char != NULL) lval = count_people_room (lval_char, NULL, NULL, 4); break; default: return false; } return (num_eval (lval, oper, rval)); } int cmd_eval_room (vnum_t vnum, const char *line, int check, RoomIndex * room, CharData * ch, const void *arg1, const void *arg2, CharData * rch) { CharData *lval_char = NULL; CharData *vch = (CharData *) arg2; ObjData *obj1 = (ObjData *) arg1; ObjData *obj2 = (ObjData *) arg2; ObjData *lval_obj = NULL; const char *original; char buf[MIL], code; int lval = 0, oper = 0, rval = -1; flag_t temp; original = line; line = one_argument (line, buf); if (NullStr (buf) || room == NULL) return false; if (room->rprog_target == NULL) room->rprog_target = ch; switch (check) { case CHK_RAND: return (number_percent () < atoi (buf)); case CHK_MOBHERE: if (is_number (buf)) return (get_mob_vnum_room (NULL, NULL, room, atov (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, atov (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 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 ("received CHK_CLONES."); break; case CHK_ORDER: bug ("received CHK_ORDER."); break; case CHK_HOUR: rval = time_info.hour; break; default: ; } if (rval >= 0) { if ((oper = keyword_lookup (fn_evals, buf)) < 0) { bugf ("prog %ld syntax error(2) '%s'", vnum, original); return false; } one_argument (line, buf); lval = rval; rval = atoi (buf); return (num_eval (lval, oper, rval)); } if (buf[0] != '$' || buf[1] == '\0') { bugf ("prog %ld syntax error(3) '%s'", vnum, original); return false; } else code = buf[1]; switch (code) { case 'i': bug ("received code case 'i'."); 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: bugf ("prog %ld syntax error(4) '%s'", vnum, original); return false; } if (lval_char == NULL && lval_obj == NULL) return false; switch (check) { case CHK_ISPC: return (lval_char != NULL && !IsNPC (lval_char)); case CHK_ISNPC: return (lval_char != NULL && IsNPC (lval_char)); case CHK_ISGOOD: return (lval_char != NULL && IsGood (lval_char)); case CHK_ISEVIL: return (lval_char != NULL && IsEvil (lval_char)); case CHK_ISNEUTRAL: return (lval_char != NULL && IsNeutral (lval_char)); case CHK_ISIMMORT: return (lval_char != NULL && IsImmortal (lval_char)); case CHK_ISCHARM: return (lval_char != NULL && IsAffected (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_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 && room->rprog_target == lval_char); default: ; } line = one_argument (line, buf); switch (check) { case CHK_AFFECTED: if ((temp = flag_value (affect_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsAffected (lval_char, temp)); case CHK_ACT: if ((temp = flag_value (act_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsNPC (lval_char) && IsSet (lval_char->act, temp)); case CHK_PLR: if ((temp = flag_value (plr_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && !IsNPC (lval_char) && IsSet (lval_char->act, temp)); case CHK_IMM: if ((temp = flag_value (imm_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsSet (lval_char->imm_flags, temp)); case CHK_OFF: if ((temp = flag_value (off_flags, buf)) == NO_FLAG) return false; return (lval_char != NULL && IsSet (lval_char->off_flags, temp)); case CHK_CARRIES: if (is_number (buf)) return (lval_char != NULL && has_item (lval_char, atov (buf), (item_t) - 1, false)); else return (lval_char != NULL && (get_obj_carry (lval_char, buf, lval_char) != NULL)); case CHK_WEARS: if (is_number (buf)) return (lval_char != NULL && has_item (lval_char, atov (buf), (item_t) - 1, true)); else return (lval_char != NULL && (get_obj_wear (lval_char, buf, false) != NULL)); case CHK_HAS: return (lval_char != NULL && has_item (lval_char, -1, (item_t) flag_value (type_flags, buf), false)); case CHK_USES: return (lval_char != NULL && has_item (lval_char, -1, (item_t) flag_value (type_flags, buf), true)); case CHK_SKILL: return (lval_char != NULL && !IsNPC (lval_char) && skill_lookup (buf) != -1 && get_skill (lval_char, skill_lookup (buf)) >= atoi (line)); 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_POS: return (lval_char != NULL && lval_char->position == flag_value (position_flags, buf)); case CHK_CLAN: return (lval_char != NULL && CharClan (lval_char) == clan_lookup (buf)); case CHK_CLASS: return (lval_char != NULL && prime_class (lval_char) == class_lookup (buf)); case CHK_RACE: return (lval_char != NULL && lval_char->race == race_lookup (buf)); case CHK_OBJTYPE: return (lval_obj != NULL && lval_obj->item_type == (item_t) flag_value (type_flags, buf)); default: ; } if ((oper = keyword_lookup (fn_evals, buf)) < 0) { bugf ("prog %ld syntax error(5): '%s'", vnum, original); 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 && IsNPC (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) / (Max (1, lval_char->max_hit)); 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_WEIGHT: if (lval_char != NULL) lval = get_carry_weight (lval_char); break; case CHK_ALIGN: if (lval_char != NULL) lval = lval_char->alignment; break; case CHK_MONEY: if (lval_char != NULL) lval = lval_char->gold; 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_GRPSIZE: if (lval_char != NULL) lval = count_people_room (lval_char, NULL, NULL, 4); break; default: return false; } return (num_eval (lval, oper, rval)); } void expand_arg_mob (char *buf, const char *format, CharData * mob, CharData * ch, const void *arg1, const void *arg2, CharData * rch) { const char *someone = "someone"; const char *something = "something"; const char *someones = "someone's"; char name[MIL]; CharData *vch = (CharData *) arg2; ObjData *obj1 = (ObjData *) arg1; ObjData *obj2 = (ObjData *) arg2; const char *str; const char *i; char *point; if (NullStr (format)) return; point = buf; str = format; while (*str != '\0') { if (*str != '$') { *point++ = *str++; continue; } ++str; switch (*str) { default: bugf ("bad code %c.", *str); i = " <@@@> "; break; case 'i': one_argument (mob->name, name); i = name; break; case 'I': i = mob->short_descr; break; case 'n': i = someone; if (ch != NULL && can_see (mob, ch)) { one_argument (ch->name, name); i = capitalize (name); } break; case 'N': i = (ch != NULL && can_see (mob, ch)) ? (IsNPC (ch) ? ch-> short_descr : ch->name) : someone; break; case 't': i = someone; if (vch != NULL && can_see (mob, vch)) { one_argument (vch->name, name); i = capitalize (name); } break; case 'T': i = (vch != NULL && can_see (mob, vch)) ? (IsNPC (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, name); i = capitalize (name); } break; case 'R': if (rch == NULL) rch = get_random_char (mob, NULL, NULL); i = (rch != NULL && can_see (mob, rch)) ? (IsNPC (ch) ? ch-> short_descr : ch->name) : someone; break; case 'q': i = someone; if (mob->mprog_target != NULL && can_see (mob, mob->mprog_target)) { one_argument (mob->mprog_target->name, name); i = capitalize (name); } break; case 'Q': i = (mob->mprog_target != NULL && can_see (mob, mob->mprog_target)) ? (IsNPC (mob->mprog_target) ? mob-> mprog_target->short_descr : mob->mprog_target-> name) : someone; break; case 'j': i = he_she[Range (0, mob->sex, 2)]; break; case 'e': i = (ch != NULL && can_see (mob, ch)) ? he_she[Range (0, ch->sex, 2)] : someone; break; case 'E': i = (vch != NULL && can_see (mob, vch)) ? he_she[Range (0, vch->sex, 2)] : someone; break; case 'J': i = (rch != NULL && can_see (mob, rch)) ? he_she[Range (0, rch->sex, 2)] : someone; break; case 'X': i = (mob->mprog_target != NULL && can_see (mob, mob->mprog_target)) ? he_she[Range (0, mob-> mprog_target-> sex, 2)] : someone; break; case 'k': i = him_her[Range (0, mob->sex, 2)]; break; case 'm': i = (ch != NULL && can_see (mob, ch)) ? him_her[Range (0, ch->sex, 2)] : someone; break; case 'M': i = (vch != NULL && can_see (mob, vch)) ? him_her[Range (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[Range (0, rch->sex, 2)] : someone; break; case 'Y': i = (mob->mprog_target != NULL && can_see (mob, mob->mprog_target)) ? him_her[Range (0, mob-> mprog_target-> sex, 2)] : someone; break; case 'l': i = his_her[Range (0, mob->sex, 2)]; break; case 's': i = (ch != NULL && can_see (mob, ch)) ? his_her[Range (0, ch->sex, 2)] : someones; break; case 'S': i = (vch != NULL && can_see (mob, vch)) ? his_her[Range (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[Range (0, rch->sex, 2)] : someones; break; case 'Z': i = (mob->mprog_target != NULL && can_see (mob, mob->mprog_target)) ? his_her[Range (0, mob-> mprog_target-> sex, 2)] : someones; break; case 'o': i = something; if (obj1 != NULL && can_see_obj (mob, obj1)) { one_argument (obj1->name, name); i = name; } 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, name); i = name; } 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, ObjData * obj, RoomIndex * room, CharData * ch, const void *arg1, const void *arg2, CharData * rch) { const char *someone = "someone"; const char *something = "something"; const char *someones = "someone's"; char name[MIL]; CharData *vch = (CharData *) arg2; ObjData *obj1 = (ObjData *) arg1; ObjData *obj2 = (ObjData *) arg2; const char *str; const char *i; char *point; if (obj && room) { bug ("received a obj and a room"); return; } if (NullStr (format)) return; point = buf; str = format; while (*str != '\0') { if (*str != '$') { *point++ = *str++; continue; } ++str; switch (*str) { default: bugf ("bad code %c.", *str); i = " <@@@> "; break; case 'i': if (obj) { one_argument (obj->name, name); i = name; } else { bug ("room had an \"i\" case."); i = " <@@@> "; } break; case 'I': if (obj) i = obj->short_descr; else { bug ("room had an \"I\" case."); i = " <@@@> "; } break; case 'n': i = someone; if (ch != NULL) { one_argument (ch->name, name); i = capitalize (name); } break; case 'N': i = (ch != NULL) ? (IsNPC (ch) ? ch->short_descr : ch->name) : someone; break; case 't': i = someone; if (vch != NULL) { one_argument (vch->name, name); i = capitalize (name); } break; case 'T': i = (vch != NULL) ? (IsNPC (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, name); i = capitalize (name); } 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) ? (IsNPC (ch) ? ch->short_descr : ch->name) : someone; break; case 'q': i = someone; if (obj && obj->oprog_target != NULL) { one_argument (obj->oprog_target->name, name); i = capitalize (name); } else if (room && room->rprog_target != NULL) { one_argument (room->rprog_target->name, name); i = capitalize (name); } break; case 'Q': i = (obj && obj->oprog_target != NULL) ? (IsNPC (obj->oprog_target) ? obj-> oprog_target->short_descr : obj->oprog_target-> name) : (room && room->rprog_target != NULL) ? (IsNPC (room->rprog_target) ? room-> rprog_target->short_descr : room-> rprog_target->name) : someone; break; case 'j': bug ("Obj/room received case 'j'"); i = " <@@@> "; break; case 'e': i = (ch != NULL) ? he_she[Range (0, ch->sex, 2)] : someone; break; case 'E': i = (vch != NULL) ? he_she[Range (0, vch->sex, 2)] : someone; break; case 'J': i = (rch != NULL) ? he_she[Range (0, rch->sex, 2)] : someone; break; case 'X': i = (obj && obj->oprog_target != NULL) ? he_she[Range (0, obj-> oprog_target-> sex, 2)] : (room && room-> rprog_target != NULL) ? he_she[Range (0, room->rprog_target->sex, 2)] : someone; break; case 'k': bug ("received case 'k'."); i = " <@@@> "; break; case 'm': i = (ch != NULL) ? him_her[Range (0, ch->sex, 2)] : someone; break; case 'M': i = (vch != NULL) ? him_her[Range (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[Range (0, rch->sex, 2)] : someone; break; case 'Y': i = (obj && obj->oprog_target != NULL) ? him_her[Range (0, obj-> oprog_target-> sex, 2)] : (room && room-> rprog_target != NULL) ? him_her[Range (0, room->rprog_target->sex, 2)] : someone; break; case 'l': bug ("received case 'l'."); i = " <@@@> "; break; case 's': i = (ch != NULL) ? his_her[Range (0, ch->sex, 2)] : someones; break; case 'S': i = (vch != NULL) ? his_her[Range (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[Range (0, rch->sex, 2)] : someones; break; case 'Z': i = (obj && obj->oprog_target != NULL) ? his_her[Range (0, obj-> oprog_target-> sex, 2)] : (room && room-> rprog_target != NULL) ? his_her[Range (0, room->rprog_target->sex, 2)] : someones; break; case 'o': i = something; if (obj1 != NULL) { one_argument (obj1->name, name); i = name; } break; case 'O': i = (obj1 != NULL) ? obj1->short_descr : something; break; case 'p': i = something; if (obj2 != NULL) { one_argument (obj2->name, name); i = name; } break; case 'P': i = (obj2 != NULL) ? obj2->short_descr : something; break; } ++str; while ((*point = *i) != '\0') ++point, ++i; } *point = '\0'; return; } const char * prog_type (prog_t type) { switch (type) { case PRG_MPROG: return "mobile"; case PRG_OPROG: return "object"; case PRG_RPROG: return "room"; default: return "unknown"; } } #define MAX_NESTED_LEVEL 12 #define BEGIN_BLOCK 0 #define IN_BLOCK -1 #define END_BLOCK -2 #define MAX_CALL_LEVEL 5 #define MAX_PTRACE 500 int ptrace_current; int ptrace_calledby[MAX_PTRACE]; vnum_t callstack_pvnum[MAX_CALL_LEVEL]; vnum_t callstack_mvnum[MAX_CALL_LEVEL]; vnum_t callstack_rvnum[MAX_CALL_LEVEL]; int callstack_line[MAX_CALL_LEVEL]; bool callstack_aborted[MAX_CALL_LEVEL]; prog_t callstack_type[MAX_CALL_LEVEL]; vnum_t ptrace_pvnum[MAX_PTRACE]; vnum_t ptrace_mvnum[MAX_PTRACE]; vnum_t ptrace_rvnum[MAX_PTRACE]; prog_t ptrace_type[MAX_PTRACE]; unsigned char ptrace_calllevel[MAX_PTRACE]; time_t ptrace_time[MAX_PTRACE]; bool ptrace_aborted[MAX_PTRACE]; int call_level = 0; Do_Fun (do_preset) { int i; chprintln (ch, "Progs reseted. (prog callstack depth to 0)"); for (i = 0; i < MAX_CALL_LEVEL; i++) { callstack_pvnum[i] = 0; callstack_mvnum[i] = 0; callstack_rvnum[i] = 0; callstack_type[i] = PRG_NONE; callstack_aborted[i] = false; } call_level = 0; logf ("%s reset the prog callstack", ch->name); return; } Do_Fun (do_pinfo) { int i; Buffer *output; output = new_buf (); bprintlnf (output, " Displaying program call abort history - calllevel currently is %d\r\n", call_level); for (i = 0; i < MAX_CALL_LEVEL; i++) { if (callstack_aborted[i]) { bprintlnf (output, " [%2d] Program %ld on %s %ld (in room %ld) {RABORTED!!! (BUGGY?){X\r\n", i, callstack_pvnum[i], prog_type (callstack_type[i]), callstack_mvnum[i], callstack_rvnum[i]); } else { bprintlnf (output, " [%2d] Program %ld on %s %ld (in room %ld)\r\n", i, callstack_pvnum[i], prog_type (callstack_type[i]), callstack_mvnum[i], callstack_rvnum[i]); } } { ProgCode *prg; for (prg = mprog_first; prg; prg = prg->next) { if (prg->disabled) { bprintlnf (output, "Mobprog %ld is disabled with the following text:{x", prg->vnum); bprintln (output, prg->disabled_text); } } for (prg = oprog_first; prg; prg = prg->next) { if (prg->disabled) { bprintlnf (output, "Objprog %ld is disabled with the following text:{x", prg->vnum); bprintln (output, prg->disabled_text); } } for (prg = rprog_first; prg; prg = prg->next) { if (prg->disabled) { bprintlnf (output, "Roomprog %ld is disabled with the following text:{x", prg->vnum); bprintln (output, prg->disabled_text); } } } sendpage (ch, buf_string (output)); free_buf (output); return; } Do_Fun (do_ptrace) { char arg1[MIL]; Buffer *output; int lines_to_show; int line; int count; int i; int lc; argument = one_argument (argument, arg1); if (NullStr (arg1)) { lines_to_show = get_scr_cols (ch); lines_to_show %= MAX_PTRACE; } else if (is_number (arg1)) { lines_to_show = atoi (arg1); if (lines_to_show < 1) { chprintln (ch, "Lines to show, increased to 1"); lines_to_show = 1; } else if (lines_to_show > MAX_PTRACE) { chprintlnf (ch, "Lines to show, decreased to the number logged in the trace - %d", MAX_PTRACE); lines_to_show = MAX_PTRACE; } } else { chprintlnf (ch, "{RThe only parameter for ptrace must be a numeric value" NEWLINE "for the number of lines of the trace you wish to see.{x"); return; } chprintlnf (ch, "Number of trace lines to show=%d", lines_to_show); output = new_buf (); bprintln (output, "{xPTrace {G#prog{x, {Mtype{x, {Yvnum{x, {Binroom{x"); line = ptrace_current + MAX_PTRACE - lines_to_show; lc = 0; for (count = 0; count < lines_to_show; count++) { line++; line %= MAX_PTRACE; if (ptrace_time[line] == 0) continue; bprintf (output, "[%3d]%s ", ++lc, str_time (ptrace_time[line], GetTzone (ch), "%H:%M:%S")); for (i = 0; i < ptrace_calllevel[line]; i++) { bprint (output, " "); } bprintlnf (output, "{G%5ld{x,{M%6s,{Y%5ld{x,{B%5ld{x, %s", ptrace_pvnum[line], prog_type (ptrace_type[line]), ptrace_mvnum[line], ptrace_rvnum[line], prog_type_to_name (ptrace_calledby[line])); } sendpage (ch, buf_string (output)); free_buf (output); } Do_Fun (do_phelp) { cmd_syntax (ch, NULL, n_fun, "trace", "reset", "info", "stat", "dump", NULL); } Do_Fun (do_pstat) { char cmd[MIL], arg[MIL]; ProgList *prg; int i; argument = one_argument (argument, cmd); one_argument (argument, arg); if (NullStr (cmd)) { cmd_syntax (ch, NULL, n_fun, "mob <vnum>", "obj <vnum>", "rpstat <vnum>", NULL); return; } else if (!str_prefix (cmd, "room")) { RoomIndex *room; if (NullStr (arg)) room = ch->in_room; else if (!is_number (arg)) { chprintln (ch, "You must provide a number."); return; } else if ((room = get_room_index (atov (arg))) == NULL) { chprintln (ch, "No such room."); return; } chprintlnf (ch, "Room #%-6ld [%s]", room->vnum, room->name); chprintlnf (ch, "Delay %-6d [%s]", room->rprog_delay, room->rprog_target == NULL ? "No target" : room->rprog_target->name); if (!room->rprog_flags) { chprintln (ch, "[No programs set]"); return; } for (i = 0, prg = room->rprog_first; prg != NULL; prg = prg->next) { chprintlnf (ch, "[%2d] Trigger [%-8s] Program [%4ld] Phrase [%s]", ++i, prog_type_to_name (prg->trig_type), prg->prog->vnum, prg->trig_phrase); } return; } else if (!str_prefix (cmd, "object")) { ObjData *obj; if (NullStr (arg) || (obj = get_obj_world (ch, arg)) == NULL) { chprintln (ch, "No such object."); return; } chprintlnf (ch, "Object #%-6ld [%s]", obj->pIndexData->vnum, obj->short_descr); chprintlnf (ch, "Delay %-6d [%s]", obj->oprog_delay, obj->oprog_target == NULL ? "No target" : obj->oprog_target->name); if (!obj->pIndexData->oprog_flags) { chprintln (ch, "[No programs set]"); return; } for (i = 0, prg = obj->pIndexData->oprog_first; prg != NULL; prg = prg->next) { chprintlnf (ch, "[%2d] Trigger [%-8s] Program [%4ld] Phrase [%s]", ++i, prog_type_to_name (prg->trig_type), prg->prog->vnum, prg->trig_phrase); } return; } else if (!str_prefix (cmd, "mobile")) { CharData *victim; if (NullStr (arg) || (victim = get_char_world (ch, arg)) == NULL) { chprintln (ch, "No such creature."); return; } if (!IsNPC (victim)) { chprintln (ch, "That is not a mobile."); return; } chprintlnf (ch, "Mobile #%-6ld [%s]", victim->pIndexData->vnum, victim->short_descr); chprintlnf (ch, "Delay %-6d [%s]", victim->mprog_delay, victim->mprog_target == NULL ? "No target" : victim->mprog_target->name); if (!victim->pIndexData->mprog_flags) { chprintln (ch, "[No programs set]"); return; } for (i = 0, prg = victim->pIndexData->mprog_first; prg != NULL; prg = prg->next) { chprintlnf (ch, "[%2d] Trigger [%-8s] Program [%4ld] Phrase [%s]", ++i, prog_type_to_name (prg->trig_type), prg->prog->vnum, prg->trig_phrase); } return; } else do_pstat (n_fun, ch, ""); } Do_Fun (do_pdump) { char cmd[MIL], buf[MIL]; ProgCode *prg; argument = one_argument (argument, cmd); one_argument (argument, buf); if (NullStr (cmd)) { cmd_syntax (ch, NULL, n_fun, "mob <vnum>", "obj <vnum>", "room <vnum>", NULL); return; } else if (!str_prefix (cmd, "mobile")) { if ((prg = get_prog_index (atov (buf), PRG_MPROG)) == NULL) { chprintln (ch, "No such MOBprogram."); return; } sendpage (ch, prg->code); } else if (!str_prefix (cmd, "object")) { if ((prg = get_prog_index (atov (buf), PRG_OPROG)) == NULL) { chprintln (ch, "No such OBJprogram."); return; } sendpage (ch, prg->code); } else if (!str_prefix (cmd, "room")) { if ((prg = get_prog_index (atov (buf), PRG_RPROG)) == NULL) { chprintln (ch, "No such ROOMprogram."); return; } sendpage (ch, prg->code); } else do_pdump (n_fun, ch, ""); } Do_Fun (do_programs) { vinterpret (ch, n_fun, argument, "trace", do_ptrace, "reset", do_preset, "info", do_pinfo, "stat", do_pstat, "dump", do_pdump, NULL, do_phelp); } void buggy_prog (ProgList * trigger, const char *fmt, ...) { char buf[MSL]; char *pBuf; int i; assert (trigger->prog->disabled == false); trigger->prog->disabled = true; sprintf (buf, "#############" NEWLINE " Disabling prog %ld,%ld,%ld,%d,%d:" NEWLINE " ", callstack_pvnum[call_level - 1], callstack_mvnum[call_level - 1], callstack_rvnum[call_level - 1], callstack_line[call_level - 1], call_level - 1); if (!NullStr (fmt)) { va_list args; pBuf = &buf[strlen (buf)]; va_start (args, fmt); vsnprintf (pBuf, sizeof (buf), fmt, args); va_end (args); bug (pBuf); } pBuf = &buf[strlen (buf)]; sprintf (pBuf, NEWLINE " Trigger type '%s' phrase '%s'" NEWLINE, prog_type_to_name (trigger->trig_type), trigger->trig_phrase); strcat (pBuf, " Call stack info:" NEWLINE); for (i = 0; i < call_level; i++) { if (!callstack_aborted[i] || (i == call_level - 1)) { sprintf (pBuf + strlen (pBuf), " Program %ld on %s %ld (in room %ld), line %d" NEWLINE, callstack_pvnum[i], prog_type (callstack_type[i]), callstack_mvnum[i], callstack_rvnum[i], callstack_line[i]); } } strcat (pBuf, "#############" NEWLINE NEWLINE); replace_str (&trigger->prog->disabled_text, buf); } void program_flow (ProgList * program, CharData * mob, ObjData * obj, RoomIndex * room, CharData * ch, const void *arg1, const void *arg2) { CharData *rch = NULL; const char *source; const char *code; const char *line; char ctrl[MAX_INPUT_LENGTH], data[MAX_STRING_LENGTH]; static bool init_ptrace = true; char buf[MSL]; prog_t type = PRG_NONE; int level, eval, check; int state[MAX_NESTED_LEVEL], cond[MAX_NESTED_LEVEL]; vnum_t mvnum = 0, ovnum = 0, rvnum = 0, pvnum; if (init_ptrace) { memset (&ptrace_time[0], 0, sizeof (time_t)); init_ptrace = false; } if (!program) { bug ("program_flow(): program==NULL!!!"); return; } if ((mob && obj) || (mob && room) || (obj && room)) { bug ("received multiple prog types."); return; } if (mob) { type = PRG_MPROG; mvnum = mob->pIndexData->vnum; rvnum = mob->in_room ? mob->in_room->vnum : 0; } else if (obj) { type = PRG_OPROG; ovnum = obj->pIndexData->vnum; mvnum = 0; rvnum = obj->in_room ? obj->in_room->vnum : 0; } else if (room) { type = PRG_RPROG; mvnum = 0; rvnum = room->vnum; } else { bug ("did not receive a prog type."); return; } pvnum = program->prog->vnum; callstack_pvnum[call_level] = pvnum; callstack_mvnum[call_level] = mvnum; callstack_rvnum[call_level] = rvnum; callstack_aborted[call_level] = true; callstack_line[call_level] = 0; callstack_type[call_level] = type; ptrace_current++; ptrace_current %= MAX_PTRACE; ptrace_calledby[ptrace_current] = program->trig_type; ptrace_pvnum[ptrace_current] = pvnum; ptrace_mvnum[ptrace_current] = mvnum; ptrace_rvnum[ptrace_current] = rvnum; ptrace_time[ptrace_current] = current_time; ptrace_calllevel[ptrace_current] = call_level; ptrace_type[ptrace_current] = type; if (++call_level > MAX_CALL_LEVEL) { int i; if (mob) bugf ("Progs: MAX_CALL_LEVEL exceeded, vnum %ld, mprog vnum %ld", mvnum, pvnum); else if (obj) bugf ("Progs: MAX_CALL_LEVEL exceeded, vnum %ld oprog vnum %ld.", ovnum, pvnum); else bugf ("Progs: MAX_CALL_LEVEL exceeded, vnum %ld rprog vnum %ld.", rvnum, pvnum); log_string ("Program callstack:\n"); for (i = 0; i < MAX_CALL_LEVEL; i++) { logf ("[%2d] Program %ld on %s %ld (in room %ld)", i, callstack_pvnum[i], prog_type (callstack_type[i]), callstack_mvnum[i], callstack_rvnum[i]); } return; } if (program->prog->disabled) { if (ch) { bugf ("Prog %ld triggered (%s) on me by '%s', not run cause prog is disabled.", program->prog->vnum, prog_type_to_name (program->trig_type), ch->name); } else { bugf ("Prog %ld triggered (%s), not run cause prog is disabled.", program->prog->vnum, prog_type_to_name (program->trig_type)); } call_level--; callstack_aborted[call_level] = false; return; } for (level = 0; level < MAX_NESTED_LEVEL; level++) { state[level] = IN_BLOCK; cond[level] = true; } level = 0; source = program->prog->code; code = source; while (*code) { bool arg_first = true; char *b = buf, *c = ctrl, *d = data; while (isspace (*code) && *code) code++; while (*code) { if (*code == '\n' || *code == '\r') break; else if (isspace (*code)) { if (arg_first) arg_first = false; else *d++ = *code; } else { if (arg_first) *c++ = *code; else *d++ = *code; } *b++ = *code++; } *b = *c = *d = '\0'; if (NullStr (buf)) break; if (buf[0] == '*') continue; line = data; if (!str_cmp (ctrl, "if")) { if (state[level] == BEGIN_BLOCK) { if (mob) buggy_prog (program, "misplaced if statement, mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "misplaced if statement, obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "misplaced if statement, room %ld prog %ld", rvnum, pvnum); call_level--; return; } state[level] = BEGIN_BLOCK; if (++level >= MAX_NESTED_LEVEL) { if (mob) buggy_prog (program, "Max nested level exceeded, mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "Max nested level exceeded, obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "Max nested level exceeded, room %ld prog %ld", rvnum, pvnum); call_level--; return; } if (level && cond[level - 1] == false) { cond[level] = false; continue; } line = one_argument (line, ctrl); if (mob && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { cond[level] = cmd_eval_mob (pvnum, line, check, mob, ch, arg1, arg2, rch); } else if (obj && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { cond[level] = cmd_eval_obj (pvnum, line, check, obj, ch, arg1, arg2, rch); } else if (room && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { cond[level] = cmd_eval_room (pvnum, line, check, room, ch, arg1, arg2, rch); } else { if (mob) buggy_prog (program, "invalid if_check (if), mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "invalid if_check (if), obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "invalid if_check (if), room %ld prog %ld", rvnum, pvnum); call_level--; return; } state[level] = END_BLOCK; } else if (!str_cmp (ctrl, "or")) { if (!level || state[level - 1] != BEGIN_BLOCK) { if (mob) buggy_prog (program, "or without if, mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "or without if, obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "or without if, room %ld prog %ld", rvnum, pvnum); return; } if (level && cond[level - 1] == false) continue; line = one_argument (line, ctrl); if (mob && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { eval = cmd_eval_mob (pvnum, line, check, mob, ch, arg1, arg2, rch); } else if (obj && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { eval = cmd_eval_obj (pvnum, line, check, obj, ch, arg1, arg2, rch); } else if (room && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { eval = cmd_eval_room (pvnum, line, check, room, ch, arg1, arg2, rch); } else { if (mob) buggy_prog (program, "invalid if_check (or), mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "invalid if_check (or), obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "invalid if_check (or), room %ld prog %ld", rvnum, pvnum); call_level--; return; } cond[level] = (eval == (int) true) ? true : cond[level]; } else if (!str_cmp (ctrl, "and")) { if (!level || state[level - 1] != BEGIN_BLOCK) { if (mob) buggy_prog (program, "and without if, mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "and without if, obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "and without if, room %ld prog %ld", rvnum, pvnum); call_level--; return; } if (level && cond[level - 1] == false) continue; line = one_argument (line, ctrl); if (mob && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { eval = cmd_eval_mob (pvnum, line, check, mob, ch, arg1, arg2, rch); } else if (obj && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { eval = cmd_eval_obj (pvnum, line, check, obj, ch, arg1, arg2, rch); } else if (room && (check = keyword_lookup (fn_keyword, ctrl)) >= 0) { eval = cmd_eval_room (pvnum, line, check, room, ch, arg1, arg2, rch); } else { if (mob) buggy_prog (program, "invalid if_check (and), mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "invalid if_check (and), obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "invalid if_check (and), room %ld prog %ld", rvnum, pvnum); call_level--; return; } cond[level] = (cond[level] == (int) true) && (eval == (int) true) ? true : false; } else if (!str_cmp (ctrl, "endif")) { if (!level || state[level - 1] != BEGIN_BLOCK) { if (mob) buggy_prog (program, "endif without if, mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "endif without if, obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "endif without if, room %ld prog %ld", rvnum, pvnum); call_level--; return; } cond[level] = true; state[level] = IN_BLOCK; state[--level] = END_BLOCK; } else if (!str_cmp (ctrl, "else")) { if (!level || state[level - 1] != BEGIN_BLOCK) { if (mob) buggy_prog (program, "else without if, mob %ld prog %ld", mvnum, pvnum); else if (obj) buggy_prog (program, "else without if, obj %ld prog %ld", ovnum, pvnum); else buggy_prog (program, "else without if, room %ld prog %ld", rvnum, pvnum); call_level--; return; } if (level && cond[level - 1] == false) continue; state[level] = IN_BLOCK; cond[level] = (cond[level] == (int) true) ? false : true; } else if (cond[level] == (int) true && (!str_cmp (ctrl, "break") || !str_cmp (ctrl, "end"))) { call_level--; callstack_aborted[call_level] = false; return; } else if ((!level || cond[level] == (int) true) && !NullStr (buf)) { 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 (ctrl, "mob")) { line = one_argument (data, ctrl); if (!mob) bug ("mob command in non MOBprog"); else mob_interpret (mob, line); } else if (!str_cmp (ctrl, "obj")) { line = one_argument (data, ctrl); if (!obj) bug ("obj command in non OBJprog"); else obj_interpret (obj, line); } else if (!str_cmp (ctrl, "room")) { line = one_argument (data, ctrl); if (!room) bug ("room command in non ROOMprog"); else room_interpret (room, line); } else { if (!mob) bugf ("Normal Mud command in non-MOBprog, prog vnum %ld", pvnum); else interpret (mob, data); } } } call_level--; callstack_aborted[call_level] = false; } void p_act_trigger (const char *argument, CharData * mob, ObjData * obj, RoomIndex * room, CharData * ch, const void *arg1, const void *arg2, flag_t type) { ProgList *prg; if ((mob && obj) || (mob && room) || (obj && room)) { bug ("Multiple program types in ACT trigger."); return; } if (mob) { if (!IsNPC (mob)) { bug ("Attempt to access p_act_trigger on a PLAYER."); return; } for (prg = mob->pIndexData->mprog_first; prg != NULL; prg = prg->next) { if (prg->trig_type == type && strstr (argument, prg->trig_phrase) != NULL) { program_flow (prg, mob, NULL, NULL, ch, arg1, arg2); break; } } } else if (obj) { for (prg = obj->pIndexData->oprog_first; prg != NULL; prg = prg->next) { if (prg->trig_type == type && strstr (argument, prg->trig_phrase) != NULL) { program_flow (prg, NULL, obj, NULL, ch, arg1, arg2); break; } } } else if (room) { for (prg = room->rprog_first; prg != NULL; prg = prg->next) { if (prg->trig_type == type && strstr (argument, prg->trig_phrase) != NULL) { program_flow (prg, NULL, NULL, room, ch, arg1, arg2); break; } } } else bug ("ACT trigger with no program type."); return; } bool p_percent_trigger (CharData * mob, ObjData * obj, RoomIndex * room, CharData * ch, const void *arg1, const void *arg2, flag_t type) { ProgList *prg; if ((mob && obj) || (mob && room) || (obj && room)) { bug ("Multiple program types in PERCENT trigger."); return (false); } if (mob) { for (prg = mob->pIndexData->mprog_first; prg != NULL; prg = prg->next) { if (prg->trig_type == type && number_percent () < atoi (prg->trig_phrase)) { program_flow (prg, mob, NULL, NULL, ch, arg1, arg2); return (true); } } } else if (obj) { for (prg = obj->pIndexData->oprog_first; prg != NULL; prg = prg->next) { if (prg->trig_type == type && number_percent () < atoi (prg->trig_phrase)) { program_flow (prg, NULL, obj, NULL, ch, arg1, arg2); return (true); } } } else if (room) { for (prg = room->rprog_first; prg != NULL; prg = prg->next) { if (prg->trig_type == type && number_percent () < atoi (prg->trig_phrase)) { program_flow (prg, NULL, NULL, room, ch, arg1, arg2); return (true); } } } else bug ("PERCENT trigger missing program type."); return (false); } void p_bribe_trigger (CharData * mob, CharData * ch, money_t amount) { ProgList *prg; for (prg = mob->pIndexData->mprog_first; prg; prg = prg->next) { if (prg->trig_type == TRIG_BRIBE && amount >= strtoul (prg->trig_phrase, (char **) NULL, 10)) { program_flow (prg, mob, NULL, NULL, ch, NULL, NULL); break; } } return; } bool p_exit_trigger (CharData * ch, int dir, prog_t type) { CharData *mob; ObjData *obj; RoomIndex *room; ProgList *prg; if (type == PRG_MPROG) { for (mob = ch->in_room->person_first; mob != NULL; mob = mob->next_in_room) { if (IsNPC (mob) && (HasTriggerMob (mob, TRIG_EXIT) || HasTriggerMob (mob, TRIG_EXALL))) { for (prg = mob->pIndexData->mprog_first; prg; prg = prg->next) { if (prg->trig_type == TRIG_EXIT && dir == atoi (prg->trig_phrase) && mob->position == mob->pIndexData->default_pos && can_see (mob, ch)) { program_flow (prg, mob, NULL, NULL, ch, NULL, NULL); return true; } else if (prg->trig_type == TRIG_EXALL && dir == atoi (prg->trig_phrase)) { program_flow (prg, mob, NULL, NULL, ch, NULL, NULL); return true; } } } } } else if (type == PRG_OPROG) { for (obj = ch->in_room->content_first; obj != NULL; obj = obj->next_content) { if (HasTriggerObj (obj, TRIG_EXALL)) { for (prg = obj->pIndexData->oprog_first; prg; prg = prg->next) { if (prg->trig_type == TRIG_EXALL && dir == atoi (prg->trig_phrase)) { program_flow (prg, NULL, obj, NULL, ch, NULL, NULL); return true; } } } } for (mob = ch->in_room->person_first; mob; mob = mob->next_in_room) { for (obj = mob->carrying_first; obj; obj = obj->next_content) { if (HasTriggerObj (obj, TRIG_EXALL)) { for (prg = obj->pIndexData->oprog_first; prg; prg = prg->next) { if (prg->trig_type == TRIG_EXALL && dir == atoi (prg->trig_phrase)) { program_flow (prg, NULL, obj, NULL, ch, NULL, NULL); return true; } } } } } } else if (type == PRG_RPROG) { room = ch->in_room; if (HasTriggerRoom (room, TRIG_EXALL)) { for (prg = room->rprog_first; prg; prg = prg->next) { if (prg->trig_type == TRIG_EXALL && dir == atoi (prg->trig_phrase)) { program_flow (prg, NULL, NULL, room, ch, NULL, NULL); return true; } } } } return false; } void p_give_trigger (CharData * mob, ObjData * obj, RoomIndex * room, CharData * ch, ObjData * dropped, flag_t type) { char buf[MIL]; const char *p; ProgList *prg; if ((mob && obj) || (mob && room) || (obj && room)) { bug ("Multiple program types in GIVE trigger."); return; } if (mob) { for (prg = mob->pIndexData->mprog_first; prg; prg = prg->next) if (prg->trig_type == TRIG_GIVE) { p = prg->trig_phrase; if (is_number (p)) { if (dropped->pIndexData->vnum == atov (p)) { program_flow (prg, mob, NULL, NULL, ch, (void *) dropped, NULL); return; } } else { while (*p) { p = one_argument (p, buf); if (is_name (buf, dropped->name) || !str_cmp ("all", buf)) { program_flow (prg, mob, NULL, NULL, ch, (void *) dropped, NULL); return; } } } } } else if (obj) { for (prg = obj->pIndexData->oprog_first; prg; prg = prg->next) if (prg->trig_type == type) { program_flow (prg, NULL, obj, NULL, ch, (void *) obj, NULL); return; } } else if (room) { for (prg = room->rprog_first; prg; prg = prg->next) if (prg->trig_type == type) { p = prg->trig_phrase; if (is_number (p)) { if (dropped->pIndexData->vnum == atov (p)) { program_flow (prg, NULL, NULL, room, ch, (void *) dropped, NULL); return; } } else { while (*p) { p = one_argument (p, buf); if (is_name (buf, dropped->name) || !str_cmp ("all", buf)) { program_flow (prg, NULL, NULL, room, ch, (void *) dropped, NULL); return; } } } } } } void p_greet_trigger (CharData * ch, prog_t type) { CharData *mob; ObjData *obj; RoomIndex *room; if (type == PRG_MPROG) { for (mob = ch->in_room->person_first; mob != NULL; mob = mob->next_in_room) { if (IsNPC (mob) && (HasTriggerMob (mob, TRIG_GREET) || HasTriggerMob (mob, TRIG_GRALL))) { if (HasTriggerMob (mob, TRIG_GREET) && mob->position == mob->pIndexData->default_pos && can_see (mob, ch)) p_percent_trigger (mob, NULL, NULL, ch, NULL, NULL, TRIG_GREET); else if (HasTriggerMob (mob, TRIG_GRALL)) p_percent_trigger (mob, NULL, NULL, ch, NULL, NULL, TRIG_GRALL); } } } else if (type == PRG_OPROG) { for (obj = ch->in_room->content_first; obj != NULL; obj = obj->next_content) { if (HasTriggerObj (obj, TRIG_GRALL)) { p_percent_trigger (NULL, obj, NULL, ch, NULL, NULL, TRIG_GRALL); return; } } for (mob = ch->in_room->person_first; mob; mob = mob->next_in_room) { for (obj = mob->carrying_first; obj; obj = obj->next_content) { if (HasTriggerObj (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 (HasTriggerRoom (room, TRIG_GRALL)) p_percent_trigger (NULL, NULL, room, ch, NULL, NULL, TRIG_GRALL); } return; } void p_hprct_trigger (CharData * mob, CharData * ch) { ProgList *prg; for (prg = mob->pIndexData->mprog_first; prg != NULL; prg = prg->next) if ((prg->trig_type == TRIG_HPCNT) && ((100 * mob->hit / mob->max_hit) < atoi (prg->trig_phrase))) { program_flow (prg, mob, NULL, NULL, ch, NULL, NULL); break; } }