forked from github/server
Archetypes (WIP): "RECRUIT 15 knight"
creates XML-configurable pre-skilled units for game variants with faster reinforcements. Speeding up locale-string lookup a little bit, and making it more unified for different classes of strings (so new ones are easily added).
This commit is contained in:
parent
0fedaf43b2
commit
b27da8c056
|
@ -0,0 +1,124 @@
|
||||||
|
#include <config.h>
|
||||||
|
#include "eressea.h"
|
||||||
|
#include "archetype.h"
|
||||||
|
|
||||||
|
/* kernel includes */
|
||||||
|
#include <kernel/equipment.h>
|
||||||
|
#include <kernel/building.h>
|
||||||
|
#include <kernel/xmlkernel.h>
|
||||||
|
#include <kernel/xmlreader.h>
|
||||||
|
|
||||||
|
/* util includes */
|
||||||
|
#include <util/umlaut.h>
|
||||||
|
#include <util/language.h>
|
||||||
|
#include <util/xml.h>
|
||||||
|
|
||||||
|
/* libxml includes */
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/encoding.h>
|
||||||
|
|
||||||
|
/* libc includes */
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static struct archetype * archetypes;
|
||||||
|
|
||||||
|
const struct archetype *
|
||||||
|
find_archetype(const char * s, const struct locale * lang)
|
||||||
|
{
|
||||||
|
struct tnode * tokens = get_translations(lang, UT_ARCHETYPES);
|
||||||
|
variant token;
|
||||||
|
|
||||||
|
if (findtoken(tokens, s, &token)==E_TOK_SUCCESS) {
|
||||||
|
return (const struct archetype *)token.v;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
register_archetype(archetype * arch)
|
||||||
|
{
|
||||||
|
arch->next = archetypes;
|
||||||
|
archetypes = arch;
|
||||||
|
}
|
||||||
|
|
||||||
|
const archetype *
|
||||||
|
get_archetype(const char * name)
|
||||||
|
{
|
||||||
|
const archetype * arch = archetypes;
|
||||||
|
for (;arch;arch=arch->next) {
|
||||||
|
if (strcmp(name, arch->name)==0) {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init_archetypes(void)
|
||||||
|
{
|
||||||
|
const struct locale * lang = locales;
|
||||||
|
for (;lang;lang=nextlocale(lang)) {
|
||||||
|
variant var;
|
||||||
|
archetype * arch = archetypes;
|
||||||
|
struct tnode * tokens = get_translations(lang, UT_ARCHETYPES);
|
||||||
|
for (;arch;arch=arch->next) {
|
||||||
|
var.v = arch;
|
||||||
|
addtoken(tokens, LOC(lang, arch->name), var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_archetypes(xmlDocPtr doc)
|
||||||
|
{
|
||||||
|
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
||||||
|
xmlXPathObjectPtr result = xmlXPathEvalExpression(BAD_CAST "/eressea/archetypes/archetype", xpath);
|
||||||
|
xmlNodeSetPtr nodes = result->nodesetval;
|
||||||
|
|
||||||
|
xmlChar * property;
|
||||||
|
if (nodes && nodes->nodeNr>0) {
|
||||||
|
xmlNodePtr node = nodes->nodeTab[0];
|
||||||
|
archetype * arch = calloc(1, sizeof(archetype));
|
||||||
|
xmlXPathObjectPtr sub;
|
||||||
|
|
||||||
|
property = xmlGetProp(node, BAD_CAST "name");
|
||||||
|
assert(property!=NULL);
|
||||||
|
arch->name = strdup((const char *)property);
|
||||||
|
xmlFree(property);
|
||||||
|
|
||||||
|
property = xmlGetProp(node, BAD_CAST "equip");
|
||||||
|
if (property!=NULL) {
|
||||||
|
arch->equip = get_equipment((const char*)property);
|
||||||
|
xmlFree(property);
|
||||||
|
} else {
|
||||||
|
arch->equip = get_equipment(arch->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
property = xmlGetProp(node, BAD_CAST "building");
|
||||||
|
if (property!=NULL) {
|
||||||
|
arch->btype = bt_find((const char*)property);
|
||||||
|
xmlFree(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
arch->size = xml_ivalue(node, "cost", 1);
|
||||||
|
|
||||||
|
xpath->node = node;
|
||||||
|
sub = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
||||||
|
if (sub->nodesetval) {
|
||||||
|
xml_readconstruction(xpath, sub->nodesetval, &arch->ctype);
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(sub);
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
|
xmlXPathFreeContext(xpath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
register_archetypes(void)
|
||||||
|
{
|
||||||
|
xml_register_callback(parse_archetypes);
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* vi: set ts=2:
|
||||||
|
+-------------------+
|
||||||
|
| | Enno Rehling <enno@eressea.de>
|
||||||
|
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
|
| (c) 1998 - 2007 | Katja Zedel <katze@felidae.kn-bremen.de>
|
||||||
|
| | Henning Peters <faroul@beyond.kn-bremen.de>
|
||||||
|
+-------------------+
|
||||||
|
|
||||||
|
This program may not be used, modified or distributed
|
||||||
|
without prior permission by the authors of Eressea.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef H_GC_ARCHETYPE
|
||||||
|
#define H_GC_ARCHETYPE
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct archetype {
|
||||||
|
char * name;
|
||||||
|
int size;
|
||||||
|
struct building_type * btype;
|
||||||
|
struct equipment * equip;
|
||||||
|
struct construction * ctype;
|
||||||
|
struct archetype * next;
|
||||||
|
} archetype;
|
||||||
|
|
||||||
|
extern const struct archetype * find_archetype(const char * s, const struct locale * lang);
|
||||||
|
extern void init_archetypes(void);
|
||||||
|
extern const struct archetype * get_archetype(const char * name);
|
||||||
|
extern void register_archetype(struct archetype * arch);
|
||||||
|
extern void register_archetypes(void);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -26,11 +26,13 @@
|
||||||
/* gamecode includes */
|
/* gamecode includes */
|
||||||
#include "laws.h"
|
#include "laws.h"
|
||||||
#include "randenc.h"
|
#include "randenc.h"
|
||||||
|
#include "archetype.h"
|
||||||
|
|
||||||
/* kernel includes */
|
/* kernel includes */
|
||||||
#include <kernel/alchemy.h>
|
#include <kernel/alchemy.h>
|
||||||
#include <kernel/building.h>
|
#include <kernel/building.h>
|
||||||
#include <kernel/calendar.h>
|
#include <kernel/calendar.h>
|
||||||
|
#include <kernel/equipment.h>
|
||||||
#include <kernel/faction.h>
|
#include <kernel/faction.h>
|
||||||
#include <kernel/give.h>
|
#include <kernel/give.h>
|
||||||
#include <kernel/item.h>
|
#include <kernel/item.h>
|
||||||
|
@ -1053,6 +1055,80 @@ maintain_buildings(region * r, boolean crash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
recruit_archetype(unit * u, order * ord)
|
||||||
|
{
|
||||||
|
int n, id;
|
||||||
|
const char * s;
|
||||||
|
|
||||||
|
init_tokens(ord);
|
||||||
|
skip_token();
|
||||||
|
n = geti();
|
||||||
|
s = getstrtoken();
|
||||||
|
id = getid();
|
||||||
|
if (n>0 && s && s[0]) {
|
||||||
|
const archetype * arch = find_archetype(s, u->faction->locale);
|
||||||
|
|
||||||
|
if (u->number>0) {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_must_be_new", ""));
|
||||||
|
/* TODO: error message */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arch==NULL) {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unknown_archetype", "name", s));
|
||||||
|
/* TODO: error message */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (arch->btype && u->building->type!=arch->btype) {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_must_be_in_building", "type", arch->btype));
|
||||||
|
/* TODO: error message */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = build(u, arch->ctype, 0, n);
|
||||||
|
if (n>0) {
|
||||||
|
scale_number(u, n);
|
||||||
|
equip_unit(u, arch->equip);
|
||||||
|
return n;
|
||||||
|
} else switch(n) {
|
||||||
|
case ENOMATERIALS:
|
||||||
|
ADDMSG(&u->faction->msgs, msg_materials_required(u, ord, arch->ctype));
|
||||||
|
return 0;
|
||||||
|
case ELOWSKILL:
|
||||||
|
case ENEEDSKILL:
|
||||||
|
/* no skill, or not enough skill points to build */
|
||||||
|
cmistake(u, ord, 50, MSG_PRODUCE);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
assert(!"unhandled return value from build() in recruit_archetype");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
recruit_classic(void)
|
||||||
|
{
|
||||||
|
static int value = -1;
|
||||||
|
if (value<0) {
|
||||||
|
const char * str = get_param(global.parameters, "recruit.classic");
|
||||||
|
value = str?atoi(str):1;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
recruit_archetypes(void)
|
||||||
|
{
|
||||||
|
static int value = -1;
|
||||||
|
if (value<0) {
|
||||||
|
const char * str = get_param(global.parameters, "recruit.archetypes");
|
||||||
|
value = str?atoi(str):0;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
economics(region *r)
|
economics(region *r)
|
||||||
|
@ -1095,9 +1171,19 @@ economics(region *r)
|
||||||
|
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
order * ord;
|
order * ord;
|
||||||
|
if (!recruit_classic()) {
|
||||||
|
if (u->number>0) continue;
|
||||||
|
}
|
||||||
for (ord = u->orders; ord; ord = ord->next) {
|
for (ord = u->orders; ord; ord = ord->next) {
|
||||||
if (get_keyword(ord) == K_RECRUIT) {
|
if (get_keyword(ord) == K_RECRUIT) {
|
||||||
recruit(u, ord, &recruitorders);
|
if (recruit_archetypes()) {
|
||||||
|
if (recruit_archetype(u, ord)>=0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (recruit_classic()) {
|
||||||
|
recruit(u, ord, &recruitorders);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1142,26 +1228,8 @@ manufacture(unit * u, const item_type * itype, int want)
|
||||||
sk, minskill, itype->rtype, 1));
|
sk, minskill, itype->rtype, 1));
|
||||||
return;
|
return;
|
||||||
case ENOMATERIALS:
|
case ENOMATERIALS:
|
||||||
/* something missing from the list of materials */
|
ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, itype->construction));
|
||||||
strcpy(buf, "Dafür braucht man mindestens:");
|
return;
|
||||||
{
|
|
||||||
int c, n;
|
|
||||||
const construction * cons = itype->construction;
|
|
||||||
char * ch = buf+strlen(buf);
|
|
||||||
assert(cons);
|
|
||||||
for (c=0;cons->materials[c].number; c++) {
|
|
||||||
requirement * m = cons->materials+c;
|
|
||||||
if (c!=0)
|
|
||||||
strcat(ch++, ",");
|
|
||||||
n = m->number / cons->reqsize;
|
|
||||||
sprintf(ch, " %d %s", n?n:1,
|
|
||||||
locale_string(u->faction->locale,
|
|
||||||
resourcename(m->rtype, m->number!=1)));
|
|
||||||
ch = ch+strlen(ch);
|
|
||||||
}
|
|
||||||
mistake(u, u->thisorder, buf, MSG_PRODUCE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (n>0) {
|
if (n>0) {
|
||||||
i_change(&u->items, itype, n);
|
i_change(&u->items, itype, n);
|
||||||
|
@ -1571,26 +1639,8 @@ create_potion(unit * u, const potion_type * ptype, int want)
|
||||||
break;
|
break;
|
||||||
case ENOMATERIALS:
|
case ENOMATERIALS:
|
||||||
/* something missing from the list of materials */
|
/* something missing from the list of materials */
|
||||||
strcpy(buf, "Dafür braucht man mindestens:");
|
ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, ptype->itype->construction));
|
||||||
{
|
return;
|
||||||
int c, n;
|
|
||||||
const construction * cons = ptype->itype->construction;
|
|
||||||
char * ch = buf+strlen(buf);
|
|
||||||
assert(cons);
|
|
||||||
for (c=0;cons->materials[c].number; c++) {
|
|
||||||
const requirement * m = cons->materials+c;
|
|
||||||
if (c!=0)
|
|
||||||
strcat(ch++, ",");
|
|
||||||
n = m->number / cons->reqsize;
|
|
||||||
sprintf(ch, " %d %s", n?n:1,
|
|
||||||
LOC(u->faction->locale,
|
|
||||||
resourcename(m->rtype, m->number!=1)));
|
|
||||||
ch = ch+strlen(ch);
|
|
||||||
}
|
|
||||||
strcat(ch,".");
|
|
||||||
mistake(u, u->thisorder, buf, MSG_PRODUCE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
i_change(&u->items, ptype->itype, built);
|
i_change(&u->items, ptype->itype, built);
|
||||||
|
|
|
@ -277,6 +277,9 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header"
|
Name="Header"
|
||||||
Filter="*.h">
|
Filter="*.h">
|
||||||
|
<File
|
||||||
|
RelativePath=".\archetype.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\creation.h">
|
RelativePath=".\creation.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -308,6 +311,9 @@
|
||||||
RelativePath=".\xmlreport.h">
|
RelativePath=".\xmlreport.h">
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath=".\archetype.c">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\creation.c">
|
RelativePath=".\creation.c">
|
||||||
</File>
|
</File>
|
||||||
|
|
|
@ -608,41 +608,45 @@ int
|
||||||
build(unit * u, const construction * ctype, int completed, int want)
|
build(unit * u, const construction * ctype, int completed, int want)
|
||||||
{
|
{
|
||||||
const construction * type = ctype;
|
const construction * type = ctype;
|
||||||
int skills; /* number of skill points remainig */
|
int skills = INT_MAX; /* number of skill points remainig */
|
||||||
int dm = get_effect(u, oldpotiontype[P_DOMORE]);
|
int basesk = 0;
|
||||||
int made = 0;
|
int made = 0;
|
||||||
int basesk, effsk;
|
|
||||||
|
|
||||||
assert(u->number);
|
|
||||||
if (want<=0) return 0;
|
if (want<=0) return 0;
|
||||||
if (type==NULL) return 0;
|
if (type==NULL) return 0;
|
||||||
if (type->improvement==NULL && completed==type->maxsize)
|
if (type->improvement==NULL && completed==type->maxsize)
|
||||||
return ECOMPLETE;
|
return ECOMPLETE;
|
||||||
|
|
||||||
basesk = effskill(u, type->skill);
|
if (type->skill!=NOSKILL) {
|
||||||
if (basesk==0) return ENEEDSKILL;
|
int effsk;
|
||||||
|
int dm = get_effect(u, oldpotiontype[P_DOMORE]);
|
||||||
|
|
||||||
effsk = basesk;
|
assert(u->number);
|
||||||
if (inside_building(u)) {
|
basesk = effskill(u, type->skill);
|
||||||
effsk = skillmod(u->building->type->attribs, u, u->region, type->skill,
|
if (basesk==0) return ENEEDSKILL;
|
||||||
|
|
||||||
|
effsk = basesk;
|
||||||
|
if (inside_building(u)) {
|
||||||
|
effsk = skillmod(u->building->type->attribs, u, u->region, type->skill,
|
||||||
|
effsk, SMF_PRODUCTION);
|
||||||
|
}
|
||||||
|
effsk = skillmod(type->attribs, u, u->region, type->skill,
|
||||||
effsk, SMF_PRODUCTION);
|
effsk, SMF_PRODUCTION);
|
||||||
}
|
if (effsk<0) return effsk; /* pass errors to caller */
|
||||||
effsk = skillmod(type->attribs, u, u->region, type->skill,
|
if (effsk==0) return ENEEDSKILL;
|
||||||
effsk, SMF_PRODUCTION);
|
|
||||||
if (effsk<0) return effsk; /* pass errors to caller */
|
|
||||||
if (effsk==0) return ENEEDSKILL;
|
|
||||||
|
|
||||||
skills = effsk * u->number;
|
skills = effsk * u->number;
|
||||||
|
|
||||||
/* technically, nimblefinge and domore should be in a global set of
|
/* technically, nimblefinge and domore should be in a global set of
|
||||||
* "game"-attributes, (as at_skillmod) but for a while, we're leaving
|
* "game"-attributes, (as at_skillmod) but for a while, we're leaving
|
||||||
* them in here. */
|
* them in here. */
|
||||||
|
|
||||||
if (dm != 0) {
|
if (dm != 0) {
|
||||||
/* Auswirkung Schaffenstrunk */
|
/* Auswirkung Schaffenstrunk */
|
||||||
dm = min(dm, u->number);
|
dm = min(dm, u->number);
|
||||||
change_effect(u, oldpotiontype[P_DOMORE], -dm);
|
change_effect(u, oldpotiontype[P_DOMORE], -dm);
|
||||||
skills += dm * effsk;
|
skills += dm * effsk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (;want>0 && skills>0;) {
|
for (;want>0 && skills>0;) {
|
||||||
int c, n;
|
int c, n;
|
||||||
|
@ -764,6 +768,23 @@ build(unit * u, const construction * ctype, int completed, int want)
|
||||||
return made;
|
return made;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message *
|
||||||
|
msg_materials_required(unit * u, order * ord, const construction * ctype)
|
||||||
|
{
|
||||||
|
/* something missing from the list of materials */
|
||||||
|
int c;
|
||||||
|
resource * reslist = NULL;
|
||||||
|
|
||||||
|
for (c=0;ctype->materials[c].number; ++c) {
|
||||||
|
resource * res = malloc(sizeof(resource));
|
||||||
|
res->number = ctype->materials[c].number / ctype->reqsize;
|
||||||
|
res->type = ctype->materials[c].rtype;
|
||||||
|
res->next = reslist;
|
||||||
|
reslist = res;
|
||||||
|
}
|
||||||
|
return msg_feedback(u, ord, "build_required", "required", reslist);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
maxbuild(const unit * u, const construction * cons)
|
maxbuild(const unit * u, const construction * cons)
|
||||||
/* calculate maximum size that can be built from available material */
|
/* calculate maximum size that can be built from available material */
|
||||||
|
@ -791,7 +812,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
|
||||||
{
|
{
|
||||||
region * r = u->region;
|
region * r = u->region;
|
||||||
boolean newbuilding = false;
|
boolean newbuilding = false;
|
||||||
int c, built = 0, id;
|
int built = 0, id;
|
||||||
building * b = NULL;
|
building * b = NULL;
|
||||||
/* einmalige Korrektur */
|
/* einmalige Korrektur */
|
||||||
static char buffer[8 + IDSIZE + 1 + NAMESIZE + 1];
|
static char buffer[8 + IDSIZE + 1 + NAMESIZE + 1];
|
||||||
|
@ -874,22 +895,9 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
|
||||||
/* the building is already complete */
|
/* the building is already complete */
|
||||||
cmistake(u, ord, 4, MSG_PRODUCE);
|
cmistake(u, ord, 4, MSG_PRODUCE);
|
||||||
return;
|
return;
|
||||||
case ENOMATERIALS: {
|
case ENOMATERIALS:
|
||||||
/* something missing from the list of materials */
|
ADDMSG(&u->faction->msgs, msg_materials_required(u, ord, btype->construction));
|
||||||
const construction * cons = btype->construction;
|
|
||||||
resource * reslist = NULL;
|
|
||||||
assert(cons);
|
|
||||||
for (c=0;cons->materials[c].number; ++c) {
|
|
||||||
resource * res = malloc(sizeof(resource));
|
|
||||||
res->number = cons->materials[c].number / cons->reqsize;
|
|
||||||
res->type = cons->materials[c].rtype;
|
|
||||||
res->next = reslist;
|
|
||||||
reslist = res;
|
|
||||||
}
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "build_required",
|
|
||||||
"required", reslist));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
case ELOWSKILL:
|
case ELOWSKILL:
|
||||||
case ENEEDSKILL:
|
case ENEEDSKILL:
|
||||||
/* no skill, or not enough skill points to build */
|
/* no skill, or not enough skill points to build */
|
||||||
|
|
|
@ -79,7 +79,7 @@ void sunhash(struct ship * sh);
|
||||||
|
|
||||||
extern int build(struct unit * u, const construction * ctype, int completed, int want);
|
extern int build(struct unit * u, const construction * ctype, int completed, int want);
|
||||||
extern int maxbuild(const struct unit *u, const construction *cons);
|
extern int maxbuild(const struct unit *u, const construction *cons);
|
||||||
|
extern struct message * msg_materials_required(struct unit * u, struct order * ord, const struct construction * ctype);
|
||||||
/** error messages that build may return: */
|
/** error messages that build may return: */
|
||||||
#define ELOWSKILL -1
|
#define ELOWSKILL -1
|
||||||
#define ENEEDSKILL -2
|
#define ENEEDSKILL -2
|
||||||
|
|
|
@ -1489,53 +1489,13 @@ findstr(const char **v, const char *s, unsigned char n)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
|
||||||
UT_NONE,
|
|
||||||
UT_PARAM,
|
|
||||||
UT_ITEM,
|
|
||||||
UT_BUILDING,
|
|
||||||
UT_HERB,
|
|
||||||
UT_POTION,
|
|
||||||
UT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct lstr {
|
|
||||||
const struct locale * lang;
|
|
||||||
struct tnode tokens[UT_MAX];
|
|
||||||
struct tnode skillnames;
|
|
||||||
struct tnode keywords;
|
|
||||||
struct tnode races;
|
|
||||||
struct tnode directions;
|
|
||||||
struct tnode options;
|
|
||||||
struct lstr * next;
|
|
||||||
} * lstrs;
|
|
||||||
|
|
||||||
static struct lstr *
|
|
||||||
get_lnames(const struct locale * lang)
|
|
||||||
{
|
|
||||||
static struct lstr * lnames = NULL;
|
|
||||||
static const struct locale * lastlang = NULL;
|
|
||||||
|
|
||||||
if (lastlang!=lang || lnames==NULL) {
|
|
||||||
lnames = lstrs;
|
|
||||||
while (lnames && lnames->lang!=lang) lnames = lnames->next;
|
|
||||||
if (lnames==NULL) {
|
|
||||||
lnames = calloc(sizeof(struct lstr), 1);
|
|
||||||
lnames->lang = lang;
|
|
||||||
lnames->next = lstrs;
|
|
||||||
lstrs = lnames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lnames;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct race *
|
const struct race *
|
||||||
findrace(const char * s, const struct locale * lang)
|
findrace(const char * s, const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_RACES);
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
if (findtoken(&lnames->races, s, &token)==E_TOK_SUCCESS) {
|
if (findtoken(tokens, s, &token)==E_TOK_SUCCESS) {
|
||||||
return (const struct race *)token.v;
|
return (const struct race *)token.v;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1544,10 +1504,10 @@ findrace(const char * s, const struct locale * lang)
|
||||||
int
|
int
|
||||||
findoption(const char *s, const struct locale * lang)
|
findoption(const char *s, const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_OPTIONS);
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
if (findtoken(&lnames->options, s, &token)==E_TOK_SUCCESS) {
|
if (findtoken(tokens, s, &token)==E_TOK_SUCCESS) {
|
||||||
return (direction_t)token.i;
|
return (direction_t)token.i;
|
||||||
}
|
}
|
||||||
return NODIRECTION;
|
return NODIRECTION;
|
||||||
|
@ -1556,22 +1516,23 @@ findoption(const char *s, const struct locale * lang)
|
||||||
skill_t
|
skill_t
|
||||||
findskill(const char *s, const struct locale * lang)
|
findskill(const char *s, const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_SKILLS);
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
if (findtoken(&lnames->skillnames, s, &token)==E_TOK_NOMATCH) return NOSKILL;
|
if (findtoken(tokens, s, &token)==E_TOK_NOMATCH) return NOSKILL;
|
||||||
return (skill_t)token.i;
|
return (skill_t)token.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyword_t
|
keyword_t
|
||||||
findkeyword(const char *s, const struct locale * lang)
|
findkeyword(const char *s, const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_KEYWORDS);
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
#ifdef AT_PERSISTENT
|
#ifdef AT_PERSISTENT
|
||||||
if (*s == '@') s++;
|
if (*s == '@') s++;
|
||||||
#endif
|
#endif
|
||||||
if (findtoken(&lnames->keywords, s, &token)==E_TOK_NOMATCH) return NOKEYWORD;
|
if (findtoken(tokens, s, &token)==E_TOK_NOMATCH) return NOKEYWORD;
|
||||||
if (global.disabled[token.i]) return NOKEYWORD;
|
if (global.disabled[token.i]) return NOKEYWORD;
|
||||||
return (keyword_t) token.i;
|
return (keyword_t) token.i;
|
||||||
}
|
}
|
||||||
|
@ -1579,12 +1540,11 @@ findkeyword(const char *s, const struct locale * lang)
|
||||||
param_t
|
param_t
|
||||||
findparam(const char *s, const struct locale * lang)
|
findparam(const char *s, const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_PARAMS);
|
||||||
const building_type * btype;
|
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
if (findtoken(&lnames->tokens[UT_PARAM], s, &token)==E_TOK_NOMATCH) {
|
if (findtoken(tokens, s, &token)==E_TOK_NOMATCH) {
|
||||||
btype = findbuildingtype(s, lang);
|
const building_type * btype = findbuildingtype(s, lang);
|
||||||
if (btype!=NULL) return (param_t) P_GEBAEUDE;
|
if (btype!=NULL) return (param_t) P_GEBAEUDE;
|
||||||
return NOPARAM;
|
return NOPARAM;
|
||||||
}
|
}
|
||||||
|
@ -1943,6 +1903,11 @@ createunit(region * r, faction * f, int number, const struct race * rc)
|
||||||
return create_unit(r, f, number, rc, 0, NULL, NULL);
|
return create_unit(r, f, number, rc, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** creates a new unit.
|
||||||
|
*
|
||||||
|
* @param dname: name, set to NULL to get a default.
|
||||||
|
* @param creator: unit to inherit stealth, group, building, ship, etc. from
|
||||||
|
*/
|
||||||
unit *
|
unit *
|
||||||
create_unit(region * r, faction * f, int number, const struct race *urace, int id, const char * dname, unit *creator)
|
create_unit(region * r, faction * f, int number, const struct race *urace, int id, const char * dname, unit *creator)
|
||||||
{
|
{
|
||||||
|
@ -2026,7 +1991,7 @@ create_unit(region * r, faction * f, int number, const struct race *urace, int i
|
||||||
a->data.v = creator;
|
a->data.v = creator;
|
||||||
}
|
}
|
||||||
/* Monster sind grundsätzlich parteigetarnt */
|
/* Monster sind grundsätzlich parteigetarnt */
|
||||||
if(f->no <= 0) fset(u, UFL_PARTEITARNUNG);
|
if (f->no <= 0) fset(u, UFL_PARTEITARNUNG);
|
||||||
|
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
@ -2299,21 +2264,22 @@ init_directions(tnode * root, const struct locale * lang)
|
||||||
{ NULL, NODIRECTION}
|
{ NULL, NODIRECTION}
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_DIRECTIONS);
|
||||||
|
|
||||||
for (i=0; dirs[i].direction!=NODIRECTION;++i) {
|
for (i=0; dirs[i].direction!=NODIRECTION;++i) {
|
||||||
variant token;
|
variant token;
|
||||||
token.i = dirs[i].direction;
|
token.i = dirs[i].direction;
|
||||||
addtoken(&lnames->directions, LOC(lang, dirs[i].name), token);
|
addtoken(tokens, LOC(lang, dirs[i].name), token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
direction_t
|
direction_t
|
||||||
finddirection(const char *s, const struct locale * lang)
|
finddirection(const char *s, const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
struct tnode * tokens = get_translations(lang, UT_DIRECTIONS);
|
||||||
variant token;
|
variant token;
|
||||||
|
|
||||||
if (findtoken(&lnames->directions, s, &token)==E_TOK_SUCCESS) {
|
if (findtoken(tokens, s, &token)==E_TOK_SUCCESS) {
|
||||||
return (direction_t)token.i;
|
return (direction_t)token.i;
|
||||||
}
|
}
|
||||||
return NODIRECTION;
|
return NODIRECTION;
|
||||||
|
@ -2322,37 +2288,48 @@ finddirection(const char *s, const struct locale * lang)
|
||||||
static void
|
static void
|
||||||
init_locale(const struct locale * lang)
|
init_locale(const struct locale * lang)
|
||||||
{
|
{
|
||||||
struct lstr * lnames = get_lnames(lang);
|
|
||||||
variant var;
|
variant var;
|
||||||
int i;
|
int i;
|
||||||
const struct race * rc;
|
const struct race * rc;
|
||||||
|
struct tnode * tokens;
|
||||||
|
|
||||||
init_directions(&lnames->directions, lang);
|
tokens = get_translations(lang, UT_DIRECTIONS);
|
||||||
|
init_directions(tokens, lang);
|
||||||
|
|
||||||
|
tokens = get_translations(lang, UT_RACES);
|
||||||
for (rc=races;rc;rc=rc->next) {
|
for (rc=races;rc;rc=rc->next) {
|
||||||
var.v = (void*)rc;
|
var.v = (void*)rc;
|
||||||
addtoken(&lnames->races, LOC(lang, rc_name(rc, 1)), var);
|
addtoken(tokens, LOC(lang, rc_name(rc, 1)), var);
|
||||||
addtoken(&lnames->races, LOC(lang, rc_name(rc, 0)), var);
|
addtoken(tokens, LOC(lang, rc_name(rc, 0)), var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokens = get_translations(lang, UT_PARAMS);
|
||||||
for (i=0;i!=MAXPARAMS;++i) {
|
for (i=0;i!=MAXPARAMS;++i) {
|
||||||
var.i = i;
|
var.i = i;
|
||||||
addtoken(&lnames->tokens[UT_PARAM], LOC(lang, parameters[i]), var);
|
addtoken(tokens, LOC(lang, parameters[i]), var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokens = get_translations(lang, UT_SKILLS);
|
||||||
for (i=0;i!=MAXSKILLS;++i) {
|
for (i=0;i!=MAXSKILLS;++i) {
|
||||||
if (i!=SK_TRADE || !TradeDisabled()) {
|
if (i!=SK_TRADE || !TradeDisabled()) {
|
||||||
const char * skname = skillname((skill_t)i, lang);
|
const char * skname = skillname((skill_t)i, lang);
|
||||||
if (skname!=NULL) {
|
if (skname!=NULL) {
|
||||||
var.i = i;
|
var.i = i;
|
||||||
addtoken(&lnames->skillnames, skname, var);
|
addtoken(tokens, skname, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokens = get_translations(lang, UT_KEYWORDS);
|
||||||
for (i=0;i!=MAXKEYWORDS;++i) {
|
for (i=0;i!=MAXKEYWORDS;++i) {
|
||||||
var.i = i;
|
var.i = i;
|
||||||
addtoken(&lnames->keywords, LOC(lang, keywords[i]), var);
|
addtoken(tokens, LOC(lang, keywords[i]), var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokens = get_translations(lang, UT_OPTIONS);
|
||||||
for (i=0;i!=MAXOPTIONS;++i) {
|
for (i=0;i!=MAXOPTIONS;++i) {
|
||||||
var.i = i;
|
var.i = i;
|
||||||
addtoken(&lnames->options, LOC(lang, options[i]), var);
|
addtoken(tokens, LOC(lang, options[i]), var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,9 @@
|
||||||
<File
|
<File
|
||||||
RelativePath=".\unit.c">
|
RelativePath=".\unit.c">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\xmlkernel.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\xmlreader.c">
|
RelativePath=".\xmlreader.c">
|
||||||
</File>
|
</File>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* vi: set ts=2:
|
||||||
|
+-------------------+
|
||||||
|
| | Enno Rehling <enno@eressea.de>
|
||||||
|
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
|
| (c) 1998 - 2007 | Katja Zedel <katze@felidae.kn-bremen.de>
|
||||||
|
| | Henning Peters <faroul@beyond.kn-bremen.de>
|
||||||
|
+-------------------+
|
||||||
|
|
||||||
|
This program may not be used, modified or distributed
|
||||||
|
without prior permission by the authors of Eressea.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef H_KRNL_XML
|
||||||
|
#define H_KRNL_XML
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
|
||||||
|
extern void xml_readconstruction(xmlXPathContextPtr xpath, xmlNodeSetPtr nodeSet, struct construction ** consPtr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -159,13 +159,13 @@ xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
xml_readconstruction(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr, construction ** consPtr)
|
xml_readconstruction(xmlXPathContextPtr xpath, xmlNodeSetPtr nodeSet, construction ** consPtr)
|
||||||
{
|
{
|
||||||
xmlNodePtr pushNode = xpath->node;
|
xmlNodePtr pushNode = xpath->node;
|
||||||
int k;
|
int k;
|
||||||
for (k=0;k!=nodeNr;++k) {
|
for (k=0;k!=nodeSet->nodeNr;++k) {
|
||||||
xmlNodePtr node = nodeTab[k];
|
xmlNodePtr node = nodeSet->nodeTab[k];
|
||||||
xmlChar * property;
|
xmlChar * property;
|
||||||
construction * con;
|
construction * con;
|
||||||
xmlXPathObjectPtr req;
|
xmlXPathObjectPtr req;
|
||||||
|
@ -176,10 +176,13 @@ xml_readconstruction(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr,
|
||||||
consPtr = &con->improvement;
|
consPtr = &con->improvement;
|
||||||
|
|
||||||
property = xmlGetProp(node, BAD_CAST "skill");
|
property = xmlGetProp(node, BAD_CAST "skill");
|
||||||
assert(property!=NULL);
|
if (property!=NULL) {
|
||||||
con->skill = sk_find((const char*)property);
|
con->skill = sk_find((const char*)property);
|
||||||
assert(con->skill!=NOSKILL);
|
assert(con->skill!=NOSKILL);
|
||||||
xmlFree(property);
|
xmlFree(property);
|
||||||
|
} else {
|
||||||
|
con->skill = NOSKILL;
|
||||||
|
}
|
||||||
|
|
||||||
con->maxsize = xml_ivalue(node, "maxsize", -1);
|
con->maxsize = xml_ivalue(node, "maxsize", -1);
|
||||||
con->minskill = xml_ivalue(node, "minskill", -1);
|
con->minskill = xml_ivalue(node, "minskill", -1);
|
||||||
|
@ -207,7 +210,6 @@ xml_readconstruction(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr,
|
||||||
|
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(req);
|
xmlXPathFreeObject(req);
|
||||||
|
|
||||||
}
|
}
|
||||||
xpath->node = pushNode;
|
xpath->node = pushNode;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +279,7 @@ parse_buildings(xmlDocPtr doc)
|
||||||
/* reading eressea/buildings/building/construction */
|
/* reading eressea/buildings/building/construction */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
||||||
xml_readconstruction(xpath, result->nodesetval->nodeTab, result->nodesetval->nodeNr, &btype->construction);
|
xml_readconstruction(xpath, result->nodesetval, &btype->construction);
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
if (gamecode_enabled) {
|
if (gamecode_enabled) {
|
||||||
|
@ -494,7 +496,7 @@ parse_ships(xmlDocPtr doc)
|
||||||
/* reading eressea/ships/ship/construction */
|
/* reading eressea/ships/ship/construction */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
||||||
xml_readconstruction(xpath, result->nodesetval->nodeTab, result->nodesetval->nodeNr, &st->construction);
|
xml_readconstruction(xpath, result->nodesetval, &st->construction);
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
/* reading eressea/ships/ship/coast */
|
/* reading eressea/ships/ship/coast */
|
||||||
|
@ -754,7 +756,7 @@ xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
|
||||||
/* reading item/construction */
|
/* reading item/construction */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
||||||
xml_readconstruction(xpath, result->nodesetval->nodeTab, result->nodesetval->nodeNr, &itype->construction);
|
xml_readconstruction(xpath, result->nodesetval, &itype->construction);
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
/* reading item/weapon */
|
/* reading item/weapon */
|
||||||
|
@ -1206,7 +1208,7 @@ parse_equipment(xmlDocPtr doc)
|
||||||
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
||||||
xmlXPathObjectPtr xpathRaces;
|
xmlXPathObjectPtr xpathRaces;
|
||||||
|
|
||||||
/* reading eressea/races/race */
|
/* reading eressea/equipment/set */
|
||||||
xpathRaces = xmlXPathEvalExpression(BAD_CAST "/eressea/equipment/set", xpath);
|
xpathRaces = xmlXPathEvalExpression(BAD_CAST "/eressea/equipment/set", xpath);
|
||||||
if (xpathRaces->nodesetval) {
|
if (xpathRaces->nodesetval) {
|
||||||
xmlNodeSetPtr nsetRaces = xpathRaces->nodesetval;
|
xmlNodeSetPtr nsetRaces = xpathRaces->nodesetval;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
+-------------------+
|
+-------------------+
|
||||||
| | Enno Rehling <enno@eressea.de>
|
| | Enno Rehling <enno@eressea.de>
|
||||||
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
|
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
| (c) 1998 - 2004 | Katja Zedel <katze@felidae.kn-bremen.de>
|
| (c) 1998 - 2007 | Katja Zedel <katze@felidae.kn-bremen.de>
|
||||||
| | Henning Peters <faroul@beyond.kn-bremen.de>
|
| | Henning Peters <faroul@beyond.kn-bremen.de>
|
||||||
+-------------------+
|
+-------------------+
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "goodies.h"
|
#include "goodies.h"
|
||||||
|
#include "umlaut.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -44,6 +45,8 @@ find_locale(const char * name)
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nextlocaleindex = 0;
|
||||||
|
|
||||||
locale *
|
locale *
|
||||||
make_locale(const char * name)
|
make_locale(const char * name)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +60,8 @@ make_locale(const char * name)
|
||||||
l->hashkey = hkey;
|
l->hashkey = hkey;
|
||||||
l->name = strdup(name);
|
l->name = strdup(name);
|
||||||
l->next = locales;
|
l->next = locales;
|
||||||
|
l->index = nextlocaleindex++;
|
||||||
|
assert(nextlocaleindex<=MAXLOCALES);
|
||||||
locales = l;
|
locales = l;
|
||||||
if (default_locale==NULL) default_locale = l;
|
if (default_locale==NULL) default_locale = l;
|
||||||
return l;
|
return l;
|
||||||
|
@ -219,3 +224,22 @@ nextlocale(const struct locale * lang)
|
||||||
{
|
{
|
||||||
return lang->next;
|
return lang->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct lstr {
|
||||||
|
tnode tokens[UT_MAX];
|
||||||
|
} lstr;
|
||||||
|
|
||||||
|
static lstr lstrs[MAXLOCALES];
|
||||||
|
|
||||||
|
struct tnode *
|
||||||
|
get_translations(const struct locale * lang, int index)
|
||||||
|
{
|
||||||
|
static struct lstr * lnames = NULL;
|
||||||
|
static const struct locale * lastlang = NULL;
|
||||||
|
|
||||||
|
assert(lang->index<MAXLOCALES || "you have to increase MAXLOCALES and recompile");
|
||||||
|
if (lang->index<MAXLOCALES) {
|
||||||
|
return lstrs[lang->index].tokens+index;
|
||||||
|
}
|
||||||
|
return lstrs[0].tokens+index;
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,19 @@ extern struct locale * default_locale;
|
||||||
extern struct locale * locales;
|
extern struct locale * locales;
|
||||||
extern struct locale * nextlocale(const struct locale * lang);
|
extern struct locale * nextlocale(const struct locale * lang);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UT_PARAMS,
|
||||||
|
UT_KEYWORDS,
|
||||||
|
UT_SKILLS,
|
||||||
|
UT_RACES,
|
||||||
|
UT_OPTIONS,
|
||||||
|
UT_DIRECTIONS,
|
||||||
|
UT_ARCHETYPES,
|
||||||
|
UT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tnode * get_translations(const struct locale * lang, int index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* feel that you need to include it, it's a sure sign that you're trying to
|
* feel that you need to include it, it's a sure sign that you're trying to
|
||||||
* do something BAD. */
|
* do something BAD. */
|
||||||
|
|
||||||
|
#define MAXLOCALES 3
|
||||||
#define SMAXHASH 2048
|
#define SMAXHASH 2048
|
||||||
typedef struct locale_str {
|
typedef struct locale_str {
|
||||||
unsigned int hashkey;
|
unsigned int hashkey;
|
||||||
|
@ -14,6 +15,7 @@ typedef struct locale_str {
|
||||||
} locale_str;
|
} locale_str;
|
||||||
|
|
||||||
typedef struct locale {
|
typedef struct locale {
|
||||||
|
int index;
|
||||||
struct locale * next;
|
struct locale * next;
|
||||||
unsigned int hashkey;
|
unsigned int hashkey;
|
||||||
const char * name;
|
const char * name;
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* gamecode includes */
|
/* gamecode includes */
|
||||||
|
#include <gamecode/archetype.h>
|
||||||
#include <gamecode/economy.h>
|
#include <gamecode/economy.h>
|
||||||
#include <gamecode/items.h>
|
#include <gamecode/items.h>
|
||||||
#include <gamecode/laws.h>
|
#include <gamecode/laws.h>
|
||||||
|
@ -223,6 +224,7 @@ game_init(void)
|
||||||
register_ships();
|
register_ships();
|
||||||
register_itemfunctions();
|
register_itemfunctions();
|
||||||
register_spells();
|
register_spells();
|
||||||
|
register_archetypes();
|
||||||
#ifdef DUNGEON_MODULE
|
#ifdef DUNGEON_MODULE
|
||||||
register_dungeon();
|
register_dungeon();
|
||||||
#endif
|
#endif
|
||||||
|
@ -245,6 +247,7 @@ game_init(void)
|
||||||
init_locales();
|
init_locales();
|
||||||
/* init_resources(); must be done inside the xml-read, because requirements use items */
|
/* init_resources(); must be done inside the xml-read, because requirements use items */
|
||||||
|
|
||||||
|
init_archetypes();
|
||||||
init_attributes();
|
init_attributes();
|
||||||
init_races();
|
init_races();
|
||||||
init_itemtypes();
|
init_itemtypes();
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<eressea xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
|
<xi:include href="messages.xml"/>
|
||||||
|
|
||||||
|
<!-- Localization -->
|
||||||
|
<xi:include href="de/strings.xml"/>
|
||||||
|
<xi:include href="en/strings.xml"/>
|
||||||
|
|
||||||
|
<xi:include href="resources.xml"/>
|
||||||
|
<xi:include href="spoils.xml"/>
|
||||||
|
<xi:include href="races.xml"/>
|
||||||
|
<xi:include href="prefixes.xml"/>
|
||||||
|
<xi:include href="ships.xml"/>
|
||||||
|
<xi:include href="rts/buildings.xml"/>
|
||||||
|
<xi:include href="rts/units.xml"/>
|
||||||
|
<xi:include href="eressea/calendar.xml"/>
|
||||||
|
<xi:include href="equipment.xml"/>
|
||||||
|
<xi:include href="spells.xml"/>
|
||||||
|
<xi:include href="terrains.xml"/>
|
||||||
|
<xi:include href="dungeons.xml"/>
|
||||||
|
|
||||||
|
<game name="Eressea" welcome="eressea" learningbydoing="0.0">
|
||||||
|
<!-- Game specific settings -->
|
||||||
|
<order name="MEINUNG" disable="yes"/>
|
||||||
|
<order name="MAGIEGEBIET" disable="yes"/>
|
||||||
|
<order name="LEHREN" disable="yes"/>
|
||||||
|
<order name="SPIONIEREN" disable="yes"/>
|
||||||
|
<order name="SABOTIEREN" disable="yes"/>
|
||||||
|
<order name="ARBEITEN" disable="yes"/>
|
||||||
|
<order name="KRIEG" disable="yes"/>
|
||||||
|
<order name="FRIEDEN" disable="yes"/>
|
||||||
|
<order name="FORSCHEN" disable="yes"/>
|
||||||
|
<order name="TARNEN" disable="yes"/>
|
||||||
|
<order name="TREIBEN" disable="yes"/>
|
||||||
|
<order name="UNTERHALTEN" disable="yes"/>
|
||||||
|
<order name="KAUFEN" disable="yes"/>
|
||||||
|
<order name="VERKAUFEN" disable="yes"/>
|
||||||
|
<order name="ZUECHTEN" disable="yes"/>
|
||||||
|
<order name="NEUSTART" disable="yes"/>
|
||||||
|
<order name="OPFERE" disable="yes"/>
|
||||||
|
<order name="LIEFERE" disable="yes"/>
|
||||||
|
<order name="BETEN" disable="yes"/>
|
||||||
|
<order name="JIHAD" disable="yes"/>
|
||||||
|
<order name="GM" disable="yes"/>
|
||||||
|
<order name="INFO" disable="yes"/>
|
||||||
|
<order name="WERWESEN" disable="yes"/>
|
||||||
|
<order name="ALLIANZ" disable="yes"/>
|
||||||
|
<order name="XONTORMIA" disable="yes"/>
|
||||||
|
<order name="SYNONYM" disable="yes"/>
|
||||||
|
|
||||||
|
<skill name="alchemy" enable="true"/>
|
||||||
|
<skill name="crossbow" enable="true"/>
|
||||||
|
<skill name="mining" enable="true"/>
|
||||||
|
<skill name="bow" enable="true"/>
|
||||||
|
<skill name="building" enable="true"/>
|
||||||
|
<skill name="trade" enable="false"/>
|
||||||
|
<skill name="forestry" enable="true"/>
|
||||||
|
<skill name="catapult" enable="true"/>
|
||||||
|
<skill name="herbalism" enable="true"/>
|
||||||
|
<skill name="magic" enable="true"/>
|
||||||
|
<skill name="training" enable="true"/>
|
||||||
|
<skill name="riding" enable="true"/>
|
||||||
|
<skill name="armorer" enable="true"/>
|
||||||
|
<skill name="shipcraft" enable="true"/>
|
||||||
|
<skill name="melee" enable="true"/>
|
||||||
|
<skill name="sailing" enable="true"/>
|
||||||
|
<skill name="polearm" enable="true"/>
|
||||||
|
<skill name="espionage" enable="false"/>
|
||||||
|
<skill name="quarrying" enable="true"/>
|
||||||
|
<skill name="roadwork" enable="true"/>
|
||||||
|
<skill name="tactics" enable="false"/>
|
||||||
|
<skill name="stealth" enable="false"/>
|
||||||
|
<skill name="entertainment" enable="false"/>
|
||||||
|
<skill name="weaponsmithing" enable="true"/>
|
||||||
|
<skill name="cartmaking" enable="true"/>
|
||||||
|
<skill name="perception" enable="false"/>
|
||||||
|
<skill name="taxation" enable="false"/>
|
||||||
|
<skill name="stamina" enable="true"/>
|
||||||
|
<skill name="unarmed" enable="true"/>
|
||||||
|
|
||||||
|
<param name="recruit.classic" value="0"/>
|
||||||
|
<param name="recruit.archetypes" value="1"/>
|
||||||
|
<param name="study.newskills" value="false"/>
|
||||||
|
<param name="entertain.base" value="0"/>
|
||||||
|
<param name="entertain.perlevel" value="20"/>
|
||||||
|
<param name="nmr.timeout" value="4"/>
|
||||||
|
<param name="nmr.removenewbie" value="10"/>
|
||||||
|
<param name="GiveRestriction" value="3"/>
|
||||||
|
<param name="hunger.long" value="1"/>
|
||||||
|
<param name="rules.check_overload" value="0"/>
|
||||||
|
</game>
|
||||||
|
<xi:include href="eressea/de/strings.xml"/>
|
||||||
|
<xi:include href="eressea/en/strings.xml"/>
|
||||||
|
<xi:include href="eressea/races.xml"/>
|
||||||
|
<xi:include href="eressea/items.xml"/>
|
||||||
|
<xi:include href="eressea/artrewards.xml"/>
|
||||||
|
<xi:include href="eressea/dungeons.xml"/>
|
||||||
|
<xi:include href="eressea/temple.xml"/>
|
||||||
|
<strings>
|
||||||
|
<string name="mailto">
|
||||||
|
<text locale="de">eressea-server@eressea.upb.de</text>
|
||||||
|
<text locale="en">eressea-server@eressea.upb.de</text>
|
||||||
|
</string>
|
||||||
|
<string name="newbie_info_1">
|
||||||
|
<text locale="de">Bitte denke daran, deine Befehle mit dem Betreff
|
||||||
|
ERESSEA BEFEHLE an eressea-server@eressea.upb.de zu senden.</text>
|
||||||
|
<text locale="en">Remember to send your orders to
|
||||||
|
eressea-server@eressea.upb.de with the subject ERESSEA ORDERS.</text>
|
||||||
|
</string>
|
||||||
|
<string name="mailcmd">
|
||||||
|
<text locale="de">ERESSEA BEFEHLE</text>
|
||||||
|
<text locale="en">ERESSEA ORDERS</text>
|
||||||
|
</string>
|
||||||
|
</strings>
|
||||||
|
</eressea>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<buildings>
|
||||||
|
|
||||||
|
<building name="castle" capacity="1">
|
||||||
|
<function name="name" value="castle_name"/>
|
||||||
|
<construction skill="building" minskill="1" maxsize="2" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
<construction skill="building" minskill="1" maxsize="8" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
<construction skill="building" minskill="2" maxsize="40" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
<construction skill="building" minskill="3" maxsize="200" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
<construction skill="building" minskill="4" maxsize="1000" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
<construction skill="building" minskill="5" maxsize="5000" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
<construction skill="building" minskill="6" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
</building>
|
||||||
|
|
||||||
|
<building name="barracks">
|
||||||
|
<construction skill="building" minskill="1" maxsize="10" reqsize="1">
|
||||||
|
<requirement type="stone" quantity="1"/>
|
||||||
|
<requirement type="log" quantity="1"/>
|
||||||
|
<requirement type="money" quantity="100"/>
|
||||||
|
</construction>
|
||||||
|
</building>
|
||||||
|
|
||||||
|
</buildings>
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<equipment>
|
||||||
|
|
||||||
|
<!-- archetypes -->
|
||||||
|
<set name="pikeman">
|
||||||
|
<skill name="polearm" level="1"/>
|
||||||
|
<skill name="stamina" level="1"/>
|
||||||
|
</set>
|
||||||
|
|
||||||
|
<set name="swordsman">
|
||||||
|
<skill name="melee" level="1"/>
|
||||||
|
<skill name="stamina" level="1"/>
|
||||||
|
</set>
|
||||||
|
|
||||||
|
<set name="knight">
|
||||||
|
<skill name="melee" level="3"/>
|
||||||
|
<skill name="polearm" level="3"/>
|
||||||
|
<skill name="stamina" level="3"/>
|
||||||
|
<skill name="riding" level="3"/>
|
||||||
|
</set>
|
||||||
|
|
||||||
|
<set name="craftsman">
|
||||||
|
<skill name="building" level="1"/>
|
||||||
|
</set>
|
||||||
|
|
||||||
|
</equipment>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<archetypes>
|
||||||
|
|
||||||
|
<archetype name="swordsman" building="barracks" cost="10">
|
||||||
|
<construction>
|
||||||
|
<requirement type="money" quantity="100"/>
|
||||||
|
</construction>
|
||||||
|
</building>
|
||||||
|
|
||||||
|
<archetype name="pikeman" building="barracks" cost="10">
|
||||||
|
<construction>
|
||||||
|
<requirement type="money" quantity="100"/>
|
||||||
|
</construction>
|
||||||
|
</building>
|
||||||
|
|
||||||
|
<archetype name="knight" building="barracks" cost="100">
|
||||||
|
<construction>
|
||||||
|
<requirement type="money" quantity="1000"/>
|
||||||
|
<requirement type="laen" quantity="1"/>
|
||||||
|
</construction>
|
||||||
|
</building>
|
||||||
|
|
||||||
|
<archetype name="craftsman" building="castle" cost="10">
|
||||||
|
<construction>
|
||||||
|
<requirement type="money" quantity="100"/>
|
||||||
|
</construction>
|
||||||
|
</building>
|
||||||
|
|
||||||
|
</archetypes>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
Aenderungen fuer Eressea RTS:
|
||||||
|
|
||||||
|
* Befehle abgeschafft:
|
||||||
|
|
||||||
|
ARBEITEN, LEHREN, SPIONIEREN, SABOTIEREN, KRIEG, FRIEDEN, FORSCHEN, TARNEN, TREIBEN, UNTERHALTEN, KAUFEN, VERKAUFEN, ZUECHTEN, LIEFERE, MEINUNG, MAGIEGEBIET, NEUSTART, OPFERE, BETEN, JIHAD, INFO, GM, WERWESEN, ALLIANZ, XONTORMIA, SYNONYM
|
||||||
|
|
||||||
|
* Learning by doing abgeschafft.
|
||||||
|
|
||||||
|
* Skills disabled:
|
||||||
|
|
||||||
|
espionage, entertainment, taxation, tactics, stealth, trade, perception
|
||||||
|
|
||||||
|
* Alle Gebaeude entfernt, mit Ausnahme von Burgen
|
||||||
|
|
||||||
|
* Keine NPC-Monster
|
||||||
|
|
||||||
|
* Einheiten koennen ueber ihre Grundskills hinaus keine neuen Skills lernen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Offene Fragen:
|
||||||
|
|
||||||
|
* Soll es eine Maximalanzahl Einheiten geben?
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
function loadscript(name)
|
||||||
|
local script = scriptpath .. "/" .. name
|
||||||
|
print("- loading " .. script)
|
||||||
|
if pcall(dofile, script)==0 then
|
||||||
|
print("Could not load " .. script)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function change_locales()
|
||||||
|
-- local localechange = { }
|
||||||
|
local localechange = { de = { "bLub" } }
|
||||||
|
|
||||||
|
for loc, flist in localechange do
|
||||||
|
for index, name in flist do
|
||||||
|
f = get_faction(atoi36(name))
|
||||||
|
if f ~= nil then
|
||||||
|
f.locale = loc
|
||||||
|
print("LOCALECHANGE ", f, loc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function run_scripts()
|
||||||
|
scripts = {
|
||||||
|
"spells.lua",
|
||||||
|
"extensions.lua",
|
||||||
|
"familiars.lua",
|
||||||
|
"write_emails.lua"
|
||||||
|
}
|
||||||
|
for index in scripts do
|
||||||
|
loadscript(scripts[index])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function process(orders)
|
||||||
|
-- initialize starting equipment for new players
|
||||||
|
equipment_setitem("new_faction", "log", "30");
|
||||||
|
equipment_setitem("new_faction", "stone", "30");
|
||||||
|
equipment_setitem("new_faction", "money", "4200");
|
||||||
|
|
||||||
|
file = "" .. get_turn()
|
||||||
|
if read_game(file)~=0 then
|
||||||
|
print("could not read game")
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
init_summary()
|
||||||
|
|
||||||
|
-- run the turn:
|
||||||
|
if read_orders(orders) ~= 0 then
|
||||||
|
print("could not read " .. orders)
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
run_scripts()
|
||||||
|
|
||||||
|
plan_monsters()
|
||||||
|
|
||||||
|
local nmrs = get_nmrs(1)
|
||||||
|
if nmrs >= 70 then
|
||||||
|
print("Shit. More than 70 factions with 1 NMR (" .. nmrs .. ")")
|
||||||
|
write_summary()
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
print (nmrs .. " Factions with 1 NMR")
|
||||||
|
|
||||||
|
process_orders()
|
||||||
|
|
||||||
|
-- post-turn updates:
|
||||||
|
update_guards()
|
||||||
|
update_scores()
|
||||||
|
|
||||||
|
change_locales()
|
||||||
|
|
||||||
|
-- use newfactions file to place out new players
|
||||||
|
autoseed(basepath .. "/newfactions", false)
|
||||||
|
|
||||||
|
write_passwords()
|
||||||
|
write_reports()
|
||||||
|
write_emails()
|
||||||
|
write_summary()
|
||||||
|
|
||||||
|
file = "" .. get_turn()
|
||||||
|
if write_game(file)~=0 then
|
||||||
|
print("could not write game")
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- main body of script
|
||||||
|
--
|
||||||
|
|
||||||
|
-- orderfile: contains the name of the orders.
|
||||||
|
if orderfile==nil then
|
||||||
|
print "you must specify an orderfile"
|
||||||
|
else
|
||||||
|
process(orderfile)
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue