#define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \
(element_info[e].move_delay_random))
+#define GET_TARGET_ELEMENT(e, ch) \
+ ((e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \
+ (e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : (e))
+
#define ELEMENT_CAN_ENTER_FIELD_BASE_X(x, y, condition) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
(condition)))
static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int);
#define CheckTriggeredElementChange(x, y, e, ev) \
- CheckTriggeredElementChangeExt(x, y, e, ev, -1, CH_SIDE_ANY, -1)
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, \
+ CH_SIDE_ANY, -1)
#define CheckTriggeredElementChangePlayer(x, y, e, ev, p, s) \
CheckTriggeredElementChangeExt(x, y, e, ev, p, s, -1)
#define CheckTriggeredElementChangeSide(x, y, e, ev, s) \
- CheckTriggeredElementChangeExt(x, y, e, ev, -1, s, -1)
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, s, -1)
#define CheckTriggeredElementChangePage(x, y, e, ev, p) \
- CheckTriggeredElementChangeExt(x, y, e, ev, -1, CH_SIDE_ANY, p)
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, \
+ CH_SIDE_ANY, p)
-static boolean CheckElementChangeExt(int, int, int, int, int, int, int);
-#define CheckElementChange(x, y, e, ev) \
- CheckElementChangeExt(x, y, e, ev, -1, CH_SIDE_ANY, -1)
+static boolean CheckElementChangeExt(int, int, int, int, int, int, int, int);
+#define CheckElementChange(x, y, e, te, ev) \
+ CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, CH_SIDE_ANY, -1)
#define CheckElementChangePlayer(x, y, e, ev, p, s) \
- CheckElementChangeExt(x, y, e, ev, p, s, -1)
-#define CheckElementChangeSide(x, y, e, ev, s) \
- CheckElementChangeExt(x, y, e, ev, -1, s, -1)
-#define CheckElementChangePage(x, y, e, ev, p) \
- CheckElementChangeExt(x, y, e, ev, -1, CH_SIDE_ANY, p)
+ CheckElementChangeExt(x, y, e, EL_EMPTY, ev, p, s, CH_PAGE_ANY)
+#define CheckElementChangeSide(x, y, e, te, ev, s) \
+ CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, s, CH_PAGE_ANY)
+#define CheckElementChangePage(x, y, e, te, ev, p) \
+ CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, CH_SIDE_ANY, p)
static void PlayLevelSound(int, int, int);
static void PlayLevelSoundNearest(int, int, int);
}
#endif
+ /* ---------- initialize run-time trigger player and element ------------- */
+
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ ei->change_page[j].actual_trigger_element = EL_EMPTY;
+ ei->change_page[j].actual_trigger_player = EL_PLAYER_1;
+ }
+ }
+
/* ---------- initialize trigger events ---------------------------------- */
/* initialize trigger events information */
boolean object_hit = FALSE;
boolean impact = (lastline || object_hit);
int element = Feld[x][y];
- int smashed = EL_UNDEFINED;
+ int smashed = EL_STEELWALL;
if (!lastline) /* check if element below was hit */
{
PlayLevelSound(x, y, SND_PEARL_BREAKING);
return;
}
- else if (impact && CheckElementChange(x, y, element, CE_IMPACT))
+ else if (impact && CheckElementChange(x, y, element, smashed, CE_IMPACT))
{
PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
TestIfElementSmashesCustomElement(x, y, MV_DOWN);
#endif
- CheckElementChange(x, y + 1, smashed, CE_SMASHED);
+ CheckElementChange(x, y + 1, smashed, element, CE_SMASHED);
CheckTriggeredElementChangeSide(x, y + 1, smashed,
CE_OTHER_IS_SWITCHING, CH_SIDE_TOP);
- CheckElementChangeSide(x, y + 1, smashed, CE_SWITCHED, CH_SIDE_TOP);
+ CheckElementChangeSide(x, y + 1, smashed, element,
+ CE_SWITCHED, CH_SIDE_TOP);
}
}
else
{
- CheckElementChange(x, y + 1, smashed, CE_SMASHED);
+ CheckElementChange(x, y + 1, smashed, element, CE_SMASHED);
}
}
}
change->trigger_element == touched_element)
{
CheckElementChangePage(newx, newy, hitting_element,
- CE_OTHER_IS_HITTING, i);
+ touched_element, CE_OTHER_IS_HITTING, i);
break;
}
}
change->trigger_element == hitting_element)
{
CheckElementChangePage(nextx, nexty, touched_element,
- CE_OTHER_GETS_HIT, i);
+ hitting_element, CE_OTHER_GETS_HIT, i);
break;
}
}
static boolean ChangeElementNow(int x, int y, int element, int page)
{
struct ElementChangeInfo *change = &element_info[element].change_page[page];
+ int target_element;
/* always use default change event to prevent running into a loop */
if (ChangeEvent[x][y] == CE_BITMASK_DEFAULT)
ChangeEvent[x][y] = CH_EVENT_BIT(CE_DELAY);
+ if (ChangeEvent[x][y] == CH_EVENT_BIT(CE_DELAY))
+ {
+ /* reset actual trigger element and player */
+ change->actual_trigger_element = EL_EMPTY;
+ change->actual_trigger_player = EL_PLAYER_1;
+ }
+
/* do not change already changed elements with same change event */
#if 0
if (Changed[x][y] & ChangeEvent[x][y])
ChangeEvent[ex][ey] = ChangeEvent[x][y];
- ChangeElementNowExt(ex, ey, change->content[xx][yy]);
+ target_element = GET_TARGET_ELEMENT(change->content[xx][yy], change);
+
+ ChangeElementNowExt(ex, ey, target_element);
something_has_changed = TRUE;
}
else
{
- ChangeElementNowExt(x, y, change->target_element);
+ target_element = GET_TARGET_ELEMENT(change->target_element, change);
+
+ ChangeElementNowExt(x, y, target_element);
PlayLevelSoundElementAction(x, y, element, ACTION_CHANGING);
}
{
page = ChangePage[x][y];
ChangePage[x][y] = -1;
+
+ change = &ei->change_page[page];
}
#if 0
int trigger_page)
{
int i, j, x, y;
+ int trigger_page_bits = (trigger_page < 0 ? CH_PAGE_ANY : 1 << trigger_page);
if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event)))
return FALSE;
change->events & CH_EVENT_BIT(trigger_event) &&
change->trigger_side & trigger_side &&
change->trigger_player & trigger_player &&
- change->trigger_page & (1 << trigger_page) &&
+ change->trigger_page & trigger_page_bits &&
IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element))
{
#if 0
change_element = TRUE;
page = j;
+ change->actual_trigger_element = trigger_element;
+ change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+
break;
}
}
static boolean CheckElementChangeExt(int x, int y,
int element,
+ int trigger_element,
int trigger_event,
int trigger_player,
int trigger_side,
change_element = TRUE;
trigger_page = i;
+ change->actual_trigger_element = trigger_element;
+ change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+
break;
}
}
if (!change_element)
return FALSE;
}
+ else
+ {
+ struct ElementInfo *ei = &element_info[element];
+ struct ElementChangeInfo *change = &ei->change_page[trigger_page];
+
+ change->actual_trigger_element = trigger_element;
+ change->actual_trigger_player = EL_PLAYER_1; /* unused */
+ }
#else
boolean change_center_element = FALSE;
int center_element_change_page = 0;
int center_element = Feld[x][y]; /* should always be non-moving! */
+ int border_trigger_element;
int i, j;
for (i = 0; i < NUM_DIRECTIONS; i++)
{
change_center_element = TRUE;
center_element_change_page = j;
+ border_trigger_element = border_element;
break;
}
#endif
)
{
- CheckElementChangePage(xx, yy, border_element, CE_OTHER_IS_TOUCHING,
- j);
+#if 0
+ printf("::: border_element %d, %d\n", x, y);
+#endif
+
+ CheckElementChangePage(xx, yy, border_element, center_element,
+ CE_OTHER_IS_TOUCHING, j);
break;
}
}
}
if (change_center_element)
- CheckElementChangePage(x, y, center_element, CE_OTHER_IS_TOUCHING,
- center_element_change_page);
+ {
+#if 0
+ printf("::: center_element %d, %d\n", x, y);
+#endif
+
+ CheckElementChangePage(x, y, center_element, border_trigger_element,
+ CE_OTHER_IS_TOUCHING, center_element_change_page);
+ }
}
void TestIfElementHitsCustomElement(int x, int y, int direction)
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
int hitx = x + dx, hity = y + dy;
int hitting_element = Feld[x][y];
+ int touched_element;
#if 0
boolean object_hit = (IN_LEV_FIELD(hitx, hity) &&
!IS_FREE(hitx, hity) &&
return;
#endif
- CheckElementChangeSide(x, y, hitting_element, CE_HITTING_SOMETHING,
- direction);
+ touched_element = (IN_LEV_FIELD(hitx, hity) ?
+ MovingOrBlocked2Element(hitx, hity) : EL_STEELWALL);
+
+ CheckElementChangeSide(x, y, hitting_element, touched_element,
+ CE_HITTING_SOMETHING, direction);
if (IN_LEV_FIELD(hitx, hity))
{
int opposite_direction = MV_DIR_OPPOSITE(direction);
int hitting_side = direction;
int touched_side = opposite_direction;
+#if 0
int touched_element = MovingOrBlocked2Element(hitx, hity);
+#endif
#if 1
boolean object_hit = (!IS_MOVING(hitx, hity) ||
MovDir[hitx][hity] != direction ||
{
int i;
- CheckElementChangeSide(hitx, hity, touched_element, CE_HIT_BY_SOMETHING,
- opposite_direction);
+ CheckElementChangeSide(hitx, hity, touched_element, hitting_element,
+ CE_HIT_BY_SOMETHING, opposite_direction);
if (IS_CUSTOM_ELEMENT(hitting_element) &&
HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
#endif
)
{
- CheckElementChangePage(x, y, hitting_element, CE_OTHER_IS_HITTING,
- i);
+ CheckElementChangePage(x, y, hitting_element, touched_element,
+ CE_OTHER_IS_HITTING, i);
break;
}
}
)
{
CheckElementChangePage(hitx, hity, touched_element,
- CE_OTHER_GETS_HIT, i);
+ hitting_element, CE_OTHER_GETS_HIT, i);
break;
}
}
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
int hitx = x + dx, hity = y + dy;
int hitting_element = Feld[x][y];
+ int touched_element;
#if 0
boolean object_hit = (IN_LEV_FIELD(hitx, hity) &&
!IS_FREE(hitx, hity) &&
return;
#endif
- CheckElementChangeSide(x, y, hitting_element, EP_CAN_SMASH_EVERYTHING,
- direction);
+ touched_element = (IN_LEV_FIELD(hitx, hity) ?
+ MovingOrBlocked2Element(hitx, hity) : EL_STEELWALL);
+
+ CheckElementChangeSide(x, y, hitting_element, touched_element,
+ EP_CAN_SMASH_EVERYTHING, direction);
if (IN_LEV_FIELD(hitx, hity))
{
int opposite_direction = MV_DIR_OPPOSITE(direction);
int hitting_side = direction;
int touched_side = opposite_direction;
+#if 0
int touched_element = MovingOrBlocked2Element(hitx, hity);
+#endif
#if 1
boolean object_hit = (!IS_MOVING(hitx, hity) ||
MovDir[hitx][hity] != direction ||
{
int i;
- CheckElementChangeSide(hitx, hity, touched_element,
+ CheckElementChangeSide(hitx, hity, touched_element, hitting_element,
CE_SMASHED_BY_SOMETHING, opposite_direction);
if (IS_CUSTOM_ELEMENT(hitting_element) &&
#endif
)
{
- CheckElementChangePage(x, y, hitting_element, CE_OTHER_IS_SMASHING,
- i);
+ CheckElementChangePage(x, y, hitting_element, touched_element,
+ CE_OTHER_IS_SMASHING, i);
break;
}
}
)
{
CheckElementChangePage(hitx, hity, touched_element,
- CE_OTHER_GETS_SMASHED, i);
+ hitting_element, CE_OTHER_GETS_SMASHED, i);
break;
}
}
#if 1
TestIfElementHitsCustomElement(jx, jy, direction);
#else
- CheckElementChangeSide(jx, jy, new_element, CE_HITTING_SOMETHING,
- direction);
+ CheckElementChangeSide(jx, jy, new_element, touched_element,
+ CE_HITTING_SOMETHING, direction);
#endif
}