diff --git a/src/kernel/event.c b/src/kernel/event.c index fbf46d11f..0581aa999 100644 --- a/src/kernel/event.c +++ b/src/kernel/event.c @@ -59,13 +59,15 @@ int read_triggers(struct gamedata *data, trigger ** tp) return 0; } -trigger *t_new(trigger_type * ttype) +trigger *t_new(trigger_type *ttype) { trigger *t = calloc(1, sizeof(trigger)); - if (!t) abort(); - t->type = ttype; - if (ttype->initialize) - ttype->initialize(t); + if (t) { + t->type = ttype; + if (ttype->initialize) { + ttype->initialize(t); + } + } return t; } diff --git a/src/spells.c b/src/spells.c index 51c150bf7..a6a01513b 100644 --- a/src/spells.c +++ b/src/spells.c @@ -4551,7 +4551,7 @@ int sp_illusionary_shapeshift(castorder * co) 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, "sp_shapeshift_fail", "target race", u, rc)); return 0; diff --git a/src/spells.test.c b/src/spells.test.c index aa5fd78d4..59052bfdb 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -286,23 +286,43 @@ static void test_watch_region(CuTest *tc) { static void test_change_race(CuTest *tc) { unit *u; - race *rctoad; + race *rctoad, *rcsmurf; trigger **tp, *tr; timeout_data *td; changerace_data *crd; test_setup(); rctoad = test_create_race("toad"); + rcsmurf = test_create_race("smurf"); u = test_create_unit(test_create_faction(), test_create_plain(0, 0)); 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, NULL, (void *)u->irace); + CuAssertPtrEquals(tc, &tt_timeout, tr->type); CuAssertPtrNotNull(tc, u->attribs); + CuAssertPtrEquals(tc, NULL, u->attribs->next); tp = get_triggers(u->attribs, "timer"); CuAssertPtrNotNull(tc, tp); - CuAssertPtrNotNull(tc, tr = *tp); - CuAssertPtrEquals(tc, &tt_timeout, tr->type); + CuAssertPtrEquals(tc, tr, *tp); + 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; CuAssertPtrNotNull(tc, td); CuAssertIntEquals(tc, 2, td->timer); diff --git a/src/triggers/changefaction.c b/src/triggers/changefaction.c index 85403083b..e87c18543 100644 --- a/src/triggers/changefaction.c +++ b/src/triggers/changefaction.c @@ -86,8 +86,10 @@ trigger_type tt_changefaction = { trigger *trigger_changefaction(unit * u, struct faction * f) { trigger *t = t_new(&tt_changefaction); - changefaction_data *td = (changefaction_data *)t->data.v; - td->unit = u; - td->faction = f; + if (t) { + changefaction_data *td = (changefaction_data *)t->data.v; + td->unit = u; + td->faction = f; + } return t; } diff --git a/src/triggers/changerace.c b/src/triggers/changerace.c index 9011b1660..48557a0c0 100644 --- a/src/triggers/changerace.c +++ b/src/triggers/changerace.c @@ -85,20 +85,35 @@ trigger_type tt_changerace = { trigger *trigger_changerace(unit * u, const race * prace, const race * irace) { 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->race = prace; - td->irace = irace; + td->u = u; + td->race = prace; + td->irace = irace; + } return t; } 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); - if (trestore) { - add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); - u->irace = irace; - u_setrace(u, urace); + trigger **texists = get_triggers(u->attribs, "timer"); + trigger *tr = NULL; + + if (texists) { + 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; } diff --git a/src/triggers/clonedied.c b/src/triggers/clonedied.c index 500104ba1..666a29a03 100644 --- a/src/triggers/clonedied.c +++ b/src/triggers/clonedied.c @@ -71,6 +71,8 @@ trigger_type tt_clonedied = { trigger *trigger_clonedied(unit * u) { trigger *t = t_new(&tt_clonedied); - t->data.v = (void *)u; + if (t) { + t->data.v = (void *)u; + } return t; } diff --git a/src/triggers/createcurse.c b/src/triggers/createcurse.c index 760834a3d..8993343c9 100644 --- a/src/triggers/createcurse.c +++ b/src/triggers/createcurse.c @@ -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) { trigger *t = t_new(&tt_createcurse); - createcurse_data *td = (createcurse_data *)t->data.v; - td->mage = mage; - td->target = target; - td->type = ct; - td->vigour = vigour; - td->duration = duration; - td->effect = effect; - td->men = men; + if (t) { + createcurse_data *td = (createcurse_data *)t->data.v; + td->mage = mage; + td->target = target; + td->type = ct; + td->vigour = vigour; + td->duration = duration; + td->effect = effect; + td->men = men; + } return t; } diff --git a/src/triggers/createunit.c b/src/triggers/createunit.c index d9437c87b..33c01e4ad 100644 --- a/src/triggers/createunit.c +++ b/src/triggers/createunit.c @@ -103,10 +103,12 @@ trigger *trigger_createunit(region * r, struct faction * f, const struct race * rc, int number) { trigger *t = t_new(&tt_createunit); - createunit_data *td = (createunit_data *)t->data.v; - td->r = r; - td->f = f; - td->race = rc; - td->number = number; + if (t) { + createunit_data *td = (createunit_data *)t->data.v; + td->r = r; + td->f = f; + td->race = rc; + td->number = number; + } return t; } diff --git a/src/triggers/giveitem.c b/src/triggers/giveitem.c index 1664c1d3a..4b1f98cbb 100644 --- a/src/triggers/giveitem.c +++ b/src/triggers/giveitem.c @@ -96,9 +96,11 @@ trigger_type tt_giveitem = { trigger *trigger_giveitem(unit * u, const item_type * itype, int number) { trigger *t = t_new(&tt_giveitem); - giveitem_data *td = (giveitem_data *)t->data.v; - td->number = number; - td->u = u; - td->itype = itype; + if (t) { + giveitem_data *td = (giveitem_data *)t->data.v; + td->number = number; + td->u = u; + td->itype = itype; + } return t; } diff --git a/src/triggers/killunit.c b/src/triggers/killunit.c index 5f221350e..a4511a062 100644 --- a/src/triggers/killunit.c +++ b/src/triggers/killunit.c @@ -61,6 +61,8 @@ trigger_type tt_killunit = { trigger *trigger_killunit(unit * u) { trigger *t = t_new(&tt_killunit); - t->data.v = (void *)u; + if (t) { + t->data.v = (void *)u; + } return t; } diff --git a/src/triggers/shock.c b/src/triggers/shock.c index 416b628ac..0dc37f084 100644 --- a/src/triggers/shock.c +++ b/src/triggers/shock.c @@ -130,6 +130,8 @@ trigger_type tt_shock = { trigger *trigger_shock(unit * u) { trigger *t = t_new(&tt_shock); - t->data.v = (void *)u; + if (t) { + t->data.v = (void *)u; + } return t; } diff --git a/src/triggers/timeout.c b/src/triggers/timeout.c index f36bc8c31..711a45b39 100644 --- a/src/triggers/timeout.c +++ b/src/triggers/timeout.c @@ -79,8 +79,10 @@ trigger_type tt_timeout = { trigger *trigger_timeout(int time, trigger * callbacks) { trigger *t = t_new(&tt_timeout); - timeout_data *td = (timeout_data *)t->data.v; - td->triggers = callbacks; - td->timer = time; + if (t) { + timeout_data *td = (timeout_data *)t->data.v; + td->triggers = callbacks; + td->timer = time; + } return t; } diff --git a/tests/data/test.dat b/tests/data/test.dat new file mode 100644 index 000000000..6e35b67f1 Binary files /dev/null and b/tests/data/test.dat differ