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;
}
trigger *t_new(trigger_type * ttype)
trigger *t_new(trigger_type *ttype)
{
trigger *t = calloc(1, sizeof(trigger));
if (!t) abort();
if (t) {
t->type = ttype;
if (ttype->initialize)
if (ttype->initialize) {
ttype->initialize(t);
}
}
return t;
}

View File

@ -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;

View File

@ -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);

View File

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

View File

@ -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);
if (t) {
changerace_data *td = (changerace_data *)t->data.v;
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 **texists = get_triggers(u->attribs, "timer");
trigger *tr = NULL;
if (texists) {
tr = *texists;
}
else {
trigger *trestore = trigger_changerace(u, u_race(u), u->irace);
if (trestore) {
add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore));
tr = trigger_timeout(duration, trestore);
add_trigger(&u->attribs, "timer", tr);
}
}
if (tr) {
u->irace = irace;
if (urace) {
u_setrace(u, urace);
}
return trestore;
}
return tr;
}

View File

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

View File

@ -115,6 +115,7 @@ 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);
if (t) {
createcurse_data *td = (createcurse_data *)t->data.v;
td->mage = mage;
td->target = target;
@ -123,5 +124,6 @@ trigger *trigger_createcurse(struct unit * mage, struct unit * target,
td->duration = duration;
td->effect = effect;
td->men = men;
}
return t;
}

View File

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

View File

@ -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);
if (t) {
giveitem_data *td = (giveitem_data *)t->data.v;
td->number = number;
td->u = u;
td->itype = itype;
}
return t;
}

View File

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

View File

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

View File

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

BIN
tests/data/test.dat Normal file

Binary file not shown.