From 998549e6879947c987a63421e16db0f590306881 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 26 May 2012 08:20:26 -0700 Subject: [PATCH] mages have spellbooks now --- src/bindings/bind_unit.c | 39 +++++++++-------- src/gamecode/laws.c | 9 ++-- src/kernel/equipment_test.c | 4 +- src/kernel/magic.c | 84 +++++++++++++++++-------------------- src/kernel/magic.h | 6 +-- src/kernel/magic_test.c | 30 +++++++++++++ src/kernel/skill.c | 18 ++++---- src/kernel/unit.c | 55 ++++++++++++------------ 8 files changed, 134 insertions(+), 111 deletions(-) diff --git a/src/bindings/bind_unit.c b/src/bindings/bind_unit.c index 79f2660e5..1b4547932 100644 --- a/src/bindings/bind_unit.c +++ b/src/bindings/bind_unit.c @@ -502,22 +502,6 @@ static int tolua_unit_addspell(lua_State * L) return 1; } -static void unit_removespell(unit * u, spell * sp) -{ - quicklist **isptr; - - isptr = get_spelllist(get_mage(u), u->faction); - ql_set_remove(isptr, sp); -} - -static int tolua_unit_removespell(lua_State * L) -{ - unit *self = (unit *) tolua_tousertype(L, 1, 0); - spell *sp = (spell *) tolua_tousertype(L, 2, 0); - unit_removespell(self, sp); - return 0; -} - static int tolua_unit_set_racename(lua_State * L) { unit *self = (unit *) tolua_tousertype(L, 1, 0); @@ -704,6 +688,7 @@ static int tolua_unit_get_items(lua_State * L) return 1; } +#ifdef TODO /* spellbooks */ static int tolua_unit_get_spells(lua_State * L) { unit *self = (unit *) tolua_tousertype(L, 1, 0); @@ -720,6 +705,24 @@ static int tolua_unit_get_spells(lua_State * L) return tolua_quicklist_push(L, "spell_list", "spell", slist); } +static void unit_removespell(unit * u, spell * sp) +{ + quicklist **isptr; + + isptr = get_spelllist(get_mage(u), u->faction); + ql_set_remove(isptr, sp); +} + +static int tolua_unit_removespell(lua_State * L) +{ + unit *self = (unit *) tolua_tousertype(L, 1, 0); + spell *sp = (spell *) tolua_tousertype(L, 2, 0); + unit_removespell(self, sp); + return 0; +} + +#endif + static int tolua_unit_get_orders(lua_State * L) { unit *self = (unit *) tolua_tousertype(L, 1, 0); @@ -953,7 +956,10 @@ void tolua_unit_open(lua_State * L) tolua_variable(L, TOLUA_CAST "race_name", &tolua_unit_get_racename, &tolua_unit_set_racename); tolua_function(L, TOLUA_CAST "add_spell", &tolua_unit_addspell); +#ifdef TODO /* spellbooks */ tolua_function(L, TOLUA_CAST "remove_spell", &tolua_unit_removespell); + tolua_variable(L, TOLUA_CAST "spells", &tolua_unit_get_spells, 0); +#endif tolua_function(L, TOLUA_CAST "cast_spell", &tolua_unit_castspell); tolua_variable(L, TOLUA_CAST "magic", &tolua_unit_get_magic, @@ -966,7 +972,6 @@ void tolua_unit_open(lua_State * L) tolua_unit_set_ship); tolua_variable(L, TOLUA_CAST "region", &tolua_unit_get_region, tolua_unit_set_region); - tolua_variable(L, TOLUA_CAST "spells", &tolua_unit_get_spells, 0); tolua_variable(L, TOLUA_CAST "number", &tolua_unit_get_number, tolua_unit_set_number); tolua_variable(L, TOLUA_CAST "race", &tolua_unit_get_race, diff --git a/src/gamecode/laws.c b/src/gamecode/laws.c index 6dd2af667..26cb72b36 100644 --- a/src/gamecode/laws.c +++ b/src/gamecode/laws.c @@ -3737,12 +3737,11 @@ static void update_spells(void) } show_new_spells(f, maxlevel, faction_get_spellbook(f)); for (i=0; i!=MAXMAGES && mages[i]; ++i) { - sc_mage *mage = get_mage(mages[i]); - if (mage && mage->spells) { -#ifdef TODO - int level = effskill(mages[i], SK_MAGIC); + unit * u = mages[i]; + sc_mage *mage = get_mage(u); + if (mage && mage->spellbook) { + int level = effskill(u, SK_MAGIC); show_new_spells(f, level, mage->spellbook); -#endif } } } diff --git a/src/kernel/equipment_test.c b/src/kernel/equipment_test.c index d376ee644..5a97502a5 100644 --- a/src/kernel/equipment_test.c +++ b/src/kernel/equipment_test.c @@ -44,8 +44,8 @@ void test_equipment(CuTest * tc) mage = get_mage(u); CuAssertPtrNotNull(tc, mage); - CuAssertPtrNotNull(tc, mage->spells); - CuAssertTrue(tc, u_hasspell(mage, sp)); + CuAssertPtrNotNull(tc, mage->spellbook); + CuAssertTrue(tc, u_hasspell(u, sp)); } CuSuite *get_equipment_suite(void) diff --git a/src/kernel/magic.c b/src/kernel/magic.c index 07d8cd9c0..7155d37de 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -33,6 +33,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "pool.h" #include "race.h" #include "region.h" +#include "save.h" #include "ship.h" #include "skill.h" #include "spell.h" @@ -200,7 +201,10 @@ static void init_mage(attrib * a) static void free_mage(attrib * a) { sc_mage *mage = (sc_mage *) a->data.v; - freelist(mage->spells); + if (mage->spellbook) { + spellbook_clear(mage->spellbook); + free(mage->spellbook); + } free(mage); } @@ -286,7 +290,7 @@ static int read_mage(attrib * a, void *owner, struct storage *store) } } } - read_spells(&mage->spells, mage->magietyp, store); + mage->spellbook = read_spellbook(store); return AT_READ_OK; } @@ -316,7 +320,7 @@ write_mage(const attrib * a, const void *owner, struct storage *store) mage->combatspells[i].sp ? mage->combatspells[i].sp->sname : "none"); store->w_int(store, mage->combatspells[i].level); } - write_spells(mage->spells, store); + write_spellbook(mage->spellbook, store); } attrib_type at_mage = { @@ -391,12 +395,6 @@ attrib_type at_seenspell = { #define MAXSPELLS 256 -static boolean has_spell(quicklist * ql, const spell * sp) -{ - int qi; - return ql_set_find(&ql, &qi, sp) != 0; -} - static boolean already_seen(const faction * f, const spell * sp) { attrib *a; @@ -521,9 +519,14 @@ void add_spellname(sc_mage * mage, const spell * sp) } } -int u_hasspell(const sc_mage *mage, const struct spell *sp) +int u_hasspell(const unit *u, const struct spell *sp) { - return mage ? has_spell(mage->spells, sp) : 0; + spellbook * book = unit_get_spellbook(u); + spellbook_entry * sbe = book ? spellbook_get(book, sp) : 0; + if (sbe) { + return sbe->level<=effskill(u, SK_MAGIC); + } + return 0; } /* ------------------------------------------------------------- */ @@ -572,7 +575,7 @@ void set_combatspell(unit * u, spell * sp, struct order *ord, int level) cmistake(u, ord, 173, MSG_MAGIC); return; } - if (!u_hasspell(mage, sp)) { + if (!u_hasspell(u, sp)) { /* Diesen Zauber kennt die Einheit nicht */ cmistake(u, ord, 169, MSG_MAGIC); return; @@ -911,19 +914,12 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) */ boolean knowsspell(const region * r, const unit * u, const spell * sp) { - sc_mage *mage; /* Ist überhaupt ein gültiger Spruch angegeben? */ if (!sp || sp->id == 0) { return false; } - /* Magier? */ - mage = get_mage(u); - if (!mage) { - log_warning("%s ist kein Magier, versucht aber zu zaubern.\n", unitname(u)); - return false; - } /* steht der Spruch in der Spruchliste? */ - return u_hasspell(mage, sp)!=0; + return u_hasspell(u, sp)!=0; } /* Um einen Spruch zu beherrschen, muss der Magier die Stufe des @@ -2876,8 +2872,7 @@ const char *curse_name(const curse_type * ctype, const struct locale *lang) return LOC(lang, mkname("spell", ctype->cname)); } -spell *unit_getspell(struct unit *u, const char *name, - const struct locale * lang) +spell *unit_getspell(struct unit *u, const char *name, const struct locale * lang) { sc_mage * mage = get_mage(u); if (mage) { @@ -2887,40 +2882,37 @@ spell *unit_getspell(struct unit *u, const char *name, if (names->lang==lang) break; } if (!names) { - quicklist *ql = mage->spells; - int qi; - names = (spell_names *)calloc(1, sizeof(spell_names)); - names->next = mage->spellnames; - names->lang = lang; - names->tokens = 0; - for (qi = 0, ql = mage->spells; ql; ql_advance(&ql, &qi, 1)) { - spell *sp = (spell *) ql_get(ql, qi); - const char *n = spell_name(sp, lang); - if (!n) { - log_error("no translation in locae %s for spell $s\n", locale_name(lang), sp->sname); - } else { - token.v = sp; - addtoken(&names->tokens, n, token); + spellbook *sb = unit_get_spellbook(u); + if (sb) { + quicklist * ql; + int qi; + names = (spell_names *)calloc(1, sizeof(spell_names)); + names->next = mage->spellnames; + names->lang = lang; + names->tokens = 0; + + for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); + spell *sp = sbe->sp; + const char *n = spell_name(sp, lang); + if (!n) { + log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname); + } else { + token.v = sp; + addtoken(&names->tokens, n, token); + } } + mage->spellnames = names; } - mage->spellnames = names; } - if (findtoken(names->tokens, name, &token) != E_TOK_NOMATCH) { + if (names && findtoken(names->tokens, name, &token) != E_TOK_NOMATCH) { return (spell *) token.v; } } return 0; } -struct quicklist **get_spelllist(struct sc_mage *mage, struct faction *f) -{ - if (mage) { - return &mage->spells; - } - return NULL; -} - static critbit_tree cb_spellbooks; spellbook * get_spellbook(const char * name) diff --git a/src/kernel/magic.h b/src/kernel/magic.h index da0b693db..0ac519711 100644 --- a/src/kernel/magic.h +++ b/src/kernel/magic.h @@ -117,7 +117,7 @@ typedef struct sc_mage { int spchange; int spellcount; combatspell combatspells[MAXCOMBATSPELLS]; - struct quicklist *spells; + struct spellbook *spellbook; struct spell_names * spellnames; } sc_mage; @@ -252,7 +252,7 @@ typedef struct sc_mage { /* löscht Kampfzauber */ void add_spellname(sc_mage * mage, const struct spell * sp); /* fügt den Spruch mit der Id spellid der Spruchliste der Einheit hinzu. */ - int u_hasspell(const sc_mage *mage, const struct spell *sp); + int u_hasspell(const struct unit *u, const struct spell *sp); /* prüft, ob der Spruch in der Spruchliste der Einheit steht. */ void pick_random_spells(struct faction *f, int level, struct spellbook * book, int num_spells); void show_new_spells(struct faction * f, int level, const struct spellbook *book); @@ -360,8 +360,6 @@ typedef struct sc_mage { extern struct message *msg_unitnotfound(const struct unit *mage, struct order *ord, const struct spllprm *spobj); extern int FactionSpells(void); - extern struct quicklist **get_spelllist(struct sc_mage *mage, - struct faction *f); extern void write_spells(struct quicklist *slist, struct storage *store); extern void read_spells(struct quicklist **slistp, magic_t mtype, diff --git a/src/kernel/magic_test.c b/src/kernel/magic_test.c index e908a3d59..42e05a94c 100644 --- a/src/kernel/magic_test.c +++ b/src/kernel/magic_test.c @@ -348,6 +348,35 @@ void test_set_post_combatspell(CuTest * tc) CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); } +void test_hasspell(CuTest * tc) +{ + spell *sp; + struct unit * u; + struct faction * f; + struct region * r; + + test_cleanup(); + test_create_world(); + r = findregion(0, 0); + f = test_create_faction(0); + f->magiegebiet = M_TYBIED; + u = test_create_unit(f, r); + skill_enabled[SK_MAGIC] = 1; + sp = create_spell("testspell", 0); + sp->sptyp |= POSTCOMBATSPELL; + + unit_add_spell(u, 0, sp, 2); + + set_level(u, SK_MAGIC, 1); + CuAssertTrue(tc, !u_hasspell(u, sp)); + + set_level(u, SK_MAGIC, 2); + CuAssertTrue(tc, u_hasspell(u, sp)); + + set_level(u, SK_MAGIC, 1); + CuAssertTrue(tc, !u_hasspell(u, sp)); +} + CuSuite *get_magic_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -361,5 +390,6 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_set_pre_combatspell); SUITE_ADD_TEST(suite, test_set_main_combatspell); SUITE_ADD_TEST(suite, test_set_post_combatspell); + SUITE_ADD_TEST(suite, test_hasspell); return suite; } diff --git a/src/kernel/skill.c b/src/kernel/skill.c index 238ac6378..c25954182 100644 --- a/src/kernel/skill.c +++ b/src/kernel/skill.c @@ -221,7 +221,7 @@ static struct skillmods *init_skills(const race * rc) int rc_skillmod(const struct race *rc, const region * r, skill_t sk) { - int mods; + int mods = 0; if (!skill_enabled[sk]) { return 0; @@ -237,19 +237,15 @@ int rc_skillmod(const struct race *rc, const region * r, skill_t sk) } mods = (*imods)->mod[rterrain(r)].value[sk]; #else - mods = skill_mod(rc, sk, r->terrain); + if (r) { + mods = skill_mod(rc, sk, r->terrain); + } #endif - if (rc == new_race[RC_ELF] && r_isforest(r)) { - if (sk == SK_PERCEPTION) { + if (rc == new_race[RC_ELF] && r && r_isforest(r)) { + if (sk == SK_PERCEPTION || sk == SK_STEALTH) { ++mods; - } else if (sk == SK_STEALTH) { - if (r_isforest(r)) { - ++mods; - } } else if (sk == SK_TACTICS) { - if (r_isforest(r)) { - mods += 2; - } + mods += 2; } } return mods; diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 532543553..1697daf2b 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -31,6 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "race.h" #include "region.h" #include "spell.h" +#include "spellbook.h" #include "save.h" #include "ship.h" #include "skill.h" @@ -1219,8 +1220,6 @@ static int item_modification(const unit * u, skill_t sk, int val) static int att_modification(const unit * u, skill_t sk) { - double bonus = 0, malus = 0; - attrib *a; double result = 0; static boolean init = false; static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct; @@ -1251,27 +1250,30 @@ static int att_modification(const unit * u, skill_t sk) /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der * jeweils erste vom Typ C_GBDREAM zurückgegen wird, wir aber alle * durchsuchen und aufaddieren müssen */ - a = a_find(u->region->attribs, &at_curse); - while (a && a->type == &at_curse) { - curse *c = (curse *) a->data.v; - if (curse_active(c) && c->type == gbdream_ct) { - double mod = curse_geteffect(c); - unit *mage = c->magician; - /* wir suchen jeweils den größten Bonus und den größten Malus */ - if (mod > bonus) { - if (mage == NULL || mage->number == 0 - || alliedunit(mage, u->faction, HELP_GUARD)) { - bonus = mod; - } - } else if (mod < malus) { - if (mage == NULL || !alliedunit(mage, u->faction, HELP_GUARD)) { - malus = mod; + if (u->region) { + double bonus = 0, malus = 0; + attrib *a = a_find(u->region->attribs, &at_curse); + while (a && a->type == &at_curse) { + curse *c = (curse *) a->data.v; + if (curse_active(c) && c->type == gbdream_ct) { + double mod = curse_geteffect(c); + unit *mage = c->magician; + /* wir suchen jeweils den größten Bonus und den größten Malus */ + if (mod > bonus) { + if (mage == NULL || mage->number == 0 + || alliedunit(mage, u->faction, HELP_GUARD)) { + bonus = mod; + } + } else if (mod < malus) { + if (mage == NULL || !alliedunit(mage, u->faction, HELP_GUARD)) { + malus = mod; + } } } + a = a->next; } - a = a->next; + result = result + bonus + malus; } - result = result + bonus + malus; return (int)result; } @@ -1283,11 +1285,11 @@ get_modifier(const unit * u, skill_t sk, int level, const region * r, int bskill = level; int skill = bskill; - assert(r); - if (sk == SK_STEALTH) { + if (r && sk == SK_STEALTH) { plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOSTEALTH)) + if (pl && fval(pl, PFL_NOSTEALTH)) { return 0; + } } skill += rc_skillmod(u->race, r, sk); @@ -1734,7 +1736,10 @@ void unit_add_spell(unit * u, sc_mage * m, struct spell * sp, int level) log_debug("adding new spell %s to a previously non-mage unit %s\n", sp->sname, unitname(u)); mage = create_mage(u, u->faction?u->faction->magiegebiet:M_GRAY); } - add_spell(&mage->spells, sp); + if (!mage->spellbook) { + mage->spellbook = create_spellbook(0); + } + spellbook_add(mage->spellbook, sp, level); add_spellname(mage, sp); } @@ -1742,10 +1747,8 @@ struct spellbook * unit_get_spellbook(const struct unit * u) { sc_mage * mage = get_mage(u); if (mage) { - if (mage->spells) { -#ifdef TODO + if (mage->spellbook) { return mage->spellbook; -#endif } return faction_get_spellbook(u->faction); }