Advertisement
ZoriaRPG

ZScript: Z3 Style Magic Mirror (v0.2.5, Tested, Working)

Nov 22nd, 2016
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.63 KB | None | 0 0
  1. ///////////////////////
  2. /// Z3 Magic Mirror ///
  3. /// v0.2.5          ///
  4. /// 22-Nov-2016     ///
  5. /// By: ZoriaRPG    ///
  6. ///////////////////////////////////////
  7. /// Partial Rewrite of the Original ///
  8. /// WarpFunctions.zh b1.1 from 2014 ///
  9. /// originally made by request for  ///
  10. /// Obderhode and used in the quest ///
  11. /// 'The Three Whistles'            ///
  12. ///////////////////////////////////////
  13.  
  14. //! To-Do
  15. //! Add in freeze flags and ghost suspension
  16.  
  17. /// Global Array
  18. int Mirror[214747];
  19.  
  20. const int TEST_MIRROR_SPARKLE = 0;
  21. const int MIRROR_SPARKLE_BEFORE_WAITDRAW = 0;
  22.  
  23. //Moon Pearl Goodies
  24. const int I_MIRROR = 160;
  25. const int I_MOONPEARL = 200;
  26. const int I_BUNNYRING = 201; //A wisp ring twith a LTM for Bunny Sprites
  27.  
  28. //Options
  29. const int WARP_RETURNS_ON_INJURY        = 1;
  30. const int REQUIRE_MOON_PEARL            = 1;
  31. const int MIRROR_RETURNS_TO_DUNGEON_ENTRANCE    = 1; //This requires placing a warp return square on dungeon entrance screens.
  32.  
  33. const int MIRROR_POST_WARP_TIMER_NUM_FRAMES = 75; // Number of frames afer warping, before Link may use a warp return sparkle.
  34.  
  35. const int POST_WARP_LINK_IS_INVINCIBLE      = 0;     //If se tto '1', Link->CollDetection will be disabled for a number of
  36.                         //frames equal to:
  37.  
  38. const int WARP_INVULNERABILITY_FRAMES       = 90; //Number of frames that Link is invulnerable after warping.
  39.  
  40. //!! Caution: This may conflict with other items that grant invulnerability!
  41.  
  42.  
  43. ///Constants for Array Indices of Mirror[]
  44.  
  45. const int IS_WARPING        = 0;
  46. const int AFTER_WARP        = 1;
  47. const int RETURN_WARP       = 2;
  48. const int AFTER_RETURN_WARP     = 3;
  49.  
  50. const int WARP_SPARKLE          = 10;
  51. const int WARP_SPARKLE_DMAP         = 11;
  52. const int WARP_SPARKLE_SCREEN       = 12;
  53. const int WARP_SPARKLE_X        = 13;
  54. const int WARP_SPARKLE_Y        = 14;
  55. const int WARP_SPARKLE_RETURN_DMAP  = 15;
  56.  
  57. const int WARP_LINK_X           = 20;
  58. const int WARP_LINK_Y           = 21;
  59. const int WARP_LINK_Z           = 22;
  60. const int WARP_LINK_HP          = 23;
  61. const int WARP_LINK_TEMP_INVULNERABILITY = 24;
  62.  
  63. const int MIRROR_SPARKLE_COMBO_FRAME = 30; //Mirror array index
  64. const int MIRROR_POST_WARP_TIMER = 40;
  65.  
  66.  
  67.  
  68. //Settings
  69.  
  70. //Sounds
  71. const int SFX_WARP_ERROR    = 67;
  72. const int SFX_WARP      = 73;
  73. const int SFX_WARP_DUNGEON  = 16;
  74.  
  75. const int WARP_WAVE_DUR     = 100; //Duration of warp wavy animation (overworld)
  76. const int WARP_WAVE_DUR_DUNGEON = 100; //Duration of warp wavy animation (inside dungeons)
  77.  
  78. const int WARP_DUR      = 60;
  79. const int POST_WARP_DELAY   = 15;
  80.  
  81.  
  82.  
  83. //Mirror Sparkle Settings
  84. const int MIRROR_SPARKLE_COMBO      = 32596; // COmbo of sparkle or other warp return effect.
  85. const int MIRROR_SPARKLE_COMBO_LAYER    = 2;
  86. const int MIRROR_SPARKLE_COMBO_W    = 1;
  87. const int MIRROR_SPARKLE_COMBO_H    = 1;
  88. const int MIRROR_SPARKLE_COMBO_CSET     = 0;
  89. const int MIRROR_SPARKLE_COMBO_XSCALE   = -1;
  90. const int MIRROR_SPARKLE_COMBO_YSCALE   = -1;
  91. const int MIRROR_SPARKLE_COMBO_RX   = 0;
  92. const int MIRROR_SPARKLE_COMBO_RY   = 0;
  93. const int MIRROR_SPARKLE_COMBO_RANGLE   = 0;
  94.  
  95. const int MIRROR_SPARKLE_COMBO_FLIP     = 0;
  96. const int MIRROR_SPARKLE_COMBO_OPACITY  = 64;
  97.  
  98. const int MIRROR_SPARKLE_COMBO_NUM_FRAMES = 4;
  99. const int MIRROR_SPARKLE_COMBO_INIT_FRAME = 1;
  100.  
  101.  
  102.  
  103.  
  104. //Accessors
  105. int IsWarping(){ return Mirror[IS_WARPING]; }
  106. void IsWarping(bool state){ if ( state ) Mirror[IS_WARPING] = 1; else Mirror[IS_WARPING] = 0; }
  107.  
  108. int AfterWarp(){ return Mirror[AFTER_WARP]; }
  109. void AfterWarp(bool state){ if ( state ) Mirror[AFTER_WARP] = 1; else Mirror[AFTER_WARP] = 0; }
  110.  
  111. int IsReturnWarping(){ return Mirror[RETURN_WARP]; }
  112. void IsReturnWarping(bool state){ if ( state ) Mirror[RETURN_WARP] = 1; else Mirror[RETURN_WARP] = 0; }
  113.  
  114. int AfterReturnWarp(){ return Mirror[AFTER_RETURN_WARP]; }
  115. void AfterReturnWarp(bool state){ if ( state ) Mirror[AFTER_RETURN_WARP] = 1; else Mirror[AFTER_RETURN_WARP] = 0; }
  116.  
  117. int WarpSparkle(){ return Mirror[WARP_SPARKLE]; }
  118. void WarpSparkle(bool state){ if ( state ) Mirror[WARP_SPARKLE] = 1; else Mirror[WARP_SPARKLE] = 0; }
  119.  
  120. int WarpSparkleReturn(){ return Mirror[WARP_SPARKLE_RETURN_DMAP]; }
  121. void WarpSparkleReturn(int dmap){ Mirror[WARP_SPARKLE_RETURN_DMAP] = dmap; }
  122.  
  123. int WarpSparkleDMap(){ return Mirror[WARP_SPARKLE_DMAP]; }
  124. void WarpSparkleDMap(int dmap){ Mirror[WARP_SPARKLE_DMAP] = dmap; }
  125.  
  126. int WarpSparkleX(){ return Mirror[WARP_SPARKLE_X]; }
  127. void WarpSparkleX(int x){ Mirror[WARP_SPARKLE_X] = x; }
  128.  
  129. int WarpSparkleY(){ return Mirror[WARP_SPARKLE_Y]; }
  130. void WarpSparkleY(int y){ Mirror[WARP_SPARKLE_Y] = y; }
  131.  
  132. int WarpSparkleScreen(){ return Mirror[WARP_SPARKLE_SCREEN]; }
  133. void WarpSparkleScreen(int screen){ Mirror[WARP_SPARKLE_SCREEN] = screen; }
  134.  
  135. //The following four functions are used to manipulate,a nd check the post-warp timer,
  136. //that prevents Link from being sent back by a sparkle as soon as he finishes warping.
  137.  
  138. int WarpReturnWait(){ return Mirror[MIRROR_POST_WARP_TIMER]; }
  139. void ReducePostWarpTimer(){ if ( Mirror[MIRROR_POST_WARP_TIMER] > 0 ) Mirror[MIRROR_POST_WARP_TIMER]--; }
  140. void SetPostWarpTimer(){ Mirror[MIRROR_POST_WARP_TIMER] = MIRROR_POST_WARP_TIMER_NUM_FRAMES; }
  141. void ClearPostWarpTimer(){ Mirror[MIRROR_POST_WARP_TIMER] = 0; }
  142.  
  143.  
  144. //Functions
  145.  
  146. //Checks the present DMap and returns irts counterpart.
  147. //!! You must set up the arrays inside this function, for it to work.
  148. int GetOtherworldlyDMap(int dmap){
  149.     int q[4];
  150.     int LightWorldDMaps[]={3,-1,-1,-1,-1}; //Populate these two arrays with the IDs of your light and dark world dmaps
  151.     int DarkWorldDMaps[]={8,-1,-1,-1,-1}; //in matched pairs.
  152.     for ( q[0] = 0; q[0] < SizeOfArray(LightWorldDMaps); q[0]++ ) {
  153.         q[1] = LightWorldDMaps[ q[0] ];
  154.         q[2] = DarkWorldDMaps[ q[0] ];
  155.         if ( dmap == q[1] ) return DarkWorldDMaps[ q[0] ];
  156.         if ( dmap == q[2] ) return LightWorldDMaps[ q[0] ];
  157.     }
  158.     return -1;
  159. }
  160.  
  161. //Returns if the present dmap is a dark world dmap
  162. //!! You must set up the arrays inside this function, for it to work.
  163. bool IsDarkWorld(){
  164.     int DarkWorldDMaps[]={8,-1,-1,-1,-1};
  165.     for ( int q = 0; q < SizeOfArray(DarkWorldDMaps); q++ ) {
  166.         if ( Game->GetCurDMap() == DarkWorldDMaps[q] ) return true;
  167.     }
  168.     return false;
  169. }
  170.  
  171. //Generates coordinates for the warp return sparkle.
  172. //this is set when we use the mirror.
  173. void SetWarpReturn(){
  174.     WarpSparkle(true);
  175.     WarpSparkleX(Link->X);
  176.     WarpSparkleY(Link->Y);
  177.     WarpSparkleDMap( GetOtherworldlyDMap( Game->GetCurDMap() ) );
  178.     WarpSparkleScreen(Game->GetCurScreen());
  179.     WarpSparkleReturn(Game->GetCurDMap());
  180. }
  181.  
  182. //Removes the warp sparkle, after using it.
  183. void ClearWarpSparkle(){
  184.     WarpSparkle(false);
  185.     WarpSparkleX(-100);
  186.     WarpSparkleY(-100);
  187.     WarpSparkleDMap(-1);
  188.     WarpSparkleScreen(-1);
  189.     WarpSparkleReturn(-1);
  190. }
  191.  
  192. //Returns if Link is in a dungeon based on the array dungeonDMaps[]
  193. //!! You must set up the array inside this function, for it to work.
  194. bool IsDungeonDMap(){
  195.     int dungeonDMaps[]={20,21,22};//List all dungeon DMaps here
  196.     for ( int q = 0; q < SizeOfArray(dungeonDMaps); q++ ) {
  197.         if ( Game->GetCurDMap() == dungeonDMaps[q] ) return true;
  198.         return false;
  199.     }
  200. }
  201.  
  202. //Returns if the warp destination is solid, prior to warping.
  203. bool WarpDestSolid(int x, int y, int screen, int map){
  204.     return ( Game->GetComboSolid(map, screen, ComboAt(x,y)) );
  205. }
  206.    
  207. //! Main Functions to Call before Waitdraw()
  208.  
  209. //Handles the initial warp routines.
  210. void MirrorWarpLink() {
  211.     if ( IsWarping() ){
  212.         SetPostWarpTimer();
  213.         NoAction();
  214.         Game->PlaySound(SFX_WARP);
  215.         Screen->Wavy = WARP_WAVE_DUR;
  216.         //Freeze all enemies and ghost scripts
  217.         for(int q = WARP_WAVE_DUR + POST_WARP_DELAY; q > 0; q--){
  218.             NoAction();
  219.             Waitframe();
  220.         }
  221.         //resume npcs and ghost scripts
  222.         Link->PitWarp(GetOtherworldlyDMap(Game->GetCurDMap()), Game->GetCurScreen());
  223.         IsWarping(false);
  224.         AfterWarp(true);
  225.     }
  226.    
  227.     if (IsReturnWarping() ){
  228.         Mirror[WARP_LINK_HP] = Link->HP;
  229.         Link->X = WarpSparkleX();
  230.         Link->Y = WarpSparkleY();
  231.         NoAction();
  232.         Game->PlaySound(SFX_WARP);
  233.         Screen->Wavy = WARP_WAVE_DUR;
  234.         //Freeze all enemies and ghost scripts
  235.         for(int q = WARP_WAVE_DUR + POST_WARP_DELAY; q > 0; q--){
  236.             NoAction();
  237.             Waitframe();
  238.         }
  239.         //resume npcs and ghost scripts
  240.         Link->PitWarp(WarpSparkleReturn(), WarpSparkleScreen());
  241.         IsReturnWarping(false);
  242.         AfterReturnWarp(true);
  243.     }
  244. }
  245.  
  246. //Post-warp cleanup, and bounce.
  247. void WarpFinish() {
  248.     if (AfterWarp()){
  249.         if ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) Link->HitDir = -1;
  250.         //SetWarpReturn();
  251.         //If the destination is solid, send Link back.
  252.         if ( Screen->ComboS[ ComboAt(Link->X, Link->Y) ] ) {
  253.             Game->PlaySound(SFX_WARP);
  254.             Screen->Wavy = WARP_WAVE_DUR;
  255.             //freeze all enemies and ghost scripts.
  256.             for (int q = WARP_WAVE_DUR + POST_WARP_DELAY; q > 0; q--){
  257.                 NoAction();
  258.                 Waitframe();
  259.             }
  260.             //resume npcs and ghost scripts
  261.             Link->X = Mirror[WARP_LINK_X];
  262.             Link->Y = Mirror[WARP_LINK_Y];
  263.             Link->PitWarp(WarpSparkleReturn(), Game->GetCurScreen());
  264.            
  265.             AfterWarp(false);
  266.         }
  267.         if ( Link->HP < Mirror[WARP_LINK_HP] && WARP_RETURNS_ON_INJURY) { //If Link is injured, send him back.
  268.             Link->HP = Mirror[WARP_LINK_HP];
  269.             Game->PlaySound(SFX_WARP);
  270.             Screen->Wavy = WARP_WAVE_DUR;
  271.             //freeze all enemies and ghost scripts.
  272.             for(int q = WARP_WAVE_DUR + POST_WARP_DELAY; q > 0; q--){
  273.                 NoAction();
  274.                 Waitframe();
  275.             }
  276.             //resume npcs and ghost scripts
  277.             Link->X = Mirror[WARP_LINK_X];
  278.             Link->Y = Mirror[WARP_LINK_Y];
  279.             Link->PitWarp(WarpSparkleReturn(), Game->GetCurScreen());
  280.  
  281.             Link->X = Mirror[WARP_LINK_X];
  282.             Link->Y = Mirror[WARP_LINK_Y];
  283.             Link->HP = Mirror[WARP_LINK_HP];
  284.            
  285.             AfterWarp(false);
  286.         }
  287.         else {
  288.             Link->X = Mirror[WARP_LINK_X];
  289.             Link->Y = Mirror[WARP_LINK_Y];
  290.             SetPostWarpTimer();
  291.             Mirror[WARP_INVULNERABILITY_FRAMES] = WARP_INVULNERABILITY_FRAMES;
  292.             AfterWarp(false);
  293.         }
  294.     }
  295.    
  296.     if (AfterReturnWarp()){
  297.         if ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) Link->HitDir = -1;
  298.         ClearWarpSparkle();
  299.         Mirror[WARP_INVULNERABILITY_FRAMES] = WARP_INVULNERABILITY_FRAMES;
  300.         AfterReturnWarp(false);
  301.         //ClearPostWarpTimer();
  302.            
  303.     }
  304.    
  305.     if ( POST_WARP_LINK_IS_INVINCIBLE ) {
  306.         if ( Mirror[WARP_INVULNERABILITY_FRAMES] ) {
  307.             //If we find a way to Flicker Link, it goes here.
  308.             Link->CollDetection = false;
  309.             Mirror[WARP_INVULNERABILITY_FRAMES]--;
  310.         }
  311.         if ( !Mirror[WARP_INVULNERABILITY_FRAMES] ) Link->CollDetection = true;
  312.     }
  313. }
  314.  
  315.  
  316. //Creates the mirror return sparkle.
  317. void MirrorSparkle(){
  318.     if ( Game->GetCurDMap() == WarpSparkleDMap() && Game->GetCurScreen() == WarpSparkleScreen() ) {
  319.         Screen->DrawCombo(  MIRROR_SPARKLE_COMBO_LAYER, WarpSparkleX(), WarpSparkleY(),
  320.             MIRROR_SPARKLE_COMBO, MIRROR_SPARKLE_COMBO_H, MIRROR_SPARKLE_COMBO_W, MIRROR_SPARKLE_COMBO_CSET,
  321.             MIRROR_SPARKLE_COMBO_XSCALE, MIRROR_SPARKLE_COMBO_YSCALE, MIRROR_SPARKLE_COMBO_RX,
  322.             MIRROR_SPARKLE_COMBO_RY, MIRROR_SPARKLE_COMBO_RANGLE, Mirror[MIRROR_SPARKLE_COMBO_FRAME],
  323.             MIRROR_SPARKLE_COMBO_FLIP, true, MIRROR_SPARKLE_COMBO_OPACITY) ; //Mirror sparkle
  324.        
  325.         //Reduce the frames
  326.         if ( Mirror[MIRROR_SPARKLE_COMBO_FRAME] >= MIRROR_SPARKLE_COMBO_NUM_FRAMES ) Mirror[MIRROR_SPARKLE_COMBO_FRAME] = MIRROR_SPARKLE_COMBO_INIT_FRAME;
  327.         else Mirror[MIRROR_SPARKLE_COMBO_FRAME]++;
  328.            
  329.         if ( !WarpReturnWait() && !Mirror[WARP_INVULNERABILITY_FRAMES] && RectCollision( Mirror[WARP_SPARKLE_X], Mirror[WARP_SPARKLE_Y], Mirror[WARP_SPARKLE_X]+16, Mirror[WARP_SPARKLE_Y]+16, Link->X+Link->HitXOffset+Link->DrawXOffset, Link->Y+Link->HitYOffset+Link->DrawYOffset, Link->X+Link->HitXOffset+Link->DrawXOffset+Link->HitWidth, Link->Y+Link->HitYOffset+Link->DrawYOffset+Link->HitHeight)
  330.             || Distance(CenterLinkX(), CenterLinkY(), Mirror[WARP_SPARKLE_X]+8, Mirror[WARP_SPARKLE_Y]+8) < 8)
  331.         {
  332.             //Reurn Link via the portal
  333.             IsReturnWarping(true);
  334.         }
  335.     }
  336. }
  337.  
  338. void TestSparkle(){
  339.     int x = WarpSparkleX();
  340.     int y = WarpSparkleY();
  341.     if ( x < 0 ) x = 0;
  342.     if ( y < 0 ) y = 0;
  343.     Screen->DrawCombo(  MIRROR_SPARKLE_COMBO_LAYER, x, y,
  344.             MIRROR_SPARKLE_COMBO, MIRROR_SPARKLE_COMBO_H, MIRROR_SPARKLE_COMBO_W, MIRROR_SPARKLE_COMBO_CSET,
  345.             MIRROR_SPARKLE_COMBO_XSCALE, MIRROR_SPARKLE_COMBO_YSCALE, MIRROR_SPARKLE_COMBO_RX,
  346.             MIRROR_SPARKLE_COMBO_RY, MIRROR_SPARKLE_COMBO_RANGLE, Mirror[MIRROR_SPARKLE_COMBO_FRAME],
  347.             MIRROR_SPARKLE_COMBO_FLIP, true, MIRROR_SPARKLE_COMBO_OPACITY) ; //Mirror sparkle
  348.        
  349.         //Reduce the frames
  350.         if ( Mirror[MIRROR_SPARKLE_COMBO_FRAME] >= MIRROR_SPARKLE_COMBO_NUM_FRAMES ) Mirror[MIRROR_SPARKLE_COMBO_FRAME] = MIRROR_SPARKLE_COMBO_INIT_FRAME;
  351.         else Mirror[MIRROR_SPARKLE_COMBO_FRAME]++;
  352. }
  353.  
  354.  
  355. //Runs the moon pearl bunny sprite change, and halts using any item other than the mirror.
  356. void MoonPearl(){
  357.     if ( IsDarkWorld() && !Link->Item[I_MOONPEARL] && !Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = true;
  358.     if ( !IsDarkWorld() && Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = false;
  359.     if ( IsDarkWorld() && Link->Item[I_MOONPEARL] && Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = false;
  360.     if ( Link->Item[I_BUNNYRING] ) {
  361.         if ( Link->PressA && GetEquipmentA() != I_MIRROR ) Link->PressA = false;
  362.         if ( Link->PressB && GetEquipmentB() != I_MIRROR ) Link->PressB = false;
  363.     }
  364. }
  365.  
  366. /// Items
  367.  
  368. item script Mirror{
  369.     void run(){
  370.         if ( IsDungeonDMap() && MIRROR_RETURNS_TO_DUNGEON_ENTRANCE ) {
  371.             //Warp to dungeon entrance.
  372.             Game->PlaySound(SFX_WARP_DUNGEON);
  373.             Screen->Wavy = WARP_WAVE_DUR_DUNGEON;
  374.             Link->Warp(Game->GetCurDMap(), Game->DMapContinue[Game->GetCurDMap()]);
  375.         }
  376.         else {
  377.             if ( IsDarkWorld() ) {
  378.                 //SetPostWarpTimer();
  379.                 SetWarpReturn();
  380.                 IsWarping(true);
  381.             }
  382.             //Warp to other world
  383.             if ( !IsDarkWorld() && SFX_WARP_ERROR ) Game->PlaySound(SFX_WARP_ERROR);
  384.         }
  385.     }
  386. }
  387.  
  388. //Global Script Example
  389.  
  390. global script Z3_Mirror{
  391.     void run(){
  392.         while(true){
  393.             if ( REQUIRE_MOON_PEARL ) MoonPearl();
  394.             ReducePostWarpTimer();
  395.             MirrorWarpLink();
  396.  
  397.             //if ( TEST_MIRROR_SPARKLE ) TestSparkle();
  398.             //if ( MIRROR_SPARKLE_BEFORE_WAITDRAW ) MirrorSparkle();
  399.             Waitdraw();
  400.             WarpFinish();
  401.             //if ( !MIRROR_SPARKLE_BEFORE_WAITDRAW ) MirrorSparkle();
  402.             if ( WarpSparkle() ) MirrorSparkle(); //Call only if it exists.
  403.             Waitframe();
  404.         }
  405.     }
  406. }
  407.  
  408. //Deprecated
  409.  
  410. //bool TouchingSolid(int x, int y) {
  411.   //  if ( Screen->isSolid(x,y) ||
  412.   //  Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y) ||
  413.   //  Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y+SOLIDITY_CHECK_DISTANCE) ||
  414.   //  Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y-SOLIDITY_CHECK_DISTANCE) ||
  415.   //  Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y) ||
  416.   //  Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y+SOLIDITY_CHECK_DISTANCE) ||
  417.   //  Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y-SOLIDITY_CHECK_DISTANCE) ) {
  418.   //      return true;
  419.   //  }
  420.   //  else {
  421.    //     return false;
  422.   //  }
  423. //}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement