diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 59629bc61..ddc8e0e4a 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -439,7 +439,9 @@ int remove_unit(unit ** ulist, unit * u) } if (u->faction) { - --u->faction->num_units; + if (count_unit(u)) { + --u->faction->num_units; + } if (u->faction->units == u) { u->faction->units = u->nextF; } @@ -1128,12 +1130,13 @@ struct building *inside_building(const struct unit *u) void u_setfaction(unit * u, faction * f) { - int cnt = u->number; if (u->faction == f) return; if (u->faction) { - --u->faction->num_units; - set_number(u, 0); + if (count_unit(u)) { + --u->faction->num_units; + u->faction->num_people -= u->number; + } join_group(u, NULL); free_orders(&u->orders); set_order(&u->thisorder, NULL); @@ -1165,14 +1168,19 @@ void u_setfaction(unit * u, faction * f) if (u->region) { update_interval(f, u->region); } - if (cnt) { - set_number(u, cnt); - } - if (f) { + if (f && count_unit(u)) { ++f->num_units; + f->num_people += u->number; } } +bool count_unit(const unit *u) +{ + const race *rc = u_race(u); + /* spells are invisible. units we cannot see do not count to our limit */ + return rc == NULL || (rc->flags & RCF_INVISIBLE) == 0; +} + void set_number(unit * u, int count) { assert(count >= 0); @@ -1181,10 +1189,10 @@ void set_number(unit * u, int count) if (count == 0) { u->flags &= ~(UFL_HERO); } - if (u->faction) { + if (u->faction && count_unit(u)) { u->faction->num_people += count - u->number; } - u->number = (unsigned short)count; + u->number = count; } void remove_skill(unit * u, skill_t sk) @@ -1487,6 +1495,8 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace, unit *u = (unit *)calloc(1, sizeof(unit)); assert(urace); + u_setrace(u, urace); + u->irace = NULL; if (f) { assert(faction_alive(f)); u_setfaction(u, f); @@ -1499,8 +1509,6 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace, } } } - u_setrace(u, urace); - u->irace = NULL; set_number(u, number); @@ -1806,7 +1814,23 @@ const struct race *u_race(const struct unit *u) void u_setrace(struct unit *u, const struct race *rc) { assert(rc); - u->_race = rc; + if (!u->faction) { + u->_race = rc; + } + else { + int n = 0; + if (count_unit(u)) { + --n; + } + u->_race = rc; + if (count_unit(u)) { + ++n; + } + if (n != 0) { + u->faction->num_units += n; + u->faction->num_people += n * u->number; + } + } } void unit_add_spell(unit * u, sc_mage * m, struct spell * sp, int level) diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 14096c872..8ae13c5e2 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -130,6 +130,7 @@ extern "C" { int weight(const struct unit *u); void renumber_unit(struct unit *u, int no); + bool count_unit(const unit *u); /* unit counts towards faction.num_units and faction.num_people */ const struct race *u_irace(const struct unit *u); const struct race *u_race(const struct unit *u); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 3932bb239..caa8a9b5c 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -531,7 +531,7 @@ static void test_unlimited_units(CuTest *tc) { CuAssertIntEquals(tc, 0, f->num_units); CuAssertIntEquals(tc, 0, f->num_people); u = test_create_unit(f, test_create_region(0, 0, NULL)); -// CuAssertTrue(tc, count_unit(u)); + CuAssertTrue(tc, count_unit(u)); CuAssertIntEquals(tc, 1, f->num_units); CuAssertIntEquals(tc, 1, f->num_people); u_setfaction(u, NULL); @@ -541,6 +541,7 @@ static void test_unlimited_units(CuTest *tc) { CuAssertIntEquals(tc, 1, f->num_units); CuAssertIntEquals(tc, 1, f->num_people); u_setrace(u, rc); + CuAssertTrue(tc, !count_unit(u)); CuAssertIntEquals(tc, 0, f->num_units); CuAssertIntEquals(tc, 0, f->num_people); scale_number(u, 10); @@ -549,6 +550,9 @@ static void test_unlimited_units(CuTest *tc) { u_setrace(u, f->race); CuAssertIntEquals(tc, 1, f->num_units); CuAssertIntEquals(tc, 10, f->num_people); + remove_unit(&u->region->units, u); + CuAssertIntEquals(tc, 0, f->num_units); + CuAssertIntEquals(tc, 0, f->num_people); test_cleanup(); }