- 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); money = rmoney(r);
if (money<=0) return; if (money<=0) return;
b = largestbuilding(r, false); b = largestbuilding(r, &is_tax_building, false);
if (b==NULL) return; if (b==NULL) return;
u = buildingowner(r, b); u = buildingowner(r, b);

View File

@ -1404,7 +1404,7 @@ display_cmd(unit * u, struct order * ord)
cmistake(u, ord, 148, MSG_EVENT); cmistake(u, ord, 148, MSG_EVENT);
break; break;
} }
if (b != largestbuilding(r,false)) { if (b != largestbuilding(r, &is_castle, false)) {
cmistake(u, ord, 147, MSG_EVENT); cmistake(u, ord, 147, MSG_EVENT);
break; break;
} }
@ -1639,7 +1639,7 @@ name_cmd(unit * u, struct order * ord)
cmistake(u, ord, 148, MSG_EVENT); cmistake(u, ord, 148, MSG_EVENT);
break; break;
} }
if (b != largestbuilding(r,false)) { if (b != largestbuilding(r, &is_castle, false)) {
cmistake(u, ord, 147, MSG_EVENT); cmistake(u, ord, 147, MSG_EVENT);
break; break;
} }
@ -2920,12 +2920,22 @@ static void age_region(region * r)
{ {
a_age(&r->attribs); a_age(&r->attribs);
handle_event(r->attribs, "timer", r); 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 static void
ageing(void) ageing(void)
{ {
const building_type * bt_castle = bt_find("castle");
faction *f; faction *f;
region *r; region *r;
@ -2993,15 +3003,9 @@ ageing(void)
for (bp=&r->buildings;*bp;) { for (bp=&r->buildings;*bp;) {
building * b = *bp; building * b = *bp;
b = age_building(b); b = age_building(b);
}
if (b==*bp) { blargest = largestbuilding(r, &is_tax_building, false);
if (b->type==bt_castle) {
if (blargest==NULL || b->size>blargest->size) {
blargest = b;
}
}
bp = &(*bp)->next;
}
if (blargest) { if (blargest) {
/* region owners update? */ /* region owners update? */
faction * f = region_get_owner(r); faction * f = region_get_owner(r);
@ -3014,7 +3018,6 @@ ageing(void)
} }
} }
} }
}
static int static int
maxunits(const faction *f) maxunits(const faction *f)

View File

@ -746,7 +746,7 @@ weapon_effskill(troop t, troop enemy, const weapon * w, boolean attacking, boole
} }
/* Burgenbonus, Pferdebonus */ /* 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; skill += 2;
if (wtype) skill = skillmod(urace(tu)->attribs, tu, tu->region, wtype->skill, skill, SMF_RIDING); 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", "tower",
"castle", "castle",
"fortress", "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; const construction * ctype;
int i = 0; int i = 0;
@ -364,10 +384,11 @@ findbuildingtype(const char * name, const struct locale * lang)
void void
register_buildings(void) register_buildings(void)
{ {
register_function((pf_generic)init_smithy, "init_smithy"); register_function((pf_generic)&init_smithy, "init_smithy");
register_function((pf_generic)castle_name, "castle_name"); register_function((pf_generic)&castle_name, "castle_name");
register_function((pf_generic)&fort_name, "fort_name");
#ifdef WDW_PYRAMID #ifdef WDW_PYRAMID
register_function((pf_generic)pyramid_name, "pyramid_name"); register_function((pf_generic)&pyramid_name, "pyramid_name");
#endif #endif
} }

View File

@ -43,6 +43,7 @@ typedef struct maintenance {
#define BTF_MAGIC 0x40 /* magical effect */ #define BTF_MAGIC 0x40 /* magical effect */
#define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */ #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_NAMECHANGE 0x100 /* name and description can be changed more than once */
#define BTF_TAXES 0x200 /* automatic taxes */
typedef struct building_type { typedef struct building_type {
const char * _name; const char * _name;

View File

@ -154,7 +154,10 @@ ExpensiveMigrants(void)
} }
return value; 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 int
AllianceAuto(void) AllianceAuto(void)
{ {
@ -172,20 +175,41 @@ AllianceAuto(void)
free(sstr); 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 int
HelpMask(void) HelpMask(void)
{ {
static int help_mask = 0; static int value = -1;
if (value<0) {
if (help_mask==0) { const char * str = get_param(global.parameters, "rules.help.mask");
help_mask = get_param_int(global.parameters, "rules.help.mask", HELP_ALL); 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 int
AllianceRestricted(void) AllianceRestricted(void)
{ {
@ -593,6 +617,20 @@ int verbosity = 0;
FILE *debug; 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 int
shipspeed(const ship * sh, const unit * u) shipspeed(const ship * sh, const unit * u)
{ {
@ -619,11 +657,13 @@ shipspeed(const ship * sh, const unit * u)
if (u->faction->race == u->race) { if (u->faction->race == u->race) {
/* race bonus for this faction? */ /* race bonus for this faction? */
if (u->race == new_race[RC_AQUARIAN]) { if (fval(u->race, RCF_SHIPSPEED)) {
k += 1; k += 1;
} }
} }
k += ShipSpeedBonus(u);
a = a_find(sh->attribs, &at_speedup); a = a_find(sh->attribs, &at_speedup);
while (a != NULL && a->type==&at_speedup) { while (a != NULL && a->type==&at_speedup) {
k += a->data.sa[0]; k += a->data.sa[0];
@ -837,9 +877,11 @@ static int
autoalliance(const plane * pl, const faction * sf, const faction * f2) autoalliance(const plane * pl, const faction * sf, const faction * f2)
{ {
static boolean init = false; static boolean init = false;
static int automode;
if (!init) { if (!init) {
init_gms(); init_gms();
init = true; init = true;
automode = ~HelpMask();
} }
if (pl && (pl->flags & PFL_FRIENDLY)) return HELP_ALL; if (pl && (pl->flags & PFL_FRIENDLY)) return HELP_ALL;
/* if f2 is a gm in this plane, everyone has an auto-help to it */ /* 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(); if (sf->alliance==f2->alliance) return AllianceAuto();
} }
return 0; return automode;
} }
static int static int
@ -1641,11 +1683,10 @@ cstring(const char *s)
} }
building * building *
largestbuilding (const region * r, boolean imaginary) largestbuilding (const region * r, boolean (*eval)(const struct building *), boolean imaginary)
{ {
static const building_type * btype = NULL; static const building_type * btype = NULL;
building *b, *best = NULL; building *b, *best = NULL;
if (!btype) btype = bt_find("castle"); /* TODO: parameter der funktion? */
/* durch die verw. von '>' statt '>=' werden die aelteren burgen /* durch die verw. von '>' statt '>=' werden die aelteren burgen
* bevorzugt. */ * bevorzugt. */
@ -1654,7 +1695,7 @@ largestbuilding (const region * r, boolean imaginary)
if (imaginary) { if (imaginary) {
const attrib * a = a_find(b->attribs, &at_icastle); const attrib * a = a_find(b->attribs, &at_icastle);
if (!a) continue; if (!a) continue;
if (a->data.v != btype) continue; if (eval && !eval(b)) continue;
} else continue; } else continue;
} }
if (best==NULL || b->size > best->size) if (best==NULL || b->size > best->size)
@ -2548,10 +2589,26 @@ static const int wagetable[7][4] = {
{15, 13, 16, 2} /* Zitadelle */ {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 static int
default_wage(const region *r, const faction * f, const race * rc) 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; int esize = 0;
curse * c; curse * c;
int wage; int wage;

View File

@ -247,8 +247,9 @@ extern char *cstring_i(char *s);
extern const char *unitname(const struct unit * u); extern const char *unitname(const struct unit * u);
extern char * write_unitname(const struct unit * u, char * buffer, size_t size); 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_all(const struct faction * f);
extern int count_migrants (const struct faction * f); extern int count_migrants (const struct faction * f);
extern int count_maxmigrants(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_BLUNT 0x10
#define WTF_SIEGE 0x20 #define WTF_SIEGE 0x20
#define WTF_ARMORPIERCING 0x40 /* armor has only half value */ #define WTF_ARMORPIERCING 0x40 /* armor has only half value */
#define WTF_HORSEBONUS 0x80
typedef struct weapon_type { typedef struct weapon_type {
const item_type * itype; 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_UNARMEDGUARD (1<<23) /* kann ohne Waffen bewachen */
#define RCF_CANSAIL (1<<24) /* Einheit darf Schiffe betreten */ #define RCF_CANSAIL (1<<24) /* Einheit darf Schiffe betreten */
#define RCF_INVISIBLE (1<<25) /* not visible in any report */ #define RCF_INVISIBLE (1<<25) /* not visible in any report */
#define RCF_SHIPSPEED (1<<26) /* race gets +1 on shipspeed */
/* Economic flags */ /* Economic flags */
#define GIVEITEM (1<<1) /* gibt Gegenstände weg */ #define GIVEITEM (1<<1) /* gibt Gegenstände weg */

View File

@ -1337,7 +1337,13 @@ region_get_owner(const struct region * r)
void void
region_set_owner(struct region * r, struct faction * owner, int turn) 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->owner = owner;
r->land->ownership->since_turn = turn; r->land->ownership->since_turn = turn;
} }

View File

@ -62,7 +62,9 @@ struct rawmaterial;
struct donation; struct donation;
struct item; 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 { typedef struct region_owner {
struct faction * 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, "decay", false)) btype->flags |= BTF_DECAY;
if (xml_bvalue(node, "magic", false)) btype->flags |= BTF_MAGIC; if (xml_bvalue(node, "magic", false)) btype->flags |= BTF_MAGIC;
if (xml_bvalue(node, "protection", false)) btype->flags |= BTF_PROTECTION; 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 */ /* reading eressea/buildings/building/construction */
xpath->node = node; 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, "cut", false)) flags |= WTF_CUT;
if (xml_bvalue(node, "blunt", false)) flags |= WTF_BLUNT; if (xml_bvalue(node, "blunt", false)) flags |= WTF_BLUNT;
if (xml_bvalue(node, "siege", false)) flags |= WTF_SIEGE; 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"); propValue = xmlGetProp(node, BAD_CAST "skill");
assert(propValue!=NULL); 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, "illusionary", false)) rc->flags |= RCF_ILLUSIONARY;
if (xml_bvalue(node, "undead", false)) rc->flags |= RCF_UNDEAD; if (xml_bvalue(node, "undead", false)) rc->flags |= RCF_UNDEAD;
if (xml_bvalue(node, "dragon", false)) rc->flags |= RCF_DRAGON; 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, "giveitem", false)) rc->ec_flags |= GIVEITEM;
if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON;

View File

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

View File

@ -759,7 +759,7 @@
<attack type="4" damage="1d7"/> <attack type="4" damage="1d7"/>
<attack type="5"/> <attack type="5"/>
</race> </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"/> <ai splitsize="10000" moverandom="yes" learn="yes"/>
<function name="itemdrop" value="defaultdrops"/> <function name="itemdrop" value="defaultdrops"/>
<skill name="mining" modifier="-2"/> <skill name="mining" modifier="-2"/>