diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index ddb112b1d..774278dc4 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -1170,7 +1170,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr) } cr_output_curses(F, f, r, TYP_REGION); cr_borders(ctx->seen, r, f, sr->mode, F); - if (sr->mode==see_unit && r->planep==get_astralplane() && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) + if (sr->mode==see_unit && is_astral(r) && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { /* Sonderbehandlung Teleport-Ebene */ region_list *rl = astralregions(r, inhabitable); diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 36dfeffa5..ed63de6a9 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -340,7 +340,7 @@ age_unit(region * r, unit * u) } } #ifdef ASTRAL_ITEM_RESTRICTIONS - if (u->region && u->region->planep==get_astralplane()) { + if (u->region && is_astral(u->region)) { item ** itemp = &u->items; while (*itemp) { item * itm = *itemp; diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index bacc16cc3..0776e6cf4 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -1072,7 +1072,7 @@ describe(FILE * F, const seen_region * sr, faction * f) *bufp = 0; rparagraph(F, buf, 0, 0, 0); - if (sr->mode==see_unit && rplane(r) == get_astralplane() && + if (sr->mode==see_unit && is_astral(r) && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { /* Sonderbehandlung Teleport-Ebene */ region_list *rl = astralregions(r, inhabitable); diff --git a/src/common/gamecode/xmlreport.c b/src/common/gamecode/xmlreport.c index 89da806c1..3a8b66b7a 100644 --- a/src/common/gamecode/xmlreport.c +++ b/src/common/gamecode/xmlreport.c @@ -60,6 +60,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include /* libxml2 includes */ #include @@ -84,14 +85,6 @@ typedef struct xml_context { xmlNsPtr ns_xml; } xml_context; -static const xmlChar * -xml_i(double number) -{ - static char buffer[128]; - snprintf(buffer, sizeof(buffer), "%.0lf", number); - return (const xmlChar *)buffer; -} - static xmlNodePtr xml_link(report_context * ctx, const xmlChar * rel, const xmlChar * ref) { diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index 6c9841a09..4bad90310 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -3943,6 +3943,7 @@ battle_flee(battle * b) void do_battle(region * r) { + static int max_turns = 0; battle *b = NULL; boolean fighting = false; ship * sh; @@ -3995,7 +3996,10 @@ do_battle(region * r) print_stats(b); /* gibt die Kampfaufstellung aus */ log_stdio(stdout, "%s (%d, %d) : ", rname(r, NULL), r->x, r->y); - for (;battle_report(b) && b->turn<=COMBAT_TURNS;++b->turn) { + if (max_turns==0) { + max_turns = get_param_int(global.parameters, "rules.combat_turns", COMBAT_TURNS); + } + for (;battle_report(b) && b->turn<=max_turns;++b->turn) { if (bdebug) { fprintf(bdebug, "*** Turn: %d\n", b->turn); } diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index 86b921d58..f0cc5928e 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -2428,10 +2428,8 @@ int lifestyle(const unit * u) { int need; - static plane * astralspace; static int gamecookie = -1; if (gamecookie!=global.cookie) { - astralspace = getplanebyname("Astralraum"); gamecookie = global.cookie; } diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index b20ff2fca..f41b5d391 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -88,6 +88,7 @@ extern "C" { #define BP_NORMAL 3 #define BP_ROAD 2 +#define STAMINA_AFFECTS_HP 1<<0 /** * Hier endet der Teil von eressea.h, der die defines für die diff --git a/src/common/kernel/move.c b/src/common/kernel/move.c index a08469649..f3980edde 100644 --- a/src/common/kernel/move.c +++ b/src/common/kernel/move.c @@ -1305,10 +1305,12 @@ movement_speed(unit * u) /* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell. * Nicht kumulativ mit anderen Beschleunigungen! */ - if (mp*dk <= BP_WALKING*u->race->speed && getplane(u->region) == get_astralplane() && is_mage(u)) { - sc_mage * mage = get_mage(u); - if (mage->magietyp == M_ASTRAL || mage->magietyp == M_TRAUM) { - mp *= 2; + if (get_param_int(global.parameters, "modules.astralspace", 0) != 0) { + if (mp*dk <= BP_WALKING*u->race->speed && is_astral(u->region) && is_mage(u)) { + sc_mage * mage = get_mage(u); + if (mage->magietyp == M_ASTRAL || mage->magietyp == M_TRAUM) { + mp *= 2; + } } } break; diff --git a/src/common/kernel/spell.h b/src/common/kernel/spell.h index 3e4e8ac7c..e50b38fed 100644 --- a/src/common/kernel/spell.h +++ b/src/common/kernel/spell.h @@ -40,7 +40,6 @@ extern "C" { extern struct attrib_type at_wdwpyramid; extern struct spell_list * spells; - extern void init_spells(void); extern void register_spell(struct spell * sp); extern struct spell * find_spell(magic_t mtype, const char * name); extern struct spell * find_spellbyid(magic_t mtype, spellid_t i); diff --git a/src/common/kernel/teleport.c b/src/common/kernel/teleport.c index d4f4565b2..aab6c7971 100644 --- a/src/common/kernel/teleport.c +++ b/src/common/kernel/teleport.c @@ -58,7 +58,7 @@ real2tp(short rk) { static region * tpregion(const region *r) { region * rt = findregion(TE_CENTER_X+real2tp(r->x), TE_CENTER_Y+real2tp(r->y)); - if (rplane(rt) != get_astralplane()) return NULL; + if (!is_astral(rt)) return NULL; return rt; } @@ -68,8 +68,8 @@ astralregions(const region * r, boolean (*valid)(const region *)) region_list * rlist = NULL; short x, y; - assert(rplane(r) == get_astralplane()); - if (rplane(r) != get_astralplane()) { + assert(is_astral(r)); + if (!is_astral(r)) { log_error(("astralregions was called with a non-astral region.\n")); return NULL; } @@ -102,7 +102,7 @@ r_astral_to_standard(const region *r) short x, y; region *r2; - assert(rplane(r) == get_astralplane()); + assert(is_astral(r)); x = (r->x-TE_CENTER_X)*TP_DISTANCE; y = (r->y-TE_CENTER_Y)*TP_DISTANCE; @@ -142,7 +142,7 @@ spawn_braineaters(float chance) if (f0==NULL) return; for (r = regions; r; r = r->next) { - if (rplane(r) != get_astralplane() || fval(r->terrain, FORBIDDEN_REGION)) continue; + if (!is_astral(r) || fval(r->terrain, FORBIDDEN_REGION)) continue; /* Neues Monster ? */ if (next-- == 0) { @@ -160,11 +160,25 @@ get_normalplane(void) return NULL; } +boolean +is_astral(const region * r) +{ + plane * pl = get_astralplane(); + return (pl && rplane(r) == pl); +} + plane * get_astralplane(void) { static plane * astralspace; + static int rule_astralplane = -1; static int gamecookie = -1; + if (rule_astralplane<0) { + rule_astralplane = get_param_int(global.parameters, "modules.astralspace", 0); + } + if (!rule_astralplane) { + return NULL; + } if (gamecookie!=global.cookie) { astralspace = getplanebyname("Astralraum"); gamecookie = global.cookie; @@ -195,7 +209,7 @@ create_teleport_plane(void) short y = TE_CENTER_Y+real2tp(r->y); plane * pl = findplane(x, y); - if (pl==aplane) { + if (aplane && pl==aplane) { ra = new_region(x, y, 0); terraform_region(ra, fog); ra->planep = aplane; diff --git a/src/common/kernel/teleport.h b/src/common/kernel/teleport.h index 5f6e0395b..df7c51372 100644 --- a/src/common/kernel/teleport.h +++ b/src/common/kernel/teleport.h @@ -23,6 +23,7 @@ extern "C" { extern struct region_list *astralregions(const struct region * rastral, boolean (*valid)(const struct region *)); extern struct region_list *all_in_range(const struct region *r, short n, boolean (*valid)(const struct region *)); extern boolean inhabitable(const struct region * r); + extern boolean is_astral(const struct region * r); extern struct plane * get_astralplane(void); extern struct plane * get_normalplane(void); diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c index 0b39771d8..c1d8b5cc1 100644 --- a/src/common/kernel/unit.c +++ b/src/common/kernel/unit.c @@ -1612,15 +1612,21 @@ unit_addorder(unit * u, order * ord) int unit_max_hp(const unit * u) { + static int rules_stamina = -1; int h; double p; static const curse_type * heal_ct = NULL; + + if (rules_stamina<0) { + rules_stamina = get_param_int(global.parameters, "rules.stamina", STAMINA_AFFECTS_HP); + } h = u->race->hitpoints; if (heal_ct==NULL) heal_ct = ct_find("healingzone"); - p = pow(effskill(u, SK_STAMINA) / 2.0, 1.5) * 0.2; - h += (int) (h * p + 0.5); - + if (rules_stamina & 1) { + p = pow(effskill(u, SK_STAMINA) / 2.0, 1.5) * 0.2; + h += (int) (h * p + 0.5); + } #if KARMA_MODULE if (fspecial(u->faction, FS_UNDEAD)) { h *= 2; diff --git a/src/common/kernel/xmlreader.c b/src/common/kernel/xmlreader.c index 84658dff4..725f86e66 100644 --- a/src/common/kernel/xmlreader.c +++ b/src/common/kernel/xmlreader.c @@ -38,6 +38,8 @@ without prior permission by the authors of Eressea. #include #include +#include + /* libxml includes */ #include #include @@ -1413,27 +1415,33 @@ parse_spells(xmlDocPtr doc) /* reading eressea/spells/spell/function */ xpath->node = node; result = xmlXPathEvalExpression(BAD_CAST "function", xpath); - for (k=0;k!=result->nodesetval->nodeNr;++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - pf_generic fun; - parse_function(node, &fun, &propValue); - if (fun==NULL) { - log_error(("unknown function name '%s' for spell '%s'\n", - (const char*)propValue, sp->sname)); + if (result->nodesetval->nodeNr==0) { + /* this is an old spell that has a spelldata entry */ + set_spelldata(sp); + } else { + for (k=0;k!=result->nodesetval->nodeNr;++k) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; + pf_generic fun; + + parse_function(node, &fun, &propValue); + if (fun==NULL) { + log_error(("unknown function name '%s' for spell '%s'\n", + (const char*)propValue, sp->sname)); + xmlFree(propValue); + continue; + } + assert(propValue!=NULL); + if (strcmp((const char*)propValue, "cast")==0) { + sp->sp_function = (spell_f)fun; + } else if (strcmp((const char*)propValue, "fumble")==0) { + sp->patzer = (pspell_f)fun; + } else { + log_error(("unknown function type '%s' for spell %s\n", + (const char*)propValue, sp->sname)); + } xmlFree(propValue); - continue; } - assert(propValue!=NULL); - if (strcmp((const char*)propValue, "cast")==0) { - sp->sp_function = (spell_f)fun; - } else if (strcmp((const char*)propValue, "fumble")==0) { - sp->patzer = (pspell_f)fun; - } else { - log_error(("unknown function type '%s' for spell %s\n", - (const char*)propValue, sp->sname)); - } - xmlFree(propValue); } xmlXPathFreeObject(result); } @@ -1473,8 +1481,9 @@ parse_spells(xmlDocPtr doc) xmlXPathFreeContext(xpath); - init_spells(); - + if (get_param_int(global.parameters, "init_spells", 1)!=0) { + init_spells(); + } return 0; } diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index 7edfc4398..0d9a587f3 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -1852,7 +1852,7 @@ sp_treewalkexit(castorder *co) spellparameter *pa = co->par; int cast_level = co->level; - if (getplane(r) != get_astralplane()) { + if (!is_astral(r)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralonly", "")); return 0; } @@ -5676,7 +5676,7 @@ sp_fetchastral(castorder *co) /* this can happen several times if the units are from different astral * regions. Only possible on the intersections of schemes */ region_list * rfind; - if (getplane(u->region) != get_astralplane()) { + if (!is_astral(u->region)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralonly", "")); continue; } @@ -8800,6 +8800,37 @@ border_type bt_chaosgate = { chaosgate_move }; +static void +set_spelldata_i(spell * sp, spelldata * data) +{ + int n; + for (n=0;n!=5 && data->components[n].name;++n); + sp->components = malloc(sizeof(spell_component) *(n+1)); + sp->components[n].type = NULL; + while (n-->0) { + sp->components[n].type = rt_find(data->components[n].name); + sp->components[n].amount = data->components[n].amount; + sp->components[n].cost = data->components[n].flags; + } + sp->sp_function = data->sp_function; + sp->patzer = data->patzer; +} + +void +set_spelldata(spell * sp) +{ + int i; + for (i=0;spelldaten[i].id!=SPL_NOSPELL;++i) { + spelldata * data = spelldaten+i; + if (strcmp(data->sname, sp->sname)==0) { + set_spelldata_i(sp, data); + return; + } + } + log_error(("unknown spell %s.\n", sp->sname)); + assert(!"there is no spell by that name"); +} + void init_spells(void) { @@ -8809,7 +8840,6 @@ init_spells(void) for (i=0;spelldaten[i].id!=SPL_NOSPELL;++i) { spelldata * data = spelldaten+i; spell * sp = malloc(sizeof(spell)); - int n; sp->id = data->id; sp->sname = strdup(data->sname); @@ -8822,16 +8852,7 @@ init_spells(void) sp->sptyp = data->sptyp; sp->rank = data->rank; sp->level = data->level; - for (n=0;n!=5 && data->components[n].name;++n); - sp->components = malloc(sizeof(spell_component) *(n+1)); - sp->components[n].type = NULL; - while (n-->0) { - sp->components[n].type = rt_find(data->components[n].name); - sp->components[n].amount = data->components[n].amount; - sp->components[n].cost = data->components[n].flags; - } - sp->sp_function = data->sp_function; - sp->patzer = data->patzer; + set_spelldata_i(sp, data); register_spell(sp); } at_register(&at_cursewall); diff --git a/src/common/spells/spells.h b/src/common/spells/spells.h index 44088cfd5..2b06e433c 100644 --- a/src/common/spells/spells.h +++ b/src/common/spells/spells.h @@ -41,6 +41,8 @@ extern "C" { } wall_data; int levitate_ship(struct ship * sh, struct unit * mage, double power, int duration); + void init_spells(void); + void set_spelldata(struct spell * sp); #ifdef __cplusplus } diff --git a/src/common/util/xml.c b/src/common/util/xml.c index 3bdd80e1a..3be21c622 100644 --- a/src/common/util/xml.c +++ b/src/common/util/xml.c @@ -24,6 +24,14 @@ #include #include +const xmlChar * +xml_i(double number) +{ + static char buffer[128]; + snprintf(buffer, sizeof(buffer), "%.0lf", number); + return (const xmlChar *)buffer; +} + int xml_ivalue(xmlNodePtr node, const char * name, int dflt) { diff --git a/src/common/util/xml.h b/src/common/util/xml.h index b23118e9c..e3242caf6 100644 --- a/src/common/util/xml.h +++ b/src/common/util/xml.h @@ -28,6 +28,8 @@ extern "C" { extern int xml_ivalue(xmlNodePtr node, const char * name, int dflt); extern boolean xml_bvalue(xmlNodePtr node, const char * name, boolean dflt); + const xmlChar * xml_i(double number); + #ifdef __cplusplus } #endif diff --git a/src/eressea/gmtool.c b/src/eressea/gmtool.c index 0b6d04180..48894877b 100644 --- a/src/eressea/gmtool.c +++ b/src/eressea/gmtool.c @@ -826,7 +826,7 @@ handlekey(state * st, int c) region * cur = mr->r; if (cur->planep==NULL) { cur = r_standard_to_astral(cur); - } else if (cur->planep==get_astralplane()) { + } else if (is_astral(cur)) { cur = r_astral_to_standard(cur); } else { cur = NULL; diff --git a/src/eressea/korrektur.c b/src/eressea/korrektur.c index 485e11e64..3ab4881f8 100644 --- a/src/eressea/korrektur.c +++ b/src/eressea/korrektur.c @@ -802,7 +802,7 @@ fix_astral_firewalls(void) { region * r; for (r = regions; r; r=r->next) { - if (r->planep==get_astralplane() && r->terrain == newterrain(T_FIREWALL)) { + if (is_astral(r) && r->terrain == newterrain(T_FIREWALL)) { terraform_region(r, newterrain(T_ASTRALB)); } } diff --git a/src/eressea/tolua/bindings.c b/src/eressea/tolua/bindings.c index ace4ee16d..81c63331f 100644 --- a/src/eressea/tolua/bindings.c +++ b/src/eressea/tolua/bindings.c @@ -713,6 +713,55 @@ static int tolua_set_alliance_name(lua_State* tolua_S) return 0; } +#include +#include +#include +#include + +static int +tolua_write_spells(lua_State* tolua_S) +{ + spell_f fun = (spell_f)get_function("lua_castspell"); + const char * filename = "magic.xml"; + xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); + xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "spells"); + spell_list * splist; + + for (splist=spells; splist; splist=splist->next) { + spell * sp = splist->data; + if (sp->sp_function!=fun) { + xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "spell"); + xmlNewProp(node, BAD_CAST "name", BAD_CAST sp->sname); + xmlNewProp(node, BAD_CAST "type", BAD_CAST magietypen[sp->magietyp]); + xmlNewProp(node, BAD_CAST "rank", xml_i(sp->rank)); + xmlNewProp(node, BAD_CAST "level", xml_i(sp->level)); + xmlNewProp(node, BAD_CAST "index", xml_i(sp->id)); + + if (sp->sptyp & TESTCANSEE) { + xmlNewProp(node, BAD_CAST "los", BAD_CAST "true"); + } + if (sp->sptyp & ONSHIPCAST) { + xmlNewProp(node, BAD_CAST "ship", BAD_CAST "true"); + } + if (sp->sptyp & OCEANCASTABLE) { + xmlNewProp(node, BAD_CAST "ocean", BAD_CAST "true"); + } + if (sp->sptyp & FARCASTING) { + xmlNewProp(node, BAD_CAST "far", BAD_CAST "true"); + } + if (sp->sptyp & SPELLLEVEL) { + xmlNewProp(node, BAD_CAST "variable", BAD_CAST "true"); + } + xmlAddChild(root, node); + } + } + xmlDocSetRootElement(doc, root); + xmlKeepBlanksDefault(0); + xmlSaveFormatFileEnc(filename, doc, "utf-8", 1); + xmlFreeDoc(doc); + return 0; +} + int tolua_eressea_open(lua_State* tolua_S) { @@ -811,6 +860,8 @@ tolua_eressea_open(lua_State* tolua_S) tolua_function(tolua_S, "set_key", tolua_setkey); tolua_function(tolua_S, "rng_int", tolua_rng_int); + + tolua_function(tolua_S, "write_spells", tolua_write_spells); } tolua_endmodule(tolua_S); return 1; diff --git a/src/res/changes.txt b/src/res/changes.txt index 612fa08c2..afdce13f8 100644 --- a/src/res/changes.txt +++ b/src/res/changes.txt @@ -1,5 +1,7 @@ Konzepte: - Astralraum abschaffen + = done (modules.astralspace). + = done (Zauber entfernt). - Regionsbesitz und Moral - Allianzen - GIB abstellen @@ -9,6 +11,7 @@ Talente: - Talentlimit 10 + Rassenbonus = done - Ausdauer wirkt sich nicht auf Trefferpunkte aus + = done (rules.stamina) - Wahrnehmung und Tarnung abschalten = done @@ -16,6 +19,7 @@ Kampf: - Regionen belagern - Allianz ersetzt HELFE KAEMPFE - Reduktion auf 1 Kampfrunde + = done (rules.combat_turns) - neue Trefferchanceberechnung - neue Beuteregelung diff --git a/src/res/eressea.xml b/src/res/eressea.xml index 5d434d531..8c6c4cdaa 100644 --- a/src/res/eressea.xml +++ b/src/res/eressea.xml @@ -19,7 +19,7 @@ - + @@ -75,6 +75,8 @@ + + diff --git a/src/res/eressea/spells.xml b/src/res/eressea/spells.xml new file mode 100644 index 000000000..0e825b27f --- /dev/null +++ b/src/res/eressea/spells.xml @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/res/eressea2.xml b/src/res/eressea2.xml index abe64d619..326b61e9a 100644 --- a/src/res/eressea2.xml +++ b/src/res/eressea2.xml @@ -88,9 +88,16 @@ - + + + + + + + + diff --git a/src/res/eressea2/spells.xml b/src/res/eressea2/spells.xml new file mode 100644 index 000000000..a766e0a3b --- /dev/null +++ b/src/res/eressea2/spells.xml @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/vc9/eressea.vcproj b/src/vc9/eressea.vcproj index 81c53b924..4e73e7cfe 100644 --- a/src/vc9/eressea.vcproj +++ b/src/vc9/eressea.vcproj @@ -118,6 +118,7 @@ /> + +