diff --git a/conf/e3/config.xml b/conf/e3/config.xml index e0669c527..4ddf8ab21 100644 --- a/conf/e3/config.xml +++ b/conf/e3/config.xml @@ -100,6 +100,7 @@ + diff --git a/conf/e4/config.xml b/conf/e4/config.xml index 1924ff2c9..99ddbdf1d 100644 --- a/conf/e4/config.xml +++ b/conf/e4/config.xml @@ -101,6 +101,7 @@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34cb0987b..d17552712 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ ENDIF() set (ERESSEA_SRC move.c + repair.c spells.c battle.c alchemy.c diff --git a/src/kernel/save.c b/src/kernel/save.c index 9f6021b65..418f55864 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -48,6 +48,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "unit.h" #include "lighthouse.h" #include "version.h" +#include "repair.h" /* attributes includes */ #include @@ -1695,6 +1696,11 @@ int readgame(const char *filename, int backup) remove_empty_factions(); } log_printf(stdout, "Done loading turn %d.\n", turn); + + n = get_param_int(global.parameters, "fix.spells", -1); + if (n>=turn) { + repair_spells("spells.txt"); + } return 0; } diff --git a/src/repair.c b/src/repair.c new file mode 100644 index 000000000..b02b0a005 --- /dev/null +++ b/src/repair.c @@ -0,0 +1,86 @@ +#include +#include + +#include "repair.h" +#include +#include + +#include +#include + +#include + +#include +#include + +static void write_spellbook_states(FILE *F) { + faction *f; + for (f = factions; f; f = f->next) { + spellbook *sb = f->spellbook; + int len = sb ? ql_length(sb->spells) : 0; + fprintf(F, "%s %d %d\n", itoa36(f->no), f->subscription, len); + } +} + +static void limit_spellbook(faction *f, int num) { + spellbook *sb = f->spellbook; + int len = sb ? ql_length(sb->spells) : 0; + if (len < num) { + log_error("limit_spellbook: spellbook is shorter than expected, %d < %d", len, num); + } + // delete spells backwards from the end: + while (len > num) { + ql_delete(&sb->spells, len--); + } +} + +void repair_spells(const char *filename) { + FILE *F = fopen(filename, "r"); + if (F) { + char id[32]; + int numspells, sub; + faction *f; + while (fscanf(F, "%s %d %d", id, &sub, &numspells) != EOF) { + int no = atoi36(id); + + f = findfaction(no); + if (!f) { + for (f = factions; f; f = f->next) { + if (f->subscription == sub) { + break; + } + } + if (f) { + log_info("repair_spells: faction %s renamed to %s, located by subscription %d", id, itoa36(f->no), sub); + } + else { + log_warning("repair_spells: cannot fix faction %s, no such subscription: %d (%d spells)", id, sub, numspells); + continue; + } + } + if (f->subscription != sub) { + log_warning("repair_spells: subscription mismatch for faction %s, %d!=%d (%d spells)", id, f->subscription, sub, numspells); + } + else { + limit_spellbook(f, numspells); + fset(f, FFL_MARK); + } + } + for (f = factions; f; f = f->next) { + if (!fval(f, FFL_MARK)) { + numspells = ql_length(f->spellbook->spells); + log_warning("repair_spells: faction %s did not get a spellbook fix (%d spells at level)", itoa36(f->no), numspells, f->max_spelllevel); + } + freset(f, FFL_MARK); + } + } + else { + F = fopen(filename, "w"); + if (!F) { + perror("repair_spells"); + abort(); + } + write_spellbook_state(F); + } + fclose(F); +} diff --git a/src/repair.h b/src/repair.h new file mode 100644 index 000000000..cf20fb1be --- /dev/null +++ b/src/repair.h @@ -0,0 +1,14 @@ + +#ifndef H_REPAIR +#define H_REPAIR + +#ifdef __cplusplus +extern "C" { +#endif + + void repair_spells(const char *filename); // one-time reduction of E3/E4 spellbooks (called at the end of readgame) + +#ifdef __cplusplus +} +#endif +#endif