diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c
index f54f5e177..2a39127a4 100644
--- a/src/common/kernel/magic.c
+++ b/src/common/kernel/magic.c
@@ -365,43 +365,17 @@ void
updatespelllist(unit * u)
{
int max = eff_skill(u, SK_MAGIC, u->region);
- int i, sk = max;
+ int sk = max;
+ spell * sp;
magic_t gebiet = find_magetype(u);
+ boolean ismonster = u->faction->no==MONSTER_FACTION;
- if (u->faction->no==MONSTER_FACTION) return;
-
-
- /* 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 */
- /* if (gebiet == M_GRAU) return; */
-
- for (i = 0; spelldaten[i].id != SPL_NOSPELL; i++) {
- boolean know = getspell(u, spelldaten[i].id);
- if (know || (spelldaten[i].magietyp == gebiet && spelldaten[i].level <= sk)) {
- if (!know) addspell(u, spelldaten[i].id);
-
- if (!already_seen(u->faction, spelldaten[i].id)) {
- a_add(&u->faction->attribs,
- a_new(&at_reportspell))->data.i = spelldaten[i].id;
- a_add(&u->faction->attribs,
- a_new(&at_seenspell))->data.i = spelldaten[i].id;
- }
- }
- }
- /* Nur Orkmagier bekommen den Keuschheitsamulettzauber */
+ /* Nur Orkmagier bekommen den Keuschheitsamulettzauber */
if (old_race(u->race) == RC_ORC
&& !getspell(u, SPL_ARTEFAKT_CHASTITYBELT)
&& find_spellbyid(SPL_ARTEFAKT_CHASTITYBELT)->level <= max)
{
- addspell(u,SPL_ARTEFAKT_CHASTITYBELT);
-
- if (!already_seen(u->faction, spelldaten[i].id)) {
- a_add(&u->faction->attribs,
- a_new(&at_reportspell))->data.i = SPL_ARTEFAKT_CHASTITYBELT;
- a_add(&u->faction->attribs,
- a_new(&at_seenspell))->data.i = SPL_ARTEFAKT_CHASTITYBELT;
- }
+ addspell(u, SPL_ARTEFAKT_CHASTITYBELT);
}
/* Nur Wyrm-Magier bekommen den Wyrmtransformationszauber */
@@ -410,12 +384,6 @@ updatespelllist(unit * u)
&& find_spellbyid(SPL_BECOMEWYRM)->level <= max)
{
addspell(u, SPL_BECOMEWYRM);
- if (!already_seen(u->faction, spelldaten[i].id)) {
- a_add(&u->faction->attribs,
- a_new(&at_reportspell))->data.i = SPL_BECOMEWYRM;
- a_add(&u->faction->attribs,
- a_new(&at_seenspell))->data.i = SPL_BECOMEWYRM;
- }
}
/* Transformierte Wyrm-Magier bekommen Drachenodem */
@@ -424,51 +392,41 @@ updatespelllist(unit * u)
switch (urc) {
/* keine breaks! Wyrme sollen alle drei Zauber können.*/
case RC_WYRM:
- {
- if(!getspell(u, SPL_WYRMODEM) &&
- find_spellbyid(SPL_WYRMODEM)->level <= max) {
-
- addspell(u, SPL_WYRMODEM);
- if (!already_seen(u->faction, spelldaten[i].id)) {
- a_add(&u->faction->attribs,
- a_new(&at_reportspell))->data.i = SPL_WYRMODEM;
- a_add(&u->faction->attribs,
- a_new(&at_seenspell))->data.i = SPL_WYRMODEM;
- }
- }
- }
+ sp = find_spellbyid(SPL_WYRMODEM);
+ if (sp!=NULL && !getspell(u, sp->id) && sp->level<=max) {
+ addspell(u, sp->id);
+ }
case RC_DRAGON:
- {
- if(!getspell(u, SPL_DRAGONODEM) &&
- find_spellbyid(SPL_DRAGONODEM)->level <= max) {
-
- addspell(u, SPL_DRAGONODEM);
- if (!already_seen(u->faction, spelldaten[i].id)) {
- a_add(&u->faction->attribs,
- a_new(&at_reportspell))->data.i = SPL_DRAGONODEM;
- a_add(&u->faction->attribs,
- a_new(&at_seenspell))->data.i = SPL_DRAGONODEM;
- }
- }
- }
+ sp = find_spellbyid(SPL_DRAGONODEM);
+ if (sp!=NULL && !getspell(u, sp->id) && sp->level<=max) {
+ addspell(u, sp->id);
+ }
case RC_FIREDRAGON:
- {
- if(!getspell(u, SPL_FIREDRAGONODEM) &&
- find_spellbyid(SPL_FIREDRAGONODEM)->level <= max) {
-
- addspell(u, SPL_FIREDRAGONODEM);
- if (!already_seen(u->faction, spelldaten[i].id)) {
- a_add(&u->faction->attribs,
- a_new(&at_reportspell))->data.i = SPL_FIREDRAGONODEM;
- a_add(&u->faction->attribs,
- a_new(&at_seenspell))->data.i = SPL_FIREDRAGONODEM;
- }
- }
- }
+ sp = find_spellbyid(SPL_FIREDRAGONODEM);
+ if (sp!=NULL && getspell(u, sp->id) && sp->level<=max) {
+ addspell(u, sp->id);
+ }
+ break;
}
}
- return;
+ /* 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 (sp = spelldaten; sp->id != SPL_NOSPELL; ++sp) {
+ boolean know = getspell(u, sp->id);
+
+ if (know || (gebiet!=M_GRAU && sp->magietyp == gebiet && sp->level <= sk)) {
+ faction * f = u->faction;
+
+ if (!know) addspell(u, sp->id);
+ if (!ismonster && !already_seen(u->faction, sp->id)) {
+ a_add(&f->attribs, a_new(&at_reportspell))->data.i = sp->id;
+ a_add(&f->attribs, a_new(&at_seenspell))->data.i = sp->id;
+ }
+ }
+ }
}
/* ------------------------------------------------------------- */
@@ -3173,3 +3131,12 @@ spell_name(const struct spell * sp, const struct locale * lang)
}
return sp->sname;
}
+
+void
+add_spelllist(spell_list ** lspells, spell * sp)
+{
+ spell_list * entry = malloc(sizeof(spell_list));
+ entry->data = sp;
+ entry->next = *lspells;
+ *lspells = entry;
+}
\ No newline at end of file
diff --git a/src/common/kernel/magic.h b/src/common/kernel/magic.h
index 9d398b05d..65af7ad95 100644
--- a/src/common/kernel/magic.h
+++ b/src/common/kernel/magic.h
@@ -34,10 +34,6 @@ struct building;
#define IRONGOLEM_CRUMBLE 15 /* monatlich Chance zu zerfallen */
#define STONEGOLEM_CRUMBLE 10 /* monatlich Chance zu zerfallen */
-/* ------------------------------------------------------------- */
-typedef struct spell_ptr spell_ptr;
-typedef struct castorder castorder;
-
/* ------------------------------------------------------------- */
/* Spruchparameter
* Wir suchen beim Parsen des Befehls erstmal nach lokalen Objekten,
@@ -112,6 +108,11 @@ extern const char *magietypen[MAXMAGIETYP];
* - Spruchliste
*/
+typedef struct spell_ptr {
+ struct spell_ptr *next;
+ spellid_t spellid;
+} spell_ptr;
+
typedef struct sc_mage {
magic_t magietyp;
int spellpoints;
@@ -121,14 +122,9 @@ typedef struct sc_mage {
int combatspelllevel[MAXCOMBATSPELLS];
int precombataura; /* Merker, wieviel Aura in den Präcombatzauber
gegangen ist. Nicht speichern. */
- spell_ptr *spellptr;
+ struct spell_ptr *spellptr;
} sc_mage;
-struct spell_ptr {
- spell_ptr *next;
- spellid_t spellid;
-};
-
/* ------------------------------------------------------------- */
/* Spruchstukturdefinition:
* id:
@@ -144,7 +140,23 @@ struct spell_ptr {
*
*/
-/* typedef struct fighter fighter; */
+/* ------------------------------------------------------------- */
+/* Zauberliste */
+
+
+typedef struct castorder {
+ struct castorder *next;
+ void *magician; /* Magier (kann vom Typ struct unit oder fighter sein) */
+ struct unit *familiar; /* Vertrauter, gesetzt, wenn der Spruch durch
+ den Vertrauten gezaubert wird */
+ struct spell *sp; /* Spruch */
+ int level; /* gewünschte Stufe oder Stufe des Magiers */
+ double force; /* Stärke des Zaubers */
+ struct region *rt; /* Zielregion des Spruchs */
+ int distance; /* Entfernung zur Zielregion */
+ char *order; /* Befehl */
+ struct spellparameter *par; /* für weitere Parameter */
+} castorder;
/* irgendwelche zauber: */
typedef void (*spell_f) (void*);
@@ -170,25 +182,12 @@ typedef struct spell {
void (*patzer) (castorder*);
} spell;
+typedef struct spell_list {
+ struct spell_list * next;
+ spell * data;
+} spell_list;
-/* ------------------------------------------------------------- */
-/* Zauberliste */
-
-
-struct castorder {
- castorder *next;
- void *magician; /* Magier (kann vom Typ struct unit oder fighter sein) */
- struct unit *familiar; /* Vertrauter, gesetzt, wenn der Spruch durch
- den Vertrauten gezaubert wird */
- struct spell *sp; /* Spruch */
- int level; /* gewünschte Stufe oder Stufe des Magiers */
- double force; /* Stärke des Zaubers */
- struct region *rt; /* Zielregion des Spruchs */
- int distance; /* Entfernung zur Zielregion */
- char *order; /* Befehl */
- struct spellparameter *par; /* für weitere Parameter */
-};
-
+extern void add_spelllist(spell_list ** lspells, spell * sp);
/* ------------------------------------------------------------- */
/* besondere Spruchtypen */
diff --git a/src/common/kernel/race.c b/src/common/kernel/race.c
index 3fe7159fb..4f731141d 100644
--- a/src/common/kernel/race.c
+++ b/src/common/kernel/race.c
@@ -391,7 +391,7 @@ racename(const struct locale *loc, const unit *u, const race * rc)
static void
oldfamiliars(unit * familiar)
{
- sc_mage * m;
+ sc_mage * m = NULL;
race_t frt = old_race(familiar->race);
switch(frt) {
@@ -432,9 +432,6 @@ oldfamiliars(unit * familiar)
/* Magie+1, Spionage, Tarnung, Wahrnehmung, Ausdauer */
m = create_mage(familiar, M_GRAU);
set_level(familiar, SK_MAGIC, 1);
- addspell(familiar, SPL_FLEE);
- addspell(familiar, SPL_SLEEP);
- addspell(familiar, SPL_FRIGHTEN);
m->combatspell[0] = SPL_FLEE;
m->combatspell[1] = SPL_SLEEP;
break;
@@ -452,10 +449,6 @@ oldfamiliars(unit * familiar)
set_level(familiar, SK_ENTERTAINMENT, 1);
set_level(familiar, SK_OBSERVATION, 1);
m = create_mage(familiar, M_GRAU);
- addspell(familiar, SPL_SEDUCE);
- addspell(familiar, SPL_CALM_MONSTER);
- addspell(familiar, SPL_SONG_OF_CONFUSION);
- addspell(familiar, SPL_DENYATTACK);
m->combatspell[0] = SPL_SONG_OF_CONFUSION;
break;
case RC_UNICORN:
@@ -464,12 +457,6 @@ oldfamiliars(unit * familiar)
set_level(familiar, SK_STEALTH, 1);
set_level(familiar, SK_OBSERVATION, 1);
m = create_mage(familiar, M_GRAU);
- addspell(familiar, SPL_RESISTMAGICBONUS);
- addspell(familiar, SPL_SONG_OF_PEACE);
- addspell(familiar, SPL_CALM_MONSTER);
- addspell(familiar, SPL_HERO);
- addspell(familiar, SPL_HEALINGSONG);
- addspell(familiar, SPL_DENYATTACK);
break;
case RC_WARG:
/* Spi, Tak, Tar, Wahri+2, Aus */
@@ -481,9 +468,6 @@ oldfamiliars(unit * familiar)
/* Mag+1, Rei-2, Hie, Sta, Spi, Tar, Wahr, Aus */
set_level(familiar, SK_MAGIC, 1);
m = create_mage(familiar, M_GRAU);
- addspell(familiar, SPL_STEALAURA);
- addspell(familiar, SPL_FRIGHTEN);
- addspell(familiar, SPL_SUMMONUNDEAD);
break;
case RC_IMP:
/* Mag+1,Rei-1,Hie,Sta,Spi+1,Tar+1,Wahr+1,Steu+1,Aus*/
@@ -493,7 +477,6 @@ oldfamiliars(unit * familiar)
set_level(familiar, SK_OBSERVATION, 1);
set_level(familiar, SK_TAXING, 1);
m = create_mage(familiar, M_GRAU);
- addspell(familiar, SPL_STEALAURA);
break;
case RC_DREAMCAT:
/* Mag+1,Hie,Sta,Spi+1,Tar+1,Wahr+1,Steu+1,Aus*/
@@ -503,16 +486,11 @@ oldfamiliars(unit * familiar)
set_level(familiar, SK_OBSERVATION, 1);
set_level(familiar, SK_TAXING, 1);
m = create_mage(familiar, M_GRAU);
- addspell(familiar, SPL_ILL_SHAPESHIFT);
- addspell(familiar, SPL_TRANSFERAURA_TRAUM);
break;
case RC_FEY:
/* Mag+1,Rei-1,Hie-1,Sta-1,Spi+2,Tar+5,Wahr+2,Aus */
set_level(familiar, SK_MAGIC, 1);
m = create_mage(familiar,M_GRAU);
- addspell(familiar, SPL_DENYATTACK);
- addspell(familiar, SPL_CALM_MONSTER);
- addspell(familiar, SPL_SEDUCE);
break;
case RC_OWL:
/* Spi+1,Tar+1,Wahr+5,Aus */
@@ -535,6 +513,13 @@ oldfamiliars(unit * familiar)
m = create_mage(familiar,M_GRAU);
break;
}
+ if (m!=NULL) {
+ spell_list * fspells = familiarspells(familiar->race);
+ while (fspells!=NULL) {
+ addspell(familiar, fspells->data->id);
+ fspells=fspells->next;
+ }
+ }
}
static item *
@@ -578,6 +563,7 @@ elf_spoil(const struct race * rc, int size)
}
return itm;
}
+
static item *
demon_spoil(const struct race * rc, int size)
{
@@ -587,6 +573,7 @@ demon_spoil(const struct race * rc, int size)
}
return itm;
}
+
static item *
goblin_spoil(const struct race * rc, int size)
{
@@ -988,3 +975,90 @@ register_races(void)
sprintf(zBuffer, "%s/races.xml", resourcepath());
xml_register(&xml_races, "eressea races", 0);
}
+
+/** familiars **/
+typedef struct familiar_spells {
+ struct familiar_spells * next;
+ spell_list * spells;
+ const race * familiar_race;
+} familiar_spells;
+
+static familiar_spells * racespells;
+
+spell_list *
+familiarspells(const race * rc)
+{
+ familiar_spells * fspells = racespells;
+ while (fspells && rc!=fspells->familiar_race) {
+ fspells = fspells->next;
+ }
+ if (fspells!=NULL) return fspells->spells;
+ return NULL;
+}
+
+familiar_spells *
+mkspells(const race * rc)
+{
+ familiar_spells * fspells;
+
+ fspells = malloc(sizeof(familiar_spells));
+ fspells->next = racespells;
+ racespells = fspells;
+ fspells->familiar_race = rc;
+ fspells->spells = NULL;
+ return fspells;
+}
+
+void
+init_familiarspells(void)
+{
+ familiar_spells * fspells;
+
+ fspells = mkspells(new_race[RC_PSEUDODRAGON]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_FLEE));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SLEEP));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_FRIGHTEN));
+
+ fspells = mkspells(new_race[RC_NYMPH]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SEDUCE));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_CALM_MONSTER));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SONG_OF_CONFUSION));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_DENYATTACK));
+
+ fspells = mkspells(new_race[RC_NYMPH]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SEDUCE));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_CALM_MONSTER));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SONG_OF_CONFUSION));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_DENYATTACK));
+
+ fspells = mkspells(new_race[RC_UNICORN]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_RESISTMAGICBONUS));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SONG_OF_PEACE));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_CALM_MONSTER));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_HERO));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_HEALINGSONG));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_DENYATTACK));
+
+ fspells = mkspells(new_race[RC_WRAITH]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_STEALAURA));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_FRIGHTEN));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SUMMONUNDEAD));
+
+ fspells = mkspells(new_race[RC_IMP]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_STEALAURA));
+
+ fspells = mkspells(new_race[RC_DREAMCAT]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_ILL_SHAPESHIFT));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_TRANSFERAURA_TRAUM));
+
+ fspells = mkspells(new_race[RC_FEY]);
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_DENYATTACK));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_CALM_MONSTER));
+ add_spelllist(&fspells->spells, find_spellbyid(SPL_SEDUCE));
+}
+
+void
+init_races(void)
+{
+ init_familiarspells();
+}
\ No newline at end of file
diff --git a/src/common/kernel/race.h b/src/common/kernel/race.h
index 0ea6a10db..c0e0f0e05 100644
--- a/src/common/kernel/race.h
+++ b/src/common/kernel/race.h
@@ -156,7 +156,9 @@ extern const char * racename(const struct locale *lang, const struct unit *u, co
extern boolean allowed_dragon(const struct region * src, const struct region * target);
extern void register_races(void);
+extern void init_races(void);
extern boolean r_insectstalled(const struct region *r);
+extern spell_list * familiarspells(const struct race * rc);
extern const char *race_prefixes[];
diff --git a/src/eressea/eressea-lua.vcproj b/src/eressea/eressea-lua.vcproj
index 75300891e..1909ca225 100644
--- a/src/eressea/eressea-lua.vcproj
+++ b/src/eressea/eressea-lua.vcproj
@@ -314,6 +314,9 @@
DisableLanguageExtensions="FALSE"/>
+
+
+#include
+#include "list.h"
+
+// Atributes includes
+#include
+
+// kernel includes
+#include
+
+// lua includes
+#include
+#include
+#include
+
+using namespace luabind;
+
+static const char *
+spell_getschool(const spell& sp)
+{
+ return magietypen[sp.magietyp];
+}
+
+void
+bind_spell(lua_State * L)
+{
+ module(L)[
+ class_("spell")
+ .def_readonly("name", &spell::sname)
+ .def_readonly("level", &spell::level)
+ .def("school", &spell_getschool)
+ ];
+}
diff --git a/src/eressea/lua/unit.cpp b/src/eressea/lua/unit.cpp
index 0a34483b0..042ef605e 100644
--- a/src/eressea/lua/unit.cpp
+++ b/src/eressea/lua/unit.cpp
@@ -1,5 +1,6 @@
#include
#include
+#include "list.h"
// Atributes includes
#include
@@ -11,6 +12,7 @@
#include
#include
#include
+#include
// lua includes
#include
@@ -19,6 +21,32 @@
using namespace luabind;
+class bind_spell_ptr {
+public:
+ static spell_ptr * next(spell_ptr * node) { return node->next; }
+ static spell * value(spell_ptr * node) { return find_spellbyid(node->spellid); }
+};
+
+static eressea::list
+unit_spells(const unit& u) {
+ sc_mage * mage = get_mage(&u);
+ if (mage==NULL) return eressea::list(NULL);
+ spell_ptr * splist = mage->spellptr;
+ return eressea::list(splist);
+}
+
+class bind_spell_list {
+public:
+ static spell_list * next(spell_list * node) { return node->next; }
+ static spell * value(spell_list * node) { return node->data; }
+};
+
+static eressea::list
+unit_familiarspells(const unit& u) {
+ spell_list * spells = familiarspells(u.race);
+ return eressea::list(spells);
+}
+
static unit *
add_unit(faction * f, region * r)
{
@@ -135,6 +163,8 @@ bind_unit(lua_State * L)
.def("eff_skill", &unit_effskill)
.def("set_skill", &unit_setskill)
.def("set_racename", &unit_setracename)
+ .property("spells", &unit_spells, return_stl_iterator)
+ .property("familiarspells", &unit_familiarspells, return_stl_iterator)
.property("number", &unit_getnumber, &unit_setnumber)
.property("race", &unit_getrace, &unit_setrace)
];
diff --git a/src/eressea/main.c b/src/eressea/main.c
index 1e0509378..b136de4d8 100644
--- a/src/eressea/main.c
+++ b/src/eressea/main.c
@@ -173,6 +173,7 @@ game_init(void)
init_attributes();
init_resources();
init_items();
+ init_races();
init_economy();
#if NEW_RESOURCEGROWTH
init_rawmaterials();
diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp
index 8e6b81842..c13972bf3 100644
--- a/src/eressea/server.cpp
+++ b/src/eressea/server.cpp
@@ -186,6 +186,7 @@ game_init(void)
init_attributes();
init_resources();
+ init_races();
init_items();
init_economy();
#if NEW_RESOURCEGROWTH