diff --git a/res/e3a/races.xml b/res/e3a/races.xml
index 46427ba92..164a599b7 100644
--- a/res/e3a/races.xml
+++ b/res/e3a/races.xml
@@ -883,7 +883,7 @@
-
+
diff --git a/res/eressea/races.xml b/res/eressea/races.xml
index 7f6c6d873..ec119bd21 100644
--- a/res/eressea/races.xml
+++ b/res/eressea/races.xml
@@ -1171,7 +1171,7 @@
-
+
diff --git a/src/kernel/race.h b/src/kernel/race.h
index 0ae925c5d..fa18cb8f2 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -214,6 +214,7 @@ extern "C" {
#define RCF_SHIPSPEED (1<<26) /* race gets +1 on shipspeed */
#define RCF_STONEGOLEM (1<<27) /* race gets stonegolem properties */
#define RCF_IRONGOLEM (1<<28) /* race gets irongolem properties */
+#define RCF_ATTACK_MOVED (1<<29) /* may attack if it has moved */
/* Economic flags */
#define ECF_KEEP_ITEM (1<<1) /* gibt Gegenstände weg */
diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c
index 28a351a72..c5af75d04 100644
--- a/src/kernel/xmlreader.c
+++ b/src/kernel/xmlreader.c
@@ -1604,6 +1604,8 @@ static void parse_ai(race * rc, xmlNodePtr node)
rc->flags |= RCF_MOVERANDOM;
if (xml_bvalue(node, "learn", false))
rc->flags |= RCF_LEARN;
+ if (xml_bvalue(node, "moveattack", false))
+ rc->flags |= RCF_ATTACK_MOVED;
}
static int parse_races(xmlDocPtr doc)
diff --git a/src/monster.c b/src/monster.c
index 47858fc5d..3d6fd6f82 100644
--- a/src/monster.c
+++ b/src/monster.c
@@ -69,7 +69,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
bool monster_is_waiting(const unit * u)
{
- if (fval(u, UFL_ISNEW | UFL_MOVED))
+ int test = fval(u_race(u), RCF_ATTACK_MOVED) ? UFL_ISNEW : UFL_ISNEW | UFL_MOVED;
+ if (fval(u, test))
return true;
return false;
}
diff --git a/src/piracy.c b/src/piracy.c
index 8911f0882..4843880b8 100644
--- a/src/piracy.c
+++ b/src/piracy.c
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -64,6 +65,8 @@ static attrib *mk_piracy(const faction * pirate, const faction * target,
}
static bool validate_pirate(unit *u, order *ord) {
+ if (fval(u_race(u), RCF_SWIM | RCF_FLY))
+ return true;
if (!u->ship) {
cmistake(u, ord, 144, MSG_MOVE);
return false;
diff --git a/src/piracy.test.c b/src/piracy.test.c
index 53907f4df..acc220d3a 100644
--- a/src/piracy.test.c
+++ b/src/piracy.test.c
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
@@ -66,6 +67,7 @@ static void test_piracy_cmd(CuTest * tc) {
}
static void test_piracy_cmd_errors(CuTest * tc) {
+ race *r;
faction *f;
unit *u, *u2;
order *ord;
@@ -73,7 +75,8 @@ static void test_piracy_cmd_errors(CuTest * tc) {
setup_piracy();
st_boat = st_get_or_create("boat");
- u = test_create_unit(f = test_create_faction(0), test_create_region(0, 0, get_or_create_terrain("ocean")));
+ r = test_create_race("pirates");
+ u = test_create_unit(f = test_create_faction(r), test_create_region(0, 0, get_or_create_terrain("ocean")));
f->locale = get_or_create_locale("de");
ord = create_order(K_PIRACY, f->locale, "");
assert(u && ord);
@@ -81,6 +84,17 @@ static void test_piracy_cmd_errors(CuTest * tc) {
piracy_cmd(u, ord);
CuAssertPtrNotNullMsg(tc, "must be on a ship for PIRACY", test_find_messagetype(f->msgs, "error144"));
+ test_clear_messages(f);
+ fset(r, RCF_SWIM);
+ piracy_cmd(u, ord);
+ CuAssertPtrEquals_Msg(tc, "swimmers are pirates", 0, test_find_messagetype(f->msgs, "error144"));
+ CuAssertPtrEquals_Msg(tc, "swimmers are pirates", 0, test_find_messagetype(f->msgs, "error146"));
+ freset(r, RCF_SWIM);
+ fset(r, RCF_FLY);
+ CuAssertPtrEquals_Msg(tc, "flyers are pirates", 0, test_find_messagetype(f->msgs, "error144"));
+ freset(r, RCF_FLY);
+ test_clear_messages(f);
+
u_set_ship(u, test_create_ship(u->region, st_boat));
u2 = test_create_unit(u->faction, u->region);