Merge pull request #942 from eressea/expel

VERTREIBE Kommando
This commit is contained in:
Enno Rehling 2021-06-11 21:11:22 +02:00 committed by GitHub
commit 317f605ff2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 338 additions and 140 deletions

View File

@ -36,6 +36,7 @@
"maketemp": ["MACHE TEMP", "MACHETEMP"],
"move" : "NACH",
"password" : "PASSWORT",
"expel" : "VERTREIBE",
"loot" : ["PLÜNDERE", "PLÜNDERN"],
"recruit": ["REKRUTIERE", "REKRUTIEREN"],
"reserve": ["RESERVIERE", "RESERVIEREN"],

View File

@ -4732,6 +4732,13 @@
<arg name="command" type="order"/>
</type>
</message>
<message name="feedback_not_inside" section="errors">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
<arg name="command" type="order"/>
</type>
</message>
<message name="feedback_unit_not_found" section="errors">
<type>
<arg name="unit" type="unit"/>

View File

@ -590,6 +590,9 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletscher
msgid "feedback_unit_not_found"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\""
msgid "feedback_not_inside"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit kontrolliert kein Schiff oder Gebäude.\""
msgid "error206"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf dem Gebäude liegt bereits so ein Zauber.\""

View File

@ -590,6 +590,9 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build
msgid "feedback_unit_not_found"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\""
msgid "feedback_unit_not_found"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not the owner of a ship or building.\""
msgid "error206"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - There is alrady a spell on that building.\""

View File

@ -2496,6 +2496,10 @@ msgctxt "keyword"
msgid "loot"
msgstr "PLÜNDERE"
msgctxt "keyword"
msgid "expel"
msgstr "VERTREIBE"
msgctxt "calendar"
msgid "month_1"
msgstr "Feldsegen"

View File

@ -2167,6 +2167,10 @@ msgctxt "keyword"
msgid "loot"
msgstr "loot"
msgctxt "keyword"
msgid "expel"
msgstr "EXPEL"
msgctxt "keyword"
msgid "guard"
msgstr "GUARD"

View File

@ -3925,21 +3925,25 @@ void force_leave(region *r, battle *b) {
if (u->building) {
uo = building_owner(u->building);
}
if (u->ship && r->land) {
else if (u->ship && r->land) {
uo = ship_owner(u->ship);
}
if (uo && is_enemy(b, uo, u)) {
message *msg = NULL;
if (u->building) {
msg = msg_message("force_leave_building", "unit owner building", u, uo, u->building);
else {
continue;
}
if (is_enemy(b, uo, u)) {
if (leave(u, true)) {
message *msg;
if (uo->building) {
msg = msg_message("force_leave_building", "unit owner building", u, uo, uo->building);
}
else {
msg = msg_message("force_leave_ship", "unit owner ship", u, uo, u->ship);
msg = msg_message("force_leave_ship", "unit owner ship", u, uo, uo->ship);
}
if (msg) {
ADDMSG(&u->faction->msgs, msg);
add_message(&u->faction->msgs, msg);
add_message(&uo->faction->msgs, msg);
msg_release(msg);
}
leave(u, false);
}
}
}

View File

@ -3939,11 +3939,12 @@ void init_processor(void)
add_proc_global(p, defaultorders, "Defaults setzen");
}
add_proc_global(p, demographics, "Nahrung, Seuchen, Wachstum, Wanderung");
p += 10;
if (!keyword_disabled(K_SORT)) {
p += 10;
add_proc_global(p, restack_units, "Einheiten sortieren");
add_proc_region(p, do_sort, "Einheiten sortieren");
}
add_proc_order(p, K_EXPEL, expel_cmd, 0, "Einheiten verjagen");
if (!keyword_disabled(K_NUMBER)) {
add_proc_order(p, K_NUMBER, renumber_cmd, 0, "Neue Nummern (Einheiten)");
p += 10;
@ -4187,3 +4188,66 @@ int locale_cmd(unit * u, order * ord)
}
return 0;
}
static void expel_building(unit *u, unit *u2, order *ord) {
building *b = u->building;
if (u != building_owner(b)) {
/* error: must be the owner */
cmistake(u, ord, 5, MSG_EVENT);
}
else {
if (leave(u2, true)) {
message *msg = msg_message("force_leave_building", "owner unit building", u, u2, u->building);
add_message(&u->faction->msgs, msg);
add_message(&u2->faction->msgs, msg);
msg_release(msg);
}
}
}
static void expel_ship(unit *u, unit *u2, order *ord) {
ship *sh = u->ship;
if (u != ship_owner(sh)) {
/* error: must be the owner */
cmistake(u, ord, 146, MSG_EVENT);
}
else if (!u->region->land) {
/* error: must not be at sea */
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "error_onlandonly", NULL));
}
else {
if (leave(u2, true)) {
message *msg = msg_message("force_leave_ship", "owner unit ship", u, u2, u->ship);
add_message(&u->faction->msgs, msg);
add_message(&u2->faction->msgs, msg);
msg_release(msg);
}
}
}
int expel_cmd(unit *u, order *ord) {
faction *f = u->faction;
unit *u2;
init_order(ord, f->locale);
getunit(u->region, u->faction, &u2);
if (u2 == NULL) {
/* error: target unit not found */
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "feedback_unit_not_found", NULL));
return 0;
}
if (u->building) {
expel_building(u, u2, ord);
}
else if (u->ship) {
expel_ship(u, u2, ord);
}
else {
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "feedback_not_inside", NULL));
/* error: unit must be owner of a ship or building */
}
return 0;
}

View File

@ -50,6 +50,7 @@ extern "C" {
bool long_order_allowed(const struct unit *u, bool flags_only);
bool password_wellformed(const char *password);
int expel_cmd(struct unit *u, struct order *ord);
int locale_cmd(struct unit *u, struct order *ord);
int password_cmd(struct unit *u, struct order *ord);
int banner_cmd(struct unit *u, struct order *ord);

View File

@ -173,6 +173,95 @@ static void test_enter_ship(CuTest * tc)
test_teardown();
}
static void test_expel_building(CuTest *tc) {
unit *u1, *u2;
order *ord;
building *b;
test_setup();
u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0));
u2 = test_create_unit(test_create_faction(), u1->region);
ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no));
expel_cmd(u2, ord);
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "feedback_not_inside"));
test_clear_messages(u2->faction);
b = u2->building = u1->building = test_create_building(u1->region, NULL);
CuAssertPtrEquals(tc, u1, building_owner(b));
expel_cmd(u2, ord);
/* Nothing happened: */
CuAssertPtrEquals(tc, u1, building_owner(b));
CuAssertPtrEquals(tc, b, u1->building);
CuAssertPtrEquals(tc, b, u2->building);
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "error5"));
test_clear_messages(u1->faction);
free_order(ord);
ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no));
expel_cmd(u1, ord);
/* owner has expelled u2: */
CuAssertPtrEquals(tc, NULL, u2->building);
CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "force_leave_building"));
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "force_leave_building"));
test_teardown();
}
static void test_expel_ship(CuTest *tc) {
unit *u1, *u2;
order *ord;
ship *sh;
test_setup();
u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0));
u2 = test_create_unit(test_create_faction(), u1->region);
ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no));
expel_cmd(u2, ord);
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "feedback_not_inside"));
test_clear_messages(u2->faction);
sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL);
CuAssertPtrEquals(tc, u1, ship_owner(sh));
expel_cmd(u2, ord);
/* Nothing happened: */
CuAssertPtrEquals(tc, u1, ship_owner(sh));
CuAssertPtrEquals(tc, sh, u1->ship);
CuAssertPtrEquals(tc, sh, u2->ship);
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "error146"));
test_clear_messages(u2->faction);
free_order(ord);
ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no));
expel_cmd(u1, ord);
/* owner has expelled u2: */
CuAssertPtrEquals(tc, NULL, u2->ship);
CuAssertPtrEquals(tc, sh, leftship(u2));
CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "force_leave_ship"));
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "force_leave_ship"));
test_teardown();
}
static void test_expel_ship_at_sea(CuTest *tc) {
unit *u1, *u2;
order *ord;
ship *sh;
test_setup();
u1 = test_create_unit(test_create_faction(), test_create_ocean(0, 0));
u2 = test_create_unit(test_create_faction(), u1->region);
sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL);
CuAssertPtrEquals(tc, u1, ship_owner(sh));
ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no));
expel_cmd(u1, ord);
/* owner has not expelled u2: */
CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "error_onlandonly"));
CuAssertPtrEquals(tc, sh, u2->ship);
test_teardown();
}
static void test_display_cmd(CuTest *tc) {
unit *u;
faction *f;
@ -2320,6 +2409,9 @@ CuSuite *get_laws_suite(void)
SUITE_ADD_TEST(suite, test_enter_building);
SUITE_ADD_TEST(suite, test_enter_ship);
SUITE_ADD_TEST(suite, test_display_cmd);
SUITE_ADD_TEST(suite, test_expel_building);
SUITE_ADD_TEST(suite, test_expel_ship);
SUITE_ADD_TEST(suite, test_expel_ship_at_sea);
SUITE_ADD_TEST(suite, test_rule_force_leave);
SUITE_ADD_TEST(suite, test_force_leave_buildings);
SUITE_ADD_TEST(suite, test_force_leave_ships);

View File

@ -95,15 +95,18 @@ static void handle_unit(void *userData, int no) {
static void handle_order(void *userData, const char *str) {
parser_state *state = (parser_state *)userData;
const char * tok, *input = str;
const char * tok, *input;
char buffer[64];
const struct locale *lang;
param_t p;
faction * f = state->f;
lang = f ? f->locale : default_locale;
ltrim(&str);
if (*str == 0) return;
input = str;
tok = parse_token(&input, buffer, sizeof(buffer));
p = findparam(tok, lang);
if (tok) {
param_t p = findparam(tok, lang);
if (p == P_FACTION || p == P_GAMENAME) {
tok = parse_token(&input, buffer, sizeof(buffer));
if (tok) {
@ -143,6 +146,7 @@ static void handle_order(void *userData, const char *str) {
}
}
}
}
int parseorders(FILE *F)
{

View File

@ -13,7 +13,7 @@
#include "util/param.h"
#include "util/parser.h"
void sort_before(unit *v, unit **up) {
static void sort_before(unit *v, unit **up) {
unit *u = *up;
region *r = u->region;
unit **vp = &r->units;
@ -24,10 +24,8 @@ void sort_before(unit *v, unit **up) {
u->next = v;
}
void restack_units(void)
void do_sort(region *r)
{
region *r;
for (r = regions; r; r = r->next) {
unit **up = &r->units;
bool sorted = false;
while (*up) {
@ -121,5 +119,12 @@ void restack_units(void)
}
}
}
void restack_units(void)
{
region *r;
for (r = regions; r; r = r->next) {
do_sort(r);
}
}

View File

@ -1,3 +1,6 @@
#pragma once
struct region;
void restack_units(void);
void do_sort(struct region *r);

View File

@ -119,7 +119,7 @@ int spy_cmd(unit * u, struct order *ord)
if (!target) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "feedback_unit_not_found", ""));
msg_feedback(u, u->thisorder, "feedback_unit_not_found", NULL));
return 0;
}
if (effskill(u, SK_SPY, NULL) < 1) {

View File

@ -156,7 +156,8 @@ const char *keywords[MAXKEYWORDS] = {
"promote",
"pay",
"loot",
"expel",
"autostudy",
"locale",
"locale"
};

View File

@ -71,6 +71,7 @@ extern "C"
K_PROMOTION,
K_PAY,
K_LOOT,
K_EXPEL,
K_AUTOSTUDY,
K_LOCALE,
MAXKEYWORDS,

View File

@ -26,7 +26,7 @@ static parse_state *states;
#define TRIMMED(wc) (iswspace(wc) || iswcntrl(wc) || (wc) == 160 || (wc) == 8199 || (wc) == 8239)
static int ltrim(const char **str_p)
int ltrim(const char **str_p)
{
int ret = 0;
wint_t wc;

View File

@ -22,6 +22,7 @@ extern "C" {
int getint(void);
int getid(void);
unsigned int atoip(const char *s);
int ltrim(const char **str_p);
#ifdef __cplusplus
}