Copy to Clipboard Test

Automatic Overhead Transparency Code

////////////////////////////////////////////////////////////////
// Overhead
// by grayswandir
////////////////////////////////////////////////////////////////
// Makes certain overhead layers transparent/invisible while link is
// underneath them.
////////////////////////////////////////////////////////////////
// Setup:
// Put Overhead_Update() in your active loop.
// Mess with the Configuration section if you want.
////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
// Configuration

// Set to 1 to make the tiles disappear completely, instead of being drawn
// transparently.
const int OVERHEAD_INVISIBLE = 0;

// These are the layers that are used. Set to 1 to enable, and 0 to disable.
const int OVERHEAD_USE_L3 = 0;
const int OVERHEAD_USE_L4 = 0;
const int OVERHEAD_USE_L5 = 1;
const int OVERHEAD_USE_L6 = 1;

// Change this to 16 if you have very fast scrolling turned on.
const int OVERHEAD_SCROLL_SPEED = 4;

////////////////////////////////////////////////////////////////
// Code

int Overhead_Data[1416];
const int OVERHEAD_STATE = 0;
const int OVERHEAD_LAST_SCREEN = 1;
const int OVERHEAD_SCROLL_DIR = 2;
const int OVERHEAD_TIMER = 3;
const int OVERHEAD_SCREENS = 4;
const int OVERHEAD_COMBOS = 8;
const int OVERHEAD_CSETS = 712;

const int OVERHEAD_STATE_UNINIT = 0;
const int OVERHEAD_STATE_SCROLLING = 1;
const int OVERHEAD_STATE_WORKING = 2;

void Overhead_Update() {
  int map; int screen; int location; int layer; bool under; int offset;

  // If this is the first time this function has been called, do some setup.
  if (OVERHEAD_STATE_UNINIT == Overhead_Data[OVERHEAD_STATE]) {
    Overhead_Data[OVERHEAD_STATE] = OVERHEAD_STATE_SCROLLING;
    Overhead_Data[OVERHEAD_LAST_SCREEN] = -1;
    for (layer = 3; layer <= 6; ++layer) {
      Overhead_Data[OVERHEAD_SCREENS + layer - 3] = -1;
    }
  }

  // If we've left our current screen, reset the layers we killed.
  screen = (Game->GetCurMap() << 8) + Game->GetCurScreen();
  if (screen != Overhead_Data[OVERHEAD_LAST_SCREEN]) {
    for (layer = 3; layer <= 6; ++layer) {
      // Skip if this layer wasn't recorded.
      if (-1 == Overhead_Data[OVERHEAD_SCREENS + layer - 3]) {continue;}

      // Replace the lost data.
      map = Overhead_Data[OVERHEAD_SCREENS + layer - 3] >> 8;
      screen = Overhead_Data[OVERHEAD_SCREENS + layer - 3] % 256;
      offset = 176 * (layer - 3);
      for (location = 0; location < 176; ++location) {
        Game->SetComboData(map, screen, location, Overhead_Data[OVERHEAD_COMBOS + offset + location]);
      }
    }

    // Remember what screen we're on, so we can tell if we've moved.
    Overhead_Data[OVERHEAD_LAST_SCREEN] = (Game->GetCurMap() << 8) + Game->GetCurScreen();
    Overhead_Data[OVERHEAD_STATE] = OVERHEAD_STATE_SCROLLING;

    // If we've just started scrolling, figure out what direction it's in so
    // we can draw the deleted combos properly. Also reset the timer.
    if (LA_SCROLLING == Link->Action) {
      if (-16 == Link->X) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_RIGHT;}
      if (256 == Link->X) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_LEFT;}
      if (-16 == Link->Y) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_DOWN;}
      if (176 == Link->Y) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_UP;}
      Overhead_Data[OVERHEAD_TIMER] = 0;
    }
  }

  // If we've finished scrolling, copy over the layers and delete them.
  if (LA_SCROLLING != Link->Action && OVERHEAD_STATE_SCROLLING == Overhead_Data[OVERHEAD_STATE]) {
    for (layer = 3; layer <= 6; ++layer) {
      // Skip this layer if we're not configured to use it.
      if (3 == layer && !OVERHEAD_USE_L3) {continue;}
      if (4 == layer && !OVERHEAD_USE_L4) {continue;}
      if (5 == layer && !OVERHEAD_USE_L5) {continue;}
      if (6 == layer && !OVERHEAD_USE_L6) {continue;}

      // If this screen doesn't use this layer, mark as not in use and skip.
      map = Screen->LayerMap(layer);
      screen = Screen->LayerScreen(layer);
      if (-1 == map || -1 == screen) {
        Overhead_Data[OVERHEAD_SCREENS + layer - 3] = -1;
        continue;
      }

      // Save this layer's screen location.
      Overhead_Data[OVERHEAD_SCREENS + layer - 3] = (map << 8) + screen;

      // Grab every combo and cset, and delete the original.
      offset = (layer - 3) * 176;
      for (location = 0; location < 176; ++location) {
        // Grab the data.
        Overhead_Data[OVERHEAD_COMBOS + offset + location] = Game->GetComboData(map, screen, location);
        Overhead_Data[OVERHEAD_CSETS + offset + location] = Game->GetComboCSet(map, screen, location);
        // Delete the original.
        Game->SetComboData(map, screen, location, 0);
      }
    }

    // Update the state so we know we've copied the data.
    Overhead_Data[OVERHEAD_STATE] = OVERHEAD_STATE_WORKING;
  }

  // See if link is standing under a combo in one of the specified layers.
  under = false;
  location = ComboAt(Link->X + 8, Link->Y + 8);
  for (layer = 3; layer <= 6; ++layer) {
    // Skip this layer if it's not in use.
    if (-1 == Overhead_Data[OVERHEAD_SCREENS + layer - 3]) {continue;}
    // Check for there being a non-0 combo at the specified position.
    if (Overhead_Data[OVERHEAD_COMBOS + (layer - 3) * 176 + location]) {
      under = true;
      break;
    }
  }

  // Offsets for scrolling.
  int x = 0;
  int y = 0;
  if (OVERHEAD_STATE_SCROLLING == Overhead_Data[OVERHEAD_STATE]) {
    if (DIR_LEFT == Overhead_Data[OVERHEAD_SCROLL_DIR]) {x = Overhead_Data[OVERHEAD_TIMER];}
    if (DIR_RIGHT == Overhead_Data[OVERHEAD_SCROLL_DIR]) {x = -Overhead_Data[OVERHEAD_TIMER];}
    if (DIR_UP == Overhead_Data[OVERHEAD_SCROLL_DIR]) {y = Overhead_Data[OVERHEAD_TIMER];}
    if (DIR_DOWN == Overhead_Data[OVERHEAD_SCROLL_DIR]) {y = -Overhead_Data[OVERHEAD_TIMER];}
    Overhead_Data[OVERHEAD_TIMER] += OVERHEAD_SCROLL_SPEED;
  }

  // Don't draw if we're under and have it set to be invisible then.
  if (under && OVERHEAD_INVISIBLE) {return;}

  // Draw the overhead layers.
  int opaque = Cond(under, OP_TRANS, OP_OPAQUE);
  for (layer = 3; layer <= 6; ++layer) {
    // Make sure the layer exists.
    if (-1 == Overhead_Data[OVERHEAD_SCREENS + layer - 3]) {continue;}

    // Draw the layer.
    offset = (layer - 3) * 176;
    for (location = 0; location < 176; ++location) {
      int combo = Overhead_Data[OVERHEAD_COMBOS + offset + location];
      if (combo) {
        Screen->FastCombo(layer, ComboX(location) + x, ComboY(location) + y,
                          combo, Overhead_Data[OVERHEAD_CSETS + offset + location],
                          opaque);
      }
    }
  }
}