From 85e35cc294d844ebbefbb9de594b6c110df9796a Mon Sep 17 00:00:00 2001 From: Eric Branlund Date: Sun, 2 Jun 2024 22:57:38 -0600 Subject: [PATCH] Deeply copy blows for player ghost Avoids modifying blows of the base race when creating a ghost. --- src/mon-init.c | 6 ++++++ src/mon-make.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/mon-init.c b/src/mon-init.c index a59557aaa..66f61d52d 100644 --- a/src/mon-init.c +++ b/src/mon-init.c @@ -1906,6 +1906,12 @@ static void cleanup_monster(void) mem_free(r->blow); } + /* + * Melee blows for the ghost race have to be freed. The rest of it + * is a shallow copy of one of the other races. + */ + mem_free(r_info[z_info->r_max - 1].blow); + mem_free(r_info); } diff --git a/src/mon-make.c b/src/mon-make.c index ce70aaa56..104547163 100644 --- a/src/mon-make.c +++ b/src/mon-make.c @@ -712,6 +712,7 @@ bool prepare_ghost(struct chunk *c, int r_idx, struct monster *mon, { int ghost_race, ghost_class = 0; uint8_t try, i; + uint16_t iblow; struct monster_race *race = &r_info[r_idx]; struct monster_lore *lore = get_lore(race); @@ -739,8 +740,18 @@ bool prepare_ghost(struct chunk *c, int r_idx, struct monster *mon, c->ghost->race = r_idx; /* Copy the info from the template to the special "ghost slot", and use - * that from here on */ + * that from here on. Melee blows have to be deeply copied so those of + * the base race are not modified. */ + mem_free(r_info[PLAYER_GHOST_RACE].blow); memcpy(&r_info[PLAYER_GHOST_RACE], race, sizeof(*race)); + r_info[PLAYER_GHOST_RACE].blow = mem_alloc(z_info->mon_blows_max + * sizeof(*r_info[PLAYER_GHOST_RACE].blow)); + for (iblow = 0; iblow < z_info->mon_blows_max; ++iblow) { + r_info[PLAYER_GHOST_RACE].blow[iblow] = race->blow[iblow]; + r_info[PLAYER_GHOST_RACE].blow[iblow].next = + (iblow < z_info->mon_blows_max - 1) ? + r_info[PLAYER_GHOST_RACE].blow + iblow + 1 : NULL; + } race = &r_info[PLAYER_GHOST_RACE]; mon->race = race; @@ -1229,6 +1240,7 @@ void wipe_mon_list(struct chunk *c, struct player *p) } /* Delete the player ghost record completely */ + mem_free(r_info[PLAYER_GHOST_RACE].blow); memset(&r_info[PLAYER_GHOST_RACE], 0, sizeof(struct monster_race)); /* Delete all the monster groups */