diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 44d781db3..9e1a7bfca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -177,8 +177,9 @@ set(TESTS_SRC market.test.c move.test.c skill.test.c - upkeep.test.c + spells.test.c spy.test.c + upkeep.test.c ${ATTRIBUTES_TESTS} ${UTIL_TESTS} ${KERNEL_TESTS} diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 27188e2ce..89ce3ae3f 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -117,6 +117,8 @@ int curse_age(attrib * a) curse *c = (curse *)a->data.v; int result = 0; + c_clearflag(c, CURSE_ISNEW); + if (c_flags(c) & CURSE_NOAGE) { c->duration = INT_MAX; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 0c6fcedd1..9906bc4aa 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1274,7 +1274,22 @@ static int item_modification(const unit * u, skill_t sk, int val) return val; } -static int att_modification(const unit * u, skill_t sk) +static int update_gbdream(const unit * u, int bonus, curse *c, const curse_type *gbdream_ct, int sign){ + if (curse_active(c) && c->type == gbdream_ct) { + double effect = curse_geteffect(c); + unit *mage = c->magician; + /* wir suchen jeweils den groessten Bonus und den groestsen Malus */ + if (sign * effect > sign * bonus) { + if (mage == NULL || mage->number == 0 + || sign>0?alliedunit(mage, u->faction, HELP_GUARD):!alliedunit(mage, u->faction, HELP_GUARD)) { + bonus = effect; + } + } + } + return bonus; +} + +int att_modification(const unit * u, skill_t sk) { double result = 0; static bool init = false; @@ -1311,22 +1326,10 @@ static int att_modification(const unit * u, skill_t sk) 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 groesten Bonus und den groesten 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; - } - } - } + + bonus = update_gbdream(u, bonus, c, gbdream_ct, 1); + malus = update_gbdream(u, malus, c, gbdream_ct, -1); + a = a->next; } result = result + bonus + malus; diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 9583ce9bd..7f281fc36 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -1,13 +1,20 @@ #include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "alchemy.h" -#include "faction.h" +#include +#include +#include +#include +#include #include "unit.h" -#include "item.h" -#include "race.h" -#include "region.h" #include #include @@ -232,6 +239,7 @@ static void test_default_name(CuTest *tc) { test_cleanup(); } + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); diff --git a/src/spells.c b/src/spells.c index 0826c7edf..3df54e2de 100644 --- a/src/spells.c +++ b/src/spells.c @@ -4645,6 +4645,8 @@ int sp_analysedream(castorder * co) return cast_level; } +static int sp_gbdreams(castorder * co, const char *curse_name, int effect); + /* ------------------------------------------------------------- */ /* Name: Schlechte Traeume * Stufe: 10 @@ -4660,28 +4662,7 @@ int sp_analysedream(castorder * co) * */ int sp_baddreams(castorder * co) { - int duration; - unit *mage = co->magician.u; - int cast_level = co->level; - float power = co->force; - region *r = co_get_region(co); - curse *c; - float effect; - - /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, - * also duration+2 */ - duration = (int)_max(1, power / 2); /* Stufe 1 macht sonst mist */ - duration = 2 + rng_int() % duration; - - /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ - effect = -1; - c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, effect, 0); - - /* Erfolg melden */ - ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", - "unit region command", c->magician, mage->region, co->order)); - - return cast_level; + return sp_gbdreams(co, "gbdream", -1); } /* ------------------------------------------------------------- */ @@ -4697,21 +4678,26 @@ int sp_baddreams(castorder * co) * (FARCASTING | SPELLLEVEL | REGIONSPELL | TESTRESISTANCE) */ int sp_gooddreams(castorder * co) +{ + return sp_gbdreams(co, "gbdream", 1); +} + +static int sp_gbdreams(castorder * co, const char *curse_name, int effect) { int duration; - curse *c; - region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; float power = co->force; - float effect; + region *r = co_get_region(co); + curse *c; /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, * also duration+2 */ duration = (int)_max(1, power / 2); /* Stufe 1 macht sonst mist */ duration = 2 + rng_int() % duration; - effect = 1; - c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, effect, 0); + + /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ + c = create_curse(mage, &r->attribs, ct_find(curse_name), power, duration, effect, 0); /* Erfolg melden */ ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", diff --git a/src/spells.h b/src/spells.h index a23558e96..65270a164 100644 --- a/src/spells.h +++ b/src/spells.h @@ -14,6 +14,10 @@ #ifndef H_SPL_SPELLS #define H_SPL_SPELLS + +#include "magic.h" + + #ifdef __cplusplus extern "C" { #endif @@ -26,6 +30,9 @@ extern "C" { void register_spells(void); void set_spelldata(struct spell *sp); + int sp_baddreams(castorder * co); + int sp_gooddreams(castorder * co); + #define ACTION_RESET 0x01 /* reset the one-time-flag FFL_SELECT (on first pass) */ #define ACTION_CANSEE 0x02 /* to people who can see the actor */ #define ACTION_CANNOTSEE 0x04 /* to people who can not see the actor */ diff --git a/src/spells.test.c b/src/spells.test.c new file mode 100644 index 000000000..ff67dd58d --- /dev/null +++ b/src/spells.test.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "spells.h" + +#include +#include + +#include +#include +#include +#include + + +static struct castorder *test_create_castorder(castorder *order, unit *u, const char *name, int level, float force, int range) { + struct locale * lang; + spell *sp; + + lang = get_or_create_locale("en"); + sp = create_spell(name, 0); + return order = create_castorder(order, u, NULL, sp, u->region, level, force, range, create_order(K_CAST, lang, ""), NULL); +} + +static void test_dreams(CuTest *tc) { + struct region *r; + struct faction *f1, *f2; + unit *u1, *u2; + int level; + castorder order; + + test_cleanup(); + test_create_world(); + r=findregion(0, 0); + f1 = test_create_faction(test_create_race("human")); + f2 = test_create_faction(test_create_race("human")); + u1 = test_create_unit(f1, r); + u2 = test_create_unit(f2, r); + + test_create_castorder(&order, u1, "goodreams", 10, 10., 0); + level = sp_gooddreams(&order); + CuAssertIntEquals(tc, 10, level); + + curse *curse = get_curse(r->attribs, ct_find("gbdream")); + CuAssertTrue(tc, curse && curse->duration > 1); + CuAssertTrue(tc, curse->effect == 1); + + a_age(&r->attribs); + + CuAssertIntEquals(tc, 1, get_modifier(u1, SK_MELEE, 11, r, false)); + CuAssertIntEquals(tc, 0, get_modifier(u2, SK_MELEE, 11, r, false)); + + test_create_castorder(&order, u1, "baddreams", 10, 10., 0); + level = sp_baddreams(&order); + CuAssertIntEquals(tc, 10, level); + + a_age(&r->attribs); + + CuAssertIntEquals(tc, 1, get_modifier(u1, SK_MELEE, 11, r, false)); + CuAssertIntEquals(tc, -1, get_modifier(u2, SK_MELEE, 11, r, false)); + + free_castorder(&order); + test_cleanup(); +} + +CuSuite *get_spells_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_dreams); + return suite; +} diff --git a/src/test_eressea.c b/src/test_eressea.c index 5f6d380e7..9c8cfa8bc 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -71,6 +71,7 @@ int RunAllTests(void) RUN_TESTS(suite, spellbook); RUN_TESTS(suite, building); RUN_TESTS(suite, spell); + RUN_TESTS(suite, spells); RUN_TESTS(suite, ally); RUN_TESTS(suite, messages); /* gamecode */