Copy to Clipboard Test

Enemy Step & Weapon Triggers Code

import "std.zh"  //only need this once

const int FFC_MISC_ETRIG = 0;       // ffc->Misc[] array index.
const int EW_MISC_EWEAPTRIG = 0;    // eweapon->Misc[] array index

// FFC checks for Enemy collisions.
// D0 = how long the enemy needs to be on the trigger for it to activate
// D1 = how many enemies need to be on the trigger for it to activate
// D2 = only this enemy type will trigger (Guy-type 0 won't work)
// D3 = only this enemy ID will trigger
// D4 = sensitive trigger? 0 = no, 1 = yes
// D5 = can Link also trigger this?  0 = no, 1 = yes, -1 = attraction, link can't trigger, but enemies are attracted to this combo
// D6 = when activated combo changes to next combo.  0 = no, 1 = yes, 2 = yes, and saved for when screen revisited
//      Note: can't use D6=2 with temp secrets (D7=2), script will attempt to set D6 to 1 if secrets are temporary
// D7 = is this the only trigger on screen?  0 = no, 1 = yes perm secrets, 2 = yes temp secrets.
//                                          <0 = trigger is unset without constant collision in this many frames
//      if D7 <= 0, you'll need the FFC_EnemyTriggerCheck or FFC_EnemyTriggerOrder on screen as well

// Note about attraction feature (D5=-1) for the step tiles:  
// The attraction places a lweapon Bait on the screen.  While scripts can create numerous baits on screen, Link can only place a bait if there // are no other baits on screen.  So if using the attraction feature, Link won't be able to use his bait weapon on that screen.  However, even // though Link won't place a bait any action script attached to the bait will still run.
// Also, the enemies will always be attracted to the first bait on screen, so if using two attraction tiles on one screen, they will go to the // lowest numbered FFC.

ffc script FFC_EnemyStepTrigger{
   void run(int duration, int numenem, int etype, int eid, int sens, int linktoo, int gotonext, int alone){
      if(Screen->State[ST_SECRET]) Quit();
      if(gotonext == 2 && (Screen->Flags[SF_SECRETS]&2 || alone==2)) gotonext = 1;
      if(alone<=0 && gotonext==2){
         int buffer1[] = "FFC_EnemyTriggerCheck";
         int buffer2[] = "FFC_EnemyTriggerOrder";
         int scriptNum1 = Game->GetFFCScript(buffer1);
         int scriptNum2 = Game->GetFFCScript(buffer1);
         ffc f;

         for(int i=1; i<=32; i++){
            f = Screen->LoadFFC(i);
            if(f->Script == scriptNum1 || f->Script == scriptNum2){
               if(f->InitD[0] == 0) gotonext = 1;
            }
         }
      }
      if(duration <= 0) duration = 1;
      if(numenem <= 0) numenem = 1;

      npc e;
      int curdura = 0;
      int olddura;
      int numCol;
      bool setNext = false;
      int unset;

      this->X = GridX(this->X);
      this->Y = GridY(this->Y);
      int loc = ComboAt(this->X,this->Y);

      if(linktoo == -1){
         lweapon lwbait = CreateLWeaponAt(LW_BAIT,this->X,this->Y);
         lwbait->DrawXOffset = -1000;
         lwbait->DeadState = -1;
      }

      while(this->Misc[FFC_MISC_ETRIG] != -1){
          if(this->Misc[FFC_MISC_ETRIG] == 2){
             curdura = 0;
             this->Misc[FFC_MISC_ETRIG] = 0;
             setNext = false;
             unset = 0;
             if(gotonext == 1) Screen->ComboD[loc]--;
             if(gotonext == 2) Game->SetComboData(Game->GetCurMap(), Game->GetCurScreen(), loc, Screen->ComboD[loc]-1);
          }         

          numCol = 0;
          olddura = curdura;

          for(int i=Screen->NumNPCs(); i>0; i--){
             if(linktoo == 1){
                if(LinkCollision(this,sens)){
                   curdura++;
                   break;
                }
             }

             e = Screen->LoadNPC(i);

             if(etype != 0){
               if(e->Type != etype) continue;
             }
             if(eid != 0){
               if(e->ID != eid) continue;
             }

             if(Collision(e,this,sens)){
                numCol++;
                if(numCol == numenem){
                   curdura++;
                   break;
                }
             }
          }
          if(olddura == curdura) curdura = 0;

          if(curdura >= duration){
             if(gotonext != 0 && !setNext){
                setNext = true;
                if(gotonext == 1) Screen->ComboD[loc]++;
                if(gotonext == 2) Game->SetComboData(Game->GetCurMap(), Game->GetCurScreen(), loc, Screen->ComboD[loc]+1);
             }

             this->Misc[FFC_MISC_ETRIG] = 1;
             if(alone<0) unset = Abs(alone);

             if(alone > 0){
                Game->PlaySound(SFX_SECRET);
                Screen->TriggerSecrets();           
                if(alone==1) Screen->State[ST_SECRET]=true;
                else Screen->State[ST_SECRET]=false;
                Quit();
             }
          }
          else if(alone < 0){
             if(unset<=0){
                this->Misc[FFC_MISC_ETRIG] = 0;
                if(setNext){
                   setNext = false;
                   if(gotonext == 1) Screen->ComboD[loc]--;
                   if(gotonext == 2) Game->SetComboData(Game->GetCurMap(), Game->GetCurScreen(), loc, Screen->ComboD[loc]-1);
                }
             }
             else unset--;
          }

          Waitframe();
      }
   }
}

// FFC checks for enemy weapon collisions
// D0 = eweapon type required to trigger.  0 for any.  eweapon types are found in std_constants.zh
// D1 = number of times the trigger needs to be hit before being triggered
// D2 = sensitive trigger? 0 = no, 1 = yes
// D3 = when activated combo changes to next combo.  0 = no, 1 = yes, 2 = yes, and saved for when screen revisited
//      Note: can't use D3=2 with temp secrets (D4=2), script will attempt to set D3 to 1 if secrets are temporary
// D4 = is this the only trigger on screen?  0 = no, 1 = yes perm secrets, 2 = yes temp secrets.
//                                           <0 = trigger is unset in this many frames
//      if D4 <= 0, you'll need the FFC_EnemyTriggerCheck or FFC_EnemyTriggerOrder on screen as well

ffc script FFC_EnemyWeapTrigger{
   void run(int ewtype, int numtimes, int sens, int gotonext, int alone){
      if(Screen->State[ST_SECRET]) Quit();
      if(gotonext == 2 && (Screen->Flags[SF_SECRETS]&2 || alone==2)) gotonext = 1;
      if(alone<=0 && gotonext==2){
         int buffer1[] = "FFC_EnemyTriggerCheck";
         int buffer2[] = "FFC_EnemyTriggerOrder";
         int scriptNum1 = Game->GetFFCScript(buffer1);
         int scriptNum2 = Game->GetFFCScript(buffer1);
         ffc f;

         for(int i=1; i<=32; i++){
            f = Screen->LoadFFC(i);
            if(f->Script == scriptNum1 || f->Script == scriptNum2){
               if(f->InitD[0] == 0) gotonext = 1;
            }
         }
      }
      if(numtimes <= 0) numtimes = 1;

      eweapon ew;
      int numCol = 0;
      bool setNext = false;
      int unset;

      this->X = GridX(this->X);
      this->Y = GridY(this->Y);
      int loc = ComboAt(this->X,this->Y);

      while(this->Misc[FFC_MISC_ETRIG] != -1){
         if(this->Misc[FFC_MISC_ETRIG] == 2){
            numCol = 0;
            setNext = false;
            unset = 0;
            this->Misc[FFC_MISC_ETRIG] = 0;
            if(gotonext == 1) Screen->ComboD[loc]--;
            if(gotonext == 2) Game->SetComboData(Game->GetCurMap(), Game->GetCurScreen(), loc, Screen->ComboD[loc]-1);
         }         

         for(int i=Screen->NumEWeapons(); i>0; i--){
            ew = Screen->LoadEWeapon(i);
            if(ew->Misc[EW_MISC_EWEAPTRIG] == 1) continue;
            if(ewtype != 0 && ew->ID != ewtype) continue;

            if(Collision(ew,this,sens)){
               numCol++;
               ew->Misc[EW_MISC_EWEAPTRIG] = 1;
            }
         }

         if(numCol >= numtimes){
             if(gotonext != 0 && !setNext){
                setNext = true;
                if(gotonext == 1) Screen->ComboD[loc]++;
                if(gotonext == 2) Game->SetComboData(Game->GetCurMap(), Game->GetCurScreen(), loc, Screen->ComboD[loc]+1);
             }

             this->Misc[FFC_MISC_ETRIG] = 1;
             if(alone<0) unset = Abs(alone);

             if(alone > 0){
                Game->PlaySound(SFX_SECRET);
                Screen->TriggerSecrets();           
                if(alone==1) Screen->State[ST_SECRET]=true;
                else Screen->State[ST_SECRET]=false;
                Quit();
             }
          }

          if(alone<0){
             if(unset<=0){
                if(this->Misc[FFC_MISC_ETRIG] == 1) numCol = 0;

                this->Misc[FFC_MISC_ETRIG] = 0;
                if(setNext){
                   setNext = false;
                   if(gotonext == 1) Screen->ComboD[loc]--;
                   if(gotonext == 2) Game->SetComboData(Game->GetCurMap(), Game->GetCurScreen(), loc, Screen->ComboD[loc]-1);
                }
             }
             else unset--;
          }

         Waitframe();
      }
   }
}

// Checks if all the Enemy Triggers (step or weapon) are currently activated, and sets Screen Secret if they are
// D0 - 0 = secrets temperary, 1 = secrets permanent 
ffc script FFC_EnemyTriggerCheck{
   void run(int temporperm){
      int numTrigs = 0;
      int numATrigs = 0;
      int ffcs[32];
      int buffer1[] = "FFC_EnemyStepTrigger";
      int buffer2[] = "FFC_EnemyWeapTrigger";
      int scriptNum1 = Game->GetFFCScript(buffer1);
      int scriptNum2 = Game->GetFFCScript(buffer2);
      ffc f;
      
      for(int i=1; i<=32; i++){
         f = Screen->LoadFFC(i);
         if(f->Script == scriptNum1 || f->Script == scriptNum2){
            ffcs[i-1] = 1;
            numTrigs++;
         }
      }

      while(true){
         numATrigs = 0;

         for(int i=1; i<=32; i++){
            if(ffcs[i-1] == 0) continue;
            f = Screen->LoadFFC(i);
            if(f->Misc[FFC_MISC_ETRIG] == 1) numATrigs++;
         }

         if(numATrigs == numTrigs){
            Game->PlaySound(SFX_SECRET);
            Screen->TriggerSecrets();           

            if(temporperm) Screen->State[ST_SECRET]=true;
            else Screen->State[ST_SECRET]=false;

            for(int i=1; i<=32; i++){
               if(ffcs[i-1] == 0) continue;
               f = Screen->LoadFFC(i);
               f->Misc[FFC_MISC_ETRIG] = -1;
            }
            
            Quit();
         }

         Waitframe();
      }
   }
}

// Checks if the Enemy Triggers (step or weapon) have been activated in the correct order.  Sets Screen Secret if they have been.
// If activated out of order, they'll all be deactivated.
// Order is defined as the order of the FFC#, so FFC1 -> FFC2 -> FFC3 -> etc
// D0 - 0 = secrets temperary, 1 = secrets permanent 
ffc script FFC_EnemyTriggerOrder{
   void run(int temporperm){
      int numTrigs = 0;
      int curTrig;
      int curATrig = 0;
      bool reset = false;
      bool newATrig = false;
      int ffcs[32];
      int buffer1[] = "FFC_EnemyStepTrigger";
      int buffer2[] = "FFC_EnemyWeapTrigger";
      int scriptNum1 = Game->GetFFCScript(buffer1);
      int scriptNum2 = Game->GetFFCScript(buffer2);
      ffc f;
      
      for(int i=1; i<=32; i++){
         f = Screen->LoadFFC(i);
         if(f->Script == scriptNum1 || f->Script == scriptNum2){
            ffcs[i-1] = 1;
            numTrigs++;
         }
      }

      while(true){
         curTrig = 0;
         newATrig = false;

         for(int i=1; i<=32; i++){
            if(ffcs[i-1] == 0) continue;
            f = Screen->LoadFFC(i);
            curTrig++;
            if(f->Misc[FFC_MISC_ETRIG] == 1){
               if(curTrig > curATrig+1){
                  reset = true;
               }
               else if(curTrig == curATrig+1){
                  newATrig = true;
               }
            }
         }         

         if(reset){
            reset = false;
            newATrig = false;
            curATrig=0;
            for(int i=1; i<=32; i++){
               if(ffcs[i-1] == 0) continue;
               f = Screen->LoadFFC(i);
               if(f->Misc[FFC_MISC_ETRIG] == 1) f->Misc[FFC_MISC_ETRIG] = 2;
            }
         }
         if(newATrig) curATrig++;

         if(numTrigs == curATrig){
            Game->PlaySound(SFX_SECRET);
            Screen->TriggerSecrets();           

            if(temporperm) Screen->State[ST_SECRET]=true;
            else Screen->State[ST_SECRET]=false;

            for(int i=1; i<=32; i++){
               if(ffcs[i-1] == 0) continue;
               f = Screen->LoadFFC(i);
               f->Misc[FFC_MISC_ETRIG] = -1;
            }
            
            Quit();
         }
        
         Waitframe();
      }
   }
}


// Overloaded Collision functions. 
bool Collision(npc e, ffc f, int sens){
   if(sens) return Collision(e,f);
   return SquareCollision(CenterX(e)-4, CenterY(e)-4, 8, CenterX(f)-4, CenterY(f)-4, 8);      
}

bool Collision(eweapon ew, ffc f, int sens){
   if(sens) return Collision(ew,f);
   return SquareCollision(CenterX(ew)-4, CenterY(ew)-4, 8, CenterX(f)-4, CenterY(f)-4, 8);      
}

// Overloaded so that you don't need to remember the order
bool Collision(ffc f, npc e, int sens){
   return Collision(e,f,sens);
}

bool Collision(ffc f, eweapon ew, int sens){
   return Collision(ew,f,sens);
}

// Overloaded Link collision function, with the sensitive or not check as above.
bool LinkCollision(ffc f, int sens){
   if(sens) return LinkCollision(f);
   return SquareCollision(Link->X+4, Link->Y+4, 8, CenterX(f)-4, CenterY(f)-4, 8);    
}