Merge pull request #720 from ennorehling/hotfix/bug-2356-curse-flags

BUG 2356: Mauern der Ewigkeit
This commit is contained in:
Enno Rehling 2017-08-18 19:54:05 +02:00 committed by GitHub
commit b8e755c023
16 changed files with 45 additions and 48 deletions

View File

@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <attributes/racename.h> #include <attributes/racename.h>
#include <attributes/otherfaction.h> #include <attributes/otherfaction.h>
#include <attributes/moved.h> #include <attributes/moved.h>
#include <spells/buildingcurse.h>
/* util includes */ /* util includes */
#include <util/assert.h> #include <util/assert.h>
@ -1905,9 +1906,7 @@ int skilldiff(troop at, troop dt, int dist)
skdiff -= beff; skdiff -= beff;
is_protected = 2; is_protected = 2;
if (b->attribs) { if (b->attribs) {
const curse_type *magicwalls_ct = ct_find("magicwalls"); if (curse_active(get_curse(b->attribs, &ct_magicwalls))) {
if (magicwalls_ct
&& curse_active(get_curse(b->attribs, magicwalls_ct))) {
/* Verdoppelt Burgenbonus */ /* Verdoppelt Burgenbonus */
skdiff -= beff; skdiff -= beff;
} }

View File

@ -11,6 +11,9 @@
#include <kernel/race.h> #include <kernel/race.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <spells/buildingcurse.h>
#include <util/functions.h> #include <util/functions.h>
#include <CuTest.h> #include <CuTest.h>
@ -463,12 +466,11 @@ static void test_battle_skilldiff_building(CuTest *tc)
unit *ua, *ud; unit *ua, *ud;
battle *b = NULL; battle *b = NULL;
building_type *btype; building_type *btype;
const curse_type *strongwall_ct, *magicwalls_ct; const curse_type *strongwall_ct;
test_setup(); test_setup();
btype = setup_castle(); btype = setup_castle();
strongwall_ct = ct_find("strongwall"); strongwall_ct = ct_find("strongwall");
magicwalls_ct = ct_find("magicwalls");
r = test_create_region(0, 0, 0); r = test_create_region(0, 0, 0);
ud = test_create_unit(test_create_faction(0), r); ud = test_create_unit(test_create_faction(0), r);
@ -484,7 +486,7 @@ static void test_battle_skilldiff_building(CuTest *tc)
ud->building->size = 10; ud->building->size = 10;
CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0)); CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0));
create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1); create_curse(NULL, &ud->building->attribs, &ct_magicwalls, 1, 1, 1, 1);
CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0)); CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0));
create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1); create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1);

View File

@ -22,6 +22,7 @@
#include <kernel/unit.h> #include <kernel/unit.h>
#include <attributes/fleechance.h> #include <attributes/fleechance.h>
#include <spells/shipcurse.h>
/* triggers includes */ /* triggers includes */
#include <triggers/changerace.h> #include <triggers/changerace.h>
@ -88,7 +89,6 @@ static int
use_speedsail(struct unit *u, const struct item_type *itype, int amount, use_speedsail(struct unit *u, const struct item_type *itype, int amount,
struct order *ord) struct order *ord)
{ {
curse *c;
double effect; double effect;
ship *sh = u->ship; ship *sh = u->ship;
if (!sh) { if (!sh) {
@ -97,9 +97,7 @@ struct order *ord)
} }
effect = SPEEDSAIL_EFFECT; effect = SPEEDSAIL_EFFECT;
c = create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX, create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, effect, 0);
effect, 0);
c_setflag(c, CURSE_NOAGE);
ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u, ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u,
SPEEDSAIL_EFFECT)); SPEEDSAIL_EFFECT));

View File

@ -61,14 +61,14 @@ static curse *cursehash[MAXENTITYHASH];
void c_setflag(curse * c, unsigned int flags) void c_setflag(curse * c, unsigned int flags)
{ {
assert(c); assert(c);
c->flags = (c->flags & ~flags) | (flags & (c->type->flags ^ flags)); c->mask = (c->mask & ~flags) | (flags & (c->type->flags ^ flags));
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
void c_clearflag(curse * c, unsigned int flags) void c_clearflag(curse * c, unsigned int flags)
{ {
assert(c); assert(c);
c->flags = (c->flags & ~flags) | (c->type->flags & flags); c->mask = (c->mask & ~flags) | (c->type->flags & flags);
} }
void chash(curse * c) void chash(curse * c)
@ -180,14 +180,13 @@ int curse_read(attrib * a, void *owner, gamedata *data)
int ur; int ur;
char cursename[64]; char cursename[64];
int n; int n;
int flags;
float flt; float flt;
assert(!c->no); assert(!c->no);
READ_INT(store, &c->no); READ_INT(store, &c->no);
chash(c); chash(c);
READ_TOK(store, cursename, sizeof(cursename)); READ_TOK(store, cursename, sizeof(cursename));
READ_INT(store, &flags); READ_INT(store, &c->mask);
READ_INT(store, &c->duration); READ_INT(store, &c->duration);
READ_FLT(store, &flt); READ_FLT(store, &flt);
c->vigour = flt; c->vigour = flt;
@ -214,7 +213,6 @@ int curse_read(attrib * a, void *owner, gamedata *data)
assert(result == 0); assert(result == 0);
return AT_READ_FAIL; return AT_READ_FAIL;
} }
c->flags = flags;
if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) { if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) {
c_clearflag(c, CURSE_ISNEW); c_clearflag(c, CURSE_ISNEW);
} }
@ -239,21 +237,13 @@ int curse_read(attrib * a, void *owner, gamedata *data)
void curse_write(const attrib * a, const void *owner, struct storage *store) void curse_write(const attrib * a, const void *owner, struct storage *store)
{ {
unsigned int flags;
curse *c = (curse *)a->data.v; curse *c = (curse *)a->data.v;
const curse_type *ct = c->type; const curse_type *ct = c->type;
unit *mage = (c->magician && c->magician->number) ? c->magician : NULL; unit *mage = (c->magician && c->magician->number) ? c->magician : NULL;
/* copied from c_clearflag */
#if RELEASE_VERSION < EXPLICIT_CURSE_ISNEW_VERSION
flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW);
#else
flags = c->flags | c->type->flags;
#endif
WRITE_INT(store, c->no); WRITE_INT(store, c->no);
WRITE_TOK(store, ct->cname); WRITE_TOK(store, ct->cname);
WRITE_INT(store, flags); WRITE_INT(store, c->mask);
WRITE_INT(store, c->duration); WRITE_INT(store, c->duration);
WRITE_FLT(store, (float)c->vigour); WRITE_FLT(store, (float)c->vigour);
write_unit_reference(mage, store); write_unit_reference(mage, store);
@ -306,6 +296,7 @@ void ct_register(const curse_type * ct)
selist **ctlp = cursetypes + hash; selist **ctlp = cursetypes + hash;
assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0); assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0);
assert((ct->flags&CURSE_ISNEW) == 0);
selist_set_insert(ctlp, (void *)ct, NULL); selist_set_insert(ctlp, (void *)ct, NULL);
++ct_changes; ++ct_changes;
} }
@ -553,7 +544,7 @@ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct,
c = (curse *)a->data.v; c = (curse *)a->data.v;
c->type = ct; c->type = ct;
c->flags = 0; c->mask = 0;
c->vigour = vigour; c->vigour = vigour;
c->duration = duration; c->duration = duration;
c->effect = effect; c->effect = effect;
@ -638,7 +629,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n)
bool dogive = false; bool dogive = false;
const curse_type *ct = c->type; const curse_type *ct = c->type;
switch ((ct->flags | c->flags) & CURSE_SPREADMASK) { switch (c_flags(c) & CURSE_SPREADMASK) {
case CURSE_SPREADALWAYS: case CURSE_SPREADALWAYS:
dogive = true; dogive = true;
men = u2->number + n; men = u2->number + n;
@ -671,7 +662,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n)
if (dogive) { if (dogive) {
curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour, curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour,
c->duration, c->effect, men); c->duration, c->effect, men);
cnew->flags = c->flags; cnew->mask = c->mask;
if (ct->typ == CURSETYP_UNIT) if (ct->typ == CURSETYP_UNIT)
set_cursedmen(cnew, men); set_cursedmen(cnew, men);

View File

@ -187,7 +187,7 @@ extern "C" {
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Allgemeine Zauberwirkungen */ /* Allgemeine Zauberwirkungen */
#define c_flags(c) ((c)->type->flags ^ (c)->flags) #define c_flags(c) ((c)->type->flags ^ (c)->mask)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -215,7 +215,7 @@ extern "C" {
double vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */ double vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */
double effect; double effect;
int no; /* 'Einheitennummer' dieses Curse */ int no; /* 'Einheitennummer' dieses Curse */
int flags; /* WARNING: these are XORed with type->flags! */ int mask; /* This is XORed with type->flags, see c_flags()! */
int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */ int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */
} curse; } curse;

View File

@ -106,7 +106,7 @@ static void test_memstream(CuTest *tc) {
storage store; storage store;
stream out = { 0 }; stream out = { 0 };
char buf[1024]; char buf[1024];
int val=0; int val = 0;
mstream_init(&out); mstream_init(&out);
binstore_init(&store, &out); binstore_init(&store, &out);
@ -137,11 +137,13 @@ static void test_write_flag(CuTest *tc) {
mstream_init(&data.strm); mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION); gamedata_init(&data, &store, RELEASE_VERSION);
setup_curse(&fix, "gbdream"); setup_curse(&fix, "magicwalls");
c = fix.c; c = fix.c;
r = fix.r; r = fix.r;
uid = r->uid; uid = r->uid;
c->flags = CURSE_ISNEW; c_setflag(c, CURSE_ISNEW);
c_setflag(c, CURSE_IMMUNE);
CuAssertIntEquals(tc, c->type->flags | CURSE_IMMUNE | CURSE_ISNEW, c_flags(c));
write_game(&data); write_game(&data);
free_gamedata(); free_gamedata();
data.strm.api->rewind(data.strm.handle); data.strm.api->rewind(data.strm.handle);
@ -150,7 +152,7 @@ static void test_write_flag(CuTest *tc) {
CuAssertPtrNotNull(tc, r); CuAssertPtrNotNull(tc, r);
CuAssertPtrNotNull(tc, r->attribs); CuAssertPtrNotNull(tc, r->attribs);
c = (curse *)r->attribs->data.v; c = (curse *)r->attribs->data.v;
CuAssertIntEquals(tc, CURSE_ISNEW, c->flags); CuAssertIntEquals(tc, c->type->flags | CURSE_IMMUNE | CURSE_ISNEW, c_flags(c));
mstream_done(&data.strm); mstream_done(&data.strm);
gamedata_done(&data); gamedata_done(&data);
@ -160,7 +162,7 @@ static void test_write_flag(CuTest *tc) {
static void test_curse_cache(CuTest *tc) static void test_curse_cache(CuTest *tc)
{ {
int cache = 0; int cache = 0;
const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL };
test_setup(); test_setup();
CuAssertIntEquals(tc, true, ct_changed(&cache)); CuAssertIntEquals(tc, true, ct_changed(&cache));
CuAssertIntEquals(tc, false, ct_changed(&cache)); CuAssertIntEquals(tc, false, ct_changed(&cache));

View File

@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/xml.h> #include <util/xml.h>
#include <attributes/movement.h> #include <attributes/movement.h>
#include <spells/shipcurse.h>
#include <storage.h> #include <storage.h>
#include <selist.h> #include <selist.h>
@ -365,7 +366,7 @@ int shipspeed(const ship * sh, const unit * u)
a = a->next; a = a->next;
} }
c = get_curse(sh->attribs, ct_find("shipspeedup")); c = get_curse(sh->attribs, &ct_shipspeedup);
while (c) { while (c) {
k += curse_geteffect_int(c); k += curse_geteffect_int(c);
c = c->nexthash; c = c->nexthash;

View File

@ -462,7 +462,7 @@ static void test_shipspeed_shipspeedup(CuTest *tc) {
register_shipcurse(); register_shipcurse();
assert(sh && cap && crew); assert(sh && cap && crew);
create_curse(0, &sh->attribs, ct_find("shipspeedup"), 1, 1, 3, 0); create_curse(0, &sh->attribs, &ct_shipspeedup, 1, 1, 3, 0);
CuAssertIntEquals_Msg(tc, "shipspeedup adds effect to range", sh->type->range + 3, shipspeed(sh, cap)); CuAssertIntEquals_Msg(tc, "shipspeedup adds effect to range", sh->type->range + 3, shipspeed(sh, cap));
test_cleanup(); test_cleanup();
} }

View File

@ -70,6 +70,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <attributes/racename.h> #include <attributes/racename.h>
#include <attributes/raceprefix.h> #include <attributes/raceprefix.h>
#include <attributes/stealth.h> #include <attributes/stealth.h>
#include <spells/buildingcurse.h>
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
@ -3885,7 +3886,6 @@ int siege_cmd(unit * u, order * ord)
building *b; building *b;
int d, pooled; int d, pooled;
int bewaffnete, katapultiere = 0; int bewaffnete, katapultiere = 0;
const curse_type *magicwalls_ct;
resource_type *rt_catapultammo = NULL; resource_type *rt_catapultammo = NULL;
resource_type *rt_catapult = NULL; resource_type *rt_catapult = NULL;
@ -3904,7 +3904,6 @@ int siege_cmd(unit * u, order * ord)
} }
/* schaden durch katapulte */ /* schaden durch katapulte */
magicwalls_ct = ct_find("magicwalls");
rt_catapultammo = rt_find("catapultammo"); rt_catapultammo = rt_find("catapultammo");
rt_catapult = rt_find("catapult"); rt_catapult = rt_find("catapult");
@ -3945,7 +3944,7 @@ int siege_cmd(unit * u, order * ord)
d = MIN(d, b->size - 1); d = MIN(d, b->size - 1);
/* meldung, schaden anrichten */ /* meldung, schaden anrichten */
if (d && !curse_active(get_curse(b->attribs, magicwalls_ct))) { if (d && !curse_active(get_curse(b->attribs, &ct_magicwalls))) {
b->size -= d; b->size -= d;
use_pooled(u, rt_catapultammo, use_pooled(u, rt_catapultammo,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d); GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d);

View File

@ -2072,7 +2072,7 @@ static int sp_homestone(castorder * co)
return 0; return 0;
} }
c = create_curse(mage, &mage->building->attribs, ct_find("magicwalls"), c = create_curse(mage, &mage->building->attribs, &ct_magicwalls,
force * force, 1, zero_effect, 0); force * force, 1, zero_effect, 0);
if (c == NULL) { if (c == NULL) {

View File

@ -75,7 +75,7 @@ CURSETYP_NORM, 0, M_SUMEFFECT, cinfo_magicrunes
}; };
/* Heimstein-Zauber */ /* Heimstein-Zauber */
static struct curse_type ct_magicwalls = { "magicwalls", const struct curse_type ct_magicwalls = { "magicwalls",
CURSETYP_NORM, CURSE_ONLYONE|CURSE_NOAGE, NO_MERGE, cinfo_building CURSETYP_NORM, CURSE_ONLYONE|CURSE_NOAGE, NO_MERGE, cinfo_building
}; };

View File

@ -21,6 +21,9 @@ extern "C" {
struct locale; struct locale;
struct curse; struct curse;
struct message; struct message;
struct curse_type;
extern const struct curse_type ct_magicwalls;
extern void register_buildingcurse(void); extern void register_buildingcurse(void);
struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self); struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self);

View File

@ -57,7 +57,7 @@ static message *cinfo_cursed_by_the_gods(const void *obj, objtype_t typ,
static struct curse_type ct_godcursezone = { static struct curse_type ct_godcursezone = {
"godcursezone", "godcursezone",
CURSETYP_NORM, CURSE_IMMUNE | CURSE_ISNEW, (NO_MERGE), CURSETYP_NORM, CURSE_IMMUNE, (NO_MERGE),
cinfo_cursed_by_the_gods, cinfo_cursed_by_the_gods,
}; };
@ -83,7 +83,7 @@ static message *cinfo_dreamcurse(const void *obj, objtype_t typ, const curse * c
static struct curse_type ct_gbdream = { static struct curse_type ct_gbdream = {
"gbdream", "gbdream",
CURSETYP_NORM, CURSE_ISNEW, (NO_MERGE), cinfo_dreamcurse CURSETYP_NORM, 0, (NO_MERGE), cinfo_dreamcurse
}; };
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -196,7 +196,7 @@ static struct curse_type ct_fogtrap = {
static struct curse_type ct_maelstrom = { static struct curse_type ct_maelstrom = {
"maelstrom", "maelstrom",
CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR),
cinfo_simple cinfo_simple
}; };
@ -214,7 +214,7 @@ static struct curse_type ct_drought = {
static struct curse_type ct_badlearn = { static struct curse_type ct_badlearn = {
"badlearn", "badlearn",
CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR),
cinfo_simple cinfo_simple
}; };

View File

@ -73,14 +73,14 @@ static message *cinfo_shipnodrift(const void *obj, objtype_t typ, const curse *
} }
static struct curse_type ct_stormwind = { "stormwind", static struct curse_type ct_stormwind = { "stormwind",
CURSETYP_NORM, 0, NO_MERGE, cinfo_ship CURSETYP_NORM, CURSE_NOAGE, NO_MERGE, cinfo_ship
}; };
static struct curse_type ct_nodrift = { "nodrift", static struct curse_type ct_nodrift = { "nodrift",
CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_shipnodrift CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_shipnodrift
}; };
static struct curse_type ct_shipspeedup = { "shipspeedup", const struct curse_type ct_shipspeedup = { "shipspeedup",
CURSETYP_NORM, 0, 0, cinfo_ship CURSETYP_NORM, 0, 0, cinfo_ship
}; };

View File

@ -22,6 +22,8 @@ extern "C" {
struct message; struct message;
struct curse; struct curse;
extern const struct curse_type ct_shipspeedup;
struct message *cinfo_ship(const void *obj, objtype_t typ, struct message *cinfo_ship(const void *obj, objtype_t typ,
const struct curse *c, int self); const struct curse *c, int self);
void register_shipcurse(void); void register_shipcurse(void);

View File

@ -170,7 +170,7 @@ message *cinfo_unit(const void *obj, objtype_t typ, const curse * c, int self)
static struct curse_type ct_orcish = { static struct curse_type ct_orcish = {
"orcish", "orcish",
CURSETYP_UNIT, CURSE_SPREADMODULO | CURSE_ISNEW, M_MEN, CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN,
cinfo_unit cinfo_unit
}; };