forked from github/server
Merge branch '2541-quit' into develop
This commit is contained in:
commit
5c7788ecdd
|
@ -2937,13 +2937,6 @@
|
||||||
<arg name="command" type="order"/>
|
<arg name="command" type="order"/>
|
||||||
</type>
|
</type>
|
||||||
</message>
|
</message>
|
||||||
<message name="error282" section="errors">
|
|
||||||
<type>
|
|
||||||
<arg name="unit" type="unit"/>
|
|
||||||
<arg name="region" type="region"/>
|
|
||||||
<arg name="command" type="order"/>
|
|
||||||
</type>
|
|
||||||
</message>
|
|
||||||
<message name="error281" section="errors">
|
<message name="error281" section="errors">
|
||||||
<type>
|
<type>
|
||||||
<arg name="unit" type="unit"/>
|
<arg name="unit" type="unit"/>
|
||||||
|
@ -3244,13 +3237,6 @@
|
||||||
<arg name="target" type="region"/>
|
<arg name="target" type="region"/>
|
||||||
</type>
|
</type>
|
||||||
</message>
|
</message>
|
||||||
<message name="error241" section="errors">
|
|
||||||
<type>
|
|
||||||
<arg name="unit" type="unit"/>
|
|
||||||
<arg name="region" type="region"/>
|
|
||||||
<arg name="command" type="order"/>
|
|
||||||
</type>
|
|
||||||
</message>
|
|
||||||
<message name="error240" section="errors">
|
<message name="error240" section="errors">
|
||||||
<type>
|
<type>
|
||||||
<arg name="unit" type="unit"/>
|
<arg name="unit" type="unit"/>
|
||||||
|
|
|
@ -587,9 +587,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Unbekannte Opti
|
||||||
msgid "error131"
|
msgid "error131"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletschern Straßen bauen zu können, muß zuerst ein Tunnel errichtet werden.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletschern Straßen bauen zu können, muß zuerst ein Tunnel errichtet werden.\""
|
||||||
|
|
||||||
msgid "error241"
|
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 81 Wochen alt sein, um einen Neustart mit einer anderen Rasse zu versuchen.\""
|
|
||||||
|
|
||||||
msgid "feedback_unit_not_found"
|
msgid "feedback_unit_not_found"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\""
|
||||||
|
|
||||||
|
@ -1119,7 +1116,7 @@ msgid "dissolve_units_4"
|
||||||
msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),\"zerfiel\", \"zerfielen\") zu Staub.\""
|
msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),\"zerfiel\", \"zerfielen\") zu Staub.\""
|
||||||
|
|
||||||
msgid "error281"
|
msgid "error281"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Gegen welche Rasse soll der Jihad ausgerufen werden?\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Zielpartei muss die selbe Rasse haben.\""
|
||||||
|
|
||||||
msgid "error171"
|
msgid "error171"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Diesen Kampfzauber gibt es nicht.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Diesen Kampfzauber gibt es nicht.\""
|
||||||
|
@ -1784,9 +1781,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Es konnte kein
|
||||||
msgid "error50"
|
msgid "error50"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafür.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafür.\""
|
||||||
|
|
||||||
msgid "error282"
|
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Gegen diese Rasse kann kein Jihad ausgerufen werden.\""
|
|
||||||
|
|
||||||
msgid "nmr_warning_final"
|
msgid "nmr_warning_final"
|
||||||
msgstr "\"Bitte sende die Befehle nächste Runde ein, wenn du weiterspielen möchtest.\""
|
msgstr "\"Bitte sende die Befehle nächste Runde ein, wenn du weiterspielen möchtest.\""
|
||||||
|
|
||||||
|
|
|
@ -587,9 +587,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Unknown option.
|
||||||
msgid "error131"
|
msgid "error131"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build a tunnel before building roads through glaciers.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build a tunnel before building roads through glaciers.\""
|
||||||
|
|
||||||
msgid "error241"
|
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The faction must be at least 81 weeks old to restart with a new race.\""
|
|
||||||
|
|
||||||
msgid "feedback_unit_not_found"
|
msgid "feedback_unit_not_found"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\""
|
||||||
|
|
||||||
|
@ -1119,7 +1116,7 @@ msgid "dissolve_units_4"
|
||||||
msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) turned to dust.\""
|
msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) turned to dust.\""
|
||||||
|
|
||||||
msgid "error281"
|
msgid "error281"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - What race did you want the jihad to be against?\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The target faction must have the same race as yours.\""
|
||||||
|
|
||||||
msgid "error171"
|
msgid "error171"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - This combat spell does not exist.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - This combat spell does not exist.\""
|
||||||
|
@ -1784,9 +1781,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - No peasant coul
|
||||||
msgid "error50"
|
msgid "error50"
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not experienced enough to do this.\""
|
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not experienced enough to do this.\""
|
||||||
|
|
||||||
msgid "error282"
|
|
||||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - You cannot start a jihad against this race.\""
|
|
||||||
|
|
||||||
msgid "nmr_warning_final"
|
msgid "nmr_warning_final"
|
||||||
msgstr "\"Please send in orders for the next turn if you want to continue playing.\""
|
msgstr "\"Please send in orders for the next turn if you want to continue playing.\""
|
||||||
|
|
||||||
|
|
|
@ -548,7 +548,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (has_skill(u, SK_ALCHEMY)) {
|
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);
|
cmistake(u, ord, 156, MSG_EVENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
44
src/give.c
44
src/give.c
|
@ -299,7 +299,7 @@ static bool can_give_men(const unit *u, const unit *dst, order *ord, message **m
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rule_transfermen(void)
|
bool rule_transfermen(void)
|
||||||
{
|
{
|
||||||
int rule = config_get_int("rules.transfermen", 1);
|
int rule = config_get_int("rules.transfermen", 1);
|
||||||
return rule != 0;
|
return rule != 0;
|
||||||
|
@ -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)) {
|
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
|
/* Falls die Zieleinheit keine Alchemisten sind, werden sie nun
|
||||||
* welche. */
|
* welche. */
|
||||||
|
@ -408,7 +408,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
|
||||||
|
|
||||||
/* wird das Alchemistenmaximum ueberschritten ? */
|
/* wird das Alchemistenmaximum ueberschritten ? */
|
||||||
|
|
||||||
if (k > skill_limit(u2->faction, SK_ALCHEMY)) {
|
if (k > faction_skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||||
error = 156;
|
error = 156;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,9 +472,23 @@ message * disband_men(int n, unit * u, struct order *ord) {
|
||||||
return msg_message("give_person_peasants", "unit amount", u, n);
|
return msg_message("give_person_peasants", "unit amount", u, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int give_unit_allowed(const unit * u)
|
||||||
|
{
|
||||||
|
if (unit_has_cursed_item(u)) {
|
||||||
|
return 78;
|
||||||
|
}
|
||||||
|
if (fval(u, UFL_HERO)) {
|
||||||
|
return 75;
|
||||||
|
}
|
||||||
|
if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) {
|
||||||
|
return 74;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void give_unit(unit * u, unit * u2, order * ord)
|
void give_unit(unit * u, unit * u2, order * ord)
|
||||||
{
|
{
|
||||||
int maxt = max_transfers();
|
int err, maxt = max_transfers();
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
if (!rule_transfermen() && u2 && u->faction != u2->faction) {
|
if (!rule_transfermen() && u2 && u->faction != u2->faction) {
|
||||||
|
@ -482,17 +496,9 @@ void give_unit(unit * u, unit * u2, order * ord)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unit_has_cursed_item(u)) {
|
err = give_unit_allowed(u);
|
||||||
cmistake(u, ord, 78, MSG_COMMERCE);
|
if (err != 0) {
|
||||||
return;
|
cmistake(u, ord, err, MSG_COMMERCE);
|
||||||
}
|
|
||||||
|
|
||||||
if (fval(u, UFL_HERO)) {
|
|
||||||
cmistake(u, ord, 75, MSG_COMMERCE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) {
|
|
||||||
cmistake(u, ord, 74, MSG_COMMERCE);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,8 +592,8 @@ void give_unit(unit * u, unit * u2, order * ord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_skill(u, SK_MAGIC)) {
|
if (has_skill(u, SK_MAGIC)) {
|
||||||
if (count_skill(u2->faction, SK_MAGIC) + u->number >
|
if (faction_count_skill(u2->faction, SK_MAGIC) + u->number >
|
||||||
skill_limit(u2->faction, SK_MAGIC)) {
|
faction_skill_limit(u2->faction, SK_MAGIC)) {
|
||||||
cmistake(u, ord, 155, MSG_COMMERCE);
|
cmistake(u, ord, 155, MSG_COMMERCE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -597,8 +603,8 @@ void give_unit(unit * u, unit * u2, order * ord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_skill(u, SK_ALCHEMY)
|
if (has_skill(u, SK_ALCHEMY)
|
||||||
&& count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
&& faction_count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
||||||
skill_limit(u2->faction, SK_ALCHEMY)) {
|
faction_skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||||
cmistake(u, ord, 156, MSG_COMMERCE);
|
cmistake(u, ord, 156, MSG_COMMERCE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,12 @@ extern "C" {
|
||||||
struct message * disband_men(int n, struct unit * u, struct order *ord);
|
struct message * disband_men(int n, struct unit * u, struct order *ord);
|
||||||
struct message * give_men(int n, struct unit *u, struct unit *u2,
|
struct message * give_men(int n, struct unit *u, struct unit *u2,
|
||||||
struct order *ord);
|
struct order *ord);
|
||||||
|
int give_unit_allowed(const struct unit * u);
|
||||||
void give_unit(struct unit *u, struct unit *u2, struct order *ord);
|
void give_unit(struct unit *u, struct unit *u2, struct order *ord);
|
||||||
void give_cmd(struct unit * u, struct order * ord);
|
void give_cmd(struct unit * u, struct order * ord);
|
||||||
struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord);
|
struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord);
|
||||||
bool can_give_to(struct unit *u, struct unit *u2);
|
bool can_give_to(struct unit *u, struct unit *u2);
|
||||||
|
bool rule_transfermen(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -572,7 +572,7 @@ static int build_limited(unit * u, const construction * con, int completed, int
|
||||||
}
|
}
|
||||||
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
|
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
|
||||||
* Talente */
|
* 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);
|
const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
|
||||||
item *itm = ring ? *i_find(&u->items, ring->itype) : 0;
|
item *itm = ring ? *i_find(&u->items, ring->itype) : 0;
|
||||||
int i = itm ? itm->number : 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)) {
|
for (qi = 0; members; selist_advance(&members, &qi, 1)) {
|
||||||
faction *m = (faction *)selist_get(members, qi);
|
faction *m = (faction *)selist_get(members, qi);
|
||||||
num += count_skill(m, sk);
|
num += faction_count_skill(m, sk);
|
||||||
}
|
}
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +623,7 @@ static int allied_skilllimit(const faction * f, skill_t sk)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count_skill(faction * f, skill_t sk)
|
int faction_count_skill(faction * f, skill_t sk)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
unit *u;
|
unit *u;
|
||||||
|
@ -638,7 +638,7 @@ int count_skill(faction * f, skill_t sk)
|
||||||
return n;
|
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 m = INT_MAX;
|
||||||
int al = allied_skilllimit(f, sk);
|
int al = allied_skilllimit(f, sk);
|
||||||
|
|
|
@ -161,8 +161,8 @@ extern "C" {
|
||||||
struct spellbook * faction_get_spellbook(struct faction *f);
|
struct spellbook * faction_get_spellbook(struct faction *f);
|
||||||
|
|
||||||
/* skills */
|
/* skills */
|
||||||
int skill_limit(struct faction *f, skill_t sk);
|
int faction_skill_limit(const struct faction *f, skill_t sk);
|
||||||
int count_skill(struct faction *f, skill_t sk);
|
int faction_count_skill(struct faction *f, skill_t sk);
|
||||||
bool faction_id_is_unused(int);
|
bool faction_id_is_unused(int);
|
||||||
|
|
||||||
#define COUNT_MONSTERS 0x01
|
#define COUNT_MONSTERS 0x01
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
static void test_destroyfaction_allies(CuTest *tc) {
|
static void test_destroyfaction_allies(CuTest *tc) {
|
||||||
faction *f1, *f2;
|
faction *f1, *f2;
|
||||||
|
@ -211,6 +212,26 @@ static void test_max_migrants(CuTest *tc) {
|
||||||
test_teardown();
|
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) {
|
static void test_valid_race(CuTest *tc) {
|
||||||
race * rc1, *rc2;
|
race * rc1, *rc2;
|
||||||
faction *f;
|
faction *f;
|
||||||
|
@ -334,6 +355,7 @@ CuSuite *get_faction_suite(void)
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_addplayer);
|
SUITE_ADD_TEST(suite, test_addplayer);
|
||||||
SUITE_ADD_TEST(suite, test_max_migrants);
|
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_addfaction);
|
||||||
SUITE_ADD_TEST(suite, test_remove_empty_factions);
|
SUITE_ADD_TEST(suite, test_remove_empty_factions);
|
||||||
SUITE_ADD_TEST(suite, test_destroyfaction_allies);
|
SUITE_ADD_TEST(suite, test_destroyfaction_allies);
|
||||||
|
|
|
@ -1812,19 +1812,29 @@ int maintenance_cost(const struct unit *u)
|
||||||
return u_race(u)->maintenance * u->number;
|
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)
|
bool has_limited_skills(const struct unit * u)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i != u->skill_size; ++i) {
|
for (i = 0; i != u->skill_size; ++i) {
|
||||||
skill *sv = u->skills + i;
|
skill *sv = u->skills + i;
|
||||||
for (j = 0; limited_skills[j] != NOSKILL; ++j) {
|
if (is_limited_skill(sv->id)) {
|
||||||
if (sv->id == limited_skills[j]) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,7 @@ extern "C" {
|
||||||
bool has_horses(const struct unit *u);
|
bool has_horses(const struct unit *u);
|
||||||
int maintenance_cost(const struct unit *u);
|
int maintenance_cost(const struct unit *u);
|
||||||
bool has_limited_skills(const struct unit *u);
|
bool has_limited_skills(const struct unit *u);
|
||||||
|
bool is_limited_skill(skill_t sk);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
84
src/laws.c
84
src/laws.c
|
@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
#include "contact.h"
|
#include "contact.h"
|
||||||
#include "economy.h"
|
#include "economy.h"
|
||||||
|
#include "give.h"
|
||||||
#include "market.h"
|
#include "market.h"
|
||||||
#include "morale.h"
|
#include "morale.h"
|
||||||
#include "monsters.h"
|
#include "monsters.h"
|
||||||
|
@ -395,8 +396,7 @@ static void peasants(region * r, int rule)
|
||||||
dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE);
|
dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE);
|
||||||
|
|
||||||
if (dead > 0) {
|
if (dead > 0) {
|
||||||
message *msg = add_message(&r->msgs, msg_message("phunger", "dead", dead));
|
ADDMSG(&r->msgs, msg_message("phunger", "dead", dead));
|
||||||
msg_release(msg);
|
|
||||||
peasants -= dead;
|
peasants -= dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,6 +941,52 @@ int leave_cmd(unit * u, struct order *ord)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (u_race(u) == fdst->race) {
|
||||||
|
u->flags &= ~UFL_HERO;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int quit_cmd(unit * u, struct order *ord)
|
int quit_cmd(unit * u, struct order *ord)
|
||||||
{
|
{
|
||||||
char token[128];
|
char token[128];
|
||||||
|
@ -952,7 +998,37 @@ int quit_cmd(unit * u, struct order *ord)
|
||||||
assert(kwd == K_QUIT);
|
assert(kwd == K_QUIT);
|
||||||
passwd = gettoken(token, sizeof(token));
|
passwd = gettoken(token, sizeof(token));
|
||||||
if (checkpasswd(f, (const char *)passwd)) {
|
if (checkpasswd(f, (const char *)passwd)) {
|
||||||
fset(f, FFL_QUIT);
|
int flags = FFL_QUIT;
|
||||||
|
if (rule_transfermen()) {
|
||||||
|
param_t p;
|
||||||
|
p = getparam(f->locale);
|
||||||
|
if (p == P_FACTION) {
|
||||||
|
faction *f2 = getfaction();
|
||||||
|
if (f2 == NULL) {
|
||||||
|
cmistake(u, ord, 66, MSG_EVENT);
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
else if (f->race != f2->race) {
|
||||||
|
cmistake(u, ord, 281, MSG_EVENT);
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unit *u2;
|
||||||
|
for (u2 = u->region->units; u2; u2 = u2->next) {
|
||||||
|
if (u2->faction == f2 && ucontact(u2, u)) {
|
||||||
|
transfer_faction(u->faction, u2->faction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (u2 == NULL) {
|
||||||
|
/* no target unit found */
|
||||||
|
cmistake(u, ord, 0, MSG_EVENT);
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f->flags |= flags;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
|
@ -2077,7 +2153,7 @@ int banner_cmd(unit * u, struct order *ord)
|
||||||
init_order_depr(ord);
|
init_order_depr(ord);
|
||||||
s = getstrtoken();
|
s = getstrtoken();
|
||||||
faction_setbanner(u->faction, s);
|
faction_setbanner(u->faction, s);
|
||||||
add_message(&u->faction->msgs, msg_message("changebanner", "value", s));
|
ADDMSG(&u->faction->msgs, msg_message("changebanner", "value", s));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
149
src/laws.test.c
149
src/laws.test.c
|
@ -1,6 +1,7 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include "laws.h"
|
#include "laws.h"
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
|
#include "contact.h"
|
||||||
#include "guard.h"
|
#include "guard.h"
|
||||||
#include "monsters.h"
|
#include "monsters.h"
|
||||||
|
|
||||||
|
@ -1868,6 +1869,149 @@ static void test_long_order_on_ocean(CuTest *tc) {
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_quit(CuTest *tc) {
|
||||||
|
faction *f;
|
||||||
|
unit *u;
|
||||||
|
region *r;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
r = test_create_plain(0, 0);
|
||||||
|
f = test_create_faction(NULL);
|
||||||
|
u = test_create_unit(f, r);
|
||||||
|
u->thisorder = create_order(K_QUIT, f->locale, "password");
|
||||||
|
|
||||||
|
faction_setpassword(f, "passwort");
|
||||||
|
quit_cmd(u, u->thisorder);
|
||||||
|
CuAssertIntEquals(tc, 0, f->flags & FFL_QUIT);
|
||||||
|
|
||||||
|
faction_setpassword(f, "password");
|
||||||
|
quit_cmd(u, u->thisorder);
|
||||||
|
CuAssertIntEquals(tc, FFL_QUIT, f->flags & FFL_QUIT);
|
||||||
|
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gifting units to another faction upon voluntary death (QUIT).
|
||||||
|
*/
|
||||||
|
static void test_quit_transfer(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));
|
||||||
|
quit_cmd(u1, u1->thisorder);
|
||||||
|
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||||
|
CuAssertPtrEquals(tc, f2, u1->faction);
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gifting units with limited skills to another faction.
|
||||||
|
*
|
||||||
|
* This is allowed only up to the limit of the target faction.
|
||||||
|
* Units that would break the limit are not transferred.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only units of the same race can be gifted to another faction.
|
||||||
|
*/
|
||||||
|
static void test_quit_transfer_migrants(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));
|
||||||
|
|
||||||
|
u_setrace(u1, test_create_race("smurf"));
|
||||||
|
|
||||||
|
quit_cmd(u1, u1->thisorder);
|
||||||
|
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||||
|
CuAssertPtrEquals(tc, f1, u1->faction);
|
||||||
|
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hero that is gifted to another faction loses their status.
|
||||||
|
*/
|
||||||
|
static void test_quit_transfer_hero(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));
|
||||||
|
|
||||||
|
u1->flags |= UFL_HERO;
|
||||||
|
|
||||||
|
quit_cmd(u1, u1->thisorder);
|
||||||
|
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||||
|
CuAssertPtrEquals(tc, f2, u1->faction);
|
||||||
|
CuAssertIntEquals(tc, 0, u1->flags & UFL_HERO);
|
||||||
|
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_laws_suite(void)
|
CuSuite *get_laws_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
@ -1943,6 +2087,11 @@ CuSuite *get_laws_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_nmr_timeout);
|
SUITE_ADD_TEST(suite, test_nmr_timeout);
|
||||||
SUITE_ADD_TEST(suite, test_long_orders);
|
SUITE_ADD_TEST(suite, test_long_orders);
|
||||||
SUITE_ADD_TEST(suite, test_long_order_on_ocean);
|
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);
|
||||||
|
SUITE_ADD_TEST(suite, test_quit_transfer_migrants);
|
||||||
|
SUITE_ADD_TEST(suite, test_quit_transfer_hero);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -603,8 +603,7 @@ void plagues(region * r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dead > 0) {
|
if (dead > 0) {
|
||||||
message *msg = add_message(&r->msgs, msg_message("pest", "dead", dead));
|
ADDMSG(&r->msgs, msg_message("pest", "dead", dead));
|
||||||
msg_release(msg);
|
|
||||||
deathcounts(r, dead);
|
deathcounts(r, dead);
|
||||||
rsetpeasants(r, peasants - dead);
|
rsetpeasants(r, peasants - dead);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3109,8 +3109,8 @@ static int sp_chaossuction(castorder * co)
|
||||||
create_special_direction(rt, r, 2, "vortex_desc", "vortex", false);
|
create_special_direction(rt, r, 2, "vortex_desc", "vortex", false);
|
||||||
new_border(&bt_chaosgate, r, rt);
|
new_border(&bt_chaosgate, r, rt);
|
||||||
|
|
||||||
add_message(&r->msgs, msg_message("chaosgate_effect_1", "mage", caster));
|
ADDMSG(&r->msgs, msg_message("chaosgate_effect_1", "mage", caster));
|
||||||
add_message(&rt->msgs, msg_message("chaosgate_effect_2", ""));
|
ADDMSG(&rt->msgs, msg_message("chaosgate_effect_2", ""));
|
||||||
return cast_level;
|
return cast_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3450,7 +3450,7 @@ static bool can_charm(const unit * u, int maxlevel)
|
||||||
while (l < h) {
|
while (l < h) {
|
||||||
int m = (l + h) / 2;
|
int m = (l + h) / 2;
|
||||||
if (sk == expskills[m]) {
|
if (sk == expskills[m]) {
|
||||||
if (skill_limit(u->faction, sk) != INT_MAX) {
|
if (faction_skill_limit(u->faction, sk) != INT_MAX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if ((int)sv->level > maxlevel) {
|
else if ((int)sv->level > maxlevel) {
|
||||||
|
|
|
@ -635,9 +635,9 @@ int study_cmd(unit * u, order * ord)
|
||||||
mtype = M_GRAY;
|
mtype = M_GRAY;
|
||||||
}
|
}
|
||||||
else if (!has_skill(u, SK_MAGIC)) {
|
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 */
|
/* 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",
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians",
|
||||||
"amount", mmax));
|
"amount", mmax));
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -694,8 +694,8 @@ int study_cmd(unit * u, order * ord)
|
||||||
if (sk == SK_ALCHEMY) {
|
if (sk == SK_ALCHEMY) {
|
||||||
maxalchemy = effskill(u, SK_ALCHEMY, NULL);
|
maxalchemy = effskill(u, SK_ALCHEMY, NULL);
|
||||||
if (!has_skill(u, SK_ALCHEMY)) {
|
if (!has_skill(u, SK_ALCHEMY)) {
|
||||||
int amax = skill_limit(u->faction, SK_ALCHEMY);
|
int amax = faction_skill_limit(u->faction, SK_ALCHEMY);
|
||||||
if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
|
if (faction_count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists",
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists",
|
||||||
"amount", amax));
|
"amount", amax));
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue