diff --git a/src/act.item.c b/src/act.item.c index 08d2746..9198ffe 100644 --- a/src/act.item.c +++ b/src/act.item.c @@ -52,11 +52,12 @@ static void wear_message(struct char_data *ch, struct obj_data *obj, int where); static void perform_put(struct char_data *ch, struct obj_data *obj, struct obj_data *cont) { + long object_id = obj_script_id(obj); if (!drop_otrigger(obj, ch)) return; - if (!obj) /* object might be extracted by drop_otrigger */ + if (!has_obj_by_uid_in_lookup_table(object_id)) /* object might be extracted by drop_otrigger */ return; if ((GET_OBJ_VAL(cont, 0) > 0) && @@ -409,24 +410,27 @@ static void perform_drop_gold(struct char_data *ch, int amount, byte mode, room_ WAIT_STATE(ch, PULSE_VIOLENCE); /* to prevent coin-bombing */ obj = create_money(amount); if (mode == SCMD_DONATE) { - send_to_char(ch, "You throw some gold into the air where it disappears in a puff of smoke!\r\n"); - act("$n throws some gold into the air where it disappears in a puff of smoke!", - FALSE, ch, 0, 0, TO_ROOM); - obj_to_room(obj, RDR); - act("$p suddenly appears in a puff of orange smoke!", 0, 0, obj, 0, TO_ROOM); + send_to_char(ch, "You throw some gold into the air where it disappears in a puff of smoke!\r\n"); + act("$n throws some gold into the air where it disappears in a puff of smoke!", + FALSE, ch, 0, 0, TO_ROOM); + obj_to_room(obj, RDR); + act("$p suddenly appears in a puff of orange smoke!", 0, 0, obj, 0, TO_ROOM); } else { char buf[MAX_STRING_LENGTH]; + long object_id = obj_script_id(obj); if (!drop_wtrigger(obj, ch)) { - extract_obj(obj); + if (has_obj_by_uid_in_lookup_table(object_id)) + extract_obj(obj); + return; } - snprintf(buf, sizeof(buf), "$n drops %s.", money_desc(amount)); - act(buf, TRUE, ch, 0, 0, TO_ROOM); + snprintf(buf, sizeof(buf), "$n drops %s.", money_desc(amount)); + act(buf, TRUE, ch, 0, 0, TO_ROOM); - send_to_char(ch, "You drop some gold.\r\n"); - obj_to_room(obj, IN_ROOM(ch)); + send_to_char(ch, "You drop some gold.\r\n"); + obj_to_room(obj, IN_ROOM(ch)); } } else { char buf[MAX_STRING_LENGTH]; @@ -447,13 +451,20 @@ static int perform_drop(struct char_data *ch, struct obj_data *obj, { char buf[MAX_STRING_LENGTH]; int value; + long object_id = obj_script_id(obj); if (!drop_otrigger(obj, ch)) return 0; + if (!has_obj_by_uid_in_lookup_table(object_id)) + return 0; // item was extracted by script + if ((mode == SCMD_DROP) && !drop_wtrigger(obj, ch)) return 0; + if (!has_obj_by_uid_in_lookup_table(object_id)) + return 0; // item was extracted by script + if (OBJ_FLAGGED(obj, ITEM_NODROP) && !PRF_FLAGGED(ch, PRF_NOHASSLE)) { snprintf(buf, sizeof(buf), "You can't %s $p, it must be CURSED!", sname); act(buf, FALSE, ch, obj, 0, TO_CHAR); diff --git a/src/dg_scripts.c b/src/dg_scripts.c index bbd5ca9..978cf6d 100644 --- a/src/dg_scripts.c +++ b/src/dg_scripts.c @@ -2994,12 +2994,23 @@ void init_lookup_table(void) } } -static struct char_data *find_char_by_uid_in_lookup_table(long uid) +static inline struct lookup_table_t *get_bucket_head(long uid) { int bucket = (int) (uid & (BUCKET_COUNT - 1)); - struct lookup_table_t *lt = &lookup_table[bucket]; + return &lookup_table[bucket]; +} + +static inline struct lookup_table_t *find_element_by_uid_in_lookup_table(long uid) +{ + struct lookup_table_t *lt = get_bucket_head(uid); for (;lt && lt->uid != uid ; lt = lt->next) ; + return lt; +} + +static struct char_data *find_char_by_uid_in_lookup_table(long uid) +{ + struct lookup_table_t *lt = find_element_by_uid_in_lookup_table(uid); if (lt) return (struct char_data *)(lt->c); @@ -3010,10 +3021,7 @@ static struct char_data *find_char_by_uid_in_lookup_table(long uid) static struct obj_data *find_obj_by_uid_in_lookup_table(long uid) { - int bucket = (int) (uid & (BUCKET_COUNT - 1)); - struct lookup_table_t *lt = &lookup_table[bucket]; - - for (;lt && lt->uid != uid ; lt = lt->next) ; + struct lookup_table_t *lt = find_element_by_uid_in_lookup_table(uid); if (lt) return (struct obj_data *)(lt->c); @@ -3022,10 +3030,16 @@ static struct obj_data *find_obj_by_uid_in_lookup_table(long uid) return NULL; } +int has_obj_by_uid_in_lookup_table(long uid) +{ + struct lookup_table_t *lt = find_element_by_uid_in_lookup_table(uid); + + return lt != NULL; +} + void add_to_lookup_table(long uid, void *c) { - int bucket = (int) (uid & (BUCKET_COUNT - 1)); - struct lookup_table_t *lt = &lookup_table[bucket]; + struct lookup_table_t *lt = get_bucket_head(uid); if (lt && lt->uid == uid) { log("add_to_lookup updating existing value for uid=%ld (%p -> %p)", uid, lt->c, c); @@ -3036,6 +3050,7 @@ void add_to_lookup_table(long uid, void *c) for (;lt && lt->next; lt = lt->next) if (lt->next->uid == uid) { log("add_to_lookup updating existing value for uid=%ld (%p -> %p)", uid, lt->next->c, c); + lt->next->c = c; return; } @@ -3054,9 +3069,7 @@ void remove_from_lookup_table(long uid) if (uid == 0) return; - for (;lt;lt = lt->next) - if (lt->uid == uid) - flt = lt; + flt = find_element_by_uid_in_lookup_table(uid); if (flt) { for (lt = &lookup_table[bucket];lt->next != flt;lt = lt->next) diff --git a/src/dg_scripts.h b/src/dg_scripts.h index 838b3f6..e860f02 100644 --- a/src/dg_scripts.h +++ b/src/dg_scripts.h @@ -449,6 +449,8 @@ void wld_command_interpreter(room_data *room, char *argument); // id helpers extern long char_script_id(char_data *ch); extern long obj_script_id(obj_data *obj); +extern int has_obj_by_uid_in_lookup_table(long uid); + #define room_script_id(room) ((long)(room)->number + ROOM_ID_BASE) #endif /* _DG_SCRIPTS_H_ */ diff --git a/src/dg_triggers.c b/src/dg_triggers.c index 1b6db8f..5a54d17 100644 --- a/src/dg_triggers.c +++ b/src/dg_triggers.c @@ -462,6 +462,7 @@ int receive_mtrigger(char_data *ch, char_data *actor, obj_data *obj) trig_data *t; char buf[MAX_INPUT_LENGTH]; int ret_val; + long object_id = obj_script_id(obj); if (!SCRIPT_CHECK(ch, MTRIG_RECEIVE) || AFF_FLAGGED(ch, AFF_CHARM)) return 1; @@ -471,9 +472,10 @@ int receive_mtrigger(char_data *ch, char_data *actor, obj_data *obj) (rand_number(1, 100) <= GET_TRIG_NARG(t))){ ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0); - ADD_UID_VAR(buf, t, obj_script_id(obj), "object", 0); + ADD_UID_VAR(buf, t, object_id, "object", 0); ret_val = script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW); - if (DEAD(actor) || DEAD(ch) || obj->carried_by != actor) + // check for purged item before dereferencing. + if (DEAD(actor) || DEAD(ch) || !has_obj_by_uid_in_lookup_table(object_id) || obj->carried_by != actor) return 0; else return ret_val; @@ -1118,6 +1120,7 @@ int drop_wtrigger(obj_data *obj, char_data *actor) trig_data *t; char buf[MAX_INPUT_LENGTH]; int ret_val; + long object_id = obj_script_id(obj); if (!actor || !SCRIPT_CHECK(&world[IN_ROOM(actor)], WTRIG_DROP)) return 1; @@ -1127,9 +1130,10 @@ int drop_wtrigger(obj_data *obj, char_data *actor) if (TRIGGER_CHECK(t, WTRIG_DROP) && (rand_number(1, 100) <= GET_TRIG_NARG(t))) { ADD_UID_VAR(buf, t, char_script_id(actor), "actor", 0); - ADD_UID_VAR(buf, t, obj_script_id(obj), "object", 0); + ADD_UID_VAR(buf, t, object_id, "object", 0); ret_val = script_driver(&room, t, WLD_TRIGGER, TRIG_NEW); - if (obj->carried_by != actor) + // check for purged object before dereferencing. + if (!has_obj_by_uid_in_lookup_table(object_id) || obj->carried_by != actor) return 0; else return ret_val;