diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index 9220165a2..e6988b522 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -3208,7 +3208,7 @@ peasant_taxes(region * r) money = rmoney(r); if (money<=0) return; - b = largestbuilding(r, false); + b = largestbuilding(r, &is_tax_building, false); if (b==NULL) return; u = buildingowner(r, b); diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index f2762cc5c..0abe75c75 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -1404,7 +1404,7 @@ display_cmd(unit * u, struct order * ord) cmistake(u, ord, 148, MSG_EVENT); break; } - if (b != largestbuilding(r,false)) { + if (b != largestbuilding(r, &is_castle, false)) { cmistake(u, ord, 147, MSG_EVENT); break; } @@ -1639,7 +1639,7 @@ name_cmd(unit * u, struct order * ord) cmistake(u, ord, 148, MSG_EVENT); break; } - if (b != largestbuilding(r,false)) { + if (b != largestbuilding(r, &is_castle, false)) { cmistake(u, ord, 147, MSG_EVENT); break; } @@ -2920,12 +2920,22 @@ static void age_region(region * r) { a_age(&r->attribs); handle_event(r->attribs, "timer", r); + + if (r->land && r->land->ownership) { + int stability = r->land->ownership->since_turn; + int morale = MORALE_TAKEOVER + stability/10; + if (r->land->ownership->owner && r->land->moraleland->morale = MIN(morale, MORALE_MAX); + } + if (!r->land->ownership->owner && r->land->moraleland->morale = MIN(morale, MORALE_DEFAULT); + } + } } static void ageing(void) { - const building_type * bt_castle = bt_find("castle"); faction *f; region *r; @@ -2993,24 +3003,17 @@ ageing(void) for (bp=&r->buildings;*bp;) { building * b = *bp; b = age_building(b); + } - if (b==*bp) { - if (b->type==bt_castle) { - if (blargest==NULL || b->size>blargest->size) { - blargest = b; - } - } - bp = &(*bp)->next; - } - if (blargest) { - /* region owners update? */ - faction * f = region_get_owner(r); - unit * u = buildingowner(r, blargest); - if (u==NULL) { - region_set_owner(r, NULL, turn); - } else if (u->faction!=f) { - region_set_owner(r, f, turn); - } + blargest = largestbuilding(r, &is_tax_building, false); + if (blargest) { + /* region owners update? */ + faction * f = region_get_owner(r); + unit * u = buildingowner(r, blargest); + if (u==NULL) { + region_set_owner(r, NULL, turn); + } else if (u->faction!=f) { + region_set_owner(r, f, turn); } } } diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index 0904410c4..e9bf0805d 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -746,7 +746,7 @@ weapon_effskill(troop t, troop enemy, const weapon * w, boolean attacking, boole } /* Burgenbonus, Pferdebonus */ - if (is_riding(t) && (wtype==NULL || !fval(wtype, WTF_MISSILE))) { + if (is_riding(t) && (wtype==NULL || (fval(wtype, WTF_HORSEBONUS) && !fval(wtype, WTF_MISSILE)))) { skill += 2; if (wtype) skill = skillmod(urace(tu)->attribs, tu, tu->region, wtype->skill, skill, SMF_RIDING); } diff --git a/src/common/kernel/building.c b/src/common/kernel/building.c index bbc10f5da..e3f86d37b 100644 --- a/src/common/kernel/building.c +++ b/src/common/kernel/building.c @@ -266,24 +266,44 @@ init_smithy(struct building_type * bt) static const char * castle_name(const struct building_type* btype, int bsize) { - const char * fname[MAXBUILDINGS] = { - "site", - "tradepost", - "fortification", - "tower", - "castle", - "fortress", - "citadel" }; - const construction * ctype; - int i = 0; + const char * fname[MAXBUILDINGS] = { + "site", + "tradepost", + "fortification", + "tower", + "castle", + "fortress", + "citadel" + }; + const construction * ctype; + int i = 0; - ctype = btype->construction; - while (ctype && ctype->maxsize != -1 && ctype->maxsize<=bsize) { - bsize-=ctype->maxsize; - ctype=ctype->improvement; - ++i; - } - return fname[i]; + ctype = btype->construction; + while (ctype && ctype->maxsize != -1 && ctype->maxsize<=bsize) { + bsize-=ctype->maxsize; + ctype=ctype->improvement; + ++i; + } + return fname[i]; +} + +static const char * +fort_name(const struct building_type* btype, int bsize) +{ + const char * fname[MAXBUILDINGS] = { + "guardhouse", + "guardtower", + }; + const construction * ctype; + int i = 0; + + ctype = btype->construction; + while (ctype && ctype->maxsize != -1 && ctype->maxsize<=bsize) { + bsize-=ctype->maxsize; + ctype=ctype->improvement; + ++i; + } + return fname[i]; } #ifdef WDW_PYRAMID @@ -364,10 +384,11 @@ findbuildingtype(const char * name, const struct locale * lang) void register_buildings(void) { - register_function((pf_generic)init_smithy, "init_smithy"); - register_function((pf_generic)castle_name, "castle_name"); + register_function((pf_generic)&init_smithy, "init_smithy"); + register_function((pf_generic)&castle_name, "castle_name"); + register_function((pf_generic)&fort_name, "fort_name"); #ifdef WDW_PYRAMID - register_function((pf_generic)pyramid_name, "pyramid_name"); + register_function((pf_generic)&pyramid_name, "pyramid_name"); #endif } diff --git a/src/common/kernel/building.h b/src/common/kernel/building.h index e9bc53eb0..f0125733f 100644 --- a/src/common/kernel/building.h +++ b/src/common/kernel/building.h @@ -43,6 +43,7 @@ typedef struct maintenance { #define BTF_MAGIC 0x40 /* magical effect */ #define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */ #define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */ +#define BTF_TAXES 0x200 /* automatic taxes */ typedef struct building_type { const char * _name; diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index 6f204292c..aad474e5a 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -154,7 +154,10 @@ ExpensiveMigrants(void) } return value; } - +/** Specifies automatic alliance modes. + * If this returns a value then the bits set are immutable between alliance + * partners (faction::alliance) and cannot be changed with the HELP command. + */ int AllianceAuto(void) { @@ -172,20 +175,41 @@ AllianceAuto(void) free(sstr); } } - return value; + return value | ~HelpMask(); } +/** Limits the available help modes + * The bitfield returned by this function specifies the available help modes + * in this game (so you can, for example, disable HELP GIVE globally). + * Disabling a status will disable the command sequence entirely (order parsing + * uses this function). + */ int HelpMask(void) { - static int help_mask = 0; - - if (help_mask==0) { - help_mask = get_param_int(global.parameters, "rules.help.mask", HELP_ALL); + static int value = -1; + if (value<0) { + const char * str = get_param(global.parameters, "rules.help.mask"); + value = 0; + if (str!=NULL) { + char * sstr = strdup(str); + char * tok = strtok(sstr, " "); + while (tok) { + value |= ally_flag(tok); + tok = strtok(NULL, " "); + } + free(sstr); + } else { + value = HELP_ALL; + } } - return help_mask; + return value; } +/** specifies modes that are restricted to members of the same alliance. + * if this returns a non-zero value, then you cannot give those modes to a + * faction unless they are in the same alliance. + */ int AllianceRestricted(void) { @@ -593,6 +617,20 @@ int verbosity = 0; FILE *debug; +static int +ShipSpeedBonus(const unit * u) +{ + static int level = -1; + if (level==-1) { + level = get_param_int(global.parameters, "movement.shipspeed.skillbonus", 0); + } + if (level>0) { + int skl = effskill(u, SK_SAILING); + return skl/level; + } + return 0; +} + int shipspeed(const ship * sh, const unit * u) { @@ -619,11 +657,13 @@ shipspeed(const ship * sh, const unit * u) if (u->faction->race == u->race) { /* race bonus for this faction? */ - if (u->race == new_race[RC_AQUARIAN]) { + if (fval(u->race, RCF_SHIPSPEED)) { k += 1; } } + k += ShipSpeedBonus(u); + a = a_find(sh->attribs, &at_speedup); while (a != NULL && a->type==&at_speedup) { k += a->data.sa[0]; @@ -837,9 +877,11 @@ static int autoalliance(const plane * pl, const faction * sf, const faction * f2) { static boolean init = false; + static int automode; if (!init) { init_gms(); init = true; + automode = ~HelpMask(); } if (pl && (pl->flags & PFL_FRIENDLY)) return HELP_ALL; /* if f2 is a gm in this plane, everyone has an auto-help to it */ @@ -857,7 +899,7 @@ autoalliance(const plane * pl, const faction * sf, const faction * f2) if (sf->alliance==f2->alliance) return AllianceAuto(); } - return 0; + return automode; } static int @@ -1641,11 +1683,10 @@ cstring(const char *s) } building * -largestbuilding (const region * r, boolean imaginary) +largestbuilding (const region * r, boolean (*eval)(const struct building *), boolean imaginary) { static const building_type * btype = NULL; building *b, *best = NULL; - if (!btype) btype = bt_find("castle"); /* TODO: parameter der funktion? */ /* durch die verw. von '>' statt '>=' werden die aelteren burgen * bevorzugt. */ @@ -1654,7 +1695,7 @@ largestbuilding (const region * r, boolean imaginary) if (imaginary) { const attrib * a = a_find(b->attribs, &at_icastle); if (!a) continue; - if (a->data.v != btype) continue; + if (eval && !eval(b)) continue; } else continue; } if (best==NULL || b->size > best->size) @@ -2548,10 +2589,26 @@ static const int wagetable[7][4] = { {15, 13, 16, 2} /* Zitadelle */ }; +boolean +is_castle(const struct building * b) +{ + static const struct building_type * bt_castle; + if (!bt_castle) bt_castle = bt_find("castle"); + return (b->type==bt_castle); +} + +boolean is_tax_building(const building * b) +{ + if (b->type->flags&BTF_TAXES) { + return true; + } + return false; +} + static int default_wage(const region *r, const faction * f, const race * rc) { - building *b = largestbuilding(r, false); + building *b = largestbuilding(r, &is_castle, false); int esize = 0; curse * c; int wage; diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index a2f5052a5..d70fcc121 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -247,8 +247,9 @@ extern char *cstring_i(char *s); extern const char *unitname(const struct unit * u); extern char * write_unitname(const struct unit * u, char * buffer, size_t size); -struct building *largestbuilding(const struct region * r, boolean imaginary); - +struct building *largestbuilding(const struct region * r, boolean (*eval)(const struct building *), boolean imaginary); +boolean is_castle(const struct building * b); +boolean is_tax_building(const struct building * b); extern int count_all(const struct faction * f); extern int count_migrants (const struct faction * f); extern int count_maxmigrants(const struct faction * f); diff --git a/src/common/kernel/item.h b/src/common/kernel/item.h index 4557a7d57..9f0915d4f 100644 --- a/src/common/kernel/item.h +++ b/src/common/kernel/item.h @@ -188,14 +188,15 @@ typedef struct armor_type { unsigned int flags; } armor_type; -#define WTF_NONE 0x00 -#define WTF_MISSILE 0x01 -#define WTF_MAGICAL 0x02 -#define WTF_PIERCE 0x04 -#define WTF_CUT 0x08 -#define WTF_BLUNT 0x10 -#define WTF_SIEGE 0x20 +#define WTF_NONE 0x00 +#define WTF_MISSILE 0x01 +#define WTF_MAGICAL 0x02 +#define WTF_PIERCE 0x04 +#define WTF_CUT 0x08 +#define WTF_BLUNT 0x10 +#define WTF_SIEGE 0x20 #define WTF_ARMORPIERCING 0x40 /* armor has only half value */ +#define WTF_HORSEBONUS 0x80 typedef struct weapon_type { const item_type * itype; diff --git a/src/common/kernel/race.h b/src/common/kernel/race.h index 4f16d84c0..9d98c06ec 100644 --- a/src/common/kernel/race.h +++ b/src/common/kernel/race.h @@ -137,6 +137,7 @@ extern int rc_specialdamage(const race *, const race *, const struct weapon_type #define RCF_UNARMEDGUARD (1<<23) /* kann ohne Waffen bewachen */ #define RCF_CANSAIL (1<<24) /* Einheit darf Schiffe betreten */ #define RCF_INVISIBLE (1<<25) /* not visible in any report */ +#define RCF_SHIPSPEED (1<<26) /* race gets +1 on shipspeed */ /* Economic flags */ #define GIVEITEM (1<<1) /* gibt Gegenstände weg */ diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index 4cf030b62..8e1e1b4f1 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -1337,7 +1337,13 @@ region_get_owner(const struct region * r) void region_set_owner(struct region * r, struct faction * owner, int turn) { - if (r->land && r->land->ownership) { + if (r->land) { + if (!r->land->ownership) { + r->land->ownership = malloc(sizeof(region_owner)); + r->land->morale = MORALE_DEFAULT; + } else if (r->land->ownership->owner) { + r->land->morale = MORALE_TAKEOVER; + } r->land->ownership->owner = owner; r->land->ownership->since_turn = turn; } diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h index 87e30b042..097f128c8 100644 --- a/src/common/kernel/region.h +++ b/src/common/kernel/region.h @@ -62,7 +62,9 @@ struct rawmaterial; struct donation; struct item; -#define MORALE_DEFAULT 2 /* Morale of peasants that have no lord */ +#define MORALE_MAX 4 /* Maximum morale allowed */ +#define MORALE_DEFAULT 2 /* Morale of peasants when they are conquered for the first time */ +#define MORALE_TAKEOVER 0 /* Morale of peasants after they lose their lord */ typedef struct region_owner { struct faction * owner; diff --git a/src/common/kernel/xmlreader.c b/src/common/kernel/xmlreader.c index 433170d6a..3a4ea5057 100644 --- a/src/common/kernel/xmlreader.c +++ b/src/common/kernel/xmlreader.c @@ -269,6 +269,7 @@ parse_buildings(xmlDocPtr doc) if (xml_bvalue(node, "decay", false)) btype->flags |= BTF_DECAY; if (xml_bvalue(node, "magic", false)) btype->flags |= BTF_MAGIC; if (xml_bvalue(node, "protection", false)) btype->flags |= BTF_PROTECTION; + if (xml_bvalue(node, "taxes", false)) btype->flags |= BTF_TAXES; /* reading eressea/buildings/building/construction */ xpath->node = node; @@ -645,6 +646,7 @@ xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) if (xml_bvalue(node, "cut", false)) flags |= WTF_CUT; if (xml_bvalue(node, "blunt", false)) flags |= WTF_BLUNT; if (xml_bvalue(node, "siege", false)) flags |= WTF_SIEGE; + if (xml_bvalue(node, "horse", (flags&WTF_MISSILE)==0)) flags |= WTF_HORSEBONUS; propValue = xmlGetProp(node, BAD_CAST "skill"); assert(propValue!=NULL); @@ -1579,6 +1581,7 @@ parse_races(xmlDocPtr doc) if (xml_bvalue(node, "illusionary", false)) rc->flags |= RCF_ILLUSIONARY; if (xml_bvalue(node, "undead", false)) rc->flags |= RCF_UNDEAD; if (xml_bvalue(node, "dragon", false)) rc->flags |= RCF_DRAGON; + if (xml_bvalue(node, "shipspeed", false)) rc->flags |= RCF_SHIPSPEED; if (xml_bvalue(node, "giveitem", false)) rc->ec_flags |= GIVEITEM; if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; diff --git a/src/res/buildings.xml b/src/res/buildings.xml index 7015020c2..d2546fb0e 100644 --- a/src/res/buildings.xml +++ b/src/res/buildings.xml @@ -166,7 +166,7 @@ - + diff --git a/src/res/races.xml b/src/res/races.xml index 5a511c8ae..affd7ef7a 100644 --- a/src/res/races.xml +++ b/src/res/races.xml @@ -759,7 +759,7 @@ - +