Remove crash bug when purging a dropped item in a wtrigger.

We're leveraging the lookup table, because it's a safer way
to see if an object has been free'd than looking at the object
itself (which while it may work may just as well fail).

Fixes #83
This commit is contained in:
Thomas Arp 2020-03-01 01:19:06 +01:00
parent 140cdc5d22
commit d5a11618f1
3 changed files with 40 additions and 19 deletions

View file

@ -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);

View file

@ -2994,12 +2994,18 @@ void init_lookup_table(void)
}
}
static struct char_data *find_char_by_uid_in_lookup_table(long uid)
static struct lookup_table_t *find_element_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) ;
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 +3016,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,6 +3025,13 @@ 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));
@ -3054,9 +3064,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)

View file

@ -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_ */