- largestbuilding() can take a filter

- morale (light) implemented
- rider bonus on weapons is configurable by XML
- wooden guard house
- help status can be masked
- shipspeed configurable (per race or via skill-level)
- tax-creating buildings configurable by XML
- bugfix: castles have no protection
This commit is contained in:
Enno Rehling 2009-05-18 13:00:09 +00:00
parent 418f611dcb
commit cf5cad9b87
14 changed files with 164 additions and 68 deletions

View File

@ -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);

View File

@ -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->morale<MORALE_MAX) {
r->land->morale = MIN(morale, MORALE_MAX);
}
if (!r->land->ownership->owner && r->land->morale<MORALE_DEFAULT) {
r->land->morale = MIN(morale, MORALE_DEFAULT);
}
}
}
static void
ageing(void)
{
const building_type * bt_castle = bt_find("castle");
faction *f;
region *r;
@ -2993,15 +3003,9 @@ 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;
}
blargest = largestbuilding(r, &is_tax_building, false);
if (blargest) {
/* region owners update? */
faction * f = region_get_owner(r);
@ -3013,7 +3017,6 @@ ageing(void)
}
}
}
}
}
static int

View File

@ -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);
}

View File

@ -273,7 +273,27 @@ castle_name(const struct building_type* btype, int bsize)
"tower",
"castle",
"fortress",
"citadel" };
"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];
}
static const char *
fort_name(const struct building_type* btype, int bsize)
{
const char * fname[MAXBUILDINGS] = {
"guardhouse",
"guardtower",
};
const construction * ctype;
int i = 0;
@ -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
}

View File

@ -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;

View File

@ -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, " ");
}
return help_mask;
free(sstr);
} else {
value = HELP_ALL;
}
}
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;

View File

@ -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);

View File

@ -196,6 +196,7 @@ typedef struct armor_type {
#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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -166,7 +166,7 @@
</construction>
</building>
<building name="castle" capacity="1">
<building name="castle" capacity="1" protection="yes" taxes="true">
<function name="name" value="castle_name"/>
<construction skill="building" minskill="1" maxsize="2" reqsize="1">
<requirement type="stone" quantity="1"/>

View File

@ -759,7 +759,7 @@
<attack type="4" damage="1d7"/>
<attack type="5"/>
</race>
<race name="aquarian" magres="0.000000" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" coastal="yes" walk="yes" giveitem="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
<race name="aquarian" magres="0.000000" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" shipspeed="yes" playerrace="yes" coastal="yes" walk="yes" giveitem="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
<ai splitsize="10000" moverandom="yes" learn="yes"/>
<function name="itemdrop" value="defaultdrops"/>
<skill name="mining" modifier="-2"/>