RTS/Archetypes (WIP):

- tested and fixed archetype-recruiting
This commit is contained in:
Enno Rehling 2007-05-28 19:45:08 +00:00
parent 2651973059
commit 54446e0a1e
18 changed files with 190 additions and 49 deletions

View File

@ -62,14 +62,21 @@ get_archetype(const char * name)
void void
init_archetypes(void) init_archetypes(void)
{ {
char zName[64];
const struct locale * lang = locales; const struct locale * lang = locales;
for (;lang;lang=nextlocale(lang)) { for (;lang;lang=nextlocale(lang)) {
variant var; variant var;
archetype * arch = archetypes; archetype * arch = archetypes;
struct tnode * tokens = get_translations(lang, UT_ARCHETYPES); struct tnode * tokens = get_translations(lang, UT_ARCHETYPES);
for (;arch;arch=arch->next) { for (;arch;arch=arch->next) {
const char * s;
var.v = arch; var.v = arch;
addtoken(tokens, LOC(lang, arch->name), var);
s = locale_getstring(lang, arch->name);
if (s!=NULL) addtoken(tokens, s, var);
sprintf(zName, "%s_p", arch->name);
s = locale_getstring(lang, zName);
if (s!=NULL) addtoken(tokens, s, var);
} }
} }
} }
@ -82,38 +89,42 @@ parse_archetypes(xmlDocPtr doc)
xmlNodeSetPtr nodes = result->nodesetval; xmlNodeSetPtr nodes = result->nodesetval;
xmlChar * property; xmlChar * property;
if (nodes && nodes->nodeNr>0) { if (nodes) {
xmlNodePtr node = nodes->nodeTab[0]; int i;
archetype * arch = calloc(1, sizeof(archetype)); for (i=0;i!=nodes->nodeNr;++i) {
xmlXPathObjectPtr sub; xmlNodePtr node = nodes->nodeTab[i];
archetype * arch = calloc(1, sizeof(archetype));
xmlXPathObjectPtr sub;
property = xmlGetProp(node, BAD_CAST "name"); property = xmlGetProp(node, BAD_CAST "name");
assert(property!=NULL); assert(property!=NULL);
arch->name = strdup((const char *)property); 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); xmlFree(property);
} else {
arch->equip = get_equipment(arch->name);
}
property = xmlGetProp(node, BAD_CAST "building"); property = xmlGetProp(node, BAD_CAST "equip");
if (property!=NULL) { if (property!=NULL) {
arch->btype = bt_find((const char*)property); arch->equip = get_equipment((const char*)property);
xmlFree(property); xmlFree(property);
} } else {
arch->equip = get_equipment(arch->name);
}
arch->size = xml_ivalue(node, "cost", 0); property = xmlGetProp(node, BAD_CAST "building");
if (property!=NULL) {
arch->btype = bt_find((const char*)property);
xmlFree(property);
}
xpath->node = node; arch->size = xml_ivalue(node, "cost", 0);
sub = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
if (sub->nodesetval) { xpath->node = node;
xml_readconstruction(xpath, sub->nodesetval, &arch->ctype); sub = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
if (sub->nodesetval) {
xml_readconstruction(xpath, sub->nodesetval, &arch->ctype);
}
xmlXPathFreeObject(sub);
register_archetype(arch);
} }
xmlXPathFreeObject(sub);
} }
xmlXPathFreeObject(result); xmlXPathFreeObject(result);

View File

@ -1058,14 +1058,13 @@ maintain_buildings(region * r, boolean crash)
static int static int
recruit_archetype(unit * u, order * ord) recruit_archetype(unit * u, order * ord)
{ {
int n, id; int n;
const char * s; const char * s;
init_tokens(ord); init_tokens(ord);
skip_token(); skip_token();
n = geti(); n = geti();
s = getstrtoken(); s = getstrtoken();
id = getid();
if (n>0 && s && s[0]) { if (n>0 && s && s[0]) {
const archetype * arch = find_archetype(s, u->faction->locale); const archetype * arch = find_archetype(s, u->faction->locale);
attrib * a = NULL; attrib * a = NULL;
@ -1104,12 +1103,14 @@ recruit_archetype(unit * u, order * ord)
n = build(u, arch->ctype, 0, n); n = build(u, arch->ctype, 0, n);
if (n>0) { if (n>0) {
scale_number(u, n); set_number(u, n);
equip_unit(u, arch->equip); equip_unit(u, arch->equip);
u->hp = n * unit_max_hp(u);
if (arch->size) { if (arch->size) {
if (a==NULL) a = a_add(&u->building->attribs, a_new(&at_recruit)); if (a==NULL) a = a_add(&u->building->attribs, a_new(&at_recruit));
a->data.i += n*arch->size; a->data.i += n*arch->size;
} }
ADDMSG(&u->faction->msgs, msg_message("recruit_archetype", "unit archetype", u, arch->name));
return n; return n;
} else switch(n) { } else switch(n) {
case ENOMATERIALS: case ENOMATERIALS:

View File

@ -1791,6 +1791,7 @@ report_plaintext(const char * filename, report_context * ctx)
dh = 0; dh = 0;
if (f->age <= 2) { if (f->age <= 2) {
const char * s;
if (f->age <= 1) { if (f->age <= 1) {
ADDMSG(&f->msgs, msg_message("changepasswd", ADDMSG(&f->msgs, msg_message("changepasswd",
"value", f->passw)); "value", f->passw));
@ -1798,14 +1799,23 @@ report_plaintext(const char * filename, report_context * ctx)
RENDER(f, buf, sizeof(buf), ("newbie_password", "password", f->passw)); RENDER(f, buf, sizeof(buf), ("newbie_password", "password", f->passw));
rnl(F); rnl(F);
centre(F, buf, true); centre(F, buf, true);
rnl(F); s = locale_getstring(f->locale, "newbie_info_1");
centre(F, LOC(f->locale, "newbie_info_1"), true); if (s) {
rnl(F); rnl(F);
centre(F, LOC(f->locale, "newbie_info_2"), true); centre(F, s, true);
}
s = locale_getstring(f->locale, "newbie_info_2");
if (s) {
rnl(F);
centre(F, s, true);
}
if ((f->options & want(O_COMPUTER)) == 0) { if ((f->options & want(O_COMPUTER)) == 0) {
f->options |= want(O_COMPUTER); f->options |= want(O_COMPUTER);
rnl(F); s = locale_getstring(f->locale, "newbie_info_3");
centre(F, LOC(f->locale, "newbie_info_3"), true); if (s) {
rnl(F);
centre(F, s, true);
}
} }
} }
rnl(F); rnl(F);

View File

@ -50,6 +50,7 @@ create_equipment(const char * eqname)
eq->items = NULL; eq->items = NULL;
eq->spells = NULL; eq->spells = NULL;
eq->subsets = NULL; eq->subsets = NULL;
eq->callback = NULL;
memset(eq->skills, 0, sizeof(eq->skills)); memset(eq->skills, 0, sizeof(eq->skills));
*eqp = eq; *eqp = eq;
break; break;
@ -113,6 +114,12 @@ equipment_setitem(equipment * eq, const item_type * itype, const char * value)
} }
} }
void
equipment_setcallback(struct equipment * eq, void (*callback)(const struct equipment *, struct unit *))
{
eq->callback = callback;
}
void void
equip_unit(struct unit * u, const struct equipment * eq) equip_unit(struct unit * u, const struct equipment * eq)
{ {
@ -163,6 +170,8 @@ equip_unit(struct unit * u, const struct equipment * eq)
} }
} }
} }
if (eq->callback) eq->callback(eq, u);
} }
} }

View File

@ -48,6 +48,7 @@ extern "C" {
struct spell_list * spells; struct spell_list * spells;
struct subset * subsets; struct subset * subsets;
struct equipment * next; struct equipment * next;
void (*callback)(const struct equipment *, struct unit *);
} equipment; } equipment;
@ -57,6 +58,7 @@ extern "C" {
extern void equipment_setitem(struct equipment * eq, const struct item_type * itype, const char * value); extern void equipment_setitem(struct equipment * eq, const struct item_type * itype, const char * value);
extern void equipment_setskill(struct equipment * eq, skill_t sk, const char * value); extern void equipment_setskill(struct equipment * eq, skill_t sk, const char * value);
extern void equipment_addspell(struct equipment * eq, struct spell * sp); extern void equipment_addspell(struct equipment * eq, struct spell * sp);
extern void equipment_setcallback(struct equipment * eq, void (*callback)(const struct equipment *, struct unit *));
extern void equip_unit(struct unit * u, const struct equipment * eq); extern void equip_unit(struct unit * u, const struct equipment * eq);
extern void equip_items(struct item ** items, const struct equipment * eq); extern void equip_items(struct item ** items, const struct equipment * eq);

View File

@ -149,7 +149,7 @@ addplayer(region *r, faction * f)
u = createunit(r, f, 1, f->race); u = createunit(r, f, 1, f->race);
equip_unit(u, get_equipment("new_faction")); equip_unit(u, get_equipment("new_faction"));
equip_unit(u, get_equipment(u->race->_name[0])); equip_unit(u, get_equipment(u->race->_name[0]));
give_starting_equipment(u); u->hp = unit_max_hp(u) * u->number;
fset(u, UFL_ISNEW); fset(u, UFL_ISNEW);
if (f->race == new_race[RC_DAEMON]) { if (f->race == new_race[RC_DAEMON]) {
race_t urc; race_t urc;

View File

@ -225,12 +225,12 @@ unit_max_hp(const unit * u)
return h; return h;
} }
void static void
give_starting_equipment(struct unit *u) equip_newunits(const struct equipment * eq, struct unit *u)
{ {
struct region *r = u->region; struct region *r = u->region;
switch(old_race(u->race)) { switch (old_race(u->race)) {
case RC_ELF: case RC_ELF:
set_show_item(u->faction, I_FEENSTIEFEL); set_show_item(u->faction, I_FEENSTIEFEL);
break; break;
@ -239,7 +239,7 @@ give_starting_equipment(struct unit *u)
set_number(u, 10); set_number(u, 10);
break; break;
case RC_HUMAN: case RC_HUMAN:
{ if (u->building==NULL) {
const building_type * btype = bt_find("castle"); const building_type * btype = bt_find("castle");
if (btype!=NULL) { if (btype!=NULL) {
building *b = new_building(btype, r, u->faction->locale); building *b = new_building(btype, r, u->faction->locale);
@ -264,7 +264,6 @@ give_starting_equipment(struct unit *u)
rsethorses(r, 250+rng_int()%51+rng_int()%51); rsethorses(r, 250+rng_int()%51+rng_int()%51);
break; break;
} }
u->hp = unit_max_hp(u) * u->number;
} }
boolean boolean
@ -449,6 +448,7 @@ register_races(void)
* to generate battle spoils * to generate battle spoils
* race->itemdrop() */ * race->itemdrop() */
register_function((pf_generic)default_spoil, "defaultdrops"); register_function((pf_generic)default_spoil, "defaultdrops");
register_function((pf_generic)equip_newunits, "equip_newunits");
sprintf(zBuffer, "%s/races.xml", resourcepath()); sprintf(zBuffer, "%s/races.xml", resourcepath());
} }

View File

@ -183,7 +183,7 @@ extern int read_race_reference(const struct race ** rp, FILE * F);
extern const char * raceprefix(const struct unit *u); extern const char * raceprefix(const struct unit *u);
extern void give_starting_equipment(struct unit *u); extern void give_starting_equipment(const struct equipment * eq, struct unit *u);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1088,6 +1088,28 @@ add_items(equipment * eq, xmlNodeSetPtr nsetItems)
} }
} }
static void
add_callbacks(equipment * eq, xmlNodeSetPtr nsetItems)
{
if (nsetItems!=NULL && nsetItems->nodeNr>0) {
int i;
for (i=0;i!=nsetItems->nodeNr;++i) {
xmlNodePtr node = nsetItems->nodeTab[i];
xmlChar * property;
pf_generic fun;
property = xmlGetProp(node, BAD_CAST "name");
if (property!=NULL) {
fun = get_function((const char*)property);
if (fun) {
equipment_setcallback(eq, (void (*)(const struct equipment *, struct unit *))fun);
}
xmlFree(property);
}
}
}
}
static void static void
add_spells(equipment * eq, xmlNodeSetPtr nsetItems) add_spells(equipment * eq, xmlNodeSetPtr nsetItems)
{ {
@ -1224,6 +1246,10 @@ parse_equipment(xmlDocPtr doc)
xpath->node = node; xpath->node = node;
xpathResult = xmlXPathEvalExpression(BAD_CAST "callback", xpath);
add_callbacks(eq, xpathResult->nodesetval);
xmlXPathFreeObject(xpathResult);
xpathResult = xmlXPathEvalExpression(BAD_CAST "item", xpath); xpathResult = xmlXPathEvalExpression(BAD_CAST "item", xpath);
add_items(eq, xpathResult->nodesetval); add_items(eq, xpathResult->nodesetval);
xmlXPathFreeObject(xpathResult); xmlXPathFreeObject(xpathResult);

View File

@ -303,6 +303,28 @@ race_setscript(const char * rcname, const luabind::object& f)
} }
} }
static void
lua_equipmentcallback(const struct equipment * eq, unit * u)
{
char fname[64];
snprintf(fname, sizeof(fname), "equip_%s", eq->name);
lua_State * L = (lua_State *)global.vm_state;
if (is_function(L, fname)) {
try {
call_function<int>(L, fname, u);
}
catch (error& e) {
lua_State* L = e.state();
const char* error = lua_tostring(L, -1);
log_error(("An exception occured while %s tried to call '%s': %s.\n",
unitname(u), fname, error));
lua_pop(L, 1);
std::terminate();
}
}
}
void void
bind_script(lua_State * L) bind_script(lua_State * L)
{ {
@ -311,6 +333,7 @@ bind_script(lua_State * L)
register_function((pf_generic)&lua_useitem, "lua_useitem"); register_function((pf_generic)&lua_useitem, "lua_useitem");
register_function((pf_generic)&lua_getresource, "lua_getresource"); register_function((pf_generic)&lua_getresource, "lua_getresource");
register_function((pf_generic)&lua_changeresource, "lua_changeresource"); register_function((pf_generic)&lua_changeresource, "lua_changeresource");
register_function((pf_generic)&lua_equipmentcallback, "lua_equip");
module(L)[ module(L)[
def("overload", &overload), def("overload", &overload),

View File

@ -223,7 +223,6 @@ 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
@ -239,6 +238,7 @@ game_init(void)
register_itemtypes(); register_itemtypes();
register_xmlreader(); register_xmlreader();
register_archetypes();
enable_xml_gamecode(); enable_xml_gamecode();
init_data(xmlfile); init_data(xmlfile);

View File

@ -137,6 +137,7 @@
<set name="elf"> <set name="elf">
<item name="fairyboot" amount="1"/> <item name="fairyboot" amount="1"/>
<callback name="equip_newunits"/>
</set> </set>
<set name="uruk"> <set name="uruk">
@ -149,6 +150,11 @@
<set name="goblin"> <set name="goblin">
<item name="roi" amount="1"/> <item name="roi" amount="1"/>
<callback name="equip_newunits"/>
</set>
<set name="human">
<callback name="equip_newunits"/>
</set> </set>
<set name="troll"> <set name="troll">
@ -181,10 +187,16 @@
<set name="cat"> <set name="cat">
<item name="roi" amount="1"/> <item name="roi" amount="1"/>
<callback name="equip_newunits"/>
</set> </set>
<set name="aquarian"> <set name="aquarian">
<skill name="sailing" level="1"/> <skill name="sailing" level="1"/>
<callback name="equip_newunits"/>
</set>
<set name="centaur">
<callback name="equip_newunits"/>
</set> </set>
<!-- equipment-sets for random encounters --> <!-- equipment-sets for random encounters -->

View File

@ -12,6 +12,7 @@
<xi:include href="prefixes.xml"/> <xi:include href="prefixes.xml"/>
<xi:include href="ships.xml"/> <xi:include href="ships.xml"/>
<xi:include href="rts/buildings.xml"/> <xi:include href="rts/buildings.xml"/>
<xi:include href="rts/strings.xml"/>
<xi:include href="rts/units.xml"/> <xi:include href="rts/units.xml"/>
<xi:include href="rts/calendar.xml"/> <xi:include href="rts/calendar.xml"/>
<xi:include href="equipment.xml"/> <xi:include href="equipment.xml"/>

View File

@ -30,6 +30,7 @@
<item name="money" amount="4200"/> <item name="money" amount="4200"/>
<item name="log" amount="30"/> <item name="log" amount="30"/>
<item name="stone" amount="30"/> <item name="stone" amount="30"/>
<callback name="lua_equip"/>
</set> </set>
</equipment> </equipment>

39
src/res/rts/strings.xml Normal file
View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<strings>
<!-- OPTION [x] -->
<string name="knight">
<text locale="en">knight</text>
<text locale="de">Ritter</text>
</string>
<string name="knight_p">
<text locale="en">knights</text>
</string>
<string name="craftsman">
<text locale="en">craftsman</text>
<text locale="de">Handwerker</text>
</string>
<string name="craftsman_p">
<text locale="en">craftsmen</text>
</string>
<string name="swordsman">
<text locale="en">swordsman</text>
<text locale="de">Schwertkämpfer</text>
</string>
<string name="swordsman_p">
<text locale="en">swordsmen</text>
</string>
<string name="pikeman">
<text locale="en">swordsman</text>
<text locale="de">Pikenier</text>
</string>
<string name="pikeman_p">
<text locale="en">pikemen</text>
<text locale="de">Pikeniere</text>
</string>
<string name="barracks">
<text locale="en">Barracks</text>
<text locale="de">Kaserne</text>
</string>
</strings>

View File

@ -2,26 +2,26 @@
<archetypes> <archetypes>
<archetype name="swordsman" building="barracks" cost="10"> <archetype name="swordsman" building="barracks" cost="10">
<construction> <construction reqsize="1">
<requirement type="money" quantity="100"/> <requirement type="money" quantity="100"/>
</construction> </construction>
</archetype> </archetype>
<archetype name="pikeman" building="barracks" cost="10"> <archetype name="pikeman" building="barracks" cost="10">
<construction> <construction reqsize="1"><!-- 1 requirement makes 1 recruit -->
<requirement type="money" quantity="100"/> <requirement type="money" quantity="100"/>
</construction> </construction>
</archetype> </archetype>
<archetype name="knight" building="barracks" cost="100"> <archetype name="knight" building="barracks" cost="100">
<construction> <construction reqsize="1">
<requirement type="money" quantity="1000"/> <requirement type="money" quantity="1000"/>
<requirement type="laen" quantity="1"/> <requirement type="laen" quantity="1"/>
</construction> </construction>
</archetype> </archetype>
<archetype name="craftsman" building="castle" cost="10"> <archetype name="craftsman" building="castle" cost="10">
<construction> <construction reqsize="1">
<requirement type="money" quantity="100"/> <requirement type="money" quantity="100"/>
</construction> </construction>
</archetype> </archetype>

View File

@ -6,7 +6,7 @@
<text locale="de">Weitere Informationen über das Spiel findest Du unter htpp://www.vinyambar.de/</text> <text locale="de">Weitere Informationen über das Spiel findest Du unter htpp://www.vinyambar.de/</text>
</string> </string>
<string name="newbie_info_3"> <string name="newbie_info_3">
<text locale="de">Mit der ersten Auswertung bekommst du einen Computerreport, den du mit vielen der Tools auf http://www.eressea-pbem.de/download.html benutzen kannst. Wenn du ihn nicht bekommen möchtest, gib einer deiner Einheiten den Befehl OPTION COMPUTER NICHT.</text> <text locale="de">Mit der ersten Auswertung bekommst du einen Computerreport, den du mit vielen der Tools auf http://www.eressea.de/ benutzen kannst. Wenn du ihn nicht bekommen möchtest, gib einer deiner Einheiten den Befehl OPTION COMPUTER NICHT.</text>
</string> </string>
<string name="defaultorder"> <string name="defaultorder">
<text locale="de">ARBEITE</text> <text locale="de">ARBEITE</text>

View File

@ -33,6 +33,12 @@ function run_scripts()
end end
end end
function equip_new_faction(u)
b = add_building(u.region, "castle")
b.size = 10
u.building = b
end
function process(orders) function process(orders)
file = "" .. get_turn() file = "" .. get_turn()
if read_game(file)~=0 then if read_game(file)~=0 then