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;
}
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,

View file

@ -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
}
}
}

View file

@ -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)

View file

@ -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)

View file

@ -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,

View file

@ -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;
}

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 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;

View file

@ -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);
}