diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index e04ea6e58..79c6e875a 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -2280,10 +2280,12 @@ expandstealing(region * r, request * stealorders) int uct = 0; unit *u2; assert(effskill(oa[i].unit, SK_STEALTH)>=4 || !"this goblin\'s talent is too low"); - for (u2 = r->units; u2; u2 = u2->next) - if (u2->faction == u->faction) - uct += u2->number; - n -= uct * 2 * MAINTENANCE; + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->faction == u->faction) { + uct += maintenance_cost(u2); + } + } + n -= uct * 2; } #endif if (n>10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index d11a67169..d9e2bb4d1 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -176,6 +176,7 @@ get_food(region *r) { unit *u; int peasantfood = rpeasants(r)*10; + faction * owner = region_owner(r); /* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber * wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise @@ -187,6 +188,15 @@ get_food(region *r) /* Erstmal zurücksetzen */ freset(u, UFL_HUNGER); + /* if the region is owned, and the owner is nice, then we'll get + * food from the peasants */ + if (owner!=NULL && (get_alliance(owner, u->faction) & HELP_MONEY)) { + int rm = rmoney(r); + int use = min(rm, need); + rsetmoney(r, rm-use); + need -= use; + } + need -= get_money(u); if (need > 0) { unit *v; @@ -569,8 +579,8 @@ peasants(region * r) /* Alle werden satt, oder halt soviele für die es auch Geld gibt */ money = rmoney(r); - satiated = min(peasants, money / MAINTENANCE); - rsetmoney(r, money - satiated * MAINTENANCE); + satiated = min(peasants, money / maintenance_cost(NULL)); + rsetmoney(r, money - satiated * maintenance_cost(NULL)); /* Von denjenigen, die nicht satt geworden sind, verhungert der * Großteil. dead kann nie größer als rpeasants(r) - satiated werden, diff --git a/src/common/gamecode/spy.c b/src/common/gamecode/spy.c index 8c3231f7a..6ec6273fe 100644 --- a/src/common/gamecode/spy.c +++ b/src/common/gamecode/spy.c @@ -396,12 +396,10 @@ sink_ship(region * r, ship * sh, const char *name, char spy, unit * saboteur) const char *spy_discovered_msg = "%s entdeckte %s beim versenken von %s."; unit **ui; region *safety = r; - faction *f; int i; direction_t d; unsigned int index; double probability = 0.0; - int money, count; char buffer[DISPLAYSIZE + 1]; vset informed; vset survivors; @@ -469,23 +467,22 @@ sink_ship(region * r, ship * sh, const char *name, char spy, unit * saboteur) * amount: */ while (informed.size != 0) { unit *lastunit = 0; + int money = 0, maintain = 0; + faction * f = (faction *) informed.data[0]; - f = (faction *) informed.data[0]; - money = 0; - count = 0; - /* find out how much money this faction still has: */ + /* find out how much money this faction still has: */ for (index = 0; index != survivors.size; ++index) { unit *u = (unit *) survivors.data[index]; if (u->faction == f) { - count += u->number; + maintain += maintenance_cost(u); money += get_money(u); lastunit = u; } } /* 'money' shall be the maintenance-surplus of the survivng * units: */ - money = money - count * MAINTENANCE; + money = money - maintain; for (index = 0; money > 0; ++index) { int remove; unit *u = (unit *) survivors.data[index]; diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index 8c3fc6235..1032713a6 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -59,14 +59,15 @@ #include "unit.h" /* util includes */ -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* libxml includes */ #include @@ -2334,8 +2335,11 @@ init_locale(const struct locale * lang) } for (i=0;i!=MAXSKILLS;++i) { if (i!=SK_TRADE || !TradeDisabled()) { - var.i = i; - addtoken(&lnames->skillnames, skillname((skill_t)i, lang), var); + const char * skname = skillname((skill_t)i, lang); + if (skname!=NULL) { + var.i = i; + addtoken(&lnames->skillnames, skname, var); + } } } for (i=0;i!=MAXKEYWORDS;++i) { @@ -2709,7 +2713,7 @@ lifestyle(const unit * u) if (u->faction->no == MONSTER_FACTION) return 0; - need = u->number * u->race->maintenance; + need = maintenance_cost(u); if (!astralspace) { astralspace = getplanebyname("Astralraum"); @@ -2823,10 +2827,8 @@ static const int wagetable[7][4] = { {15, 13, 16, 2} /* Zitadelle */ }; -/* Gibt Arbeitslohn für entsprechende Rasse zurück, oder für -* die Bauern wenn f == NULL. */ -int -wage(const region *r, const faction * f, const race * rc) +static int +default_wage(const region *r, const faction * f, const race * rc) { building *b = largestbuilding(r, false); int esize = 0; @@ -2888,6 +2890,18 @@ wage(const region *r, const faction * f, const race * rc) return wage; } +/* Gibt Arbeitslohn für entsprechende Rasse zurück, oder für +* die Bauern wenn f == NULL. */ +int +wage(const region *r, const faction * f, const race * rc) +{ + if (global.functions.wage) { + return global.functions.wage(r, f, rc); + } + return default_wage(r, f, rc); +} + + static region * findspecialdirection(const region *r, const char *token) { @@ -2906,6 +2920,18 @@ findspecialdirection(const region *r, const char *token) return NULL; } +#define MAINTENANCE 10 +int +maintenance_cost(const struct unit * u) +{ + if (u==NULL) return MAINTENANCE; + if (global.functions.maintenance) { + int retval = global.functions.maintenance(u); + if (retval>=0) return retval; + } + return u->race->maintenance * u->number; +} + message * movement_error(unit * u, const char * token, order * ord, int error_code) { diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index d45b3ff70..4e02823a1 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -366,7 +366,6 @@ extern void plagues(struct region * r, boolean ismagic); #define STARTMONEY 5000 #define PRODUCEEXP 10 -#define MAINTENANCE 10 #define TAVERN_MAINTENANCE 14 /* Man gibt in einer Taverne mehr Geld aus! */ @@ -1122,6 +1121,7 @@ extern int besieged(const struct unit * u); extern int maxworkingpeasants(const struct region * r); extern int wage(const struct region *r, const struct faction *f, const struct race * rc); +extern int maintenance_cost(const struct unit * u); extern int movewhere(const struct unit *u, const char * token, struct region * r, struct region** resultp); extern struct message * movement_error(struct unit * u, const char * token, struct order * ord, int error_code); extern boolean move_blocked(const struct unit * u, const struct region *src, const struct region *dest); @@ -1159,6 +1159,10 @@ typedef struct settings { struct param * parameters; void * vm_state; + struct global_functions { + int (*wage)(const struct region *r, const struct faction * f, const struct race * rc); + int (*maintenance)(const struct unit * u); + } functions; } settings; extern settings global; diff --git a/src/common/kernel/skill.c b/src/common/kernel/skill.c index f601c0586..be56c89ba 100644 --- a/src/common/kernel/skill.c +++ b/src/common/kernel/skill.c @@ -75,10 +75,28 @@ static const char *skillnames[MAXSKILLS] = "unarmed" }; +static boolean skill_enabled[MAXSKILLS]; + const char * skillname(skill_t sk, const struct locale * lang) { - return locale_string(lang, mkname("skill", skillnames[sk])); + if (skill_enabled[sk]) { + return locale_string(lang, mkname("skill", skillnames[sk])); + } + return NULL; +} + +void +enable_skill(const char * skname, boolean value) +{ + skill_t sk; + for (sk=0;sk!=MAXSKILLS) { + if (strcmp(skillnames[sk], skname)==0) { + skill_enabled[sk] = value; + return; + } + } + log_error(("Trying to set unknown skill %s to %u", skname, value)); } skill_t @@ -88,7 +106,9 @@ sk_find(const char * name) if (name==NULL) return NOSKILL; if (strncmp(name, "sk_", 3)==0) name+=3; for (i=0;i!=MAXSKILLS;++i) { - if (strcmp(name, skillnames[i])==0) return i; + if (skill_enabled[i]) { + if (strcmp(name, skillnames[i])==0) return i; + } } return NOSKILL; } diff --git a/src/common/kernel/skill.h b/src/common/kernel/skill.h index b0fd60416..efbcea363 100644 --- a/src/common/kernel/skill.h +++ b/src/common/kernel/skill.h @@ -48,7 +48,7 @@ extern struct attrib * make_skillmod(skill_t sk, unsigned int flags, skillmod_fu extern const char * skillname(skill_t, const struct locale *); extern skill_t sk_find(const char * name); - +extern void enable_skill(const char * name, boolean value); extern int level_days(int level); extern int level(int days); diff --git a/src/common/kernel/xmlreader.c b/src/common/kernel/xmlreader.c index cce4d76fb..acf3e5c47 100644 --- a/src/common/kernel/xmlreader.c +++ b/src/common/kernel/xmlreader.c @@ -1865,6 +1865,18 @@ parse_main(xmlDocPtr doc) } xmlXPathFreeObject(result); + /* reading eressea/game/skill */ + result = xmlXPathEvalExpression(BAD_CAST "skill", xpath); + nodes = result->nodesetval; + for (i=0;i!=nodes->nodeNr;++i) { + xmlNodePtr node = nodes->nodeTab[i]; + xmlChar * name = xmlGetProp(node, BAD_CAST "name"); + boolean enable = xml_bvalue(node, "enable", true); + enable_skill((const char*)name, enable); + xmlFree(name); + } + xmlXPathFreeObject(result); + xmlXPathFreeContext(xpath); return 0; } diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index 4a8c561c1..a587dbb8c 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -4616,7 +4616,7 @@ sp_seduce(castorder *co) /* Erfolgsmeldung */ sprintf(buf, "%s schenkt %s ", unitname(target), unitname(mage)); - loot = min(cast_level * 1000, get_money(target) - (MAINTENANCE*target->number)); + loot = min(cast_level * 1000, get_money(target) - (maintenance_cost(target))); loot = max(loot, 0); change_money(mage, loot); change_money(target, -loot); diff --git a/src/config.h b/src/config.h index 0ad8a7f99..a20de3c3d 100644 --- a/src/config.h +++ b/src/config.h @@ -221,10 +221,6 @@ extern char * strdup(const char *s); #endif #if defined (ghs) || defined (__GNUC__) || defined (__hpux) || defined (__sgi) || defined (__DECCXX) || defined (__KCC) || defined (__rational__) || defined (__USLC__) || defined (ACE_RM544) -// Some compilers complain about "statement with no effect" with (a). -// This eliminates the warnings, and no code is generated for the null -// conditional statement. NOTE: that may only be true if -O is enabled, -// such as with GreenHills (ghs) 1.8.8. # define unused(a) do {/* null */} while (&a == 0) #else /* ghs || __GNUC__ || ..... */ # define unused(a) (a) diff --git a/src/eressea/lua/faction.cpp b/src/eressea/lua/faction.cpp index 7bf84006a..a409f8eac 100644 --- a/src/eressea/lua/faction.cpp +++ b/src/eressea/lua/faction.cpp @@ -242,21 +242,21 @@ faction_setorigin(faction& f, int x, int y) y = 0; } -int +short faction_getorigin_x(const faction& f) { return f.ursprung->x; } void -faction_setorigin_x(faction& f, int x) { +faction_setorigin_x(faction& f, short x) { f.ursprung->x = x; } -int +short faction_getorigin_y(const faction& f) { return f.ursprung->y; } void -faction_setorigin_y(faction& f, int y) { +faction_setorigin_y(faction& f, short y) { f.ursprung->y = y; } diff --git a/src/eressea/lua/script.cpp b/src/eressea/lua/script.cpp index a9a74c94e..30ea0ed7a 100644 --- a/src/eressea/lua/script.cpp +++ b/src/eressea/lua/script.cpp @@ -29,14 +29,17 @@ #include #include #include +#include #include #include +using namespace luabind; + static void free_script(attrib * a) { if (a->data.v!=NULL) { - luabind::object * f = (luabind::object *)a->data.v; + object * f = (object *)a->data.v; delete f; } } @@ -53,11 +56,11 @@ call_script(struct unit * u) const attrib * a = a_findc(u->attribs, &at_script); if (a==NULL) a = a_findc(u->race->attribs, &at_script); if (a!=NULL && a->data.v!=NULL) { - luabind::object * func = (luabind::object *)a->data.v; + object * func = (object *)a->data.v; try { func->operator()(u); } - catch (luabind::error& e) { + catch (error& e) { lua_State* L = e.state(); const char* error = lua_tostring(L, -1); log_error((error)); @@ -75,7 +78,7 @@ setscript(struct attrib ** ap, void * fptr) if (a == NULL) { a = a_add(ap, a_new(&at_script)); } else if (a->data.v!=NULL) { - luabind::object * f = (luabind::object *)a->data.v; + object * f = (object *)a->data.v; delete f; } a->data.v = fptr; @@ -96,9 +99,9 @@ lua_callspell(castorder *co) lua_State * L = (lua_State *)global.vm_state; if (is_function(L, fname)) { try { - retval = luabind::call_function(L, fname, co->rt, mage, co->level, co->force); + retval = call_function(L, fname, co->rt, mage, co->level, co->force); } - catch (luabind::error& e) { + 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", @@ -121,9 +124,9 @@ lua_useitem(struct unit * u, const struct item_type * itype, int amount, struct lua_State * L = (lua_State *)global.vm_state; if (is_function(L, fname)) { try { - retval = luabind::call_function(L, fname, u, amount); + retval = call_function(L, fname, u, amount); } - catch (luabind::error& e) { + 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", @@ -145,9 +148,9 @@ lua_initfamiliar(unit * u) lua_State * L = (lua_State *)global.vm_state; if (is_function(L, fname)) { try { - luabind::call_function(L, fname, u); + call_function(L, fname, u); } - catch (luabind::error& e) { + 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", @@ -171,9 +174,9 @@ lua_changeresource(unit * u, const struct resource_type * rtype, int delta) lua_State * L = (lua_State *)global.vm_state; if (is_function(L, fname)) { try { - retval = luabind::call_function(L, fname, u, delta); + retval = call_function(L, fname, u, delta); } - catch (luabind::error& e) { + 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", @@ -189,17 +192,17 @@ bool is_function(struct lua_State * luaState, const char * fname) { #if BOOST_VERSION > 103002 - luabind::object globals = luabind::globals(luaState); - luabind::object fun = globals[fname]; + object globals = globals(luaState); + object fun = globals[fname]; if (fun.is_valid()) { - if (luabind::type(fun)==LUA_TFUNCTION) { + if (type(fun)==LUA_TFUNCTION) { return true; } - log_warning(("Lua global object %s is not a function, type is %u\n", fname, luabind::type(fun))); + log_warning(("Lua global object %s is not a function, type is %u\n", fname, type(fun))); } #else - luabind::object globals = luabind::get_globals(luaState); - luabind::object fun = globals[fname]; + object globals = get_globals(luaState); + object fun = globals[fname]; if (fun.is_valid()) { if (fun.type()==LUA_TFUNCTION) { return true; @@ -220,9 +223,9 @@ lua_getresource(unit * u, const struct resource_type * rtype) lua_State * L = (lua_State *)global.vm_state; if (is_function(L, fname)) { try { - retval = luabind::call_function(L, fname, u); + retval = call_function(L, fname, u); } - catch (luabind::error& e) { + 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", @@ -234,6 +237,69 @@ lua_getresource(unit * u, const struct resource_type * rtype) return retval; } +struct script_interface { + void destroy() { + delete wage; + wage = 0; + delete maintenance; + maintenance = 0; + } + object * wage; + object * maintenance; +}; + +static script_interface interface; + +static int +lua_wage(const region * r, const faction * f, const race * rc) +{ + int retval = -1; + + assert(interface.wage); + try { + retval = object_cast(interface.wage->operator()(r, f, rc)); + } + catch (error& e) { + lua_State* L = e.state(); + const char* error = lua_tostring(L, -1); + log_error(("An exception occured in interface 'wage': %s.\n", error)); + lua_pop(L, 1); + std::terminate(); + } + return retval; +} + +static int +lua_maintenance(const unit * u) +{ + int retval = -1; + assert(interface.maintenance); + + try { + retval = object_cast(interface.maintenance->operator()(u)); + } + catch (error& e) { + lua_State* L = e.state(); + const char* error = lua_tostring(L, -1); + log_error(("An exception occured in interface 'maintenance': %s.\n", error)); + lua_pop(L, 1); + std::terminate(); + } + return retval; +} + +static void +overload(const char * name, const object& f) +{ + if (strcmp(name, "wage")==0) { + global.functions.wage = &lua_wage; + interface.wage = new object(f);; + } else if (strcmp(name, "maintenance")==0) { + global.functions.maintenance = &lua_maintenance; + interface.maintenance = new object(f);; + } +} + void bind_script(lua_State * L) { @@ -242,4 +308,14 @@ 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"); + + module(L)[ + def("overload", &overload) + ]; +} + +void +reset_scripts() +{ + interface.destroy(); } diff --git a/src/eressea/lua/script.h b/src/eressea/lua/script.h index 4667d1cae..6f30f465c 100644 --- a/src/eressea/lua/script.h +++ b/src/eressea/lua/script.h @@ -16,5 +16,6 @@ extern int call_script(struct unit * u); extern void setscript(struct attrib ** ap, void * fptr); extern bool is_function(struct lua_State * luaState, const char * fname); +extern void reset_scripts(); #endif diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp index af5bed104..920660610 100644 --- a/src/eressea/server.cpp +++ b/src/eressea/server.cpp @@ -94,6 +94,7 @@ /* lua includes */ #include "lua/bindings.h" +#include "lua/script.h" #include #include #include @@ -320,6 +321,7 @@ lua_init(void) void lua_done(lua_State * luaState) { + reset_scripts(); lua_close(luaState); } diff --git a/src/res/eressea.xml b/src/res/eressea.xml index 41de7522d..76c36d810 100644 --- a/src/res/eressea.xml +++ b/src/res/eressea.xml @@ -22,6 +22,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/res/hse-05-01.xml b/src/res/hse-05-01.xml index 0089df9c9..6137faf38 100644 --- a/src/res/hse-05-01.xml +++ b/src/res/hse-05-01.xml @@ -26,6 +26,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/res/hse4.xml b/src/res/hse4.xml index bcf909094..57668f43c 100644 --- a/src/res/hse4.xml +++ b/src/res/hse4.xml @@ -26,9 +26,41 @@ Game specific + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/res/tutorial.xml b/src/res/tutorial.xml index 56b789c26..fe2eb2d8e 100644 --- a/src/res/tutorial.xml +++ b/src/res/tutorial.xml @@ -23,6 +23,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/res/vinyambar-wdw.xml b/src/res/vinyambar-wdw.xml index 4661227bb..d10364928 100644 --- a/src/res/vinyambar-wdw.xml +++ b/src/res/vinyambar-wdw.xml @@ -22,6 +22,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +