Merge branch 'develop' of github.com:ennorehling/eressea into develop

This commit is contained in:
Enno Rehling 2018-11-23 12:35:24 +01:00
commit 037113b35d
21 changed files with 359 additions and 324 deletions

View File

@ -132,7 +132,7 @@ function equip_unit(u, name, flags)
end
local spells = set['spells']
if spells then
for name, level in ipairs(spells) do
for name, level in pairs(spells) do
u:add_spell(name, level)
end
end

View File

@ -215,12 +215,12 @@ function test_bug_2517()
uf = um.familiar
assert_not_nil(uf)
assert_equal('lynx', uf.race)
assert_nil(uf.magic)
assert_equal('gray', uf.magic)
uf:add_order('LERNE Magie')
um:clear_orders()
um:add_order('ARBEITEN')
process_orders()
assert_nil(uf.magic)
assert_equal('gray', uf.magic)
uf:add_order('ZAUBERE STUFE 1 Viehheilung')
process_orders()
assert_equal(50, uf:get_item('money'))

View File

@ -276,8 +276,12 @@ static int tolua_unit_set_guard(lua_State * L)
static const char *unit_getmagic(const unit * u)
{
sc_mage *mage = get_mage_depr(u);
return mage ? magic_school[mage->magietyp] : NULL;
struct sc_mage *mage = get_mage(u);
if (mage) {
magic_t mtype = mage_get_type(mage);
return magic_school[mtype];
}
return NULL;
}
static int tolua_unit_get_magic(lua_State * L)
@ -289,16 +293,15 @@ static int tolua_unit_get_magic(lua_State * L)
static void unit_setmagic(unit * u, const char *type)
{
sc_mage *mage = get_mage(u);
struct sc_mage *mage = get_mage(u);
if (mage == NULL) {
int mtype;
for (mtype = 0; mtype != MAXMAGIETYP; ++mtype) {
if (strcmp(magic_school[mtype], type) == 0)
break;
}
if (mtype == MAXMAGIETYP)
if (strcmp(magic_school[mtype], type) == 0) {
create_mage(u, (magic_t)mtype);
return;
if (mage == NULL) {
mage = create_mage(u, (magic_t)mtype);
}
}
}
}
@ -521,7 +524,7 @@ static int tolua_unit_addspell(lua_State * L)
return EINVAL;
}
else {
unit_add_spell(u, 0, sp, level);
unit_add_spell(u, sp, level);
}
lua_pushinteger(L, err);
@ -748,8 +751,8 @@ static int tolua_unit_get_items(lua_State * L)
static int tolua_unit_get_spells(lua_State * L)
{
unit *self = (unit *) tolua_tousertype(L, 1, 0);
sc_mage *mage = self ? get_mage_depr(self) : 0;
spellbook *sb = mage ? mage->spellbook : 0;
struct sc_mage *mage = self ? get_mage(self) : NULL;
spellbook *sb = mage_get_spellbook(mage);
selist *slist = 0;
if (sb) {
selist **slist_ptr = &sb->spells;

View File

@ -880,7 +880,7 @@ void cr_output_unit(stream *out, const faction * f,
const char *xc;
const char *c;
int i;
sc_mage *mage;
struct sc_mage *mage;
i = ualias(u);
if (i > 0)
@ -957,19 +957,23 @@ void cr_output_unit(stream *out, const faction * f,
}
/* spells that this unit can cast */
mage = get_mage_depr(u);
mage = get_mage(u);
if (mage) {
int maxlevel = effskill(u, SK_MAGIC, 0);
cr_output_spells(out, u, maxlevel);
for (i = 0; i != MAXCOMBATSPELLS; ++i) {
const spell *sp = mage->combatspells[i].sp;
int level;
const spell *sp = mage_get_combatspell(mage, i, &level);
if (sp) {
const char *name =
translate(mkname("spell", sp->sname), spell_name(sp, lang));
const char *name;
if (level > maxlevel) {
level = maxlevel;
}
stream_printf(out, "KAMPFZAUBER %d\n", i);
name = translate(mkname("spell", sp->sname), spell_name(sp, lang));
stream_printf(out, "\"%s\";name\n", name);
stream_printf(out, "%d;level\n", mage->combatspells[i].level);
stream_printf(out, "%d;level\n", level);
}
}
}

View File

@ -587,14 +587,12 @@ void give_unit(unit * u, unit * u2, order * ord)
}
}
if (has_skill(u, SK_MAGIC)) {
sc_mage *mage;
if (count_skill(u2->faction, SK_MAGIC) + u->number >
skill_limit(u2->faction, SK_MAGIC)) {
cmistake(u, ord, 155, MSG_COMMERCE);
return;
}
mage = get_mage_depr(u);
if (!mage || u2->faction->magiegebiet != mage->magietyp) {
if (u2->faction->magiegebiet != unit_get_magic(u)) {
cmistake(u, ord, 157, MSG_COMMERCE);
return;
}

View File

@ -25,7 +25,7 @@ static void test_manacrystal(CuTest *tc) {
CuAssertIntEquals(tc, -1, use_manacrystal(u, itype, 1, NULL));
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error295"));
test_clear_messages(u->faction);
create_mage(u, M_GRAY);
create_mage(u, M_GWYRRD);
set_level(u, SK_MAGIC, 5);
CuAssertIntEquals(tc, 0, get_spellpoints(u));
CuAssertIntEquals(tc, 1, use_manacrystal(u, itype, 1, NULL));

View File

@ -1293,16 +1293,6 @@ ship *read_ship(gamedata *data)
return sh;
}
static void fix_fam_mage(unit *u) {
sc_mage *m = get_mage(u);
if (m && m->magietyp != M_GRAY) {
/* unit should be a familiar that has aura and a spell-list */
if (!m->spellbook) {
m->magietyp = M_GRAY;
}
}
}
static void fix_fam_triggers(unit *u) {
attrib * a = a_find(u->attribs, &at_mage);
attrib * am = a_find(u->attribs, &at_familiarmage);
@ -1507,20 +1497,18 @@ int read_game(gamedata *data)
assert(f->units);
for (u = f->units; u; u = u->nextF) {
if (data->version < SPELL_LEVEL_VERSION) {
sc_mage *mage = get_mage_depr(u);
struct sc_mage *mage = get_mage(u);
if (mage) {
faction *f = u->faction;
int skl = effskill(u, SK_MAGIC, 0);
if (f->magiegebiet == M_GRAY) {
log_error("faction %s had magic=gray, fixing (%s)", factionname(f), magic_school[mage->magietyp]);
f->magiegebiet = mage->magietyp;
f->magiegebiet = mage_get_type(mage);
log_error("faction %s had magic=gray, fixing (%s)",
factionname(f), magic_school[f->magiegebiet]);
}
if (f->max_spelllevel < skl) {
f->max_spelllevel = skl;
}
if (mage->spellcount < 0) {
mage->spellcount = 0;
}
}
}
if (u->number > 0) {

View File

@ -117,7 +117,7 @@ enum {
MAXOPTIONS
};
typedef enum {
typedef enum magic_t {
M_GRAY = 0, /* Gray */
M_ILLAUN = 1, /* Illaun */
M_TYBIED = 2, /* Tybied */

View File

@ -1657,34 +1657,6 @@ void u_setrace(struct unit *u, const struct race *rc)
}
}
void unit_add_spell(unit * u, sc_mage * m, struct spell * sp, int level)
{
sc_mage *mage = m ? m : get_mage_depr(u);
if (!mage) {
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);
}
if (!mage->spellbook) {
mage->spellbook = create_spellbook(0);
}
spellbook_add(mage->spellbook, sp, level);
}
struct spellbook * unit_get_spellbook(const struct unit * u)
{
sc_mage * mage = get_mage_depr(u);
if (mage) {
if (mage->spellbook) {
return mage->spellbook;
}
if (mage->magietyp != M_GRAY) {
return faction_get_spellbook(u->faction);
}
}
return NULL;
}
int effskill(const unit * u, skill_t sk, const region *r)
{
assert(u);

View File

@ -228,8 +228,6 @@ extern "C" {
int unit_max_hp(const struct unit *u);
void scale_number(struct unit *u, int n);
struct spellbook * unit_get_spellbook(const struct unit * u);
void unit_add_spell(struct unit * u, struct sc_mage * m, struct spell * sp, int level);
void remove_empty_units_in_region(struct region * r);
void remove_empty_units(void);

View File

@ -2419,8 +2419,23 @@ int combatspell_cmd(unit * u, struct order *ord)
}
else {
/* KAMPFZAUBER "<Spruchname>" setzt diesen Kampfzauber */
/* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */
if (!knowsspell(u->region, u, sp)) {
/* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC);
}
else if (!u_hasspell(u, sp)) {
/* Diesen Zauber kennt die Einheit nicht */
cmistake(u, ord, 169, MSG_MAGIC);
}
else if (!(sp->sptyp & ISCOMBATSPELL)) {
/* Diesen Kampfzauber gibt es nicht */
cmistake(u, ord, 171, MSG_MAGIC);
}
else {
set_combatspell(u, sp, ord, level);
}
}
return 0;
}
@ -3169,8 +3184,8 @@ static int faction_getmages(faction * f, unit ** results, int numresults)
for (u = f->units; u; u = u->nextF) {
if (u->number > 0) {
sc_mage *mage = get_mage_depr(u);
if (mage) {
struct sc_mage * mage = get_mage(u);
if (mage && mage_get_spellbook(mage)) {
int level = effskill(u, SK_MAGIC, 0);
if (level > maxlevel) {
maxlevel = level;
@ -3229,11 +3244,12 @@ static void update_spells(void)
unit *mages[MAXMAGES];
int i;
int maxlevel = faction_getmages(f, mages, MAXMAGES);
struct spellbook *fsb;
if (maxlevel && FactionSpells()) {
spellbook * book = get_spellbook(magic_school[f->magiegebiet]);
if (!f->spellbook) {
f->spellbook = create_spellbook(0);
f->spellbook = create_spellbook(NULL);
}
copy_spells(book, f->spellbook, maxlevel);
if (maxlevel > f->max_spelllevel) {
@ -3241,13 +3257,14 @@ static void update_spells(void)
pick_random_spells(f, maxlevel, common_spells, COMMONSPELLS);
}
}
show_new_spells(f, maxlevel, faction_get_spellbook(f));
fsb = faction_get_spellbook(f);
show_new_spells(f, maxlevel, fsb);
for (i = 0; i != MAXMAGES && mages[i]; ++i) {
unit * u = mages[i];
sc_mage *mage = get_mage_depr(u);
if (mage && mage->spellbook) {
int level = effskill(u, SK_MAGIC, 0);
show_new_spells(f, level, mage->spellbook);
spellbook *sb = unit_get_spellbook(u);
if (sb != fsb) {
int level = effskill(u, SK_MAGIC, NULL);
show_new_spells(f, level, sb);
}
}
}

View File

@ -103,6 +103,78 @@ const char *magic_school[MAXMAGIETYP] = {
"common"
};
struct combatspell {
int level;
const struct spell *sp;
};
typedef struct sc_mage {
magic_t magietyp;
int spellpoints;
int spchange;
int spellcount;
struct combatspell combatspells[MAXCOMBATSPELLS];
struct spellbook *spellbook;
} sc_mage;
int mage_get_spellpoints(const sc_mage *m)
{
return m ? m->spellpoints : 0;
}
int mage_change_spellpoints(sc_mage *m, int delta)
{
if (m) {
int val = m->spellpoints + delta;
return m->spellpoints = (val >= 0) ? val : m->spellpoints;
}
return 0;
}
magic_t mage_get_type(const sc_mage *m)
{
return m ? m->magietyp : M_GRAY;
}
const spell *mage_get_combatspell(const sc_mage *mage, int nr, int *level)
{
assert(nr < MAXCOMBATSPELLS);
if (mage) {
if (level) {
*level = mage->combatspells[nr].level;
}
return mage->combatspells[nr].sp;
}
return NULL;
}
void unit_set_magic(struct unit *u, enum magic_t mtype)
{
sc_mage *mage = get_mage(u);
if (mage) {
mage->magietyp = mtype;
}
}
magic_t unit_get_magic(const unit *u)
{
return mage_get_type(get_mage(u));
}
void unit_add_spell(unit * u, struct spell * sp, int level)
{
sc_mage *mage = get_mage(u);
if (!mage) {
log_error("adding new spell %s to a previously non-magical unit %s\n", sp->sname, unitname(u));
mage = create_mage(u, M_GRAY);
}
if (!mage->spellbook) {
mage->spellbook = create_spellbook(0);
}
spellbook_add(mage->spellbook, sp, level);
}
/**
** at_icastle
** TODO: separate castle-appearance from illusion-effects
@ -199,6 +271,23 @@ const building_type *icastle_type(const struct attrib *a) {
extern int dice(int count, int value);
bool FactionSpells(void)
{
static int config, rule;
if (config_changed(&config)) {
rule = config_get_int("rules.magic.factionlist", 0);
}
return rule != 0;
}
int get_spell_level_mage(const spell * sp, void * cbdata)
{
sc_mage *mage = (sc_mage *)cbdata;
spellbook *book = get_spellbook(magic_school[mage->magietyp]);
spellbook_entry *sbe = spellbook_get(book, sp);
return sbe ? sbe->level : 0;
}
/* ------------------------------------------------------------- */
/* aus dem alten System übriggebliegene Funktionen, die bei der
* Umwandlung von alt nach neu gebraucht werden */
@ -219,23 +308,6 @@ static void free_mage(variant *var)
free(mage);
}
bool FactionSpells(void)
{
static int config, rule;
if (config_changed(&config)) {
rule = config_get_int("rules.magic.factionlist", 0);
}
return rule != 0;
}
int get_spell_level_mage(const spell * sp, void * cbdata)
{
sc_mage *mage = (sc_mage *)cbdata;
spellbook *book = get_spellbook(magic_school[mage->magietyp]);
spellbook_entry *sbe = spellbook_get(book, sp);
return sbe ? sbe->level : 0;
}
static int read_mage(variant *var, void *owner, struct gamedata *data)
{
storage *store = data->store;
@ -278,7 +350,7 @@ static int read_mage(variant *var, void *owner, struct gamedata *data)
read_spellbook(&mage->spellbook, data, get_spell_level_mage, mage);
}
else {
read_spellbook(0, data, 0, mage);
read_spellbook(NULL, data, NULL, mage);
}
return AT_READ_OK;
}
@ -312,9 +384,10 @@ attrib_type at_mage = {
ATF_UNIQUE
};
bool is_mage(const unit * u)
bool is_mage(const struct unit * u)
{
return get_mage_depr(u) != NULL;
sc_mage *m = get_mage(u);
return (m && m->magietyp != M_GRAY);
}
sc_mage *get_mage(const unit * u)
@ -326,12 +399,22 @@ sc_mage *get_mage(const unit * u)
return NULL;
}
sc_mage *get_mage_depr(const unit * u)
struct spellbook * mage_get_spellbook(const struct sc_mage * mage) {
if (mage) {
return mage->spellbook;
}
return NULL;
}
struct spellbook * unit_get_spellbook(const struct unit * u)
{
if (has_skill(u, SK_MAGIC)) {
attrib *a = a_find(u->attribs, &at_mage);
if (a) {
return (sc_mage *)a->data.v;
sc_mage * mage = get_mage(u);
if (mage) {
if (mage->spellbook) {
return mage->spellbook;
}
if (mage->magietyp != M_GRAY) {
return faction_get_spellbook(u->faction);
}
}
return NULL;
@ -436,17 +519,15 @@ int u_hasspell(const unit *u, const struct spell *sp)
int get_combatspelllevel(const unit * u, int nr)
{
sc_mage *m = get_mage_depr(u);
assert(nr < MAXCOMBATSPELLS);
if (m) {
int level = effskill(u, SK_MAGIC, 0);
if (level < m->combatspells[nr].level) {
int level;
if (mage_get_combatspell(get_mage(u), nr, &level) != NULL) {
int maxlevel = effskill(u, SK_MAGIC, 0);
if (level > maxlevel) {
return maxlevel;
}
return level;
}
return m->combatspells[nr].level;
}
return -1;
return 0;
}
/* ------------------------------------------------------------- */
@ -454,40 +535,15 @@ int get_combatspelllevel(const unit * u, int nr)
const spell *get_combatspell(const unit * u, int nr)
{
sc_mage *m;
assert(nr < MAXCOMBATSPELLS);
m = get_mage_depr(u);
if (m) {
return m->combatspells[nr].sp;
}
return NULL;
return mage_get_combatspell(get_mage(u), nr, NULL);
}
void set_combatspell(unit * u, spell * sp, struct order *ord, int level)
{
sc_mage *mage = get_mage_depr(u);
sc_mage *mage = get_mage(u);
int i = -1;
assert(mage || !"trying to set a combat spell for non-mage");
/* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */
if (!knowsspell(u->region, u, sp)) {
/* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC);
return;
}
if (!u_hasspell(u, sp)) {
/* Diesen Zauber kennt die Einheit nicht */
cmistake(u, ord, 169, MSG_MAGIC);
return;
}
if (!(sp->sptyp & ISCOMBATSPELL)) {
/* Diesen Kampfzauber gibt es nicht */
cmistake(u, ord, 171, MSG_MAGIC);
return;
}
if (sp->sptyp & PRECOMBATSPELL)
i = 0;
else if (sp->sptyp & COMBATSPELL)
@ -502,13 +558,12 @@ void set_combatspell(unit * u, spell * sp, struct order *ord, int level)
void unset_combatspell(unit * u, spell * sp)
{
sc_mage *m;
int nr = 0;
sc_mage *m = get_mage(u);
m = get_mage_depr(u);
if (!m)
if (!m) {
return;
}
if (!sp) {
int i;
for (i = 0; i < MAXCOMBATSPELLS; i++) {
@ -540,26 +595,15 @@ void unset_combatspell(unit * u, spell * sp)
/* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurück */
int get_spellpoints(const unit * u)
{
sc_mage *m;
m = get_mage_depr(u);
if (!m)
return 0;
return m->spellpoints;
return mage_get_spellpoints(get_mage(u));
}
void set_spellpoints(unit * u, int sp)
{
sc_mage *m;
m = get_mage_depr(u);
if (!m)
return;
sc_mage *m = get_mage(u);
if (m) {
m->spellpoints = sp;
return;
}
}
/*
@ -567,23 +611,7 @@ void set_spellpoints(unit * u, int sp)
*/
int change_spellpoints(unit * u, int mp)
{
sc_mage *m;
int sp;
m = get_mage_depr(u);
if (!m) {
return 0;
}
/* verhindere negative Magiepunkte */
sp = m->spellpoints + mp;
if (sp > 0) {
m->spellpoints = sp;
}
else {
m->spellpoints = 0;
}
return sp;
return mage_change_spellpoints(get_mage(u), mp);
}
/* bietet die Möglichkeit, die maximale Anzahl der Magiepunkte mit
@ -593,11 +621,8 @@ static int get_spchange(const unit * u)
{
sc_mage *m;
m = get_mage_depr(u);
if (!m)
return 0;
return m->spchange;
m = get_mage(u);
return m ? m->spchange : 0;
}
/* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte
@ -645,9 +670,7 @@ int max_spellpoints(const region * r, const unit * u)
int change_maxspellpoints(unit * u, int csp)
{
sc_mage *m;
m = get_mage_depr(u);
sc_mage *m = get_mage(u);
if (!m) {
return 0;
}
@ -660,28 +683,22 @@ int change_maxspellpoints(unit * u, int csp)
*/
int countspells(unit * u, int step)
{
sc_mage *m;
sc_mage * m = get_mage(u);
if (m) {
int count;
m = get_mage_depr(u);
if (!m) {
return 0;
}
if (step == 0) {
return m->spellcount;
}
count = m->spellcount + step;
m->spellcount = (count > 0) ? count : 0;
return m->spellcount;
}
return 0;
}
int spellcount(const unit *u) {
sc_mage *m = get_mage_depr(u);
if (m) {
return m->spellcount;
}
return 0;
sc_mage *m = get_mage(u);
return m ? m->spellcount : 0;
}
/**
@ -2193,18 +2210,67 @@ void remove_familiar(unit * mage)
}
}
void create_newfamiliar(unit * mage, unit * fam)
{
/* skills and spells: */
static void equip_familiar(unit *fam) {
/* items, skills and spells: */
char eqname[64];
const race *rc = u_race(fam);
set_familiar(mage, fam);
snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name);
if (!equip_unit(fam, eqname)) {
log_info("could not perform initialization for familiar %s.\n", rc->_name);
}
}
static int copy_spell_cb(spellbook_entry *sbe, void *udata) {
spellbook *sb = (spellbook *)udata;
spell * sp = spellref_get(&sbe->spref);
if (!spellbook_get(sb, sp)) {
spellbook_add(sb, sp, sbe->level);
}
return 0;
}
/**
* Einmalige Reparatur von Vertrauten (Bugs 2451, 2517).
*/
void fix_fam_mage(unit *u) {
sc_mage *dmage;
unit *du = unit_create(0);
u_setrace(du, u_race(u));
dmage = create_mage(du, M_GRAY);
equip_familiar(du);
if (dmage) {
sc_mage *mage = get_mage(u);
if (!mage) {
mage = create_mage(u, dmage->magietyp);
}
else if (dmage->magietyp != mage->magietyp) {
mage->magietyp = dmage->magietyp;
}
if (dmage->spellbook) {
if (!mage->spellbook) {
mage->spellbook = create_spellbook(NULL);
spellbook_foreach(dmage->spellbook, copy_spell_cb, mage->spellbook);
}
}
else {
if (mage->spellbook) {
spellbook_clear(mage->spellbook);
mage->spellbook = NULL;
}
}
}
free_unit(du);
}
void create_newfamiliar(unit * mage, unit * fam)
{
create_mage(fam, M_GRAY);
set_familiar(mage, fam);
equip_familiar(fam);
/* TODO: Diese Attribute beim Tod des Familiars entfernen: */
/* Wenn der Magier stirbt, dann auch der Vertraute */
add_trigger(&mage->attribs, "destroy", trigger_killunit(fam));

View File

@ -27,18 +27,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" {
#endif
/* ------------------------------------------------------------- */
#define MAXCOMBATSPELLS 3 /* PRECOMBAT COMBAT POSTCOMBAT */
#define MAX_SPELLRANK 9 /* Standard-Rank 5 */
#define MAXINGREDIENT 5 /* bis zu 5 Komponenten pro Zauber */
#define CHAOSPATZERCHANCE 10 /* +10% Chance zu Patzern */
/* ------------------------------------------------------------- */
#define IRONGOLEM_CRUMBLE 15 /* monatlich Chance zu zerfallen */
#define STONEGOLEM_CRUMBLE 10 /* monatlich Chance zu zerfallen */
struct sc_mage;
struct unit;
extern const char *magic_school[MAXMAGIETYP];
extern struct attrib_type at_familiar;
extern struct attrib_type at_familiarmage;
@ -99,26 +97,12 @@ extern "C" {
* - Spruchliste
*/
typedef struct combatspell {
int level;
const struct spell *sp;
} combatspell;
typedef struct spell_names {
struct spell_names *next;
const struct locale *lang;
void * tokens;
} spell_names;
typedef struct sc_mage {
magic_t magietyp;
int spellpoints;
int spchange;
int spellcount;
combatspell combatspells[MAXCOMBATSPELLS];
struct spellbook *spellbook;
} sc_mage;
/* ------------------------------------------------------------- */
/* Zauberliste */
@ -217,12 +201,22 @@ extern "C" {
*/
/* Magier */
sc_mage *create_mage(struct unit *u, magic_t mtyp);
struct sc_mage *create_mage(struct unit *u, magic_t mtyp);
/* macht die struct unit zu einem neuen Magier: legt die struct u->mage an
* und initialisiert den Magiertypus mit mtyp. */
sc_mage *get_mage(const struct unit *u);
sc_mage *get_mage_depr(const struct unit *u);
/* gibt u->mage zurück, bei nicht-Magiern *NULL */
struct sc_mage *get_mage(const struct unit *u);
enum magic_t mage_get_type(const struct sc_mage *mage);
const struct spell *mage_get_combatspell(const struct sc_mage *mage, int nr, int *level);
struct spellbook * mage_get_spellbook(const struct sc_mage * mage);
int mage_get_spellpoints(const struct sc_mage *m);
int mage_change_spellpoints(struct sc_mage *m, int delta);
enum magic_t unit_get_magic(const struct unit *u);
void unit_set_magic(struct unit *u, enum magic_t mtype);
struct spellbook * unit_get_spellbook(const struct unit * u);
void unit_add_spell(struct unit * u, struct spell * sp, int level);
bool is_mage(const struct unit *u);
/* gibt true, wenn u->mage gesetzt. */
bool is_familiar(const struct unit *u);
@ -332,7 +326,8 @@ extern "C" {
void remove_familiar(struct unit *mage);
void create_newfamiliar(struct unit *mage, struct unit *familiar);
void create_newclone(struct unit *mage, struct unit *familiar);
struct unit *has_clone(struct unit *mage);
void fix_fam_mage(struct unit *u);
const char *spell_info(const struct spell *sp,
const struct locale *lang);

View File

@ -117,7 +117,7 @@ void test_pay_spell(CuTest * tc)
CuAssertPtrNotNull(tc, sp);
set_level(u, SK_MAGIC, 5);
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
change_resource(u, get_resourcetype(R_SILVER), 1);
change_resource(u, get_resourcetype(R_AURA), 3);
@ -151,7 +151,7 @@ void test_pay_spell_failure(CuTest * tc)
CuAssertPtrNotNull(tc, sp);
set_level(u, SK_MAGIC, 5);
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
CuAssertIntEquals(tc, 1, change_resource(u, get_resourcetype(R_SILVER), 1));
CuAssertIntEquals(tc, 2, change_resource(u, get_resourcetype(R_AURA), 2));
@ -182,7 +182,7 @@ void test_getspell_unit(CuTest * tc)
r = test_create_region(0, 0, NULL);
f = test_create_faction(NULL);
u = test_create_unit(f, r);
create_mage(u, M_GRAY);
create_mage(u, M_GWYRRD);
enable_skill(SK_MAGIC, true);
set_level(u, SK_MAGIC, 1);
@ -193,7 +193,7 @@ void test_getspell_unit(CuTest * tc)
CuAssertPtrEquals(tc, NULL, unit_getspell(u, "Herp-a-derp", lang));
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
CuAssertPtrNotNull(tc, unit_getspell(u, "Herp-a-derp", lang));
test_teardown();
}
@ -277,7 +277,7 @@ void test_set_pre_combatspell(CuTest * tc)
sp = create_spell("testspell");
sp->sptyp |= PRECOMBATSPELL;
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
set_combatspell(u, sp, 0, 2);
CuAssertPtrEquals(tc, sp, (spell *)get_combatspell(u, index));
@ -309,7 +309,7 @@ void test_set_main_combatspell(CuTest * tc)
sp = create_spell("testspell");
sp->sptyp |= COMBATSPELL;
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
set_combatspell(u, sp, 0, 2);
CuAssertPtrEquals(tc, sp, (spell *)get_combatspell(u, index));
@ -341,7 +341,7 @@ void test_set_post_combatspell(CuTest * tc)
sp = create_spell("testspell");
sp->sptyp |= POSTCOMBATSPELL;
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
set_combatspell(u, sp, 0, 2);
CuAssertPtrEquals(tc, sp, (spell *)get_combatspell(u, index));
@ -371,7 +371,7 @@ void test_hasspell(CuTest * tc)
sp = create_spell("testspell");
sp->sptyp |= POSTCOMBATSPELL;
unit_add_spell(u, 0, sp, 2);
unit_add_spell(u, sp, 2);
set_level(u, SK_MAGIC, 1);
CuAssertTrue(tc, !u_hasspell(u, sp));
@ -407,7 +407,7 @@ void test_multi_cast(CuTest *tc) {
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
set_level(u, SK_MAGIC, 10);
unit_add_spell(u, 0, sp, 1);
unit_add_spell(u, sp, 1);
CuAssertPtrEquals(tc, sp, unit_getspell(u, "Feuerball", lang));
unit_addorder(u, create_order(K_CAST, u->faction->locale, "Feuerball"));
@ -451,7 +451,7 @@ static void test_max_spellpoints(CuTest *tc) {
CuAssertIntEquals(tc, 1, max_spellpoints(u->region, u));
rc->maxaura = 200;
CuAssertIntEquals(tc, 2, max_spellpoints(u->region, u));
create_mage(u, M_GRAY);
create_mage(u, M_GWYRRD);
set_level(u, SK_MAGIC, 1);
CuAssertIntEquals(tc, 3, max_spellpoints(u->region, u));
set_level(u, SK_MAGIC, 2);
@ -485,7 +485,7 @@ static void test_illusioncastle(CuTest *tc)
static void test_is_mage(CuTest *tc) {
unit *u;
sc_mage *mage;
struct sc_mage *mage;
test_setup();
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
@ -502,18 +502,13 @@ static void test_is_mage(CuTest *tc) {
static void test_get_mage(CuTest *tc) {
unit *u;
sc_mage *mage;
struct sc_mage *mage;
test_setup();
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
CuAssertPtrEquals(tc, NULL, get_mage(u));
CuAssertPtrEquals(tc, NULL, get_mage_depr(u));
CuAssertPtrNotNull(tc, mage = create_mage(u, M_CERDDOR));
CuAssertPtrEquals(tc, mage, get_mage(u));
CuAssertPtrEquals(tc, NULL, get_mage_depr(u));
set_level(u, SK_MAGIC, 1);
CuAssertPtrEquals(tc, mage, get_mage(u));
CuAssertPtrEquals(tc, mage, get_mage_depr(u));
test_teardown();
}

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 1998-2014,
Copyright (c) 1998-2018,
Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -1430,9 +1430,10 @@ int movement_speed(const unit * u)
/* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell.
* Nicht kumulativ mit anderen Beschleunigungen! */
if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region)) {
sc_mage *mage = get_mage(u);
if (mage && (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN)) {
if (has_skill(u, SK_MAGIC)) {
struct sc_mage *mage = get_mage(u);
if (mage) {
magic_t mtype = mage_get_type(mage);
if (mtype == M_TYBIED || mtype == M_ILLAUN) {
mp *= 2;
}
}

View File

@ -637,10 +637,10 @@ static size_t spskill(char *buffer, size_t size, const struct locale * lang,
bufp = STRLCPY(bufp, " ", size);
if (sv->id == SK_MAGIC) {
sc_mage *mage = get_mage(u);
if (mage && mage->magietyp != M_GRAY) {
bufp = STRLCPY(bufp, LOC(lang, mkname("school",
magic_school[mage->magietyp])), size);
magic_t mtype = unit_get_magic(u);
if (mtype != M_GRAY) {
bufp = STRLCPY(bufp,
LOC(lang, mkname("school", magic_school[mtype])), size);
bufp = STRLCPY(bufp, " ", size);
}
}

View File

@ -704,13 +704,13 @@ static int sp_destroy_magic(castorder * co)
static int sp_transferaura(castorder * co)
{
int aura, gain, multi = 2;
int aura, used, multi = 2;
unit *caster = co_get_caster(co);
unit *mage = co_get_magician(co);
int cast_level = co->level;
spellparameter *pa = co->par;
unit *u;
sc_mage *scm_dst, *scm_src = get_mage(mage);
struct sc_mage *scm_dst, *scm_src = get_mage(mage);
assert(scm_src);
/* wenn kein Ziel gefunden, Zauber abbrechen */
@ -725,26 +725,30 @@ static int sp_transferaura(castorder * co)
/* Wieviel Transferieren? */
aura = pa->param[1]->data.i;
u = pa->param[0]->data.u;
scm_dst = get_mage_depr(u);
scm_dst = get_mage(u);
if (scm_dst == NULL) {
/* "Zu dieser Einheit kann ich keine Aura uebertragen." */
cmistake(caster, co->order, 207, MSG_MAGIC);
return 0;
}
else if (scm_src->magietyp == M_TYBIED) {
if (scm_src->magietyp != scm_dst->magietyp)
else {
magic_t src = mage_get_type(scm_src);
magic_t dst = mage_get_type(scm_dst);
if (src != dst) {
if (src == M_TYBIED) {
multi = 3;
}
else if (scm_src->magietyp == M_GRAY) {
if (scm_src->magietyp != scm_dst->magietyp)
else if (src == M_GRAY) {
multi = 4;
}
else if (scm_dst->magietyp != scm_src->magietyp) {
else {
/* "Zu dieser Einheit kann ich keine Aura uebertragen." */
cmistake(caster, co->order, 207, MSG_MAGIC);
return 0;
}
}
}
if (aura < multi) {
/* "Auraangabe fehlerhaft." */
@ -752,16 +756,15 @@ static int sp_transferaura(castorder * co)
return 0;
}
gain = scm_src->spellpoints;
if (gain > aura) gain = aura;
gain = gain / multi;
scm_src->spellpoints -= gain * multi;
scm_dst->spellpoints += gain;
used = mage_get_spellpoints(scm_src);
if (used > aura) used = aura;
mage_change_spellpoints(scm_src, -used);
mage_change_spellpoints(scm_dst, used / multi);
/* sprintf(buf, "%s transferiert %d Aura auf %s", unitname(mage),
gain, unitname(u)); */
ADDMSG(&caster->faction->msgs, msg_message("auratransfer_success",
"unit target aura", caster, u, gain));
"unit target aura", caster, u, used));
return cast_level;
}
@ -5748,14 +5751,6 @@ static int sp_eternizewall(castorder * co)
return cast_level;
}
static magic_t get_magic_type(const struct unit *u) {
sc_mage *mage = get_mage(u);
if (mage) {
return mage->magietyp;
}
return M_GRAY;
}
/* ------------------------------------------------------------- */
/* Name: Opfere Kraft
* Stufe: 15
@ -5810,7 +5805,7 @@ int sp_permtransfer(castorder * co)
change_maxspellpoints(mage, -aura);
change_spellpoints(mage, -aura);
if (get_magic_type(tu) == get_magic_type(mage)) {
if (unit_get_magic(tu) == unit_get_magic(mage)) {
change_maxspellpoints(tu, aura / 2);
}
else {
@ -5925,6 +5920,7 @@ int sp_stealaura(castorder * co)
int cast_level = co->level;
double power = co->force;
spellparameter *pa = co->par;
struct sc_mage *scm;
/* wenn kein Ziel gefunden, Zauber abbrechen */
if (pa->param[0]->flag == TARGET_NOTFOUND)
@ -5933,17 +5929,18 @@ int sp_stealaura(castorder * co)
/* Zieleinheit */
u = pa->param[0]->data.u;
if (!get_mage_depr(u)) {
scm = get_mage(u);
if (!scm) {
ADDMSG(&caster->faction->msgs, msg_message("stealaura_fail", "unit target",
caster, u));
ADDMSG(&u->faction->msgs, msg_message("stealaura_fail_detect", "unit", u));
return 0;
}
taura = (get_mage_depr(u)->spellpoints * (rng_int() % (int)(3 * power) + 1)) / 100;
taura = (mage_get_spellpoints(scm) * (rng_int() % (int)(3 * power) + 1)) / 100;
if (taura > 0) {
change_spellpoints(u, -taura);
mage_change_spellpoints(scm, -taura);
change_spellpoints(mage, taura);
/* sprintf(buf, "%s entzieht %s %d Aura.", unitname(mage), unitname(u),
taura); */

View File

@ -72,11 +72,11 @@ void spy_message(int spy, const unit * u, const unit * target)
ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u,
target, status));
if (spy > 20) {
sc_mage *mage = get_mage_depr(target);
magic_t mtype = unit_get_magic(target);
/* for mages, spells and magic school */
if (mage) {
if (mtype != M_GRAY) {
ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "spy target type", u,
target, magic_school[mage->magietyp]));
target, magic_school[mtype]));
}
}
if (spy > 6) {

View File

@ -420,10 +420,10 @@ int teach_cmd(unit * teacher, struct order *ord)
if (sk == SK_MAGIC) {
/* ist der Magier schon spezialisiert, so versteht er nur noch
* Lehrer seines Gebietes */
sc_mage *mage1 = get_mage_depr(teacher);
sc_mage *mage2 = get_mage_depr(scholar);
if (mage2 && mage1 && mage2->magietyp != M_GRAY
&& mage1->magietyp != mage2->magietyp) {
magic_t mage2 = unit_get_magic(scholar);
if (mage2 != M_GRAY) {
magic_t mage1 = unit_get_magic(teacher);
if (mage1 != mage2) {
if (feedback) {
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord,
"error_different_magic", "target", scholar));
@ -431,6 +431,7 @@ int teach_cmd(unit * teacher, struct order *ord)
continue;
}
}
}
sk_academy = sk;
teaching -= teach_unit(teacher, scholar, teaching, sk, false, &academy_students);
}
@ -622,7 +623,7 @@ int study_cmd(unit * u, order * ord)
}
if (sk == SK_MAGIC) {
magic_t mtyp;
magic_t mtype;
if (u->number > 1) {
cmistake(u, ord, 106, MSG_MAGIC);
return -1;
@ -630,7 +631,7 @@ int study_cmd(unit * u, order * ord)
if (is_familiar(u)) {
/* Vertraute zaehlen nicht zu den Magiern einer Partei,
* koennen aber nur Graue Magie lernen */
mtyp = M_GRAY;
mtype = M_GRAY;
}
else if (!has_skill(u, SK_MAGIC)) {
int mmax = skill_limit(u->faction, SK_MAGIC);
@ -640,24 +641,24 @@ int study_cmd(unit * u, order * ord)
"amount", mmax));
return -1;
}
mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE || mtyp == M_GRAY) {
mtype = getmagicskill(u->faction->locale);
if (mtype == M_NONE || mtype == M_GRAY) {
/* wurde kein Magiegebiet angegeben, wird davon
* ausgegangen, dass das normal gelernt werden soll */
if (u->faction->magiegebiet != 0) {
mtyp = u->faction->magiegebiet;
mtype = u->faction->magiegebiet;
}
else {
/* Es wurde kein Magiegebiet angegeben und die Partei
* hat noch keins gewaehlt. */
mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE) {
mtype = getmagicskill(u->faction->locale);
if (mtype == M_NONE) {
cmistake(u, ord, 178, MSG_MAGIC);
return -1;
}
}
}
if (mtyp != u->faction->magiegebiet) {
if (mtype != u->faction->magiegebiet) {
/* Es wurde versucht, ein anderes Magiegebiet zu lernen
* als das der Partei */
if (u->faction->magiegebiet != 0) {
@ -667,25 +668,25 @@ int study_cmd(unit * u, order * ord)
else {
/* Lernt zum ersten mal Magie und legt damit das
* Magiegebiet der Partei fest */
u->faction->magiegebiet = mtyp;
u->faction->magiegebiet = mtype;
}
}
create_mage(u, mtyp);
create_mage(u, mtype);
}
else {
/* ist schon ein Magier und kein Vertrauter */
if (u->faction->magiegebiet == 0) {
/* die Partei hat noch kein Magiegebiet gewaehlt. */
mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE) {
mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE) {
mtype = getmagicskill(u->faction->locale);
if (mtype == M_NONE) {
mtype = getmagicskill(u->faction->locale);
if (mtype == M_NONE) {
cmistake(u, ord, 178, MSG_MAGIC);
return -1;
}
}
/* Legt damit das Magiegebiet der Partei fest */
u->faction->magiegebiet = mtyp;
u->faction->magiegebiet = mtype;
}
}
}

View File

@ -429,9 +429,9 @@ static void test_study_magic(CuTest *tc) {
CuAssertIntEquals(tc, 0, study_cmd(u, u->thisorder));
CuAssertIntEquals(tc, M_GWYRRD, f->magiegebiet);
CuAssertIntEquals(tc, 0, i_get(u->items, itype));
CuAssertPtrNotNull(tc, get_mage_depr(u));
CuAssertPtrNotNull(tc, get_mage(u));
CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "error65"));
CuAssertIntEquals(tc, M_GWYRRD, get_mage_depr(u)->magietyp);
CuAssertIntEquals(tc, M_GWYRRD, unit_get_magic(u));
test_teardown();
}

View File

@ -23,7 +23,7 @@ static void test_shock(CuTest *tc) {
test_setup();
shock_setup();
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
create_mage(u, M_GRAY);
create_mage(u, M_GWYRRD);
set_level(u, SK_MAGIC, 5);
set_spellpoints(u, 10);
u->hp = 10;
@ -44,7 +44,7 @@ static void test_shock_low(CuTest *tc) {
test_setup();
shock_setup();
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
create_mage(u, M_GRAY);
create_mage(u, M_GWYRRD);
set_level(u, SK_MAGIC, 5);
set_spellpoints(u, 1);
u->hp = 1;