Copy to Clipboard Test

Authentic dungeon barriers Code

const int SCRIPT_BARRIERS = 1; // Must refer to "Barrier"'s ffc script slot in the quest

// ID's of barrier-related combos
// Barriers in raised state
const int BARRIER_A_RAISED           = 32;
const int BARRIER_B_RAISED           = 33;

// Barriers in lowered state
const int BARRIER_A_LOWERED          = 34;
const int BARRIER_B_LOWERED          = 35;

// Barriers animating to raised state
const int BARRIER_A_ANIMRAISE        = 36;
const int BARRIER_B_ANIMRAISE        = 37;

// Barriers animating to lowered state
const int BARRIER_A_ANIMLOWER        = 38;
const int BARRIER_B_ANIMLOWER        = 39;

// Raised barriers that Link can walk on
const int BARRIER_A_WALKABLE         = 40;
const int BARRIER_B_WALKABLE         = 41;

// Barrier switches
const int BARRIER_A_SWITCH           = 42;
const int BARRIER_B_SWITCH           = 43;

const int BARRIER_SWITCH_DUMMY = 177; // ID of a switch hit detection dummy enemy
const int BARRIER_SWITCH_DUMMY_HP = 32767;

// Global array to store the state of barriers per dmap
// If you have more than 16 dmaps you can change the capacity in the []'s
// You may change the states in other scripts, but the changes will not be visible
// until there is a new screen, so set them before Barriers_NewScreen() is called.
bool barriers[16]; // false = blue barriers raised, true = red barriers raised


global script slot2 {
 void run() {
  // Initialize variables used to listen on screen changes
  int curscreen = -1;

  while (true) {
   // Keep track of screen changes
   // Run a Barrier script on every screen change
   if (Game->GetCurScreen() != curscreen) {
    curscreen = Game->GetCurScreen();
    Barriers_NewScreen();}

   Waitframe();}}}


// Function that makes preparations for barriers on each screen and starts an FFC script
void Barriers_NewScreen() {

 // Search for a barrier-related combo
 for (int i = 0; i <= 175; i++) {
  int cd = Screen->ComboD[i];
  if (cd == BARRIER_A_RAISED || cd == BARRIER_A_LOWERED || cd == BARRIER_A_SWITCH ||
      cd == BARRIER_B_RAISED || cd == BARRIER_B_LOWERED || cd == BARRIER_B_SWITCH) {
   // A barrier-related combo was found

   // Make initial changes to combos
   if (barriers[Game->GetCurDMap()]) {
    for (int j = i; j <= 175; j++) {
     int cd = Screen->ComboD[j];
     if (cd == BARRIER_A_RAISED) Screen->ComboD[j] = BARRIER_A_LOWERED;
     else if (cd == BARRIER_B_LOWERED) Screen->ComboD[j] = BARRIER_B_RAISED;
     else if (cd == BARRIER_A_SWITCH) Screen->ComboD[j] = BARRIER_B_SWITCH;}}
   else {
    for (int j = i; j <= 175; j++) {
     int cd = Screen->ComboD[j];
     if (cd == BARRIER_B_RAISED) Screen->ComboD[j] = BARRIER_B_LOWERED;
     else if (cd == BARRIER_A_LOWERED) Screen->ComboD[j] = BARRIER_A_RAISED;
     else if (cd == BARRIER_B_SWITCH) Screen->ComboD[j] = BARRIER_A_SWITCH;}}
   
   // So run FFCscript to control barriers
   int args[] = {0,0,0,0,0,0,0,0};
   RunFFCScript(SCRIPT_BARRIERS, args);
   break;}
}}

// This lets you toggle barriers on any dmap
bool ToggleBarriers(int dmap) {
 if (dmap == Game->GetCurDMap()) ToggleBarriers();
 else barriers[dmap] = !barriers[dmap];
 return barriers[dmap];}

// This toggles barriers on the current dmap
bool ToggleBarriers() {

 int curdmap = Game->GetCurDMap();
 if (!barriers[curdmap]) {
  barriers[curdmap] = true;
  for (int i = 0; i <= 175; i++) {
   int cd = Screen->ComboD[i];
   if (cd == BARRIER_A_RAISED || cd == BARRIER_A_WALKABLE || cd == BARRIER_A_ANIMRAISE) {
    Screen->ComboD[i] = BARRIER_A_ANIMLOWER;}
   else if (cd == BARRIER_B_LOWERED || cd == BARRIER_B_ANIMLOWER) {
    Screen->ComboD[i] = BARRIER_B_ANIMRAISE;}
   else if (cd == BARRIER_A_SWITCH) {Screen->ComboD[i] = BARRIER_B_SWITCH;}}}
 else {
  barriers[curdmap] = false;
  for (int i = 0; i <= 175; i++) {
   int cd = Screen->ComboD[i];
   if (cd == BARRIER_B_RAISED || cd == BARRIER_B_WALKABLE || cd == BARRIER_B_ANIMRAISE) {
    Screen->ComboD[i] = BARRIER_B_ANIMLOWER;}
   else if (cd == BARRIER_A_LOWERED || cd == BARRIER_A_ANIMLOWER) {
    Screen->ComboD[i] = BARRIER_A_ANIMRAISE;}
   else if (cd == BARRIER_B_SWITCH) {Screen->ComboD[i] = BARRIER_A_SWITCH;}}}

 return barriers[curdmap];
}

// This script controls barriers on the screen
// The FFC is automatically created by Barriers_NewScreen()
ffc script Barriers {
 void run() {

  // Initialize storage for bswitch hit dummies
  int bswitch_count;
  npc bswitch[8];

  for (int i = 0; i <= 175; i++) {
   if (Screen->ComboD[i] == BARRIER_A_SWITCH || Screen->ComboD[i] == BARRIER_B_SWITCH) {
    npc bs = CreateNPCAt(BARRIER_SWITCH_DUMMY, ComboX(i), ComboY(i));
    bs->HitWidth = 8; // Smaller hit box to avoid annoying collisions with Link
    bs->HitHeight = 8;
    bs->HP = BARRIER_SWITCH_DUMMY_HP;
    bswitch[bswitch_count++] = bs;}}

  // Change raised barriers to walkable ones if Link enters screen on a raised barrier
  int lcombo = LinkOnComboD();
  bool onbarrier = (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED);
  if (onbarrier) for (int i = 0; i < 176; i++) {
   if (Screen->ComboD[i] == BARRIER_A_RAISED) {Screen->ComboD[i] = BARRIER_A_WALKABLE;}
   else if (Screen->ComboD[i] == BARRIER_B_RAISED) {Screen->ComboD[i] = BARRIER_B_WALKABLE;}}


  while (true) {

   // Detect hits on bswitches, and change combos accordingly
   for (int j = 0; j < bswitch_count; j++) {
    if (bswitch[j]->HP < BARRIER_SWITCH_DUMMY_HP) {
     bswitch[j]->HP = BARRIER_SWITCH_DUMMY_HP;
     ToggleBarriers();
     break;}} //break so that only one bswitch hit may register per frame


   // Make barriers walkable if Link is on raised barriers, or unwalkable if not
   lcombo = LinkOnComboD();
   if (!onbarrier && (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED)) {
    onbarrier = true;
    for (int i = 0; i <= 175; i++) {
     if (Screen->ComboD[i] == BARRIER_A_RAISED) {Screen->ComboD[i] = BARRIER_A_WALKABLE;}
     else if (Screen->ComboD[i] == BARRIER_B_RAISED) {Screen->ComboD[i] = BARRIER_B_WALKABLE;}}}
   else if (onbarrier && !(lcombo == BARRIER_A_WALKABLE || lcombo == BARRIER_B_WALKABLE)) {
    onbarrier = false;
    for (int i = 0; i <= 175; i++) {
     if (Screen->ComboD[i] == BARRIER_A_WALKABLE) {Screen->ComboD[i] = BARRIER_A_RAISED;}
     else if (Screen->ComboD[i] == BARRIER_B_WALKABLE) {Screen->ComboD[i] = BARRIER_B_RAISED;}}}

   Waitframe();}
}}



// A utility function that returns the ID of the combo that Link appears to stand on
int LinkOnComboD() {
 return Screen->ComboD[ComboAt(Link->X+8, Link->Y+13)];
}