forked from github/server
RTS/Archetypes (WIP):
- tested and fixed archetype-recruiting
This commit is contained in:
parent
2651973059
commit
54446e0a1e
|
@ -62,14 +62,21 @@ get_archetype(const char * name)
|
|||
void
|
||||
init_archetypes(void)
|
||||
{
|
||||
char zName[64];
|
||||
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) {
|
||||
const char * s;
|
||||
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;
|
||||
|
||||
xmlChar * property;
|
||||
if (nodes && nodes->nodeNr>0) {
|
||||
xmlNodePtr node = nodes->nodeTab[0];
|
||||
archetype * arch = calloc(1, sizeof(archetype));
|
||||
xmlXPathObjectPtr sub;
|
||||
if (nodes) {
|
||||
int i;
|
||||
for (i=0;i!=nodes->nodeNr;++i) {
|
||||
xmlNodePtr node = nodes->nodeTab[i];
|
||||
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);
|
||||
property = xmlGetProp(node, BAD_CAST "name");
|
||||
assert(property!=NULL);
|
||||
arch->name = strdup((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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
sub = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
|
||||
if (sub->nodesetval) {
|
||||
xml_readconstruction(xpath, sub->nodesetval, &arch->ctype);
|
||||
arch->size = xml_ivalue(node, "cost", 0);
|
||||
|
||||
xpath->node = node;
|
||||
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);
|
||||
|
||||
|
|
|
@ -1058,14 +1058,13 @@ maintain_buildings(region * r, boolean crash)
|
|||
static int
|
||||
recruit_archetype(unit * u, order * ord)
|
||||
{
|
||||
int n, id;
|
||||
int n;
|
||||
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);
|
||||
attrib * a = NULL;
|
||||
|
@ -1104,12 +1103,14 @@ recruit_archetype(unit * u, order * ord)
|
|||
|
||||
n = build(u, arch->ctype, 0, n);
|
||||
if (n>0) {
|
||||
scale_number(u, n);
|
||||
set_number(u, n);
|
||||
equip_unit(u, arch->equip);
|
||||
u->hp = n * unit_max_hp(u);
|
||||
if (arch->size) {
|
||||
if (a==NULL) a = a_add(&u->building->attribs, a_new(&at_recruit));
|
||||
a->data.i += n*arch->size;
|
||||
}
|
||||
ADDMSG(&u->faction->msgs, msg_message("recruit_archetype", "unit archetype", u, arch->name));
|
||||
return n;
|
||||
} else switch(n) {
|
||||
case ENOMATERIALS:
|
||||
|
|
|
@ -1791,6 +1791,7 @@ report_plaintext(const char * filename, report_context * ctx)
|
|||
|
||||
dh = 0;
|
||||
if (f->age <= 2) {
|
||||
const char * s;
|
||||
if (f->age <= 1) {
|
||||
ADDMSG(&f->msgs, msg_message("changepasswd",
|
||||
"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));
|
||||
rnl(F);
|
||||
centre(F, buf, true);
|
||||
rnl(F);
|
||||
centre(F, LOC(f->locale, "newbie_info_1"), true);
|
||||
rnl(F);
|
||||
centre(F, LOC(f->locale, "newbie_info_2"), true);
|
||||
s = locale_getstring(f->locale, "newbie_info_1");
|
||||
if (s) {
|
||||
rnl(F);
|
||||
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) {
|
||||
f->options |= want(O_COMPUTER);
|
||||
rnl(F);
|
||||
centre(F, LOC(f->locale, "newbie_info_3"), true);
|
||||
s = locale_getstring(f->locale, "newbie_info_3");
|
||||
if (s) {
|
||||
rnl(F);
|
||||
centre(F, s, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
rnl(F);
|
||||
|
|
|
@ -50,6 +50,7 @@ create_equipment(const char * eqname)
|
|||
eq->items = NULL;
|
||||
eq->spells = NULL;
|
||||
eq->subsets = NULL;
|
||||
eq->callback = NULL;
|
||||
memset(eq->skills, 0, sizeof(eq->skills));
|
||||
*eqp = eq;
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ extern "C" {
|
|||
struct spell_list * spells;
|
||||
struct subset * subsets;
|
||||
struct equipment * next;
|
||||
void (*callback)(const struct equipment *, struct unit *);
|
||||
} 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_setskill(struct equipment * eq, skill_t sk, const char * value);
|
||||
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_items(struct item ** items, const struct equipment * eq);
|
||||
|
|
|
@ -149,7 +149,7 @@ addplayer(region *r, faction * f)
|
|||
u = createunit(r, f, 1, f->race);
|
||||
equip_unit(u, get_equipment("new_faction"));
|
||||
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);
|
||||
if (f->race == new_race[RC_DAEMON]) {
|
||||
race_t urc;
|
||||
|
|
|
@ -225,12 +225,12 @@ unit_max_hp(const unit * u)
|
|||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
give_starting_equipment(struct unit *u)
|
||||
static void
|
||||
equip_newunits(const struct equipment * eq, struct unit *u)
|
||||
{
|
||||
struct region *r = u->region;
|
||||
|
||||
switch(old_race(u->race)) {
|
||||
switch (old_race(u->race)) {
|
||||
case RC_ELF:
|
||||
set_show_item(u->faction, I_FEENSTIEFEL);
|
||||
break;
|
||||
|
@ -239,7 +239,7 @@ give_starting_equipment(struct unit *u)
|
|||
set_number(u, 10);
|
||||
break;
|
||||
case RC_HUMAN:
|
||||
{
|
||||
if (u->building==NULL) {
|
||||
const building_type * btype = bt_find("castle");
|
||||
if (btype!=NULL) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
u->hp = unit_max_hp(u) * u->number;
|
||||
}
|
||||
|
||||
boolean
|
||||
|
@ -449,6 +448,7 @@ register_races(void)
|
|||
* to generate battle spoils
|
||||
* race->itemdrop() */
|
||||
register_function((pf_generic)default_spoil, "defaultdrops");
|
||||
register_function((pf_generic)equip_newunits, "equip_newunits");
|
||||
|
||||
sprintf(zBuffer, "%s/races.xml", resourcepath());
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ extern int read_race_reference(const struct race ** rp, FILE * F);
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
add_spells(equipment * eq, xmlNodeSetPtr nsetItems)
|
||||
{
|
||||
|
@ -1224,6 +1246,10 @@ parse_equipment(xmlDocPtr doc)
|
|||
|
||||
xpath->node = node;
|
||||
|
||||
xpathResult = xmlXPathEvalExpression(BAD_CAST "callback", xpath);
|
||||
add_callbacks(eq, xpathResult->nodesetval);
|
||||
xmlXPathFreeObject(xpathResult);
|
||||
|
||||
xpathResult = xmlXPathEvalExpression(BAD_CAST "item", xpath);
|
||||
add_items(eq, xpathResult->nodesetval);
|
||||
xmlXPathFreeObject(xpathResult);
|
||||
|
|
|
@ -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
|
||||
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_getresource, "lua_getresource");
|
||||
register_function((pf_generic)&lua_changeresource, "lua_changeresource");
|
||||
register_function((pf_generic)&lua_equipmentcallback, "lua_equip");
|
||||
|
||||
module(L)[
|
||||
def("overload", &overload),
|
||||
|
|
|
@ -223,7 +223,6 @@ game_init(void)
|
|||
register_ships();
|
||||
register_itemfunctions();
|
||||
register_spells();
|
||||
register_archetypes();
|
||||
#ifdef DUNGEON_MODULE
|
||||
register_dungeon();
|
||||
#endif
|
||||
|
@ -239,6 +238,7 @@ game_init(void)
|
|||
|
||||
register_itemtypes();
|
||||
register_xmlreader();
|
||||
register_archetypes();
|
||||
enable_xml_gamecode();
|
||||
|
||||
init_data(xmlfile);
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
|
||||
<set name="elf">
|
||||
<item name="fairyboot" amount="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="uruk">
|
||||
|
@ -149,6 +150,11 @@
|
|||
|
||||
<set name="goblin">
|
||||
<item name="roi" amount="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="human">
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="troll">
|
||||
|
@ -181,10 +187,16 @@
|
|||
|
||||
<set name="cat">
|
||||
<item name="roi" amount="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="aquarian">
|
||||
<skill name="sailing" level="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="centaur">
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<!-- equipment-sets for random encounters -->
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<xi:include href="prefixes.xml"/>
|
||||
<xi:include href="ships.xml"/>
|
||||
<xi:include href="rts/buildings.xml"/>
|
||||
<xi:include href="rts/strings.xml"/>
|
||||
<xi:include href="rts/units.xml"/>
|
||||
<xi:include href="rts/calendar.xml"/>
|
||||
<xi:include href="equipment.xml"/>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<item name="money" amount="4200"/>
|
||||
<item name="log" amount="30"/>
|
||||
<item name="stone" amount="30"/>
|
||||
<callback name="lua_equip"/>
|
||||
</set>
|
||||
|
||||
</equipment>
|
||||
|
|
|
@ -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>
|
|
@ -2,26 +2,26 @@
|
|||
<archetypes>
|
||||
|
||||
<archetype name="swordsman" building="barracks" cost="10">
|
||||
<construction>
|
||||
<construction reqsize="1">
|
||||
<requirement type="money" quantity="100"/>
|
||||
</construction>
|
||||
</archetype>
|
||||
|
||||
<archetype name="pikeman" building="barracks" cost="10">
|
||||
<construction>
|
||||
<construction reqsize="1"><!-- 1 requirement makes 1 recruit -->
|
||||
<requirement type="money" quantity="100"/>
|
||||
</construction>
|
||||
</archetype>
|
||||
|
||||
<archetype name="knight" building="barracks" cost="100">
|
||||
<construction>
|
||||
<construction reqsize="1">
|
||||
<requirement type="money" quantity="1000"/>
|
||||
<requirement type="laen" quantity="1"/>
|
||||
</construction>
|
||||
</archetype>
|
||||
|
||||
<archetype name="craftsman" building="castle" cost="10">
|
||||
<construction>
|
||||
<construction reqsize="1">
|
||||
<requirement type="money" quantity="100"/>
|
||||
</construction>
|
||||
</archetype>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<text locale="de">Weitere Informationen über das Spiel findest Du unter htpp://www.vinyambar.de/</text>
|
||||
</string>
|
||||
<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 name="defaultorder">
|
||||
<text locale="de">ARBEITE</text>
|
||||
|
|
|
@ -33,6 +33,12 @@ function run_scripts()
|
|||
end
|
||||
end
|
||||
|
||||
function equip_new_faction(u)
|
||||
b = add_building(u.region, "castle")
|
||||
b.size = 10
|
||||
u.building = b
|
||||
end
|
||||
|
||||
function process(orders)
|
||||
file = "" .. get_turn()
|
||||
if read_game(file)~=0 then
|
||||
|
|
Loading…
Reference in New Issue