Merge branch 'develop' into develop

This commit is contained in:
Enno Rehling 2017-02-02 20:27:47 +01:00 committed by GitHub
commit 3b46004828
11 changed files with 75 additions and 68 deletions

View File

@ -718,6 +718,7 @@ static void cr_output_spells(stream *out, const unit * u, int maxlevel)
for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) { for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->level <= maxlevel) { if (sbe->level <= maxlevel) {
// TODO: no need to deref spref here, spref->name == sp->sname
spell * sp = sbe->sp; spell * sp = sbe->sp;
const char *name = translate(mkname("spell", sp->sname), spell_name(sp, f->locale)); const char *name = translate(mkname("spell", sp->sname), spell_name(sp, f->locale));
if (!header) { if (!header) {

View File

@ -87,8 +87,7 @@ void equipment_setskill(equipment * eq, skill_t sk, const char *value)
} }
typedef struct lazy_spell { typedef struct lazy_spell {
char *name; struct spellref *spref;
struct spell *sp;
int level; int level;
} lazy_spell; } lazy_spell;
@ -96,9 +95,8 @@ void equipment_addspell(equipment * eq, const char * name, int level)
{ {
if (eq) { if (eq) {
lazy_spell *ls = malloc(sizeof(lazy_spell)); lazy_spell *ls = malloc(sizeof(lazy_spell));
ls->sp = NULL; ls->spref = spellref_create(NULL, name);
ls->level = level; ls->level = level;
ls->name = strdup(name);
selist_push(&eq->spells, ls); selist_push(&eq->spells, ls);
} }
} }
@ -162,12 +160,8 @@ void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask)
for (qi = 0; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0; ql; selist_advance(&ql, &qi, 1)) {
lazy_spell *sbe = (lazy_spell *)selist_get(ql, qi); lazy_spell *sbe = (lazy_spell *)selist_get(ql, qi);
if (!sbe->sp) { spell *sp = spellref_get(sbe->spref);
sbe->sp = find_spell(sbe->name); unit_add_spell(u, mage, sp, sbe->level);
free(sbe->name);
sbe->name = NULL;
}
unit_add_spell(u, mage, sbe->sp, sbe->level);
} }
} }
} }
@ -238,7 +232,7 @@ void equip_items(struct item **items, const struct equipment *eq)
void free_ls(void *arg) { void free_ls(void *arg) {
lazy_spell *ls = (lazy_spell*)arg; lazy_spell *ls = (lazy_spell*)arg;
free(ls->name); spellref_free(ls->spref);
free(ls); free(ls);
} }

View File

@ -146,12 +146,18 @@ spell *find_spellbyid(unsigned int id)
return NULL; return NULL;
} }
struct spellref *spellref_create(const char *name) struct spellref *spellref_create(spell *sp, const char *name)
{ {
spellref *spref = malloc(sizeof(spellref)); spellref *spref = malloc(sizeof(spellref));
if (sp) {
spref->sp = sp;
spref->name = strdup(sp->sname);
}
else if (name) {
spref->name = strdup(name); spref->name = strdup(name);
spref->sp = NULL; spref->sp = NULL;
}
return spref; return spref;
} }
@ -166,6 +172,7 @@ void spellref_free(spellref *spref)
struct spell *spellref_get(struct spellref *spref) struct spell *spellref_get(struct spellref *spref)
{ {
if (!spref->sp) { if (!spref->sp) {
assert(spref->name);
spref->sp = find_spell(spref->name); spref->sp = find_spell(spref->name);
if (spref->sp) { if (spref->sp) {
free(spref->name); free(spref->name);

View File

@ -50,7 +50,7 @@ extern "C" {
struct spell *sp; struct spell *sp;
} spellref; } spellref;
struct spellref *spellref_create(const char *name); struct spellref *spellref_create(struct spell *sp, const char *name);
void spellref_free(struct spellref *spref); void spellref_free(struct spellref *spref);
struct spell *spellref_get(struct spellref *spref); struct spell *spellref_get(struct spellref *spref);
@ -70,7 +70,7 @@ extern "C" {
} }
#endif #endif
#endif #endif
/* ------------------------------------------------------------- *//* Erläuterungen zu den Spruchdefinitionen /* ------------------------------------------------------------- *//* Erl<EFBFBD>uterungen zu den Spruchdefinitionen
* *
* Spruchstukturdefinition: * Spruchstukturdefinition:
* spell{ * spell{
@ -88,35 +88,35 @@ extern "C" {
* id: * id:
* SPL_NOSPELL muss der letzte Spruch in der Liste spelldaten sein, * SPL_NOSPELL muss der letzte Spruch in der Liste spelldaten sein,
* denn nicht auf die Reihenfolge in der Liste sondern auf die id wird * denn nicht auf die Reihenfolge in der Liste sondern auf die id wird
* geprüft * gepr<EFBFBD>ft
* *
* sptyp: * sptyp:
* besondere Spruchtypen und Flags * besondere Spruchtypen und Flags
* (Regionszauber, Kampfzauber, Farcastbar, Stufe variable, ..) * (Regionszauber, Kampfzauber, Farcastbar, Stufe variable, ..)
* *
* rank: * rank:
* gibt die Priorität und damit die Reihenfolge an, in der der Spruch * gibt die Priorit<EFBFBD>t und damit die Reihenfolge an, in der der Spruch
* gezaubert wird. * gezaubert wird.
* 1: Aura übertragen * 1: Aura <EFBFBD>bertragen
* 2: Antimagie * 2: Antimagie
* 3: Magierverändernde Sprüche (Magic Boost, ..) * 3: Magierver<EFBFBD>ndernde Spr<EFBFBD>che (Magic Boost, ..)
* 4: Monster erschaffen * 4: Monster erschaffen
* 5: Standartlevel * 5: Standartlevel
* 7: Teleport * 7: Teleport
* *
* Komponenten[Anzahl mögl. Items][Art:Anzahl:Kostentyp] * Komponenten[Anzahl m<EFBFBD>gl. Items][Art:Anzahl:Kostentyp]
* *
* R_AURA: * R_AURA:
* Grundkosten für einen Zauber. Soviel Mp ssen mindestens investiert * Grundkosten f<EFBFBD>r einen Zauber. Soviel Mp m<EFBFBD>ssen mindestens investiert
* werden, um den Spruch zu wirken. Zusätzliche Mp nnen unterschiedliche * werden, um den Spruch zu wirken. Zus<EFBFBD>tzliche Mp k<EFBFBD>nnen unterschiedliche
* Auswirkungen haben, die in der Spruchfunktionsroutine definiert werden. * Auswirkungen haben, die in der Spruchfunktionsroutine definiert werden.
* *
* R_PERMAURA: * R_PERMAURA:
* Kosten an permantenter Aura * Kosten an permantenter Aura
* *
* Komponenten Kostentyp: * Komponenten Kostentyp:
* SPC_LEVEL == Spruch mit Levelabhängigen Magiekosten. Die angegeben * SPC_LEVEL == Spruch mit Levelabh<EFBFBD>ngigen Magiekosten. Die angegeben
* Kosten müssen r Stufe 1 berechnet sein. * Kosten m<EFBFBD>ssen f<EFBFBD>r Stufe 1 berechnet sein.
* SPC_FIX == Feste Kosten * SPC_FIX == Feste Kosten
* *
* Wenn keine spezielle Syntax angegeben ist, wird die * Wenn keine spezielle Syntax angegeben ist, wird die
@ -137,34 +137,34 @@ extern "C" {
* *
* u : eine Einheitennummer * u : eine Einheitennummer
* r : hier kommen zwei Regionskoordinaten x y * r : hier kommen zwei Regionskoordinaten x y
* b : Gebäude- oder Burgnummer * b : Geb<EFBFBD>ude- oder Burgnummer
* s : Schiffsnummer * s : Schiffsnummer
* c : String, wird ohne Weiterverarbeitung übergeben * c : String, wird ohne Weiterverarbeitung <EFBFBD>bergeben
* i : Zahl (int), wird ohne Weiterverarbeitung übergeben * i : Zahl (int), wird ohne Weiterverarbeitung <EFBFBD>bergeben
* k : Keywort - dieser String gibt den Paramter an, der folgt. Der * k : Keywort - dieser String gibt den Paramter an, der folgt. Der
* Parameter wird mit findparam() identifiziert. * Parameter wird mit findparam() identifiziert.
* k muss immer von einem c als Platzhalter für das Objekt gefolgt * k muss immer von einem c als Platzhalter f<EFBFBD>r das Objekt gefolgt
* werden. * werden.
* Ein gutes Beispiel sind hierfür die Sprüche zur Magieanalyse. * Ein gutes Beispiel sind hierf<EFBFBD>r die Spr<EFBFBD>che zur Magieanalyse.
* + : gibt an, das der vorherige Parameter mehrfach vorkommen kann. Da * + : gibt an, das der vorherige Parameter mehrfach vorkommen kann. Da
* ein Ende nicht definiert werden kann, muss dies immer am Schluss * ein Ende nicht definiert werden kann, muss dies immer am Schluss
* kommen. * kommen.
* *
* Flags für das Parsing: * Flags f<EFBFBD>r das Parsing:
* TESTRESISTANCE : alle Zielobjekte, also alle Parameter vom Typ Unit, * TESTRESISTANCE : alle Zielobjekte, also alle Parameter vom Typ Unit,
* Burg, Schiff oder Region, werden auf ihre * Burg, Schiff oder Region, werden auf ihre
* Magieresistenz überprüft * Magieresistenz <EFBFBD>berpr<EFBFBD>ft
* TESTCANSEE : jedes Objekt vom Typ Einheit wird auf seine * TESTCANSEE : jedes Objekt vom Typ Einheit wird auf seine
* Sichtbarkeit überprüft * Sichtbarkeit <EFBFBD>berpr<EFBFBD>ft
* SEARCHLOCAL : die Zielobjekte werden nur regional gesucht * SEARCHLOCAL : die Zielobjekte werden nur regional gesucht
* REGIONSPELL : Ziel ist die Region, auch wenn kein Zielobjekt * REGIONSPELL : Ziel ist die Region, auch wenn kein Zielobjekt
* angegeben wird. Ist TESTRESISTANCE gesetzt, so wird * angegeben wird. Ist TESTRESISTANCE gesetzt, so wird
* die Magieresistenz der Region überprüft * die Magieresistenz der Region <EFBFBD>berpr<EFBFBD>ft
* *
* Bei fehlendem Ziel oder wenn dieses dem Zauber widersteht, wird die * Bei fehlendem Ziel oder wenn dieses dem Zauber widersteht, wird die
* Spruchfunktion nicht aufgerufen. * Spruchfunktion nicht aufgerufen.
* Sind zu wenig Parameter vorhanden, wird der Zauber ebenfalls nicht * Sind zu wenig Parameter vorhanden, wird der Zauber ebenfalls nicht
* ausgeführt. * ausgef<EFBFBD>hrt.
* Ist eins von mehreren Zielobjekten resistent, so wird das Flag * Ist eins von mehreren Zielobjekten resistent, so wird das Flag
* pa->param[n]->flag == TARGET_RESISTS * pa->param[n]->flag == TARGET_RESISTS
* Ist eins von mehreren Zielobjekten nicht gefunden worden, so ist * Ist eins von mehreren Zielobjekten nicht gefunden worden, so ist

View File

@ -74,13 +74,14 @@ static void test_spellref(CuTest *tc)
spellref *ref; spellref *ref;
spell *sp; spell *sp;
test_setup(); test_setup();
ref = spellref_create("hodor"); ref = spellref_create(NULL, "hodor");
CuAssertPtrNotNull(tc, ref); CuAssertPtrNotNull(tc, ref);
CuAssertPtrEquals(tc, NULL, ref->sp);
CuAssertStrEquals(tc, "hodor", ref->name);
CuAssertPtrEquals(tc, NULL, spellref_get(ref)); CuAssertPtrEquals(tc, NULL, spellref_get(ref));
sp = create_spell("hodor", 0); sp = create_spell("hodor", 0);
CuAssertPtrNotNull(tc, sp); CuAssertPtrNotNull(tc, sp);
CuAssertPtrEquals(tc, sp, spellref_get(ref)); CuAssertPtrEquals(tc, sp, spellref_get(ref));
CuAssertPtrEquals(tc, NULL, ref->name);
spellref_free(ref); spellref_free(ref);
test_cleanup(); test_cleanup();
} }

View File

@ -71,7 +71,7 @@ void write_spellbook(const struct spellbook *book, struct storage *store)
WRITE_TOK(store, "end"); WRITE_TOK(store, "end");
} }
void spellbook_add(spellbook *sb, struct spell * sp, int level) void spellbook_add(spellbook *sb, spell *sp, int level)
{ {
spellbook_entry * sbe; spellbook_entry * sbe;
@ -116,7 +116,7 @@ int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *),
return 0; return 0;
} }
spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp) spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp)
{ {
if (sb) { if (sb) {
selist *ql; selist *ql;
@ -124,11 +124,10 @@ spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp)
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
if (sp == sbe->sp) { if (sbe->sp==sp) {
return sbe; return sbe;
} }
} }
} }
return 0; return 0;
} }

View File

@ -29,7 +29,7 @@ extern "C" {
struct selist; struct selist;
typedef struct spellbook_entry { typedef struct spellbook_entry {
struct spell * sp; struct spell *sp;
int level; int level;
} spellbook_entry; } spellbook_entry;
@ -44,10 +44,10 @@ extern "C" {
void read_spellbook(struct spellbook **bookp, struct gamedata *data, int(*get_level)(const struct spell * sp, void *), void * cbdata); void read_spellbook(struct spellbook **bookp, struct gamedata *data, int(*get_level)(const struct spell * sp, void *), void * cbdata);
void write_spellbook(const struct spellbook *book, struct storage *store); void write_spellbook(const struct spellbook *book, struct storage *store);
void spellbook_add(spellbook *sbp, struct spell * sp, int level); void spellbook_add(spellbook *sbp, struct spell *sp, int level);
int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data); int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data);
void spellbook_clear(spellbook *sb); void spellbook_clear(spellbook *sb);
spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp); spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -79,7 +79,7 @@ static spellref *xml_spellref(xmlNode * node, const char *name)
{ {
xmlChar *propValue = xmlGetProp(node, BAD_CAST name); xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
if (propValue != NULL) { if (propValue != NULL) {
spellref *ref = spellref_create((const char *)propValue); spellref *ref = spellref_create(NULL, (const char *)propValue);
xmlFree(propValue); xmlFree(propValue);
return ref; return ref;
} }
@ -2068,17 +2068,20 @@ static int parse_strings(xmlDocPtr doc)
void register_xmlreader(void) void register_xmlreader(void)
{ {
xml_register_callback(parse_strings);
xml_register_callback(parse_messages);
xml_register_callback(parse_resources);
xml_register_callback(parse_rules); xml_register_callback(parse_rules);
xml_register_callback(parse_buildings); /* requires resources */ xml_register_callback(parse_races);
xml_register_callback(parse_spells); /* requires resources */
xml_register_callback(parse_ships); /* requires terrains */
xml_register_callback(parse_races); /* requires spells */
xml_register_callback(parse_spellbooks); /* requires spells */
xml_register_callback(parse_equipment); /* requires spells */
xml_register_callback(parse_calendar); xml_register_callback(parse_calendar);
xml_register_callback(parse_resources);
xml_register_callback(parse_buildings); /* requires resources */
xml_register_callback(parse_ships); /* requires resources, terrains */
xml_register_callback(parse_equipment); /* requires resources */
xml_register_callback(parse_spells); /* requires resources */
xml_register_callback(parse_spellbooks); /* requires spells */
xml_register_callback(parse_strings);
xml_register_callback(parse_messages);
} }
#endif #endif

View File

@ -430,7 +430,6 @@ void show_new_spells(faction * f, int level, const spellbook *book)
for (qi = 0; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->level <= level) { if (sbe->level <= level) {
if (!already_seen(f, sbe->sp)) { if (!already_seen(f, sbe->sp)) {
attrib * a = a_new(&at_reportspell); attrib * a = a_new(&at_reportspell);
spellbook_entry * entry = (spellbook_entry *)a->data.v; spellbook_entry * entry = (spellbook_entry *)a->data.v;
@ -481,7 +480,8 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
commonspells[maxspell] = sbe; commonspells[maxspell] = sbe;
sbe = 0; sbe = 0;
} }
else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { else {
if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) {
// already have this spell, remove it from the list of candidates // already have this spell, remove it from the list of candidates
commonspells[spellno] = commonspells[--numspells]; commonspells[spellno] = commonspells[--numspells];
if (maxspell > numspells) { if (maxspell > numspells) {
@ -490,6 +490,7 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
sbe = 0; sbe = 0;
} }
} }
}
if (sbe && spellno < maxspell) { if (sbe && spellno < maxspell) {
if (!f->spellbook) { if (!f->spellbook) {
@ -2948,6 +2949,7 @@ const char *spell_info(const spell * sp, const struct locale *lang)
return LOC(lang, mkname("spellinfo", sp->sname)); return LOC(lang, mkname("spellinfo", sp->sname));
} }
// TODO: should take the name, not the spell (spellref optimizations)
const char *spell_name(const spell * sp, const struct locale *lang) const char *spell_name(const spell * sp, const struct locale *lang)
{ {
return LOC(lang, mkname("spell", sp->sname)); return LOC(lang, mkname("spell", sp->sname));
@ -2967,15 +2969,14 @@ static void select_spellbook(void **tokens, spellbook *sb, const struct locale *
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
spell *sp = sbe->sp;
const char *n = spell_name(sp, lang); const char *n = spell_name(sbe->sp, lang);
if (!n) { if (!n) {
log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname); log_error("no translation in locale %s for spell %s\n", locale_name(lang), sbe->sp->sname);
} }
else { else {
variant token; variant token;
token.v = sp; token.v = sbe->sp;
addtoken((struct tnode **)tokens, n, token); addtoken((struct tnode **)tokens, n, token);
} }
} }

View File

@ -234,7 +234,7 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
} while (*begin); } while (*begin);
} }
static size_t write_spell_modifier(spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) { static size_t write_spell_modifier(const spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) {
if (sp->sptyp & flag) { if (sp->sptyp & flag) {
size_t bytes = 0; size_t bytes = 0;
if (cont) { if (cont) {
@ -255,7 +255,7 @@ void nr_spell_syntax(struct stream *out, spellbook_entry * sbe, const struct loc
char buf[4096]; char buf[4096];
char *bufp = buf; char *bufp = buf;
size_t size = sizeof(buf) - 1; size_t size = sizeof(buf) - 1;
spell * sp = sbe->sp; const spell * sp = sbe->sp;
const char *params = sp->parameter; const char *params = sp->parameter;
if (sp->sptyp & ISCOMBATSPELL) { if (sp->sptyp & ISCOMBATSPELL) {
@ -445,7 +445,7 @@ void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *la
char buf[4096]; char buf[4096];
char *startp, *bufp = buf; char *startp, *bufp = buf;
size_t size = sizeof(buf) - 1; size_t size = sizeof(buf) - 1;
spell * sp = sbe->sp; const spell * sp = sbe->sp;
newline(out); newline(out);
centre(out, spell_name(sp, lang), true); centre(out, spell_name(sp, lang), true);

View File

@ -680,6 +680,7 @@ size_t size)
if (wrptr(&bufp, &size, result) != 0) { if (wrptr(&bufp, &size, result) != 0) {
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
} }
// TODO: no need to deref the spellref here (spref->name is good)
bufp = STRLCPY(bufp, spell_name(sbe->sp, f->locale), size); bufp = STRLCPY(bufp, spell_name(sbe->sp, f->locale), size);
} }
} }