rnd-20030829-B-src
authorHolger Schemel <info@artsoft.org>
Fri, 29 Aug 2003 21:09:32 +0000 (23:09 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:43:31 +0000 (10:43 +0200)
src/conftime.h
src/editor.c
src/files.c
src/game.c
src/init.c
src/libgame/gadgets.c
src/main.h

index ff54e7f1751bb135986d2b2bec760e9515708707..6ffa2c350fd9fcecf602dec269a5051bd3ff2ccf 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2003-08-28 23:39]"
+#define COMPILE_DATE_STRING "[2003-08-29 22:16]"
index 02e65f15c66813d595d3df642ed90ba8f990c1bd..12053e073e7d9f6745413d40669c627a036cb20b 100644 (file)
@@ -1609,7 +1609,7 @@ static struct
   {
     ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_CAN_CHANGE,       GADGET_ID_NONE,
-    &custom_element_properties[EP_CAN_CHANGE],
+    &custom_element_change.can_change,
     NULL, "element changes to:",       "element can change to other element"
   },
   {
@@ -6680,18 +6680,19 @@ static void HandleGraphicbuttonGadgets(struct GadgetInfo *gi)
 {
   int type_id = gi->custom_type_id;
 
-  if (type_id == ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE)
+  if (type_id == ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE ||
+      type_id == ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE)
   {
-    if (element_info[properties_element].current_change_page > 0)
-      element_info[properties_element].current_change_page--;
+    struct ElementInfo *ei = &element_info[properties_element];
+    int step = BUTTON_STEPSIZE(gi->event.button);
 
-    DrawPropertiesWindow();
-  }
-  else if (type_id == ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE)
-  {
-    if (element_info[properties_element].current_change_page <
-       element_info[properties_element].num_change_pages - 1)
-      element_info[properties_element].current_change_page++;
+    step *= (type_id == ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE ? -1 : +1);
+    ei->current_change_page += step;
+
+    if (ei->current_change_page < 0)
+      ei->current_change_page = 0;
+    else if (ei->current_change_page >= ei->num_change_pages)
+      ei->current_change_page = ei->num_change_pages - 1;
 
     DrawPropertiesWindow();
   }
index d9840486bf81bbf77fb0641882c2cbbf23eb7fe5..db3a432d41aa3623ee0d26ac783343663f6f25c6 100644 (file)
@@ -62,37 +62,39 @@ void setElementChangePages(struct ElementInfo *ei, int change_pages)
   ei->change = &ei->change_page[ei->current_change_page];
 }
 
-void setElementChangeInfoToDefaults(struct ElementChangeInfo *eci)
+void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 {
   int x, y;
 
-  eci->events = CE_BITMASK_DEFAULT;
-  eci->target_element = EL_EMPTY_SPACE;
+  change->can_change = FALSE;
 
-  eci->delay_fixed = 0;
-  eci->delay_random = 0;
-  eci->delay_frames = -1;      /* later set to reliable default value */
+  change->events = CE_BITMASK_DEFAULT;
+  change->target_element = EL_EMPTY_SPACE;
 
-  eci->trigger_element = EL_EMPTY_SPACE;
+  change->delay_fixed = 0;
+  change->delay_random = 0;
+  change->delay_frames = -1;   /* later set to reliable default value */
 
-  eci->explode = FALSE;
-  eci->use_content = FALSE;
-  eci->only_complete = FALSE;
-  eci->use_random_change = FALSE;
-  eci->random = 0;
-  eci->power = CP_NON_DESTRUCTIVE;
+  change->trigger_element = EL_EMPTY_SPACE;
+
+  change->explode = FALSE;
+  change->use_content = FALSE;
+  change->only_complete = FALSE;
+  change->use_random_change = FALSE;
+  change->random = 0;
+  change->power = CP_NON_DESTRUCTIVE;
 
   for(x=0; x<3; x++)
     for(y=0; y<3; y++)
-      eci->content[x][y] = EL_EMPTY_SPACE;
+      change->content[x][y] = EL_EMPTY_SPACE;
 
-  eci->player_action = 0;
-  eci->collide_action = 0;
-  eci->other_action = 0;
+  change->player_action = 0;
+  change->collide_action = 0;
+  change->other_action = 0;
 
-  eci->pre_change_function = NULL;
-  eci->change_function = NULL;
-  eci->post_change_function = NULL;
+  change->pre_change_function = NULL;
+  change->change_function = NULL;
+  change->post_change_function = NULL;
 }
 
 static void setLevelInfoToDefaults(struct LevelInfo *level)
@@ -841,6 +843,18 @@ static void LoadLevel_InitLevel(struct LevelInfo *level, char *filename)
     }
   }
 
+  /* initialize "can_change" field for old levels with only one change page */
+  if (level->game_version <= VERSION_IDENT(3,0,2))
+  {
+    for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+    {
+      int element = EL_CUSTOM_START + i;
+
+      if (CAN_CHANGE(element))
+       element_info[element].change->can_change = TRUE;
+    }
+  }
+
   /* copy elements to runtime playfield array */
   for(x=0; x<MAX_LEV_FIELDX; x++)
     for(y=0; y<MAX_LEV_FIELDY; y++)
index fa9d44a4ccb41e92bd5960810aa1771548d3600a..0f2aff310c07a1e89555c6d5fa9be3a317eb6a66 100644 (file)
@@ -171,7 +171,6 @@ static void TestIfElementTouchesCustomElement(int, int);
 
 static boolean CheckTriggeredElementChange(int, int, int, int);
 static boolean CheckElementChange(int, int, int, int);
-static void ChangeElementNow(int, int, int);
 
 static void PlaySoundLevel(int, int, int);
 static void PlaySoundLevelNearest(int, int, int);
@@ -216,7 +215,7 @@ struct ChangingElementInfo
   void (*post_change_function)(int x, int y);
 };
 
-static struct ChangingElementInfo changing_element_list[] =
+static struct ChangingElementInfo change_delay_list[] =
 {
   {
     EL_NUT_BREAKING,
@@ -415,14 +414,16 @@ collect_count_list[] =
   { EL_UNDEFINED,              0 },
 };
 
-static boolean changing_element[MAX_NUM_ELEMENTS];
 static unsigned long trigger_events[MAX_NUM_ELEMENTS];
 
-#define IS_AUTO_CHANGING(e)    (changing_element[e])
+#define IS_AUTO_CHANGING(e)    (element_info[e].change_events & \
+                                CH_EVENT_BIT(CE_DELAY))
 #define IS_JUST_CHANGING(x, y) (ChangeDelay[x][y] != 0)
 #define IS_CHANGING(x, y)      (IS_AUTO_CHANGING(Feld[x][y]) || \
                                 IS_JUST_CHANGING(x, y))
 
+#define CE_PAGE(e, ce)         (element_info[e].event_page[ce])
+
 
 void GetPlayerConfig()
 {
@@ -742,7 +743,7 @@ void DrawGameDoorValues()
 
 static void InitGameEngine()
 {
-  int i;
+  int i, j, k;
 
   /* set game engine from tape file when re-playing, else from level file */
   game.engine_version = (tape.playing ? tape.engine_version :
@@ -775,48 +776,80 @@ static void InitGameEngine()
   /* initialize changing elements information */
   for (i=0; i < MAX_NUM_ELEMENTS; i++)
   {
+    struct ElementInfo *ei = &element_info[i];
+
     /* this pointer might have been changed in the level editor */
-    element_info[i].change = &element_info[i].change_page[0];
+    ei->change = &ei->change_page[0];
 
     if (!IS_CUSTOM_ELEMENT(i))
     {
-      element_info[i].change->target_element = EL_EMPTY_SPACE;
-      element_info[i].change->delay_fixed = 0;
-      element_info[i].change->delay_random = 0;
-      element_info[i].change->delay_frames = 1;
+      ei->change->target_element = EL_EMPTY_SPACE;
+      ei->change->delay_fixed = 0;
+      ei->change->delay_random = 0;
+      ei->change->delay_frames = 1;
     }
 
-    changing_element[i] = FALSE;
+    ei->change_events = CE_BITMASK_DEFAULT;
+    for (j=0; j < NUM_CHANGE_EVENTS; j++)
+    {
+      ei->event_page_num[j] = 0;
+      ei->event_page[j] = &ei->change_page[0];
+    }
   }
 
   /* add changing elements from pre-defined list */
-  for (i=0; changing_element_list[i].element != EL_UNDEFINED; i++)
+  for (i=0; change_delay_list[i].element != EL_UNDEFINED; i++)
   {
-    int element = changing_element_list[i].element;
-    struct ChangingElementInfo *ce = &changing_element_list[i];
-    struct ElementChangeInfo *change = element_info[element].change;
+    struct ChangingElementInfo *ch_delay = &change_delay_list[i];
+    struct ElementInfo *ei = &element_info[ch_delay->element];
 
-    change->target_element       = ce->target_element;
-    change->delay_fixed          = ce->change_delay;
+    ei->change->target_element       = ch_delay->target_element;
+    ei->change->delay_fixed          = ch_delay->change_delay;
 
-    change->pre_change_function  = ce->pre_change_function;
-    change->change_function      = ce->change_function;
-    change->post_change_function = ce->post_change_function;
+    ei->change->pre_change_function  = ch_delay->pre_change_function;
+    ei->change->change_function      = ch_delay->change_function;
+    ei->change->post_change_function = ch_delay->post_change_function;
 
-    changing_element[element] = TRUE;
+    ei->change_events |= CH_EVENT_BIT(CE_DELAY);
   }
 
-  /* add changing elements from custom element configuration */
+#if 1
+  /* add change events from custom element configuration */
+  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++)
+    {
+      if (!ei->change_page[j].can_change)
+       continue;
+
+      for (k=0; k < NUM_CHANGE_EVENTS; k++)
+      {
+       /* only add event page for the first page found with this event */
+       if (ei->change_page[j].events & CH_EVENT_BIT(k) &&
+           !(ei->change_events & CH_EVENT_BIT(k)))
+       {
+         ei->change_events |= CH_EVENT_BIT(k);
+         ei->event_page_num[k] = j;
+         ei->event_page[k] = &ei->change_page[j];
+       }
+      }
+    }
+  }
+
+#else
+
+  /* add change events from custom element configuration */
   for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
     int element = EL_CUSTOM_START + i;
 
     /* only add custom elements that change after fixed/random frame delay */
-    if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, CE_DELAY))
-      continue;
-
-    changing_element[element] = TRUE;
+    if (CAN_CHANGE(element) && HAS_CHANGE_EVENT(element, CE_DELAY))
+      element_info[element].change_events |= CH_EVENT_BIT(CE_DELAY);
   }
+#endif
 
   /* ---------- initialize trigger events ---------------------------------- */
 
@@ -824,11 +857,32 @@ static void InitGameEngine()
   for (i=0; i<MAX_NUM_ELEMENTS; i++)
     trigger_events[i] = EP_BITMASK_DEFAULT;
 
+#if 1
+  /* add trigger events from element change event properties */
+  for (i=0; i<MAX_NUM_ELEMENTS; i++)
+  {
+    struct ElementInfo *ei = &element_info[i];
+
+    for (j=0; j < ei->num_change_pages; j++)
+    {
+      if (!ei->change_page->can_change)
+       continue;
+
+      if (ei->change_page[j].events & CH_EVENT_BIT(CE_BY_OTHER))
+      {
+       int trigger_element = ei->change_page[j].trigger_element;
+
+       trigger_events[trigger_element] |= ei->change_page[j].events;
+      }
+    }
+  }
+#else
   /* add trigger events from element change event properties */
   for (i=0; i<MAX_NUM_ELEMENTS; i++)
     if (HAS_CHANGE_EVENT(i, CE_BY_OTHER))
       trigger_events[element_info[i].change->trigger_element] |=
        element_info[i].change->events;
+#endif
 
   /* ---------- initialize push delay -------------------------------------- */
 
@@ -1208,16 +1262,19 @@ void InitGame()
 
       if (CAN_CHANGE(element))
       {
-       content = element_info[element].change->target_element;
-       is_player = ELEM_IS_PLAYER(content);
-
-       if (is_player && (found_rating < 3 || element < found_element))
+       for (i=0; i < element_info[element].num_change_pages; i++)
        {
-         start_x = x;
-         start_y = y;
+         content = element_info[element].change_page[i].target_element;
+         is_player = ELEM_IS_PLAYER(content);
 
-         found_rating = 3;
-         found_element = element;
+         if (is_player && (found_rating < 3 || element < found_element))
+         {
+           start_x = x;
+           start_y = y;
+
+           found_rating = 3;
+           found_element = element;
+         }
        }
       }
 
@@ -1238,16 +1295,19 @@ void InitGame()
        if (!CAN_CHANGE(element))
          continue;
 
-       content = element_info[element].change->content[xx][yy];
-       is_player = ELEM_IS_PLAYER(content);
-
-       if (is_player && (found_rating < 1 || element < found_element))
+       for (i=0; i < element_info[element].num_change_pages; i++)
        {
-         start_x = x + xx - 1;
-         start_y = y + yy - 1;
+         content = element_info[element].change_page[i].content[xx][yy];
+         is_player = ELEM_IS_PLAYER(content);
 
-         found_rating = 1;
-         found_element = element;
+         if (is_player && (found_rating < 1 || element < found_element))
+         {
+           start_x = x + xx - 1;
+           start_y = y + yy - 1;
+
+           found_rating = 1;
+           found_element = element;
+         }
        }
       }
     }
@@ -2837,24 +2897,12 @@ void Impact(int x, int y)
     PlaySoundLevel(x, y, SND_PEARL_BREAKING);
     return;
   }
-#if 1
   else if (impact && CheckElementChange(x, y, element, CE_IMPACT))
   {
     PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
 
     return;
   }
-#else
-  else if (impact && CAN_CHANGE(element) &&
-          HAS_CHANGE_EVENT(element, CE_IMPACT))
-  {
-    PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
-
-    ChangeElementNow(x, y, element);
-
-    return;
-  }
-#endif
 
   if (impact && element == EL_AMOEBA_DROP)
   {
@@ -2986,17 +3034,10 @@ void Impact(int x, int y)
        {
          ToggleLightSwitch(x, y + 1);
        }
-#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
       {
@@ -5286,7 +5327,7 @@ static void ChangeElementNowExt(int x, int y, int target_element)
 {
   /* check if element under player changes from accessible to unaccessible
      (needed for special case of dropping element which then changes) */
-  if (IS_PLAYER(x, y) &&
+  if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) &&
       IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element))
   {
     Bang(x, y);
@@ -5316,26 +5357,12 @@ static void ChangeElementNowExt(int x, int y, int target_element)
     RelocatePlayer(x, y, target_element);
 }
 
-static void ChangeElementNow(int x, int y, int element)
+static void ChangeElementNow(int x, int y, int element, int page)
 {
-  struct ElementChangeInfo *change = element_info[element].change;
-
-#if 0
-  if (element >= EL_CUSTOM_START + 17 && element <= EL_CUSTOM_START + 39)
-    printf("::: changing... [%d]\n", FrameCounter);
-#endif
-
-#if 0
-  /* prevent CheckTriggeredElementChange() from looping */
-  Changing[x][y] = TRUE;
-#endif
+  struct ElementChangeInfo *change = &element_info[element].change_page[page];
 
   CheckTriggeredElementChange(x, y, Feld[x][y], CE_OTHER_IS_CHANGING);
 
-#if 0
-  Changing[x][y] = FALSE;
-#endif
-
   if (change->explode)
   {
     Bang(x, y);
@@ -5432,42 +5459,21 @@ static void ChangeElementNow(int x, int y, int element)
   }
 }
 
-static void ChangeElement(int x, int y)
+static void ChangeElement(int x, int y, int page)
 {
-#if 1
   int element = MovingOrBlocked2Element(x, y);
-#else
-  int element = Feld[x][y];
-#endif
-  struct ElementChangeInfo *change = element_info[element].change;
+  struct ElementChangeInfo *change = &element_info[element].change_page[page];
 
   if (ChangeDelay[x][y] == 0)          /* initialize element change */
   {
-#if 1
     ChangeDelay[x][y] = (    change->delay_fixed  * change->delay_frames +
                         RND(change->delay_random * change->delay_frames)) + 1;
-#else
-    ChangeDelay[x][y] = changing_element[element].change_delay + 1;
-
-    if (IS_CUSTOM_ELEMENT(element) && HAS_CHANGE_EVENT(element, CE_DELAY))
-    {
-      int max_random_delay = element_info[element].change->delay_random;
-      int delay_frames = element_info[element].change->delay_frames;
-
-      ChangeDelay[x][y] += RND(max_random_delay * delay_frames);
-    }
-#endif
 
     ResetGfxAnimation(x, y);
     ResetRandomAnimationValue(x, y);
 
-#if 1
     if (change->pre_change_function)
       change->pre_change_function(x, y);
-#else
-    if (changing_element[element].pre_change_function)
-      changing_element[element].pre_change_function(x, y);
-#endif
   }
 
   ChangeDelay[x][y]--;
@@ -5479,20 +5485,11 @@ static void ChangeElement(int x, int y)
     if (IS_ANIMATED(graphic))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
-#if 1
     if (change->change_function)
       change->change_function(x, y);
-#else
-    if (changing_element[element].change_function)
-      changing_element[element].change_function(x, y);
-#endif
   }
   else                                 /* finish element change */
   {
-#if 0
-    int next_element = changing_element[element].next_element;
-#endif
-
     if (IS_MOVING(x, y))               /* never change a running system ;-) */
     {
       ChangeDelay[x][y] = 1;           /* try change after next move step */
@@ -5500,27 +5497,17 @@ static void ChangeElement(int x, int y)
       return;
     }
 
-#if 1
-    ChangeElementNow(x, y, element);
+    ChangeElementNow(x, y, element, page);
 
     if (change->post_change_function)
       change->post_change_function(x, y);
-#else
-    if (next_element != EL_UNDEFINED)
-      ChangeElementNow(x, y, next_element);
-    else
-      ChangeElementNow(x, y, element_info[element].change->target_element);
-
-    if (changing_element[element].post_change_function)
-      changing_element[element].post_change_function(x, y);
-#endif
   }
 }
 
 static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
                                           int trigger_event)
 {
-  int i, x, y;
+  int i, j, x, y;
 
   if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event)))
     return FALSE;
@@ -5529,11 +5516,39 @@ static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
   if (trigger_event == CE_OTHER_IS_CHANGING)
     Changing[lx][ly] = TRUE;
 
-  for (i=0; i<MAX_NUM_ELEMENTS; i++)
+  for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
-    if (!CAN_CHANGE(i) || !HAS_CHANGE_EVENT(i, trigger_event) ||
-       element_info[i].change->trigger_element != trigger_element)
+    int element = EL_CUSTOM_START + i;
+
+#if 1
+    boolean change_element = FALSE;
+    int page;
+
+    if (!CAN_CHANGE(element) ||
+       !HAS_ANY_CHANGE_EVENT(element, trigger_event))
+      continue;
+
+    for (j=0; j < element_info[element].num_change_pages; j++)
+    {
+      if (element_info[element].change_page[j].trigger_element ==
+         trigger_element)
+      {
+       change_element = TRUE;
+       page = j;
+
+       break;
+      }
+    }
+
+    if (!change_element)
+      continue;
+
+#else
+    if (!CAN_CHANGE(element) ||
+       !HAS_ANY_CHANGE_EVENT(element, trigger_event) ||
+       element_info[element].change->trigger_element != trigger_element)
       continue;
+#endif
 
     for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
     {
@@ -5543,10 +5558,10 @@ static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
       if (Changing[x][y])      /* do not change just changing elements */
        continue;
 
-      if (Feld[x][y] == i)
+      if (Feld[x][y] == element)
       {
        ChangeDelay[x][y] = 1;
-       ChangeElement(x, y);
+       ChangeElement(x, y, page);
 
        Changing[x][y] = TRUE;  /* do not change just changed elements */
       }
@@ -5560,20 +5575,28 @@ static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
   return TRUE;
 }
 
-static boolean CheckElementChange(int x, int y, int element, int trigger_event)
+static boolean CheckElementChangeExt(int x, int y, int element,
+                                    int trigger_event, int page)
 {
-  if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, trigger_event))
+  if (!CAN_CHANGE(element) || !HAS_ANY_CHANGE_EVENT(element, trigger_event))
     return FALSE;
 
   if (Feld[x][y] == EL_BLOCKED)
     Blocked2Moving(x, y, &x, &y);
 
   ChangeDelay[x][y] = 1;
-  ChangeElement(x, y);
+  ChangeElement(x, y, page);
 
   return TRUE;
 }
 
+static boolean CheckElementChange(int x, int y, int element, int trigger_event)
+{
+  int page = element_info[element].event_page_num[trigger_event];
+
+  return CheckElementChangeExt(x, y, element, trigger_event, page);
+}
+
 static void PlayerActions(struct PlayerInfo *player, byte player_action)
 {
   static byte stored_player_action[MAX_PLAYERS];
@@ -5626,13 +5649,7 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
     CheckGravityMovement(player);
 
     if (player->MovPos == 0)
-    {
-#if 0
-      printf("Trying... Player frame reset\n");
-#endif
-
       InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir);
-    }
 
     if (player->MovPos == 0)   /* needed for tape.playing */
       player->is_moving = FALSE;
@@ -5843,7 +5860,7 @@ void GameActions()
     /* this may take place after moving, so 'element' may have changed */
     if (IS_CHANGING(x, y))
     {
-      ChangeElement(x, y);
+      ChangeElement(x, y, element_info[element].event_page_num[CE_DELAY]);
       element = Feld[x][y];
       graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
     }
@@ -6682,8 +6699,9 @@ void TestIfElementTouchesCustomElement(int x, int y)
     { 0, +1 }
   };
   boolean change_center_element = FALSE;
+  int center_element_change_page = 0;
   int center_element = Feld[x][y];
-  int i;
+  int i, j;
 
   if (check_changing)  /* prevent this function from running into a loop */
     return;
@@ -6703,17 +6721,47 @@ void TestIfElementTouchesCustomElement(int x, int y)
 
     /* check for change of center element (but change it only once) */
     if (IS_CUSTOM_ELEMENT(center_element) &&
-       border_element == element_info[center_element].change->trigger_element)
-      change_center_element = TRUE;
+       element_info[center_element].change_events & CE_OTHER_IS_TOUCHING &&
+       !change_center_element)
+    {
+      for (j=0; j < element_info[center_element].num_change_pages; j++)
+      {
+       struct ElementChangeInfo *change =
+         &element_info[center_element].change_page[j];
+
+       if (change->events & CE_OTHER_IS_TOUCHING &&
+           change->trigger_element == border_element)
+       {
+         change_center_element = TRUE;
+         center_element_change_page = j;
+
+         break;
+       }
+      }
+    }
 
     /* check for change of border element */
     if (IS_CUSTOM_ELEMENT(border_element) &&
-       center_element == element_info[border_element].change->trigger_element)
-      CheckElementChange(xx, yy, border_element, CE_OTHER_IS_TOUCHING);
+       element_info[border_element].change_events & CE_OTHER_IS_TOUCHING)
+    {
+      for (j=0; j < element_info[border_element].num_change_pages; j++)
+      {
+       struct ElementChangeInfo *change =
+         &element_info[border_element].change_page[j];
+
+       if (change->events & CE_OTHER_IS_TOUCHING &&
+           change->trigger_element == center_element)
+       {
+         CheckElementChangeExt(xx,yy, border_element,CE_OTHER_IS_TOUCHING, j);
+         break;
+       }
+      }
+    }
   }
 
   if (change_center_element)
-    CheckElementChange(x, y, center_element, CE_OTHER_IS_TOUCHING);
+    CheckElementChangeExt(x, y, center_element, CE_OTHER_IS_TOUCHING,
+                         center_element_change_page);
 
   check_changing = FALSE;
 }
index c129a676540638525f22d3e1c38facde79b61573..86b4ecaec8e64acd0d09510a9fcb2a485dea11a5 100644 (file)
@@ -2829,6 +2829,12 @@ void InitElementPropertiesEngine(int engine_version)
             element_info[i].token_name,
             element_info[i].crumbled[ACTION_DEFAULT]);
 #endif
+
+    /* ---------- CAN_CHANGE ----------------------------------------------- */
+    SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);     /* default: cannot change */
+    for (j=0; j < element_info[i].num_change_pages; j++)
+      if (element_info[i].change_page[j].can_change)
+       SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
   }
 
 #if 0
index 55174eef8b749c09812f870cd7d2059d33f11205..aacadafad4cfec7fd7d80e42199eae8294ebc91b 100644 (file)
@@ -105,8 +105,6 @@ static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my)
   return NULL;
 }
 
-#if 1
-
 static void setTextAreaCursorExt(struct GadgetInfo *gi, boolean set_cursor_pos)
 {
   char *text = gi->textarea.value;
@@ -147,15 +145,6 @@ static void setTextAreaCursorExt(struct GadgetInfo *gi, boolean set_cursor_pos)
     pos++;
   }
 
-  if (y >= area_ysize)
-  {
-    x = area_xsize - 1;
-  }
-
-#if 0
-  printf("::: %d, %d [%d]\n", cursor_x, cursor_y, cursor_position);
-#endif
-
   gi->textarea.cursor_x = x;
   gi->textarea.cursor_y = y;
   gi->textarea.cursor_x_preferred = x;
@@ -177,98 +166,6 @@ static void setTextAreaCursorPosition(struct GadgetInfo *gi, int pos)
   setTextAreaCursorExt(gi, FALSE);
 }
 
-#else
-
-static void setTextAreaCursorPosition(struct GadgetInfo *gi, int x, int y)
-{
-  char *text = gi->textarea.value;
-  int area_xsize = gi->textarea.xsize;
-  int area_ysize = gi->textarea.ysize;
-  int cursor_x = 0;
-  int cursor_y = 0;
-  int cursor_position = 0;
-
-  while (*text && cursor_y < area_ysize)
-  {
-    char buffer[MAX_OUTPUT_LINESIZE + 1];
-    int i;
-
-    for (i=0; i < area_xsize && *text && *text != '\n'; i++)
-      buffer[i] = *text++;
-    buffer[i] = '\0';
-
-#if 1
-    if (i == 0 && *text == '\n')
-    {
-      text++;
-      cursor_position++;
-    }
-#endif
-
-    if (x == -1 && y == -1)            /* get x/y from cursor position */
-    {
-      if (cursor_position + i >= gi->textarea.cursor_position)
-      {
-#if 0
-       printf("::: cursor: %d + %d >= %d\n", cursor_position, i,
-              gi->textarea.cursor_position);
-#endif
-
-       cursor_x = gi->textarea.cursor_position - cursor_position;
-       cursor_position = gi->textarea.cursor_position;
-
-       break;
-      }
-    }
-
-    if (cursor_y == y || !*text)       /* correct y position found */
-    {
-      cursor_x = MIN(i, x);
-      cursor_position += cursor_x;
-
-      break;
-    }
-    else
-      cursor_position += i;
-
-#if 0
-    if (*text == '\n')
-    {
-      text++;
-      cursor_position++;
-
-      if (i == area_xsize)
-       cursor_y++;
-    }
-#endif
-
-    cursor_y++;
-  }
-
-  if (cursor_x >= area_xsize)
-  {
-    cursor_x = 0;
-    cursor_y++;
-  }
-
-  if (cursor_y >= area_ysize)
-  {
-    cursor_x = area_xsize - 1;
-    cursor_y = area_ysize - 1;
-  }
-
-#if 0
-  printf("::: %d, %d [%d]\n", cursor_x, cursor_y, cursor_position);
-#endif
-
-  gi->textarea.cursor_x = cursor_x;
-  gi->textarea.cursor_y = cursor_y;
-  gi->textarea.cursor_x_preferred = cursor_x;
-  gi->textarea.cursor_position = cursor_position;
-}
-
-#endif
-
 static void default_callback_info(void *ptr)
 {
   return;
@@ -378,11 +275,6 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
        cursor_string[0] = (cursor_letter != '\0' ? cursor_letter : ' ');
        cursor_string[1] = '\0';
 
-#if 0
-       if (pressed)
-         printf("::: PRESSED!\n");
-#endif
-
        /* draw cursor, if active */
        if (pressed)
          DrawTextExt(drawto,
@@ -473,14 +365,6 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
        cursor_string[0] = (cursor_letter != '\0' ? cursor_letter : ' ');
        cursor_string[1] = '\0';
 
-#if 0
-       printf("::: '%s' [%d, %d] [%d] [%d -> '%s']\n",
-              gi->textarea.value,
-              gi->textarea.cursor_x, gi->textarea.cursor_y,
-              gi->textarea.cursor_position,
-              pressed, cursor_string);
-#endif
-
        /* draw cursor, if active */
        if (pressed)
          DrawTextExt(drawto,
@@ -635,7 +519,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
          /* selectbox text values */
          for (i=0; i < gi->selectbox.num_values; i++)
          {
-           int mask_mode;
+           int mask_mode = BLIT_MASKED;
+
+           strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
+           text[gi->selectbox.size] = '\0';
 
            if (i == gi->selectbox.current_index)
            {
@@ -645,17 +532,11 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                            gi->selectbox.width - 2 * border_x, font_height,
                            gi->selectbox.inverse_color);
 
-             strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
-             text[1 + gi->selectbox.size] = '\0';
-
-             mask_mode = BLIT_INVERSE;
-           }
-           else
-           {
-             strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
+             /* prevent use of cursor graphic by drawing at least two chars */
+             strcat(text, "  ");
              text[gi->selectbox.size] = '\0';
 
-             mask_mode = BLIT_MASKED;
+             mask_mode = BLIT_INVERSE;
            }
 
            DrawTextExt(drawto,
@@ -1467,10 +1348,6 @@ void HandleGadgets(int mx, int my, int button)
   last_mx = mx;
   last_my = my;
 
-#if 1
-
-#if 1
-
   /* if mouse button pressed outside text or selectbox gadget, deactivate it */
   if (anyTextGadgetActive() &&
       button != 0 && !motion_status && new_gi != last_gi)
@@ -1487,171 +1364,6 @@ void HandleGadgets(int mx, int my, int button)
     last_gi = NULL;
   }
 
-#else
-
-  /* special treatment for leaving text and number input gadgets */
-  if (anyTextInputGadgetActive() &&
-      button != 0 && !motion_status && new_gi != last_gi)
-  {
-    /* if mouse button pressed outside text input gadget, deactivate it */
-    CheckRangeOfNumericInputGadget(last_gi);
-    DrawGadget(last_gi, DG_UNPRESSED, last_gi->direct_draw);
-
-    last_gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-    if (last_gi->event_mask & GD_EVENT_TEXT_LEAVING)
-      last_gi->callback_action(last_gi);
-
-    last_gi = NULL;
-  }
-
-  /* special treatment for leaving text area gadgets */
-  if (anyTextAreaGadgetActive() &&
-      button != 0 && !motion_status && new_gi != last_gi)
-  {
-    /* if mouse button pressed outside text input gadget, deactivate it */
-    DrawGadget(last_gi, DG_UNPRESSED, last_gi->direct_draw);
-
-    last_gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-    if (last_gi->event_mask & GD_EVENT_TEXT_LEAVING)
-      last_gi->callback_action(last_gi);
-
-    last_gi = NULL;
-  }
-
-  /* special treatment for leaving selectbox gadgets */
-  if (anySelectboxGadgetActive() &&
-      button != 0 && !motion_status && new_gi != last_gi)
-  {
-    /* if mouse button pressed outside selectbox gadget, deactivate it */
-    DrawGadget(last_gi, DG_UNPRESSED, last_gi->direct_draw);
-
-    last_gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-    if (last_gi->event_mask & GD_EVENT_TEXT_LEAVING)
-      last_gi->callback_action(last_gi);
-
-    last_gi = NULL;
-  }
-
-#endif
-
-#else
-
-  /* special treatment for text and number input gadgets */
-  if (anyTextInputGadgetActive() && button != 0 && !motion_status)
-  {
-    struct GadgetInfo *gi = last_gi;
-
-    if (new_gi == last_gi)
-    {
-      int old_cursor_position = gi->textinput.cursor_position;
-
-      /* if mouse button pressed inside activated text gadget, set cursor */
-      gi->textinput.cursor_position =
-       (mx - gi->x - gi->border.xsize) / getFontWidth(gi->font);
-
-      if (gi->textinput.cursor_position < 0)
-       gi->textinput.cursor_position = 0;
-      else if (gi->textinput.cursor_position > strlen(gi->textinput.value))
-       gi->textinput.cursor_position = strlen(gi->textinput.value);
-
-      if (gi->textinput.cursor_position != old_cursor_position)
-       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else
-    {
-      /* if mouse button pressed outside text input gadget, deactivate it */
-      CheckRangeOfNumericInputGadget(gi);
-      DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
-
-      gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
-       gi->callback_action(gi);
-
-      last_gi = NULL;
-    }
-  }
-
-  /* special treatment for text area gadgets */
-  if (anyTextAreaGadgetActive() && button != 0 && !motion_status)
-  {
-    struct GadgetInfo *gi = last_gi;
-
-    if (new_gi == last_gi)
-    {
-      int old_cursor_position = gi->textarea.cursor_position;
-      int x = (mx - gi->x - gi->border.xsize) / getFontWidth(gi->font);
-      int y = (my - gi->y - gi->border.ysize) / getFontHeight(gi->font);
-
-      x = (x < 0 ? 0 : x >= gi->textarea.xsize ? gi->textarea.xsize - 1 : x);
-      y = (y < 0 ? 0 : y >= gi->textarea.ysize ? gi->textarea.ysize - 1 : y);
-
-      setTextAreaCursorXY(gi, x, y);
-
-#if 0
-      printf("::: %d -----> %d\n",
-            old_cursor_position,
-            gi->textarea.cursor_position);
-#endif
-
-      if (gi->textarea.cursor_position != old_cursor_position)
-       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else
-    {
-      /* if mouse button pressed outside text input gadget, deactivate it */
-      DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
-
-      gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
-       gi->callback_action(gi);
-
-      last_gi = NULL;
-    }
-  }
-
-  /* special treatment for selectbox gadgets */
-  if (anySelectboxGadgetActive() && button != 0 && !motion_status)
-  {
-    struct GadgetInfo *gi = last_gi;
-
-    if (new_gi == last_gi)
-    {
-      int old_index = gi->selectbox.current_index;
-
-      /* if mouse button pressed inside activated selectbox, select value */
-      if (my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height)
-       gi->selectbox.current_index =
-         (my - gi->selectbox.y - gi->border.ysize) / getFontHeight(gi->font);
-
-      if (gi->selectbox.current_index < 0)
-       gi->selectbox.current_index = 0;
-      else if (gi->selectbox.current_index > gi->selectbox.num_values - 1)
-       gi->selectbox.current_index = gi->selectbox.num_values - 1;
-
-      if (gi->selectbox.current_index != old_index)
-       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else
-    {
-      /* if mouse button pressed outside selectbox gadget, deactivate it */
-      DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
-
-      gi->event.type = GD_EVENT_TEXT_LEAVING;
-
-      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
-       gi->callback_action(gi);
-
-      last_gi = NULL;
-    }
-  }
-
-#endif
-
   gadget_pressed =
     (button != 0 && last_gi == NULL && new_gi != NULL && press_event);
   gadget_pressed_repeated =
@@ -1789,15 +1501,6 @@ void HandleGadgets(int mx, int my, int button)
     {
       last_info_gi->event.type = GD_EVENT_INFO_LEAVING;
       last_info_gi->callback_info(last_info_gi);
-
-#if 0
-      default_callback_info(NULL);
-
-      printf("It seems that we are leaving gadget [%s]!\n",
-            (last_info_gi != NULL &&
-             last_info_gi->info_text != NULL ?
-             last_info_gi->info_text : ""));
-#endif
     }
 
     last_info_gi = new_gi;
@@ -1891,7 +1594,6 @@ void HandleGadgets(int mx, int my, int button)
       }
     }
 
-    /* !!! bad for TEXT_INPUT ... !!! */
     DrawGadget(gi, DG_PRESSED, gi->direct_draw);
 
     gi->state = GD_BUTTON_PRESSED;
@@ -1906,11 +1608,6 @@ void HandleGadgets(int mx, int my, int button)
       gi->callback_action(gi);
   }
 
-#if 0
-  if (!mouse_moving)
-    printf("::: PRESSED...?\n");
-#endif
-
   if (gadget_pressed_repeated)
   {
     gi->event.type = GD_EVENT_PRESSED;
@@ -2035,18 +1732,10 @@ static void insertCharIntoTextArea(struct GadgetInfo *gi, char c)
   if (strlen(gi->textarea.value) == MAX_GADGET_TEXTSIZE) /* no space left */
     return;
 
-#if 0
-  printf("::: '%s' + '%c'", gi->textarea.value, c);
-#endif
-
   strcpy(text, gi->textarea.value);
   strcpy(&gi->textarea.value[cursor_position + 1], &text[cursor_position]);
   gi->textarea.value[cursor_position] = c;
 
-#if 0
-  printf(" => '%s'\n", gi->textarea.value);
-#endif
-
   setTextAreaCursorPosition(gi, gi->textarea.cursor_position + 1);
 }
 
@@ -2143,10 +1832,6 @@ void HandleGadgetsKeyInput(Key key)
     char letter = getCharFromKey(key);
     boolean legal_letter = (letter != 0);
 
-#if 0
-    printf("::: KEY: %x!\n", key);
-#endif
-
     if (legal_letter)
     {
       insertCharIntoTextArea(gi, letter);
index 1f16fcc82deec921f94ebd28c5730e55c91876e5..8a0fca2c30269df31ab100a379625bde365543bf 100644 (file)
 
 #define CH_EVENT_BIT(c)                (1 << (c))
 #define CH_EVENT_VAR(e)                (element_info[e].change->events)
+#define CH_ANY_EVENT_VAR(e)    (element_info[e].change_events)
 
 #define HAS_CHANGE_EVENT(e,c)  (IS_CUSTOM_ELEMENT(e) &&                  \
                                 (CH_EVENT_VAR(e) & CH_EVENT_BIT(c)) != 0)
+#define HAS_ANY_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) &&               \
+                                (CH_ANY_EVENT_VAR(e) & CH_EVENT_BIT(c)) != 0)
 #define SET_CHANGE_EVENT(e,c,v)        (IS_CUSTOM_ELEMENT(e) ?                   \
                                 ((v) ?                                   \
                                  (CH_EVENT_VAR(e) |=  CH_EVENT_BIT(c)) : \
@@ -1233,6 +1236,8 @@ struct DoorInfo
 
 struct ElementChangeInfo
 {
+  boolean can_change;          /* use or ignore this change info */
+
   unsigned long events;                /* bitfield for change events */
 
   short target_element;                /* target element after change */
@@ -1317,10 +1322,13 @@ struct ElementInfo
   int num_change_pages;                /* actual number of change pages */
   int current_change_page;     /* currently edited change page */
 
-  /* ---------- internal values used in game at runtime ---------- */
+  /* ---------- internal values used at runtime when playing ---------- */
 
   unsigned long change_events; /* bitfield for combined change events */
 
+  int event_page_num[NUM_CHANGE_EVENTS]; /* page number for each event */
+  struct ElementChangeInfo *event_page[NUM_CHANGE_EVENTS]; /* page for event */
+
   /* ---------- internal values used in level editor ---------- */
 
   int access_type;             /* walkable or passable */