#define GADGET_ID_CHANGE_DELAY_RND_DOWN (GADGET_ID_COUNTER_FIRST + 48)
#define GADGET_ID_CHANGE_DELAY_RND_TEXT (GADGET_ID_COUNTER_FIRST + 49)
#define GADGET_ID_CHANGE_DELAY_RND_UP (GADGET_ID_COUNTER_FIRST + 50)
+#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 51)
+#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 52)
+#define GADGET_ID_CHANGE_CONT_RND_UP (GADGET_ID_COUNTER_FIRST + 53)
/* drawing area identifiers */
-#define GADGET_ID_DRAWING_AREA_FIRST (GADGET_ID_COUNTER_FIRST + 51)
+#define GADGET_ID_DRAWING_AREA_FIRST (GADGET_ID_COUNTER_FIRST + 54)
#define GADGET_ID_DRAWING_LEVEL (GADGET_ID_DRAWING_AREA_FIRST + 0)
#define GADGET_ID_ELEMENT_CONTENT_0 (GADGET_ID_DRAWING_AREA_FIRST + 1)
#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 8)
#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 9)
#define GADGET_ID_CHANGE_PLAYER_ACTION (GADGET_ID_SELECTBOX_FIRST + 10)
-#define GADGET_ID_CHANGE_IMPACT_ACTION (GADGET_ID_SELECTBOX_FIRST + 11)
+#define GADGET_ID_CHANGE_COLLIDE_ACTION (GADGET_ID_SELECTBOX_FIRST + 11)
#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 12)
#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 13)
#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 21)
#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 22)
#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_CHANGE_BY_PLAYER (GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_CHANGE_IMPACT_SMASHED (GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_CHANGE_BY_OTHER (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_CHANGE_USE_RANDOM (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CHANGE_BY_PLAYER (GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_CHANGE_BY_COLLISION (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_CHANGE_BY_OTHER (GADGET_ID_CHECKBUTTON_FIRST + 28)
/* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 29)
#define GADGET_ID_ELEMENTLIST_LAST (GADGET_ID_ELEMENTLIST_FIRST + \
ED_NUM_ELEMENTLIST_BUTTONS - 1)
#define ED_COUNTER_ID_MOVE_DELAY_RND 14
#define ED_COUNTER_ID_CHANGE_DELAY_FIX 15
#define ED_COUNTER_ID_CHANGE_DELAY_RND 16
+#define ED_COUNTER_ID_CHANGE_CONT_RND 17
-#define ED_NUM_COUNTERBUTTONS 17
+#define ED_NUM_COUNTERBUTTONS 18
#define ED_COUNTER_ID_LEVEL_FIRST ED_COUNTER_ID_LEVEL_XSIZE
#define ED_COUNTER_ID_LEVEL_LAST ED_COUNTER_ID_LEVEL_RANDOM
#define ED_COUNTER_ID_CUSTOM_LAST ED_COUNTER_ID_MOVE_DELAY_RND
#define ED_COUNTER_ID_CHANGE_FIRST ED_COUNTER_ID_CHANGE_DELAY_FIX
-#define ED_COUNTER_ID_CHANGE_LAST ED_COUNTER_ID_CHANGE_DELAY_RND
+#define ED_COUNTER_ID_CHANGE_LAST ED_COUNTER_ID_CHANGE_CONT_RND
/* values for scrollbutton gadgets */
#define ED_SCROLLBUTTON_ID_AREA_UP 0
#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER 8
#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 9
#define ED_SELECTBOX_ID_CHANGE_PLAYER_ACTION 10
-#define ED_SELECTBOX_ID_CHANGE_IMPACT_ACTION 11
+#define ED_SELECTBOX_ID_CHANGE_COLLIDE_ACTION 11
#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 12
#define ED_SELECTBOX_ID_CHANGE_POWER 13
#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 19
#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 20
#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 21
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY 22
-#define ED_CHECKBUTTON_ID_CHANGE_BY_PLAYER 23
-#define ED_CHECKBUTTON_ID_CHANGE_IMPACT_SMASHED 24
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER 25
+#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 22
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY 23
+#define ED_CHECKBUTTON_ID_CHANGE_BY_PLAYER 24
+#define ED_CHECKBUTTON_ID_CHANGE_BY_COLLISION 25
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER 26
-#define ED_NUM_CHECKBUTTONS 26
+#define ED_NUM_CHECKBUTTONS 27
#define ED_CHECKBUTTON_ID_LEVEL_FIRST ED_CHECKBUTTON_ID_DOUBLE_SPEED
#define ED_CHECKBUTTON_ID_LEVEL_LAST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
GADGET_ID_CHANGE_DELAY_RND_TEXT,
&custom_element.change.delay_random,
NULL, "+random", NULL
- }
+ },
+ {
+ ED_SETTINGS_XPOS(3), ED_SETTINGS_YPOS(12),
+ 0, 100,
+ GADGET_ID_CHANGE_CONT_RND_DOWN, GADGET_ID_CHANGE_CONT_RND_UP,
+ GADGET_ID_CHANGE_CONT_RND_TEXT,
+ &custom_element.change.random,
+ NULL, "use random change:", NULL
+ },
};
static struct
};
static int value_change_player_action = 0;
-static struct ValueTextInfo options_change_impact_action[] =
+static struct ValueTextInfo options_change_collide_action[] =
{
+ { CE_COLLISION, "on collision" },
{ CE_IMPACT, "on impact" },
{ CE_SMASHED, "when smashed" },
{ -1, NULL }
};
-static int value_change_impact_action = 0;
+static int value_change_collide_action = 0;
static struct ValueTextInfo options_change_other_action[] =
{
{ CE_OTHER_COLLECTING, "collecting" },
+ { CE_OTHER_TOUCHING, "touching" },
+ { CE_OTHER_PRESSING, "pressing" },
{ CE_OTHER_PUSHING, "pushing" },
{ CE_OTHER_CHANGING, "change of" },
{ CE_OTHER_EXPLODING, "explosion of" },
},
{
ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(6),
- GADGET_ID_CHANGE_IMPACT_ACTION,
+ GADGET_ID_CHANGE_COLLIDE_ACTION,
-1,
- options_change_impact_action,
- &value_change_impact_action,
+ options_change_collide_action,
+ &value_change_collide_action,
NULL, NULL, "change after impact or smash"
},
{
11, "Advanced", "Advanced element configuration"
},
{
- ED_SETTINGS_XPOS(0) + 262, ED_SETTINGS_YPOS(12),
+ ED_SETTINGS_XPOS(0) + 262, ED_SETTINGS_YPOS(13),
GADGET_ID_SAVE_AS_TEMPLATE,
-1, "Save as template", "Save current settings as new template"
},
},
{
ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(6),
- GADGET_ID_CHANGE_IMPACT_SMASHED,
- &custom_element_change_events[CE_IMPACT_SMASHED],
+ GADGET_ID_CHANGE_BY_COLLISION,
+ &custom_element_change_events[CE_BY_COLLISION],
NULL, "element changes by impact or smash"
},
{
"only use complete change", "only use complete extended content"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12),
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(12),
+ GADGET_ID_CHANGE_USE_RANDOM,
+ &custom_element.change.use_random_change,
+ NULL, "use random value for new content"
+ },
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13),
GADGET_ID_CUSTOM_USE_TEMPLATE,
&custom_element.use_template,
"use template", "use template for custom properties"
CE_PRESSED_BY_PLAYER);
/* set change by impact/smash selectbox help value */
- value_change_impact_action =
+ value_change_collide_action =
(HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED :
HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT :
- CE_IMPACT);
+ HAS_CHANGE_EVENT(element, CE_COLLISION) ? CE_COLLISION :
+ CE_COLLISION);
/* set change by other element action selectbox help value */
value_change_other_action =
(HAS_CHANGE_EVENT(element, CE_OTHER_EXPLODING) ? CE_OTHER_EXPLODING :
HAS_CHANGE_EVENT(element, CE_OTHER_CHANGING) ? CE_OTHER_CHANGING :
HAS_CHANGE_EVENT(element, CE_OTHER_PUSHING) ? CE_OTHER_PUSHING :
+ HAS_CHANGE_EVENT(element, CE_OTHER_PRESSING) ? CE_OTHER_PRESSING :
+ HAS_CHANGE_EVENT(element, CE_OTHER_TOUCHING) ? CE_OTHER_TOUCHING :
HAS_CHANGE_EVENT(element, CE_OTHER_COLLECTING) ? CE_OTHER_COLLECTING :
CE_OTHER_COLLECTING);
}
custom_element_change_events[CE_BY_PLAYER];
/* set player change event from checkbox and selectbox */
+ custom_element_change_events[CE_COLLISION] = FALSE;
custom_element_change_events[CE_IMPACT] = FALSE;
custom_element_change_events[CE_SMASHED] = FALSE;
- custom_element_change_events[value_change_impact_action] =
- custom_element_change_events[CE_IMPACT_SMASHED];
+ custom_element_change_events[value_change_collide_action] =
+ custom_element_change_events[CE_BY_COLLISION];
/* set other element action change event from checkbox and selectbox */
custom_element_change_events[CE_OTHER_COLLECTING] = FALSE;
+ custom_element_change_events[CE_OTHER_TOUCHING] = FALSE;
+ custom_element_change_events[CE_OTHER_PRESSING] = FALSE;
custom_element_change_events[CE_OTHER_PUSHING] = FALSE;
custom_element_change_events[CE_OTHER_CHANGING] = FALSE;
custom_element_change_events[CE_OTHER_EXPLODING] = FALSE;
static void CheckGravityMovement(struct PlayerInfo *);
static void KillHeroUnlessProtected(int, int);
-static void CheckTriggeredElementChange(int, int);
-static void CheckPlayerElementChange(int, int, int, int);
+static void TestIfPlayerTouchesCustomElement(int, int);
+
+static boolean CheckTriggeredElementChange(int, int);
+static boolean CheckElementChange(int, int, int, int);
static void ChangeElementNow(int, int, int);
static void PlaySoundLevel(int, int, int);
MovDir[x][y] = 0;
MovDelay[x][y] = 0;
-#if 0
- Store[x][y] = 0;
- Store2[x][y] = 0;
-#endif
-
AmoebaNr[x][y] = 0;
ChangeDelay[x][y] = 0;
Pushed[x][y] = FALSE;
return;
}
-#if 1
if (element == EL_BLOCKED &&
(Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
RemoveField(oldx, oldy);
RemoveField(newx, newy);
-#if 1
Store[oldx][oldy] = Store2[oldx][oldy] = 0;
-#endif
if (next_element != EL_UNDEFINED)
Feld[oldx][oldy] = next_element;
-#else
- if (element == EL_BLOCKED &&
- (Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
- Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
- Feld[oldx][oldy] == EL_BD_MAGIC_WALL_EMPTYING ||
- Feld[oldx][oldy] == EL_AMOEBA_DROPPING))
- Feld[oldx][oldy] = get_next_element(Feld[oldx][oldy]);
- else
- Feld[oldx][oldy] = EL_EMPTY;
-
- Store[oldx][oldy] = Store2[oldx][oldy] = 0;
-
- Feld[newx][newy] = EL_EMPTY;
- MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
- MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
- ChangeDelay[oldx][oldy] = ChangeDelay[newx][newy] = 0;
- Pushed[oldx][oldy] = Pushed[newx][newy] = FALSE;
- GfxAction[oldx][oldy] = GfxAction[newx][newy] = ACTION_DEFAULT;
-#endif
DrawLevelField(oldx, oldy);
DrawLevelField(newx, newy);
PlaySoundLevel(x, y, SND_PEARL_BREAKING);
return;
}
+#if 1
+ else if (impact && CheckElementChange(x, y, element, ACTION_IMPACT))
+ {
+ PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
+
+ return;
+ }
+#else
else if (impact && CAN_CHANGE(element) &&
HAS_CHANGE_EVENT(element, CE_IMPACT))
{
return;
}
+#endif
if (impact && element == EL_AMOEBA_DROP)
{
{
ToggleLightSwitch(x, y + 1);
}
- else if (CAN_CHANGE(smashed) &&
- HAS_CHANGE_EVENT(smashed, CE_SMASHED))
+#if 1
+ else
+ {
+ CheckElementChange(x, y + 1, smashed, CE_SMASHED);
+ }
+#else
+ else if (CAN_CHANGE(smashed) && HAS_CHANGE_EVENT(smashed, CE_SMASHED))
{
ChangeElementNow(x, y + 1, smashed);
}
+#endif
+ }
+ else
+ {
+ CheckElementChange(x, y + 1, smashed, CE_SMASHED);
}
}
}
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
int horiz_move = (dx != 0);
int newx = x + dx, newy = y + dy;
+ int nextx = newx + dx, nexty = newy + dy;
int step = (horiz_move ? dx : dy) * TILEX / MOVE_DELAY_NORMAL_SPEED;
#if 1
boolean pushed = Pushed[x][y];
if (CAN_SMASH(element) && direction == MV_DOWN &&
(newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1)))
Impact(x, newy);
+#endif
+
+#if 0
+ if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
+ CheckTriggeredElementChange(element, CE_COLLISION);
+#else
+#if 1
+ if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
+ CheckElementChange(newx, newy, element, CE_COLLISION);
+#else
+ if ((!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty)) &&
+ CAN_CHANGE(element) && HAS_CHANGE_EVENT(element, CE_COLLISION))
+ ChangeElementNow(newx, newy, element);
+#endif
#endif
}
else /* still moving on */
if (!change->only_complete || complete_change)
{
+ if (change->only_complete && change->use_random_change &&
+ RND(change->random) != 0)
+ return;
+
for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++)
{
int ex = x + xx - 1;
int ey = y + yy - 1;
- if (can_change[xx][yy])
+ if (can_change[xx][yy] && (!change->use_random_change ||
+ RND(change->random) == 0))
{
ChangeElementNowExt(ex, ey, change->content[xx][yy]);
static void ChangeElement(int x, int y)
{
+#if 1
+ int element = MovingOrBlocked2Element(x, y);
+#else
int element = Feld[x][y];
+#endif
struct ElementChangeInfo *change = &element_info[element].change;
if (ChangeDelay[x][y] == 0) /* initialize element change */
}
}
-static void CheckTriggeredElementChange(int trigger_element, int trigger_event)
+static boolean CheckTriggeredElementChange(int trigger_element,
+ int trigger_event)
{
int i, x, y;
if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event)))
- return;
+ return FALSE;
for (i=0; i<MAX_NUM_ELEMENTS; i++)
{
}
}
}
+
+ return TRUE;
}
-static void CheckPlayerElementChange(int x, int y, int element,
- int trigger_event)
+static boolean CheckElementChange(int x, int y, int element, int trigger_event)
{
if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, trigger_event))
- return;
+ return FALSE;
+
+ if (Feld[x][y] == EL_BLOCKED)
+ Blocked2Moving(x, y, &x, &y);
ChangeDelay[x][y] = 1;
ChangeElement(x, y);
+
+ return TRUE;
}
static void PlayerActions(struct PlayerInfo *player, byte player_action)
}
TestIfHeroTouchesBadThing(jx, jy);
+ TestIfPlayerTouchesCustomElement(jx, jy);
if (!player->active)
RemoveHero(player);
ScreenMovDir = MV_NO_MOVING;
}
+void TestIfPlayerTouchesCustomElement(int x, int y)
+{
+ static int xy[4][2] =
+ {
+ { 0, -1 },
+ { -1, 0 },
+ { +1, 0 },
+ { 0, +1 }
+ };
+ boolean center_is_player = (IS_PLAYER(x, y));
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ int xx = x + xy[i][0];
+ int yy = y + xy[i][1];
+
+ if (center_is_player && IN_LEV_FIELD(xx, yy))
+ {
+ CheckTriggeredElementChange(Feld[xx][yy], CE_OTHER_TOUCHING);
+ CheckElementChange(xx, yy, Feld[xx][yy], CE_TOUCHED_BY_PLAYER);
+ }
+ }
+}
+
void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir)
{
int i, kill_x = -1, kill_y = -1;
player->push_delay_value = GET_NEW_PUSH_DELAY(element);
CheckTriggeredElementChange(element, CE_OTHER_PUSHING);
- CheckPlayerElementChange(x, y, element, CE_PUSHED_BY_PLAYER);
+ CheckElementChange(x, y, element, CE_PUSHED_BY_PLAYER);
break;
}
else
{
- CheckPlayerElementChange(x, y, element, CE_PRESSED_BY_PLAYER);
+ CheckTriggeredElementChange(element, CE_OTHER_PRESSING);
+ CheckElementChange(x, y, element, CE_PRESSED_BY_PLAYER);
}
return MF_NO_ACTION;