forked from github/server
limited-skill units are only transferred up to the limit.
This commit is contained in:
parent
6637c94852
commit
8605409ed3
12 changed files with 126 additions and 24 deletions
|
@ -548,7 +548,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
|||
return;
|
||||
}
|
||||
if (has_skill(u, SK_ALCHEMY)) {
|
||||
if (count_skill(u->faction, SK_ALCHEMY) + n > skill_limit(u->faction, SK_ALCHEMY)) {
|
||||
if (faction_count_skill(u->faction, SK_ALCHEMY) + n > faction_skill_limit(u->faction, SK_ALCHEMY)) {
|
||||
cmistake(u, ord, 156, MSG_EVENT);
|
||||
return;
|
||||
}
|
||||
|
|
12
src/give.c
12
src/give.c
|
@ -391,7 +391,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
|
|||
}
|
||||
|
||||
if (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY)) {
|
||||
int k = count_skill(u2->faction, SK_ALCHEMY);
|
||||
int k = faction_count_skill(u2->faction, SK_ALCHEMY);
|
||||
|
||||
/* Falls die Zieleinheit keine Alchemisten sind, werden sie nun
|
||||
* welche. */
|
||||
|
@ -408,7 +408,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
|
|||
|
||||
/* wird das Alchemistenmaximum ueberschritten ? */
|
||||
|
||||
if (k > skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
if (k > faction_skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
error = 156;
|
||||
}
|
||||
}
|
||||
|
@ -592,8 +592,8 @@ void give_unit(unit * u, unit * u2, order * ord)
|
|||
}
|
||||
}
|
||||
if (has_skill(u, SK_MAGIC)) {
|
||||
if (count_skill(u2->faction, SK_MAGIC) + u->number >
|
||||
skill_limit(u2->faction, SK_MAGIC)) {
|
||||
if (faction_count_skill(u2->faction, SK_MAGIC) + u->number >
|
||||
faction_skill_limit(u2->faction, SK_MAGIC)) {
|
||||
cmistake(u, ord, 155, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
|
@ -603,8 +603,8 @@ void give_unit(unit * u, unit * u2, order * ord)
|
|||
}
|
||||
}
|
||||
if (has_skill(u, SK_ALCHEMY)
|
||||
&& count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
||||
skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
&& faction_count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
||||
faction_skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
cmistake(u, ord, 156, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -572,7 +572,7 @@ static int build_limited(unit * u, const construction * con, int completed, int
|
|||
}
|
||||
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
|
||||
* Talente */
|
||||
if (skill_limit(u->faction, con->skill) == INT_MAX) {
|
||||
if (faction_skill_limit(u->faction, con->skill) == INT_MAX) {
|
||||
const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
|
||||
item *itm = ring ? *i_find(&u->items, ring->itype) : 0;
|
||||
int i = itm ? itm->number : 0;
|
||||
|
|
|
@ -609,7 +609,7 @@ static int allied_skillcount(const faction * f, skill_t sk)
|
|||
|
||||
for (qi = 0; members; selist_advance(&members, &qi, 1)) {
|
||||
faction *m = (faction *)selist_get(members, qi);
|
||||
num += count_skill(m, sk);
|
||||
num += faction_count_skill(m, sk);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ static int allied_skilllimit(const faction * f, skill_t sk)
|
|||
return value;
|
||||
}
|
||||
|
||||
int count_skill(faction * f, skill_t sk)
|
||||
int faction_count_skill(faction * f, skill_t sk)
|
||||
{
|
||||
int n = 0;
|
||||
unit *u;
|
||||
|
@ -638,7 +638,7 @@ int count_skill(faction * f, skill_t sk)
|
|||
return n;
|
||||
}
|
||||
|
||||
int skill_limit(faction * f, skill_t sk)
|
||||
int faction_skill_limit(const faction * f, skill_t sk)
|
||||
{
|
||||
int m = INT_MAX;
|
||||
int al = allied_skilllimit(f, sk);
|
||||
|
|
|
@ -161,8 +161,8 @@ extern "C" {
|
|||
struct spellbook * faction_get_spellbook(struct faction *f);
|
||||
|
||||
/* skills */
|
||||
int skill_limit(struct faction *f, skill_t sk);
|
||||
int count_skill(struct faction *f, skill_t sk);
|
||||
int faction_skill_limit(const struct faction *f, skill_t sk);
|
||||
int faction_count_skill(struct faction *f, skill_t sk);
|
||||
bool faction_id_is_unused(int);
|
||||
|
||||
#define COUNT_MONSTERS 0x01
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
static void test_destroyfaction_allies(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
|
@ -211,6 +212,26 @@ static void test_max_migrants(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_skill_limit(CuTest *tc) {
|
||||
faction *f;
|
||||
|
||||
test_setup();
|
||||
f = test_create_faction(NULL);
|
||||
CuAssertIntEquals(tc, INT_MAX, faction_skill_limit(f, SK_ENTERTAINMENT));
|
||||
CuAssertIntEquals(tc, 3, faction_skill_limit(f, SK_ALCHEMY));
|
||||
config_set_int("rules.maxskills.alchemy", 4);
|
||||
CuAssertIntEquals(tc, 4, faction_skill_limit(f, SK_ALCHEMY));
|
||||
CuAssertIntEquals(tc, 3, faction_skill_limit(f, SK_MAGIC));
|
||||
CuAssertIntEquals(tc, 3, max_magicians(f));
|
||||
config_set_int("rules.maxskills.magic", 4);
|
||||
CuAssertIntEquals(tc, 4, faction_skill_limit(f, SK_MAGIC));
|
||||
CuAssertIntEquals(tc, 4, max_magicians(f));
|
||||
f->race = test_create_race(racenames[RC_ELF]);
|
||||
CuAssertIntEquals(tc, 5, faction_skill_limit(f, SK_MAGIC));
|
||||
CuAssertIntEquals(tc, 5, max_magicians(f));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_valid_race(CuTest *tc) {
|
||||
race * rc1, *rc2;
|
||||
faction *f;
|
||||
|
@ -334,6 +355,7 @@ CuSuite *get_faction_suite(void)
|
|||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_addplayer);
|
||||
SUITE_ADD_TEST(suite, test_max_migrants);
|
||||
SUITE_ADD_TEST(suite, test_skill_limit);
|
||||
SUITE_ADD_TEST(suite, test_addfaction);
|
||||
SUITE_ADD_TEST(suite, test_remove_empty_factions);
|
||||
SUITE_ADD_TEST(suite, test_destroyfaction_allies);
|
||||
|
|
|
@ -1812,17 +1812,27 @@ int maintenance_cost(const struct unit *u)
|
|||
return u_race(u)->maintenance * u->number;
|
||||
}
|
||||
|
||||
static skill_t limited_skills[] = { SK_MAGIC, SK_ALCHEMY, SK_TACTICS, SK_SPY, SK_HERBALISM, NOSKILL };
|
||||
static skill_t limited_skills[] = { SK_ALCHEMY, SK_HERBALISM, SK_MAGIC, SK_SPY, SK_TACTICS, NOSKILL };
|
||||
|
||||
bool is_limited_skill(skill_t sk)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; limited_skills[i] != NOSKILL; ++i) {
|
||||
if (sk == limited_skills[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_limited_skills(const struct unit * u)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
skill *sv = u->skills + i;
|
||||
for (j = 0; limited_skills[j] != NOSKILL; ++j) {
|
||||
if (sv->id == limited_skills[j]) {
|
||||
return true;
|
||||
}
|
||||
if (is_limited_skill(sv->id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -251,6 +251,7 @@ extern "C" {
|
|||
bool has_horses(const struct unit *u);
|
||||
int maintenance_cost(const struct unit *u);
|
||||
bool has_limited_skills(const struct unit *u);
|
||||
bool is_limited_skill(skill_t sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
34
src/laws.c
34
src/laws.c
|
@ -943,8 +943,42 @@ int leave_cmd(unit * u, struct order *ord)
|
|||
|
||||
void transfer_faction(faction *fsrc, faction *fdst) {
|
||||
unit *u;
|
||||
skill_t sk;
|
||||
int skill_count[MAXSKILLS];
|
||||
int skill_limit[MAXSKILLS];
|
||||
|
||||
for (sk = 0; sk != MAXSKILLS; ++sk) {
|
||||
skill_limit[sk] = faction_skill_limit(fdst, sk);
|
||||
}
|
||||
memset(skill_count, 0, sizeof(skill_count));
|
||||
|
||||
for (u = fdst->units; u != NULL; u = u->nextF) {
|
||||
if (u->skills) {
|
||||
int i;
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
const skill *sv = u->skills + i;
|
||||
skill_t sk = (skill_t)sv->id;
|
||||
skill_count[sk] += u->number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u = fsrc->units; u != NULL; u = u->nextF) {
|
||||
if (give_unit_allowed(u) == 0) {
|
||||
if (u->skills) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
const skill *sv = u->skills + i;
|
||||
skill_t sk = (skill_t)sv->id;
|
||||
if (skill_count[sk] + u->number > skill_limit[sk]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != u->skill_size) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
u_setfaction(u, fdst);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1912,6 +1912,40 @@ static void test_quit_transfer(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_quit_transfer_limited(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
unit *u1, *u2;
|
||||
region *r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_plain(0, 0);
|
||||
f1 = test_create_faction(NULL);
|
||||
faction_setpassword(f1, "password");
|
||||
u1 = test_create_unit(f1, r);
|
||||
f2 = test_create_faction(NULL);
|
||||
u2 = test_create_unit(f2, r);
|
||||
contact_unit(u2, u1);
|
||||
u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s",
|
||||
LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no));
|
||||
|
||||
set_level(u1, SK_MAGIC, 1);
|
||||
set_level(u2, SK_MAGIC, 1);
|
||||
CuAssertIntEquals(tc, true, has_limited_skills(u1));
|
||||
|
||||
config_set_int("rules.maxskills.magic", 1);
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f1, u1->faction);
|
||||
|
||||
f1->flags -= FFL_QUIT;
|
||||
config_set_int("rules.maxskills.magic", 2);
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f2, u1->faction);
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
CuSuite *get_laws_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -1989,6 +2023,7 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_long_order_on_ocean);
|
||||
SUITE_ADD_TEST(suite, test_quit);
|
||||
SUITE_ADD_TEST(suite, test_quit_transfer);
|
||||
SUITE_ADD_TEST(suite, test_quit_transfer_limited);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -3451,7 +3451,7 @@ static bool can_charm(const unit * u, int maxlevel)
|
|||
while (l < h) {
|
||||
int m = (l + h) / 2;
|
||||
if (sk == expskills[m]) {
|
||||
if (skill_limit(u->faction, sk) != INT_MAX) {
|
||||
if (faction_skill_limit(u->faction, sk) != INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
else if ((int)sv->level > maxlevel) {
|
||||
|
|
|
@ -635,9 +635,9 @@ int study_cmd(unit * u, order * ord)
|
|||
mtype = M_GRAY;
|
||||
}
|
||||
else if (!has_skill(u, SK_MAGIC)) {
|
||||
int mmax = skill_limit(u->faction, SK_MAGIC);
|
||||
int mmax = faction_skill_limit(u->faction, SK_MAGIC);
|
||||
/* Die Einheit ist noch kein Magier */
|
||||
if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) {
|
||||
if (faction_count_skill(u->faction, SK_MAGIC) + u->number > mmax) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians",
|
||||
"amount", mmax));
|
||||
return -1;
|
||||
|
@ -694,8 +694,8 @@ int study_cmd(unit * u, order * ord)
|
|||
if (sk == SK_ALCHEMY) {
|
||||
maxalchemy = effskill(u, SK_ALCHEMY, NULL);
|
||||
if (!has_skill(u, SK_ALCHEMY)) {
|
||||
int amax = skill_limit(u->faction, SK_ALCHEMY);
|
||||
if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
|
||||
int amax = faction_skill_limit(u->faction, SK_ALCHEMY);
|
||||
if (faction_count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists",
|
||||
"amount", amax));
|
||||
return -1;
|
||||
|
|
Loading…
Reference in a new issue