Advertisement
ZoriaRPG

Merged Scripts for Nightmeres

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