From d639310ae112c8031f132c251da7845498bb5961 Mon Sep 17 00:00:00 2001 From: Enno Rehling <enno@eressea.de> Date: Sat, 9 Sep 2023 07:03:30 +0200 Subject: [PATCH] fix a crash caused by new weapons code --- src/battle.c | 24 ++++++++++++++---------- src/battle.h | 7 +++++-- src/battle.test.c | 16 ++++++++-------- src/items/weapons.c | 4 ++-- src/spells/combatspells.c | 7 ++++--- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/battle.c b/src/battle.c index 195fc3ff3..33098abe5 100644 --- a/src/battle.c +++ b/src/battle.c @@ -665,9 +665,9 @@ weapon_effskill(troop t, troop enemy, const weapon * w, fighter *tf = t.fighter; unit *tu = t.fighter->unit; /* Alle Modifier berechnen, die fig durch die Waffen bekommt. */ - if (w) { + if (w && w->item.type) { int skill = 0; - const weapon_type *wtype = WEAPON_TYPE(w); + const weapon_type *wtype = resource2weapon(w->item.type->rtype); if (attacking) { skill = w->attackskill; @@ -1941,9 +1941,12 @@ static int setreload(troop at) { fighter *af = at.fighter; const weapon_type *wtype = WEAPON_TYPE(af->person[at.index].missile); - if (wtype->reload == 0) - return 0; - return af->person[at.index].reload = wtype->reload; + if (wtype) { + if (wtype->reload != 0) { + return af->person[at.index].reload = wtype->reload; + } + } + return 0; } int getreload(troop at) @@ -3113,7 +3116,7 @@ static void equip_weapons(fighter* fig) wp = arraddnptr(fig->weapons, 1); wp->attackskill = weapon_skill(wtype, u, true); wp->defenseskill = weapon_skill(wtype, u, false); - wp->item = itm; + wp->item.ref = itm; } w = arrlen(fig->weapons); qsort(fig->weapons, w, sizeof(weapon), cmp_weapon); @@ -3122,11 +3125,12 @@ static void equip_weapons(fighter* fig) /* hand out weapons: */ for (i = 0; i != w; ++i) { - const weapon *wp = fig->weapons + i; - const weapon_type *wtype = WEAPON_TYPE(wp); + weapon *wp = fig->weapons + i; + const item *itm = wp->item.ref; + const weapon_type *wtype = resource2weapon(item2resource(itm->type)); bool is_missile; assert(wtype); - + wp->item.type = itm->type; is_missile = (wtype->flags & WTF_MISSILE); if (!is_missile && wpless > wp->attackskill + wp->defenseskill) { /* we fight better with bare hands than this melee weapon */ @@ -3146,7 +3150,7 @@ static void equip_weapons(fighter* fig) } if (wp->attackskill >= 0 || wp->defenseskill >= 0) { - int count = wp->item->number; + int count = itm->number; while (count > 0 && (p_missile < fig->alive || p_melee < fig->alive)) { if (is_missile) { if (p_missile < fig->alive) { diff --git a/src/battle.h b/src/battle.h index 3929b6336..b53b62abb 100644 --- a/src/battle.h +++ b/src/battle.h @@ -96,12 +96,15 @@ typedef struct battle { } battle; typedef struct weapon { - const struct item* item; + union { + struct item *ref; + const struct item_type *type; + } item; int attackskill; int defenseskill; } weapon; -#define WEAPON_TYPE(wp) ((wp) ? (wp)->item->type->rtype->wtype : NULL) +#define WEAPON_TYPE(wp) ((wp && (wp)->item.type) ? (wp)->item.type->rtype->wtype : NULL) typedef struct troop { struct fighter* fighter; diff --git a/src/battle.test.c b/src/battle.test.c index 24574fa86..9de185d19 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -124,12 +124,12 @@ static void test_select_weapon(CuTest *tc) { b = make_battle(au->region); af = make_fighter(b, au, make_side(b, au->faction, 0, 0, 0), false); CuAssertIntEquals(tc, 3, (int)arrlen(af->weapons)); - CuAssertPtrEquals(tc, i_axe, (item *)af->person[0].melee->item); + CuAssertPtrEquals(tc, it_axe, (item_type *)af->person[0].melee->item.type); CuAssertPtrEquals(tc, NULL, (weapon *)af->person[0].missile); - CuAssertPtrEquals(tc, i_sword, (item *)af->person[1].melee->item); - CuAssertPtrEquals(tc, i_missile, (item *)af->person[1].missile->item); + CuAssertPtrEquals(tc, it_sword, (item_type *)af->person[1].melee->item.type); + CuAssertPtrEquals(tc, it_missile, (item_type *)af->person[1].missile->item.type); CuAssertPtrEquals(tc, NULL, (weapon *)af->person[2].melee); - CuAssertPtrEquals(tc, i_missile, (item *)af->person[2].missile->item); + CuAssertPtrEquals(tc, it_missile, (item_type *)af->person[2].missile->item.type); free_battle(b); test_teardown(); @@ -154,7 +154,7 @@ static void test_select_weapon_restricted(CuTest *tc) { b = make_battle(au->region); af = make_fighter(b, au, make_side(b, au->faction, 0, 0, 0), false); CuAssertIntEquals(tc, 1, (int)arrlen(af->weapons)); - CuAssertPtrEquals(tc, au->items, (void *)af->weapons[0].item); + CuAssertPtrEquals(tc, (item_type *)au->items->type, (item_type *)af->weapons[0].item.type); CuAssertPtrEquals(tc, af->weapons, (void *)af->person[0].melee); free_battle(b); @@ -163,7 +163,7 @@ static void test_select_weapon_restricted(CuTest *tc) { b = make_battle(au->region); af = make_fighter(b, au, make_side(b, au->faction, 0, 0, 0), false); CuAssertIntEquals(tc, 1, (int)arrlen(af->weapons)); - CuAssertPtrEquals(tc, au->items, (void *)af->weapons[0].item); + CuAssertPtrEquals(tc, (item_type *)au->items->type, (item_type *)af->weapons[0].item.type); CuAssertPtrNotNull(tc, af->person); CuAssertPtrEquals(tc, NULL, (void *)af->person[0].melee); free_battle(b); @@ -175,7 +175,7 @@ static void test_select_weapon_restricted(CuTest *tc) { af = make_fighter(b, au, make_side(b, au->faction, 0, 0, 0), false); CuAssertPtrNotNull(tc, af->weapons); CuAssertIntEquals(tc, 1, (int)arrlen(af->weapons)); - CuAssertPtrEquals(tc, au->items, (void *)af->weapons[0].item); + CuAssertPtrEquals(tc, (item_type *)au->items->type, (item_type *)af->weapons[0].item.type); CuAssertPtrEquals(tc, af->weapons, (void *)af->person[0].melee); free_battle(b); @@ -185,7 +185,7 @@ static void test_select_weapon_restricted(CuTest *tc) { b = make_battle(au->region); af = make_fighter(b, au, make_side(b, au->faction, 0, 0, 0), false); CuAssertIntEquals(tc, 1, (int)arrlen(af->weapons)); - CuAssertPtrEquals(tc, au->items, (void *)af->weapons[0].item); + CuAssertPtrEquals(tc, (item_type *)au->items->type, (void *)af->weapons[0].item.type); CuAssertPtrEquals(tc, NULL, (void *)af->person[0].melee); free_battle(b); diff --git a/src/items/weapons.c b/src/items/weapons.c index 168bd61f5..23805e5c5 100644 --- a/src/items/weapons.c +++ b/src/items/weapons.c @@ -43,7 +43,7 @@ int *casualties) message *msg; for (i = 0; i <= at->index; ++i) { const weapon *wp = fi->person[i].melee; - if (wp != NULL && wp->item->type == wtype->itype) + if (WEAPON_TYPE(wp) == wtype) ++k; } msg = msg_message("useflamingsword", "amount unit", k, fi->unit); @@ -103,7 +103,7 @@ int *casualties) message *msg; for (i = 0; i <= at->index; ++i) { - if (af->person[i].reload == 0 && af->person[i].missile->item->type == wtype->itype) + if (af->person[i].reload == 0 && WEAPON_TYPE(af->person[i].missile) == wtype) ++k; } msg = msg_message("usecatapult", "amount unit", k, au); diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 2a0c51cf0..7bfc49df9 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -287,10 +287,11 @@ int sp_combatrosthauch(struct castorder * co) for (w = 0; w != len; ++w) { weapon *wp = df->weapons; if (df->unit->items && force > 0) { - item ** itp = i_find(&df->unit->items, wp->item->type); + const item_type *itype = wp->item.type; + item ** itp = i_find(&df->unit->items, itype); if (*itp) { item *it = *itp; - requirement *mat = wp->item->type->construction->materials; + requirement *mat = itype->construction->materials; int n = force; if (it->number < n) n = it->number; @@ -299,7 +300,7 @@ int sp_combatrosthauch(struct castorder * co) int p; force -= n; k += n; - i_change(itp, wp->item->type, -n); + i_change(itp, itype, -n); for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].melee == wp) { df->person[p].melee = NULL;