forked from github/server
WIP: spellref everywhere
This commit is contained in:
parent
abed38db0c
commit
7e69149c40
|
@ -718,7 +718,8 @@ static void cr_output_spells(stream *out, const unit * u, int maxlevel)
|
|||
for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
if (sbe->level <= maxlevel) {
|
||||
spell * sp = sbe->sp;
|
||||
// TODO: no need to deref spref here, spref->name == sp->sname
|
||||
spell * sp = spellref_get(sbe->spref);
|
||||
const char *name = translate(mkname("spell", sp->sname), spell_name(sp, f->locale));
|
||||
if (!header) {
|
||||
stream_printf(out, "SPRUECHE\n");
|
||||
|
@ -1621,7 +1622,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
|
|||
a = a_find(f->attribs, &at_reportspell);
|
||||
while (a && a->type == &at_reportspell) {
|
||||
spellbook_entry *sbe = (spellbook_entry *)a->data.v;
|
||||
cr_reportspell(F, sbe->sp, sbe->level, f->locale);
|
||||
cr_reportspell(F, spellref_get(sbe->spref), sbe->level, f->locale);
|
||||
a = a->next;
|
||||
}
|
||||
for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem;
|
||||
|
|
|
@ -167,10 +167,15 @@ struct spell *spellref_get(struct spellref *spref)
|
|||
{
|
||||
if (!spref->sp) {
|
||||
spref->sp = find_spell(spref->name);
|
||||
if (spref->sp) {
|
||||
free(spref->name);
|
||||
spref->name = NULL;
|
||||
}
|
||||
}
|
||||
return spref->sp;
|
||||
}
|
||||
|
||||
spellref *spellref_copy(spellref *spref)
|
||||
{
|
||||
spellref *result = spellref_create(spref->name);
|
||||
if (spref->sp) {
|
||||
result->sp = spref->sp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ extern "C" {
|
|||
|
||||
struct spellref *spellref_create(const char *name);
|
||||
void spellref_free(struct spellref *spref);
|
||||
struct spellref *spellref_copy(struct spellref *spref);
|
||||
struct spell *spellref_get(struct spellref *spref);
|
||||
|
||||
int sp_antimagiczone(struct castorder *co);
|
||||
|
@ -70,7 +71,7 @@ extern "C" {
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
/* ------------------------------------------------------------- *//* Erläuterungen zu den Spruchdefinitionen
|
||||
/* ------------------------------------------------------------- *//* Erl<EFBFBD>uterungen zu den Spruchdefinitionen
|
||||
*
|
||||
* Spruchstukturdefinition:
|
||||
* spell{
|
||||
|
@ -88,35 +89,35 @@ extern "C" {
|
|||
* id:
|
||||
* SPL_NOSPELL muss der letzte Spruch in der Liste spelldaten sein,
|
||||
* denn nicht auf die Reihenfolge in der Liste sondern auf die id wird
|
||||
* geprüft
|
||||
* gepr<EFBFBD>ft
|
||||
*
|
||||
* sptyp:
|
||||
* besondere Spruchtypen und Flags
|
||||
* (Regionszauber, Kampfzauber, Farcastbar, Stufe variable, ..)
|
||||
*
|
||||
* 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.
|
||||
* 1: Aura übertragen
|
||||
* 1: Aura <EFBFBD>bertragen
|
||||
* 2: Antimagie
|
||||
* 3: Magierverändernde Sprüche (Magic Boost, ..)
|
||||
* 3: Magierver<EFBFBD>ndernde Spr<EFBFBD>che (Magic Boost, ..)
|
||||
* 4: Monster erschaffen
|
||||
* 5: Standartlevel
|
||||
* 7: Teleport
|
||||
*
|
||||
* Komponenten[Anzahl mögl. Items][Art:Anzahl:Kostentyp]
|
||||
* Komponenten[Anzahl m<EFBFBD>gl. Items][Art:Anzahl:Kostentyp]
|
||||
*
|
||||
* R_AURA:
|
||||
* Grundkosten für einen Zauber. Soviel Mp müssen mindestens investiert
|
||||
* werden, um den Spruch zu wirken. Zusätzliche Mp können unterschiedliche
|
||||
* Grundkosten f<EFBFBD>r einen Zauber. Soviel Mp m<EFBFBD>ssen mindestens investiert
|
||||
* werden, um den Spruch zu wirken. Zus<EFBFBD>tzliche Mp k<EFBFBD>nnen unterschiedliche
|
||||
* Auswirkungen haben, die in der Spruchfunktionsroutine definiert werden.
|
||||
*
|
||||
* R_PERMAURA:
|
||||
* Kosten an permantenter Aura
|
||||
*
|
||||
* Komponenten Kostentyp:
|
||||
* SPC_LEVEL == Spruch mit Levelabhängigen Magiekosten. Die angegeben
|
||||
* Kosten müssen für Stufe 1 berechnet sein.
|
||||
* SPC_LEVEL == Spruch mit Levelabh<EFBFBD>ngigen Magiekosten. Die angegeben
|
||||
* Kosten m<EFBFBD>ssen f<EFBFBD>r Stufe 1 berechnet sein.
|
||||
* SPC_FIX == Feste Kosten
|
||||
*
|
||||
* Wenn keine spezielle Syntax angegeben ist, wird die
|
||||
|
@ -137,34 +138,34 @@ extern "C" {
|
|||
*
|
||||
* u : eine Einheitennummer
|
||||
* r : hier kommen zwei Regionskoordinaten x y
|
||||
* b : Gebäude- oder Burgnummer
|
||||
* b : Geb<EFBFBD>ude- oder Burgnummer
|
||||
* s : Schiffsnummer
|
||||
* c : String, wird ohne Weiterverarbeitung übergeben
|
||||
* i : Zahl (int), wird ohne Weiterverarbeitung übergeben
|
||||
* c : String, wird ohne Weiterverarbeitung <EFBFBD>bergeben
|
||||
* i : Zahl (int), wird ohne Weiterverarbeitung <EFBFBD>bergeben
|
||||
* k : Keywort - dieser String gibt den Paramter an, der folgt. Der
|
||||
* 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.
|
||||
* 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
|
||||
* ein Ende nicht definiert werden kann, muss dies immer am Schluss
|
||||
* kommen.
|
||||
*
|
||||
* Flags für das Parsing:
|
||||
* Flags f<EFBFBD>r das Parsing:
|
||||
* TESTRESISTANCE : alle Zielobjekte, also alle Parameter vom Typ Unit,
|
||||
* Burg, Schiff oder Region, werden auf ihre
|
||||
* Magieresistenz überprüft
|
||||
* Magieresistenz <EFBFBD>berpr<EFBFBD>ft
|
||||
* TESTCANSEE : jedes Objekt vom Typ Einheit wird auf seine
|
||||
* Sichtbarkeit überprüft
|
||||
* Sichtbarkeit <EFBFBD>berpr<EFBFBD>ft
|
||||
* SEARCHLOCAL : die Zielobjekte werden nur regional gesucht
|
||||
* REGIONSPELL : Ziel ist die Region, auch wenn kein Zielobjekt
|
||||
* 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
|
||||
* Spruchfunktion nicht aufgerufen.
|
||||
* 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
|
||||
* pa->param[n]->flag == TARGET_RESISTS
|
||||
* Ist eins von mehreren Zielobjekten nicht gefunden worden, so ist
|
||||
|
|
|
@ -50,7 +50,7 @@ void read_spellbook(spellbook **bookp, gamedata *data, int(*get_level)(const spe
|
|||
sb = *bookp;
|
||||
}
|
||||
if (level > 0 && (data->version >= SPELLBOOK_VERSION || !spellbook_get(sb, sp))) {
|
||||
spellbook_add(sb, sp, level);
|
||||
spellbook_add_spell(sb, sp, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,25 +64,43 @@ void write_spellbook(const struct spellbook *book, struct storage *store)
|
|||
if (book) {
|
||||
for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
WRITE_TOK(store, sbe->sp->sname);
|
||||
WRITE_TOK(store, sbe->spref->name);
|
||||
WRITE_INT(store, sbe->level);
|
||||
}
|
||||
}
|
||||
WRITE_TOK(store, "end");
|
||||
}
|
||||
|
||||
void spellbook_add(spellbook *sb, struct spell * sp, int level)
|
||||
void spellbook_add(spellbook *sb, spellref *spref, int level)
|
||||
{
|
||||
spellbook_entry * sbe;
|
||||
|
||||
assert(sb && sp && level > 0);
|
||||
assert(sb && spref && level > 0);
|
||||
#ifndef NDEBUG
|
||||
if (spellbook_get(sb, spellref_get(spref))) {
|
||||
log_error("duplicate spell in spellbook '%s': '%s'\n", sb->name, spref->name);
|
||||
}
|
||||
#endif
|
||||
sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry));
|
||||
sbe->spref = spellref_copy(spref);
|
||||
sbe->level = level;
|
||||
selist_push(&sb->spells, sbe);
|
||||
}
|
||||
|
||||
void spellbook_add_spell(spellbook *sb, spell *sp, int level)
|
||||
{
|
||||
spellbook_entry * sbe;
|
||||
|
||||
assert(sb && sp->sname && level > 0);
|
||||
#ifndef NDEBUG
|
||||
if (spellbook_get(sb, sp)) {
|
||||
log_error("duplicate spell in spellbook '%s': '%s'\n", sb->name, sp->sname);
|
||||
}
|
||||
#endif
|
||||
sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry));
|
||||
sbe->sp = sp;
|
||||
// FIXME: create a better API to create spellref from spell
|
||||
sbe->spref = spellref_create(sp->sname);
|
||||
sbe->spref->sp = sp;
|
||||
sbe->level = level;
|
||||
selist_push(&sb->spells, sbe);
|
||||
}
|
||||
|
@ -95,6 +113,7 @@ void spellbook_clear(spellbook *sb)
|
|||
assert(sb);
|
||||
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
spellref_free(sbe->spref);
|
||||
free(sbe);
|
||||
}
|
||||
selist_free(sb->spells);
|
||||
|
@ -124,11 +143,10 @@ spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp)
|
|||
|
||||
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
if (sp == sbe->sp) {
|
||||
if (sp == spellref_get(sbe->spref)) {
|
||||
return sbe;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
struct selist;
|
||||
|
||||
typedef struct spellbook_entry {
|
||||
struct spell * sp;
|
||||
struct spellref * spref;
|
||||
int level;
|
||||
} spellbook_entry;
|
||||
|
||||
|
@ -44,7 +44,8 @@ extern "C" {
|
|||
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 spellbook_add(spellbook *sbp, struct spell * sp, int level);
|
||||
void spellbook_add(spellbook *sbp, struct spellref *spref, int level);
|
||||
void spellbook_add_spell(spellbook *sb, struct spell *sp, int level);
|
||||
int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data);
|
||||
void spellbook_clear(spellbook *sb);
|
||||
spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp);
|
||||
|
|
|
@ -2076,9 +2076,9 @@ void register_xmlreader(void)
|
|||
xml_register_callback(parse_buildings); /* requires resources */
|
||||
xml_register_callback(parse_ships); /* requires terrains */
|
||||
xml_register_callback(parse_races); /* requires spells */
|
||||
xml_register_callback(parse_spells); /* requires resources */
|
||||
xml_register_callback(parse_spellbooks); /* requires spells */
|
||||
xml_register_callback(parse_equipment); /* requires spells */
|
||||
xml_register_callback(parse_spells); /* requires resources */
|
||||
xml_register_callback(parse_calendar);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3458,8 +3458,8 @@ static void copy_spells(const spellbook * src, spellbook * dst, int maxlevel)
|
|||
for (qi = 0, ql = src->spells; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
if (sbe->level <= maxlevel) {
|
||||
if (!spellbook_get(dst, sbe->sp)) {
|
||||
spellbook_add(dst, sbe->sp, sbe->level);
|
||||
if (!spellbook_get(dst, spellref_get(sbe->spref))) {
|
||||
spellbook_add(dst, sbe->spref, sbe->level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
28
src/magic.c
28
src/magic.c
|
@ -430,14 +430,14 @@ void show_new_spells(faction * f, int level, const spellbook *book)
|
|||
for (qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
if (sbe->level <= level) {
|
||||
|
||||
if (!already_seen(f, sbe->sp)) {
|
||||
spell *sp = spellref_get(sbe->spref);
|
||||
if (!already_seen(f, sp)) {
|
||||
attrib * a = a_new(&at_reportspell);
|
||||
spellbook_entry * entry = (spellbook_entry *)a->data.v;
|
||||
entry->level = sbe->level;
|
||||
entry->sp = sbe->sp;
|
||||
entry->spref = spellref_copy(sbe->spref);
|
||||
a_add(&f->attribs, a);
|
||||
a_add(&f->attribs, a_new(&at_seenspell))->data.v = sbe->sp;
|
||||
a_add(&f->attribs, a_new(&at_seenspell))->data.v = sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,13 +481,16 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
|
|||
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;
|
||||
else {
|
||||
spell *sp = spellref_get(sbe->spref);
|
||||
if (f->spellbook && spellbook_get(f->spellbook, sp)) {
|
||||
// already have this spell, remove it from the list of candidates
|
||||
commonspells[spellno] = commonspells[--numspells];
|
||||
if (maxspell > numspells) {
|
||||
maxspell = numspells;
|
||||
}
|
||||
sbe = 0;
|
||||
}
|
||||
sbe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,7 +498,7 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
|
|||
if (!f->spellbook) {
|
||||
f->spellbook = create_spellbook(0);
|
||||
}
|
||||
spellbook_add(f->spellbook, sbe->sp, sbe->level);
|
||||
spellbook_add(f->spellbook, sbe->spref, sbe->level);
|
||||
commonspells[spellno] = commonspells[--numspells];
|
||||
}
|
||||
}
|
||||
|
@ -2948,6 +2951,7 @@ const char *spell_info(const spell * sp, const struct locale *lang)
|
|||
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)
|
||||
{
|
||||
return LOC(lang, mkname("spell", sp->sname));
|
||||
|
@ -2967,7 +2971,7 @@ static void select_spellbook(void **tokens, spellbook *sb, const struct locale *
|
|||
|
||||
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
|
||||
spell *sp = sbe->sp;
|
||||
spell *sp = spellref_get(sbe->spref);
|
||||
|
||||
const char *n = spell_name(sp, lang);
|
||||
if (!n) {
|
||||
|
|
|
@ -234,7 +234,7 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
|
|||
} 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) {
|
||||
size_t bytes = 0;
|
||||
if (cont) {
|
||||
|
@ -255,7 +255,7 @@ void nr_spell_syntax(struct stream *out, spellbook_entry * sbe, const struct loc
|
|||
char buf[4096];
|
||||
char *bufp = buf;
|
||||
size_t size = sizeof(buf) - 1;
|
||||
spell * sp = sbe->sp;
|
||||
const spell * sp = spellref_get(sbe->spref);
|
||||
const char *params = sp->parameter;
|
||||
|
||||
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 *startp, *bufp = buf;
|
||||
size_t size = sizeof(buf) - 1;
|
||||
spell * sp = sbe->sp;
|
||||
const spell * sp = spellref_get(sbe->spref);
|
||||
|
||||
newline(out);
|
||||
centre(out, spell_name(sp, lang), true);
|
||||
|
|
|
@ -680,7 +680,8 @@ size_t size)
|
|||
if (wrptr(&bufp, &size, result) != 0) {
|
||||
WARN_STATIC_BUFFER();
|
||||
}
|
||||
bufp = STRLCPY(bufp, spell_name(sbe->sp, f->locale), size);
|
||||
// TODO: no need to deref the spellref here (spref->name is good)
|
||||
bufp = STRLCPY(bufp, spell_name(spellref_get(sbe->spref), f->locale), size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue