Advertisement
Guest User

Global.z

a guest
Dec 1st, 2017
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 124.03 KB | None | 0 0
  1. //Paste your current global script in here
  2.  
  3. //========================================
  4. // Global Globals/Functions/Constants
  5. //========================================
  6. // import "std.zh" // Only need this once.
  7. import "ghost.zh"
  8. // Passive Subscreen A/B Counter Fix
  9. // A fix to display the proper counter for the A and B buttons on the passive subscreen when the quest rule "Can Select A-Button Weapon on Subscreen" is on.
  10. //
  11. // In your Slot2 (or Active) global script, put SetCountersAB(); before the waitframe.
  12. // A sample global script is commented out at the bottom.
  13. //
  14. // See notes below about the constants used ESPECIALLY if your quest makes use of the Script1-25 item counters. If you're not sure, you'll likely be safe with the defaults.
  15. //
  16. // On your passive subscreen, place a Counter object with each Button Item display. Edit the properties.
  17. // On the Attributes Tab, change Item 1 to the corresponding Script counter - default is A Button = Script 24, B Button = Script 25
  18. // Leave "Show Zero" and "Only Selected" UNCHECKED.
  19. //
  20. // Note: make sure that your item has its Counter Reference declared. Edit the item, Pickup tab.
  21. // For instance, Arrows are hardcoded to use either rupees or arrows. Unless the Counter Reference is set, the counter won't show.
  22. // This should point to the item's counter NOT the script counters used by this script.
  23. //
  24.  
  25.  
  26. // Set these constants to unused Script counters. Valid numbers would be 7-31.
  27. // By default they are set to the highest values to hopefully avoid interfering with any other scripts.
  28. // The counter values and associated references are all in std_constants.zh
  29. // You'll need to know the counter reference number NOT the value. So for the defaults, you'll need to use Script Counters 24 & 25.
  30. const int CR_ABUTTON = 30; // Script 24 counter reference
  31. const int CR_BBUTTON = 31; // Script 25 counter reference
  32.  
  33.  
  34. void SetCountersAB(){
  35. itemdata itemA = Game->LoadItemData(GetEquipmentA());
  36. itemdata itemB = Game->LoadItemData(GetEquipmentB());
  37.  
  38. if(GetEquipmentA()==0){
  39. Game->Counter[CR_ABUTTON]=0;
  40. }else if(Game->Counter[CR_ABUTTON]!=Game->Counter[itemA->Counter]){
  41. Game->Counter[CR_ABUTTON]=Game->Counter[itemA->Counter];
  42. }
  43.  
  44. if(GetEquipmentB()==0){
  45. Game->Counter[CR_BBUTTON]=0;
  46. }else if(Game->Counter[CR_BBUTTON]!=Game->Counter[itemB->Counter]){
  47. Game->Counter[CR_BBUTTON]=Game->Counter[itemB->Counter];
  48. }
  49. }
  50.  
  51.  
  52.  
  53. // global script active{
  54. // void run(){
  55. // while(true){
  56. // Might have other stuff here...
  57. //
  58. // SetCountersAB();
  59. //
  60. // Waitframe();
  61. // }
  62. // }
  63. //}
  64.  
  65. const int SCRIPT_BARRIERS = 1; // Must refer to "Barrier"'s ffc script slot in the quest
  66.  
  67. // ID's of barrier-related combos
  68. // Barriers in raised state
  69. const int BARRIER_A_RAISED = 32;
  70. const int BARRIER_B_RAISED = 33;
  71.  
  72. // Barriers in lowered state
  73. const int BARRIER_A_LOWERED = 34;
  74. const int BARRIER_B_LOWERED = 35;
  75.  
  76. // Barriers animating to raised state
  77. const int BARRIER_A_ANIMRAISE = 36;
  78. const int BARRIER_B_ANIMRAISE = 37;
  79.  
  80. // Barriers animating to lowered state
  81. const int BARRIER_A_ANIMLOWER = 38;
  82. const int BARRIER_B_ANIMLOWER = 39;
  83.  
  84. // Raised barriers that Link can walk on
  85. const int BARRIER_A_WALKABLE = 40;
  86. const int BARRIER_B_WALKABLE = 41;
  87.  
  88. // Barrier switches
  89. const int BARRIER_A_SWITCH = 42;
  90. const int BARRIER_B_SWITCH = 43;
  91.  
  92. const int BARRIER_SWITCH_DUMMY = 177; // ID of a switch hit detection dummy enemy
  93. const int BARRIER_SWITCH_DUMMY_HP = 32767;
  94.  
  95. // Global array to store the state of barriers per dmap
  96. // If you have more than 16 dmaps you can change the capacity in the []'s
  97. // You may change the states in other scripts, but the changes will not be visible
  98. // until there is a new screen, so set them before Barriers_NewScreen() is called.
  99. bool barriers[16]; // false = blue barriers raised, true = red barriers raised
  100.  
  101. // Function that makes preparations for barriers on each screen and starts an FFC script
  102. void Barriers_NewScreen() {
  103.  
  104. // Search for a barrier-related combo
  105. for (int i = 0; i <= 175; i++) {
  106. int cd = Screen->ComboD[i];
  107. if (cd == BARRIER_A_RAISED || cd == BARRIER_A_LOWERED || cd == BARRIER_A_SWITCH ||
  108. cd == BARRIER_B_RAISED || cd == BARRIER_B_LOWERED || cd == BARRIER_B_SWITCH) {
  109. // A barrier-related combo was found
  110.  
  111. // Make initial changes to combos
  112. if (barriers[Game->GetCurDMap()]) {
  113. for (int j = i; j <= 175; j++) {
  114. int cd = Screen->ComboD[j];
  115. if (cd == BARRIER_A_RAISED) Screen->ComboD[j] = BARRIER_A_LOWERED;
  116. else if (cd == BARRIER_B_LOWERED) Screen->ComboD[j] = BARRIER_B_RAISED;
  117. else if (cd == BARRIER_A_SWITCH) Screen->ComboD[j] = BARRIER_B_SWITCH;}}
  118. else {
  119. for (int j = i; j <= 175; j++) {
  120. int cd = Screen->ComboD[j];
  121. if (cd == BARRIER_B_RAISED) Screen->ComboD[j] = BARRIER_B_LOWERED;
  122. else if (cd == BARRIER_A_LOWERED) Screen->ComboD[j] = BARRIER_A_RAISED;
  123. else if (cd == BARRIER_B_SWITCH) Screen->ComboD[j] = BARRIER_A_SWITCH;}}
  124.  
  125. // So run FFCscript to control barriers
  126. int args[] = {0,0,0,0,0,0,0,0};
  127. RunFFCScript(SCRIPT_BARRIERS, args);
  128. break;}
  129. }}
  130.  
  131. // This lets you toggle barriers on any dmap
  132. bool ToggleBarriers(int dmap) {
  133. if (dmap == Game->GetCurDMap()) ToggleBarriers();
  134. else barriers[dmap] = !barriers[dmap];
  135. return barriers[dmap];}
  136.  
  137. // This toggles barriers on the current dmap
  138. bool ToggleBarriers() {
  139.  
  140. int curdmap = Game->GetCurDMap();
  141. if (!barriers[curdmap]) {
  142. barriers[curdmap] = true;
  143. for (int i = 0; i <= 175; i++) {
  144. int cd = Screen->ComboD[i];
  145. if (cd == BARRIER_A_RAISED || cd == BARRIER_A_WALKABLE || cd == BARRIER_A_ANIMRAISE) {
  146. Screen->ComboD[i] = BARRIER_A_ANIMLOWER;}
  147. else if (cd == BARRIER_B_LOWERED || cd == BARRIER_B_ANIMLOWER) {
  148. Screen->ComboD[i] = BARRIER_B_ANIMRAISE;}
  149. else if (cd == BARRIER_A_SWITCH) {Screen->ComboD[i] = BARRIER_B_SWITCH;}}}
  150. else {
  151. barriers[curdmap] = false;
  152. for (int i = 0; i <= 175; i++) {
  153. int cd = Screen->ComboD[i];
  154. if (cd == BARRIER_B_RAISED || cd == BARRIER_B_WALKABLE || cd == BARRIER_B_ANIMRAISE) {
  155. Screen->ComboD[i] = BARRIER_B_ANIMLOWER;}
  156. else if (cd == BARRIER_A_LOWERED || cd == BARRIER_A_ANIMLOWER) {
  157. Screen->ComboD[i] = BARRIER_A_ANIMRAISE;}
  158. else if (cd == BARRIER_B_SWITCH) {Screen->ComboD[i] = BARRIER_A_SWITCH;}}}
  159.  
  160. return barriers[curdmap];
  161. }
  162.  
  163. // This script controls barriers on the screen
  164. // The FFC is automatically created by Barriers_NewScreen()
  165. ffc script Barriers {
  166. void run() {
  167.  
  168. // Initialize storage for bswitch hit dummies
  169. int bswitch_count;
  170. npc bswitch[8];
  171.  
  172. for (int i = 0; i <= 175; i++) {
  173. if (Screen->ComboD[i] == BARRIER_A_SWITCH || Screen->ComboD[i] == BARRIER_B_SWITCH) {
  174. npc bs = CreateNPCAt(BARRIER_SWITCH_DUMMY, ComboX(i), ComboY(i));
  175. bs->HitWidth = 8; // Smaller hit box to avoid annoying collisions with Link
  176. bs->HitHeight = 8;
  177. bs->HP = BARRIER_SWITCH_DUMMY_HP;
  178. bswitch[bswitch_count++] = bs;}}
  179.  
  180. // Change raised barriers to walkable ones if Link enters screen on a raised barrier
  181. int lcombo = LinkOnComboD();
  182. bool onbarrier = (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED);
  183. if (onbarrier) for (int i = 0; i < 176; i++) {
  184. if (Screen->ComboD[i] == BARRIER_A_RAISED) {Screen->ComboD[i] = BARRIER_A_WALKABLE;}
  185. else if (Screen->ComboD[i] == BARRIER_B_RAISED) {Screen->ComboD[i] = BARRIER_B_WALKABLE;}}
  186.  
  187.  
  188. while (true) {
  189.  
  190. // Detect hits on bswitches, and change combos accordingly
  191. for (int j = 0; j < bswitch_count; j++) {
  192. if (bswitch[j]->HP < BARRIER_SWITCH_DUMMY_HP) {
  193. bswitch[j]->HP = BARRIER_SWITCH_DUMMY_HP;
  194. ToggleBarriers();
  195. break;}} //break so that only one bswitch hit may register per frame
  196.  
  197.  
  198. // Make barriers walkable if Link is on raised barriers, or unwalkable if not
  199. lcombo = LinkOnComboD();
  200. if (!onbarrier && (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED)) {
  201. onbarrier = true;
  202. for (int i = 0; i <= 175; i++) {
  203. if (Screen->ComboD[i] == BARRIER_A_RAISED) {Screen->ComboD[i] = BARRIER_A_WALKABLE;}
  204. else if (Screen->ComboD[i] == BARRIER_B_RAISED) {Screen->ComboD[i] = BARRIER_B_WALKABLE;}}}
  205. else if (onbarrier && !(lcombo == BARRIER_A_WALKABLE || lcombo == BARRIER_B_WALKABLE)) {
  206. onbarrier = false;
  207. for (int i = 0; i <= 175; i++) {
  208. if (Screen->ComboD[i] == BARRIER_A_WALKABLE) {Screen->ComboD[i] = BARRIER_A_RAISED;}
  209. else if (Screen->ComboD[i] == BARRIER_B_WALKABLE) {Screen->ComboD[i] = BARRIER_B_RAISED;}}}
  210.  
  211. Waitframe();}
  212. }}
  213.  
  214.  
  215.  
  216. // A utility function that returns the ID of the combo that Link appears to stand on
  217. int LinkOnComboD() {
  218. return Screen->ComboD[ComboAt(Link->X+8, Link->Y+13)];
  219. }
  220.  
  221.  
  222. //X--------------------X
  223. //| Bottle Constants |
  224. //X--------------------X
  225.  
  226. const int FFC_SFA = 31; //FFC used for screen freeze A
  227. const int FFC_SFB = 32; //FFC used for screen freeze B
  228. const int CMB_SFA = 2; //Combo used for screen freeze A
  229. const int CMB_SFB = 3; //Combo used for screen freeze B
  230.  
  231. const int BOTTLE_SETTING_NO_WATER = 0; //Set to 1 if water shouldn't be bottleable
  232.  
  233. const int TIL_BOTTLE = 52020; //First of the tiles used for the bottle items. Should come in four identical rows.
  234. //Tile order in each row should go as such:
  235. //Empty, Empty, Red Potion, Green Potion, Blue Potion, Water, Fairy, Bee
  236.  
  237. const int REDPOTION_HEARTS = 8; //Hearts the red potion heals
  238. const int GREENPOTION_MP = 256; //MP the green potion restores
  239. const int BLUEPOTION_HEARTS = 16; //Hearts the blue potion heals
  240. const int BLUEPOTION_MP = 256; //MP the blue potion restores
  241.  
  242. const int LW_WATER = 31; //LWeapon type used for bottled water. Script 1 by default
  243. const int SPR_BOTTLEWATER = 88; //Sprite used for bottled water
  244. const int SFX_BOTTLEWATER = 55; //Sound when water is dumped out
  245.  
  246. const int FAIRY_HEARTS = 3; //Hearts healed by a fairy
  247. const int CMB_FAIRY = 904; //Fairy combo
  248. const int CS_FAIRY = 8; //Fairy cset
  249. const int SFX_FAIRY = 64; //Sound that plays when a fairy appears
  250.  
  251. const int IC_BOTTLE = 67; //Item class used for bottles. Custom 1 by default.
  252.  
  253. const int I_BOTTLE1 = 143; //Item ID for the first bottle (Level 1)
  254. const int I_BOTTLE2 = 144; //Item ID for the second bottle (Level 2)
  255. const int I_BOTTLE3 = 145; //Item ID for the second bottle (Level 3)
  256. const int I_BOTTLE4 = 146; //Item ID for the second bottle (Level 4)
  257.  
  258. const int FREQ_HEARTREFILL = 8; //Frequency in frames at which potions/fairies restore hearts
  259. const int SFX_HEARTREFILL = 22; //Sound when potion/fairy restores a heart
  260. const int FREQ_MAGICSOUND = 8; //Frequency in frames where the magic refill sound plays
  261. const int SFX_MAGICREFILL = 61; //Magic refill sound
  262. const int SFX_ERROR = 62; //Error sound
  263.  
  264. const int TIL_BOTTLESWING = 52006; //Tile of a right facing open bottle used when trying to catch something
  265. const int CS_BOTTLESWING = 11; //CSet of the swinging bottle
  266. const int SFX_BOTTLESWING = 63; //Sound used for the bottle being swung
  267.  
  268. const int I_WATERBOTTLE = 150; //Item for bottle water pickup
  269. const int I_FAIRYBOTTLE = 151; //Item for bottle fairy pickup
  270. const int I_BEEBOTTLE = 152; //Item for bottle bee pickup
  271.  
  272. const int CMB_BEE = 905; //Combo used for the bee
  273. const int CS_BEE = 8; //CSet used for the bee
  274. const int SFX_BEE = 65; //SFX used for the bee
  275. const int LW_BEE = 32; //Lweapon used for the bee (Script 2 by default)
  276. const int EW_BEE = 32; //Eweapon used for the bee (Script 2 by default)
  277. const int DAMAGE_BEE = 4; //Damage the bee deals
  278. const int FFCM_BEE_SELFDESTRUCT = 0; //FFC misc used to tell the bee to disappear
  279.  
  280. const int STR_CANTAFFORD = 2; //Message for when you can't afford an item
  281. const int STR_NOBOTTLE = 3; //Message for when you don't have a bottle to store a potion in
  282.  
  283. const int C_WHITE = 0x01; //The color white
  284. const int C_BLACK = 0x0F; //The color black
  285.  
  286.  
  287. //X--------------------------X
  288. //| Screen Freeze Function |
  289. //X--------------------------X
  290.  
  291. void Screen_Freeze(){
  292. ffc f1 = Screen->LoadFFC(FFC_SFA);
  293. ffc f2 = Screen->LoadFFC(FFC_SFB);
  294. f1->Data = CMB_SFA;
  295. f2->Data = CMB_SFB;
  296. }
  297.  
  298. void Screen_Unfreeze(){
  299. ffc f1 = Screen->LoadFFC(FFC_SFA);
  300. ffc f2 = Screen->LoadFFC(FFC_SFB);
  301. f1->Data = 0;
  302. f2->Data = 0;
  303. }
  304.  
  305.  
  306. //X--------------------------X
  307. //| Empty Bottle Functions |
  308. //X--------------------------X
  309.  
  310. //X--------------------------------------------------------X
  311. //| These constants don't need to be changed. |
  312. //| They just define various states of the empty bottle. |
  313. //| BS_ constants are also used for the potion filling |
  314. //| pickup item script. Look here to see what to set D2 |
  315. //| to for that. |
  316. //X--------------------------------------------------------X
  317. // |
  318. const int BS_EMPTY = 0; // |
  319. const int BS_POTIONRED = 1; // |
  320. const int BS_POTIONGREEN = 2; // |
  321. const int BS_POTIONBLUE = 3; // |
  322. const int BS_WATER = 4; // |
  323. const int BS_FAIRY = 5; // |
  324. const int BS_BEE = 6; // |
  325. // |
  326. const int BSI_BOTTLEUSED = 4; // |
  327. const int BSI_BOTTLETIMER = 5; // |
  328. const int BSI_OLDHP = 6; // |
  329. const int BSI_OLDMP = 7; // |
  330. const int BSI_FAIRYTIMER = 8; // |
  331. const int BSI_FAIRYREVIVE = 9; // |
  332. // |
  333. //---------------------------------------------------------X
  334.  
  335.  
  336. int BottleState[12]; //0-3: States of bottles, 4: Bottle used,
  337. //5: Potion timer, 6: OldHP, 7: OldMP
  338.  
  339. //This function should be called at the beginning of your global and
  340. //refreshes the graphics for the bottles.
  341. void RefreshBottles(){
  342. for(int i=0; i<4; i++){
  343. CopyTile(TIL_BOTTLE+20*i+1+BottleState[i], TIL_BOTTLE+20*i);
  344. }
  345. }
  346.  
  347. int UsingEmptyBottle(){
  348. if(Link->PressA){
  349. int id = GetEquipmentA();
  350. if(id>0){
  351. itemdata A = Game->LoadItemData(id);
  352. if(A->Family==IC_BOTTLE)
  353. return A->Level-1;
  354. }
  355. }
  356. else if(Link->PressB){
  357. int id = GetEquipmentB();
  358. if(id>0){
  359. itemdata B = Game->LoadItemData(id);
  360. if(B->Family==IC_BOTTLE)
  361. return B->Level-1;
  362. }
  363. }
  364. return -1;
  365. }
  366.  
  367. bool CanFillBottle(){
  368. int bottles[4] = {I_BOTTLE1, I_BOTTLE2, I_BOTTLE3, I_BOTTLE4};
  369. for(int i=0; i<4; i++){
  370. if(Link->Item[bottles[i]]&&BottleState[i]==BS_EMPTY)
  371. return true;
  372. }
  373. return false;
  374. }
  375.  
  376. int FillBottle(int state){
  377. int bottles[4] = {I_BOTTLE1, I_BOTTLE2, I_BOTTLE3, I_BOTTLE4};
  378. for(int i=0; i<4; i++){
  379. if(Link->Item[bottles[i]]&&BottleState[i]==BS_EMPTY){
  380. BottleState[i] = state;
  381. RefreshBottles();
  382. return i;
  383. }
  384. }
  385. }
  386.  
  387. int HasFairy(){
  388. int bottles[4] = {I_BOTTLE1, I_BOTTLE2, I_BOTTLE3, I_BOTTLE4};
  389. for(int i=0; i<4; i++){
  390. if(Link->Item[bottles[i]]&&BottleState[i]==BS_FAIRY)
  391. return i;
  392. }
  393. return -1;
  394. }
  395.  
  396. //This function goes in the while loop of your global script before waitdraw
  397. void EmptyBottleGlobal(){
  398. int bottle = BottleState[BSI_BOTTLEUSED];
  399. if(BottleState[BSI_BOTTLETIMER]>0){
  400. if(BottleState[bottle]==BS_POTIONRED){
  401. if(BottleState[BSI_BOTTLETIMER]%FREQ_HEARTREFILL==0){
  402. Link->HP += 16;
  403. Game->PlaySound(SFX_HEARTREFILL);
  404. if(Link->HP>=Link->MaxHP){
  405. BottleState[BSI_BOTTLETIMER] = 0;
  406. }
  407. }
  408. }
  409. else if(BottleState[bottle]==BS_POTIONGREEN){
  410. Link->MP += 2;
  411. if(BottleState[BSI_BOTTLETIMER]%FREQ_MAGICSOUND==0)
  412. Game->PlaySound(SFX_MAGICREFILL);
  413. if(Link->MP>=Link->MaxMP){
  414. BottleState[BSI_BOTTLETIMER] = 0;
  415. }
  416. }
  417. else if(BottleState[bottle]==BS_POTIONBLUE){
  418. if(BottleState[BSI_BOTTLETIMER]%FREQ_HEARTREFILL==0&&Link->HP<BottleState[BSI_OLDHP]+BLUEPOTION_HEARTS*16&&Link->HP<Link->MaxHP){
  419. Link->HP += 16;
  420. Game->PlaySound(SFX_HEARTREFILL);
  421. }
  422. if(Link->MP<BottleState[BSI_OLDMP]+BLUEPOTION_MP&&Link->MP<Link->MaxMP){
  423. if(BottleState[BSI_BOTTLETIMER]%FREQ_MAGICSOUND==0)
  424. Game->PlaySound(SFX_MAGICREFILL);
  425. Link->MP += 2;
  426. }
  427. if(Link->HP>=Link->MaxHP&&Link->MP>=Link->MaxMP){
  428. BottleState[BSI_BOTTLETIMER] = 0;
  429. }
  430. }
  431. else if(BottleState[bottle]==BS_FAIRY){
  432. if(BottleState[BSI_BOTTLETIMER]<2&&BottleState[BSI_FAIRYTIMER]<120)
  433. BottleState[BSI_BOTTLETIMER] = 2;
  434. BottleState[BSI_FAIRYTIMER]++;
  435. int X = Link->X+VectorX(16*(BottleState[BSI_FAIRYTIMER]/120), BottleState[BSI_FAIRYTIMER]*8);
  436. int Y = Link->Y+VectorY(8*(BottleState[BSI_FAIRYTIMER]/120), BottleState[BSI_FAIRYTIMER]*8)-BottleState[BSI_FAIRYTIMER]/8;
  437. if(BottleState[BSI_FAIRYREVIVE]==1){
  438. if(BottleState[BSI_FAIRYTIMER]<10||BottleState[BSI_FAIRYTIMER]>110)
  439. Screen->Rectangle(6, 0, 0, 256, 176, C_BLACK, 1, 0, 0, 0, true, 64);
  440. else
  441. Screen->Rectangle(6, 0, 0, 256, 176, C_BLACK, 1, 0, 0, 0, true, 128);
  442. Screen->FastTile(6, Link->X+Link->DrawXOffset, Link->Y+Link->DrawYOffset, Link->Tile, 6, 128);
  443. }
  444. if(BottleState[BSI_FAIRYTIMER]<80||BottleState[BSI_FAIRYTIMER]%2==0)
  445. Screen->FastCombo(6, X, Y, CMB_FAIRY, CS_FAIRY, 128);
  446. if(BottleState[BSI_BOTTLETIMER]%FREQ_HEARTREFILL==0&&Link->HP<Link->MaxHP){
  447. Link->HP += 16;
  448. Game->PlaySound(SFX_HEARTREFILL);
  449. }
  450. if(Link->HP>=Link->MaxHP&&BottleState[BSI_FAIRYTIMER]>=120){
  451. BottleState[BSI_BOTTLETIMER] = 0;
  452. }
  453. }
  454. BottleState[BSI_BOTTLETIMER]--;
  455. NoAction();
  456. if(BottleState[BSI_BOTTLETIMER]<=0){
  457. BottleState[bottle] = BS_EMPTY;
  458. BottleState[BSI_BOTTLEUSED] = -1;
  459. RefreshBottles();
  460. Screen_Unfreeze();
  461. }
  462. }
  463. else{
  464. bottle = UsingEmptyBottle();
  465. if(bottle>-1){
  466. if(BottleState[bottle]==BS_EMPTY){
  467. int scriptname[] = "Bottle_Empty";
  468. int scriptid = Game->GetFFCScript(scriptname);
  469. int Args[8] = {bottle};
  470. RunFFCScript(scriptid, Args);
  471. }
  472. else if(BottleState[bottle]==BS_POTIONRED){
  473. if(Link->HP==Link->MaxHP){
  474. Game->PlaySound(SFX_ERROR);
  475. }
  476. else{
  477. BottleState[BSI_BOTTLEUSED] = bottle;
  478. BottleState[BSI_BOTTLETIMER] = FREQ_HEARTREFILL*REDPOTION_HEARTS;
  479. Screen_Freeze();
  480. }
  481. }
  482. else if(BottleState[bottle]==BS_POTIONGREEN){
  483. if(Link->MP==Link->MaxMP){
  484. Game->PlaySound(SFX_ERROR);
  485. }
  486. else{
  487. BottleState[BSI_BOTTLEUSED] = bottle;
  488. BottleState[BSI_BOTTLETIMER] = GREENPOTION_MP/2;
  489. Screen_Freeze();
  490. }
  491. }
  492. else if(BottleState[bottle]==BS_POTIONBLUE){
  493. if(Link->HP==Link->MaxHP&&Link->MP==Link->MaxMP){
  494. Game->PlaySound(SFX_ERROR);
  495. }
  496. else{
  497. BottleState[BSI_BOTTLEUSED] = bottle;
  498. BottleState[BSI_BOTTLETIMER] = Max(FREQ_HEARTREFILL*BLUEPOTION_HEARTS, BLUEPOTION_MP/2);
  499. BottleState[BSI_OLDHP] = Link->HP;
  500. BottleState[BSI_OLDMP] = Link->MP;
  501. Screen_Freeze();
  502. }
  503. }
  504. else if(BottleState[bottle]==BS_WATER){
  505. Link->Action = LA_ATTACKING;
  506. lweapon l = CreateLWeaponAt(LW_WATER, Link->X+InFrontX(Link->Dir, 0), Link->Y+InFrontY(Link->Dir, 0));
  507. l->UseSprite(SPR_BOTTLEWATER);
  508. l->DeadState = l->ASpeed*l->NumFrames;
  509. l->CollDetection = false;
  510. Game->PlaySound(SFX_BOTTLEWATER);
  511. BottleState[bottle] = BS_EMPTY;
  512. RefreshBottles();
  513. }
  514. else if(BottleState[bottle]==BS_FAIRY){
  515. if(Link->HP==Link->MaxHP){
  516. Game->PlaySound(SFX_ERROR);
  517. }
  518. else{
  519. BottleState[BSI_BOTTLEUSED] = bottle;
  520. BottleState[BSI_BOTTLETIMER] = FREQ_HEARTREFILL*FAIRY_HEARTS;
  521. BottleState[BSI_FAIRYTIMER] = 0;
  522. BottleState[BSI_FAIRYREVIVE] = 0;
  523. Game->PlaySound(SFX_FAIRY);
  524. Screen_Freeze();
  525. }
  526. }
  527. else if(BottleState[bottle]==BS_BEE){
  528. int scriptname[] = "Bottle_Bee";
  529. int scriptid = Game->GetFFCScript(scriptname);
  530. int vars[8] = {1};
  531. RunFFCScript(scriptid, vars);
  532. BottleState[bottle] = BS_EMPTY;
  533. RefreshBottles();
  534. }
  535. }
  536. int fairy = HasFairy();
  537. if(Link->HP<=0&&fairy>-1){
  538. Link->HP = 1;
  539. BottleState[BSI_BOTTLEUSED] = fairy;
  540. BottleState[BSI_BOTTLETIMER] = FREQ_HEARTREFILL*FAIRY_HEARTS;
  541. BottleState[BSI_FAIRYTIMER] = 0;
  542. BottleState[BSI_FAIRYREVIVE] = 1;
  543. Game->PlaySound(SFX_FAIRY);
  544. Screen_Freeze();
  545. }
  546. }
  547. }
  548.  
  549.  
  550. //X-------------------------------X
  551. //| Empty Bottle Action Scripts |
  552. //X-------------------------------X
  553.  
  554. ffc script Bottle_Empty{
  555. void run(int bottleid){
  556. int Angle = 0;
  557. if(Link->Dir==DIR_UP)
  558. Angle = -90;
  559. else if(Link->Dir==DIR_DOWN)
  560. Angle = 90;
  561. else if(Link->Dir==DIR_LEFT)
  562. Angle = 180;
  563. Game->PlaySound(SFX_BOTTLESWING);
  564. Link->Action = LA_ATTACKING;
  565. int Collected = 0;
  566. for(int i=-45; i<45; i+=10){
  567. int X = Link->X+VectorX(12, Angle+i);
  568. int Y = Link->Y+VectorY(12, Angle+i);
  569. Screen->DrawTile(2, X, Y, TIL_BOTTLESWING, 1, 1, CS_BOTTLESWING, -1, -1, X, Y, Angle+i+90, 0, true, 128);
  570. if(Collected==0||Collected==BS_WATER){
  571. if(OnWater(X+8, Y+8)&&Collected==0&&BOTTLE_SETTING_NO_WATER==0){
  572. Collected = BS_WATER;
  573. }
  574. for(int j=1; j<=Screen->NumItems(); j++){
  575. item itm = Screen->LoadItem(j);
  576. if(itm->ID==I_FAIRY||itm->ID==I_FAIRYSTILL){
  577. if(RectCollision(itm->X+itm->HitXOffset, itm->Y+itm->HitYOffset, itm->X+itm->HitXOffset+itm->HitWidth, itm->Y+itm->HitYOffset+itm->HitHeight, X+4, Y+4, X+11, Y+11)){
  578. Collected = BS_FAIRY;
  579. Remove(itm);
  580. break;
  581. }
  582. }
  583. }
  584. for(int j=1; j<=32; j++){
  585. ffc f = Screen->LoadFFC(j);
  586. int scriptname[] = "Bottle_Bee";
  587. int scriptid = Game->GetFFCScript(scriptname);
  588. if(f->Script==scriptid){
  589. if(RectCollision(X+4, Y+4, X+11, Y+11, f->X+4, f->Y+4, f->X+11, f->Y+11)){
  590. Collected = BS_BEE;
  591. f->Misc[FFCM_BEE_SELFDESTRUCT] = 1;
  592. }
  593. }
  594. }
  595. }
  596. WaitNoAction();
  597. }
  598. if(Collected==BS_WATER){
  599. BottleState[bottleid] = BS_WATER;
  600. RefreshBottles();
  601. item itm = CreateItemAt(I_WATERBOTTLE, Link->X, Link->Y);
  602. itm->Pickup = IP_HOLDUP;
  603. }
  604. else if(Collected==BS_FAIRY){
  605. BottleState[bottleid] = BS_FAIRY;
  606. RefreshBottles();
  607. item itm = CreateItemAt(I_FAIRYBOTTLE, Link->X, Link->Y);
  608. itm->Pickup = IP_HOLDUP;
  609. }
  610. else if(Collected==BS_BEE){
  611. BottleState[bottleid] = BS_BEE;
  612. RefreshBottles();
  613. item itm = CreateItemAt(I_BEEBOTTLE, Link->X, Link->Y);
  614. itm->Pickup = IP_HOLDUP;
  615. }
  616. WaitNoAction(10);
  617. }
  618. bool OnWater(int x, int y){
  619. int ct = Screen->ComboT[ComboAt(x, y)];
  620. if(ct==CT_WATER||ct==CT_SHALLOWWATER)
  621. return true;
  622. return false;
  623. }
  624. }
  625.  
  626. ffc script Bottle_Bee{
  627. void run(int friendly){
  628. this->Data = CMB_BEE;
  629. this->CSet = CS_BEE;
  630. if(friendly==1){
  631. this->X = Link->X;
  632. this->Y = Link->Y;
  633. }
  634. int i; int j; int k;
  635. int X = this->X;
  636. int Y = this->Y;
  637. lweapon lh;
  638. eweapon eh;
  639. int Lifespan = Rand(900, 1200);
  640. for(i=0; i<40; i++){
  641. Y -= 0.5;
  642. this->X = X;
  643. this->Y = Y;
  644. Waitframe();
  645. }
  646. while(Lifespan>0){
  647. int Angle;
  648. if(friendly==1){
  649. int Tx = -1000;
  650. int Ty = -1000;
  651. int Dist = 1000;
  652. for(i=1; i<=Screen->NumNPCs(); i++){
  653. npc n = Screen->LoadNPC(i);
  654. if(Distance(X+8, Y+8, CenterX(n), CenterY(n))<Dist){
  655. Dist = Distance(X+8, Y+8, CenterX(n), CenterY(n));
  656. Tx = CenterX(n)-8;
  657. Ty = CenterY(n)-8;
  658. }
  659. }
  660. Angle = Angle(X, Y, Tx, Ty);
  661. if(Screen->NumNPCs()==0)
  662. Angle = Angle(X, Y, Link->X, Link->Y);
  663. }
  664. else{
  665. if(Distance(Link->X, Link->Y, X, Y)<80&&Rand(2)==0)
  666. Angle = Angle(X, Y, Link->X, Link->Y);
  667. else
  668. Angle = Rand(360);
  669. }
  670. k = Rand(32, 48);
  671. for(i=0; i<k; i++){
  672. Lifespan--;
  673. j = (j+1)%360;
  674. if(j%30==0)
  675. Game->PlaySound(SFX_BEE);
  676. X = Clamp(X+VectorX(2, Angle), -16, 256);
  677. Y = Clamp(Y+VectorY(2, Angle), -16, 176);
  678. this->X = X;
  679. this->Y = Y;
  680. if(friendly==1){
  681. if(lh->isValid()){
  682. lh->X = X;
  683. lh->Y = Y;
  684. }
  685. else{
  686. lh = CreateLWeaponAt(LW_BEE, X, Y);
  687. lh->HitXOffset = 4;
  688. lh->HitYOffset = 4;
  689. lh->HitWidth = 8;
  690. lh->HitHeight = 8;
  691. lh->DrawYOffset = -1000;
  692. lh->Dir = 8;
  693. lh->Damage = DAMAGE_BEE;
  694. }
  695. }
  696. else{
  697. if(eh->isValid()){
  698. eh->X = X;
  699. eh->Y = Y;
  700. }
  701. else{
  702. eh = CreateEWeaponAt(EW_BEE, X, Y);
  703. eh->HitXOffset = 4;
  704. eh->HitYOffset = 4;
  705. eh->HitWidth = 8;
  706. eh->HitHeight = 8;
  707. eh->DrawYOffset = -1000;
  708. eh->Dir = 8;
  709. eh->Damage = DAMAGE_BEE;
  710. }
  711. }
  712. if(this->Misc[FFCM_BEE_SELFDESTRUCT]==1){
  713. if(lh->isValid())
  714. lh->DeadState = 0;
  715. if(eh->isValid())
  716. eh->DeadState = 0;
  717. this->Data = 0;
  718. this->CSet = 0;
  719. Quit();
  720. }
  721. Waitframe();
  722. }
  723. }
  724. if(lh->isValid())
  725. lh->DeadState = 0;
  726. if(eh->isValid())
  727. eh->DeadState = 0;
  728. this->Data = 0;
  729. this->CSet = 0;
  730. for(i=0; i<40; i++){
  731. if(i%2==0)
  732. Screen->FastCombo(2, X, Y, CMB_BEE, CS_BEE, 128);
  733. Waitframe();
  734. }
  735. }
  736. }
  737.  
  738.  
  739. //X----------------------------X
  740. //| Other Associated Scripts |
  741. //X----------------------------X
  742.  
  743. item script PotionFill{
  744. void run(int str, int state){
  745. FillBottle(state);
  746. Screen->Message(str);
  747. }
  748. }
  749.  
  750. ffc script ItemShop{
  751. void run(int id, int strdescription, int price, int potion){
  752. itemdata ic = Game->LoadItemData(id);
  753. while(true){
  754. if(Link->X>this->X-8&&Link->X<this->X+8&&Link->Y>this->Y&&Link->Y<this->Y+10&&Link->Dir==DIR_UP){
  755. if(Link->PressL){
  756. Screen->Message(strdescription);
  757. NoAction();
  758. }
  759. else if(Link->PressR){
  760. if(Game->Counter[CR_RUPEES]+Game->DCounter[CR_RUPEES]>=price){
  761. if(potion>0&&!CanFillBottle()){
  762. Screen->Message(STR_NOBOTTLE);
  763. NoAction();
  764. }
  765. else{
  766. item itm = CreateItemAt(id, Link->X, Link->Y);
  767. itm->Pickup = IP_HOLDUP;
  768. Game->DCounter[CR_RUPEES] -= price;
  769. for(int i=0; i<10; i++){
  770. WaitNoAction();
  771. }
  772. }
  773. }
  774. else{
  775. Screen->Message(STR_CANTAFFORD);
  776. NoAction();
  777. }
  778. }
  779. }
  780. DrawPrice(this, price);
  781. Waitframe();
  782. }
  783. }
  784. void DrawPrice(ffc this, int price){
  785. int xoff = -2;
  786. if(price>999)
  787. xoff = -8;
  788. else if(price>99)
  789. xoff = -6;
  790. else if(price>9)
  791. xoff = -4;
  792. Screen->DrawInteger(5, this->X+8+xoff+1, this->Y+18+1, FONT_Z3SMALL, C_BLACK, -1, -1, -1, price, 0, 128);
  793. Screen->DrawInteger(5, this->X+8+xoff, this->Y+18, FONT_Z3SMALL, C_WHITE, -1, -1, -1, price, 0, 128);
  794. }
  795. }
  796.  
  797. ffc script BeeGrass{
  798. void run(int chances){
  799. int Combo = Screen->ComboD[ComboAt(this->X+8, this->Y+8)];
  800. while(Screen->ComboD[ComboAt(this->X+8, this->Y+8)]==Combo){
  801. Waitframe();
  802. }
  803. if(Rand(chances)==0){
  804. int scriptname[] = "Bottle_Bee";
  805. int scriptid = Game->GetFFCScript(scriptname);
  806. int i = RunFFCScript(scriptid, 0);
  807. ffc f = Screen->LoadFFC(i);
  808. f->X = this->X;
  809. f->Y = this->Y;
  810. }
  811. }
  812. }
  813.  
  814. ffc script WaterTrigger{
  815. void run(){
  816. if(!Screen->State[ST_SECRET]){
  817. while(true){
  818. for(int i=1; i<=Screen->NumLWeapons(); i++){
  819. lweapon l = Screen->LoadLWeapon(i);
  820. if(l->ID==LW_WATER&&Collision(this, l)){
  821. Screen->TriggerSecrets();
  822. Game->PlaySound(SFX_SECRET);
  823. Screen->State[ST_SECRET] = true;
  824. Quit();
  825. }
  826. }
  827. Waitframe();
  828. }
  829. }
  830. }
  831. }
  832.  
  833.  
  834. //========================================
  835. // Global Globals/Functions/Constants
  836. //========================================
  837.  
  838. ///Constants and Variables used by platform script;
  839. const int DIAGONAL_MOVEMENT = 1; //Enable the option and change this to 0 for nes movement.
  840. int onplatform; //Global variable use this to check if Link is on a platform for other scripts.
  841.  
  842.  
  843. void NesMovementFix()
  844. {
  845. if(DIAGONAL_MOVEMENT==0 && (Link->InputUp || Link->InputDown))
  846. {
  847. Link->InputLeft = false;
  848. Link->InputRight = false;
  849. }
  850. }
  851.  
  852. void MovingPlatforms()
  853. {
  854. onplatform = 0;
  855. if(Link->Z == 0)
  856. {
  857. int buffer[] = "movingplatform";
  858. for(int i = 1; i <= 32; i++)
  859. {
  860. ffc f = Screen->LoadFFC(i);
  861. if(f->Script != Game->GetFFCScript(buffer)) continue;
  862. if(Abs(Link->X + 8 - CenterX(f)) >= f->TileWidth*8) continue;
  863. if(Abs(Link->Y + 12 - CenterY(f)) >= f->TileHeight*8) continue;
  864. onplatform = FFCNum(f);
  865. break;
  866. }
  867. }
  868. }
  869.  
  870. ffc script MovingPlatform
  871. {
  872. void run()
  873. {
  874. float oldx = this->X;
  875. float oldy = this->Y;
  876. float linkx;
  877. float linky;
  878. while(true)
  879. {
  880. if(onplatform == FFCNum(this))
  881. {
  882. linkx += this->X - oldx;
  883. linky += this->Y - oldy;
  884. if(linkx << 0 != 0)
  885. {
  886. Link->X += linkx << 0;
  887. linkx -= linkx << 0;
  888. }
  889. if(linky << 0 != 0)
  890. {
  891. Link->Y += linky << 0;
  892. linky -= linky << 0;
  893. }
  894. }
  895. else
  896. {
  897. linkx = 0;
  898. linky = 0;
  899. }
  900. oldx = this->X;
  901. oldy = this->Y;
  902. Waitframe();
  903. }
  904. }
  905. }
  906.  
  907. //========================================
  908. // Global Globals/Functions/Constants
  909. //========================================
  910.  
  911. int MooshPit[16];
  912. const int MP_LASTX = 0;
  913. const int MP_LASTY = 1;
  914. const int MP_LASTDMAP = 2;
  915. const int MP_LASTSCREEN = 3;
  916. const int MP_ENTRYX = 4;
  917. const int MP_ENTRYY = 5;
  918. const int MP_ENTRYDMAP = 6;
  919. const int MP_ENTRYSCREEN = 7;
  920. const int MP_FALLX = 8;
  921. const int MP_FALLY = 9;
  922. const int MP_FALLTIMER = 10;
  923. const int MP_FALLSTATE = 11;
  924. const int MP_DAMAGETYPE = 12;
  925.  
  926. const int CT_HOLELAVA = 128; //Combo type for pits (No Ground Enemies by default)
  927. const int CF_LAVA = 98; //Combo flag marking pits as lava (Script 1 by default)
  928.  
  929. const int SPR_FALLHOLE = 88; //Sprite for Link falling in a hole
  930. const int SPR_FALLLAVA = 89; //Sprite for Link falling in lava
  931.  
  932. const int SFX_FALLHOLE = 38; //Sound for falling in a hole
  933. const int SFX_FALLLAVA = 13; //Sound for falling in lava
  934.  
  935. const int DAMAGE_FALLHOLE = 8; //How much damage pits deal (1/2 heart default)
  936. const int DAMAGE_FALLLAVA = 16; //How much damage lava deals (1 heart default)
  937.  
  938. const int FFC_MOOSHPIT_AUTOWARPA = 32; //FFC that turns into an auto side warp combo when you fall in a pit
  939. const int CMB_MOOSHPIT_AUTOWARPA = 2; //Combo number of an invisible Auto Side Warp A combo
  940. const int SF_MISC_MOOSHPITWARP = 2; //Number of the screen flag under the Misc. section that makes pits warp (Script 1 by default)
  941. //All pit warps use Side Warp A
  942.  
  943. const int MOOSHPIT_MIN_FALL_TIME = 60; //Minimum time for the pit's fall animation, to prevent repeated falling in pits
  944. const int MOOSHPIT_EXTRA_FALL_TIME = 0; //Extra frames at the end of the falling animation before Link respawns
  945.  
  946. //Width and height of Link's hitbox for colliding with pits
  947. const int MOOSHPIT_LINKHITBOXWIDTH = 2;
  948. const int MOOSHPIT_LINKHITBOXHEIGHT = 2;
  949.  
  950. //Width and height of Link's hitbox for colliding with pits/lava in sideview
  951. const int MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH = 2;
  952. const int MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT = 2;
  953.  
  954. const int MOOSHPIT_NO_GRID_SNAP = 0; //Set to 1 to prevent Link's falling sprite from snapping to the combo grid.
  955.  
  956. bool MooshPit_OnPit(int LinkX, int LinkY, bool countFFCs){
  957. if(Link->Action==LA_FROZEN)
  958. return false;
  959.  
  960. if(countFFCs){
  961. if(MooshPit_OnFFC(LinkX, LinkY))
  962. return false;
  963. }
  964.  
  965. bool sideview;
  966. if(Screen->Flags[SF_ROOMTYPE]&100b)
  967. sideview = true;
  968. //wew lad
  969. int width = MOOSHPIT_LINKHITBOXWIDTH;
  970. int height = MOOSHPIT_LINKHITBOXHEIGHT;
  971. for(int x=0; x<=1; x++){
  972. for(int y=0; y<=1; y++){
  973. int X; int Y;
  974. if(sideview){ //Hitbox functions differently in sideview
  975. width = MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH;
  976. height = MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT;
  977. X = LinkX+7-width/2+width;
  978. Y = LinkY+7-height/2+height;
  979. }
  980. else{
  981. X = LinkX+7-width/2+width;
  982. Y = LinkY+11-height/2+height;
  983. }
  984.  
  985. //If one corner of Link's hitbox isn't on a pit, return false
  986. if(Screen->ComboT[ComboAt(X, Y)]!=CT_HOLELAVA){
  987. return false;
  988. }
  989. }
  990. }
  991. return true;
  992. }
  993.  
  994. bool MooshPit_OnFFC(int LinkX, int LinkY){
  995. for(int i=1; i<=32; i++){ //Cycle through every FFC
  996. ffc f = Screen->LoadFFC(i);
  997. //Check if the FFC is solid
  998. if(f->Data>0&&!f->Flags[FFCF_CHANGER]&&!f->Flags[FFCF_ETHEREAL]){
  999. //Check if Link collides with the FFC
  1000. if(RectCollision(LinkX+4, LinkY+9, LinkX+11, LinkY+14, f->X, f->Y, f->X+f->EffectWidth-1, f->Y+f->EffectHeight-1)){
  1001. return true;
  1002. }
  1003. }
  1004. }
  1005. //If Link doesn't collide with any FFC, return false
  1006. return false;
  1007. }
  1008.  
  1009. void MooshPit_Init(){
  1010. MooshPit[MP_LASTX] = Link->X;
  1011. MooshPit[MP_LASTY] = Link->Y;
  1012. MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
  1013. MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
  1014. MooshPit[MP_ENTRYX] = Link->X;
  1015. MooshPit[MP_ENTRYY] = Link->Y;
  1016. MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
  1017. MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  1018. MooshPit[MP_FALLSTATE] = 0;
  1019. MooshPit[MP_FALLTIMER] = 0;
  1020. Link->CollDetection = true;
  1021. Link->Invisible = false;
  1022. }
  1023.  
  1024. void MooshPit_Update(){
  1025. bool isWarp;
  1026. if(Screen->Flags[SF_MISC]&(1<<SF_MISC_MOOSHPITWARP))
  1027. isWarp = true;
  1028.  
  1029. bool sideview;
  1030. if(Screen->Flags[SF_ROOMTYPE]&100b)
  1031. sideview = true;
  1032.  
  1033. if(Link->Action!=LA_SCROLLING){
  1034. //Update the entry point whenever the screen changes
  1035. if(MooshPit[MP_ENTRYDMAP]!=Game->GetCurDMap()||MooshPit[MP_ENTRYSCREEN]!=Game->GetCurDMapScreen()){
  1036. MooshPit[MP_ENTRYX] = Link->X;
  1037. MooshPit[MP_ENTRYY] = Link->Y;
  1038. MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
  1039. MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  1040. }
  1041.  
  1042. if(MooshPit[MP_FALLSTATE]==0){ //Not falling in pit
  1043. if(Link->Z<=0&&MooshPit_OnPit(Link->X, Link->Y, true)){ //If Link steps on a pit
  1044. int underLink;
  1045. if(!sideview)
  1046. underLink = ComboAt(Link->X+8, Link->Y+12);
  1047. else
  1048. underLink = ComboAt(Link->X+8, Link->Y+8);
  1049.  
  1050. lweapon fall;
  1051.  
  1052. //Check if the combo is lava
  1053. if(ComboFI(underLink, CF_LAVA)){
  1054. //Play sound and display animation
  1055. Game->PlaySound(SFX_FALLLAVA);
  1056. fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  1057. if(!MOOSHPIT_NO_GRID_SNAP){
  1058. fall->X = ComboX(underLink);
  1059. fall->Y = ComboY(underLink);
  1060. }
  1061. fall->UseSprite(SPR_FALLLAVA);
  1062. fall->CollDetection = false;
  1063. fall->DeadState = fall->ASpeed*fall->NumFrames;
  1064.  
  1065. //Mark as lava damage
  1066. MooshPit[MP_DAMAGETYPE] = 1;
  1067. }
  1068. //Otherwise it's a pit
  1069. else{
  1070. //Play sound and display animation
  1071. Game->PlaySound(SFX_FALLHOLE);
  1072. fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  1073. if(!MOOSHPIT_NO_GRID_SNAP){
  1074. fall->X = ComboX(underLink);
  1075. fall->Y = ComboY(underLink);
  1076. }
  1077. fall->UseSprite(SPR_FALLHOLE);
  1078. fall->CollDetection = false;
  1079. fall->DeadState = fall->ASpeed*fall->NumFrames;
  1080.  
  1081. //Mark as hole damage
  1082. MooshPit[MP_DAMAGETYPE] = 0;
  1083. }
  1084.  
  1085. MooshPit[MP_FALLX] = Link->X;
  1086. MooshPit[MP_FALLY] = Link->Y;
  1087.  
  1088. //Cooldown should last as long as the fall animation
  1089. MooshPit[MP_FALLSTATE] = 1;
  1090. MooshPit[MP_FALLTIMER] = Max(MOOSHPIT_MIN_FALL_TIME, fall->DeadState+MOOSHPIT_EXTRA_FALL_TIME);
  1091.  
  1092. //Render Link invisible and intangible
  1093. Link->Invisible = true;
  1094. Link->CollDetection = false;
  1095.  
  1096. NoAction();
  1097. }
  1098. else if(!MooshPit_OnPit(Link->X, Link->Y, false)&&Link->Action!=LA_FROZEN){ //All other times, while Link is on solid ground, record Link's last position
  1099. if(sideview){
  1100. //Link has no Z value in sideview, so we check if he's on a platform instead
  1101. if(OnSidePlatform(Link->X, Link->Y)){
  1102. MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
  1103. MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
  1104. MooshPit[MP_LASTX] = Link->X;
  1105. MooshPit[MP_LASTY] = Link->Y;
  1106. }
  1107. }
  1108. else{
  1109. if(Link->Z<=0){
  1110. MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
  1111. MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
  1112. MooshPit[MP_LASTX] = Link->X;
  1113. MooshPit[MP_LASTY] = Link->Y;
  1114. }
  1115. }
  1116. }
  1117. }
  1118. else if(MooshPit[MP_FALLSTATE]==1){ //Falling animation
  1119. if(MooshPit[MP_FALLTIMER]>0)
  1120. MooshPit[MP_FALLTIMER]--;
  1121.  
  1122. Link->Jump = 0;
  1123. Link->Z = 0;
  1124.  
  1125. //Keep Link invisible just in case
  1126. Link->Invisible = true;
  1127. Link->CollDetection = false;
  1128. NoAction();
  1129. if(MooshPit[MP_FALLTIMER]==0){
  1130. if(!isWarp||MooshPit[MP_DAMAGETYPE]==1){ //If the pit isn't a warp, deal damage and move Link back to the return point
  1131. //If the entry would dump Link back in the pit, dump him out at the failsafe position
  1132. if(MooshPit_OnPit(MooshPit[MP_ENTRYX], MooshPit[MP_ENTRYY], false)){
  1133. Link->X = MooshPit[MP_LASTX];
  1134. Link->Y = MooshPit[MP_LASTY];
  1135. //If the failsafe position was on a different screen, warp there
  1136. if(Game->GetCurDMap()!=MooshPit[MP_LASTDMAP]||Game->GetCurDMapScreen()!=MooshPit[MP_LASTSCREEN]){
  1137. Link->PitWarp(MooshPit[MP_LASTDMAP], MooshPit[MP_LASTSCREEN]);
  1138. }
  1139.  
  1140. Link->Invisible = false;
  1141. Link->CollDetection = true;
  1142. }
  1143. else{
  1144. //Move Link to the start and make him visible
  1145. Link->X = MooshPit[MP_ENTRYX];
  1146. Link->Y = MooshPit[MP_ENTRYY];
  1147.  
  1148. Link->Invisible = false;
  1149. Link->CollDetection = true;
  1150. }
  1151.  
  1152. //Subtract HP based on damage type
  1153. if(MooshPit[MP_DAMAGETYPE]==1)
  1154. Link->HP -= DAMAGE_FALLLAVA;
  1155. else
  1156. Link->HP -= DAMAGE_FALLHOLE;
  1157. //Play hurt sound and animation
  1158. Link->Action = LA_GOTHURTLAND;
  1159. Link->HitDir = -1;
  1160. Game->PlaySound(SFX_OUCH);
  1161.  
  1162. MooshPit[MP_FALLSTATE] = 0;
  1163. }
  1164. else{
  1165. MooshPit[MP_FALLSTATE] = 2;
  1166. MooshPit[MP_FALLTIMER] = 1;
  1167. ffc warp = Screen->LoadFFC(FFC_MOOSHPIT_AUTOWARPA);
  1168. warp->Data = CMB_MOOSHPIT_AUTOWARPA;
  1169. warp->Flags[FFCF_CARRYOVER] = false;
  1170. }
  1171. }
  1172. }
  1173. else if(MooshPit[MP_FALLSTATE]==2){ //Just warped
  1174. if(sideview){
  1175. Link->X = MooshPit[MP_FALLX];
  1176. Link->Y = 0;
  1177. }
  1178. else{
  1179. Link->X = MooshPit[MP_FALLX];
  1180. Link->Y = MooshPit[MP_FALLY];
  1181. Link->Z = 176;
  1182. }
  1183. Link->Invisible = false;
  1184. Link->CollDetection = true;
  1185.  
  1186. MooshPit[MP_FALLSTATE] = 0;
  1187. MooshPit[MP_FALLTIMER] = 0;
  1188. }
  1189. }
  1190. }
  1191.  
  1192. void MooshPit_ResetEntry(){
  1193. MooshPit[MP_ENTRYX] = Link->X;
  1194. MooshPit[MP_ENTRYY] = Link->Y;
  1195. MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
  1196. MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  1197. }
  1198.  
  1199. //========================================
  1200. // Global Globals/Functions/Constants
  1201. //========================================
  1202.  
  1203. //Standard Version
  1204.  
  1205. //========================================
  1206. // Global Globals/Functions/Constants
  1207. //========================================
  1208.  
  1209.  
  1210. int Pots[176];
  1211. int nPots;
  1212.  
  1213. //Constants used to configure the script
  1214. const int PS_HEIGHT = 2; //hight of sprite
  1215. const int PS_WIDTH = 2; //width of sprite
  1216. const int PS_AFRAMES = 8; //number of animation sprites used
  1217. const int PS_SPEED = 3; //speed of the animation: smaller = faster, don't use 0!
  1218. const int PS_CSET = 7; //cset to be used
  1219. const int PS_LAYER = 3; //layer to be displayed on
  1220. const int PS_ANIMATION = 1300; //the combo ID of the top left of the first frame on the tiles page
  1221. const int PS_SFX = 62; //sound effect to be used
  1222. const int PS_CFLAG = 130; //combo type flag that identifies pots (130 = Slash->Next (Item))
  1223. //see std_constants.zh for other type flags
  1224.  
  1225. void Pot_Script(){
  1226. int w; int h;
  1227. int i; int n;
  1228. int timer = PS_SPEED * PS_AFRAMES; //note that the max is 255 (~4 seconds)
  1229. int x; int y; int aframe;
  1230. int OffsetX = PS_WIDTH * 8 - 8; //center the sprite according to height and width
  1231. int OffsetY = PS_HEIGHT * 8 - 8; //center the sprite according to height and width
  1232.  
  1233. //initialize pots array, the first 8 bits store the position and the second 8 bits store the timer
  1234. if(ScreenChanged){
  1235. i = 0;
  1236. for(n = 0; n < 176; n++)
  1237. if(Screen->ComboT[n] == PS_CFLAG) Pots[i++] = n;
  1238. nPots = i;
  1239. return;
  1240. }
  1241.  
  1242. //scan for broken pots..
  1243. for(n = 0; n < nPots; n++){
  1244. if(Screen->ComboT[Pots[n] & 0xff] == PS_CFLAG)
  1245. continue;
  1246.  
  1247. //we found one! if its timer isn't set, set it and play sound
  1248. if((Pots[n] & 0xff00) == 0){
  1249. Game->PlaySound(PS_SFX);
  1250. Pots[n] |= (timer << 8);
  1251. }
  1252.  
  1253.  
  1254. //now figure out where we are in the animation cycle
  1255. aframe = PS_ANIMATION + PS_WIDTH * Floor((timer - (Pots[n] >> 8)) / PS_SPEED);
  1256.  
  1257. //display tiles
  1258. x = ComboX(Pots[n] & 0xff) - OffsetX;
  1259. y = ComboY(Pots[n] & 0xff) - OffsetY;
  1260. for(w = 0; w < PS_WIDTH; w++){
  1261. for(h = 0; h < PS_HEIGHT; h++){
  1262. Screen->FastTile(PS_LAYER, x + 16 * w, y + 16 * h, aframe + w + 20 * h, PS_CSET, 255);
  1263. }
  1264. }
  1265.  
  1266. //subtract 1 from the timer and remove pot from the array when timer = 0
  1267. Pots[n] -= 0x100;
  1268. if((Pots[n] & 0xff00) == 0) Pots[n] = Pots[--nPots];
  1269. }
  1270. }
  1271.  
  1272.  
  1273.  
  1274. //force ScreenChange to be ture if player dies or F6 continues (ScreenChanged = true; doesn't work)
  1275. //put this into the "onExit" slot
  1276. //========================================
  1277. // Global Globals/Functions/Constants
  1278. //========================================
  1279.  
  1280. // [ITEM] PEGASUS BOOTS -------------------------------------------------------------------------------------------------------------------------------------------
  1281. // (original: Joe123, edits: Zepinho, justin ...................................................................................................................................
  1282.  
  1283.  
  1284.  
  1285. // -------------------------------------------------------------------------------
  1286. // SETUP
  1287. //
  1288. // 1. Add the necessary tiles to your quest file. Dust animation. SFX. etc.
  1289. // 2. Set the following constants
  1290. // 3. Set the size of the Dust_Array in the Global variable section. The formula is provided.
  1291. // Leave the rest of the global variables alone.
  1292. // 4. Create your Pegasus Boot item, custom item class, attach the PegasusBoots item script to the active slot.
  1293. // 5. If you have no other global scripts, ignore this step.
  1294. // If you do, Scroll down to bottom of this script and read instructions on how to add the necessary global functions to your script.
  1295. // 6. Make sure there are no functions / variables you're trying to include twice.
  1296. // constant BIG_LINK come to mind. Marked with !!!!!!!!!!!!!!!
  1297.  
  1298.  
  1299. // Optional setup stuff
  1300. // Jump related - Roc Items, and otherwise
  1301. // 1. If not using can select both A and B button items, OR if not using Roc's feather you should set I_ROCSFEATHER_INCREASER to 0.
  1302. // 2. If using Roc's Feather item setup a second Roc Feather item, and can select A/B items.
  1303. // Roc item class. Equipment item. Height multiplier = a number greater than your Roc feather height. 2 works well if standard Roc Feather HM = 1.
  1304. // Give it the same sprite and SFX as Roc Feather. or can make them different if you'd like.
  1305. // Make note of the item# of the Increaser item, so you can set the constant below.
  1306. // The PegasusBoots script gives and takes the Increaser item automatically, so don't give it in your quest.
  1307. // If already using multiple levels of Roc Item, or if your Roc Feather is NOT the default item number (91), you'll need to modify the script.
  1308. // 3. If you're just keying jumping to another button L/R/EX1/etc, the Roc Increaser won't function. You'll need to modify the script.
  1309. //
  1310. // Swords - extra swords, and non default sword item#s
  1311. // 1. More swords can be added by adding new constants with their item numbers, and sprites.
  1312. // And adding more to the if statement that uses the I_SWORD constants in the PegasusDash function.
  1313. // 2. The script currently uses the default item numbers for swords. If you change those, you'll have to replace the corresponding I_SWORD constant.
  1314. // 3. Dash sword will draw an animated sword if the sprite is animated. EXCEPT when scrolling.
  1315. //
  1316. // Dash Slash related - cutting tall grass, bushes, etc while dashing
  1317. // 1. By default things combo types - Grass, Flowers, Bush, and next versions are set to use the sprites you define. And their default item drop set. (IS_COMBOS = 12)
  1318. // 2. Slash combo types don't have a default sprite, and use the default item sets (IS_COMBOS = 12). Slash->Item which uses its default item set (IS_MAGICLIFE = 10).
  1319. // 3. Continous combo types accounted for at all.
  1320. // 4. The SFX is the same for all of them.
  1321. // 5. If you want to change any of this, find the function DoDashSlash. Easy to find with a row of !!!!!!!!!! above.
  1322. // Edit to your liking.
  1323. // 6. If using any of the Slash combo type with solid combo, you'll have a bug where you can't initiate a dashslash while standing beside it.
  1324. // You can edit the function CanDashSlash to fix it. It is marked by a row of !!!!!!!!!!!!!!!!!
  1325. //
  1326. // Dust drawing related
  1327. // 1. If using the "No screen scrolling" quest rule. You can switch to the old dust drawing code if you wish, and clear up some variables and functions.
  1328. // Uncomment DustDrawLW, and remove DustDrawTile. The ScrollFix function can be removed, with its associated global variables.
  1329. // Dust_Array, the DustDrawTile function, the dashSword while scrolling code, and the dashSword variables can all be safely removed in this case.
  1330.  
  1331.  
  1332. // !!!!!!! this is also used by other scripts, only needs to be included in script file once
  1333. const int BIG_LINK = 0; // Set this constant to 1 if using the Large Link Hit Box feature.
  1334.  
  1335. // Pegasus Boots Constants
  1336. const int CF_DASH = 100; // CF_Script3, ComboFlag that Link can't dash through if walkable, and will break if solid
  1337. // Could be reused for situations where dash is impossible.
  1338.  
  1339. const int INV_COMBO_ID = 14; // Solid DashCombos will break into this
  1340.  
  1341. const int DashSFXLength = 9; // Time between repeating Dash SFX
  1342. const int SFX_DASH = 64; // Dashing SFX
  1343. const int SFX_HITWALL = 137; // Hitting a wall
  1344. const int SFX_PEGASUSBREAK = 66; // SFX to play when breaking a Pegasus Boot block
  1345.  
  1346. const int T_DUST = 27420; // Dust Kick-up tile
  1347. const int DustAFrames = 2; // Dust Kick-up animation frames
  1348. const int DustASpeed = 4; // Dust Kick-up animation speed
  1349. const int DustCSet = 2; // Dust Kick-up CSet
  1350.  
  1351. const int I_ROCSFEATHER_INCREASER = 124; // Roc's feather upgrade, to automatically give to Link when using Pegasus Boots
  1352.  
  1353. const int DASH_SWORD_DMG = 8; // Dash sword deals this regardless of sword damage.
  1354. const int DASH_SWORD_MULT = 0; // Dash sword deals equipped sword damage times this. 0 uses above value. >0 uses this.
  1355. const int SPRITE_SWORD1 = 0; // Set these to the sprite number used by that sword level
  1356. const int SPRITE_SWORD2 = 1;
  1357. const int SPRITE_SWORD3 = 2;
  1358. const int SPRITE_SWORD4 = 3;
  1359.  
  1360. const int NPC_ITEMSET = 177; // ID of a dummy enemy with type different from "none", hp0, itemset overridden by script
  1361.  
  1362.  
  1363. const int SPRITE_BUSH_CUT = 52; // set these to whatever sprites they should correspond to
  1364. const int SPRITE_FLOWER_CUT = 53; // sprites with 0 for either NumFrames or AniSpeed will not show.
  1365. const int SPRITE_GRASS_CUT = 54;
  1366.  
  1367. const int CanDrown = 1; // 0 makes Link stop beside water combos regardless of quest rule, and their walkability
  1368. // Set 0 if not using drownable water, or if you don't want Link to dash into water.
  1369. // Set 1 if using drownable water, and want Link to dash in and either drown or swim.
  1370.  
  1371. //END Pegasus Boots constants
  1372.  
  1373.  
  1374. // -------------------------------------------------------------------------------
  1375. // Global Variables
  1376.  
  1377. // to draw while Scrolling
  1378. int scrollDir;
  1379. int scrollCounter;
  1380. int drawX;
  1381. int drawY;
  1382.  
  1383. //Pegasus Boots Global variables
  1384. int PegasusDash = -1;
  1385. bool PegasusCollision;
  1386. int DashCounter;
  1387. int StoreInput;
  1388. int StoreHP;
  1389.  
  1390. int dashSwordTile = 0; // for drawing dashsword while scrolling, script sets these.
  1391. int dashSwordCSet = 0;
  1392.  
  1393. //!!!!!!!!!!!!! this array size needs to be set, the number inside the []
  1394. int Dust_Array[2]; // Array size should be max number of dust animations active at one time
  1395. // Formula is ( (DustAFrames*DustASpeed) / 4 )
  1396.  
  1397. //END Pegasus Boots global variables
  1398.  
  1399.  
  1400.  
  1401. // -------------------------------------------------------------------------------
  1402. // Pegasus Boots functions
  1403.  
  1404. item script PegasusBoots{
  1405. void run(){
  1406.  
  1407. if(ComboFI(Link->X+8,Link->Y + Cond(BIG_LINK==0, 12, 8),CF_DASH)) Quit(); // can't dash on non-solid dash combos
  1408.  
  1409. if(CanDrown == 0 && IsWater(TouchedComboLoc()) ) Quit(); // stop beside non-drownable water
  1410.  
  1411. if(Link->Action == LA_SWIMMING || Link->Action == LA_DROWNING) Quit(); // can't use dash when in water
  1412.  
  1413. if(IsJumping()) Quit(); // can't initiate dash while jumping
  1414.  
  1415. // Link won't dash if facing up or down in sideview
  1416. if(IsSideview()){
  1417. if(Link->Dir == DIR_UP || Link->Dir == DIR_DOWN) Quit();
  1418. }
  1419.  
  1420. PegasusDash = Link->Dir;
  1421.  
  1422. if(Link->InputB && !Link->InputA) StoreInput = 2;
  1423. else if(Link->InputA && !Link->InputB) StoreInput = 1;
  1424. }
  1425. }
  1426.  
  1427.  
  1428. // Stops dashing, no collision. Easy for other scripts to call.
  1429. void StopDash(){
  1430. PegasusDash = -1;
  1431. DashCounter = 0;
  1432. }
  1433.  
  1434.  
  1435. // takes care of all the PegasusBoots functions
  1436. // call it in your global while loop, above the waitdraw and waitframe.
  1437. void PegasusBoots(){
  1438. lweapon mysword;
  1439.  
  1440. int loc = ComboAt(Link->X+8,Link->Y + Cond(BIG_LINK==0, 12, 8));
  1441.  
  1442. // this fixes the bug that makes Link dive immediately after dashing into water with flippers
  1443. if(DashCounter < 0){
  1444. DashCounter++;
  1445.  
  1446. if(Link->Action == LA_SWIMMING){
  1447. Link->InputA = false;
  1448. }else if(Link->Action == LA_DIVING){
  1449. Link->Action == LA_SWIMMING;
  1450. Link->InputA = false;
  1451. }else{
  1452. DashCounter = 0;
  1453. }
  1454. }
  1455.  
  1456. // fixs a bug with drownable water and diagonal movement off
  1457. if(CanDrown == 1 && IsWater(loc)
  1458. && Link->Action != LA_SWIMMING && Link->Action != LA_DROWNING && Link->Action != LA_DIVING){
  1459.  
  1460. if(Link->Dir == DIR_UP) Link->InputUp = true;
  1461. else if(Link->Dir == DIR_DOWN) Link->InputDown = true;
  1462. else if(Link->Dir == DIR_LEFT) Link->InputLeft = true;
  1463. else if(Link->Dir == DIR_RIGHT) Link->InputRight = true;
  1464. }
  1465.  
  1466.  
  1467. if(PegasusDash >= 0){
  1468. if(!PegasusCollision){
  1469. if( (Link->Action != LA_SCROLLING && ((StoreInput == 1 && !Link->InputA) || (StoreInput == 2 && !Link->InputB)))
  1470. || StoreHP > Link->HP || Link->Action == LA_RAFTING
  1471. || Link->Action == LA_DROWNING || Link->Action == LA_SWIMMING || Link->Action == LA_DIVING
  1472. || (CanDrown == 0 && IsWater(TouchedComboLoc())) || (CanDrown == 1 && IsWater(loc)) ){
  1473.  
  1474. StopDash();
  1475.  
  1476. if(Link->Action == LA_SWIMMING) DashCounter = -20;
  1477. }
  1478.  
  1479. if(!UsingItem(I_ROCSFEATHER_INCREASER))
  1480. NoAction();
  1481.  
  1482. if(Link->Item[I_ROCSFEATHER] && !Link->Item[I_ROCSFEATHER_INCREASER]){
  1483. Link->Item[I_ROCSFEATHER_INCREASER]=true;
  1484. }
  1485.  
  1486. // Link runs on spot for 10 frames before dash happens
  1487. if(Link->Action != LA_SCROLLING && DashCounter > 10){
  1488. if(PegasusDash == DIR_UP && DashCheck(Link->X+8,Link->Y+6,true) != 2){
  1489. Link->Y--;
  1490. drawY--;
  1491. Link->InputUp = true;
  1492. }
  1493. else if(PegasusDash == DIR_DOWN && DashCheck(Link->X+8,Link->Y+17,true) != 2){
  1494. Link->Y++;
  1495. drawY++;
  1496. Link->InputDown = true;
  1497. }
  1498. else if(PegasusDash == DIR_LEFT && DashCheck(Link->X,Link->Y+12,false) != 2){
  1499. Link->X--;
  1500. drawX--;
  1501. Link->InputLeft = true;
  1502. }
  1503. else if(PegasusDash == DIR_RIGHT && DashCheck(Link->X+16,Link->Y+12,false) != 2){
  1504. Link->X++;
  1505. drawX++;
  1506. Link->InputRight = true;
  1507. }
  1508. else{
  1509. PegasusCollision = true;
  1510. DashCounter = 0;
  1511. }
  1512. }//end DashCounter if
  1513.  
  1514. // do stuff if not jumping
  1515. if( !IsJumping() ){
  1516.  
  1517. // handles breaking of solid Pegasus combos
  1518. if(ComboFI(loc,CF_DASH) && Screen->ComboS[loc] == 1111b){
  1519. Screen->ComboD[loc]=INV_COMBO_ID;
  1520. if(Screen->ComboF[loc] == CF_DASH) Screen->ComboF[loc] = 0;
  1521. Game->PlaySound(SFX_PEGASUSBREAK);
  1522. }
  1523.  
  1524. DustDrawTile(); // use new dust draw code that works while scrolling
  1525. // DustDrawLW(); // use old dust draw code that doesn't work while scrolling (quest rule "no screen scrolling" on)
  1526.  
  1527. if(DashCounter%DashSFXLength == 0) Game->PlaySound(SFX_DASH);
  1528. }
  1529.  
  1530. // draws dashSword when scrolling
  1531. if(Link->Action == LA_SCROLLING && dashSwordTile > 0){
  1532.  
  1533. if(PegasusDash == DIR_UP)
  1534. Screen->DrawTile(0,drawX+InFrontX(DIR_UP,6),drawY+InFrontY(DIR_UP,6),
  1535. dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,0,true,128);
  1536. else if(PegasusDash == DIR_DOWN)
  1537. Screen->DrawTile(0,drawX+InFrontX(DIR_DOWN,6),drawY+InFrontY(DIR_DOWN,6),
  1538. dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,3,true,128);
  1539. else if(PegasusDash == DIR_LEFT)
  1540. Screen->DrawTile(0,drawX+InFrontX(DIR_LEFT,6),drawY+InFrontY(DIR_LEFT,6)+3,
  1541. dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,1,true,128);
  1542. else if(PegasusDash == DIR_RIGHT)
  1543. Screen->DrawTile(0,drawX+InFrontX(DIR_RIGHT,6),drawY+InFrontY(DIR_RIGHT,6)+3,
  1544. dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,0,true,128);
  1545. }
  1546.  
  1547. int swordEquip = LinkSwordEquip();
  1548.  
  1549. if(swordEquip > -1 && DashCounter>10){
  1550. // draws dashSword when not scrolling
  1551.  
  1552. mysword = LoadLWeaponOf(LW_SCRIPT3);
  1553. if(!mysword->isValid()) mysword = Screen->CreateLWeapon(LW_SCRIPT3);
  1554.  
  1555. if(swordEquip==I_SWORD4){
  1556. mysword->UseSprite(SPRITE_SWORD4);
  1557. }else if(swordEquip==I_SWORD3){
  1558. mysword->UseSprite(SPRITE_SWORD3);
  1559. }else if(swordEquip==I_SWORD2){
  1560. mysword->UseSprite(SPRITE_SWORD2);
  1561. }else{
  1562. mysword->UseSprite(SPRITE_SWORD1);
  1563. }//end sprite if
  1564.  
  1565. if(DASH_SWORD_MULT > 0){
  1566. itemdata itm = Game->LoadItemData(swordEquip);
  1567. mysword->Damage = itm->Power * DASH_SWORD_MULT;
  1568. }
  1569. else mysword->Damage = DASH_SWORD_DMG;
  1570.  
  1571. mysword->X = Link->X+InFrontX(PegasusDash, 6);
  1572. mysword->Y = Link->Y+InFrontY(PegasusDash, 6);
  1573.  
  1574. mysword->Dir = PegasusDash;
  1575. if(mysword->Dir < 2){ //dir is up or down
  1576. if(mysword->Dir == DIR_DOWN) mysword->Flip = 3;
  1577. }
  1578. else{ //dir is left or right
  1579. mysword->OriginalTile += 1;
  1580. mysword->Tile = mysword->OriginalTile;
  1581. if(mysword->Dir == DIR_LEFT) mysword->Flip = 1;
  1582. mysword->Y += 3;
  1583. }//end dir if
  1584.  
  1585. // save our sword sprite for when scrolling
  1586. dashSwordTile = mysword->Tile;
  1587. dashSwordCSet = mysword->OriginalCSet;
  1588.  
  1589. // slash stuff while dashing with sword
  1590. DoDashSlash(ComboAt(TouchedX()+InFrontX(mysword->Dir,4),TouchedY()+InFrontY(mysword->Dir,4)));
  1591. }
  1592. else{ // we don't have dashSword
  1593.  
  1594. mysword = LoadLWeaponOf(LW_SCRIPT3);
  1595. Remove(mysword);
  1596.  
  1597. dashSwordTile = 0;
  1598. dashSwordCSet = 0;
  1599. }//end mysword if
  1600.  
  1601. }//end !PegasusCollision if
  1602.  
  1603. else{ //is PegasusCollision, DashCounter has been reset to 0.
  1604. NoAction();
  1605.  
  1606. // knockback code
  1607. if(PegasusDash == DIR_UP && DashCheck(Link->X+8,Link->Y+18,true) == 0) Link->Y++;
  1608. else if(PegasusDash == DIR_DOWN && DashCheck(Link->X+8,Link->Y+6,true) == 0) Link->Y--;
  1609. else if(PegasusDash == DIR_LEFT && DashCheck(Link->X+18,Link->Y+8,false) == 0) Link->X++;
  1610. else if(PegasusDash == DIR_RIGHT && DashCheck(Link->X-2,Link->Y+8,false) == 0) Link->X--;
  1611.  
  1612. if(DashCounter == 1){
  1613. Screen->ClearSprites(SL_LWPNS);
  1614. Game->PlaySound(SFX_HITWALL);
  1615. Screen->Quake = 10;
  1616. }
  1617. else if(DashCounter == 10){
  1618. StopDash();
  1619. PegasusCollision = false;
  1620. }
  1621.  
  1622. if(DashCounter < 5) Link->Z++;
  1623. }// end PegasusCollision if/else
  1624.  
  1625. DashCounter++;
  1626. }// end PegasusDash if
  1627.  
  1628. else{ // !PegasusDash
  1629. mysword = LoadLWeaponOf(LW_SCRIPT3);
  1630. Remove(mysword);
  1631.  
  1632. dashSwordTile = 0;
  1633. dashSwordCSet = 0;
  1634.  
  1635. if(Link->Item[I_ROCSFEATHER_INCREASER]) Link->Item[I_ROCSFEATHER_INCREASER]=false;
  1636. }//end PegasusDash if/else
  1637.  
  1638. StoreHP = Link->HP;
  1639. }//end function
  1640.  
  1641.  
  1642. // next two functions draw dust when dashing. first one allows drawing during scrolling. the second is the old code, and currently unused.
  1643. void DustDrawTile(){
  1644. if(PegasusDash < 0) return;
  1645.  
  1646. int dX;
  1647. int dY;
  1648.  
  1649. if(DashCounter%4 == 0){
  1650. for(int i = 0; i < SizeOfArray(Dust_Array); i++){
  1651. if(Dust_Array[i] == 0){
  1652. Dust_Array[i] = 1;
  1653. break;
  1654. }
  1655. }
  1656. }
  1657.  
  1658. for(int i = 0; i < SizeOfArray(Dust_Array); i++){
  1659. if(Dust_Array[i]==0) continue;
  1660.  
  1661. if(PegasusDash == DIR_UP){
  1662. dX = drawX;
  1663. if(Dust_Array[i] < 4) dY = drawY+8;
  1664. else dY = drawY+8+3+(Dust_Array[i]-1);
  1665.  
  1666. }else if(PegasusDash == DIR_DOWN){
  1667. dX = drawX;
  1668.  
  1669. if(Dust_Array[i] < 4) dY = drawY;
  1670. else dY = drawY-3-(Dust_Array[i]-1);
  1671.  
  1672. }else if(PegasusDash == DIR_LEFT){
  1673.  
  1674. if(Dust_Array[i] < 4) dX = drawX;
  1675. else dX = drawX+3+(Dust_Array[i]-1);
  1676.  
  1677. dY = drawY+8;
  1678.  
  1679. }else if(PegasusDash == DIR_RIGHT){
  1680.  
  1681. if(Dust_Array[i] < 4) dX = drawX;
  1682. else dX = drawX-3-(Dust_Array[i]-1);
  1683.  
  1684. dY = drawY+8;
  1685. }
  1686.  
  1687. Screen->FastTile(0, dX, dY, T_DUST+ Floor(Dust_Array[i]/DustASpeed), DustCSet, 128);
  1688.  
  1689. if(Dust_Array[i] == DustAFrames*DustASpeed) Dust_Array[i] = 0;
  1690. else Dust_Array[i]++;
  1691. }
  1692. }
  1693.  
  1694. void DustDrawLW(){
  1695. if(PegasusDash < 0) return;
  1696.  
  1697. lweapon Dust;
  1698. if(DashCounter%4 == 0){
  1699. for(int j=1;j<=Screen->NumLWeapons();j++){
  1700. Dust = Screen->LoadLWeapon(j);
  1701. if(Dust->ID != LW_SCRIPT10) continue;
  1702. if(PegasusDash < 1) Dust->Y-=3;
  1703. else if(PegasusDash < 2) Dust->Y+=3;
  1704. else if(PegasusDash < 3) Dust->X-=3;
  1705. else if(PegasusDash < 4) Dust->X+=3;
  1706. }//end for loop
  1707.  
  1708. Dust = Screen->CreateLWeapon(LW_SCRIPT10);
  1709. Dust->OriginalTile = T_DUST;
  1710. Dust->CSet = DustCSet;
  1711. Dust->Y = Link->Y+8;
  1712. Dust->X = Link->X;
  1713. Dust->NumFrames = DustAFrames;
  1714. Dust->ASpeed = DustASpeed;
  1715. Dust->DeadState = DustAFrames*DustASpeed;
  1716. }//end dust if
  1717. }
  1718.  
  1719.  
  1720. // Check whether Link can dash onto a combo
  1721. int DashCheck(int x, int y, bool xy){
  1722. int xoffset; int yoffset;
  1723. bool Solid;
  1724.  
  1725. if(xy) xoffset = 4;
  1726. else yoffset = 3;
  1727.  
  1728. if(Screen->isSolid(x-xoffset,y-yoffset) || Screen->isSolid(x+xoffset,y+yoffset)) Solid = true;
  1729.  
  1730. if(Solid && CanDashSlash(x,y) ) Solid = false;
  1731.  
  1732. //Not solid and not a Dash combo return 0
  1733. if(!Solid && !ComboFI(x-xoffset,y-yoffset,CF_DASH) && !ComboFI(x+xoffset,y+yoffset,CF_DASH)) return 0;
  1734.  
  1735. //Is solid and is a Dash combo return 1
  1736. else if(Solid && (ComboFI(x-xoffset,y-yoffset,CF_DASH) || ComboFI(x+xoffset,y+yoffset,CF_DASH))) return 1;
  1737.  
  1738. //Is either solid without a Dash combo, or not solid with a Dash combo
  1739. else return 2;
  1740. }
  1741.  
  1742.  
  1743. //fixes a bug where you can't initiate a dash next to a slashable solid combo
  1744. bool CanDashSlash(int x, int y){
  1745. if(LinkSwordEquip() == -1) return false;
  1746.  
  1747. int loc;
  1748. loc = ComboAt(x, y);
  1749.  
  1750. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1751. // can add more combo types here by adding || Screen->ComboT[loc] == CT_
  1752. // CT_ types you might consider CT_SLASH, CT_SLASHNEXT, CT_SLASHNEXTITEM if those are solid in your quest
  1753.  
  1754. if(Screen->ComboT[loc] == CT_BUSH || Screen->ComboT[loc] == CT_BUSHNEXT )
  1755. return true;
  1756.  
  1757. return false;
  1758. }
  1759.  
  1760. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1761. // replaces the code in old Pegasus boots function for dash cutting through slashable combos.
  1762. // allows easier customization to suit your needs.
  1763.  
  1764. void DoDashSlash(int loc){
  1765. int ctype = Screen->ComboT[loc];
  1766. int sprite;
  1767. int itmset = IS_COMBOS; // item set 12 (tall grass by default)
  1768.  
  1769. bool playsound = false;
  1770.  
  1771. // add sprites to certain types
  1772. if(ctype == CT_BUSH || ctype == CT_BUSHNEXT) sprite = SPRITE_BUSH_CUT;
  1773. else if(ctype == CT_TALLGRASS || ctype == CT_TALLGRASSNEXT) sprite = SPRITE_GRASS_CUT;
  1774. else if(ctype == CT_FLOWERS) sprite = SPRITE_FLOWER_CUT;
  1775.  
  1776. // no sprite is typically associated with Slash type combos, but it could be added.
  1777.  
  1778. // itemset is changed here to the default for these types. could add more item sets based on type
  1779. if(ctype == CT_SLASHITEM || ctype == CT_SLASHNEXTITEM) itmset = 10; // default for these combo types
  1780.  
  1781. //these types default to undercombo
  1782. if(ctype == CT_BUSH || ctype == CT_TALLGRASS || ctype == CT_FLOWERS || ctype == CT_SLASH || ctype == CT_SLASHITEM){
  1783. Screen->ComboD[loc] = Screen->UnderCombo;
  1784. playsound = true;
  1785. }
  1786.  
  1787. //these types default to next combo
  1788. if(ctype == CT_BUSHNEXT || ctype == CT_TALLGRASSNEXT || ctype == CT_FLOWERS || ctype == CT_SLASHNEXT || ctype == CT_SLASHNEXTITEM){
  1789. Screen->ComboD[loc] += 1;
  1790. playsound = true;
  1791. }
  1792.  
  1793. //no functionality added for Continuous type combos.
  1794.  
  1795. if(playsound){
  1796. CreateGraphicAt(sprite,ComboX(loc),ComboY(loc));
  1797.  
  1798. Game->PlaySound(SFX_GRASSCUT); // could have different sounds for different types too by modifyng above.
  1799. ItemSetAt(itmset,loc);
  1800. }//end playsound if
  1801. }
  1802.  
  1803. // END Pegasus Boots functions
  1804.  
  1805.  
  1806.  
  1807. // .............................................................................................................................................................................
  1808. // Utility Functions used by Pegasus Boots and other scripts that might be useful for other things .......................................................................................
  1809.  
  1810.  
  1811. //returns the item# of an equipped sword. checks and returns A button first, then B button. returns -1 if no sword equipped.
  1812. int LinkSwordEquip(){
  1813. itemdata itm = Game->LoadItemData( GetEquipmentA() );
  1814.  
  1815. if(itm->Family==IC_SWORD) return GetEquipmentA();
  1816.  
  1817. itm = Game->LoadItemData(GetEquipmentB());
  1818.  
  1819. if(itm->Family==IC_SWORD) return GetEquipmentB();
  1820.  
  1821. return -1;
  1822. }
  1823.  
  1824. // the combo that link is touching in the direction he's facing
  1825. int TouchedComboLoc(){
  1826. int loc;
  1827. loc = ComboAt( TouchedX(), TouchedY() );
  1828. return loc;
  1829. }
  1830.  
  1831. // the x coord that link is touching in the direction he's facing
  1832. int TouchedX(){
  1833. int x = 0;
  1834. if(Link->Dir == DIR_UP || Link->Dir == DIR_DOWN) x = Link->X+8;
  1835. else if(Link->Dir == DIR_LEFT) x = Link->X-1;
  1836. else if(Link->Dir == DIR_RIGHT) x = Link->X+17;
  1837. return x;
  1838. }
  1839.  
  1840. // the y coord that link is touching in the direction he's facing
  1841. int TouchedY(){
  1842. int y = 0;
  1843. if(Link->Dir == DIR_UP) y = Link->Y+7;
  1844. else if(Link->Dir == DIR_DOWN) y = Link->Y+17;
  1845. else if(Link->Dir == DIR_LEFT || Link->Dir == DIR_RIGHT) y = Link->Y+8;
  1846. return y;
  1847. }
  1848.  
  1849. // draws a sprite as a non-damaging eweapon
  1850. int CreateGraphicAt(int sprite, int x, int y){
  1851. eweapon e = Screen->CreateEWeapon(EW_SCRIPT1);
  1852. e->HitXOffset = 500;
  1853. e->UseSprite(sprite);
  1854. e->DeadState = Max(1,e->NumFrames*e->ASpeed);
  1855. e->X = x;
  1856. e->Y = y;
  1857. return e->DeadState;
  1858. }
  1859.  
  1860. //creates and kills an enemy of type NPC_ITEMSET to fake an itemdropset.
  1861. void ItemSetAt(int itemset,int loc){
  1862. npc e = Screen->CreateNPC(NPC_ITEMSET);
  1863. e->ItemSet = itemset;
  1864. if(e->isValid()){
  1865. e->X = loc%16*16;
  1866. e->Y = loc-loc%16;
  1867. }
  1868. e->HP = HP_SILENT;
  1869. }
  1870.  
  1871.  
  1872. // utility function returns true if Link is jumping, necessary because SideView gravity sucks
  1873. // might need tweaking depending on other SideView scripts you use.
  1874.  
  1875. bool IsJumping(){
  1876. if(IsSideview()){
  1877. if(Link->Action == LA_SWIMMING || Link->Action == LA_DIVING || Link->Action == LA_DROWNING) return false;
  1878. if(Link->Jump != 0) return true;
  1879. if(!OnSidePlatform(Link->X,Link->Y)) return true;
  1880. }
  1881. else{
  1882. if(Link->Z > 0) return true;
  1883. }
  1884.  
  1885. return false;
  1886. }
  1887.  
  1888.  
  1889. // Allows drawing tiles to correct position on Link when scrolling
  1890. // Sets drawX/drawY either to Link X/Y when not scrolling, or the visual position when scrolling.
  1891. // currently only used by Pegasus Boots (which is also setting drawX/drawY to Link's new x/y as he dashes)
  1892.  
  1893. void ScrollFix(){
  1894. //function by Saffith
  1895.  
  1896. if(Link->Action==LA_SCROLLING){
  1897. if(scrollDir==-1)
  1898. {
  1899. if(Link->Y>160)
  1900. {
  1901. scrollDir=DIR_UP;
  1902. scrollCounter=45;
  1903. }
  1904. else if(Link->Y<0)
  1905. {
  1906. scrollDir=DIR_DOWN;
  1907. scrollCounter=45;
  1908. }
  1909. else if(Link->X>240)
  1910. {
  1911. scrollDir=DIR_LEFT;
  1912. scrollCounter=65;
  1913. }
  1914. else
  1915. {
  1916. scrollDir=DIR_RIGHT;
  1917. scrollCounter=65;
  1918. }
  1919. }
  1920.  
  1921. if(scrollDir==DIR_UP && scrollCounter<45 && scrollCounter>4)
  1922. drawY+=4;
  1923. else if(scrollDir==DIR_DOWN && scrollCounter<45 && scrollCounter>4)
  1924. drawY-=4;
  1925. else if(scrollDir==DIR_LEFT && scrollCounter<65 && scrollCounter>4)
  1926. drawX+=4;
  1927. else if(scrollDir==DIR_RIGHT && scrollCounter<65 && scrollCounter>4)
  1928. drawX-=4;
  1929.  
  1930. scrollCounter--;
  1931. }
  1932. else
  1933. {
  1934. drawX=Link->X;
  1935. drawY=Link->Y;
  1936. if(scrollDir!=-1)
  1937. scrollDir=-1;
  1938. }
  1939. }
  1940.  
  1941. //END Utility functions
  1942. // .............................................................................................................................................................................
  1943.  
  1944.  
  1945.  
  1946. // .............................................................................................................................................................................
  1947. // Sample global script using Pegasus Boots.
  1948. // If you aren't using any other global scripts, you can just import this as is.
  1949.  
  1950. //** If you have an existing global script, just add ScrollFix(); the top of the while loop
  1951. //** and PegasusBoots(); below that, but before the Waitdraw(); and Waitframe();
  1952. //** And remove, or comment this global script out.
  1953.  
  1954.  
  1955. //========================================
  1956. // Global Globals/Functions/Constants
  1957. //========================================
  1958.  
  1959. ///Common Constant, only need to define once per script file.
  1960. //const int BIG_LINK = 0; //Set this to 1 if using the Large Link Hit Box feature.
  1961.  
  1962. //Constants used by Ice Combos
  1963. const int CT_ICECOMBO = 142; //The combo type "Script1 by default"
  1964. const int ICE_ACCELERATION = 1;
  1965. const int ICE_DECELERATION = 1;
  1966. const int ICE_MAXSTEP = 150;
  1967.  
  1968. //Declare global variables used by Ice Combos.
  1969. bool isScrolling;
  1970. bool onice;
  1971. float Ice_X;
  1972. float Ice_Y;
  1973. int Ice_XStep;
  1974. int Ice_YStep;
  1975. //End declaration
  1976.  
  1977. //Active Script
  1978.  
  1979.  
  1980. //Initializes global variables used for ice combos.
  1981. void Setup_IceCombos()
  1982. {
  1983. isScrolling = false;
  1984. onice = false;
  1985. Ice_X = 0;
  1986. Ice_Y = 0;
  1987. Ice_XStep = 0;
  1988. Ice_YStep = 0;
  1989. }
  1990.  
  1991. //Adds Ice Combo functionally to CT_ICECOMBO;
  1992. void Update_IceCombos(int oldscreen)
  1993. {
  1994. //Update Variables
  1995. if(Link->Action != LA_SCROLLING)
  1996. {
  1997. if(isScrolling || oldscreen != Game->GetCurScreen() || (!onice && OnIce()))
  1998. {
  1999. Ice_X = Link->X;
  2000. Ice_Y = Link->Y;
  2001. if(isScrolling)
  2002. isScrolling = false;
  2003. else
  2004. {
  2005. Ice_XStep = 0;
  2006. Ice_YStep = 0;
  2007. }
  2008. }
  2009. onice = OnIce();
  2010. }
  2011. else
  2012. {
  2013. isScrolling = true;
  2014. return;
  2015. }
  2016.  
  2017. //Ice Physics
  2018. if(onice)
  2019. {
  2020. //Y Adjustment
  2021. if(Link_Walking() && (Link->InputUp || Link->InputDown))
  2022. {
  2023. if(Link->InputUp && !Link->InputDown)
  2024. Ice_YStep -= ICE_ACCELERATION;
  2025. else if(!Link->InputUp && Link->InputDown)
  2026. Ice_YStep += ICE_ACCELERATION;
  2027. }
  2028. else if(Ice_YStep != 0)
  2029. Ice_YStep = Cond(Abs(Ice_YStep) - ICE_DECELERATION > 0, Ice_YStep - Sign(Ice_YStep)*ICE_DECELERATION, 0);
  2030. Ice_YStep = Clamp(Ice_YStep, -ICE_MAXSTEP, ICE_MAXSTEP);
  2031.  
  2032. //X Adjustment
  2033. if(Link_Walking() && (Link->InputLeft || Link->InputRight))
  2034. {
  2035. if(Link->InputLeft && !Link->InputRight)
  2036. Ice_XStep -= ICE_ACCELERATION;
  2037. else if(!Link->InputLeft && Link->InputRight)
  2038. Ice_XStep += ICE_ACCELERATION;
  2039. }
  2040. else if(Ice_XStep != 0)
  2041. Ice_XStep = Cond(Abs(Ice_XStep) - ICE_DECELERATION > 0, Ice_XStep -Sign(Ice_XStep)*ICE_DECELERATION, 0);
  2042. Ice_XStep = Clamp(Ice_XStep, -ICE_MAXSTEP, ICE_MAXSTEP);
  2043.  
  2044. //Reset the Ice Position to Link's Actual Position if he's hurt or hopping out of water.
  2045. if(Link->Action == LA_GOTHURTLAND || Link->Action == LA_HOPPING)
  2046. {
  2047. Ice_X = Link->X;
  2048. Ice_Y = Link->Y;
  2049. }
  2050.  
  2051. //Initialize variables for solidity checking.
  2052. int newx = (Ice_X + Ice_XStep/100)<<0;
  2053. int newy = (Ice_Y + Ice_YStep/100)<<0;
  2054.  
  2055. //Vertical Edge
  2056. if(newx < Ice_X<<0)
  2057. {
  2058. for(int y = Ice_Y+Cond(BIG_LINK, 0, 8); y < (Ice_Y<<0) + 16 && Ice_XStep != 0; y++)
  2059. {
  2060. if(Screen->isSolid(newx, y))
  2061. Ice_XStep = 0;
  2062. }
  2063. }
  2064. else if(newx > Ice_X<<0)
  2065. {
  2066. for(int y = Ice_Y+8; y < (Ice_Y<<0) + 16 && Ice_XStep != 0; y++)
  2067. {
  2068. if(Screen->isSolid(newx+15, y))
  2069. Ice_XStep = 0;
  2070. }
  2071. }
  2072.  
  2073. //Horizontal Edge
  2074. if(newy < Ice_Y<<0)
  2075. {
  2076. for(int x = Ice_X; x < (Ice_X<<0) + 16 && Ice_YStep != 0; x++)
  2077. {
  2078. if(Screen->isSolid(x, newy+Cond(BIG_LINK, 0, 8)))
  2079. {
  2080. Ice_YStep = 0;
  2081. }
  2082. }
  2083. }
  2084. else if(newy > Ice_Y<<0)
  2085. {
  2086. for(int x = Ice_X; x < (Ice_X<<0) + 16 && Ice_YStep != 0; x++)
  2087. {
  2088. if(Screen->isSolid(x, newy+15))
  2089. {
  2090. Ice_YStep = 0;
  2091. }
  2092. }
  2093. }
  2094.  
  2095. Ice_X += Ice_XStep/100;
  2096. Ice_Y += Ice_YStep/100;
  2097. Link->X = Ice_X;
  2098. Link->Y = Ice_Y;
  2099. }
  2100. else
  2101. {
  2102. Ice_XStep = 0;
  2103. Ice_YStep = 0;
  2104. }
  2105. }
  2106.  
  2107. //Function used to check if Link is over a ice combo.
  2108. bool OnIce()
  2109. {
  2110. if(Link->Z != 0)
  2111. return false;
  2112. else
  2113. {
  2114. int comboLoc = ComboAt(Link->X + 8, Link->Y + 12);
  2115. if(Screen->ComboT[comboLoc] == CT_ICECOMBO)
  2116. return true;
  2117. else if(Screen->LayerScreen(1) != -1 && GetLayerComboT(1, comboLoc) == CT_ICECOMBO)
  2118. return true;
  2119. else if(Screen->LayerScreen(2) != -1 && GetLayerComboT(2, comboLoc) == CT_ICECOMBO)
  2120. return true;
  2121. else
  2122. return false;
  2123. }
  2124. }
  2125.  
  2126. //Returns true, if keyboard input is moving Link.
  2127. bool Link_Walking()
  2128. {
  2129. if(UsingItem(I_HAMMER)) return false;
  2130. else return (Link->Action == LA_WALKING || Link->Action == LA_CHARGING || Link->Action == LA_SPINNING);
  2131. }
  2132.  
  2133. //========================================
  2134. // Global Globals/Functions/Constants
  2135. //========================================
  2136.  
  2137. const int CMB_MINECART = 7688; //Combo of the minecart, first of 16
  2138. //1-4: Minecart, stationary, 4-way
  2139. //5-8: Minecart, moving, 4-way
  2140. //9-12: Minecart, front layer, 4-way
  2141. //13-16: Link riding in minecart, 4-way
  2142. const int CS_MINECART = 2;
  2143.  
  2144. const int CMB_MINECART_TRACK = 7680; //First of a set of 7 minecart track combos.
  2145. //Only these combos when placed on layer 0 will actually function as minecart tracks
  2146. //1: Up/Down
  2147. //2: Left/Right
  2148. //3: Right/Down
  2149. //4: Left/Down
  2150. //5: Right/Up
  2151. //6: Left/Up
  2152. //7: Exit pad
  2153.  
  2154. const int SFX_MINECART = 65; //Looping sound of the minecart on the tracks
  2155. const int MINECART_SFX_FREQ = 30; //How often the sound loops
  2156.  
  2157. const int MINECART_LINKYOFFSET = -10; //Offset Link's sprite is drawn at compared to the minecart
  2158.  
  2159. const int DAMAGE_MINECART_COLLISION = 8; //How much damage the minecart does when it hits enemies
  2160. const int LW_MINECART_DAMAGE = 2; //Weapon type the minecart's hitbox uses. LW_BEAM by default
  2161.  
  2162. int GBCart[80];
  2163. const int GBC_DIR = 65;
  2164. const int GBC_CURID = 66;
  2165. const int GBC_FIRSTLOAD = 67;
  2166. const int GBC_ACTIVEFFC = 68;
  2167.  
  2168. void Minecart_Init(){
  2169. Link->DrawYOffset = 0;
  2170. Link->CollDetection = true;
  2171. GBCart[GBC_DIR] = -1;
  2172. if(GBCart[GBC_FIRSTLOAD]==0){
  2173. for(int i=0; i<64; i++){
  2174. GBCart[i] = -1;
  2175. }
  2176. GBCart[GBC_FIRSTLOAD] = 1;
  2177. }
  2178. }
  2179.  
  2180. void Minecart_Update(){
  2181. if(GBCart[GBC_DIR]>-1){
  2182. int scr[] = "GBMinecart_FFC";
  2183. Link->DrawYOffset = MINECART_LINKYOFFSET;
  2184. Link->CollDetection = false;
  2185. if(Link->Action==LA_SCROLLING){
  2186. GBCart[GBC_ACTIVEFFC] = -1;
  2187. Minecart_Draw(ScrollingLinkX(), ScrollingLinkY(), GBCart[GBC_DIR], true);
  2188. }
  2189. else if(GBCart[GBC_ACTIVEFFC]>0){
  2190. ffc f = Screen->LoadFFC(GBCart[GBC_ACTIVEFFC]);
  2191. if(f->Script==Game->GetFFCScript(scr)){
  2192. Link->X = f->X;
  2193. Link->Y = f->Y;
  2194. }
  2195. }
  2196. if(Minecart_CountFFCs(Game->GetFFCScript(scr), GBCart[GBC_CURID])==0){
  2197. ffc f = Screen->LoadFFC(GBCart[GBC_ACTIVEFFC]);
  2198. if(f->Script!=Game->GetFFCScript(scr)||f->InitD[1]!=GBCart[GBC_CURID]){
  2199. if(Link->X>=0&&Link->X<=240&&Link->Y>=0&&Link->Y<=160){
  2200. int args[8];
  2201. args[0] = GBCart[GBC_DIR];
  2202. args[1] = GBCart[GBC_CURID];
  2203. args[2] = 0;
  2204. args[3] = 1;
  2205. f = Screen->LoadFFC(RunFFCScript(Game->GetFFCScript(scr), args));
  2206. f->CSet = CS_MINECART;
  2207. GBCart[GBC_ACTIVEFFC] = FFCNum(f);
  2208. f->Flags[FFCF_PRELOAD] = true;
  2209. f->X = Link->X;
  2210. f->Y = Link->Y;
  2211. }
  2212. }
  2213. }
  2214. }
  2215. }
  2216.  
  2217. int Minecart_CountFFCs(int scrpt, int id){
  2218. int count;
  2219. for(int i=1; i<=32; i++){
  2220. ffc f = Screen->LoadFFC(i);
  2221. if(f->Script==scrpt&&f->InitD[1]==id&&f->InitD[3]==1)
  2222. count++;
  2223. }
  2224. return count;
  2225. }
  2226.  
  2227. void Minecart_Draw(int x, int y, int dir, bool linkInside){
  2228. int layer = 2;
  2229. if(ScreenFlag(1, 4))
  2230. layer = 1;
  2231. dir = Clamp(dir, 0, 3);
  2232. if(linkInside){
  2233. Screen->FastCombo(layer, x, y, CMB_MINECART+4+dir, CS_MINECART, 128);
  2234. if(Link->Action==LA_WALKING||Link->Action==LA_NONE||Link->Action==LA_SCROLLING){
  2235. Screen->FastCombo(layer, x, y+MINECART_LINKYOFFSET, CMB_MINECART+12+Link->Dir, 6, 128);
  2236. Link->Invisible = true;
  2237. }
  2238. else
  2239. Link->Invisible = false;
  2240. Screen->FastCombo(4, x, y, CMB_MINECART+8+dir, CS_MINECART, 128);
  2241. }
  2242. else{
  2243. Screen->FastCombo(layer, x, y, CMB_MINECART+dir, CS_MINECART, 128);
  2244. }
  2245. }
  2246.  
  2247.  
  2248. ffc script GBMinecart_FFC{
  2249. void run(int startDir, int ID, int start, int spawned){
  2250. int ffcNum = FFCNum(this);
  2251. int tempID;
  2252. if(ID>0)
  2253. tempID = Clamp(ID-1, 0, 63);
  2254.  
  2255. if(GBCart[GBC_DIR]<=-1||GBCart[GBC_CURID]!=ID)
  2256. this->Data = CMB_MINECART+startDir;
  2257. else if(spawned==0){
  2258. if(Link->X<=0||Link->X>=240||Link->Y<=0||Link->Y>=160){
  2259. this->Data = 0;
  2260. Quit();
  2261. }
  2262. else{
  2263. GBCart[GBC_DIR] = -1;
  2264. Waitframe();
  2265. }
  2266. }
  2267. else{
  2268. if(GBCart[GBC_ACTIVEFFC]==-1)
  2269. GBCart[GBC_ACTIVEFFC] = ffcNum;
  2270. }
  2271. if(spawned==0&&GBCart[GBC_DIR]==-1&&ID>0){
  2272. if(GBCart[tempID]==-1){
  2273. if(start){
  2274. GBCart[tempID] = Game->GetCurScreen();
  2275. }
  2276. else{
  2277. this->Data = 0;
  2278. Quit();
  2279. }
  2280. }
  2281. else if(GBCart[tempID]!=Game->GetCurScreen()&&GBCart[GBC_FIRSTLOAD]==1){
  2282. this->Data = 0;
  2283. Quit();
  2284. }
  2285. }
  2286. int lastDir = startDir;
  2287. int sfxCounter;
  2288. lweapon hitbox;
  2289. while(true){
  2290. while(GBCart[GBC_DIR]==-1||GBCart[GBC_CURID]!=ID){
  2291. this->Data = CMB_MINECART+startDir;
  2292. if(Link->Y<this->Y)
  2293. this->Flags[FFCF_OVERLAY] = true;
  2294. else
  2295. this->Flags[FFCF_OVERLAY] = false;
  2296. if(GBMinecart_Collision(this)){
  2297. while(Link->Z>0){
  2298. WaitNoAction();
  2299. }
  2300. this->Flags[FFCF_OVERLAY] = false;
  2301. Link->Dir = AngleDir4(Angle(Link->X, Link->Y, this->X, this->Y));
  2302. Link->Jump = 2;
  2303. Game->PlaySound(SFX_JUMP);
  2304. int angle = Angle(Link->X, Link->Y, this->X, this->Y+MINECART_LINKYOFFSET);
  2305. int dist = Distance(Link->X, Link->Y, this->X, this->Y+MINECART_LINKYOFFSET);
  2306. int linkX = Link->X;
  2307. int linkY = Link->Y;
  2308. for(int i=0; i<26; i++){
  2309. linkX += VectorX(dist/26, angle);
  2310. linkY += VectorY(dist/26, angle);
  2311. Link->X = linkX;
  2312. Link->Y = linkY;
  2313. WaitNoAction();
  2314. }
  2315. Link->DrawYOffset = MINECART_LINKYOFFSET;
  2316. Link->CollDetection = false;
  2317. GBCart[GBC_DIR] = startDir;
  2318. GBCart[GBC_CURID] = ID;
  2319. GBCart[GBC_ACTIVEFFC] = FFCNum(this);
  2320. sfxCounter = 0;
  2321. }
  2322. Waitframe();
  2323. }
  2324. while(GBCart[GBC_DIR]!=-1&&GBCart[GBC_CURID]==ID){
  2325. int cp = ComboAt(this->X+8, this->Y+8);
  2326. lastDir = GBCart[GBC_DIR];
  2327. GBCart[GBC_DIR] = GBMinecart_NextDirection(cp, GBCart[GBC_DIR]);
  2328. for(int i=0; i<8&&GBCart[GBC_DIR]>-1; i++){
  2329. if(sfxCounter==0)
  2330. Game->PlaySound(SFX_MINECART);
  2331.  
  2332. sfxCounter++;
  2333. if(sfxCounter>MINECART_SFX_FREQ)
  2334. sfxCounter = 0;
  2335. if(GBCart[GBC_DIR]==DIR_UP)
  2336. this->Y -= 2;
  2337. else if(GBCart[GBC_DIR]==DIR_DOWN)
  2338. this->Y += 2;
  2339. else if(GBCart[GBC_DIR]==DIR_LEFT)
  2340. this->X -= 2;
  2341. else if(GBCart[GBC_DIR]==DIR_RIGHT)
  2342. this->X += 2;
  2343. this->Data = FFCS_INVISIBLE_COMBO;
  2344. hitbox = GBMinecart_UpdateHitbox(hitbox, this->X, this->Y, true);
  2345. Minecart_Draw(this->X, this->Y, GBCart[GBC_DIR], true);
  2346. Link->X = this->X;
  2347. Link->Y = this->Y;
  2348. Waitframe();
  2349. }
  2350. this->X = GridX(this->X+8);
  2351. this->Y = GridY(this->Y+8);
  2352. if(GBCart[GBC_DIR]<=-1){
  2353. if(GBCart[GBC_DIR]<-1)
  2354. lastDir = Abs(GBCart[GBC_DIR])-2;
  2355. GBCart[GBC_DIR] = -1;
  2356. this->Data = CMB_MINECART+lastDir;
  2357.  
  2358. Link->DrawYOffset = 0;
  2359. Link->Invisible = false;
  2360. Link->CollDetection = true;
  2361. cp = GBMinecart_ComboInFront(cp, lastDir);
  2362. Link->Dir = AngleDir4(Angle(Link->X, Link->Y, ComboX(cp), ComboY(cp)));
  2363. Link->Y += MINECART_LINKYOFFSET;
  2364. Link->Jump = 2;
  2365. Game->PlaySound(SFX_JUMP);
  2366. int angle = Angle(Link->X, Link->Y, ComboX(cp), ComboY(cp));
  2367. int dist = Distance(Link->X, Link->Y, ComboX(cp), ComboY(cp));
  2368. int linkX = Link->X;
  2369. int linkY = Link->Y;
  2370. for(int i=0; i<26; i++){
  2371. linkX += VectorX(dist/26, angle);
  2372. linkY += VectorY(dist/26, angle);
  2373. Link->X = linkX;
  2374. Link->Y = linkY;
  2375. hitbox = GBMinecart_UpdateHitbox(hitbox, this->X, this->Y, false);
  2376. WaitNoAction();
  2377. }
  2378. startDir = OppositeDir(lastDir);
  2379. if(GBCart[GBC_CURID]>0){
  2380. tempID = Clamp(GBCart[GBC_CURID]-1, 0, 63);
  2381. GBCart[tempID] = Game->GetCurScreen();
  2382. }
  2383. //MooshPit_ResetEntry();
  2384. }
  2385. }
  2386. }
  2387. }
  2388. int GBMinecart_NextDirection(int cp, int dir){
  2389. int up[6] = {1, 0, 0, 0, 1, 1};
  2390. int down[6] = {1, 0, 1, 1, 0, 0};
  2391. int left[6] = {0, 1, 0, 1, 0, 1};
  2392. int right[6] = {0, 1, 1, 0, 1, 0};
  2393. int directions[4] = {up, down, left, right};
  2394.  
  2395. int c;
  2396.  
  2397. //Combo under
  2398. c = Screen->ComboD[cp];
  2399. if(c>=CMB_MINECART_TRACK&&c<=CMB_MINECART_TRACK+5)
  2400. c = Clamp(c-CMB_MINECART_TRACK, 0, 5);
  2401. else
  2402. c = -1;
  2403.  
  2404. int frontDir = -1;
  2405. int d = directions[dir];
  2406. if(d[c]==1&&frontDir==-1){
  2407. frontDir = dir;
  2408. }
  2409. else{
  2410. for(int i=0; i<4; i++){
  2411. if(i!=OppositeDir(dir)&&i!=dir){
  2412. d = directions[i];
  2413. if(d[c]==1){
  2414. int c2 = Screen->ComboD[GBMinecart_ComboInFront(cp, i)];
  2415. if(c2>=CMB_MINECART_TRACK&&c2<=CMB_MINECART_TRACK+5)
  2416. return i;
  2417. if(c2==CMB_MINECART_TRACK+6)
  2418. return -2-i;
  2419. else
  2420. return OppositeDir(dir);
  2421. }
  2422. }
  2423. }
  2424. }
  2425.  
  2426. c = Screen->ComboD[GBMinecart_ComboInFront(cp, dir)];
  2427. if(c>=CMB_MINECART_TRACK&&c<=CMB_MINECART_TRACK+6)
  2428. c = Clamp(c-CMB_MINECART_TRACK, 0, 6);
  2429. else
  2430. c = -1;
  2431. if(c==-1)
  2432. return OppositeDir(dir);
  2433. else if(c==6)
  2434. return -1;
  2435.  
  2436. if(frontDir>-1)
  2437. return frontDir;
  2438. return dir;
  2439. }
  2440. int GBMinecart_ComboInFront(int cp, int dir){
  2441. if(cp<16&&dir==DIR_UP)
  2442. return cp;
  2443. else if(cp>159&&dir==DIR_DOWN)
  2444. return cp;
  2445. else if(cp%16==0&&dir==DIR_LEFT)
  2446. return cp;
  2447. else if(cp%16==15&&dir==DIR_RIGHT)
  2448. return cp;
  2449. if(dir==DIR_UP)
  2450. cp -= 16;
  2451. else if(dir==DIR_DOWN)
  2452. cp += 16;
  2453. else if(dir==DIR_LEFT)
  2454. cp--;
  2455. else if(dir==DIR_RIGHT)
  2456. cp++;
  2457. return cp;
  2458. }
  2459. bool GBMinecart_Collision(ffc this){
  2460. if(Abs(Link->X-this->X)<12&&Abs(Link->Y-this->Y)<10)
  2461. return true;
  2462. return false;
  2463. }
  2464. lweapon GBMinecart_UpdateHitbox(lweapon hitbox, int x, int y, bool alive){
  2465. if(hitbox->isValid()){
  2466. hitbox->X = x;
  2467. hitbox->Y = y;
  2468. hitbox->Dir = GBCart[GBC_DIR];
  2469. hitbox->Step = 0;
  2470. hitbox->DeadState = -1;
  2471. hitbox->DrawYOffset = -1000;
  2472. if(!alive){
  2473. hitbox->DeadState = 0;
  2474. }
  2475. }
  2476. else{
  2477. if(alive){
  2478. hitbox = CreateLWeaponAt(LW_MINECART_DAMAGE, x, y);
  2479. hitbox->Dir = GBCart[GBC_DIR];
  2480. hitbox->Damage = DAMAGE_MINECART_COLLISION;
  2481. hitbox->Step = 0;
  2482. hitbox->DeadState = -1;
  2483. hitbox->DrawYOffset = -1000;
  2484. }
  2485. }
  2486. return hitbox;
  2487. }
  2488. }
  2489.  
  2490. ffc script GBMinecart_Shutter{
  2491. void run(){
  2492. int thisData = this->Data;
  2493. int thisCSet = this->CSet;
  2494. this->Data = FFCS_INVISIBLE_COMBO;
  2495. int cp = ComboAt(this->X+8, this->Y+8);
  2496. int underCombo = Screen->ComboD[cp];
  2497. int underCSet = Screen->ComboC[cp];
  2498. int LinkX = Link->X;
  2499. if(LinkX<=0)
  2500. LinkX = 240;
  2501. else if(LinkX>=240)
  2502. LinkX = 0;
  2503. int LinkY = Link->Y;
  2504. if(LinkY<=0)
  2505. LinkY = 160;
  2506. else if(LinkY>=160)
  2507. LinkY = 0;
  2508. if(!(Abs(this->X-LinkX)<20&&Abs(this->Y-LinkY)<20)){
  2509. Screen->ComboD[cp] = thisData;
  2510. Screen->ComboC[cp] = thisCSet;
  2511. while(GBCart[GBC_DIR]==-1||!(Abs(this->X-Link->X)<20&&Abs(this->Y-Link->Y)<20)){
  2512. Waitframe();
  2513. }
  2514. Game->PlaySound(SFX_SHUTTER);
  2515. Screen->ComboD[cp] = underCombo;
  2516. Screen->ComboC[cp] = underCSet;
  2517. this->Data = thisData+1;
  2518. this->CSet = thisCSet;
  2519. Waitframes(4);
  2520. this->Data = FFCS_INVISIBLE_COMBO;
  2521. }
  2522. else{
  2523. Waitframe();
  2524.  
  2525. }
  2526. while(true){
  2527. while(GBCart[GBC_DIR]>-1&&(Abs(this->X-Link->X)<20&&Abs(this->Y-Link->Y)<20)){
  2528. Waitframe();
  2529. }
  2530. Game->PlaySound(SFX_SHUTTER);
  2531. this->Data = thisData+1;
  2532. this->CSet = thisCSet;
  2533. Waitframes(4);
  2534. Screen->ComboD[cp] = thisData;
  2535. Screen->ComboC[cp] = thisCSet;
  2536. this->Data = FFCS_INVISIBLE_COMBO;
  2537. while(GBCart[GBC_DIR]==-1||!(Abs(this->X-Link->X)<20&&Abs(this->Y-Link->Y)<20)){
  2538. Waitframe();
  2539. }
  2540. Game->PlaySound(SFX_SHUTTER);
  2541. Screen->ComboD[cp] = underCombo;
  2542. Screen->ComboC[cp] = underCSet;
  2543. this->Data = thisData+1;
  2544. this->CSet = thisCSet;
  2545. Waitframes(4);
  2546. this->Data = FFCS_INVISIBLE_COMBO;
  2547. }
  2548. }
  2549. }
  2550.  
  2551. ffc script GBMinecart_ResetID{
  2552. void run(int id1, int id2, int id3, int id4, int id5, int id6, int id7, int id8){
  2553. if(Distance(Link->X, Link->Y, this->X, this->Y)<16){
  2554. int ids[8];
  2555. ids[0] = id1;
  2556. ids[1] = id2;
  2557. ids[2] = id3;
  2558. ids[3] = id4;
  2559. ids[4] = id5;
  2560. ids[5] = id6;
  2561. ids[6] = id7;
  2562. ids[7] = id8;
  2563. for(int i=0; i<8; i++){
  2564. int tempID = Clamp(ids[i]-1, 0, 63);
  2565. if(ids[i]>0)
  2566. GBCart[tempID] = -1;
  2567. }
  2568. }
  2569. }
  2570. }
  2571. //========================================
  2572. // Global Globals/Functions/Constants
  2573. //========================================
  2574.  
  2575. const int QUESTRULE_VERYFASTSCROLLING = 1; //Set this to 1 if the Very Fast Scrolling quest rule is enabled
  2576.  
  2577.  
  2578. int scrollingDraws[8];
  2579. const int SD_NSCX = 0;
  2580. const int SD_NSCY = 1;
  2581. const int SD_OSCX = 2;
  2582. const int SD_OSCY = 3;
  2583. const int SD_SAVELASTSCREEN = 4;
  2584. const int SD_LASTSCREEN = 5;
  2585. const int SD_SCROLLDIR = 6;
  2586. const int SD_SCROLLTIMER = 7;
  2587.  
  2588. void ScrollingDraws_Init(){
  2589. scrollingDraws[SD_SAVELASTSCREEN] = Game->GetCurScreen();
  2590. scrollingDraws[SD_SCROLLTIMER] = -1;
  2591. scrollingDraws[SD_NSCX] = -1000;
  2592. scrollingDraws[SD_NSCY] = -1000;
  2593. scrollingDraws[SD_OSCX] = 0;
  2594. scrollingDraws[SD_OSCY] = 0;
  2595. }
  2596.  
  2597. void ScrollingDraws_Update(){
  2598. if(Link->Action==LA_SCROLLING){
  2599. //Try to get the direction the screen is scrolling based on the position of the last screen visited
  2600. if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]-16)
  2601. scrollingDraws[SD_SCROLLDIR] = DIR_UP;
  2602. else if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]+16)
  2603. scrollingDraws[SD_SCROLLDIR] = DIR_DOWN;
  2604. else if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]-1)
  2605. scrollingDraws[SD_SCROLLDIR] = DIR_LEFT;
  2606. else if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]+1)
  2607. scrollingDraws[SD_SCROLLDIR] = DIR_RIGHT;
  2608.  
  2609. //If Link just started scrolling, reset the timer
  2610. if(scrollingDraws[SD_SCROLLTIMER]==-1){
  2611. scrollingDraws[SD_SCROLLTIMER] = 0;
  2612. }
  2613.  
  2614. //Change max timer frames to account for Fast Scrolling
  2615. int framesX = 64;
  2616. int framesY = 44;
  2617. if(QUESTRULE_VERYFASTSCROLLING){
  2618. framesX = 16;
  2619. framesY = 11;
  2620. }
  2621.  
  2622. //There's a few extra frames after the screen stops visibly scrolling. Clamp the timer to accommodate.
  2623. int i;
  2624. if(scrollingDraws[SD_SCROLLDIR]==DIR_UP||scrollingDraws[SD_SCROLLDIR]==DIR_DOWN)
  2625. i = Clamp(scrollingDraws[SD_SCROLLTIMER], 0, framesY);
  2626. else
  2627. i = Clamp(scrollingDraws[SD_SCROLLTIMER], 0, framesX);
  2628.  
  2629. int newScreenX;
  2630. int newScreenY;
  2631. int oldScreenX;
  2632. int oldScreenY;
  2633.  
  2634. int incrementX = 256/framesX;
  2635. int incrementY = 176/framesY;
  2636.  
  2637. //Set screen positions based on the timer
  2638. if(scrollingDraws[SD_SCROLLDIR]==DIR_UP){
  2639. newScreenX = 0;
  2640. newScreenY = -176+incrementY*i;
  2641. oldScreenX = 0;
  2642. oldScreenY = incrementY*i;
  2643. }
  2644. else if(scrollingDraws[SD_SCROLLDIR]==DIR_DOWN){
  2645. newScreenX = 0;
  2646. newScreenY = 176-incrementY*i;
  2647. oldScreenX = 0;
  2648. oldScreenY = -incrementY*i;
  2649. }
  2650. else if(scrollingDraws[SD_SCROLLDIR]==DIR_LEFT){
  2651. newScreenX = -256+incrementX*i;
  2652. newScreenY = 0;
  2653. oldScreenX = incrementX*i;
  2654. oldScreenY = 0;
  2655. }
  2656. else if(scrollingDraws[SD_SCROLLDIR]==DIR_RIGHT){
  2657. newScreenX = 256-incrementX*i;
  2658. newScreenY = 0;
  2659. oldScreenX = -incrementX*i;
  2660. oldScreenY = 0;
  2661. }
  2662.  
  2663. scrollingDraws[SD_NSCX] = newScreenX;
  2664. scrollingDraws[SD_NSCY] = newScreenY;
  2665. scrollingDraws[SD_OSCX] = oldScreenX;
  2666. scrollingDraws[SD_OSCY] = oldScreenY;
  2667.  
  2668. if(scrollingDraws[SD_SCROLLTIMER]>=0)
  2669. scrollingDraws[SD_SCROLLTIMER]++;
  2670. }
  2671. else{ //Globals are reset when Link isn't scrolling
  2672. scrollingDraws[SD_SAVELASTSCREEN] = Game->GetCurScreen();
  2673. scrollingDraws[SD_SCROLLTIMER] = -1;
  2674. scrollingDraws[SD_NSCX] = -1000;
  2675. scrollingDraws[SD_NSCY] = -1000;
  2676. scrollingDraws[SD_OSCX] = 0;
  2677. scrollingDraws[SD_OSCY] = 0;
  2678. }
  2679.  
  2680. scrollingDraws[SD_LASTSCREEN] = Game->GetCurScreen();
  2681. }
  2682.  
  2683. //Returns the X position of the top left corner of the old screen when scrolling.
  2684. //When not scrolling, returns 0.
  2685. int ScrollingOldX(){
  2686. return scrollingDraws[SD_OSCX];
  2687. }
  2688. //Returns the Y position of the top left corner of the old screen when scrolling.
  2689. //When not scrolling, returns 0.
  2690. int ScrollingOldY(){
  2691. return scrollingDraws[SD_OSCY];
  2692. }
  2693.  
  2694. //Returns the X position of the top left corner of the new screen when scrolling.
  2695. //When not scrolling, returns -1000.
  2696. int ScrollingNewX(){
  2697. return scrollingDraws[SD_NSCX];
  2698. }
  2699. //Returns the Y position of the top left corner of the new screen when scrolling.
  2700. //When not scrolling, returns -1000.
  2701. int ScrollingNewY(){
  2702. return scrollingDraws[SD_NSCY];
  2703. }
  2704. //Returns Link's X position when scrolling.
  2705. //When not scrolling, returns Link's X position on the screen.
  2706. int ScrollingLinkX(){
  2707. if(Link->Action!=LA_SCROLLING)
  2708. return Link->X;
  2709. return scrollingDraws[SD_NSCX]+Link->X;
  2710. }
  2711. //Returns Link's Y position when scrolling.
  2712. //When not scrolling, returns Link's Y position on the screen.
  2713. int ScrollingLinkY(){
  2714. if(Link->Action!=LA_SCROLLING)
  2715. return Link->Y;
  2716. return scrollingDraws[SD_NSCY]+Link->Y;
  2717. }
  2718.  
  2719.  
  2720. //Function for testing the drawing positions
  2721. void ScrollingDraws_TestFunction(){
  2722. if(Link->Action==LA_SCROLLING){
  2723. Screen->FastTile(6, ScrollingLinkX(), ScrollingLinkY(), Link->Tile, 8, 128);
  2724. Screen->FastTile(6, ScrollingOldX(), ScrollingOldY(), Link->Tile, 6, 128);
  2725. Screen->FastTile(6, ScrollingNewX(), ScrollingNewY(), Link->Tile, 7, 128);
  2726. }
  2727. }
  2728. //========================================
  2729. // Global Globals/Functions/Constants
  2730. //========================================
  2731.  
  2732. // uncomment this line (remove the //) if you haven't already imported std.zh in your script file
  2733. //import "std.zh"
  2734.  
  2735. int BetterByrna[8];
  2736. const int BETTERBYRNA_COST = 0;
  2737. const int BETTERBYRNA_MP_TRACKER = 1;
  2738. const int BETTERBYRNA_INVINCIBLE = 2;
  2739. const int BETTERBYRNA_BLOCK_PROJECTILES = 3;
  2740.  
  2741.  
  2742. void BetterByrna()
  2743. {
  2744. if (NumLWeaponsOf(LW_CANEOFBYRNA) > 0)
  2745. {
  2746. // make player invincible
  2747. if (Link->CollDetection && BetterByrna[BETTERBYRNA_INVINCIBLE])
  2748. {
  2749. Link->CollDetection = false;
  2750. }
  2751.  
  2752. // deduct MP cost
  2753. if (BetterByrna[BETTERBYRNA_MP_TRACKER] >= 1)
  2754. {
  2755. if (Link->MP - Floor(BetterByrna[BETTERBYRNA_MP_TRACKER]) >= 0)
  2756. {
  2757. Link->MP -= Floor(BetterByrna[BETTERBYRNA_MP_TRACKER]);
  2758. }
  2759. else
  2760. {
  2761. Link->MP = 0;
  2762. }
  2763. BetterByrna[BETTERBYRNA_MP_TRACKER] -= Floor(BetterByrna[BETTERBYRNA_MP_TRACKER]);
  2764. }
  2765. if (Link->MP == 0)
  2766. {
  2767. lweapon byrna = LoadLWeaponOf(LW_CANEOFBYRNA);
  2768. Remove(byrna);
  2769. }
  2770. else
  2771. {
  2772. BetterByrna[BETTERBYRNA_MP_TRACKER] += BetterByrna[BETTERBYRNA_COST] * (Game->Generic[GEN_MAGICDRAINRATE] * 0.5);
  2773. }
  2774.  
  2775. // block projectiles
  2776. if (BetterByrna[BETTERBYRNA_BLOCK_PROJECTILES])
  2777. {
  2778. for (int i = Screen->NumEWeapons(); i > 0; i--)
  2779. {
  2780. eweapon projectile = Screen->LoadEWeapon(i);
  2781. if (projectile->ID != EW_BOMBBLAST && projectile->ID != EW_SBOMBBLAST)
  2782. {
  2783. for (int j = Screen->NumLWeapons(); j > 0; j--)
  2784. {
  2785. lweapon byrna = Screen->LoadLWeapon(j);
  2786. if (byrna->ID == LW_CANEOFBYRNA && Collision(projectile, byrna))
  2787. {
  2788. Remove(projectile);
  2789. }
  2790. }
  2791. }
  2792. }
  2793. }
  2794. }
  2795. // make player vulnerable again
  2796. else if (!Link->CollDetection)
  2797. {
  2798. Link->CollDetection = true;
  2799. }
  2800.  
  2801. if (Link->MP == 0 && (Link->InputA || Link->InputB))
  2802. {
  2803. itemdata a_button = Game->LoadItemData(GetEquipmentA());
  2804. itemdata b_button = Game->LoadItemData(GetEquipmentB());
  2805. if (Link->InputA && a_button->Family == IC_CBYRNA)
  2806. {
  2807. Link->InputA = false;
  2808. Link->PressA = false;
  2809. }
  2810. if (Link->InputB && b_button->Family == IC_CBYRNA)
  2811. {
  2812. Link->InputB = false;
  2813. Link->PressB = false;
  2814. }
  2815. }
  2816. }
  2817.  
  2818. // D0: reserved for other things, like pickup message scripts
  2819. // D1: MP cost per frame
  2820. // D2: 1 for invincible while cane is in use
  2821. // D3: 1 to block enemy projectiles
  2822. item script BetterByrnaItem
  2823. {
  2824. void run(int foo, int cost, int invincible, int block_projectiles)
  2825. {
  2826. BetterByrna[BETTERBYRNA_COST] = cost;
  2827. BetterByrna[BETTERBYRNA_INVINCIBLE] = invincible;
  2828. BetterByrna[BETTERBYRNA_BLOCK_PROJECTILES] = block_projectiles;
  2829. }
  2830. }
  2831. //========================================
  2832. // Global Globals/Functions/Constants
  2833. //========================================
  2834.  
  2835. const int CUSTOM_LENS_HINTS_MAX_LAYERS = 0; //Maximum layers to check screens for lens hints
  2836.  
  2837. //Global script example.
  2838.  
  2839. //Main custom lens hint drawing function. Put this into main loop of "Action" global script.
  2840. void DrawCustomLensHints(){
  2841. if (Link->MP<=0) return;
  2842. if (!UsingItem(I_LENS))return;
  2843. //Add lens hints here.
  2844. DrawCustomLensHint(0, 120, 1028, 8, 1);//Draw combo#1028 with cset 8 on all combos of type 120 (damage 8 hearts)
  2845. DrawCustomLensHint(1, 98, 1029, 7, 1);//Draw combo#1029 with cset 7 on all combos with inherent or placed flag 98 (Script 1)
  2846. DrawCustomLensHint(2, 55, 1030, 6, 1);//Draw combo#1030 with cset 6 on all NPC`s with ID#55 (Arrow Pols Voices)
  2847. //Add more lens hints here.
  2848.  
  2849. }
  2850.  
  2851. //Lenstype: 0-combo type, 1-combo flag, 2 - NPC.
  2852. //miscvalue1: depends on lenstype:
  2853. // 0 - combo type ID
  2854. // 1 - combo flag ID
  2855. // 2 - NPC ID
  2856. //cmb - combo to draw, cset - cset to use for hint drawing
  2857. //minlevel - minimum item level for Lens-like item needed to be used to reveal this hint.
  2858. void DrawCustomLensHint(int lenstype, int miscvalue1, int cmb, int cset, int minlevel){
  2859. int lens = GetCurrentItem(IC_LENS);
  2860. itemdata it = Game->LoadItemData(lens);
  2861. if (it->Level<minlevel) return;
  2862. if (lenstype==0){//combo types
  2863. for (int l=0; l<=CUSTOM_LENS_HINTS_MAX_LAYERS; l++){
  2864. if (l==0){
  2865. for (int c=0;c<176;c++){
  2866. if (Screen->ComboT[c]==miscvalue1) Screen->FastCombo(0, ComboX(c), ComboY(c), cmb, cset, OP_OPAQUE);
  2867. }
  2868. if ((Screen->LayerMap(l)==-1)||(Screen->LayerScreen(l)==-1))continue;
  2869. for (int c=0;c<176;c++){
  2870. int lc = GetLayerComboT(l, c);
  2871. if (Screen->ComboT[lc]==miscvalue1) Screen->FastCombo(l, ComboX(lc), ComboY(lc), cmb, cset, OP_OPAQUE);
  2872. }
  2873. }
  2874. }
  2875. return;
  2876. }
  2877. else if (lenstype==1){//combo flags
  2878. for (int l=0; l<=CUSTOM_LENS_HINTS_MAX_LAYERS; l++){
  2879. if (l==0){
  2880. for (int c=0;c<176;c++){
  2881. if (ComboFI(c, miscvalue1)) Screen->FastCombo(0, ComboX(c), ComboY(c), cmb, cset, OP_OPAQUE);
  2882. }
  2883. if ((Screen->LayerMap(l)==-1)||(Screen->LayerScreen(l)==-1))continue;
  2884. for (int c=0;c<176;c++){
  2885. int lc = GetLayerComboT(l, c);
  2886. if (ComboFI(lc, miscvalue1)) Screen->FastCombo(l, ComboX(lc), ComboY(lc), cmb, cset, OP_OPAQUE);
  2887. }
  2888. }
  2889. }
  2890. return;
  2891. }
  2892. else if (lenstype==2){//enemies
  2893. for (int i=1; i<= Screen->NumNPCs(); i++ ){
  2894. npc lensie= Screen->LoadNPC(i);
  2895. if (lensie->ID==miscvalue1) Screen->FastCombo(6, lensie->X, lensie->Y-lensie->Z, cmb, cset, OP_OPAQUE);
  2896. }
  2897. }
  2898. }
  2899.  
  2900. //Draws Lens hints on FFC`s if FFC runs given script and has specific value set in checked Init D variable.
  2901. void DrawFFCLensHint(int scr, int dreg, int dvalue, int cmb, int cset, int minlevel){
  2902. int lens = GetCurrentItem(IC_LENS);
  2903. itemdata it = Game->LoadItemData(lens);
  2904. if (it->Level<minlevel) return;
  2905. for (int i=1;i<=32;i++){
  2906. ffc lensie = Screen->LoadFFC(i);
  2907. if (lensie->Script!=scr) continue;
  2908. if (lensie->InitD[dreg]!=dvalue) continue;
  2909. Screen->FastCombo(0, CenterX(lensie), CenterY(lensie), cmb, cset, OP_OPAQUE);
  2910. }
  2911. }
  2912.  
  2913. //FFC version of custom lens hints.
  2914. //D0 - Lenstype: 0-combo type, 1-combo flag, 2 - NPC.
  2915. //D1: depends on lenstype:
  2916. // 0 - combo type ID
  2917. // 1 - combo flag ID
  2918. // 2 - NPC ID
  2919. //D2 - combo to draw,
  2920. //D3 - cset to use for hint drawing
  2921. //D4 - minimum item level for Lens-like item needed to be used to reveal this hint.
  2922. ffc script CustomLensHints{
  2923. void run (int lenstype, int miscvalue1, int cmb, int cset, int minlevel){
  2924. while (true){
  2925. DrawCustomLensHint(lenstype, miscvalue1, cmb, cset, minlevel);
  2926. Waitframe();
  2927. }
  2928. }
  2929. }
  2930. //========================================
  2931. // Global Globals/Functions/Constants
  2932. //========================================
  2933.  
  2934. //Better Stone of Agony
  2935. const int BetterAgony_ID = 123; //item ID
  2936. const int BetterAgony_DetectionRadius = 32; //the secret detection radius in pixels
  2937. const int BetterAgony_DetectionFlag = 98; //script flag number to use for secret detection
  2938. const int BetterAgony_Vibrate = 1; //wether or not it makes link vibrate. 0 = no, 1 = yes
  2939. const int BetterAgony_SFX = 61; //sound effect to play. leave as 0 if unneeded
  2940. const int BetterAgony_SFXRepeatRate = 30; //how fast to repeat the sound effect, in frames
  2941. const int BetterAgony_ComboID = 8; //combo to draw above links head as an indicator. leave as 0 if unneeded.
  2942. const int BetterAgony_ComboCSet = 7; //cset to use for the combo
  2943.  
  2944.  
  2945. //D0: How to detect secrets
  2946. //0 = Detect trigger flags
  2947. //1 = Detect the script flag
  2948. //2 = Detect both trigger flags and the script flag
  2949. //D1: Condition for detecting secrets
  2950. //0 = Always detect
  2951. //1 = Don't detect if permanent secrets are activated
  2952. ffc script BetterStoneOfAgony{
  2953. void run(int type, int condition){
  2954. bool SecretDetected;
  2955. bool OtherFrame;
  2956. int LinkVibration;
  2957. bool LinkOffset;
  2958. int SFXRepeat;
  2959. while(true){
  2960. while( !Link->Item[BetterAgony_ID] || (condition == 1 && Screen->State[ST_SECRET]) ) { //halt the script
  2961. LinkVibration = 0;
  2962. if ( LinkOffset )
  2963. Link->DrawYOffset ++; //revert drawoffset
  2964. LinkOffset = false;
  2965. SFXRepeat = 0;
  2966. Waitframe();
  2967. }
  2968. if ( OtherFrame ) { //only check every other frame to prevent slowdown
  2969. SecretDetected = false;
  2970. for(int i = 0; i <= 6; i++) { //for all layers
  2971. if ( i == 0 || Screen->LayerMap(i) != -1 ) { //dont check unvalid layers
  2972. for(int j = 0; j <= 175; j++) { //all combos
  2973. if ( Distance(Link->X, Link->Y, ComboX(j), ComboY(j)) <= BetterAgony_DetectionRadius ) //check distance
  2974. if ( (IsATriggerFlag(GetLayerComboF(i, j)) && type != 1)
  2975. || (GetLayerComboF(i, j) == BetterAgony_DetectionFlag && type != 0) ) //check flag
  2976. SecretDetected = true;
  2977. }
  2978. }
  2979. }
  2980. }
  2981. if ( OtherFrame )
  2982. OtherFrame = false;
  2983. else
  2984. OtherFrame = true;
  2985. if ( SecretDetected ) {
  2986. if ( BetterAgony_Vibrate == 1 ) { //link vibrates using drawoffset
  2987. if ( LinkVibration == 0 ) {
  2988. Link->DrawYOffset --;
  2989. LinkOffset = true;
  2990. }
  2991. if ( LinkVibration == 3 ) {
  2992. Link->DrawYOffset ++;
  2993. LinkOffset = false;
  2994. }
  2995. LinkVibration ++;
  2996. if ( LinkVibration > 5 )
  2997. LinkVibration = 0;
  2998. }
  2999. if ( BetterAgony_SFX != 0 ) { //repeatedly played sfx
  3000. if ( SFXRepeat == 0 )
  3001. Game->PlaySound(BetterAgony_SFX);
  3002. SFXRepeat ++;
  3003. if ( SFXRepeat > BetterAgony_SFXRepeatRate )
  3004. SFXRepeat = 0;
  3005. }
  3006. if ( BetterAgony_ComboID != 0 ) //indicator combo drawn on layer 7 above link
  3007. Screen->FastCombo(7, Link->X, Link->Y-16, BetterAgony_ComboID, BetterAgony_ComboCSet, OP_OPAQUE);
  3008. }
  3009. else { //secrets not detected
  3010. LinkVibration = 0;
  3011. if ( LinkOffset )
  3012. Link->DrawYOffset ++; //revert drawoffset
  3013. LinkOffset = false;
  3014. SFXRepeat = 0;
  3015. }
  3016. Waitframe();
  3017. }
  3018. }
  3019. }
  3020.  
  3021. bool IsATriggerFlag(int f) {
  3022. if ( (f >= 3 && f <= 6) || f == 11 || (f >= 68 && f <= 90) ) //trigger flags
  3023. return true;
  3024. else
  3025. return false;
  3026. }
  3027. global script Main2{
  3028. void run(){
  3029. //=================
  3030. // Global Init
  3031. //=================
  3032.  
  3033.  
  3034. // Initialize variables used to listen on screen changes
  3035. int curscreen = -1;
  3036.  
  3037.  
  3038. //=================
  3039. // Global Init
  3040. //=================
  3041.  
  3042. MooshPit_Init();
  3043.  
  3044. //Setup variables for ice combos.
  3045. Setup_IceCombos();
  3046.  
  3047. //Variable that stores Game->GetCurScreen() the previous frame.
  3048. int oldscreen = Game->GetCurScreen();
  3049.  
  3050. //Main Loop
  3051. //=================
  3052. // Global Init
  3053. //=================
  3054.  
  3055. ScrollingDraws_Init();
  3056. Minecart_Init();
  3057. //=================
  3058. // Global Init
  3059. //=================
  3060.  
  3061. ScrollingDraws_Init();
  3062. StartGhostZH();
  3063.  
  3064.  
  3065. //=================
  3066. // Global Init
  3067. //=================
  3068.  
  3069. int BetterAgony_LastDMap = Game->GetCurDMap();
  3070. int BetterAgony_LastScreen = Game->GetCurDMapScreen();
  3071. while(true){
  3072.  
  3073. //=====================
  3074. // Global Update 1
  3075. //=====================
  3076.  
  3077. // Keep track of screen changes
  3078. // Run a Barrier script on every screen change
  3079. if (Game->GetCurScreen() != curscreen) {
  3080. curscreen = Game->GetCurScreen();
  3081. Barriers_NewScreen();}
  3082. RefreshBottles();
  3083. while(true){
  3084. EmptyBottleGlobal();
  3085. //=====================
  3086. // Global Update 2
  3087. //=====================
  3088.  
  3089. NesMovementFix();
  3090. //=====================
  3091. // Global Update 1
  3092. //=====================
  3093.  
  3094. MooshPit_Update();
  3095. //=====================
  3096. // Global Update 1
  3097. //=====================
  3098.  
  3099.  
  3100. //Call Dungeonmap functions
  3101. if(Game->GetCurDMap()==1){ //Put the dmap-number of your dungeon here
  3102. if(!Link->Item[185]){ //Put the number of the fake-item here
  3103. Link->InputMap = false;
  3104. }
  3105. }
  3106.  
  3107.  
  3108.  
  3109.  
  3110. //=====================
  3111. // Global Update 1
  3112. //=====================
  3113.  
  3114.  
  3115. ScrollFix(); // keep at top of while loop
  3116.  
  3117. PegasusBoots(); // before waitdraw
  3118.  
  3119.  
  3120.  
  3121. //=====================
  3122. // Global Update 1
  3123. //=====================
  3124.  
  3125. ScrollingDraws_Update();
  3126. //=====================
  3127. // Global Update 1
  3128. //=====================
  3129.  
  3130. ScrollingDraws_Update();
  3131. UpdateGhostZH1();
  3132. //=====================
  3133. // Global Update 1
  3134. //=====================
  3135.  
  3136. BetterByrna();
  3137.  
  3138. //=====================
  3139. // Global Update 1
  3140. //=====================
  3141.  
  3142. if ( Game->GetCurDMap() != BetterAgony_LastDMap || Game->GetCurDMapScreen() != BetterAgony_LastScreen )
  3143. Link->DrawYOffset = 0; //fix better stone of agony link draw offset
  3144. BetterAgony_LastDMap = Game->GetCurDMap();
  3145. BetterAgony_LastScreen = Game->GetCurDMapScreen();
  3146. Waitdraw();
  3147.  
  3148.  
  3149.  
  3150. Update_IceCombos(oldscreen);
  3151. oldscreen = Game->GetCurScreen();
  3152. //=====================
  3153. // Global Update 2
  3154. //=====================
  3155.  
  3156. Minecart_Update();
  3157. UpdateGhostZH2();
  3158.  
  3159. //=====================
  3160. // Global Update 2
  3161. //=====================
  3162.  
  3163. DrawCustomLensHints();
  3164.  
  3165. Waitframe();
  3166. ScreenChange_Update();
  3167. Pot_Script();
  3168. }
  3169. }
  3170. }
  3171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement