diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index 785c3edba..2ae12e250 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -630,6 +630,20 @@ fwriteorder(FILE * F, const struct order * ord, const struct locale * lang) fputc('"', F); } +static void cr_output_spells(FILE * F, spell_list * slist, const faction * f, int maxlevel) +{ + if (slist) { + fprintf(F, "SPRUECHE\n"); + for (;slist; slist = slist->next) { + spell * sp = slist->data; + if (sp->level <= maxlevel) { + const char * name = add_translation(mkname("spell", sp->sname), spell_name(sp, f->locale)); + fprintf(F, "\"%s\"\n", name); + } + } + } +} + /* prints all that belongs to a unit */ static void cr_output_unit(FILE * F, const region * r, @@ -845,26 +859,18 @@ cr_output_unit(FILE * F, const region * r, /* spells */ if (is_mage(u)) { sc_mage * mage = get_mage(u); - spell_list * slist = mage->spells; - if (slist) { - int i; - int t = effskill(u, SK_MAGIC); - fprintf(F, "SPRUECHE\n"); - for (;slist; slist = slist->next) { - spell * sp = slist->data; - if (sp->level <= t) { - const char * name = add_translation(mkname("spell", sp->sname), spell_name(sp, f->locale)); - fprintf(F, "\"%s\"\n", name); - } - } - for (i=0;i!=MAXCOMBATSPELLS;++i) { - const spell * sp = mage->combatspells[i].sp; - if (sp) { - const char * name = add_translation(mkname("spell", sp->sname), spell_name(sp, f->locale)); - fprintf(F, "KAMPFZAUBER %d\n", i); - fprintf(F, "\"%s\";name\n", name); - fprintf(F, "%d;level\n", mage->combatspells[i].level); - } + spell_list ** slistp = get_spelllist(mage, u->faction); + int i, maxlevel = effskill(u, SK_MAGIC); + + cr_output_spells(F, *slistp, f, maxlevel); + + for (i=0;i!=MAXCOMBATSPELLS;++i) { + const spell * sp = mage->combatspells[i].sp; + if (sp) { + const char * name = add_translation(mkname("spell", sp->sname), spell_name(sp, f->locale)); + fprintf(F, "KAMPFZAUBER %d\n", i); + fprintf(F, "\"%s\";name\n", name); + fprintf(F, "%d;level\n", mage->combatspells[i].level); } } } diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index b6f04f57c..42c42103e 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -2229,7 +2229,7 @@ reshow(unit * u, struct order * ord, const char * s, param_t p) } /* try for a spell */ sp = get_spellfromtoken(u, s, u->faction->locale); - if (sp!=NULL && has_spell(u, sp)) { + if (sp!=NULL && u_hasspell(u, sp)) { attrib *a = a_find(u->faction->attribs, &at_seenspell); while (a!=NULL && a->type==&at_seenspell && a->data.v!=sp) a = a->next; if (a!=NULL) a_remove(&u->faction->attribs, a); diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c index aaed7b6ee..bd43f9f1b 100644 --- a/src/common/gamecode/study.c +++ b/src/common/gamecode/study.c @@ -587,7 +587,7 @@ learn_cmd(unit * u, order * ord) if (!is_mage(u)) create_mage(u, mtyp); } else { /* ist schon ein Magier und kein Vertrauter */ - if(u->faction->magiegebiet == 0){ + if (u->faction->magiegebiet == 0) { /* die Partei hat noch kein Magiegebiet gewählt. */ mtyp = getmagicskill(u->faction->locale); if (mtyp == M_NONE){ @@ -737,5 +737,17 @@ learn_cmd(unit * u, order * ord) } } } + else if (sk==SK_MAGIC) { + sc_mage * mage = get_mage(u); + int level = eff_skill(u, SK_MAGIC, r); + if (FactionSpells() && level>u->faction->max_spelllevel) { + update_spellbook(u->faction, level); + } + if (!mage) { + mage = create_mage(u, u->faction->magiegebiet); + } + updatespelllist(u); + } + return 0; } diff --git a/src/common/kernel/equipment.c b/src/common/kernel/equipment.c index d6650cb41..ca5edca83 100644 --- a/src/common/kernel/equipment.c +++ b/src/common/kernel/equipment.c @@ -141,7 +141,7 @@ equip_unit(struct unit * u, const struct equipment * eq) assert(!"trying to equip spells on a non-mage!"); } else { while (sp) { - add_spell(m, sp->data); + add_spell(get_spelllist(m, u->faction), sp->data); sp = sp->next; } } diff --git a/src/common/kernel/faction.c b/src/common/kernel/faction.c index 7a08a36d8..bc0171b99 100644 --- a/src/common/kernel/faction.c +++ b/src/common/kernel/faction.c @@ -264,6 +264,8 @@ destroyfaction(faction * f) if (!f->alive) return; + freelist(f->spellbook); + while (f->battles) { struct bmsg * bm = f->battles; f->battles = bm->next; diff --git a/src/common/kernel/faction.h b/src/common/kernel/faction.h index bbbf4ed18..eb5150c3f 100644 --- a/src/common/kernel/faction.h +++ b/src/common/kernel/faction.h @@ -65,6 +65,8 @@ typedef struct faction { char *email; char *passw; char *override; + int max_spelllevel; + struct spell_list * spellbook; const struct locale * locale; int lastorders; /* enno: short? */ int age; /* enno: short? */ diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index 15c410af9..e04d53847 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -201,6 +201,36 @@ free_mage(attrib * a) free(mage); } +int FactionSpells(void) +{ + static int rules_factionspells = -1; + if (rules_factionspells<0) { + rules_factionspells = get_param_int(global.parameters, "rules.magic.factionlist", 0); + } + return rules_factionspells; +} + +void read_spellist(struct spell_list ** slistp, struct storage * store) +{ + for (;;) { + spell * sp; + char spname[64]; + + if (store->versionr_int(store); + if (i < 0) break; + sp = find_spellbyid(M_GRAU, (spellid_t)i); + } else { + store->r_tok_buf(store, spname, sizeof(spname)); + if (strcmp(spname, "end")==0) break; + sp = find_spell(M_GRAU, spname); + } + if (sp!=NULL) { + add_spell(slistp, sp); + } + } +} + static int read_mage(attrib * a, struct storage * store) { @@ -241,35 +271,26 @@ read_mage(attrib * a, struct storage * store) } } } - - for (;;) { - spell * sp; - - if (store->versionr_int(store); - if (i < 0) break; - sp = find_spellbyid(mage->magietyp, (spellid_t)i); - } else { - store->r_tok_buf(store, spname, sizeof(spname)); - if (strcmp(spname, "end")==0) break; - sp = find_spell(mage->magietyp, spname); - } - if (sp==NULL) { - /* flag upstream to show that updatespellist() is necessary (hackish) */ - mage->spellcount = -1; - continue; - } - add_spell(mage, sp); - } + read_spellist(&mage->spells, store); return AT_READ_OK; } +void write_spelllist(const spell_list * slist, struct storage * store) +{ + while (slist!=NULL) { + spell * sp = slist->data; + store->w_tok(store, sp->sname); + slist = slist->next; + } + store->w_tok(store, "end"); +} + static void write_mage(const attrib * a, struct storage * store) { int i; sc_mage *mage = (sc_mage*)a->data.v; - spell_list *slist = mage->spells; + store->w_int(store, mage->magietyp); store->w_int(store, mage->spellpoints); store->w_int(store, mage->spchange); @@ -277,12 +298,7 @@ write_mage(const attrib * a, struct storage * store) store->w_tok(store, mage->combatspells[i].sp?mage->combatspells[i].sp->sname:"none"); store->w_int(store, mage->combatspells[i].level); } - while (slist!=NULL) { - spell * sp = slist->data; - store->w_tok(store, sp->sname); - slist = slist->next; - } - store->w_tok(store, "end"); + write_spelllist(mage->spells, store); } attrib_type at_mage = { @@ -325,59 +341,13 @@ find_magetype(const unit * u) return m->magietyp; } -/* ------------------------------------------------------------- */ -/* ein 'neuer' Magier bekommt von Anfang an alle Sprüche seines -* Magiegebietes mit einer Stufe kleiner oder gleich seinem Magietalent -* in seine List-of-known-spells. Ausgenommen mtyp 0 (M_GRAU) */ - -static void -createspelllist(unit *u, magic_t mtyp) -{ - spell_list * slist; - int sk; - - if (mtyp == M_GRAU) return; - - sk = effskill(u, SK_MAGIC); - if (sk == 0) return; - - for (slist=spells;slist!=NULL;slist=slist->next) { - spell * sp = slist->data; - if (sp->magietyp == mtyp && sp->level <= sk) { - if (!has_spell(u, sp)) { - add_spell(get_mage(u), sp); - } - } - } -} - -/* ------------------------------------------------------------- */ -/* Erzeugen eines neuen Magiers */ -sc_mage * -create_mage(unit * u, magic_t mtyp) -{ - sc_mage *mage; - attrib *a; - - a = a_find(u->attribs, &at_mage); - if (a!=NULL) { - a_remove(&u->attribs, a); - } - a = a_add(&u->attribs, a_new(&at_mage)); - mage = a->data.v; - - mage->magietyp = mtyp; - createspelllist(u, mtyp); - return mage; -} - /* ------------------------------------------------------------- */ /* Ausgabe der Spruchbeschreibungen - * Anzeige des Spruchs nur, wenn die Stufe des besten Magiers vorher - * kleiner war (u->faction->seenspells). Ansonsten muss nur geprüft - * werden, ob dieser Magier den Spruch schon kennt, und andernfalls der - * Spruch zu seiner List-of-known-spells hinzugefügt werden. - */ +* Anzeige des Spruchs nur, wenn die Stufe des besten Magiers vorher +* kleiner war (u->faction->seenspells). Ansonsten muss nur geprüft +* werden, ob dieser Magier den Spruch schon kennt, und andernfalls der +* Spruch zu seiner List-of-known-spells hinzugefügt werden. +*/ static int @@ -427,24 +397,65 @@ already_seen(const faction * f, const spell * sp) return false; } -void -updatespelllist(unit * u) -{ - int sk = eff_skill(u, SK_MAGIC, u->region); - spell_list * slist; - spell * sp; - struct sc_mage * mage = get_mage(u); - magic_t gebiet = find_magetype(u); - boolean ismonster = is_monsters(u->faction); +#define GRAYSPELLS 2 /* number of new gray spells per level */ +#define MAXSPELLS 256 - /* Nur Wyrm-Magier bekommen den Wyrmtransformationszauber */ - sp = find_spellbyid(M_GRAU, SPL_BECOMEWYRM); +/** update the spellbook with a new level +* Written for Eressea 1.1 +*/ +void +update_spellbook(faction * f, int level) +{ + spell * grayspells[MAXSPELLS]; + int numspells = 0; + spell_list * slist; + + for (slist=spells;slist!=NULL;slist=slist->next) { + spell * sp = slist->data; + if (sp->magietyp == M_GRAU && levelmax_spelllevel && sp->level<=level) { + grayspells[numspells++] = sp; + } else { + if (sp->magietyp == f->magiegebiet && sp->level <= level) { + if (!has_spell(f->spellbook, sp)) { + add_spell(&f->spellbook, sp); + } + } + } + } + while (numspells>0 && level>f->max_spelllevel) { + int i; + for (i=0;i!=GRAYSPELLS;++i) { + int maxspell = numspells; + int spellno = -1; + spell * sp; + do { + if (spellno==maxspell) { + --maxspell; + } + spellno = rng_int() % maxspell; + sp = grayspells[spellno]; + } + while (maxspell>0 && sp && sp->level<=f->max_spelllevel); + + if (sp) { + add_spell(&f->spellbook, sp); + grayspells[spellno] = 0; + } + } + ++f->max_spelllevel; + } +} #if KARMA_MODULE +void wyrm_update(unit * u, struct sc_mage * mage, int sk) +{ + spell_list * slist, ** slistp; + /* Nur Wyrm-Magier bekommen den Wyrmtransformationszauber */ + spell * sp = find_spellbyid(M_GRAU, SPL_BECOMEWYRM); + if (fspecial(u->faction, FS_WYRM) && !has_spell(u, sp) && sp->level<=sk) { add_spell(mage, find_spellbyid(M_GRAU, SPL_BECOMEWYRM)); } -#endif /* KARMA_MODULE */ /* Transformierte Wyrm-Magier bekommen Drachenodem */ if (dragonrace(u->race)) { @@ -453,36 +464,55 @@ updatespelllist(unit * u) /* keine breaks! Wyrme sollen alle drei Zauber können.*/ case RC_WYRM: sp = find_spellbyid(M_GRAU, SPL_WYRMODEM); - if (sp!=NULL && !has_spell(u, sp) && sp->level<=sk) { - add_spell(mage, sp); + slistp = get_spelllist(mage, u->faction); + if (sp!=NULL && !has_spell(*slistp, sp) && sp->level<=sk) { + add_spell(slistp, sp); } case RC_DRAGON: sp = find_spellbyid(M_GRAU, SPL_DRAGONODEM); - if (sp!=NULL && !has_spell(u, sp) && sp->level<=sk) { - add_spell(mage, sp); + slistp = get_spelllist(mage, u->faction); + if (sp!=NULL && !has_spell(*slistp, sp) && sp->level<=sk) { + add_spell(slistp, sp); } case RC_FIREDRAGON: sp = find_spellbyid(M_GRAU, SPL_FIREDRAGONODEM); - if (sp!=NULL && !has_spell(u, sp) && sp->level<=sk) { - add_spell(mage, sp); + slistp = get_spelllist(mage, u->faction); + if (sp!=NULL && !has_spell(*slistp, sp) && sp->level<=sk) { + add_spell(slistp, sp); } break; } } + return slistp; +} +#endif + +void +updatespelllist(unit * u) +{ + int sk = eff_skill(u, SK_MAGIC, u->region); + spell_list * slist = spells; + struct sc_mage * mage = get_mage(u); + magic_t gebiet = find_magetype(u); + boolean ismonster = is_monsters(u->faction); /* Magier mit keinem bzw M_GRAU bekommen weder Sprüche angezeigt noch * neue Sprüche in ihre List-of-known-spells. Das sind zb alle alten * Drachen, die noch den Skill Magie haben */ - for (slist=spells;slist!=NULL;slist=slist->next) { + if (FactionSpells()) { + spells = u->faction->spellbook; + } + + for (;slist!=NULL;slist=slist->next) { spell * sp = slist->data; if (sp->level<=sk) { - boolean know = has_spell(u, sp); + boolean know = u_hasspell(u, sp); if (know || (gebiet!=M_GRAU && sp->magietyp == gebiet)) { faction * f = u->faction; - if (!know) add_spell(mage, sp); + if (!know) add_spell(get_spelllist(mage, u->faction), sp); if (!ismonster && !already_seen(u->faction, sp)) { a_add(&f->attribs, a_new(&at_reportspell))->data.v = sp; a_add(&f->attribs, a_new(&at_seenspell))->data.v = sp; @@ -490,18 +520,41 @@ updatespelllist(unit * u) } } } + +#if KARMA_MODULE + wyrm_update(u, mage, sk); +#endif /* KARMA_MODULE */ +} + +/* ------------------------------------------------------------- */ +/* Erzeugen eines neuen Magiers */ +sc_mage * +create_mage(unit * u, magic_t mtyp) +{ + sc_mage *mage; + attrib *a; + + a = a_find(u->attribs, &at_mage); + if (a!=NULL) { + a_remove(&u->attribs, a); + } + a = a_add(&u->attribs, a_new(&at_mage)); + mage = a->data.v; + + mage->magietyp = mtyp; + return mage; } /* ------------------------------------------------------------- */ /* Funktionen für die Bearbeitung der List-of-known-spells */ void -add_spell(sc_mage* m, spell * sp) +add_spell(spell_list ** slistp, spell * sp) { - if (m==NULL) { + if (slistp==NULL) { log_error(("add_spell: unit is not a mage.\n")); } else { - spell_list ** slist = spelllist_find(&m->spells, sp); + spell_list ** slist = spelllist_find(slistp, sp); if (*slist) { spell * psp = (*slist)->data; if (psp==sp) { @@ -514,16 +567,23 @@ add_spell(sc_mage* m, spell * sp) } boolean -has_spell(const unit *u, const spell * sp) +has_spell(spell_list * slist, const spell * sp) { - sc_mage * m = get_mage(u); - if (m!=NULL) { - spell_list * sfind = *spelllist_find(&m->spells, sp); + if (slist!=NULL) { + spell_list * sfind = *spelllist_find(&slist, sp); return sfind!=NULL && sfind->data==sp; } return false; } +boolean +u_hasspell(const struct unit *u, const struct spell * sp) +{ + sc_mage * mage = get_mage(u); + if (mage) return has_spell(mage->spells, sp); + return false; +} + /* ------------------------------------------------------------- */ /* Eingestellte Kampfzauberstufe ermitteln */ @@ -572,7 +632,7 @@ set_combatspell(unit *u, spell *sp, struct order * ord, int level) cmistake(u, ord, 173, MSG_MAGIC); return; } - if (!has_spell(u, sp)) { + if (!u_hasspell(u, sp)) { /* Diesen Zauber kennt die Einheit nicht */ cmistake(u, ord, 169, MSG_MAGIC); return; @@ -917,7 +977,7 @@ knowsspell(const region * r, const unit * u, const spell * sp) return false; } /* steht der Spruch in der Spruchliste? */ - if (!has_spell(u, sp)) { + if (!u_hasspell(u, sp)) { /* ist der Spruch aus einem anderen Magiegebiet? */ if (find_magetype(u) != sp->magietyp) { return false; @@ -1439,52 +1499,52 @@ regeneration(unit * u) void regeneration_magiepunkte(void) { - region *r; - unit *u; - int aura, auramax; - double reg_aura; - int n; + region *r; + unit *u; + int aura, auramax; + double reg_aura; + int n; - for (r = regions; r; r = r->next) { - for (u = r->units; u; u = u->next) { - if (u->number && is_mage(u)) { - aura = get_spellpoints(u); - auramax = max_spellpoints(r, u); - if (aura < auramax) { - struct building * b = inside_building(u); - const struct building_type * btype = b?b->type:NULL; - reg_aura = (double)regeneration(u); + for (r = regions; r; r = r->next) { + for (u = r->units; u; u = u->next) { + if (u->number && is_mage(u)) { + aura = get_spellpoints(u); + auramax = max_spellpoints(r, u); + if (aura < auramax) { + struct building * b = inside_building(u); + const struct building_type * btype = b?b->type:NULL; + reg_aura = (double)regeneration(u); - /* Magierturm erhöht die Regeneration um 75% */ - /* Steinkreis erhöht die Regeneration um 50% */ - if (btype) reg_aura *= btype->auraregen; + /* Magierturm erhöht die Regeneration um 75% */ + /* Steinkreis erhöht die Regeneration um 50% */ + if (btype) reg_aura *= btype->auraregen; - /* Bonus/Malus durch Zauber */ - n = get_curseeffect(u->attribs, C_AURA, 0); - if (n>0) { - reg_aura = (reg_aura*n)/100; - } + /* Bonus/Malus durch Zauber */ + n = get_curseeffect(u->attribs, C_AURA, 0); + if (n>0) { + reg_aura = (reg_aura*n)/100; + } - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine)*/ + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine)*/ - /* maximal Differenz bis Maximale-Aura regenerieren - * mindestens 1 Aura pro Monat */ - reg_aura = MAX(1,reg_aura); - reg_aura = MIN((auramax - aura), reg_aura); + /* maximal Differenz bis Maximale-Aura regenerieren + * mindestens 1 Aura pro Monat */ + reg_aura = MAX(1,reg_aura); + reg_aura = MIN((auramax - aura), reg_aura); - aura += (int)reg_aura; - ADDMSG(&u->faction->msgs, msg_message( - "regenaura", "unit region amount", - u, r, (int)reg_aura)); - } - set_spellpoints(u, MIN(aura, auramax)); + aura += (int)reg_aura; + ADDMSG(&u->faction->msgs, msg_message( + "regenaura", "unit region amount", + u, r, (int)reg_aura)); + } + set_spellpoints(u, MIN(aura, auramax)); - /* Zum letzten Mal Spruchliste aktualisieren */ - updatespelllist(u); - } - } - } + /* Zum letzten Mal Spruchliste aktualisieren */ + /*updatespelllist(u);*/ + } + } + } } static boolean @@ -2871,3 +2931,11 @@ spelllist_find(spell_list ** lspells, const spell * sp) } return lspells; } + +extern struct spell_list ** get_spelllist(struct sc_mage * mage, struct faction * f) +{ + if (mage) { + return &mage->spells; + } + return NULL; +} diff --git a/src/common/kernel/magic.h b/src/common/kernel/magic.h index 53cec18a4..41d25ec5a 100644 --- a/src/common/kernel/magic.h +++ b/src/common/kernel/magic.h @@ -279,10 +279,13 @@ void set_combatspell(struct unit *u, spell *sp, struct order * ord, int level); /* setzt Kampfzauber */ void unset_combatspell(struct unit *u, spell *sp); /* löscht Kampfzauber */ -void add_spell(struct sc_mage *mage, spell *sp); +void add_spell(spell_list ** slistp, spell *sp); /* fügt den Spruch mit der Id spellid der Spruchliste der Einheit hinzu. */ -boolean has_spell(const struct unit *u, const struct spell * sp); +boolean has_spell(struct spell_list *slist, const struct spell * sp); /* prüft, ob der Spruch in der Spruchliste der Einheit steht. */ +boolean u_hasspell(const struct unit * u, const struct spell * sp); + /* prüft, ob der Spruch in der Spruchliste der Einheit steht. */ +void update_spellbook(struct faction * f, int level); void updatespelllist(struct unit *u); /* fügt alle Zauber des Magiegebietes der Einheit, deren Stufe kleiner * als das aktuelle Magietalent ist, in die Spruchliste der Einheit @@ -376,7 +379,11 @@ extern const char * spell_name(const struct spell * sp, const struct locale * la extern const char * curse_name(const struct curse_type * ctype, const struct locale * lang); extern struct message * msg_unitnotfound(const struct unit * mage, struct order * ord, const struct spllprm * spobj); +extern int FactionSpells(); +extern struct spell_list ** get_spelllist(struct sc_mage * mage, struct faction * f); +extern void write_spelllist(const struct spell_list * slist, struct storage * store); +extern void read_spellist(struct spell_list ** slistp, struct storage * store); #ifdef __cplusplus } #endif diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 875e9d583..8b59d9d27 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -1249,6 +1249,7 @@ readfaction(struct storage * store) } } read_groups(store, f); + read_spellist(&f->spellbook, store); return f; } @@ -1312,6 +1313,7 @@ writefaction(struct storage * store, const faction * f) store->w_id(store, 0); store->w_brk(store); write_groups(store, f->groups); + write_spelllist(f->spellbook, store); } int diff --git a/src/eressea/lua/unit.cpp b/src/eressea/lua/unit.cpp index 500263e5b..337787d0a 100644 --- a/src/eressea/lua/unit.cpp +++ b/src/eressea/lua/unit.cpp @@ -258,7 +258,7 @@ unit_addspell(unit * u, const char * name) if (strcmp(name, sp->sname)==0) { struct sc_mage * mage = get_mage(u); if (add) log_error(("two spells are called %s.\n", name)); - add_spell(mage, sp); + add_spell(get_spelllist(mage, u->faction), sp); add = true; } slist=slist->next; diff --git a/src/eressea/tolua/bind_faction.c b/src/eressea/tolua/bind_faction.c index c9abcc189..aaa8647eb 100644 --- a/src/eressea/tolua/bind_faction.c +++ b/src/eressea/tolua/bind_faction.c @@ -391,6 +391,24 @@ tolua_faction_tostring(lua_State *tolua_S) return 1; } +static int tolua_faction_get_spells(lua_State* tolua_S) +{ + faction* self = (faction*)tolua_tousertype(tolua_S, 1, 0); + spell_list * slist = self->spellbook; + if (slist) { + spell_list ** spell_ptr = (spell_list **)lua_newuserdata(tolua_S, sizeof(spell_list *)); + luaL_getmetatable(tolua_S, "spell_list"); + lua_setmetatable(tolua_S, -2); + + *spell_ptr = slist; + lua_pushcclosure(tolua_S, tolua_spelllist_next, 1); + return 1; + } + + lua_pushnil(tolua_S); + return 1; +} + void tolua_faction_open(lua_State* tolua_S) { @@ -410,6 +428,7 @@ tolua_faction_open(lua_State* tolua_S) tolua_variable(tolua_S, "info", tolua_faction_get_info, tolua_faction_set_info); tolua_variable(tolua_S, "units", tolua_faction_get_units, NULL); tolua_variable(tolua_S, "heroes", tolua_faction_get_heroes, NULL); + tolua_variable(tolua_S, "spells", tolua_faction_get_spells, 0); tolua_variable(tolua_S, "maxheroes", tolua_faction_get_maxheroes, NULL); tolua_variable(tolua_S, "password", tolua_faction_get_password, tolua_faction_set_password); tolua_variable(tolua_S, "email", tolua_faction_get_email, tolua_faction_set_email); diff --git a/src/eressea/tolua/bind_unit.c b/src/eressea/tolua/bind_unit.c index ae115cb94..0428f5b59 100644 --- a/src/eressea/tolua/bind_unit.c +++ b/src/eressea/tolua/bind_unit.c @@ -489,12 +489,13 @@ unit_addspell(unit * u, const char * name) { int add = 0; spell_list * slist = spells; + spell_list ** starget = NULL; while (slist!=NULL) { spell * sp = slist->data; if (strcmp(name, sp->sname)==0) { - struct sc_mage * mage = get_mage(u); + starget = get_spelllist(get_mage(u), u->faction); if (add) log_error(("two spells are called %s.\n", name)); - add_spell(mage, sp); + add_spell(starget, sp); add = 1; } slist=slist->next; @@ -514,17 +515,16 @@ tolua_unit_addspell(lua_State* tolua_S) static void unit_removespell(unit * u, const spell * sp) { - sc_mage * mage = get_mage(u); - if (mage!=NULL) { - spell_list ** isptr = &mage->spells; - while (*isptr && (*isptr)->data != sp) { - isptr = &(*isptr)->next; - } - if (*isptr) { - spell_list * sptr = *isptr; - *isptr = sptr->next; - free(sptr); - } + spell_list ** isptr; + isptr = get_spelllist(get_mage(u), u->faction); + + while (*isptr && (*isptr)->data != sp) { + isptr = &(*isptr)->next; + } + if (*isptr) { + spell_list * sptr = *isptr; + *isptr = sptr->next; + free(sptr); } } @@ -719,18 +719,23 @@ static int tolua_unit_get_items(lua_State* tolua_S) static int tolua_unit_get_spells(lua_State* tolua_S) { unit* self = (unit*)tolua_tousertype(tolua_S, 1, 0); - sc_mage * mage; - spell_list ** spell_ptr = (spell_list **)lua_newuserdata(tolua_S, sizeof(spell_list *)); + sc_mage * mage = get_mage(self); - luaL_getmetatable(tolua_S, "spell_list"); - lua_setmetatable(tolua_S, -2); + if (mage) { + spell_list ** slist = get_spelllist(mage, self->faction); + assert(slist); + if (slist) { + spell_list ** spell_ptr = (spell_list **)lua_newuserdata(tolua_S, sizeof(spell_list *)); + luaL_getmetatable(tolua_S, "spell_list"); + lua_setmetatable(tolua_S, -2); - mage = get_mage(self); - - *spell_ptr = mage?mage->spells:0; - - lua_pushcclosure(tolua_S, tolua_spelllist_next, 1); + *spell_ptr = *slist; + lua_pushcclosure(tolua_S, tolua_spelllist_next, 1); + return 1; + } + } + lua_pushnil(tolua_S); return 1; } diff --git a/src/eressea/tolua/bindings.c b/src/eressea/tolua/bindings.c index c13813df0..550ab1718 100644 --- a/src/eressea/tolua/bindings.c +++ b/src/eressea/tolua/bindings.c @@ -48,6 +48,7 @@ without prior permission by the authors of Eressea. #include #include +#include #include #include #include @@ -775,6 +776,55 @@ tolua_write_spells(lua_State* tolua_S) return 0; } +static int +tolua_get_spell_text(lua_State *tolua_S) +{ + const struct locale * loc = find_locale("en"); + spell * self = (spell *)tolua_tousertype(tolua_S, 1, 0); + lua_pushstring(tolua_S, spell_info(self, loc)); + return 1; +} + +static int +tolua_get_spell_school(lua_State *tolua_S) +{ + spell * self = (spell *)tolua_tousertype(tolua_S, 1, 0); + lua_pushstring(tolua_S, magietypen[self->magietyp]); + return 1; +} + +static int +tolua_get_spell_level(lua_State *tolua_S) +{ + spell * self = (spell *)tolua_tousertype(tolua_S, 1, 0); + lua_pushnumber(tolua_S, self->level); + return 1; +} + +static int +tolua_get_spell_name(lua_State *tolua_S) +{ + spell * self = (spell *)tolua_tousertype(tolua_S, 1, 0); + lua_pushstring(tolua_S, self->sname); + return 1; +} + +static int tolua_get_spells(lua_State* tolua_S) +{ + spell_list * slist = spells; + if (slist) { + spell_list ** spell_ptr = (spell_list **)lua_newuserdata(tolua_S, sizeof(spell_list *)); + luaL_getmetatable(tolua_S, "spell_list"); + lua_setmetatable(tolua_S, -2); + + *spell_ptr = slist; + lua_pushcclosure(tolua_S, tolua_spelllist_next, 1); + return 1; + } + + lua_pushnil(tolua_S); + return 1; +} int tolua_eressea_open(lua_State* tolua_S) { @@ -801,6 +851,17 @@ tolua_eressea_open(lua_State* tolua_S) } tolua_endmodule(tolua_S); + tolua_cclass(tolua_S, "spell", "spell", "", NULL); + tolua_beginmodule(tolua_S, "spell"); + { + tolua_function(tolua_S, "__tostring", tolua_get_spell_name); + tolua_variable(tolua_S, "name", tolua_get_spell_name, 0); + tolua_variable(tolua_S, "school", tolua_get_spell_school, 0); + tolua_variable(tolua_S, "level", tolua_get_spell_level, 0); + tolua_variable(tolua_S, "text", tolua_get_spell_text, 0); + } + tolua_endmodule(tolua_S); + tolua_function(tolua_S, "get_region_by_id", tolua_get_region_byid); tolua_function(tolua_S, "get_faction", tolua_get_faction); @@ -874,6 +935,7 @@ tolua_eressea_open(lua_State* tolua_S) tolua_function(tolua_S, "rng_int", tolua_rng_int); + tolua_function(tolua_S, "spells", tolua_get_spells); tolua_function(tolua_S, "write_spells", tolua_write_spells); } tolua_endmodule(tolua_S); diff --git a/src/res/e2k9.xml b/src/res/e2k9.xml index ff5a96223..feab6b43e 100644 --- a/src/res/e2k9.xml +++ b/src/res/e2k9.xml @@ -114,6 +114,7 @@ + @@ -124,6 +125,7 @@ + diff --git a/src/res/e2k9/races.xml b/src/res/e2k9/races.xml index 584aff7bf..aeb95f895 100644 --- a/src/res/e2k9/races.xml +++ b/src/res/e2k9/races.xml @@ -9,7 +9,6 @@ - @@ -30,7 +29,6 @@ - @@ -97,7 +95,6 @@ - @@ -120,7 +117,6 @@ - @@ -192,7 +188,6 @@ - @@ -221,7 +216,6 @@ - @@ -245,7 +239,6 @@ - @@ -269,7 +262,6 @@ - @@ -295,7 +287,6 @@ - @@ -321,7 +312,6 @@ - @@ -350,7 +340,6 @@ - @@ -376,7 +365,6 @@ - @@ -400,7 +388,6 @@ - @@ -427,7 +414,6 @@ - @@ -456,7 +442,6 @@ - @@ -482,7 +467,6 @@ - @@ -532,7 +516,6 @@ - @@ -562,7 +545,6 @@ - @@ -588,7 +570,6 @@ - @@ -613,7 +594,6 @@ - @@ -640,7 +620,6 @@ - @@ -681,7 +660,6 @@ - @@ -707,7 +685,6 @@ - @@ -846,7 +823,6 @@ - diff --git a/src/res/e2k9/spells.xml b/src/res/e2k9/spells.xml index 9e786157a..0451a1b2f 100644 --- a/src/res/e2k9/spells.xml +++ b/src/res/e2k9/spells.xml @@ -174,21 +174,6 @@ - - - - - - - - - - - - - - - diff --git a/src/scripts/tests.lua b/src/scripts/tests.lua index efa04b332..75fc278c1 100644 --- a/src/scripts/tests.lua +++ b/src/scripts/tests.lua @@ -1,45 +1,45 @@ local function test_rename() - free_game() - local r = region.create(0, 0, "plain") - local f = faction.create("enno@eressea.de", "human", "de") - local u = unit.create(f, r) - u:add_item("aoh", 1) - assert(u:get_item("ao_healing")==1) + free_game() + local r = region.create(0, 0, "plain") + local f = faction.create("enno@eressea.de", "human", "de") + local u = unit.create(f, r) + u:add_item("aoh", 1) + assert(u:get_item("ao_healing")==1) end local function test_pure() - free_game() - local r = region.create(0, 0, "plain") + free_game() + local r = region.create(0, 0, "plain") end local function test_read_write() - free_game() - local r = region.create(0, 0, "plain") - local f = faction.create("enno@eressea.de", "human", "de") - local u = unit.create(f, r) - u.number = 2 - local fno = f.id - local uno = u.id - local result = 0 - assert(r.terrain=="plain") - result = write_game("test_read_write.dat", "binary") - assert(result==0) - assert(get_region(0, 0)~=nil) - assert(get_faction(fno)~=nil) - assert(get_unit(uno)~=nil) - r = nil - f = nil - u = nil - free_game() - assert(get_region(0, 0)==nil) - assert(get_faction(fno)==nil) - assert(get_unit(uno)==nil) - result = read_game("test_read_write.dat", "binary") - assert(result==0) - assert(get_region(0, 0)~=nil) - assert(get_faction(fno)~=nil) - assert(get_unit(uno)~=nil) - free_game() + free_game() + local r = region.create(0, 0, "plain") + local f = faction.create("enno@eressea.de", "human", "de") + local u = unit.create(f, r) + u.number = 2 + local fno = f.id + local uno = u.id + local result = 0 + assert(r.terrain=="plain") + result = write_game("test_read_write.dat", "binary") + assert(result==0) + assert(get_region(0, 0)~=nil) + assert(get_faction(fno)~=nil) + assert(get_unit(uno)~=nil) + r = nil + f = nil + u = nil + free_game() + assert(get_region(0, 0)==nil) + assert(get_faction(fno)==nil) + assert(get_unit(uno)==nil) + result = read_game("test_read_write.dat", "binary") + assert(result==0) + assert(get_region(0, 0)~=nil) + assert(get_faction(fno)~=nil) + assert(get_unit(uno)~=nil) + free_game() end local function test_gmtool() @@ -245,6 +245,31 @@ local function test_recruit() -- assert(u:get_item("money")==10) end +local function test_spells() + free_game() + local r = region.create(0, 0, "plain") + local f = faction.create("enno@eressea.de", "human", "de") + local u = unit.create(f, r) + u.race = "elf" + u.number = 1 + u:clear_orders() + u:add_item("money", 10000) + u:set_skill("magic", 5) + u:add_order("LERNE MAGIE Tybied") + process_orders() + local sp + local nums = 0 + if f.spells~=nil then + for sp in f.spells do + nums = nums + 1 + end + end + for sp in u.spells do + nums = nums - 1 + end + assert(nums==0) +end + local function test_produce() free_game() local r = region.create(0, 0, "plain") @@ -327,10 +352,11 @@ tests = { ["events"] = test_events, ["produce"] = test_produce, ["rename"] = test_rename, - ["recruit"] = test_recruit + ["recruit"] = test_recruit, + ["spells"] = test_spells } mytests = { - ["alliance"] = test_alliance + ["spells"] = test_spells } fail = 0 for k, v in pairs(tests) do