diff --git a/src/common/gamecode/Jamfile b/src/common/gamecode/Jamfile index 506a3eb5b..084a7b9c9 100644 --- a/src/common/gamecode/Jamfile +++ b/src/common/gamecode/Jamfile @@ -8,9 +8,11 @@ SubDirHdrs $(SUBDIR)/../.. ; SubDirHdrs $(XMLHDRS) ; SOURCES = + archetype.c creation.c creport.c economy.c + give.c items.c laws.c luck.c diff --git a/src/common/gamecode/archetype.c b/src/common/gamecode/archetype.c index 60b432235..8dc3c814c 100644 --- a/src/common/gamecode/archetype.c +++ b/src/common/gamecode/archetype.c @@ -108,6 +108,26 @@ parse_archetypes(xmlDocPtr doc) arch->size = xml_ivalue(node, "cost", 0); + xpath->node = node; + sub = xmlXPathEvalExpression(BAD_CAST "allow|deny", xpath); + if (sub->nodesetval && sub->nodesetval->nodeNr) { + int k; + arch->rules = calloc(sub->nodesetval->nodeNr+1, sizeof(rule)); + for (k=0;k!=sub->nodesetval->nodeNr;++k) { + xmlNodePtr rule = sub->nodesetval->nodeTab[k]; + arch->rules[k].allow = (rule->name[0]=='a'); + + property = xmlGetProp(rule, BAD_CAST "property"); + arch->rules[k].property = strdup((const char *)property); + xmlFree(property); + + property = xmlGetProp(rule, BAD_CAST "value"); + arch->rules[k].value = strdup((const char *)property); + xmlFree(property); + } + } + xmlXPathFreeObject(sub); + xpath->node = node; sub = xmlXPathEvalExpression(BAD_CAST "construction", xpath); if (sub->nodesetval) { diff --git a/src/common/gamecode/archetype.h b/src/common/gamecode/archetype.h index 6c1eb4003..f500794bc 100644 --- a/src/common/gamecode/archetype.h +++ b/src/common/gamecode/archetype.h @@ -17,13 +17,20 @@ without prior permission by the authors of Eressea. extern "C" { #endif + typedef struct rule { + boolean allow; + char * property; + char * value; + } rule; + typedef struct archetype { + struct archetype * next; char * name[2]; int size; struct building_type * btype; struct equipment * equip; struct construction * ctype; - struct archetype * next; + struct rule * rules; } archetype; extern const struct archetype * find_archetype(const char * s, const struct locale * lang); diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index d0c372d41..4c55ff7f0 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -24,6 +24,7 @@ #include "economy.h" /* gamecode includes */ +#include "give.h" #include "laws.h" #include "randenc.h" #include "archetype.h" @@ -34,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -1081,6 +1081,37 @@ recruit_archetype(unit * u, order * ord) /* TODO: error message */ return 0; } + if (arch->rules) { + /* Simple allow/deny style restrictions for archetypes (let only humans + * recruit gamedesigners, etc). These need to be more powerful to be + * useful, and the current way they are implemented is not, but the + * general idea strikes me as good. Also, feedback should be configurable + * for each failed rule. + */ + int k; + for (k=0;arch->rules[k].property;++k) { + boolean match = false; + if (arch->rules[k].value[0]=='*') match = true; + else if (strcmp(arch->rules[k].property, "race")==0) { + const race * rc = rc_find(arch->rules[k].value); + assert(rc); + if (rc==u->race) match = true; + } else if (strcmp(arch->rules[k].property, "building")==0) { + const building_type * btype = bt_find(arch->rules[k].value); + assert(btype); + if (u->building && u->building->type==btype) match = true; + } + if (match) { + if (arch->rules[k].allow) break; + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "recruit_rule_fail", + "property value", arch->rules[k].property, arch->rules[k].value)); + /* TODO: error message */ + return 0; + } + } + } + } if (arch->btype) { if (u->building==NULL || u->building->type!=arch->btype) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_must_be_in_building", "type", arch->btype)); @@ -1131,7 +1162,7 @@ recruit_archetype(unit * u, order * ord) return -1; } -static int +int recruit_classic(void) { static int value = -1; @@ -1142,7 +1173,7 @@ recruit_classic(void) return value; } -static int +int recruit_archetypes(void) { static int value = -1; diff --git a/src/common/gamecode/economy.h b/src/common/gamecode/economy.h index 4262a47a8..2f11538f9 100644 --- a/src/common/gamecode/economy.h +++ b/src/common/gamecode/economy.h @@ -55,6 +55,8 @@ void maintain_buildings(struct region * r, boolean crash); extern void add_spende(struct faction * f1, struct faction * f2, int betrag, struct region * r); extern int make_cmd(struct unit * u, struct order * ord); extern void split_allocations(struct region * r); +extern int recruit_classic(void); +extern int recruit_archetypes(void); #ifdef __cplusplus } diff --git a/src/common/gamecode/gamecode.vcproj b/src/common/gamecode/gamecode.vcproj index da2682184..1088b6fa3 100644 --- a/src/common/gamecode/gamecode.vcproj +++ b/src/common/gamecode/gamecode.vcproj @@ -289,6 +289,9 @@ + + @@ -323,6 +326,9 @@ + + diff --git a/src/common/kernel/give.c b/src/common/gamecode/give.c similarity index 91% rename from src/common/kernel/give.c rename to src/common/gamecode/give.c index 46f3f6e1a..018f810d6 100644 --- a/src/common/kernel/give.c +++ b/src/common/gamecode/give.c @@ -12,23 +12,24 @@ */ #include #include "eressea.h" - #include "give.h" +#include "economy.h" + /* kernel includes */ -#include "faction.h" -#include "item.h" -#include "magic.h" -#include "message.h" -#include "order.h" -#include "pool.h" -#include "race.h" -#include "region.h" -#include "reports.h" -#include "ship.h" -#include "skill.h" -#include "terrain.h" -#include "unit.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* attributes includes */ #include @@ -250,8 +251,28 @@ give_men(int n, unit * u, unit * u2, struct order * ord) else freset(u2, UFL_HERO); #endif } - + if (u2) { + if (u2->number!=0 && recruit_archetypes()) { + /* must have same set of skills */ + boolean okay = false; + if (u->skill_size==u2->skill_size) { + int i; + for (i=0;i!=u->skill_size;++i) { + int j; + for (j=0;j!=u2->skill_size;++j) { + if (u->skills[i].id==u2->skills[j].id) break; + } + if (j!=u2->skill_size) break; + } + if (i==u->skill_size) okay = true; + } + if (!okay) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "give_cannot_merge", "")); + } + } + + /* Einheiten von Schiffen können nicht NACH in von * Nicht-alliierten bewachten Regionen ausführen */ sh = leftship(u); diff --git a/src/common/kernel/give.h b/src/common/gamecode/give.h similarity index 100% rename from src/common/kernel/give.h rename to src/common/gamecode/give.h diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c index e257015e6..2700563e7 100644 --- a/src/common/gamecode/monster.c +++ b/src/common/gamecode/monster.c @@ -25,6 +25,7 @@ /* gamecode includes */ #include "economy.h" +#include "give.h" /* triggers includes */ #include @@ -40,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/src/common/kernel/Jamfile b/src/common/kernel/Jamfile index ad2c8d8a2..4e394d0ba 100644 --- a/src/common/kernel/Jamfile +++ b/src/common/kernel/Jamfile @@ -19,7 +19,6 @@ SOURCES = equipment.c faction.c group.c - give.c item.c karma.c magic.c diff --git a/src/common/kernel/kernel.vcproj b/src/common/kernel/kernel.vcproj index 847357e14..641c1a514 100644 --- a/src/common/kernel/kernel.vcproj +++ b/src/common/kernel/kernel.vcproj @@ -210,9 +210,6 @@ - - @@ -328,9 +325,6 @@ - - diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c index 7b3710c67..2ac37458f 100644 --- a/src/common/kernel/unit.c +++ b/src/common/kernel/unit.c @@ -1004,7 +1004,7 @@ add_skill(unit * u, skill_t id) skill * sv = u->skills; #ifndef NDEBUG for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { - assert(sv->id != id); + assert(sv->id != id); } #endif ++u->skill_size; diff --git a/src/res/rts/units.xml b/src/res/rts/units.xml index 5911d7b9d..72a3b864d 100644 --- a/src/res/rts/units.xml +++ b/src/res/rts/units.xml @@ -27,6 +27,8 @@ + +