avoid units with multiple changerace triggers

This commit is contained in:
Enno Rehling 2021-06-19 19:12:48 +02:00
parent 6cac6439bf
commit b6d5b729bf
13 changed files with 99 additions and 46 deletions

View File

@ -59,13 +59,15 @@ int read_triggers(struct gamedata *data, trigger ** tp)
return 0; return 0;
} }
trigger *t_new(trigger_type * ttype) trigger *t_new(trigger_type *ttype)
{ {
trigger *t = calloc(1, sizeof(trigger)); trigger *t = calloc(1, sizeof(trigger));
if (!t) abort(); if (t) {
t->type = ttype; t->type = ttype;
if (ttype->initialize) if (ttype->initialize) {
ttype->initialize(t); ttype->initialize(t);
}
}
return t; return t;
} }

View File

@ -4551,7 +4551,7 @@ int sp_illusionary_shapeshift(castorder * co)
return 0; return 0;
} }
if (NULL == change_race(u, 3 + (int)power, NULL, irace)) { if (NULL == change_race(u, 3 + (int)power, NULL, rc)) {
ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order,
"sp_shapeshift_fail", "target race", u, rc)); "sp_shapeshift_fail", "target race", u, rc));
return 0; return 0;

View File

@ -286,23 +286,43 @@ static void test_watch_region(CuTest *tc) {
static void test_change_race(CuTest *tc) { static void test_change_race(CuTest *tc) {
unit *u; unit *u;
race *rctoad; race *rctoad, *rcsmurf;
trigger **tp, *tr; trigger **tp, *tr;
timeout_data *td; timeout_data *td;
changerace_data *crd; changerace_data *crd;
test_setup(); test_setup();
rctoad = test_create_race("toad"); rctoad = test_create_race("toad");
rcsmurf = test_create_race("smurf");
u = test_create_unit(test_create_faction(), test_create_plain(0, 0)); u = test_create_unit(test_create_faction(), test_create_plain(0, 0));
CuAssertPtrEquals(tc, (void *)u->faction->race, (void *)u->_race); CuAssertPtrEquals(tc, (void *)u->faction->race, (void *)u->_race);
CuAssertPtrNotNull(tc, change_race(u, 2, rctoad, NULL)); CuAssertPtrNotNull(tc, tr = change_race(u, 2, rctoad, NULL));
CuAssertPtrEquals(tc, (void *)rctoad, (void *)u->_race); CuAssertPtrEquals(tc, (void *)rctoad, (void *)u->_race);
CuAssertPtrEquals(tc, NULL, (void *)u->irace); CuAssertPtrEquals(tc, NULL, (void *)u->irace);
CuAssertPtrEquals(tc, &tt_timeout, tr->type);
CuAssertPtrNotNull(tc, u->attribs); CuAssertPtrNotNull(tc, u->attribs);
CuAssertPtrEquals(tc, NULL, u->attribs->next);
tp = get_triggers(u->attribs, "timer"); tp = get_triggers(u->attribs, "timer");
CuAssertPtrNotNull(tc, tp); CuAssertPtrNotNull(tc, tp);
CuAssertPtrNotNull(tc, tr = *tp); CuAssertPtrEquals(tc, tr, *tp);
CuAssertPtrEquals(tc, &tt_timeout, tr->type); CuAssertPtrEquals(tc, NULL, tr->next);
td = (timeout_data *)tr->data.v;
CuAssertPtrNotNull(tc, td);
CuAssertIntEquals(tc, 2, td->timer);
CuAssertPtrNotNull(tc, td->triggers);
CuAssertPtrEquals(tc, &tt_changerace, td->triggers->type);
CuAssertPtrEquals(tc, NULL, td->triggers->next);
crd = (changerace_data *)td->triggers->data.v;
CuAssertPtrEquals(tc, (void *)u->faction->race, (void *)crd->race);
CuAssertPtrEquals(tc, NULL, (void *)crd->irace);
/* change race, but do not add a second change_race trigger */
CuAssertPtrEquals(tc, tr, change_race(u, 2, rctoad, NULL));
CuAssertPtrNotNull(tc, u->attribs);
CuAssertPtrEquals(tc, NULL, u->attribs->next);
CuAssertPtrEquals(tc, NULL, tr->next);
CuAssertPtrEquals(tc, (void *)rctoad, (void *)u->_race);
CuAssertPtrEquals(tc, NULL, (void *)u->irace);
td = (timeout_data *)tr->data.v; td = (timeout_data *)tr->data.v;
CuAssertPtrNotNull(tc, td); CuAssertPtrNotNull(tc, td);
CuAssertIntEquals(tc, 2, td->timer); CuAssertIntEquals(tc, 2, td->timer);

View File

@ -86,8 +86,10 @@ trigger_type tt_changefaction = {
trigger *trigger_changefaction(unit * u, struct faction * f) trigger *trigger_changefaction(unit * u, struct faction * f)
{ {
trigger *t = t_new(&tt_changefaction); trigger *t = t_new(&tt_changefaction);
changefaction_data *td = (changefaction_data *)t->data.v; if (t) {
td->unit = u; changefaction_data *td = (changefaction_data *)t->data.v;
td->faction = f; td->unit = u;
td->faction = f;
}
return t; return t;
} }

View File

@ -85,20 +85,35 @@ trigger_type tt_changerace = {
trigger *trigger_changerace(unit * u, const race * prace, const race * irace) trigger *trigger_changerace(unit * u, const race * prace, const race * irace)
{ {
trigger *t = t_new(&tt_changerace); trigger *t = t_new(&tt_changerace);
changerace_data *td = (changerace_data *)t->data.v; if (t) {
changerace_data *td = (changerace_data *)t->data.v;
td->u = u; td->u = u;
td->race = prace; td->race = prace;
td->irace = irace; td->irace = irace;
}
return t; return t;
} }
extern struct trigger *change_race(struct unit *u, int duration, const struct race *urace, const struct race *irace) { extern struct trigger *change_race(struct unit *u, int duration, const struct race *urace, const struct race *irace) {
trigger *trestore = trigger_changerace(u, u_race(u), u->irace); trigger **texists = get_triggers(u->attribs, "timer");
if (trestore) { trigger *tr = NULL;
add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore));
u->irace = irace; if (texists) {
u_setrace(u, urace); tr = *texists;
} }
return trestore; else {
trigger *trestore = trigger_changerace(u, u_race(u), u->irace);
if (trestore) {
tr = trigger_timeout(duration, trestore);
add_trigger(&u->attribs, "timer", tr);
}
}
if (tr) {
u->irace = irace;
if (urace) {
u_setrace(u, urace);
}
}
return tr;
} }

View File

@ -71,6 +71,8 @@ trigger_type tt_clonedied = {
trigger *trigger_clonedied(unit * u) trigger *trigger_clonedied(unit * u)
{ {
trigger *t = t_new(&tt_clonedied); trigger *t = t_new(&tt_clonedied);
t->data.v = (void *)u; if (t) {
t->data.v = (void *)u;
}
return t; return t;
} }

View File

@ -115,13 +115,15 @@ trigger *trigger_createcurse(struct unit * mage, struct unit * target,
const curse_type * ct, double vigour, int duration, double effect, int men) const curse_type * ct, double vigour, int duration, double effect, int men)
{ {
trigger *t = t_new(&tt_createcurse); trigger *t = t_new(&tt_createcurse);
createcurse_data *td = (createcurse_data *)t->data.v; if (t) {
td->mage = mage; createcurse_data *td = (createcurse_data *)t->data.v;
td->target = target; td->mage = mage;
td->type = ct; td->target = target;
td->vigour = vigour; td->type = ct;
td->duration = duration; td->vigour = vigour;
td->effect = effect; td->duration = duration;
td->men = men; td->effect = effect;
td->men = men;
}
return t; return t;
} }

View File

@ -103,10 +103,12 @@ trigger *trigger_createunit(region * r, struct faction * f,
const struct race * rc, int number) const struct race * rc, int number)
{ {
trigger *t = t_new(&tt_createunit); trigger *t = t_new(&tt_createunit);
createunit_data *td = (createunit_data *)t->data.v; if (t) {
td->r = r; createunit_data *td = (createunit_data *)t->data.v;
td->f = f; td->r = r;
td->race = rc; td->f = f;
td->number = number; td->race = rc;
td->number = number;
}
return t; return t;
} }

View File

@ -96,9 +96,11 @@ trigger_type tt_giveitem = {
trigger *trigger_giveitem(unit * u, const item_type * itype, int number) trigger *trigger_giveitem(unit * u, const item_type * itype, int number)
{ {
trigger *t = t_new(&tt_giveitem); trigger *t = t_new(&tt_giveitem);
giveitem_data *td = (giveitem_data *)t->data.v; if (t) {
td->number = number; giveitem_data *td = (giveitem_data *)t->data.v;
td->u = u; td->number = number;
td->itype = itype; td->u = u;
td->itype = itype;
}
return t; return t;
} }

View File

@ -61,6 +61,8 @@ trigger_type tt_killunit = {
trigger *trigger_killunit(unit * u) trigger *trigger_killunit(unit * u)
{ {
trigger *t = t_new(&tt_killunit); trigger *t = t_new(&tt_killunit);
t->data.v = (void *)u; if (t) {
t->data.v = (void *)u;
}
return t; return t;
} }

View File

@ -130,6 +130,8 @@ trigger_type tt_shock = {
trigger *trigger_shock(unit * u) trigger *trigger_shock(unit * u)
{ {
trigger *t = t_new(&tt_shock); trigger *t = t_new(&tt_shock);
t->data.v = (void *)u; if (t) {
t->data.v = (void *)u;
}
return t; return t;
} }

View File

@ -79,8 +79,10 @@ trigger_type tt_timeout = {
trigger *trigger_timeout(int time, trigger * callbacks) trigger *trigger_timeout(int time, trigger * callbacks)
{ {
trigger *t = t_new(&tt_timeout); trigger *t = t_new(&tt_timeout);
timeout_data *td = (timeout_data *)t->data.v; if (t) {
td->triggers = callbacks; timeout_data *td = (timeout_data *)t->data.v;
td->timer = time; td->triggers = callbacks;
td->timer = time;
}
return t; return t;
} }

BIN
tests/data/test.dat Normal file

Binary file not shown.