mages have spellbooks now

This commit is contained in:
Enno Rehling 2012-05-26 08:20:26 -07:00
parent 409328a9c2
commit 998549e687
8 changed files with 134 additions and 111 deletions

View file

@ -502,22 +502,6 @@ static int tolua_unit_addspell(lua_State * L)
return 1; 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) static int tolua_unit_set_racename(lua_State * L)
{ {
unit *self = (unit *) tolua_tousertype(L, 1, 0); unit *self = (unit *) tolua_tousertype(L, 1, 0);
@ -704,6 +688,7 @@ static int tolua_unit_get_items(lua_State * L)
return 1; return 1;
} }
#ifdef TODO /* spellbooks */
static int tolua_unit_get_spells(lua_State * L) static int tolua_unit_get_spells(lua_State * L)
{ {
unit *self = (unit *) tolua_tousertype(L, 1, 0); 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); 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) static int tolua_unit_get_orders(lua_State * L)
{ {
unit *self = (unit *) tolua_tousertype(L, 1, 0); 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_variable(L, TOLUA_CAST "race_name", &tolua_unit_get_racename,
&tolua_unit_set_racename); &tolua_unit_set_racename);
tolua_function(L, TOLUA_CAST "add_spell", &tolua_unit_addspell); tolua_function(L, TOLUA_CAST "add_spell", &tolua_unit_addspell);
#ifdef TODO /* spellbooks */
tolua_function(L, TOLUA_CAST "remove_spell", &tolua_unit_removespell); 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_function(L, TOLUA_CAST "cast_spell", &tolua_unit_castspell);
tolua_variable(L, TOLUA_CAST "magic", &tolua_unit_get_magic, 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_unit_set_ship);
tolua_variable(L, TOLUA_CAST "region", &tolua_unit_get_region, tolua_variable(L, TOLUA_CAST "region", &tolua_unit_get_region,
tolua_unit_set_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_variable(L, TOLUA_CAST "number", &tolua_unit_get_number,
tolua_unit_set_number); tolua_unit_set_number);
tolua_variable(L, TOLUA_CAST "race", &tolua_unit_get_race, tolua_variable(L, TOLUA_CAST "race", &tolua_unit_get_race,

View file

@ -3737,12 +3737,11 @@ static void update_spells(void)
} }
show_new_spells(f, maxlevel, faction_get_spellbook(f)); show_new_spells(f, maxlevel, faction_get_spellbook(f));
for (i=0; i!=MAXMAGES && mages[i]; ++i) { for (i=0; i!=MAXMAGES && mages[i]; ++i) {
sc_mage *mage = get_mage(mages[i]); unit * u = mages[i];
if (mage && mage->spells) { sc_mage *mage = get_mage(u);
#ifdef TODO if (mage && mage->spellbook) {
int level = effskill(mages[i], SK_MAGIC); int level = effskill(u, SK_MAGIC);
show_new_spells(f, level, mage->spellbook); show_new_spells(f, level, mage->spellbook);
#endif
} }
} }
} }

View file

@ -44,8 +44,8 @@ void test_equipment(CuTest * tc)
mage = get_mage(u); mage = get_mage(u);
CuAssertPtrNotNull(tc, mage); CuAssertPtrNotNull(tc, mage);
CuAssertPtrNotNull(tc, mage->spells); CuAssertPtrNotNull(tc, mage->spellbook);
CuAssertTrue(tc, u_hasspell(mage, sp)); CuAssertTrue(tc, u_hasspell(u, sp));
} }
CuSuite *get_equipment_suite(void) CuSuite *get_equipment_suite(void)

View file

@ -33,6 +33,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "pool.h" #include "pool.h"
#include "race.h" #include "race.h"
#include "region.h" #include "region.h"
#include "save.h"
#include "ship.h" #include "ship.h"
#include "skill.h" #include "skill.h"
#include "spell.h" #include "spell.h"
@ -200,7 +201,10 @@ static void init_mage(attrib * a)
static void free_mage(attrib * a) static void free_mage(attrib * a)
{ {
sc_mage *mage = (sc_mage *) a->data.v; sc_mage *mage = (sc_mage *) a->data.v;
freelist(mage->spells); if (mage->spellbook) {
spellbook_clear(mage->spellbook);
free(mage->spellbook);
}
free(mage); 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; 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"); mage->combatspells[i].sp ? mage->combatspells[i].sp->sname : "none");
store->w_int(store, mage->combatspells[i].level); store->w_int(store, mage->combatspells[i].level);
} }
write_spells(mage->spells, store); write_spellbook(mage->spellbook, store);
} }
attrib_type at_mage = { attrib_type at_mage = {
@ -391,12 +395,6 @@ attrib_type at_seenspell = {
#define MAXSPELLS 256 #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) static boolean already_seen(const faction * f, const spell * sp)
{ {
attrib *a; 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); cmistake(u, ord, 173, MSG_MAGIC);
return; return;
} }
if (!u_hasspell(mage, sp)) { if (!u_hasspell(u, sp)) {
/* Diesen Zauber kennt die Einheit nicht */ /* Diesen Zauber kennt die Einheit nicht */
cmistake(u, ord, 169, MSG_MAGIC); cmistake(u, ord, 169, MSG_MAGIC);
return; 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) boolean knowsspell(const region * r, const unit * u, const spell * sp)
{ {
sc_mage *mage;
/* Ist überhaupt ein gültiger Spruch angegeben? */ /* Ist überhaupt ein gültiger Spruch angegeben? */
if (!sp || sp->id == 0) { if (!sp || sp->id == 0) {
return false; 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? */ /* 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 /* 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)); return LOC(lang, mkname("spell", ctype->cname));
} }
spell *unit_getspell(struct unit *u, const char *name, spell *unit_getspell(struct unit *u, const char *name, const struct locale * lang)
const struct locale * lang)
{ {
sc_mage * mage = get_mage(u); sc_mage * mage = get_mage(u);
if (mage) { if (mage) {
@ -2887,40 +2882,37 @@ spell *unit_getspell(struct unit *u, const char *name,
if (names->lang==lang) break; if (names->lang==lang) break;
} }
if (!names) { if (!names) {
quicklist *ql = mage->spells; spellbook *sb = unit_get_spellbook(u);
int qi; if (sb) {
names = (spell_names *)calloc(1, sizeof(spell_names)); quicklist * ql;
names->next = mage->spellnames; int qi;
names->lang = lang; names = (spell_names *)calloc(1, sizeof(spell_names));
names->tokens = 0; names->next = mage->spellnames;
for (qi = 0, ql = mage->spells; ql; ql_advance(&ql, &qi, 1)) { names->lang = lang;
spell *sp = (spell *) ql_get(ql, qi); names->tokens = 0;
const char *n = spell_name(sp, lang);
if (!n) { for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) {
log_error("no translation in locae %s for spell $s\n", locale_name(lang), sp->sname); spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi);
} else { spell *sp = sbe->sp;
token.v = sp; const char *n = spell_name(sp, lang);
addtoken(&names->tokens, n, token); 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 (spell *) token.v;
} }
} }
return 0; 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; static critbit_tree cb_spellbooks;
spellbook * get_spellbook(const char * name) spellbook * get_spellbook(const char * name)

View file

@ -117,7 +117,7 @@ typedef struct sc_mage {
int spchange; int spchange;
int spellcount; int spellcount;
combatspell combatspells[MAXCOMBATSPELLS]; combatspell combatspells[MAXCOMBATSPELLS];
struct quicklist *spells; struct spellbook *spellbook;
struct spell_names * spellnames; struct spell_names * spellnames;
} sc_mage; } sc_mage;
@ -252,7 +252,7 @@ typedef struct sc_mage {
/* löscht Kampfzauber */ /* löscht Kampfzauber */
void add_spellname(sc_mage * mage, const struct spell * sp); void add_spellname(sc_mage * mage, const struct spell * sp);
/* fügt den Spruch mit der Id spellid der Spruchliste der Einheit hinzu. */ /* 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. */ /* 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 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); 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, extern struct message *msg_unitnotfound(const struct unit *mage,
struct order *ord, const struct spllprm *spobj); struct order *ord, const struct spllprm *spobj);
extern int FactionSpells(void); 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 write_spells(struct quicklist *slist, struct storage *store);
extern void read_spells(struct quicklist **slistp, magic_t mtype, extern void read_spells(struct quicklist **slistp, magic_t mtype,

View file

@ -348,6 +348,35 @@ void test_set_post_combatspell(CuTest * tc)
CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); 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 *get_magic_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); 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_pre_combatspell);
SUITE_ADD_TEST(suite, test_set_main_combatspell); SUITE_ADD_TEST(suite, test_set_main_combatspell);
SUITE_ADD_TEST(suite, test_set_post_combatspell); SUITE_ADD_TEST(suite, test_set_post_combatspell);
SUITE_ADD_TEST(suite, test_hasspell);
return suite; return suite;
} }

View file

@ -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 rc_skillmod(const struct race *rc, const region * r, skill_t sk)
{ {
int mods; int mods = 0;
if (!skill_enabled[sk]) { if (!skill_enabled[sk]) {
return 0; 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]; mods = (*imods)->mod[rterrain(r)].value[sk];
#else #else
mods = skill_mod(rc, sk, r->terrain); if (r) {
mods = skill_mod(rc, sk, r->terrain);
}
#endif #endif
if (rc == new_race[RC_ELF] && r_isforest(r)) { if (rc == new_race[RC_ELF] && r && r_isforest(r)) {
if (sk == SK_PERCEPTION) { if (sk == SK_PERCEPTION || sk == SK_STEALTH) {
++mods; ++mods;
} else if (sk == SK_STEALTH) {
if (r_isforest(r)) {
++mods;
}
} else if (sk == SK_TACTICS) { } else if (sk == SK_TACTICS) {
if (r_isforest(r)) { mods += 2;
mods += 2;
}
} }
} }
return mods; return mods;

View file

@ -31,6 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "race.h" #include "race.h"
#include "region.h" #include "region.h"
#include "spell.h" #include "spell.h"
#include "spellbook.h"
#include "save.h" #include "save.h"
#include "ship.h" #include "ship.h"
#include "skill.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) static int att_modification(const unit * u, skill_t sk)
{ {
double bonus = 0, malus = 0;
attrib *a;
double result = 0; double result = 0;
static boolean init = false; static boolean init = false;
static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct; 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 /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der
* jeweils erste vom Typ C_GBDREAM zurückgegen wird, wir aber alle * jeweils erste vom Typ C_GBDREAM zurückgegen wird, wir aber alle
* durchsuchen und aufaddieren müssen */ * durchsuchen und aufaddieren müssen */
a = a_find(u->region->attribs, &at_curse); if (u->region) {
while (a && a->type == &at_curse) { double bonus = 0, malus = 0;
curse *c = (curse *) a->data.v; attrib *a = a_find(u->region->attribs, &at_curse);
if (curse_active(c) && c->type == gbdream_ct) { while (a && a->type == &at_curse) {
double mod = curse_geteffect(c); curse *c = (curse *) a->data.v;
unit *mage = c->magician; if (curse_active(c) && c->type == gbdream_ct) {
/* wir suchen jeweils den größten Bonus und den größten Malus */ double mod = curse_geteffect(c);
if (mod > bonus) { unit *mage = c->magician;
if (mage == NULL || mage->number == 0 /* wir suchen jeweils den größten Bonus und den größten Malus */
|| alliedunit(mage, u->faction, HELP_GUARD)) { if (mod > bonus) {
bonus = mod; if (mage == NULL || mage->number == 0
} || alliedunit(mage, u->faction, HELP_GUARD)) {
} else if (mod < malus) { bonus = mod;
if (mage == NULL || !alliedunit(mage, u->faction, HELP_GUARD)) { }
malus = 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; return (int)result;
} }
@ -1283,11 +1285,11 @@ get_modifier(const unit * u, skill_t sk, int level, const region * r,
int bskill = level; int bskill = level;
int skill = bskill; int skill = bskill;
assert(r); if (r && sk == SK_STEALTH) {
if (sk == SK_STEALTH) {
plane *pl = rplane(r); plane *pl = rplane(r);
if (pl && fval(pl, PFL_NOSTEALTH)) if (pl && fval(pl, PFL_NOSTEALTH)) {
return 0; return 0;
}
} }
skill += rc_skillmod(u->race, r, sk); 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)); 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); 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); add_spellname(mage, sp);
} }
@ -1742,10 +1747,8 @@ struct spellbook * unit_get_spellbook(const struct unit * u)
{ {
sc_mage * mage = get_mage(u); sc_mage * mage = get_mage(u);
if (mage) { if (mage) {
if (mage->spells) { if (mage->spellbook) {
#ifdef TODO
return mage->spellbook; return mage->spellbook;
#endif
} }
return faction_get_spellbook(u->faction); return faction_get_spellbook(u->faction);
} }