Advertisement
ZoriaRPG

NightmeresCombined Global, Revision 2

Feb 2nd, 2018
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 63.17 KB | None | 0 0
  1. /// Tamamo's Holes, Lava, and Platforms
  2. /// and Barriers + Followers, for Nightmeres (on PZC)
  3. /// Combined together for ease of use, and streamlined for stack efficiency.
  4.  
  5. /// Global Constants, Arrays, and Variables
  6.  
  7. //Common Constant, only need to define once per script file.
  8. const int BIG_LINK                  = 0;   //Set this constant to 1 if using the Large Link Hit Box feature.
  9. const int DIAGONAL_MOVEMENT         = 1; //Enable the option and change this to 0 for nes movement.
  10.  
  11. //Constants used by Bottomless Pits & Lava.
  12. const int CT_HOLELAVA              = 128; //Combo type to use for pit holes and lava."No Ground Enemies by default"
  13. const int CF_PIT                   = 101;  //The combo flag to register combos as pits.
  14. const int CF_LAVA                  = 102;  //The combo flag to register combos as lava.
  15. const int WPS_LINK_FALL            = 89;  //The weapon sprite to display when Link falls into a pit. "Sprite 88 by default"
  16. const int WPS_LINK_LAVA            = 90;  //The weapon sprite to display when Link drowns in lava. "Sprite 89 by default"
  17. const int SFX_LINK_FALL            = 38;  //The sound to play when Link falls into a pit. "SFX_FALL by default"
  18. const int SFX_LINK_LAVA            = 55;  //The sound to play when Link drowns in Lava. "SFX_SPLASH by default.
  19. const int CMB_AUTOWARP             = 48;  //The first of your four transparent autowarp combos.
  20. const int HOLELAVA_DAMAGE          = 8;   //Damage in hit points to inflict on link. "One Heart Container is worth 16 hit points"
  21.  
  22. //Global variables used by Bottomless Pits & Lava.
  23.  
  24. float PitsLava[256];
  25.      //These need to be turned into array indices:    
  26.       int olddmap;
  27.       int oldscreen;
  28.       int startx;
  29.       int starty;
  30.       int startdir;
  31. const int HL_FALLING            = 0;
  32. const int HL_WARPING            = 1;
  33. const int HL_ONPLATFORM         = 3;
  34.  
  35.  
  36. const int CMB_FFC_INVIS         = 1; //Combo higher than ID 0 with an invisible tile.
  37.  
  38. // ID's of barrier-related combos
  39. // Barriers in raised state
  40. const int BARRIER_A_RAISED              = 15036;
  41. const int BARRIER_B_RAISED              = 15038;
  42.  
  43. // Barriers in lowered state
  44. const int BARRIER_A_LOWERED             = 15037;
  45. const int BARRIER_B_LOWERED             = 15039;
  46.  
  47. // Barriers animating to raised state
  48. const int BARRIER_A_ANIMRAISE           = 15041;
  49. const int BARRIER_B_ANIMRAISE           = 15043;
  50.  
  51. // Barriers animating to lowered state
  52. const int BARRIER_A_ANIMLOWER           = 15040;
  53. const int BARRIER_B_ANIMLOWER           = 15042;
  54.  
  55. // Raised barriers that Link can walk on
  56. const int BARRIER_A_WALKABLE            = 15044;
  57. const int BARRIER_B_WALKABLE            = 15045;
  58.  
  59. // Barrier switches
  60. const int BARRIER_A_SWITCH              = 15046;
  61. const int BARRIER_B_SWITCH              = 15047;
  62.  
  63. const int BARRIER_SWITCH_DUMMY      = 191; // ID of a switch hit detection dummy enemy
  64. const int BARRIER_SWITCH_DUMMY_HP   = 32767;
  65.  
  66. // Global array to store the state of barriers per dmap
  67. // If you have more than 16 dmaps you can change the capacity in the []'s
  68. // You may change the states in other scripts, but the changes will not be visible
  69. // until there is a new screen, so set them before Barriers_NewScreen() is called.
  70. bool barriers[255]; // false = blue barriers raised, true = red barriers raised
  71. bool firstCheck; //used by follower  script
  72.  
  73. int curscreen = -1; //Used by barriers, and should be converted to an array index
  74. int switch_index; // and this should be in the same array
  75.  
  76. //Follower script constants.
  77. const int FOLLOWER_FFC_INDEX        = 32; //The number of the FFC used.  This script will "hijack" this one, so don't use it for anything else on screens when you expect the player to have a follower.
  78. const int FOLLOWER_FIRST_COMBO_ID   = 23568; //combo of the first combo.  In order, the concecutive combos must be "still up", "still down", "still left", "still right", "moving up", "moving down", "moving left", "moving right".
  79. const int FOLLOWER_CSET         = 11;
  80. const int FOLLOWER_REQUIRED_ITEM    = 158; //Item that makes the FFC follower follow you
  81.  
  82. //Barriers array indices.
  83. const int BAR_PASTX     = 14; //followerX[]
  84. const int BAR_PASTY     = 14; //followerY[] //why not one array? -Z
  85.  
  86.  
  87. //Global Variables for Sideview Ladder, GB Shield, and Power Bracelet
  88. float GB_Shield[256]; //Array to hold shield values. Set to an arbitrarily large size. Min [3]
  89. //sideview ladder
  90. bool onLadder = false;
  91. //power bracelets
  92. bool throw_disabled;
  93. int holding_block;
  94. bool holding_bush;
  95. int link_catching;
  96.  
  97.  
  98. //Shield Sound Effects
  99. const int SFX_GBSHIELD             = 17; //Shield active SFX
  100.  
  101. //Array indices of GB_Shield[]
  102. const int SHIELD_ITEM              = 0;
  103. const int SHIELD_BUTTON            = 1;
  104. const int SHIELD_ENABLED           = 2;
  105.  
  106.  
  107.  
  108. //NPC constants
  109. const int RESET_NPC_LAYER_ON_ENTRY = 1; //This fix will replace all CMB_NPC_SOLID tiles with CMB_NPC_HIDDEN
  110.                                         //when entering the screen. This should prevent problems with shared
  111.                                         //layers. If you don't want this fix, set it to 0.
  112.  
  113. const int LAYER_NPC = 2; //The layer NPCs use for solid combos
  114. const int CMB_NPC_HIDDEN = 41; //Non-solid combo used for hidden NPCs
  115. const int CMB_NPC_SOLID = 42; //Solid combo placed under visible NPCs
  116.  
  117. const int LAYER_NPC_CANTALK = 4; //The layer used for the speech bubble
  118. const int CMB_NPC_CANTALK = 37; //The combo used for the speech bubble
  119. const int CS_NPC_CANTALK = 8; //The CSet used for the speech bubble
  120.  
  121. const int NPCBT_NONE = 0; //Regular NPCs
  122. const int NPCBT_FACELINK = 1; //NPCs that turn to face Link
  123. const int NPCBT_GUARDH = 2; //NPCs that move along a horizontal path
  124. const int NPCBT_GUARDV = 3; //NPCs that move along a vertical path
  125.  
  126. //Alternate NPC constant
  127. const int CMB_AUTOWARPD = 0; //Only include this once in the script file. Set to the number of an Autowarp-type combo you create, preferably transparent.
  128.  
  129.  
  130.  
  131. //Bracelet constants
  132. const int CF_PICK = 98; // SCRIPT1, bracelet
  133.  
  134. const int SCRIPT_POWERBRACELET = 9; // set this to the ffc script slot assigned to PowerBracelet script when compiling
  135.  
  136. const int LTM_CATCHING = 123; // LTM for Link catching a block with the Power Bracelet
  137. const int LTM_PULLING = 125; // LTM for Link pulling a block with the Power Bracelet
  138. const int LTM_HOLDING = 124; // LTM for Link holding a block with the Power Bracelet
  139.  
  140. const int BLOCK_VH=4; //thrown block/bush horizontal initial velocity
  141. const int BLOCK_VV=0; //thrown block/bush vertical initial velocity
  142. const int BLOCK_DMG=8; //damage dealt to enemies by thrown block/bush
  143. const int LW_BLOCK = 31; //id of a lweapon to be used as thrown block
  144. const float BLOCK_FALL = 0.5; //gravity acceleration for block in sideview screens
  145. const int PB_PULL_TIME=14; // num of frames to wait for pickup with PB
  146. const int PB_UNDERCOMBO=0; // combo to set after picking up a block; set a negative value to have a shift of the original combo
  147.  
  148. const int SFX_PICKUP_BLOCK = 45; // sfx played when link picks up the block
  149. const int SFX_THROW_BLOCK = 51; // sfx played when the block is thrown
  150. const int SFX_CRASH_BLOCK = 11; // sfx of a block crashing
  151.  
  152. const int INV_COMBO_ID = 0; // id of an invisible combo
  153. const int INV_TILE_ID = 4; // id of an invisible tile
  154. const int CRASH_SPR = 88; // sprite for a block crashing at ground
  155. const int BUSH_SPR = 54; // sprite for a bush crashing at ground
  156. const int LAYER_OVER = 4; // an overhead layer
  157.  
  158. const int NPC_ITEMSET = 182; // id of a dummy enemy with type different from "none"
  159.  
  160.  
  161. // Sideview Ladder constant
  162. const int CT_SVLADDER               = 142;      // CT_SCRIPT1, ComboType for Sideview Ladder
  163. const int CF_SVLADDER               = 99;       // CF_SCRIPT2, ComboFlag for Sideview Ladder
  164.  
  165. /// FFC Scripts
  166.  
  167. ffc script Holelava
  168. {
  169.     void run(int warp, bool position, int damage)
  170.     {
  171.         while(true)
  172.         {
  173.             while(!PitsLava[HL_WARPING] || OnPlatform()) Waitframe();
  174.             if(warp > 0)
  175.             {
  176.                 this->Data = CMB_AUTOWARP+warp-1;
  177.                 this->Flags[FFCF_CARRYOVER] = true;
  178.                 Waitframe();
  179.                 this->Data = FFCS_INVISIBLE_COMBO;
  180.                 this->Flags[FFCF_CARRYOVER] = false;
  181.                 Link->Z = Link->Y;
  182.                 PitsLava[HL_WARPING] = 0;
  183.                 Link->DrawXOffset -= Cond(Link->DrawXOffset < 0, -1000, 1000);
  184.                 Link->HitXOffset -= Cond(Link->HitXOffset < 0, -1000, 1000);
  185.                 Quit();
  186.             }
  187.             if(position)
  188.             {
  189.                 Link->X = this->X;
  190.                 Link->Y = this->Y;
  191.             }
  192.             else
  193.             {
  194.                 Link->X = this->InitD[6];
  195.                 Link->Y = this->InitD[7];
  196.             }
  197.             if(damage)
  198.             {
  199.                 Link->HP -= damage;
  200.                 Link->Action = LA_GOTHURTLAND;
  201.                 Link->HitDir = -1;
  202.                 Game->PlaySound(SFX_OUCH);
  203.             }
  204.             Link->DrawXOffset -= Cond(Link->DrawXOffset < 0, -1000, 1000);
  205.             Link->HitXOffset -= Cond(Link->HitXOffset < 0, -1000, 1000);
  206.             PitsLava[HL_WARPING] = 0;
  207.             Waitframe();
  208.         }
  209.     }
  210. }
  211.  
  212.  
  213. ffc script MovingPlatform {
  214.     void run(){
  215.         float oldx = this->X;
  216.         float oldy = this->Y;
  217.         float linkx;
  218.         float linky;
  219.         while(true){
  220.             if ( OnPlatform() == FFCNum(this) ){
  221.                 linkx += this->X - oldx;
  222.                 linky += this->Y - oldy;
  223.                 if ( linkx << 0 != 0 ) {
  224.                     Link->X += linkx << 0;
  225.                     linkx -= linkx << 0;
  226.                 }
  227.                 if ( linky << 0 != 0 ){
  228.                     Link->Y += linky << 0;
  229.                     linky -= linky << 0;
  230.                 }
  231.             }
  232.             else {
  233.                 linkx = 0;
  234.                 linky = 0;
  235.             }
  236.             oldx = this->X;
  237.             oldy = this->Y;
  238.             Waitframe();
  239.         }
  240.     }
  241. }
  242.  
  243.  
  244. /// Global Scripts
  245.  
  246. global script active
  247. {                          
  248.     void run()
  249.     {
  250.         // Initialize variables used to listen on screen changes
  251.         curscreen = -1;
  252.         firstCheck = false; //leave this alone
  253.         ffc follower;
  254.         int followerX[15];
  255.         int followerY[15];
  256.  
  257.         switch_index = 0;
  258.         StartGhostZH();
  259.         InitHoleLava();
  260.         while(true){
  261.             UpdateGhostZH1();
  262.             GameboyShield(); //Handles the gameboy style shield, by MM.
  263.             PowerBracelet();
  264.             _Do_Barriers();
  265.             GLB_Sideview_Ladder();
  266.             _Follower(follower, followerX, followerY);
  267.            
  268.             NesMovementFix();
  269.             Waitdraw();
  270.             UpdateGhostZH2();
  271.             LREx1Ex2ItemSwitch();
  272.             MovingPlatforms();
  273.             RunHoleLava();
  274.             UpdateLadders();
  275.             Waitframe();
  276.         }//end whileloop
  277.     }//end run
  278. }//end global slot2
  279.  
  280. global script OnContinue{
  281.     void run() 
  282.     {
  283.         Link->Item[LTM_CATCHING] = false;
  284.         Link->Item[LTM_HOLDING] = false;
  285.         Link->Item[LTM_PULLING] = false;
  286.         holding_block = 0;
  287.         holding_bush = false;
  288.         link_catching = 0;
  289.     }
  290. }
  291.  
  292. /// Global Functions
  293.  
  294. //Sets or returns if we are on a platform.
  295. int OnPlatform(){return PitsLava[HL_ONPLATFORM];}
  296. void OnPlatform(int a){ PitsLava[HL_ONPLATFORM] = a; }
  297.  
  298. bool OnPlatform (ffc this)
  299. {
  300.      if(CenterLinkX() < this->X - 4) return false;
  301.      else if(CenterLinkX() >= this->X + this->EffectWidth + 4) return false;
  302.      else if(CenterLinkY() < this->Y - 4) return false;
  303.      else if(CenterLinkY() >= this->Y + this->EffectHeight + 4) return false;
  304.      else return true;
  305. }
  306.  
  307. //Used to determine if Link is on a Pit or Lava combo.
  308. int OnPitCombo()
  309. {
  310.     int moving_platform[] = "MovingPlatform";
  311.     int script_num = Game->GetFFCScript(moving_platform);
  312.     int comboLoc = ComboAt(Link->X+8, Link->Y + Cond(BIG_LINK==0, 12, 8));
  313.     for (int i = 1; i <= 32; i++)
  314.     {
  315.         ffc f = Screen->LoadFFC(i);
  316.         if (f->Script == script_num && OnPlatform(f))
  317.             return 0;
  318.     }
  319.    
  320.     if(Screen->ComboT[comboLoc] != CT_HOLELAVA)
  321.         return 0;
  322.     else if(Screen->ComboI[comboLoc] == CF_PIT || Screen->ComboI[comboLoc] == CF_LAVA)
  323.         return Screen->ComboI[comboLoc];
  324.     else if(Screen->ComboF[comboLoc] == CF_PIT || Screen->ComboF[comboLoc] == CF_LAVA)
  325.         return Screen->ComboF[comboLoc];
  326.     else
  327.         return 0;
  328. }
  329.  
  330.  
  331. //Snaps Link to the combo so he appears completely over pit and lava combos.
  332. void SnaptoGrid()
  333. {
  334.     int x = Link->X;
  335.     int y = Link->Y + Cond(BIG_LINK==0, 8, 0);
  336.     int comboLoc = ComboAt(x, y);
  337.  
  338.     //X Axis
  339.     if(Screen->ComboT[comboLoc] == CT_HOLELAVA && Cond(x % 16 == 0, true, Screen->ComboT[comboLoc+1] != CT_HOLELAVA))
  340.         Link->X = ComboX(comboLoc);
  341.     else if(Screen->ComboT[comboLoc+1] == CT_HOLELAVA && Cond(x % 16 == 0, true, Screen->ComboT[comboLoc] != CT_HOLELAVA))
  342.         Link->X = ComboX(comboLoc+1);
  343.     if(Cond(y % 16 == 0, false, Screen->ComboT[comboLoc+16] == CT_HOLELAVA) && Cond(x % 16 == 0, true, Screen->ComboT[comboLoc+17] != CT_HOLELAVA))
  344.         Link->X = ComboX(comboLoc+16);
  345.     else if(Cond(y % 16 == 0, false, Screen->ComboT[comboLoc+17] == CT_HOLELAVA) && Cond(x % 16 == 0, true, Screen->ComboT[comboLoc+16] != CT_HOLELAVA))
  346.         Link->X = ComboX(comboLoc+17);
  347.  
  348.     //Y Axis
  349.     if(Screen->ComboT[comboLoc] == CT_HOLELAVA && Cond(y % 16 == 0, true, Screen->ComboT[comboLoc+16] != CT_HOLELAVA))
  350.         Link->Y = ComboY(comboLoc);
  351.     else if(Screen->ComboT[comboLoc+16] == CT_HOLELAVA && Cond(y % 16 == 0, true, Screen->ComboT[comboLoc] != CT_HOLELAVA))
  352.         Link->Y = ComboY(comboLoc+16);
  353.     if(Cond(x % 16 == 0, false, Screen->ComboT[comboLoc+1] == CT_HOLELAVA) && Cond(y % 16 == 0, true, Screen->ComboT[comboLoc+17] != CT_HOLELAVA))
  354.         Link->Y = ComboY(comboLoc+1);
  355.     else if(Cond(x % 16 == 0, false, Screen->ComboT[comboLoc+17] == CT_HOLELAVA) && Cond(y % 16 == 0, true, Screen->ComboT[comboLoc+1] != CT_HOLELAVA))
  356.         Link->Y = ComboY(comboLoc+17);
  357. }
  358.  
  359. void LREx1Ex2ItemSwitch()
  360. {
  361.     if (Link->PressL && Link->Action != LA_SCROLLING)
  362.     {
  363.         Link->SelectBWeapon(DIR_LEFT);
  364.     }
  365.     if (Link->PressR && Link->Action != LA_SCROLLING)
  366.     {
  367.         Link->SelectBWeapon(DIR_RIGHT);
  368.     }
  369.     if (Link->PressEx1 && Link->Action != LA_SCROLLING)
  370.     {
  371.         Link->SelectAWeapon(DIR_LEFT);
  372.     }
  373.     if (Link->PressEx2 && Link->Action != LA_SCROLLING)
  374.     {
  375.         Link->SelectAWeapon(DIR_RIGHT);
  376.     }
  377. }
  378.  
  379. //Hole_Lava Init. Call before Waitdraw().
  380. void InitHoleLava(){
  381.     //Initialize variables used to store Link's strating position on Screen Init.
  382.             olddmap = Game->GetCurDMap();
  383.             oldscreen = Game->GetCurDMapScreen();
  384.             startx = Link->X;
  385.             starty = Link->Y;
  386.             startdir = Link->Dir;
  387.  
  388.             //Clear global variables used by Bottomless pits.
  389.             PitsLava[HL_FALLING] = 0;
  390.             PitsLava[HL_WARPING] = 0;
  391. }
  392.  
  393. //Main Hole_Lava Rountine. Call after Waitdraw().
  394. void RunHoleLava(){
  395.     if(Link->Action != LA_SCROLLING)
  396.     {
  397.         Update_HoleLava(startx, starty, olddmap, oldscreen, startdir);
  398.         if(Link->Z==0 && !PitsLava[HL_FALLING] && (oldscreen != Game->GetCurDMapScreen() || olddmap != Game->GetCurDMap()))
  399.         {
  400.             olddmap = Game->GetCurDMap();
  401.             oldscreen = Game->GetCurDMapScreen();
  402.             startx = Link->X;
  403.             starty = Link->Y;
  404.             startdir = Link->Dir;
  405.         }
  406.     }
  407. }
  408.  
  409. //Handles Pit Combo Functionality.
  410. void Update_HoleLava(int x, int y, int dmap, int scr, int dir)
  411. {
  412.     lweapon hookshot = LoadLWeaponOf(LW_HOOKSHOT);
  413.     if(hookshot->isValid()) return;
  414.  
  415.     if(PitsLava[HL_FALLING])
  416.     {
  417.         if(IsSideview()) Link->Jump=0;
  418.         PitsLava[HL_FALLING]--;
  419.         if(PitsLava[HL_FALLING] == 1)
  420.         {
  421.             int buffer[] = "Holelava";
  422.             if(CountFFCsRunning(Game->GetFFCScript(buffer)))
  423.             {
  424.                 ffc f = Screen->LoadFFC(FindFFCRunning(Game->GetFFCScript(buffer)));
  425.                 PitsLava[HL_WARPING] = 1;
  426.                 if(f->InitD[1]==0)
  427.                 {
  428.                     f->InitD[6] = x;
  429.                     f->InitD[7] = y;
  430.                 }
  431.             }
  432.             else
  433.             {
  434.                 Link->X = x;
  435.                 Link->Y = y;
  436.                 Link->Dir = dir;
  437.                 Link->DrawXOffset -= Cond(Link->DrawXOffset < 0, -1000, 1000);
  438.                 Link->HitXOffset -= Cond(Link->HitXOffset < 0, -1000, 1000);
  439.                 Link->HP -= HOLELAVA_DAMAGE;
  440.                 Link->Action = LA_GOTHURTLAND;
  441.                 Link->HitDir = -1;
  442.                 Game->PlaySound(SFX_OUCH);
  443.                 if(Game->GetCurDMap()!=dmap || Game->GetCurDMapScreen()!=scr)
  444.                 Link->PitWarp(dmap, scr);
  445.             }
  446.             NoAction();
  447.             Link->Action = LA_NONE;
  448.         }
  449.     }
  450.     else if(Link->Z==0 && OnPitCombo() && !PitsLava[HL_WARPING] && !OnPlatform())
  451.     {
  452.         Link->DrawXOffset += Cond(Link->DrawXOffset < 0, -1000, 1000);
  453.         Link->HitXOffset += Cond(Link->HitXOffset < 0, -1000, 1000);
  454.         int comboflag = OnPitCombo();
  455.         SnaptoGrid();
  456.         Game->PlaySound(Cond(comboflag == CF_PIT, SFX_LINK_FALL, SFX_LINK_LAVA));
  457.         lweapon dummy = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  458.         dummy->UseSprite(Cond(comboflag == CF_PIT, WPS_LINK_FALL, WPS_LINK_LAVA));
  459.         dummy->DeadState = dummy->NumFrames*dummy->ASpeed;
  460.         dummy->DrawXOffset = 0;
  461.         dummy->DrawYOffset = 0;
  462.         PitsLava[HL_FALLING] = dummy->DeadState;
  463.         NoAction();
  464.         Link->Action = LA_NONE;
  465.     }
  466. }
  467.  
  468. //Handles moving platforms
  469. void MovingPlatforms(){
  470.     OnPlatform(0);
  471.     if ( Link->Z == 0 ) {
  472.         int buffer[] = "MovingPlatform";
  473.         for(int i = 1; i <= 32; i++) {
  474.             ffc f = Screen->LoadFFC(i);
  475.             if(f->Script != Game->GetFFCScript(buffer)) continue;
  476.             if(Abs(Link->X + 8 - CenterX(f)) >= f->TileWidth*8) continue;
  477.             if(Abs(Link->Y + 12 - CenterY(f)) >= f->TileHeight*8) continue;
  478.             OnPlatform(FFCNum(f));
  479.             break;
  480.         }
  481.     }
  482. }
  483.  
  484. //Used if we are using NES movement
  485. void NesMovementFix(){
  486.     if(DIAGONAL_MOVEMENT==0 && (Link->InputUp || Link->InputDown)){
  487.         Link->InputLeft = false;
  488.         Link->InputRight = false;
  489.     }
  490. }
  491.  
  492. // Function that makes preparations for barriers on each screen and starts an FFC script
  493. void Barriers_NewScreen()
  494. {
  495.     int cd; int cd2; int i; int j;
  496.     // Search for a barrier-related combo
  497.     for (i = 0; i <= 175; ++i)
  498.     {
  499.         cd = Screen->ComboD[i];
  500.         if (cd == BARRIER_A_RAISED || cd == BARRIER_A_LOWERED || cd == BARRIER_A_SWITCH ||
  501.             cd == BARRIER_B_RAISED || cd == BARRIER_B_LOWERED || cd == BARRIER_B_SWITCH)
  502.         {
  503.             // A barrier-related combo was found
  504.  
  505.             // Make initial changes to combos
  506.             if (barriers[Game->GetCurLevel()])
  507.             {
  508.                 for (j = i; j <= 175; ++j)
  509.                 {
  510.                     cd2 = Screen->ComboD[j];
  511.                     if (cd2 == BARRIER_A_RAISED) Screen->ComboD[j] = BARRIER_A_LOWERED;
  512.                     else if (cd2 == BARRIER_B_LOWERED) Screen->ComboD[j] = BARRIER_B_RAISED;
  513.                     else if (cd2 == BARRIER_A_SWITCH) Screen->ComboD[j] = BARRIER_B_SWITCH;
  514.                 }
  515.             }
  516.             else
  517.             {
  518.                 for (j = i; j <= 175; ++j)
  519.                 {
  520.                     cd2 = Screen->ComboD[j];
  521.                     if (cd2 == BARRIER_B_RAISED) Screen->ComboD[j] = BARRIER_B_LOWERED;
  522.                     else if (cd2 == BARRIER_A_LOWERED) Screen->ComboD[j] = BARRIER_A_RAISED;
  523.                     else if (cd2 == BARRIER_B_SWITCH) Screen->ComboD[j] = BARRIER_A_SWITCH;
  524.                 }
  525.             }
  526.    
  527.             // So run FFCscript to control barriers
  528.             int fif[]="Barriers";
  529.             ffc f = Screen->LoadFFC(FOLLOWER_FFC_INDEX);
  530.             f->Script = Game->GetFFCScript(fif);
  531.             f->Data = CMB_FFC_INVIS;
  532.             f->X = -100;
  533.             f->Y = -100;
  534.             f->Flags[FFCF_PRELOAD] = true;
  535.             break;
  536.         }
  537.     }
  538. }
  539.  
  540. // This lets you toggle barriers on any dmap
  541. bool ToggleBarriers(int dmap)
  542. {
  543.     if (dmap == Game->GetCurLevel()) ToggleBarriers();
  544.     else barriers[dmap] = !barriers[dmap];
  545.     return barriers[dmap];
  546. }
  547.  
  548. // This toggles barriers on the current dmap
  549. bool ToggleBarriers()
  550. {
  551.     int cd;
  552.     int curdmap = Game->GetCurLevel();
  553.     if (!barriers[curdmap])
  554.     {
  555.         barriers[curdmap] = true;
  556.         for (int i = 0; i <= 175; ++i)
  557.         {
  558.             cd = Screen->ComboD[i];
  559.             if (cd == BARRIER_A_RAISED || cd == BARRIER_A_WALKABLE || cd == BARRIER_A_ANIMRAISE)
  560.             {
  561.                 Screen->ComboD[i] = BARRIER_A_ANIMLOWER;
  562.             }
  563.             else if (cd == BARRIER_B_LOWERED || cd == BARRIER_B_ANIMLOWER)
  564.             {
  565.                 Screen->ComboD[i] = BARRIER_B_ANIMRAISE;
  566.             }
  567.             else if (cd == BARRIER_A_SWITCH)
  568.             {
  569.                 Screen->ComboD[i] = BARRIER_B_SWITCH;
  570.             }
  571.         }
  572.     }
  573.     else
  574.     {
  575.         barriers[curdmap] = false;
  576.         for (int i = 0; i <= 175; ++i)
  577.         {
  578.             cd = Screen->ComboD[i];
  579.             if (cd == BARRIER_B_RAISED || cd == BARRIER_B_WALKABLE || cd == BARRIER_B_ANIMRAISE) #
  580.             {
  581.                 Screen->ComboD[i] = BARRIER_B_ANIMLOWER;
  582.             }
  583.             else if (cd == BARRIER_A_LOWERED || cd == BARRIER_A_ANIMLOWER)
  584.             {
  585.                 Screen->ComboD[i] = BARRIER_A_ANIMRAISE;
  586.             }
  587.             else if (cd == BARRIER_B_SWITCH)
  588.             {
  589.                 Screen->ComboD[i] = BARRIER_A_SWITCH;
  590.             }
  591.         }
  592.     }
  593.  
  594.     return barriers[curdmap];
  595. }
  596.  
  597. // This script controls barriers on the screen
  598. // The FFC is automatically created by Barriers_NewScreen()
  599. ffc script Barriers
  600. {
  601.     void run()
  602.     {
  603.  
  604.         // Initialize storage for bswitch hit dummies
  605.         int bswitch_count;
  606.         npc bswitch[8]; int i; int j;
  607.  
  608.         for (i = 0; i <= 175; ++i)
  609.         {
  610.             if (Screen->ComboD[i] == BARRIER_A_SWITCH || Screen->ComboD[i] == BARRIER_B_SWITCH)
  611.             {
  612.                 npc bs = CreateNPCAt(BARRIER_SWITCH_DUMMY, ComboX(i), ComboY(i));
  613.                 bs->HitWidth = 8; // Smaller hit box to avoid annoying collisions with Link
  614.                 bs->HitHeight = 8;
  615.                 bs->HP = BARRIER_SWITCH_DUMMY_HP;
  616.                 bswitch[bswitch_count++] = bs;
  617.             }
  618.         }
  619.  
  620.         // Change raised barriers to walkable ones if Link enters screen on a raised barrier
  621.         int lcombo = LinkOnComboD();
  622.         bool onbarrier = (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED);
  623.         if (onbarrier)
  624.         {
  625.             for (i = 0; i < 176; ++i)
  626.             {
  627.                 if (Screen->ComboD[i] == BARRIER_A_RAISED)
  628.                 {
  629.                     Screen->ComboD[i] = BARRIER_A_WALKABLE;
  630.                 }
  631.                 else if (Screen->ComboD[i] == BARRIER_B_RAISED)
  632.                 {
  633.                     Screen->ComboD[i] = BARRIER_B_WALKABLE;
  634.                 }
  635.             }
  636.         }
  637.  
  638.  
  639.         while (true)
  640.         {
  641.  
  642.             // Detect hits on bswitches, and change combos accordingly
  643.             for (j = 0; j < bswitch_count; ++j)
  644.             {
  645.                 if (bswitch[j]->HP < BARRIER_SWITCH_DUMMY_HP)
  646.                 {
  647.                     bswitch[j]->HP = BARRIER_SWITCH_DUMMY_HP;
  648.                     ToggleBarriers();
  649.                     break; //break so that only one bswitch hit may register per frame
  650.                 }
  651.             }
  652.  
  653.  
  654.             // Make barriers walkable if Link is on raised barriers, or unwalkable if not
  655.             lcombo = LinkOnComboD();
  656.             if (!onbarrier && (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED))
  657.             {
  658.                 onbarrier = true;
  659.                 for (i = 0; i <= 175; ++i)
  660.                 {
  661.                     if (Screen->ComboD[i] == BARRIER_A_RAISED)
  662.                     {
  663.                         Screen->ComboD[i] = BARRIER_A_WALKABLE;
  664.                     }
  665.                     else if (Screen->ComboD[i] == BARRIER_B_RAISED)
  666.                     {
  667.                         Screen->ComboD[i] = BARRIER_B_WALKABLE;
  668.                     }
  669.                 }
  670.             }
  671.             else if (onbarrier && !(lcombo == BARRIER_A_WALKABLE || lcombo == BARRIER_B_WALKABLE))
  672.             {
  673.                 onbarrier = false;
  674.                 for (i = 0; i <= 175; ++i)
  675.                 {
  676.                     if (Screen->ComboD[i] == BARRIER_A_WALKABLE)
  677.                     {
  678.                         Screen->ComboD[i] = BARRIER_A_RAISED;
  679.                     }
  680.                     else if (Screen->ComboD[i] == BARRIER_B_WALKABLE)
  681.                     {
  682.                         Screen->ComboD[i] = BARRIER_B_RAISED;
  683.                     }
  684.                 }
  685.             }
  686.  
  687.             Waitframe();
  688.         }
  689.     }
  690. }
  691.  
  692.  
  693.  
  694. // A utility function that returns the ID of the combo that Link appears to stand on
  695. int LinkOnComboD() {
  696.     return Screen->ComboD[ComboAt(Link->X+8, Link->Y+13)];
  697. }
  698.  
  699. void _Follower(ffc follower, int followerX, int followerY)
  700. {
  701.     if(Link->Item[FOLLOWER_REQUIRED_ITEM])
  702.     {
  703.         if(Link->Action != LA_SCROLLING && follower->Data==0)
  704.         {
  705.             follower = Screen->LoadFFC(FOLLOWER_FFC_INDEX);
  706.             follower->Data = FOLLOWER_FIRST_COMBO_ID;
  707.             follower->CSet = FOLLOWER_CSET;
  708.  
  709.             followerX[BAR_PASTX] = Link->X;
  710.             follower->X = Link->X;
  711.             followerY[BAR_PASTY] = Link->Y;
  712.             follower->Y = Link->Y;
  713.  
  714.             for ( int i = 0; i < 13; i++ )
  715.             {
  716.                 followerX[i] = Link->X;
  717.                 followerY[i] = Link->Y;
  718.             }
  719.  
  720.             firstCheck = true;
  721.         }
  722.         if(Link->Action != LA_SCROLLING)
  723.         {
  724.             if((Link->InputUp || Link->InputDown || Link->InputRight || Link->InputLeft)&&(!(Link->InputA || Link->InputB)))
  725.             {
  726.                 followerX[BAR_PASTX] = follower->X;
  727.                 follower->X = followerX[0];
  728.                 for(switch_index=0; switch_index<12; switch_index++)
  729.                 {
  730.                     followerX[switch_index] = followerX[switch_index + 1];
  731.                 }
  732.                 followerX[12] = Link->X;
  733.  
  734.                 followerY[BAR_PASTY] = follower->Y;
  735.                 follower->Y = followerY[0];
  736.                 for(switch_index=0; switch_index<12; switch_index++)
  737.                 {
  738.                     followerY[switch_index] = followerY[switch_index + 1];
  739.                 }
  740.                 followerY[12] = Link->Y;
  741.             }
  742.  
  743.             if(follower->Y > followerY[BAR_PASTY])
  744.             {
  745.                 follower->Data = FOLLOWER_FIRST_COMBO_ID + 5;
  746.             }
  747.             else if(follower->Y < followerY[BAR_PASTY])
  748.             {
  749.                 follower->Data = FOLLOWER_FIRST_COMBO_ID + 4;
  750.             }
  751.             else if(follower->X > followerX[BAR_PASTX])
  752.             {
  753.                 follower->Data = FOLLOWER_FIRST_COMBO_ID + 7;
  754.             }
  755.             else if(follower->X < followerX[BAR_PASTX])
  756.             {
  757.                 follower->Data = FOLLOWER_FIRST_COMBO_ID + 6;
  758.             }
  759.  
  760.             if(!(Link->InputUp || Link->InputDown || Link->InputRight || Link->InputLeft))
  761.             {
  762.                 if((follower->Data == (FOLLOWER_FIRST_COMBO_ID + 4))||(follower->Data == (FOLLOWER_FIRST_COMBO_ID + 5))||(follower->Data == (FOLLOWER_FIRST_COMBO_ID + 6))||(follower->Data == (FOLLOWER_FIRST_COMBO_ID + 7)))
  763.                 {
  764.                     follower->Data = follower->Data - 4;
  765.                 }
  766.                 else if((follower->Data == (FOLLOWER_FIRST_COMBO_ID + 3))||(follower->Data == (FOLLOWER_FIRST_COMBO_ID + 2))||(follower->Data == (FOLLOWER_FIRST_COMBO_ID + 1))||(follower->Data == (FOLLOWER_FIRST_COMBO_ID)))
  767.                 {
  768.                     //empty else if ??? -Z
  769.                 }
  770.                 else
  771.                 {
  772.                     follower->Data = FOLLOWER_FIRST_COMBO_ID;
  773.                 }
  774.             }
  775.         }
  776.         if(Link->Action == LA_SCROLLING)
  777.         {
  778.             firstCheck = false;
  779.         }
  780.     }
  781. }
  782.  
  783. void _Do_Barriers()
  784. {
  785.     // Keep track of screen changes
  786.     // Run a Barrier script on every screen change
  787.     if (Game->GetCurScreen() != curscreen)
  788.     {
  789.         curscreen = Game->GetCurScreen();
  790.         Barriers_NewScreen();
  791.     }
  792. }
  793.  
  794. void UpdateLadders()
  795. {
  796.     if (onLadder) Link->Dir = DIR_UP;
  797. }
  798.  
  799.  
  800. void PowerBracelet()
  801. {
  802.     if(Link->Item[LTM_HOLDING])
  803.     {
  804.         if(CountFFCsRunning(SCRIPT_POWERBRACELET)==0 && holding_block>0)
  805.         {
  806.             holding_block = 0;
  807.             Link->Item[LTM_HOLDING] = false;
  808.             Link->Item[LTM_CATCHING] = false;
  809.             Link->Item[LTM_PULLING] = false;
  810.         }
  811.     }
  812. }
  813.  
  814.  
  815. // Global function that doesn't get us stuck as always climbing when leaving an FFC sideview ladder screen while climbing
  816. // sets onLadder to false if it isn't Sideview, or if the Sideview Ladder FFC script isn't present on new screen
  817.  
  818. void FFCBugFix_SVLadder(int oldscreen, int olddmap)
  819. {
  820.     if(!IsSideview()) onLadder = false;
  821.     else
  822.     {
  823.         int buffer[] = "Sideview_Ladder";
  824.         if(CountFFCsRunning(Game->GetFFCScript(buffer)) == 0) onLadder = false;
  825.     }
  826. }
  827.  
  828.  
  829.  
  830. // Global version of Sideview Ladder script.  
  831. // If you have lots of screens using the sideview ladder this will save you the hassle of having to place the FFC on each one
  832. // If using the global, DON'T use the FFC.
  833.  
  834. void GLB_Sideview_Ladder()
  835. {
  836.     onLadder = false;
  837.     if(!IsSideview()) return;
  838.  
  839.     itemdata feather = Game->LoadItemData(I_ROCSFEATHER);
  840.  
  841.     if( isSVLadder(Link->X+8, Link->Y+6) || isSVLadder(Link->X+8, Link->Y+15) )
  842.     {
  843.         // Link is on SV ladder
  844.         onLadder = true;
  845.  
  846.         if(Link->Jump < 0) Link->Jump=0;
  847.  
  848.         if(Link->InputUp)
  849.         {
  850.             if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) )
  851.                 Link->Y--;
  852.         }
  853.  
  854.         else if(Link->InputDown)
  855.         {
  856.             if( !isSolid(Link->X+1, Link->Y+16) && !isSolid(Link->X+8, Link->Y+16) && !isSolid(Link->X+14, Link->Y+16) )
  857.             Link->Y++;
  858.         }
  859.  
  860.         if( (Link->InputRight || Link->InputLeft) && useFeather() && Link->Jump == 0)
  861.         {
  862.             if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) )
  863.             {
  864.                 Game->PlaySound(feather->UseSound);
  865.                 Link->Jump = 1.6 + (feather->Power*0.8);
  866.             }
  867.         }
  868.  
  869.         if(isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+14, Link->Y+16) )
  870.         {
  871.             // Link is standing on solid ground at the base of SV Ladder
  872.             onLadder = false;
  873.  
  874.             if(useFeather())
  875.             {
  876.                 Game->PlaySound(feather->UseSound);
  877.                 Link->Jump = 1.6 + (feather->Power*0.8);
  878.             }
  879.         }
  880.     }
  881.     else if( isSVLadder(Link->X+8,Link->Y+16) )
  882.     {
  883.         // Link is standing on top of SV Ladder
  884.         Link->Jump=0;
  885.  
  886.         if(Link->InputDown)
  887.         {
  888.             Link->Y++;
  889.             onLadder = true;
  890.  
  891.         }
  892.         else if(useFeather())
  893.         {
  894.             Game->PlaySound(feather->UseSound);
  895.             Link->Jump = 1.6 + (feather->Power*0.8);
  896.         }
  897.     }
  898.     else if( isSVLadder(Link->X+8,Link->Y+17) || isSVLadder(Link->X+8,Link->Y+18) )
  899.     {
  900.         // Link is falling above SV Ladder, snap him to grid so we don't miss
  901.  
  902.         Link->Jump = 0;
  903.         Link->Y += 16 - (Link->Y%16);
  904.     }
  905. }//end GLB_Sideview_Ladder
  906.  
  907.  
  908. // ----------------------------------------------------------------------
  909. // Utility functions used by Sideview Ladder
  910. // Useful for other scripts to call for script interactions
  911.  
  912.  
  913. // Returns true if x,y is both the SV Ladder flag and type
  914. bool isSVLadder(int x, int y)
  915. {
  916.    int loc = ComboAt(x,y);
  917.    return( Screen->ComboT[loc] == CT_SVLADDER && ComboFI(loc, CF_SVLADDER) );
  918. }
  919.  
  920. bool isSVLadder(int loc)
  921. {
  922.    return( Screen->ComboT[loc] == CT_SVLADDER && ComboFI(loc, CF_SVLADDER) );
  923. }
  924.  
  925. // returns true if feather is equipped and being used
  926. // could add more checks for more Roc Items in here, or some other type of jumping method, eg L-button.
  927. bool useFeather()
  928. {
  929.    if(GetEquipmentA()==I_ROCSFEATHER && Link->PressA) return true;
  930.    if(GetEquipmentB()==I_ROCSFEATHER && Link->PressB) return true;
  931.    return false;
  932. }
  933.  
  934. //When will I be done editing/fixing these same three scripts as a courtesy for users?! I didn't even write the things! -Z
  935.  
  936.  
  937.  
  938. //----------------------------------------------------------------
  939. // F1.3 Circular Motion
  940. ffc script CircularMotion
  941. {
  942.     void run(int radius, int speed, int angle, int radius2, int angle2)
  943.     {
  944.         if(radius2 == 0) radius2 = radius; //Circle
  945.         if(angle < 0) angle = Rand(360); //Random Start
  946.         int cx = this->X;
  947.         int cy = this->Y;
  948.         while(true)
  949.         {
  950.             angle += speed;
  951.             if(angle < -360)angle+=360; //Wrap if below -360.
  952.             else if(angle > 360)angle-=360; //Wrap if above 360.
  953.             if(angle2==0)
  954.             {
  955.                 this->X = cx + radius*Cos(angle);
  956.                 this->Y = cy + radius2*Sin(angle);
  957.             }
  958.             else //Rotate at center.
  959.             {
  960.                 this->X = cx + radius*Cos(angle)*Cos(angle2) - radius2*Sin(angle)*Sin(angle2);
  961.                 this->Y = cy + radius2*Sin(angle)*Cos(angle2) + radius*Cos(angle)*Sin(angle2);
  962.             }
  963.             Waitframe();
  964.         }
  965.     }
  966. }
  967.  
  968. // -------------
  969.  
  970.  
  971. // Item script
  972. item script PowerBracelet
  973. {
  974.     void run()
  975.     {
  976.         // if(holding_block==0 && holding_item==0 && holding_bomb==0)
  977.         if(holding_block==0) // use this line if not using GB_Shop and GB_Bombs
  978.         {
  979.             if(!link_catching && isSolid(TouchedX(),TouchedY()))
  980.             {
  981.                 link_catching=1;
  982.                 int args[] = {0,0,0,0,0,0,0,0};
  983.                 int id = RunFFCScript(SCRIPT_POWERBRACELET, args);
  984.             }
  985.         }
  986.     }
  987. }
  988.  
  989.  
  990.  
  991. // FFC script (automatically called by the item script - you don't have to place any ffc on the screen for this)
  992. ffc script UsePowerBracelet
  993. {
  994.     void run(int input)
  995.     {
  996.         // initialization
  997.         this->Data = INV_COMBO_ID;
  998.         this->X = -16;
  999.         this->Y = -16;
  1000.         int counter = 0;
  1001.  
  1002.         while(Link->InputA || Link->InputB)
  1003.         {
  1004.             // set link catching the wall / block / bush
  1005.             if(!Link->Item[LTM_CATCHING]) Link->Item[LTM_CATCHING] = true;
  1006.  
  1007.             // to fix a bug...
  1008.             if(!isSolid(TouchedX(),TouchedY())) break;
  1009.  
  1010.             // if pressing opposite direction, set link pulling
  1011.             if(OppositeDir())
  1012.             {
  1013.                 if(!Link->Item[LTM_PULLING]) Link->Item[LTM_PULLING] = true;
  1014.                 counter ++;
  1015.             }
  1016.             else
  1017.             {
  1018.                 if(Link->Item[LTM_PULLING]) Link->Item[LTM_PULLING] = false;
  1019.                 counter = 0;
  1020.             }
  1021.  
  1022.             // if pulling a block or bush for 15 frames or more, pick it up
  1023.             if(counter>PB_PULL_TIME)
  1024.             {
  1025.                 int loc=TouchedComboLoc();
  1026.                 if(Screen->ComboF[loc]==CF_PICK || Screen->ComboI[loc]==CF_PICK)
  1027.                 {
  1028.                     link_catching = 0;
  1029.                     int combo = Screen->ComboD[loc];
  1030.                     int cset = Screen->ComboC[loc];
  1031.                     if(isBush(Screen->ComboT[loc])) holding_bush = true;
  1032.                     else holding_bush = false;
  1033.                     if(PB_UNDERCOMBO<0) Screen->ComboD[loc] += (-PB_UNDERCOMBO);
  1034.                     else Screen->ComboD[loc] = PB_UNDERCOMBO;
  1035.                     ItemSetAt(IS_DEFAULT,loc);
  1036.                     Game->PlaySound(SFX_PICKUP_BLOCK);
  1037.                     throw_disabled = true;
  1038.  
  1039.                     // mid-air block
  1040.                     for(int i=0;i<16;i++)
  1041.                     {
  1042.                         int blockX = (Link->X+ComboX(loc))/2;
  1043.                         int blockY = Link->Y-7;
  1044.                         Screen->FastCombo(LAYER_OVER, blockX, blockY, combo, cset, 128 );
  1045.                         WaitNoAction();
  1046.                     }
  1047.  
  1048.                     // set link holding
  1049.                     holding_block = 1;
  1050.                     if(!Link->Item[LTM_HOLDING]) Link->Item[LTM_HOLDING] = true;
  1051.                     while(throw_disabled || (!Link->InputA && !Link->InputB))
  1052.                     {
  1053.                         if(!Link->InputA && !Link->InputB) throw_disabled = false;
  1054.                         Screen->FastCombo(LAYER_OVER, Link->X, Link->Y - 14, combo, cset, 128 );
  1055.                         if(Link->Invisible || (Link->Action != LA_NONE && Link->Action != LA_WALKING)) break; // break if falling in pit or water!
  1056.                         Waitframe();
  1057.                     }
  1058.                     if(Link->Invisible || (Link->Action != LA_NONE && Link->Action != LA_WALKING)) break; // break if falling in pit or water!
  1059.                     counter = 0;
  1060.                     holding_block = 0;
  1061.                     if(Link->Item[LTM_CATCHING]) Link->Item[LTM_CATCHING] = false;
  1062.                     if(Link->Item[LTM_PULLING]) Link->Item[LTM_PULLING] = false;
  1063.                     if(Link->Item[LTM_HOLDING]) Link->Item[LTM_HOLDING] = false;
  1064.  
  1065.                     // throw block
  1066.                     lweapon w = CreateLWeaponAt(LW_SCRIPT1,Link->X,Link->Y);
  1067.                     w->Damage = BLOCK_DMG;
  1068.                     w->OriginalTile = INV_TILE_ID;
  1069.                     w->NumFrames = 1;
  1070.                     w->Dir = Link->Dir;
  1071.                     w->Step = Floor(BLOCK_VH*100);
  1072.                     w->DrawYOffset = -14;
  1073.                     w->HitXOffset = -4;
  1074.                     w->HitYOffset = -4;
  1075.                     w->HitWidth = 16 + 8;
  1076.                     w->HitHeight = 16 + 8;
  1077.                     w->HitZHeight = 16 + 8;
  1078.                     Game->PlaySound(SFX_THROW_BLOCK);
  1079.                     while(w->DrawYOffset<0 && !isSolid(w->X+8,w->Y+ 8) && !isOutOfScreen(w->X,w->Y,16,16))
  1080.                     {
  1081.                         if(counter<4) Link->Action = LA_ATTACKING;
  1082.                         w->DrawYOffset += Floor(counter*GRAVITY) - BLOCK_VV;
  1083.                         Screen->FastCombo(LAYER_OVER, w->X, w->Y + w->DrawYOffset, combo, cset, 128 );
  1084.                         Waitframe();
  1085.                         counter ++;
  1086.                     }
  1087.                     if(holding_bush) Game->PlaySound(SFX_GRASSCUT);
  1088.                     else Game->PlaySound(SFX_CRASH_BLOCK);
  1089.                     if(w->isValid())
  1090.                     {
  1091.                         w->DeadState = WDS_DEAD;
  1092.                         if(holding_bush) CreateGraphicAt(BUSH_SPR,w->X,w->Y + w->DrawYOffset);
  1093.                         else CreateGraphicAt(CRASH_SPR,w->X,w->Y + w->DrawYOffset);
  1094.                     }
  1095.                     break;
  1096.                 }
  1097.             }
  1098.             NoMoveAction();
  1099.             Waitframe();
  1100.         }
  1101.         link_catching = 0;
  1102.         holding_block = 0;
  1103.         counter = 0;
  1104.         if(Link->Item[LTM_CATCHING]) Link->Item[LTM_CATCHING] = false;
  1105.         if(Link->Item[LTM_PULLING]) Link->Item[LTM_PULLING] = false;
  1106.         if(Link->Item[LTM_HOLDING]) Link->Item[LTM_HOLDING] = false;
  1107.         this->Data = 0;
  1108.         Quit();
  1109.     }
  1110. }
  1111.  
  1112.  
  1113. // utility functions
  1114. bool isBush(int ct)
  1115. {
  1116.     if(ct==CT_BUSH) return true;
  1117.     if(ct==CT_BUSHC) return true;
  1118.     if(ct==CT_BUSHNEXT) return true;
  1119.     if(ct==CT_BUSHNEXTC) return true;
  1120.     if(ct==CT_FLOWERS) return true;
  1121.     if(ct==CT_FLOWERSC) return true;
  1122.     return false;
  1123. }
  1124.  
  1125. // ------------------------------------------
  1126.  
  1127. // x touched by Link
  1128. int TouchedX()
  1129. {
  1130.     int x;
  1131.     if(Link->Dir == DIR_UP) x = Link->X+8;
  1132.     else if(Link->Dir == DIR_DOWN) x = Link->X+8;
  1133.     else if(Link->Dir == DIR_LEFT) x = Link->X-2;
  1134.     else if(Link->Dir == DIR_RIGHT) x = Link->X+18;
  1135.     return x;
  1136. }
  1137.  
  1138. // y touched by Link
  1139. int TouchedY()
  1140. {
  1141.     int y;
  1142.     if(Link->Dir == DIR_UP) y = Link->Y+6;
  1143.     else if(Link->Dir == DIR_DOWN) y = Link->Y+18;
  1144.     else if(Link->Dir == DIR_LEFT) y = Link->Y+8;
  1145.     else if(Link->Dir == DIR_RIGHT) y = Link->Y+8;
  1146.     return y;
  1147. }
  1148.  
  1149. // location of the touched combo
  1150. int TouchedComboLoc()
  1151. {
  1152.     int loc;
  1153.     loc = ComboAt( TouchedX(), TouchedY() );
  1154.     return loc;
  1155. }
  1156.  
  1157. // create a dummy npc and kill it, giving an item
  1158. void ItemSetAt(int itemset,int loc)
  1159. {
  1160.     npc e = Screen->CreateNPC(NPC_ITEMSET);
  1161.     e->ItemSet = itemset;
  1162.     if(e->isValid())
  1163.     {
  1164.         e->X = loc%16*16;
  1165.         e->Y = loc-loc%16;
  1166.     }
  1167.     e->HP = HP_SILENT;
  1168. }
  1169.  
  1170. // function to test if (x,y) is out of the screen
  1171. bool isOutOfScreen(int x, int y, int dx, int dy)
  1172. {
  1173.     if((x+dx) > 16*16) return true;
  1174.     else if(x < 0) return true;
  1175.     else if((y+dy) > 16*11) return true;
  1176.     else if(y < 0) return true;
  1177.     else return false;
  1178. }
  1179.  
  1180. // create a sprite
  1181. int CreateGraphicAt(int sprite, int x, int y)
  1182. {
  1183.     eweapon e = Screen->CreateEWeapon(EW_SCRIPT1);
  1184.     e->HitXOffset = 500;
  1185.     e->UseSprite(sprite);
  1186.     e->DeadState = e->NumFrames*e->ASpeed;
  1187.     e->X = x;
  1188.     e->Y = y;
  1189.     return e->DeadState;
  1190. }
  1191.  
  1192. // inhibit all the movement actions
  1193. void NoMoveAction()
  1194. {
  1195.     Link->InputUp = false;
  1196.     Link->InputDown = false;
  1197.     Link->InputLeft = false;
  1198.     Link->InputRight = false;
  1199. }
  1200.  
  1201.  
  1202. // this utility routine by Saffith checks for walkability of combos
  1203. bool isSolid(int x, int y)
  1204. {
  1205.     if(x<0 || x>255 || y<0 || y>175) return false;
  1206.     int mask=1111b;
  1207.     if(x%16< 8) mask&=0011b;
  1208.     else mask&=1100b;
  1209.     if(y%16< 8) mask&=0101b;
  1210.     else mask&=1010b;
  1211.     return (!(Screen->ComboS[ComboAt(x, y)]&mask)==0);
  1212. }
  1213.  
  1214. // gives true if Link pushes the opposite direction of his facing direction
  1215. bool OppositeDir()
  1216. {
  1217.     if(Link->InputDown && Link->Dir==DIR_UP) return true;
  1218.     if(Link->InputUp && Link->Dir==DIR_DOWN) return true;
  1219.     if(Link->InputRight && Link->Dir==DIR_LEFT) return true;
  1220.     if(Link->InputLeft && Link->Dir==DIR_RIGHT) return true;
  1221.     else return false;
  1222. }
  1223.  
  1224. // -----------------------------
  1225.  
  1226.  
  1227. //F1.4 Moosh NPC
  1228. //Useful for...? Stuff.
  1229. //Solid, but needs to be aligned to grid, pixel-perfect
  1230.  
  1231. ffc script NPCScript{
  1232.     void run(int String, int ItemCheck, int Type, int Arg1, int Arg2, int NoSolid, int Script){
  1233.         //Stores the NPC's combo, hides it
  1234.         int Combo = this->Data;
  1235.         this->Data = CMB_NPC_HIDDEN;
  1236.         //Waits until the NPC should appear and shows it
  1237.         if(ItemCheck<0){
  1238.             while(!Link->Item[Abs(ItemCheck)]){
  1239.                 Waitframe();
  1240.             }
  1241.             this->Data = Combo;
  1242.             if(Type==NPCBT_FACELINK){
  1243.                 this->Data = Combo + Arg1;
  1244.             }
  1245.         }
  1246.         else if(ItemCheck>0){
  1247.             if(!Link->Item[Abs(ItemCheck)]){
  1248.                 this->Data = Combo;
  1249.                 if(Type==NPCBT_FACELINK){
  1250.                     this->Data = Combo + Arg1;
  1251.                 }
  1252.             }
  1253.         }
  1254.         else if(ItemCheck==0){
  1255.             this->Data = Combo;
  1256.             if(Type==NPCBT_FACELINK){
  1257.                 this->Data = Combo + Arg1;
  1258.             }
  1259.         }
  1260.         //Saves the width and height of the FFC for collision checks
  1261.         int Width = 16;
  1262.         int Height = 16;
  1263.         if(this->EffectWidth!=16)
  1264.             Width = this->EffectWidth;
  1265.         else if(this->TileWidth>1)
  1266.             Width = this->TileWidth*16;
  1267.         if(this->EffectHeight!=16)
  1268.             Height = this->EffectHeight;
  1269.         else if(this->TileHeight>1)
  1270.             Height = this->TileHeight*16;
  1271.         //Wait until the screen is done scrolling to avoid a weird ZC crashing bug
  1272.         Waitframe();
  1273.         while(Link->Action==LA_SCROLLING){
  1274.             Waitframe();
  1275.         }
  1276.         //Shared Layer Fix
  1277.         if(RESET_NPC_LAYER_ON_ENTRY==1){
  1278.             if(Screen->LoadFFC(FindFFCRunning(this->Script))==this){
  1279.                 for(int i=0; i<176; i++){
  1280.                     if(GetLayerComboD(LAYER_NPC, i)==CMB_NPC_SOLID){
  1281.                         SetLayerComboD(LAYER_NPC, i, CMB_NPC_HIDDEN);
  1282.                     }
  1283.                 }
  1284.             }
  1285.         }
  1286.         //Sets the space below the NPC or the space a guard NPC occupies to be solid
  1287.         if(LAYER_NPC>-1&&NoSolid==0){
  1288.             if(Type==NPCBT_GUARDH){
  1289.                 for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
  1290.                     for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  1291.                         SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  1292.                     }
  1293.                 }
  1294.             }
  1295.             else if(Type==NPCBT_GUARDV){
  1296.                 for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  1297.                     for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
  1298.                         SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  1299.                     }
  1300.                 }
  1301.             }
  1302.             else{
  1303.                 for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  1304.                     for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  1305.                         SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  1306.                     }
  1307.                 }
  1308.             }
  1309.         }
  1310.         while(true){
  1311.             //Removes NPCs if Link has the required item
  1312.             if(ItemCheck>0){
  1313.                 if(Link->Item[ItemCheck]){
  1314.                     this->Data = CMB_NPC_HIDDEN;
  1315.                     if(LAYER_NPC>-1&&NoSolid==0){
  1316.                         if(Type==NPCBT_GUARDH){
  1317.                             for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
  1318.                                 for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  1319.                                     SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  1320.                                 }
  1321.                             }
  1322.                         }
  1323.                         else if(Type==NPCBT_GUARDV){
  1324.                             for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  1325.                                 for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
  1326.                                     SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  1327.                                 }
  1328.                             }
  1329.                         }
  1330.                         else{
  1331.                             for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  1332.                                 for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  1333.                                     SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  1334.                                 }
  1335.                             }
  1336.                         }
  1337.                     }
  1338.                     Quit();
  1339.                 }
  1340.             }
  1341.             //Handles animation for turning NPCs
  1342.             if(Type==NPCBT_FACELINK&&(Link->X>0&&Link->X<240&&Link->Y>0&&Link->Y<160)){
  1343.                 if(Distance(CenterLinkX(), CenterLinkY(), CenterX(this), CenterY(this))<Arg2)
  1344.                     this->Data = Combo + AngleDir4(Angle(CenterX(this), CenterY(this), CenterLinkX(), CenterLinkY()));
  1345.                 else
  1346.                     this->Data = Combo + Arg1;
  1347.             }
  1348.             //Handles movement for guard NPCs
  1349.             else if(Type==NPCBT_GUARDH){
  1350.                 if(Link->X>16*Arg1-32&&Link->X<16*Arg2+32&&Link->Y>this->Y-32&&Link->Y<this->Y+32){
  1351.                     this->X = Clamp(this->X+(-this->X + Link->X)/4, 16*Arg1, 16*Arg2);
  1352.                 }
  1353.             }
  1354.             else if(Type==NPCBT_GUARDV){
  1355.                 if(Link->X>this->X-32&&Link->X<this->X+32&&Link->Y>16*Arg1-32&&Link->Y<16*Arg2+32){
  1356.                     this->Y = Clamp(this->Y+(-this->Y + Link->Y)/4, 16*Arg1, 16*Arg2);
  1357.                 }
  1358.             }
  1359.             //Facing Up
  1360.             if(Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  1361.                 if(CMB_NPC_CANTALK>0)
  1362.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1363.                 if(Link->PressA){
  1364.                     Link->InputA = false;
  1365.                     Link->PressA = false;
  1366.                     Screen->Message(String);
  1367.                     if(Script>0){
  1368.                         RunFFCScript(Script, 0);
  1369.                     }
  1370.                 }
  1371.             }
  1372.             //Facing Down
  1373.             else if(Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  1374.                 if(CMB_NPC_CANTALK>0)
  1375.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1376.                 if(Link->PressA){
  1377.                     Link->InputA = false;
  1378.                     Link->PressA = false;
  1379.                     Screen->Message(String);
  1380.                     if(Script>0){
  1381.                         RunFFCScript(Script, 0);
  1382.                     }
  1383.                 }
  1384.             }
  1385.             //Facing Left
  1386.             else if(Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
  1387.                 if(CMB_NPC_CANTALK>0)
  1388.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1389.                 if(Link->PressA){
  1390.                     Link->InputA = false;
  1391.                     Link->PressA = false;
  1392.                     Screen->Message(String);
  1393.                     if(Script>0){
  1394.                         RunFFCScript(Script, 0);
  1395.                     }
  1396.                 }
  1397.             }
  1398.             //Facing Right
  1399.             else if(Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
  1400.                 if(CMB_NPC_CANTALK>0)
  1401.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1402.                 if(Link->PressA){
  1403.                     Link->InputA = false;
  1404.                     Link->PressA = false;
  1405.                     Screen->Message(String);
  1406.                     if(Script>0){
  1407.                         RunFFCScript(Script, 0);
  1408.                     }
  1409.                 }
  1410.             }
  1411.             Waitframe();
  1412.         }
  1413.     }
  1414. }
  1415.  
  1416. ffc script NPCScript_Simple{
  1417.     void run(int String, int Script, int D0, int D1, int D2, int D3, int D4, int D5){
  1418.         //Saves the width and height of the FFC for collision checks
  1419.         int Width = 16;
  1420.         int Height = 16;
  1421.         if(this->EffectWidth!=16)
  1422.             Width = this->EffectWidth;
  1423.         else if(this->TileWidth>1)
  1424.             Width = this->TileWidth*16;
  1425.         if(this->EffectHeight!=16)
  1426.             Height = this->EffectHeight;
  1427.         else if(this->TileHeight>1)
  1428.             Height = this->TileHeight*16;
  1429.         while(true){
  1430.             //Facing Up
  1431.             if(Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  1432.                 if(CMB_NPC_CANTALK>0)
  1433.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1434.                 if(Link->PressA){
  1435.                     Link->InputA = false;
  1436.                     Link->PressA = false;
  1437.                     Screen->Message(String);
  1438.                     if(Script>0){
  1439.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  1440.                         RunFFCScript(Script, Args);
  1441.                     }
  1442.                 }
  1443.             }
  1444.             //Facing Down
  1445.             else if(Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  1446.                 if(CMB_NPC_CANTALK>0)
  1447.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1448.                 if(Link->PressA){
  1449.                     Link->InputA = false;
  1450.                     Link->PressA = false;
  1451.                     Screen->Message(String);
  1452.                     if(Script>0){
  1453.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  1454.                         RunFFCScript(Script, Args);
  1455.                     }
  1456.                 }
  1457.             }
  1458.             //Facing Left
  1459.             else if(Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
  1460.                 if(CMB_NPC_CANTALK>0)
  1461.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1462.                 if(Link->PressA){
  1463.                     Link->InputA = false;
  1464.                     Link->PressA = false;
  1465.                     Screen->Message(String);
  1466.                     if(Script>0){
  1467.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  1468.                         RunFFCScript(Script, Args);
  1469.                     }
  1470.                 }
  1471.             }
  1472.             //Facing Right
  1473.             else if(Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
  1474.                 if(CMB_NPC_CANTALK>0)
  1475.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  1476.                 if(Link->PressA){
  1477.                     Link->InputA = false;
  1478.                     Link->PressA = false;
  1479.                     Screen->Message(String);
  1480.                     if(Script>0){
  1481.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  1482.                         RunFFCScript(Script, Args);
  1483.                     }
  1484.                 }
  1485.             }
  1486.             Waitframe();
  1487.         }
  1488.     }
  1489. }
  1490.  
  1491. const int D_TRADE = 0; //Screen->D value used for the trade sequence state
  1492.  
  1493. ffc script TradeSequence{
  1494.     void run(int CheckItem, int TradeItem, int NoItemString, int HasItemString, int TradedString){
  1495.         //Check if the player has already traded
  1496.         if(Screen->D[D_TRADE]==0){
  1497.             //If player hasn't traded and has the required item, play HasItemString, give the new item, and take the old item
  1498.             if(Link->Item[CheckItem]){
  1499.                 Screen->Message(HasItemString);
  1500.                 WaitNoAction();
  1501.                 item itm = CreateItemAt(TradeItem, Link->X, Link->Y);
  1502.                 itm->Pickup = IP_HOLDUP;
  1503.                 Link->Item[CheckItem] = false;
  1504.                 Screen->D[D_TRADE] = 1;
  1505.                 WaitNoAction();
  1506.             }
  1507.             //If player hasn't traded and doesn't have the required item, play NoItemString
  1508.             else{
  1509.                 Screen->Message(NoItemString);
  1510.                 WaitNoAction();
  1511.             }
  1512.         }
  1513.         //If the player has already traded, play TradedString
  1514.         else{
  1515.             Screen->Message(TradedString);
  1516.             WaitNoAction();
  1517.         }
  1518.     }
  1519. }
  1520.  
  1521. //---------------------------------------------------------------
  1522.  
  1523. //F1.5 Alternate NPC
  1524. //Useful for triggering stuff
  1525. //No NPC solidarity
  1526.  
  1527. // FFC script for talking NPCs with different functions
  1528. // It's pretty much a sign you can approach from any side.
  1529. // d0: String number to be displayed
  1530. // D1: Set to anything other than zero. Tells the ffc that this NPC has more than one message. Use string control codes to determine what message to display. Use \3\x\y\z at the beginning of your string where X is Zero, Y is one and Z is the string to switch to.
  1531. // D2: If you want the NPC to warp you to another screen after you talk to it. Set to anything other than zero to activate. Uses Sidewarp D to set destination.
  1532. // D3: If you want the NPC to heal you fully after you talk to it. Set to anything other than zero to activate.
  1533. // D4: The counter to check for amount listed in D5. If requirements are met, screen secrets are triggered. Check std_constants for countertypes.
  1534. // D5: Used to test in-game counters. Can be used for collectibles, either existing or created. Set to Zero if this NPC doesn't require certain items.
  1535.  
  1536. ffc script altnpcscript
  1537. {
  1538.     void run(int message, int differentmessage, int warpoccurs, int healoccurs, int countertype, int amount)
  1539.     {
  1540.     // So that people don't have to be pixel perfect on placing npcs.
  1541.     this->X = Round(this->X / 8) * 8;
  1542.     this->Y = Round(this->Y / 8) * 8;
  1543.                
  1544.         while(true)
  1545.         {
  1546.         // Set up some values to make the if statement smaller.
  1547.         int LinkX = Link->X + 8;
  1548.         int LinkY = Link->Y + 8;
  1549.            
  1550.         int thisX = Round(this->X / 8) * 8;
  1551.         int thisY = Round(this->Y / 8) * 8;
  1552.            
  1553.         int centerX = thisX + this->EffectWidth / 2;
  1554.         int centerY = thisY + this->EffectHeight / 2;
  1555.            
  1556.         // If Link is on one of the sides of the NPC and facing it
  1557.         if(
  1558.             ((Abs(LinkX - centerX) < this->EffectWidth / 2 && Abs(LinkY - centerY) <= this->EffectHeight / 2 + 12 && LinkY < centerY && Link->Dir == DIR_DOWN) ||
  1559.             (Abs(LinkX - centerX) < this->EffectWidth / 2 && Abs(LinkY - centerY) <= this->EffectHeight / 2 + 4 && LinkY > centerY && Link->Dir == DIR_UP) ||
  1560.             (Abs(LinkY + 3 - centerY) < this->EffectHeight / 2 && Abs(LinkX - centerX) <= this->EffectWidth / 2 + 12 && LinkX < centerX && Link->Dir == DIR_RIGHT) ||
  1561.             (Abs(LinkY + 3- centerY) < this->EffectHeight / 2 && Abs(LinkX - centerX) <= this->EffectWidth / 2 + 12 && LinkX > centerX && Link->Dir == DIR_LEFT)))
  1562.             {
  1563.                     // If the player talks to the NPC. Automatically uses L to reduce arguments on NPCs. can be changed to the button of your choice.
  1564.             if(Link->InputA)
  1565.                 {
  1566.                         // Show the message
  1567.                         int perm;//A variable which will be zero until you speak with the NPC.
  1568.                         //If this NPC says more than one thing, this code runs.
  1569.                         if(differentmessage !=0 && Screen->D[perm] == 1){
  1570.                             Screen->Message(message);
  1571.                             //Check to see if you've spoken to this NPC and it wants a certain # of items.
  1572.                             if ( Game->Counter[countertype] >= amount && Screen->State[ST_SECRET] == false && Screen->D[perm] == 1  && amount != 0) {
  1573.                                 Game->PlaySound(27);
  1574.                                 Screen->TriggerSecrets();
  1575.                                 Screen->State[ST_SECRET] = true;
  1576.                             }
  1577.                             //Heals Link if this NPC does that.
  1578.                             if(healoccurs != 0){
  1579.                                 Link->HP = Link->MaxHP;
  1580.                                 Link->MP = Link->MaxMP;
  1581.                             }
  1582.                             //Warps Link if this NPC does that.
  1583.                             if(warpoccurs != 0){
  1584.                                 Waitframe();
  1585.                                 this->Data = CMB_AUTOWARPD;
  1586.                     }
  1587.                         }
  1588.                         //All other NPC functions.
  1589.                         else{
  1590.                             Screen->Message(message);
  1591.                             if (Screen->D[perm]){
  1592.                                 return;
  1593.                             }
  1594.                             else{
  1595.                                 Waitframe();
  1596.                                 Screen->D[perm] = 1;
  1597.                             }
  1598.                             //Heals Link if this NPC does that.
  1599.                             if(healoccurs != 0){
  1600.                                 Link->HP = Link->MaxHP;
  1601.                                 Link->MP = Link->MaxMP;
  1602.                             }
  1603.                             //Warps Link if this NPC does that.
  1604.                             if(warpoccurs != 0){
  1605.                                 Waitframe();
  1606.                                 this->Data = CMB_AUTOWARPD;
  1607.                     }
  1608.                         }
  1609.              // Wait a bit before letting the npc trigger again.
  1610.              Waitframes(30);
  1611.                      } // End of if Link triggered npc
  1612.                  } // End of Link positioning
  1613.          Waitframe();  
  1614.             } // End of while(true)
  1615.     } // End of void run(int message)
  1616. } // End of ffc script altnpcscript
  1617.  
  1618. //-----------------------------------------------------------------
  1619. //F1.6 RealNPC
  1620. //Solid, non-grid-aligned
  1621.  
  1622. ffc script real_npcV2 {
  1623.   void run(int m, int gmitem, int f, int d, int def_dir, int npcissolid, int gm_min, int gm_max) {
  1624.     int d_x;
  1625.     int d_y;
  1626.     int a_x;
  1627.     int a_y;
  1628.     int ir;
  1629.     int tho=(this->TileHeight*16-16);
  1630.     int orig_d = this->Data;
  1631.     int Apressed2;  
  1632.     int Appr2;
  1633.     int onscreenedge;
  1634.     if(d == 0) d = 48;
  1635.  
  1636.  
  1637.     while(true) {
  1638.         //This detects if link is on the edge of the screen
  1639.         if (Link->X<8 || Link->Y<8 || Link->X>232 || Link->Y>152){onscreenedge=1;} else {onscreenedge=0;}
  1640.  
  1641.         //This checks if you're above or below the NPC to create an overhead effect
  1642.         if (Link->Y<this->Y-8+tho && onscreenedge==0){this->Flags[FFCF_OVERLAY] = true;} else {this->Flags[FFCF_OVERLAY] = false;}
  1643.  
  1644.         //This detects if A was pressed, allowing you to exit messages with the A button
  1645.         if (Link->InputA)
  1646.         {
  1647.             if (Apressed2==1){Apressed2=0;}
  1648.         else
  1649.         {
  1650.             if (Appr2==0){Apressed2=1; Appr2=1;}}
  1651.         }
  1652.         else
  1653.         {
  1654.             Apressed2=0;
  1655.             Appr2=0;
  1656.         }
  1657.  
  1658.         d_x = this->X - Link->X;
  1659.         d_y = this->Y+(this->TileHeight*16-16) - Link->Y;
  1660.         a_x = Abs(d_x);
  1661.         a_y = Abs(d_y);
  1662.    
  1663.         if(f != 0) {
  1664.             if(a_x < d && a_y < d) {
  1665.                   if(a_x <= a_y) {
  1666.                     if(d_y >= 0) {
  1667.                           this->Data = orig_d + DIR_DOWN;
  1668.                     } else {
  1669.                         this->Data = orig_d + DIR_UP;
  1670.                     }
  1671.                 } else {
  1672.                     if(d_x >= 0) {
  1673.                         this->Data = orig_d + DIR_LEFT;
  1674.                     } else {
  1675.                         this->Data = orig_d + DIR_RIGHT;
  1676.                     }
  1677.                   }
  1678.             } else {
  1679.                 this->Data = orig_d + def_dir;
  1680.             }
  1681.         }
  1682.        
  1683.         //This checks if you have item D1, and makes the NPC disappear if you do.
  1684.         if (Link->Item[gmitem] == true){this->X=-256; this->Y=-256;}
  1685.         else
  1686.         {
  1687.  
  1688.             //This enables horizontal guard mode.
  1689.             if (gm_max>0)
  1690.             {
  1691.                 if (Link->X>gm_min-32 && Link->X<gm_max+32 && Link->Y>this->Y+tho-32 && Link->Y<this->Y+tho+32) {ir=1;}
  1692.                 else {ir=0;}
  1693.                 if (Link->X<this->X-2 && this->X>gm_min && ir==1)
  1694.                 {
  1695.                     if (Link->X>gm_min){this->Vx= (- this->X + Link->X)/4;}
  1696.                     else{this->Vx= (- this->X + gm_min)/4;}
  1697.                 }
  1698.                 if (Link->X>this->X+2 && this->X<gm_max && ir==1)
  1699.                 {
  1700.                     if (Link->X<gm_max){this->Vx= (Link->X - this->X)/4;}
  1701.                     else{this->Vx= (gm_max - this->X)/4;}
  1702.                 }
  1703.                 if (Link->X<this->X+2 && Link->X>this->X-2){this->Vx=0;}
  1704.                 if (ir==0){this->Vx=0;}
  1705.                 if (this->X<gm_min+1){
  1706.                     if (this->Vx<0) this->Vx=0;
  1707.                         this->X=gm_min;
  1708.                 }
  1709.                 if (this->X>gm_max-1){
  1710.                     if (this->Vx>0) this->Vx=0;
  1711.                     this->X=gm_max;
  1712.             }
  1713.         }
  1714.  
  1715.         //This enables vertical guard mode.
  1716.         if (gm_max<0)
  1717.         {
  1718.             if (Link->Y>-gm_min-32 && Link->Y<-gm_max+32 && Link->X>this->X-32 && Link->X<this->X+32) {ir=1;}
  1719.             else {ir=0;}
  1720.             if (Link->Y<this->Y-2+tho && this->Y+tho>-gm_min && ir==1)
  1721.             {
  1722.                 if (Link->Y>-gm_min){this->Vy= (- this->Y-tho + Link->Y)/4;}
  1723.                 else {this->Vy= (- this->Y-tho + -gm_min)/4;}
  1724.             }
  1725.             if (Link->Y>this->Y+2+tho && this->Y+tho<-gm_max && ir==1)
  1726.             {
  1727.                 if (Link->Y<-gm_max){this->Vy= (Link->Y - this->Y-tho)/4;}
  1728.                 else {this->Vy= (-gm_max - this->Y-tho)/4;}
  1729.             }
  1730.                 if (Link->Y<this->Y+2+tho && Link->Y>this->Y-2+tho){this->Vy=0;}
  1731.                 if (ir==0){this->Vy=0;}
  1732.                 if (this->Y+tho<-gm_min+1){
  1733.                     if (this->Vy<0)this->Vy=0;
  1734.                     this->Y=-gm_min-tho;
  1735.                 }
  1736.                 if (this->Y+tho>-gm_max-1){
  1737.                     if (this->Vy>0)this->Vy=0;
  1738.                     this->Y=-gm_max-tho;
  1739.                 }
  1740.             }
  1741.  
  1742.         }
  1743.  
  1744.         if (this->Vy>0)this->Data = orig_d + DIR_UP;
  1745.         if (this->Vy<0)this->Data = orig_d + DIR_DOWN;
  1746.         if (this->Vx>0)this->Data = orig_d + DIR_RIGHT;
  1747.         if (this->Vx<0)this->Data = orig_d + DIR_LEFT;
  1748.    
  1749.         if(Apressed2==1 && a_x < 24 && a_y < 24) {
  1750.             //This is all checking if Link is facing the NPC while to the left, to the right, above, or below the NPC
  1751.             if (Link->X<this->X-8 && Link->Y>this->Y+tho-12 && Link->Y<this->Y+tho+8 && Link->Dir == DIR_RIGHT || Link->X>this->X+8 && Link->Y>this->Y+tho-12 && Link->Y<this->Y+tho+8 && Link->Dir == DIR_LEFT || Link->Y<this->Y+tho-8 && Link->X>this->X-8 && Link->X<this->X+8 && Link->Dir == DIR_DOWN || Link->Y>this->Y+tho+8 && Link->X>this->X-8 && Link->X<this->X+8 && Link->Dir == DIR_UP){
  1752.                 Apressed2=0;
  1753.                 Screen->Message(m);
  1754.                 Link->InputA = false;
  1755.             }
  1756.         }
  1757.  
  1758.         //This enables the NPC to be solid without having to lay a solid combo under it.
  1759.         if (npcissolid>0){
  1760.             if ((Abs(Link->X - this->X) < 10) &&
  1761.                 (Link->Y <= this->Y+tho + 12) && (Link->Y > this->Y+tho+8)){Link->Y = this->Y+tho+12;}
  1762.            
  1763.             if ((Abs(Link->Y - this->Y-tho) < 10) &&
  1764.                 (Link->X >= this->X - 12) && (Link->X < this->X-8)){Link->X = this->X-12;}
  1765.        
  1766.             if ((Abs(Link->X - this->X) < 10) &&
  1767.                 (Link->Y >= this->Y+tho - 12) && (Link->Y < this->Y+tho-8)){Link->Y = this->Y+tho-12;}
  1768.        
  1769.             if ((Abs(Link->Y - this->Y-tho) < 10) &&
  1770.                 (Link->X <= this->X + 12) && (Link->X > this->X+8)){Link->X = this->X+12;}
  1771.         }
  1772.        
  1773.         Waitframe();
  1774.     }
  1775.   }
  1776. }
  1777.  
  1778.  
  1779.  
  1780.  
  1781. //Handles MoscowModder's Gameboy Shield
  1782. void GameboyShield(){
  1783.     if( !ShieldOn() && ShieldItem() ){ //Enable shield when using dummy
  1784.         ShieldOn(true); //Set shield state to on
  1785.         if ( !Link->Item[ ShieldItem() ] )  Link->Item[ ShieldItem() ] = true; //Give the shield
  1786.         Game->PlaySound(SFX_GBSHIELD); //Play the sound
  1787.     }
  1788.     else if( ( ( ShieldButton() && !Link->InputA )||(!ShieldButton() && !Link->InputB)) //When button is released
  1789.             && ShieldOn() ){ //And shield is still on
  1790.         Link->Item[ ShieldItem() ]=false; //Remove shield
  1791.         ShieldItem(0); //Reset shield item variable
  1792.         ShieldOn(false); //Set shield state to off
  1793.     }
  1794. }
  1795.  
  1796. /////////////////////////////////////
  1797. /// Global Accessors  ///////////////
  1798. /// Setter and Getters for Arrays ///
  1799. /////////////////////////////////////
  1800.  
  1801. //Global setter/getter functions for shield script.
  1802.  
  1803. //Returns if shield is enabled.
  1804. bool ShieldOn(){
  1805.     return ( GB_Shield[SHIELD_ENABLED] != 0 );
  1806. }
  1807.  
  1808. //Sets if shield is enabled.
  1809. bool ShieldOn(bool state){
  1810.     if ( state ) GB_Shield[SHIELD_ENABLED] = 1;
  1811.     else GB_Shield[SHIELD_ENABLED] = 0;
  1812. }
  1813.  
  1814. //Returns if shield is on Button-A
  1815. bool ShieldButton(){
  1816.     return ( GB_Shield[SHIELD_BUTTON] != 0 );
  1817. }
  1818.  
  1819. //Sets if shield is on Button-A
  1820. bool ShieldButton(bool buttonA){
  1821.     if ( buttonA ) GB_Shield[SHIELD_BUTTON] = 1;
  1822.     else GB_Shield[SHIELD_BUTTON] = 0;
  1823. }
  1824.  
  1825. //Returns the item used as the shield in inventory.
  1826. int ShieldItem(){
  1827.     return GB_Shield[SHIELD_ITEM];
  1828. }
  1829.  
  1830. //Sets the inventory item to use as a shield.
  1831. void ShieldItem(int itm){
  1832.     GB_Shield[SHIELD_ITEM] = itm;
  1833. }
  1834.  
  1835.  
  1836. ////////////////////
  1837. /// Item Scripts ///
  1838. ////////////////////
  1839.  
  1840. //MoscowModder's Shield Script
  1841. //D0: "Real" shield item to give
  1842. item script gbshield{
  1843.     void run ( int shield ){
  1844.         ShieldItem(shield);
  1845.         if ( Link->PressB ) ShieldButton(false);
  1846.         else if ( Link->PressA ) ShieldButton(true);
  1847.     }
  1848. }
  1849.  
  1850.  
  1851.  
  1852. // F1.0-F1.1 Sideview Ladder and Global
  1853. // ----------------------------------------------------------------------
  1854. // Setup
  1855. //
  1856. // 1. Modify the constants to fit your needs. It looks for both, so they can potentially be used by other scripts.
  1857. //    If so, the other script will probably want to make sure it isn't both.  isSVLadder function is helpful for this.
  1858. // 2. Use one of the existing globals (see step#3) if no other global scripts.
  1859. //    Or see the samp`  le globals at the bottom of the script to see how to combine.
  1860. // 3. Decide if using the global version or FFC version. DON'T USE BOTH!!!!
  1861. //    Global - if you have lots of screens with the sideview ladder combos
  1862. //    FFC - only a few sideview ladder screens, or want more flexibility reusing the Script ComboTypes/Flags.
  1863. //    Both versions require adding things to the global script.  Each has its own sample global script at the bottom.
  1864.  
  1865. //  3a. If using the FFC version, just place the Sideview_Ladder FFC on that screen. Won't run on non-SV screens.
  1866. //      See the sample global, as there are numerous things to add to global for the FFC version.
  1867. //  3b. If using the global version, add or uncomment the GLB_Sideview_Ladder(); part of the global script.  
  1868. //      See the sample global for what needs to be included.
  1869.  
  1870. // 4. Watch out for compile conflicts with the isSolid function that many other scripts use.
  1871.  
  1872. // Optional Setup
  1873. //
  1874. // Roc's Feather
  1875. // 1. The script looks for only the default Roc Feather item#.  
  1876. //    So if you've changed that, or have multiple levels of Roc items, you'll need to mod that part of the script.
  1877. //
  1878. // Item use on ladder
  1879. // 1. A/B buttons are still enabled, allowing item use on the ladder
  1880. //    Expect weird behavior with certain items due to the script changing Link's direction.
  1881. //    i.e. can stab sword to the side while facing up
  1882. //    If you use the hookshot, you're likely going to need to modify the script to make it work right, or disable it.
  1883.  
  1884.  
  1885. // ----------------------------------------------------------------------
  1886. // Sideview Ladder functions (FFC and global versions)
  1887.  
  1888.  
  1889. // Place the FFC version on any screen with your sideview ladders.  won't run on non Sideview screens
  1890. // DON'T use this AND the global version
  1891.  
  1892. ffc script Sideview_Ladder{
  1893.    void run(){
  1894.       onLadder = false;
  1895.       if(!IsSideview()) Quit();
  1896.  
  1897.       itemdata feather = Game->LoadItemData(I_ROCSFEATHER);
  1898.  
  1899.       while(true){
  1900.          onLadder = false;
  1901.  
  1902.          if( isSVLadder(Link->X+8, Link->Y+6) || isSVLadder(Link->X+8, Link->Y+15) ){
  1903.             // Link is on SV ladder
  1904.             onLadder = true;
  1905.  
  1906.             if(Link->Jump < 0) Link->Jump=0;
  1907.  
  1908.             if(Link->InputUp){
  1909.                if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) )
  1910.                   Link->Y--;
  1911.             }
  1912.  
  1913.             else if(Link->InputDown){
  1914.                if( !isSolid(Link->X+1, Link->Y+16) && !isSolid(Link->X+8, Link->Y+16) && !isSolid(Link->X+14, Link->Y+16) )
  1915.                   Link->Y++;
  1916.             }
  1917.  
  1918.             if( (Link->InputRight || Link->InputLeft) && useFeather() && Link->Jump == 0){
  1919.                if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) ){
  1920.  
  1921.                   Game->PlaySound(feather->UseSound);
  1922.                   Link->Jump = 1.6 + (feather->Power*0.8);
  1923.                }
  1924.             }
  1925.  
  1926.             if(isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+14, Link->Y+16) ){
  1927.                // Link is standing on solid ground at the base of SV Ladder
  1928.                onLadder = false;
  1929.  
  1930.                if(useFeather()){
  1931.                   Game->PlaySound(feather->UseSound);
  1932.                   Link->Jump = 1.6 + (feather->Power*0.8);
  1933.                }
  1934.             }
  1935.          }
  1936.          else if( isSVLadder(Link->X+8,Link->Y+16) ){
  1937.             // Link is standing on top of SV Ladder
  1938.  
  1939.             Link->Jump=0;
  1940.  
  1941.             if(Link->InputDown){
  1942.                Link->Y++;
  1943.                onLadder = true;
  1944.  
  1945.             }else if(useFeather()){
  1946.                Game->PlaySound(feather->UseSound);
  1947.                Link->Jump = 1.6 + (feather->Power*0.8);
  1948.             }
  1949.          }
  1950.          else if( isSVLadder(Link->X+8,Link->Y+17) || isSVLadder(Link->X+8,Link->Y+18) ){
  1951.             // Link is falling above SV Ladder, snap him to grid so we don't miss
  1952.  
  1953.             Link->Jump = 0;
  1954.             Link->Y += 16 - (Link->Y%16);
  1955.          }
  1956.  
  1957.          Waitframe();
  1958.       }// end whileloop
  1959.    }//end run
  1960. }//end ffc Sideview_Ladder
  1961.  
  1962.  
  1963. //end merge (2nd Feb, 2018, Z)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement