diff --git a/.gitmodules b/.gitmodules
index e5eb61079..7c4dc3765 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,31 +1,31 @@
[submodule "lunit"]
path = lunit
- url = git://github.com/badgerman/lunit.git
+ url = git://github.com/ennorehling/lunit.git
[submodule "crypto"]
path = crypto
- url = git://github.com/badgerman/crypto.git
+ url = git://github.com/ennorehling/crypto.git
[submodule "cmake"]
path = cmake
- url = git://github.com/badgerman/cmake.git
+ url = git://github.com/ennorehling/cmake.git
[submodule "quicklist"]
path = quicklist
- url = git://github.com/badgerman/quicklist.git
+ url = git://github.com/ennorehling/quicklist.git
[submodule "critbit"]
path = critbit
- url = git://github.com/badgerman/critbit.git
+ url = git://github.com/ennorehling/critbit.git
[submodule "dlmalloc"]
path = dlmalloc
- url = git://github.com/badgerman/dlmalloc.git
+ url = git://github.com/ennorehling/dlmalloc.git
[submodule "cutest"]
path = cutest
- url = git://github.com/badgerman/cutest.git
-[submodule "iniparser"]
- path = iniparser
- url = git://github.com/badgerman/iniparser.git
+ url = git://github.com/ennorehling/cutest.git
[submodule "cJSON"]
path = cJSON
- url = git://github.com/badgerman/cJSON.git
+ url = git://github.com/ennorehling/cJSON.git
+[submodule "iniparser"]
+ path = iniparser
+ url = git://github.com/ennorehling/iniparser.git
[submodule "storage"]
path = storage
- url = git://github.com/badgerman/storage.git
+ url = git://github.com/ennorehling/storage.git
branch = master
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/buildno.h b/src/buildno.h
index a8118b327..a0d2bfde8 100644
--- a/src/buildno.h
+++ b/src/buildno.h
@@ -1,3 +1,3 @@
#define VERSION_MAJOR 3
#define VERSION_MINOR 5
-#define VERSION_BUILD 4
+#define VERSION_BUILD 5
diff --git a/src/kernel/save.c b/src/kernel/save.c
index 114126b0c..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
@@ -1165,6 +1166,9 @@ faction *readfaction(struct gamedata * data)
}
READ_INT(data->store, &f->subscription);
+ if (data->version >= SPELL_LEVEL_VERSION) {
+ READ_INT(data->store, &f->max_spelllevel);
+ }
if (alliances || data->version >= OWNER_2_VERSION) {
int allianceid;
READ_INT(data->store, &allianceid);
@@ -1294,6 +1298,9 @@ void writefaction(struct gamedata *data, const faction * f)
write_faction_reference(f, data->store);
WRITE_INT(data->store, f->subscription);
+#if RELEASE_VERSION >= SPELL_LEVEL_VERSION
+ WRITE_INT(data->store, f->max_spelllevel);
+#endif
if (f->alliance) {
WRITE_INT(data->store, f->alliance->id);
if (f->alliance->flags & ALF_NON_ALLIED) {
@@ -1348,6 +1355,14 @@ void writefaction(struct gamedata *data, const faction * f)
write_spellbook(f->spellbook, data->store);
}
+static int cb_sb_maxlevel(spellbook_entry *sbe, void *cbdata) {
+ faction *f = (faction *)cbdata;
+ if (sbe->level > f->max_spelllevel) {
+ f->max_spelllevel = sbe->level;
+ }
+ return 0;
+}
+
int readgame(const char *filename, int backup)
{
int n, p, nread;
@@ -1648,32 +1663,44 @@ int readgame(const char *filename, int backup)
}
else {
for (u = f->units; u; u = u->nextF) {
- sc_mage *mage = get_mage(u);
- if (mage) {
- faction *f = u->faction;
- int skl = effskill(u, SK_MAGIC);
- if (f->magiegebiet == M_GRAY) {
- log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]);
- f->magiegebiet = mage->magietyp;
- }
- if (f->max_spelllevel < skl) {
- f->max_spelllevel = skl;
- }
- if (mage->spellcount < 0) {
- mage->spellcount = 0;
+ if (global.data_version < SPELL_LEVEL_VERSION) {
+ sc_mage *mage = get_mage(u);
+ if (mage) {
+ faction *f = u->faction;
+ int skl = effskill(u, SK_MAGIC);
+ if (f->magiegebiet == M_GRAY) {
+ log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]);
+ f->magiegebiet = mage->magietyp;
+ }
+ if (f->max_spelllevel < skl) {
+ f->max_spelllevel = skl;
+ }
+ if (mage->spellcount < 0) {
+ mage->spellcount = 0;
+ }
}
}
if (u->number > 0) {
f->alive = true;
- break;
+ if (global.data_version >= SPELL_LEVEL_VERSION) {
+ break;
+ }
}
}
+ if (global.data_version < SPELL_LEVEL_VERSION) {
+ spellbook_foreach(f->spellbook, cb_sb_maxlevel, f);
+ }
}
}
if (loadplane || maxregions >= 0) {
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/kernel/version.h b/src/kernel/version.h
index 430628157..a32cfbe96 100644
--- a/src/kernel/version.h
+++ b/src/kernel/version.h
@@ -30,8 +30,9 @@
#define AUTO_RACENAME_VERSION 345 /* NPC units with name==NULL will automatically get their race for a name */
#define JSON_REPORT_VERSION 346 /* bit 3 in f->options flags the json report */
#define EXPLICIT_CURSE_ISNEW_VERSION 347 /* CURSE_ISNEW is not reset in read/write, but in age() */
+#define SPELL_LEVEL_VERSION 348 /* f->max_spelllevel gets stored, not calculated */
-#define RELEASE_VERSION EXPLICIT_CURSE_ISNEW_VERSION /* current datafile */
+#define RELEASE_VERSION SPELL_LEVEL_VERSION /* current datafile */
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
diff --git a/src/laws.c b/src/laws.c
index b867b9f14..9a62ac53f 100755
--- a/src/laws.c
+++ b/src/laws.c
@@ -4531,7 +4531,6 @@ void processorders(void)
init_processor();
init = 1;
}
- update_spells();
process();
/*************************************************/
diff --git a/src/magic.c b/src/magic.c
index 72fe72a25..9ad9e0ad9 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -464,11 +464,13 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
spellno = rng_int() % maxspell;
sbe = commonspells[spellno];
if (sbe->level > f->max_spelllevel) {
+ // not going to pick it in this round, move it to the end for later
commonspells[spellno] = commonspells[--maxspell];
commonspells[maxspell] = sbe;
sbe = 0;
}
else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) {
+ // already have this spell, remove it from the list of candidates
commonspells[spellno] = commonspells[--numspells];
if (maxspell > numspells) {
maxspell = numspells;
diff --git a/src/repair.c b/src/repair.c
new file mode 100644
index 000000000..665f250ae
--- /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_states(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