Advertisement
ZoriaRPG

ZScript: Z3 Style Magic Mirror (v0.4.0) + Z3 Items

Nov 27th, 2016
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 37.39 KB | None | 0 0
  1. ///////////////////////
  2. /// Z3 Magic Mirror ///
  3. /// v0.4.0          ///
  4. /// 27-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.  //! BUG    If Link is warped onto an entrance/exit (cave walk down/u) warp tile, that tile will activate and he will
  18.  //!        seem to walk in and out of a place then error out and return.
  19.  
  20.  //v0.3x Changelog
  21.  //v0.3.3 Modified the solidity tests for a far more fine tuned check.
  22.  //v0.3.4 Added a check to error if the player tries to use the mirron when standing on a cave combo, to prevent
  23.  // warping onto an aligning cave combo in the light world.
  24.  //0.3.5 Trimmed the solidity check slightly.
  25.  
  26. /// Global Array
  27. int Mirror[214747];
  28.  
  29. const int TEST_MIRROR_SPARKLE = 0;
  30. const int MIRROR_SPARKLE_BEFORE_WAITDRAW = 0;
  31.  
  32. //Moon Pearl Goodies
  33. const int I_MIRROR = 160;
  34. const int I_MOONPEARL = 200;
  35. const int I_BUNNYRING = 201; //A wisp ring twith a LTM for Bunny Sprites
  36.  
  37. //Sound Effect Settings
  38.  
  39. const int MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC     = 0;
  40. const int MIRROR_DUNEON_SOUND_USES_ENHANCED_MUSIC   = 0;
  41.  
  42. //Durations
  43. const int MIRROR_WARP_FIRST_HALF_DUR        = 180;
  44. const int MIRROR_WARP_SECOND_HALF_DUR       = 180;
  45. const int MIRROR_DUNGEON_WARP_FIRST_HALF_DUR    = 180;  
  46. const int MIRROR_DUNGEON_WARP_SECOND_HALF_DUR   = 180;
  47. const int SFX_WARP_ERROR_DUR            = 80;
  48.  
  49. //Sound Effect IDs
  50. const int SFX_WARP_ERROR            = 67;
  51. const int SFX_MIRROR_WARP_START         = 73;
  52. const int SFX_MIRROR_WARP_FINISH        = 74;
  53. const int SFX_MIRROR_WARP_DUNGEON_START     = 75;
  54. const int SFX_MIRROR_WARP_DUNGEON_FINISH    = 76;
  55.  
  56. //ZStrings for the Enhanced Music filenames
  57. const int MUS_MIRROR_WARP_START         = 20;
  58. const int MUS_MIRROR_WARP_FINISH        = 21;
  59. const int MUS_MIRROR_WARP_DUNGEON_START     = 22;
  60. const int MUS_MIRROR_WARP_DUNGEON_FINISH    = 23;
  61.  
  62. //Enhanced Music Tracks
  63. const int MUS_MIRROR_WARP_START_TRACK       = 1;
  64. const int MUS_MIRROR_WARP_FINISH_TRACK      = 1;
  65. const int MUS_MIRROR_WARP_DUNGEON_START_TRACK   = 1;
  66. const int MUS_MIRROR_WARP_DUNGEON_FINISH_TRACK  = 1;
  67.  
  68.  
  69. //Options
  70. const int WARP_RETURNS_ON_INJURY        = 1;
  71. const int REQUIRE_MOON_PEARL            = 1;
  72. const int MIRROR_RETURNS_TO_DUNGEON_ENTRANCE    = 1; //This requires placing a warp return square on dungeon entrance screens.
  73.  
  74. const int MIRROR_POST_WARP_TIMER_NUM_FRAMES = 75; // Number of frames afer warping, before Link may use a warp return sparkle.
  75.  
  76. const int POST_WARP_LINK_IS_INVINCIBLE      = 0;     //If se tto '1', Link->CollDetection will be disabled for a number of
  77.                         //frames equal to:
  78.  
  79. const int WARP_INVULNERABILITY_FRAMES       = 90; //Number of frames that Link is invulnerable after warping.
  80.  
  81. //!! Caution: This may conflict with other items that grant invulnerability!
  82.  
  83. const int SF_FORBID_MIRROR = 0; //A script screen flag to forbid usin the mirror.
  84.  
  85. ///Constants for Array Indices of Mirror[]
  86.  
  87. const int IS_WARPING            = 0;
  88. const int AFTER_WARP            = 1;
  89. const int RETURN_WARP           = 2;
  90. const int AFTER_RETURN_WARP         = 3;
  91. const int DUNGEON_WARP          = 4;
  92.  
  93. const int WARP_SPARKLE          = 10;
  94. const int WARP_SPARKLE_DMAP         = 11;
  95. const int WARP_SPARKLE_SCREEN       = 12;
  96. const int WARP_SPARKLE_X        = 13;
  97. const int WARP_SPARKLE_Y        = 14;
  98. const int WARP_SPARKLE_RETURN_DMAP  = 15;
  99.  
  100. const int WARP_LINK_X           = 20;
  101. const int WARP_LINK_Y           = 21;
  102. const int WARP_LINK_Z           = 22;
  103. const int WARP_LINK_HP          = 23;
  104. const int WARP_LINK_TEMP_INVULNERABILITY = 24;
  105.  
  106. const int MIRROR_SPARKLE_COMBO_FRAME    = 30; //Mirror array index
  107. const int MIRROR_POST_WARP_TIMER    = 40;
  108.  
  109.  
  110.  
  111. //Animation Settings
  112.  
  113. const int WARP_WAVE_DUR     = 100; //Duration of warp wavy animation (overworld)
  114. const int WARP_WAVE_DUR_DUNGEON = 100; //Duration of warp wavy animation (inside dungeons)
  115.  
  116. const int WARP_DUR      = 60;
  117. const int POST_WARP_DELAY   = 15;
  118.  
  119.  
  120. //Mirror Sparkle Settings
  121. const int MIRROR_SPARKLE_COMBO      = 32596; // COmbo of sparkle or other warp return effect.
  122. const int MIRROR_SPARKLE_COMBO_LAYER    = 2;
  123. const int MIRROR_SPARKLE_COMBO_W    = 1;
  124. const int MIRROR_SPARKLE_COMBO_H    = 1;
  125. const int MIRROR_SPARKLE_COMBO_CSET     = 0;
  126. const int MIRROR_SPARKLE_COMBO_XSCALE   = -1;
  127. const int MIRROR_SPARKLE_COMBO_YSCALE   = -1;
  128. const int MIRROR_SPARKLE_COMBO_RX   = 0;
  129. const int MIRROR_SPARKLE_COMBO_RY   = 0;
  130. const int MIRROR_SPARKLE_COMBO_RANGLE   = 0;
  131.  
  132. const int MIRROR_SPARKLE_COMBO_FLIP     = 0;
  133. const int MIRROR_SPARKLE_COMBO_OPACITY  = 64;
  134.  
  135. const int MIRROR_SPARKLE_COMBO_NUM_FRAMES = 4;
  136. const int MIRROR_SPARKLE_COMBO_INIT_FRAME = 1;
  137.  
  138.  
  139.  
  140.  
  141. //Accessors
  142. int IsWarping(){ return Mirror[IS_WARPING]; }
  143. void IsWarping(bool state){ if ( state ) Mirror[IS_WARPING] = 1; else Mirror[IS_WARPING] = 0; }
  144.  
  145. int AfterWarp(){ return Mirror[AFTER_WARP]; }
  146. void AfterWarp(bool state){ if ( state ) Mirror[AFTER_WARP] = 1; else Mirror[AFTER_WARP] = 0; }
  147.  
  148. int IsReturnWarping(){ return Mirror[RETURN_WARP]; }
  149. void IsReturnWarping(bool state){ if ( state ) Mirror[RETURN_WARP] = 1; else Mirror[RETURN_WARP] = 0; }
  150.  
  151. int AfterReturnWarp(){ return Mirror[AFTER_RETURN_WARP]; }
  152. void AfterReturnWarp(bool state){ if ( state ) Mirror[AFTER_RETURN_WARP] = 1; else Mirror[AFTER_RETURN_WARP] = 0; }
  153.  
  154. void DungeonWarp(bool state) { if ( state ) Mirror[DUNGEON_WARP] = 1; else Mirror[DUNGEON_WARP] = 0; }
  155. int DungeonWarp() { return Mirror[DUNGEON_WARP]; }
  156.  
  157. int WarpSparkle(){ return Mirror[WARP_SPARKLE]; }
  158. void WarpSparkle(bool state){ if ( state ) Mirror[WARP_SPARKLE] = 1; else Mirror[WARP_SPARKLE] = 0; }
  159.  
  160. int WarpSparkleReturn(){ return Mirror[WARP_SPARKLE_RETURN_DMAP]; }
  161. void WarpSparkleReturn(int dmap){ Mirror[WARP_SPARKLE_RETURN_DMAP] = dmap; }
  162.  
  163. int WarpSparkleDMap(){ return Mirror[WARP_SPARKLE_DMAP]; }
  164. void WarpSparkleDMap(int dmap){ Mirror[WARP_SPARKLE_DMAP] = dmap; }
  165.  
  166. int WarpSparkleX(){ return Mirror[WARP_SPARKLE_X]; }
  167. void WarpSparkleX(int x){ Mirror[WARP_SPARKLE_X] = x; }
  168.  
  169. int WarpSparkleY(){ return Mirror[WARP_SPARKLE_Y]; }
  170. void WarpSparkleY(int y){ Mirror[WARP_SPARKLE_Y] = y; }
  171.  
  172. int WarpSparkleScreen(){ return Mirror[WARP_SPARKLE_SCREEN]; }
  173. void WarpSparkleScreen(int screen){ Mirror[WARP_SPARKLE_SCREEN] = screen; }
  174.  
  175. //The following four functions are used to manipulate,a nd check the post-warp timer,
  176. //that prevents Link from being sent back by a sparkle as soon as he finishes warping.
  177.  
  178. int WarpReturnWait(){ return Mirror[MIRROR_POST_WARP_TIMER]; }
  179. void ReducePostWarpTimer(){ if ( Mirror[MIRROR_POST_WARP_TIMER] > 0 ) Mirror[MIRROR_POST_WARP_TIMER]--; }
  180. void SetPostWarpTimer(){ Mirror[MIRROR_POST_WARP_TIMER] = MIRROR_POST_WARP_TIMER_NUM_FRAMES; }
  181. void ClearPostWarpTimer(){ Mirror[MIRROR_POST_WARP_TIMER] = 0; }
  182.  
  183.  
  184. //Functions
  185.  
  186. //Checks the present DMap and returns irts counterpart.
  187. //!! You must set up the arrays inside this function, for it to work.
  188. int GetOtherworldlyDMap(int dmap){
  189.     int q[4];
  190.     int LightWorldDMaps[]={3,-1,-1,-1,-1}; //Populate these two arrays with the IDs of your light and dark world dmaps
  191.     int DarkWorldDMaps[]={8,-1,-1,-1,-1}; //in matched pairs.
  192.     for ( q[0] = 0; q[0] < SizeOfArray(LightWorldDMaps); q[0]++ ) {
  193.         q[1] = LightWorldDMaps[ q[0] ];
  194.         q[2] = DarkWorldDMaps[ q[0] ];
  195.         if ( dmap == q[1] ) return DarkWorldDMaps[ q[0] ];
  196.         if ( dmap == q[2] ) return LightWorldDMaps[ q[0] ];
  197.     }
  198.     return -1;
  199. }
  200.  
  201. //Returns if the present dmap is a dark world dmap
  202. //!! You must set up the arrays inside this function, for it to work.
  203. bool IsDarkWorld(){
  204.     int DarkWorldDMaps[]={8,-1,-1,-1,-1};
  205.     for ( int q = 0; q < SizeOfArray(DarkWorldDMaps); q++ ) {
  206.         if ( Game->GetCurDMap() == DarkWorldDMaps[q] ) return true;
  207.     }
  208.     return false;
  209. }
  210.  
  211. //Generates coordinates for the warp return sparkle.
  212. //this is set when we use the mirror.
  213. void SetWarpReturn(){
  214.     WarpSparkle(true);
  215.     WarpSparkleX(Link->X);
  216.     WarpSparkleY(Link->Y);
  217.     WarpSparkleDMap( GetOtherworldlyDMap( Game->GetCurDMap() ) );
  218.     WarpSparkleScreen(Game->GetCurScreen());
  219.     WarpSparkleReturn(Game->GetCurDMap());
  220. }
  221.  
  222. //Removes the warp sparkle, after using it.
  223. void ClearWarpSparkle(){
  224.     WarpSparkle(false);
  225.     WarpSparkleX(-100);
  226.     WarpSparkleY(-100);
  227.     WarpSparkleDMap(-1);
  228.     WarpSparkleScreen(-1);
  229.     WarpSparkleReturn(-1);
  230. }
  231.  
  232. //Returns if Link is in a dungeon based on the array dungeonDMaps[]
  233. //!! You must set up the array inside this function, for it to work.
  234. bool IsDungeonDMap(){
  235.     int dungeonDMaps[]={20,21,22};//List all dungeon DMaps here
  236.     for ( int q = 0; q < SizeOfArray(dungeonDMaps); q++ ) {
  237.         if ( Game->GetCurDMap() == dungeonDMaps[q] ) return true;
  238.         return false;
  239.     }
  240. }
  241.  
  242. //Returns if the warp destination is solid, prior to warping.
  243. bool ___WarpDestSolid(int x, int y, int screen, int map){
  244.     return ( Game->GetComboSolid(map, screen, ComboAt(x,y)) );
  245. }
  246.    
  247.  
  248. //A very precise way to check if the warp destination is solid, based on Link's standard hitbox.
  249. //Checks if any of Link's corners or axis positions are on a solid combo, and if a
  250. bool WarpDestSolid(){
  251.     if ( Screen->isSolid(Link->X+4, Link->Y) ||
  252.         Screen->isSolid(Link->X+8, Link->Y+8) ||
  253.         Screen->isSolid(Link->X+4, Link->Y+8) ||
  254.         Screen->isSolid(Link->X+8, Link->Y) ||
  255.         Screen->isSolid(Link->X+8, Link->Y+15) ||
  256.         Screen->isSolid(Link->X+15, Link->Y+8)  || 
  257.         Screen->isSolid(Link->X+15, Link->Y) ||
  258.         Screen->isSolid(Link->X+4, Link->Y+15) ||
  259.         Screen->isSolid(Link->X+15, Link->Y+15)) return true;
  260.     return false;
  261. }
  262. //! Main Functions to Call before Waitdraw()
  263.  
  264. //Handles the initial warp routines.
  265. void MirrorWarpLink() {
  266.     int q; int curmusic[256]; int curmusictrack; int nextmusic[256]; int nexttrack; int curmidi; int nextmidi;
  267.     int warpmusic[256];
  268.     if ( IsWarping() ){
  269.         Link->X = Mirror[WARP_LINK_X];
  270.         Link->Y = Mirror[WARP_LINK_Y];
  271.         SetPostWarpTimer();
  272.        
  273.         //Freeze all enemies and ghost scripts
  274.        
  275.        
  276.         //Start the warp sound first half...
  277.         NoAction();
  278.         if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  279.             Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  280.             curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  281.             Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  282.             nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  283.             Game->GetMessage(MUS_MIRROR_WARP_START, warpmusic);
  284.             if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_START_TRACK) ) {
  285.                 if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  286.             }
  287.         }
  288.         else {
  289.             if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  290.         }
  291.        
  292.         Screen->Wavy = WARP_WAVE_DUR;
  293.        
  294.         for ( q = 0; q < MIRROR_WARP_FIRST_HALF_DUR; q++ ) {
  295.             WaitNoAction();
  296.         }
  297.        
  298.        
  299.         //Do the warp
  300.         Link->PitWarp(GetOtherworldlyDMap(Game->GetCurDMap()), Game->GetCurScreen());
  301.         NoAction();
  302.        
  303.         //Second half of the music
  304.         if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  305.             Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  306.             curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  307.             Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  308.             nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  309.             Game->GetMessage(MUS_MIRROR_WARP_FINISH, warpmusic);
  310.             if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_FINISH_TRACK) ) {
  311.                 if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  312.             }
  313.         }
  314.         else {
  315.             if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  316.         }
  317.        
  318.        
  319.         for ( q = 0; q < MIRROR_DUNGEON_WARP_SECOND_HALF_DUR; q++ ) {
  320.             WaitNoAction();
  321.         }
  322.        
  323.         //Resume the enhanced music file for the dmap
  324.         Game->PlayEnhancedMusic(nextmusic, nexttrack);
  325.        
  326.         //resume npcs and ghost scripts
  327.        
  328.         IsWarping(false);
  329.         //for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY) / 2; q > 0; q--){
  330.         //  NoAction();
  331.         //  Waitframe();
  332.         //}
  333.         AfterWarp(true);
  334.     }
  335.    
  336.     if (IsReturnWarping() ){
  337.         Mirror[WARP_LINK_HP] = Link->HP;
  338.  
  339.         Link->X = WarpSparkleX();
  340.         Link->Y = WarpSparkleY();
  341.    
  342.         //Freeze all enemies and ghost scripts
  343.        
  344.         //Start the warp sound first half...
  345.         NoAction();
  346.         if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  347.             Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  348.             curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  349.             Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  350.             nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  351.             Game->GetMessage(MUS_MIRROR_WARP_START, warpmusic);
  352.             if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_START_TRACK) ) {
  353.                 if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  354.             }
  355.         }
  356.         else {
  357.             if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  358.         }
  359.        
  360.         Screen->Wavy = WARP_WAVE_DUR;
  361.        
  362.         for ( q = 0; q < MIRROR_WARP_FIRST_HALF_DUR; q++ ) {
  363.             WaitNoAction();
  364.         }
  365.        
  366.         //Do the return warp
  367.         Link->PitWarp(WarpSparkleReturn(), WarpSparkleScreen());
  368.        
  369.        
  370.         //Second half of the music
  371.         if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  372.             Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  373.             curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  374.             Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  375.             nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  376.             Game->GetMessage(MUS_MIRROR_WARP_FINISH, warpmusic);
  377.             if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_FINISH_TRACK) ) {
  378.                 if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  379.             }
  380.         }
  381.         else {
  382.             if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  383.         }
  384.        
  385.        
  386.         for ( q = 0; q < MIRROR_DUNGEON_WARP_SECOND_HALF_DUR; q++ ) {
  387.             WaitNoAction();
  388.         }
  389.        
  390.         //Resume the enhanced music file for the dmap
  391.         Game->PlayEnhancedMusic(nextmusic, nexttrack);
  392.        
  393.         //resume npcs and ghost scripts
  394.        
  395.        
  396.         IsReturnWarping(false);
  397.         //for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY) / 2; q > 0; q--){
  398.         //  NoAction();
  399.         //  Waitframe();
  400.         //}
  401.         AfterReturnWarp(true);
  402.     }
  403.     if ( DungeonWarp() ) {
  404.         //Warp to dungeon entrance.
  405.        
  406.         //Start the warp sound first half...
  407.         NoAction();
  408.         if ( MIRROR_DUNEON_SOUND_USES_ENHANCED_MUSIC ) {
  409.             Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  410.             curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  411.             Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  412.             nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  413.             Game->GetMessage(MUS_MIRROR_WARP_DUNGEON_START, warpmusic);
  414.             if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_DUNGEON_START_TRACK) ) {
  415.                 if ( SFX_MIRROR_WARP_DUNGEON_START ) Game->PlaySound(SFX_MIRROR_WARP_DUNGEON_START);
  416.             }
  417.         }
  418.         else {
  419.             if ( SFX_MIRROR_WARP_DUNGEON_START ) Game->PlaySound(SFX_MIRROR_WARP_DUNGEON_START);
  420.         }
  421.        
  422.         Screen->Wavy = WARP_WAVE_DUR;
  423.        
  424.         for ( q = 0; q < MIRROR_DUNGEON_WARP_FIRST_HALF_DUR; q++ ) {
  425.             WaitNoAction();
  426.         }
  427.        
  428.         //Do the dungeon warp
  429.         Link->Warp(Game->GetCurDMap(), Game->DMapContinue[Game->GetCurDMap()]);
  430.        
  431.        
  432.         //Second half of the music
  433.         if ( MIRROR_DUNEON_SOUND_USES_ENHANCED_MUSIC ) {
  434.             Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  435.             curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  436.             Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  437.             nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  438.             Game->GetMessage(MUS_MIRROR_DUNGEON_WARP_FINISH, warpmusic);
  439.             if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_DUNGEON_WARP_FINISH_TRACK) ) {
  440.                 if ( SFX_MIRROR_DUNGEON_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_DUNGEON_WARP_FINISH);
  441.             }
  442.         }
  443.         else {
  444.             if ( SFX_MIRROR_DUNGEON_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_DUNGEON_WARP_FINISH);
  445.         }
  446.        
  447.        
  448.         for ( q = 0; q < MIRROR_DUNGEON_DUNGEON_WARP_SECOND_HALF_DUR; q++ ) {
  449.             WaitNoAction();
  450.         }
  451.        
  452.         DungeonWarp(false);
  453.        
  454.        
  455.         //Resume the enhanced music file for the dmap
  456.         Game->PlayEnhancedMusic(curmusic, curmusictrack);
  457.        
  458.         //resume npcs and ghost scripts
  459.        
  460.            
  461.     }
  462. }
  463.  
  464.  
  465.  
  466. //Post-warp cleanup, and bounce.
  467. void WarpFinish() {
  468.     if (AfterWarp()){
  469.         int q;
  470.         if ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) Link->HitDir = -1;
  471.         //SetWarpReturn();
  472.         //If the destination is solid, send Link back.
  473.         if ( WarpDestSolid() ) {
  474.             //freeze all enemies and ghost scripts.
  475.             ClearWarpSparkle();
  476.            
  477.             Game->PlaySound(SFX_WARP_ERROR);
  478.             for ( q = 0; q < SFX_WARP_ERROR_DUR; q++ )
  479.                 WaitNoAction();
  480.            
  481.             Screen->Wavy = WARP_WAVE_DUR;
  482.            
  483.             for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY); q > 0; q--){
  484.                 NoAction();
  485.                 Waitframe();
  486.             }
  487.            
  488.             //resume npcs and ghost scripts
  489.             Link->X = Mirror[WARP_LINK_X];
  490.             Link->Y = Mirror[WARP_LINK_Y];
  491.            
  492.             //Start the warp sound first half...
  493.             NoAction();
  494.             if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  495.                 Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  496.                 curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  497.                 Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  498.                 nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  499.                 Game->GetMessage(MUS_MIRROR_WARP_START, warpmusic);
  500.                 if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_START_TRACK) ) {
  501.                     if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  502.                 }
  503.             }
  504.             else {
  505.                 if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  506.             }
  507.            
  508.             Screen->Wavy = WARP_WAVE_DUR;
  509.            
  510.             for ( q = 0; q < MIRROR_WARP_FIRST_HALF_DUR; q++ ) {
  511.                 WaitNoAction();
  512.             }
  513.            
  514.            
  515.             //Do the return warp
  516.            
  517.             Link->PitWarp(GetOtherworldlyDMap(Game->GetCurDMap()), Game->GetCurScreen());
  518.            
  519.             AfterWarp(false);
  520.            
  521.             //Second half of the music
  522.             if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  523.                 Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  524.                 curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  525.                 Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  526.                 nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  527.                 Game->GetMessage(MUS_MIRROR_WARP_FINISH, warpmusic);
  528.                 if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_FINISH_TRACK) ) {
  529.                     if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  530.                 }
  531.             }
  532.             else {
  533.                 if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  534.             }
  535.            
  536.            
  537.             for ( q = 0; q < MIRROR_DUNGEON_WARP_SECOND_HALF_DUR; q++ ) {
  538.                 WaitNoAction();
  539.             }
  540.            
  541.            
  542.         //resume npcs and ghost scripts
  543.             for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY); q > 0; q--){
  544.                 NoAction();
  545.                 Waitframe();
  546.             }
  547.         }
  548.         if ( Link->HP < Mirror[WARP_LINK_HP] && WARP_RETURNS_ON_INJURY) { //If Link is injured, send him back.
  549.             Link->HP = Mirror[WARP_LINK_HP];
  550.            
  551.             Screen->Wavy = WARP_WAVE_DUR;
  552.             //freeze all enemies and ghost scripts.
  553.            
  554.             //Start the warp sound first half...
  555.             NoAction();
  556.             if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  557.                 Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  558.                 curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  559.                 Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  560.                 nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  561.                 Game->GetMessage(MUS_MIRROR_WARP_START, warpmusic);
  562.                 if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_START_TRACK) ) {
  563.                     if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  564.                 }
  565.             }
  566.             else {
  567.                 if ( SFX_MIRROR_WARP_START ) Game->PlaySound(SFX_MIRROR_WARP_START);
  568.             }
  569.            
  570.             Screen->Wavy = WARP_WAVE_DUR;
  571.            
  572.             for ( q = 0; q < MIRROR_WARP_FIRST_HALF_DUR; q++ ) {
  573.                 WaitNoAction();
  574.             }
  575.            
  576.            
  577.             //Do the return warp
  578.            
  579.            
  580.             Link->X = Mirror[WARP_LINK_X];
  581.             Link->Y = Mirror[WARP_LINK_Y];
  582.             Link->PitWarp(WarpSparkleReturn(), Game->GetCurScreen());
  583.  
  584.             Link->X = Mirror[WARP_LINK_X];
  585.             Link->Y = Mirror[WARP_LINK_Y];
  586.             Link->HP = Mirror[WARP_LINK_HP];
  587.            
  588.             AfterWarp(false);
  589.            
  590.            
  591.             //Second half of the music
  592.             if ( MIRROR_WARP_SOUND_USES_ENHANCED_MUSIC ) {
  593.                 Game->GetDMapMusicFilename(Game->GetCurDMap(), curmusic);
  594.                 curmusictrack = Game->GetDMapMusicTrack(Game->GetCurDMap());
  595.                 Game->GetDMapMusicFilename(GetOtherworldlyDMap(Game->GetCurDMap()), nextmusic);
  596.                 nexttrack = Game->GetDMapMusicTrack(GetOtherworldlyDMap(Game->GetCurDMap()));
  597.                 Game->GetMessage(MUS_MIRROR_WARP_FINISH, warpmusic);
  598.                 if !( Game->PlayEnhancedMusic(warpmusic, MUS_MIRROR_WARP_FINISH_TRACK) ) {
  599.                     if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  600.                 }
  601.             }
  602.             else {
  603.                 if ( SFX_MIRROR_WARP_FINISH ) Game->PlaySound(SFX_MIRROR_WARP_FINISH);
  604.             }
  605.            
  606.            
  607.             for ( q = 0; q < MIRROR_DUNGEON_WARP_SECOND_HALF_DUR; q++ ) {
  608.                 WaitNoAction();
  609.             }
  610.  
  611.             //resume npcs and ghost scripts
  612.         }
  613.         else {
  614.             Link->X = Mirror[WARP_LINK_X];
  615.             Link->Y = Mirror[WARP_LINK_Y];
  616.             //SetPostWarpTimer();
  617.             //Mirror[WARP_LINK_TEMP_INVULNERABILITY] = WARP_INVULNERABILITY_FRAMES;
  618.             AfterWarp(false);
  619.         }
  620.     }
  621.    
  622.     if (AfterReturnWarp()){
  623.         if ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) Link->HitDir = -1;
  624.         ClearWarpSparkle();
  625.         Mirror[WARP_LINK_TEMP_INVULNERABILITY] = WARP_INVULNERABILITY_FRAMES;
  626.         AfterReturnWarp(false);
  627.         ClearPostWarpTimer();
  628.            
  629.     }
  630.    
  631.     if ( POST_WARP_LINK_IS_INVINCIBLE ) {
  632.         if ( Mirror[WARP_LINK_TEMP_INVULNERABILITY] ) {
  633.             //If we find a way to Flicker Link, it goes here.
  634.             Link->CollDetection = false;
  635.             Mirror[WARP_LINK_TEMP_INVULNERABILITY]--;
  636.         }
  637.         if ( !Mirror[WARP_LINK_TEMP_INVULNERABILITY] ) Link->CollDetection = true;
  638.     }
  639.    
  640.     //if ( Mirror[MIRROR_POST_WARP_TIMER] > 0 ) Mirror[MIRROR_POST_WARP_TIMER]--;
  641. }
  642.  
  643.  
  644. //Creates the mirror return sparkle.
  645. void MirrorSparkle(){
  646.     if ( Game->GetCurDMap() == WarpSparkleDMap() && Game->GetCurScreen() == WarpSparkleScreen() ) {
  647.         Screen->DrawCombo(  MIRROR_SPARKLE_COMBO_LAYER, WarpSparkleX(), WarpSparkleY(),
  648.             MIRROR_SPARKLE_COMBO, MIRROR_SPARKLE_COMBO_H, MIRROR_SPARKLE_COMBO_W, MIRROR_SPARKLE_COMBO_CSET,
  649.             MIRROR_SPARKLE_COMBO_XSCALE, MIRROR_SPARKLE_COMBO_YSCALE, MIRROR_SPARKLE_COMBO_RX,
  650.             MIRROR_SPARKLE_COMBO_RY, MIRROR_SPARKLE_COMBO_RANGLE, Mirror[MIRROR_SPARKLE_COMBO_FRAME],
  651.             MIRROR_SPARKLE_COMBO_FLIP, true, MIRROR_SPARKLE_COMBO_OPACITY) ; //Mirror sparkle
  652.        
  653.         //Reduce the frames
  654.         if ( Mirror[MIRROR_SPARKLE_COMBO_FRAME] >= MIRROR_SPARKLE_COMBO_NUM_FRAMES ) Mirror[MIRROR_SPARKLE_COMBO_FRAME] = MIRROR_SPARKLE_COMBO_INIT_FRAME;
  655.         else Mirror[MIRROR_SPARKLE_COMBO_FRAME]++;
  656.            
  657.         if ( !WarpReturnWait() && !IsTempInvincible() ){
  658.            
  659.             if ( Abs( Link->X - WarpSparkleX()) < 8 && Abs(Link->Y - WarpSparkleY()) < 8 )
  660.             {
  661.                 //Reurn Link via the portal
  662.                 IsReturnWarping(true);
  663.             }
  664.         }
  665.     }
  666. }
  667.  
  668. bool IsTempInvincible(){
  669.     if ( Mirror[WARP_LINK_TEMP_INVULNERABILITY] && POST_WARP_LINK_IS_INVINCIBLE ) return true;
  670.     if ( !Mirror[WARP_LINK_TEMP_INVULNERABILITY] || !POST_WARP_LINK_IS_INVINCIBLE ) return false;
  671. }
  672.  
  673. void TestSparkle(){
  674.     int x = WarpSparkleX();
  675.     int y = WarpSparkleY();
  676.     if ( x < 0 ) x = 0;
  677.     if ( y < 0 ) y = 0;
  678.     Screen->DrawCombo(  MIRROR_SPARKLE_COMBO_LAYER, x, y,
  679.             MIRROR_SPARKLE_COMBO, MIRROR_SPARKLE_COMBO_H, MIRROR_SPARKLE_COMBO_W, MIRROR_SPARKLE_COMBO_CSET,
  680.             MIRROR_SPARKLE_COMBO_XSCALE, MIRROR_SPARKLE_COMBO_YSCALE, MIRROR_SPARKLE_COMBO_RX,
  681.             MIRROR_SPARKLE_COMBO_RY, MIRROR_SPARKLE_COMBO_RANGLE, Mirror[MIRROR_SPARKLE_COMBO_FRAME],
  682.             MIRROR_SPARKLE_COMBO_FLIP, true, MIRROR_SPARKLE_COMBO_OPACITY) ; //Mirror sparkle
  683.        
  684.         //Reduce the frames
  685.         if ( Mirror[MIRROR_SPARKLE_COMBO_FRAME] >= MIRROR_SPARKLE_COMBO_NUM_FRAMES ) Mirror[MIRROR_SPARKLE_COMBO_FRAME] = MIRROR_SPARKLE_COMBO_INIT_FRAME;
  686.         else Mirror[MIRROR_SPARKLE_COMBO_FRAME]++;
  687. }
  688.  
  689.  
  690. //Runs the moon pearl bunny sprite change, and halts using any item other than the mirror.
  691. void MoonPearl(){
  692.     if ( IsDarkWorld() && !Link->Item[I_MOONPEARL] && !Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = true;
  693.     if ( !IsDarkWorld() && Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = false;
  694.     if ( IsDarkWorld() && Link->Item[I_MOONPEARL] && Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = false;
  695.     if ( Link->Item[I_BUNNYRING] ) {
  696.         if ( Link->PressA && GetEquipmentA() != I_MIRROR ) Link->PressA = false;
  697.         if ( Link->PressB && GetEquipmentB() != I_MIRROR ) Link->PressB = false;
  698.     }
  699. }
  700.  
  701. /// Items
  702.  
  703. item script Mirror{
  704.     void run(){
  705.         int cmb[4];
  706.         cmb[0] = Screen->ComboT[ComboAt(Link->X+8, Link->Y+8)];
  707.         cmb[1] = GetLayerComboT(1,cmb[0]);
  708.         cmb[2] = GetLayerComboT(2,cmb[0]);
  709.         if ( IsDungeonDMap() && MIRROR_RETURNS_TO_DUNGEON_ENTRANCE ) {
  710.             DungeonWarp(true);
  711.             //Warp to dungeon entrance.
  712.             //Game->PlaySound(SFX_WARP_DUNGEON);
  713.             //Screen->Wavy = WARP_WAVE_DUR_DUNGEON;
  714.             //Link->Warp(Game->GetCurDMap(), Game->DMapContinue[Game->GetCurDMap()]);
  715.         }
  716.        
  717.        
  718.         else {
  719.             if ( IsDarkWorld() ) {
  720.                 for ( cmb[3] = 0; cmb[3] <= 3; cmb[3]++ ) {
  721.                     if ( cmb[ cmb[3] ] == CT_CAVE || cmb[ cmb[3] ] == CT_CAVE2 || cmb[ cmb[3] ] == CT_CAVEB
  722.                         || cmb[ cmb[3] ] == CT_CAVEC || cmb[ cmb[3] ] == CT_CAVED ||
  723.                         cmb[ cmb[3] ] == CT_CAVE2B || cmb[ cmb[3] ] == CT_CAVE2C ||cmb[ cmb[3] ] == CT_CAVE2D )
  724.                     {
  725.                         Game->PlaySound(SFX_WARP_ERROR);
  726.                         Quit();
  727.                     }
  728.                 }
  729.                 SetPostWarpTimer();
  730.                 //Mirror[MIRROR_POST_WARP_TIMER] = MIRROR_POST_WARP_TIMER_NUM_FRAMES;
  731.                 Mirror[WARP_LINK_X] = Link->X;
  732.                 Mirror[WARP_LINK_Y] = Link->Y;
  733.                 Mirror[WARP_LINK_HP] = Link->HP;
  734.                 SetWarpReturn();
  735.                 IsWarping(true);
  736.             }
  737.             //Warp to other world
  738.             if ( !IsDarkWorld() && SFX_WARP_ERROR ) Game->PlaySound(SFX_WARP_ERROR);
  739.         }
  740.     }
  741. }
  742.  
  743. //Global Script Example
  744.  
  745. global script Z3_Mirror{
  746.     void run(){
  747.         while(true){
  748.             if ( REQUIRE_MOON_PEARL ) MoonPearl();
  749.             ReducePostWarpTimer();
  750.             MirrorWarpLink();
  751.            
  752.             //if ( TEST_MIRROR_SPARKLE ) TestSparkle();
  753.             //if ( MIRROR_SPARKLE_BEFORE_WAITDRAW ) MirrorSparkle();
  754.             WarpFinish();
  755.             Waitdraw();
  756.            
  757.             //if ( !MIRROR_SPARKLE_BEFORE_WAITDRAW ) MirrorSparkle();
  758.             if ( WarpSparkle() ) MirrorSparkle(); //Call only if it exists.
  759.             Waitframe();
  760.         }
  761.     }
  762. }
  763.  
  764. //Deprecated
  765.  
  766. const int SOLIDITY_CHECK_DISTANCE = 8;
  767.  
  768. bool TouchingSolid(int x, int y) {
  769.     if ( Screen->isSolid(x,y) ||
  770.         Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y) ||
  771.         Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y+SOLIDITY_CHECK_DISTANCE) ||
  772.         Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y-SOLIDITY_CHECK_DISTANCE) ||
  773.         Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y) ||
  774.         Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y+SOLIDITY_CHECK_DISTANCE) ||
  775.         Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y-SOLIDITY_CHECK_DISTANCE) ) {
  776.         return true;
  777.     }
  778.     return false;
  779. }
  780.  
  781. bool TouchingSolid(){
  782.     if ( Screen->isSolid(Link->X,Link->Y) ||
  783.         Screen->isSolid(Link->X + 15, Link->Y) ||
  784.         Screen->isSolid(Link->X + 15, Link->Y+15) ||
  785.         Screen->isSolid(Link->X + 15, Link->Y-15) ||
  786.         Screen->isSolid(Link->X - 15, Link->Y) ||
  787.         Screen->isSolid(Link->X - 15, Link->Y+15) ||
  788.         Screen->isSolid(Link->X - 15, Link->Y-15) )
  789.     {
  790.         return true;
  791.     }
  792.     return false;
  793. }
  794.  
  795.  
  796.  
  797. //Cape
  798.  
  799.  
  800. void CapeOfInvisibility(){}
  801.  
  802.  
  803.  
  804. //if ( Mirror[CAPE_ON] ) {
  805. //  CapeCost();
  806. //  DoCape();
  807. //}
  808.  
  809. void DoCape(){
  810.     int scale = Rand(13,15);
  811.     int flip;
  812.     if ( Link->Dir == DIR_DOWN ) flip = 1;
  813.     else if ( Link->Dir == DIR_LEFT ) flip = 7;
  814.     else if ( Link->Dir == DIR_DOWN ) flip = ;
  815.     else flip = 0;
  816.     Screen->DrawTile(CAPE_SHADOW_LAYER, Link->X+CAPE_SHADOW_X_OFFSET, Link->Y+CAPE_SHADOW_Y_OFFSET, CAPE_SHADOW_TILE, 1,1, CAPE_SHADOW_CSET, scale, scale, 0, 0, 0, flip, true, CAPE_SHADOW_OPACITY);
  817. }
  818.  
  819. const int CAPE_SHADOW_LAYER = 2;
  820. const int CAPE_SHADOW_X_OFFSET = 0;
  821. const int CAPE_SHADOW_Y_OFFSET = 4;
  822. const int CAPE_SHADOW_TILE = 2001;
  823. const int CAPE_SHADOW_CSET = 0;
  824. const int CAPE_SHADOW_OPACITY = 64;
  825.  
  826.  
  827.  
  828.  
  829.  
  830. item script CapeOfInvisibility{
  831.     void run(){
  832.         if ( Mirror[CAPE_ON] ) { Mirror[CAPE_ON] = 0; }
  833.         else {
  834.             InitCapeTimer(); //Should we start at 0 to ensure a magic cost?
  835.             Mirror[CAPE_ON] = 1;
  836.         }
  837.     }
  838. }
  839.  
  840. void InitCapeTimer() { Mirror[CAPE_TIMER] = CAPE_MAGIC_USE_RATE; }
  841.  
  842.  
  843.  
  844. //! I need to include these, along with IsInvisible() and IsInvincible() to ensure that there ar eno comflicts between this and other cape/cane scripts.
  845.  
  846.  
  847.  
  848. const int CAPE_ON = 50;
  849.  
  850.  
  851.  
  852. const int CAPE_MAGIC_COST = 3; //Cost per rate
  853. const int CAPE_MAGIC_USE_RATE = 50; //frames per cost unit
  854.  
  855.  
  856.  
  857. //cAPE ARRAY INDICES
  858. const int CAPE_TIMER = 60;
  859. const int CAPE_SHADOW_WAVER_TIMER = 61;
  860.  
  861.  
  862. //Cape Settingds
  863. const int CAPE_SHADOW_TILE = 2100;
  864.  
  865. /////////////////////
  866. /// Cane of Byrna ///
  867. /////////////////////
  868.  
  869. void InitByrnaTimer() { Mirror[BYRNA_TIMER] = BYRNA_MAGIC_USE_RATE; }
  870.  
  871. void ByrnaCost(){
  872.     if ( Mirror[BYRNA_TIMER] > 0 ) Mirror[BYRNA_TIMER]--;
  873.     if ( Mirror[BYRNA_TIMER] <= 0 ) {
  874.         Game->MCounter[CR_MAGIC] -= ( CAPE_MAGIC_COST * Game->Generic[GEN_MAGICDRAINRATE]; //Allow half magic
  875.         InitByrnaTimer();
  876.     }
  877. }
  878.  
  879.  
  880. //Byrna Array Indices
  881. const int BYRNA_ON = 51;
  882.  
  883. const int BYRNA_TIMER = 70;
  884.  
  885. //The true z3 cane has only one orbit
  886. const int BYRNA_BEAM_SPRITE         = 80;
  887. const int BYRNA_BEAM_1_ORBIT_X      = 81;
  888. const int BYRNA_BEAM_1_ORBIT_Y      = 82;
  889. const int BYRNA_BEAM_1_ORBIT_CX     = 83;
  890. const int BYRNA_BEAM_1_ORBIT_CY     = 84;
  891. const int BYRNA_BEAM_1_ORBIT_VELOCITY   = 85;
  892. const int BYRNA_BEAM_1_ORBIT_ANG1   = 86;
  893. const int BYRNA_BEAM_1_ORBIT_ANG2   = 87;
  894. const int BYRNA_BEAM_1_ORBIT_RADIUS     = 88;
  895. const int BYRNA_BEAM_1_ORBIT_RADIUS2    = 89;
  896. const int BYRNA_BEAM_1_ORBIT_FRAME  = 90;
  897. const int BYRNA_ORBIT_SOUND_TIMER   = 91;
  898.  
  899. void ByrnaSound(){
  900.     if ( Mirror[BYRNA_ORBIT_SOUND_TIMER] > 0 ) Mirror[BYRNA_ORBIT_SOUND_TIMER]--;
  901.     else {
  902.         Mirror[BYRNA_ORBIT_SOUND_TIMER] = BYRNA_ORBIT_SOUND_LOOP_TIME;
  903.         if ( SFX_BYRNA_ORBIT ) Game->PlaySound(SFX_BYRNA_ORBIT);
  904.     }
  905. }
  906.  
  907.  
  908. //const int BYRNA_BEAM_2_ORBIT_X        = 86;
  909. //const int BYRNA_BEAM_2_ORBIT_Y        = 87;
  910. //const int BYRNA_BEAM_2_ORBIT_VELOCITY     = 88;
  911. //const int BYRNA_BEAM_2_ORBIT_SIN  = 89;
  912. //const int BYRNA_BEAM_2_ORBIT_COSIN    = 90;
  913.  
  914. //const int BYRNA_BEAM_3_ORBIT_X        = 91;
  915. //const int BYRNA_BEAM_3_ORBIT_Y        = 92;
  916. //const int BYRNA_BEAM_3_ORBIT_VELOCITY     = 93;
  917. //const int BYRNA_BEAM_3_ORBIT_SIN  = 94;
  918. //const int BYRNA_BEAM_3_ORBIT_COSIN    = 95;
  919.  
  920. //const int BYRNA_BEAM_4_ORBIT_X        = 96;
  921. //const int BYRNA_BEAM_4_ORBIT_Y        = 97;
  922. //const int BYRNA_BEAM_4_ORBIT_VELOCITY     = 98;
  923. //const int BYRNA_BEAM_4_ORBIT_SIN  = 99;
  924. //const int BYRNA_BEAM_4_ORBIT_COSIN    = 100;
  925.  
  926. const int BYRNA_COST = 4;
  927. const int BYRNA_MAGIC_USE_RATE = 120; //frames per unit of cost
  928.  
  929. const int WDS_BYRNABLOCKED = 0; //Deadstate for eweapons blocked by the byrna beam.
  930. const int BYRNA_BEAMS_REFLECT_WEAPONS = 1;
  931. const int BYRNA_DAMAGE = 2;
  932. const int LW_CUSTOMBYRNA = 20; //The weapon type to spoof.
  933.  
  934. const int BYRNA_NUM_ORBITS = 1;
  935.  
  936. const int BYRNA_ORBIT_RADIUS = 40;
  937. const int BYRNA_ORBIT_SPEED = 120;
  938. const int BYRNA_ORBIT_COMBO = 2002;
  939. const int BYRNA_ORBIT_NUM_FRAMES = 4;
  940. const int BYRNA_ORBIT_COMBO_LAYER = 6;
  941. const int BYRNA_ORBIT_COMBO_H = 1;
  942. const int BYRNA_ORBIT_COMBO_W = 1;
  943. const int BYRNA_ORBIT_COMBO_CSET = 0;
  944. const int BYRNA_ORBIT_COMBO_RY = 0;
  945. const int BYRNA_ORBIT_COMBO_RX = 0;
  946. const int BYRNA_ORBIT_COMBO_RANGLE = 0;
  947. const int BYRNA_ORBIT_COMBO_FLIP = 0;
  948. const int BYRNA_ORBIT_COMBO_OPACITY = 128;
  949. const int BYRNA_ORBIT_COMBO_XSCALE = -1;
  950. const int BYRNA_ORBIT_COMBO_YSCALE = -1;
  951. const int BYRNA_ORBIT_INIT_FRAME = 1;
  952.  
  953.  
  954. const int SFX_BYRNA_ON = 63;
  955. const int SFX_BYRNA_OFF = 64;
  956. const int SFX_BYRNA_ORBIT = 65;
  957. const int BYRNA_ORBIT_SOUND_LOOP_TIME = 90;
  958.  
  959. //Handles the cost calcs.
  960. void ByrnaCost(){
  961.     if ( Mirror[BYRNA_TIMER] > 0 ) Mirror[BYRNA_TIMER]--;
  962.     if ( Mirror[BYRNA_TIMER] <= 0 ) {
  963.         Game->MCounter[CR_MAGIC] -= ( CAPE_MAGIC_COST * Game->Generic[GEN_MAGICDRAINRATE]; //Allow half magic
  964.         InitByrnaTimer();
  965.     }
  966. }
  967.  
  968.  
  969. //Prime the vars for orbiting. Call this only from the item script, when enabling.
  970. void InitByrna(){
  971.     Mirror[BYRNA_BEAM_1_ORBIT_RADIUS] = BYRNA_ORBIT_RADIUS;
  972.     Mirror[BYRNA_BEAM_1_ORBIT_VELOCITY] = BYRNA_ORBIT_SPEED;
  973.     if ( Mirror[BYRNA_BEAM_1_ORBIT_RADIUS2] == 0 ) Mirror[BYRNA_BEAM_1_ORBIT_RADIUS2] = Mirror[BYRNA_BEAM_1_ORBIT_RADIUS]; //Circle
  974.         if ( Mirror[BYRNA_BEAM_1_ORBIT_ANG1] < 0 ) Mirror[BYRNA_BEAM_1_ORBIT_ANG1] = Rand(360); //Random Start
  975.         Mirror[BYRNA_BEAM_1_ORBIT_CX] = Mirror[BYRNA_BEAM_1_ORBIT_X];
  976.         Mirror[BYRNA_BEAM_1_ORBIT_CY] = Mirror[BYRNA_BEAM_1_ORBIT_Y];
  977. }
  978.  
  979.  
  980.  
  981. //Call before Waitdraw to make the orbits, as if ( Mirror[BYRNA_ON] ) DoByrna();
  982. void DoByrna(){
  983.  
  984.     int q[8];  
  985.    
  986.     Mirror[BYRNA_BEAM_1_ORBIT_ANG1] += Mirror[BYRNA_BEAM_1_ORBIT_VELOCITY];
  987.     if ( Mirror[BYRNA_BEAM_1_ORBIT_ANG1] < -360) Mirror[BYRNA_BEAM_1_ORBIT_ANG1] += 360; //Wraping happens
  988.     else if ( Mirror[BYRNA_BEAM_1_ORBIT_ANG1] > 360) Mirror[BYRNA_BEAM_1_ORBIT_ANG1] -= 360;
  989.            
  990.     Mirror[BYRNA_BEAM_1_ORBIT_X] = Mirror[BYRNA_BEAM_1_ORBIT_CX] + VectorX(Mirror[BYRNA_BEAM_1_ORBIT_RADIUS],
  991.         Mirror[BYRNA_BEAM_1_ORBIT_ANG1]);
  992.  
  993.     Mirror[BYRNA_BEAM_1_ORBIT_Y] = Mirror[BYRNA_BEAM_1_ORBIT_CY] + VectorY(Mirror[BYRNA_BEAM_1_ORBIT_RADIUS2],
  994.         Mirror[BYRNA_BEAM_1_ORBIT_ANG1]);
  995.     //Create the beams and have them orbit Link
  996.     //track their positions in Misc indices
  997.     Screen->DrawCombo(  BYRNA_ORBIT_COMBO_LAYER, Mirror[BYRNA_BEAM_1_ORBIT_X], Mirror[BYRNA_BEAM_1_ORBIT_Y],
  998.             BYRNA_ORBIT_COMBO, BYRNA_ORBIT_COMBO_H, BYRNA_ORBIT_COMBO_W, BYRNA_ORBIT_COMBO_CSET,
  999.             BYRNA_ORBIT_COMBO_XSCALE, BYRNA_ORBIT_COMBO_YSCALE, BYRNA_ORBIT_COMBO_RX,
  1000.             BYRNA_ORBIT_COMBO_RY, BYRNA_ORBIT_COMBO_RANGLE, Mirror[BYRNA_BEAM_1_ORBIT_FRAME],
  1001.             BYRNA_ORBIT_COMBO_FLIP, true, BYRNA_ORBIT_COMBO_OPACITY) ; //Mirror sparkle
  1002.        
  1003.     //Reduce the frames
  1004.     if ( Mirror[BYRNA_BEAM_1_ORBIT_FRAME] >= BYRNA_ORBIT_NUM_FRAMES ) Mirror[BYRNA_BEAM_1_ORBIT_FRAME] = BYRNA_ORBIT_INIT_FRAME;
  1005.     else Mirror[BYRNA_BEAM_1_ORBIT_FRAME]++;
  1006.    
  1007.        
  1008.     //No, wait, the beams need to be drawn tiles and we need TileCollision.
  1009.    
  1010.     q[4] = Screen->NummNPCs(); q[5] = Screen->NumEWeapons();
  1011.     //int loops = Max(npcs,
  1012.     for ( q[0] = Max(q[4], q[5]); q > 0; q-- ) {
  1013.         if ( q[0] < q[4] ) npc n = Screen->LoadNPC(q[0]);
  1014.         if ( q[0] < q[5] ) eweapon e = Screen->LoadEWeapon(q[0]);
  1015.         for ( q[1] = 0; q[1] < BYRNA_NUM_ORBITS; q[1]++ ) { //for each beam
  1016.            
  1017.             if ( q[0] < q[4] ) {
  1018.                 if ( Abs( n->X - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 && Abs(n->Y - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 )
  1019.                 {
  1020.                     beam[ q[0] ] = Screen->CreateLWeapon(LW_CUSTOMBYRNA);
  1021.                     beam[ q[0] ]-> X = n->X;
  1022.                     beam[ q[0] ]-> Y = n->Y; //Spawn a weapon n the npc
  1023.                     beam[ q[0] ]->Damage = BYRNA_DAMAGE;
  1024.                 }
  1025.             }
  1026.             if ( q[0] < q[5] ) {   
  1027.                 if ( Abs( e->X - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 && Abs(e->Y - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 )
  1028.                 {
  1029.                     //block/reflect
  1030.                     if ( BYRNA_BEAMS_REFLECT_WEAPONS ) ReflectWeapon(e);
  1031.                     else e->DeasDtate = WDS_BYRNABLOCKED:
  1032.                 }
  1033.             }
  1034.         }
  1035.     }
  1036.    
  1037. }
  1038.  
  1039. item script CaneOfByrna{
  1040.     void run(){
  1041.         if ( Mirror[BYRNA_ON] ) { Mirror[BYRNA_ON] = 0; }
  1042.         else { InitByrna(); Mirror[BYRNA_ON] = 1; }
  1043.     }
  1044. }
  1045.  
  1046. //The main byrna function. Call directly, prior to Waitdraw();
  1047. void CaneOfByrna(){ ByrnaCost(); DoByrna(); ByrnaSound();}
  1048.  
  1049.  
  1050.  
  1051.  
  1052. bool IsInvisible(){
  1053.     if ( Mirror[CAPE_ON] ) return true;
  1054.     return false;
  1055. }
  1056.  
  1057. bool IsInvincible(){
  1058.     if ( Mirror[BYRNA_ON] || Mirror[WARP_LINK_TEMP_INVULNERABILITY] ) return true;
  1059.     return false;
  1060. }
  1061.  
  1062. void HandleInvisibilityAndInvincibility(){
  1063.     if ( IsInvisible() ) Link->Invisible = true;
  1064.     else Link->Invisible = false;
  1065.     if ( IsInvincible() ) Link->CollDetection = false;
  1066.     else Link->CollDetection = true;
  1067. }
  1068.  
  1069. //! We can tighten this down baed on Link's proximity to the grid.
  1070. bool LinkTouchingSolidCombo(){
  1071.     int cmb[6];
  1072.     cmb[0] = ComboAt(Link->X, Link->Y);
  1073.     cmb[1] = ____AdjacentCombo(cmb,3);
  1074.     cmb[2] = ____AdjacentCombo(cmb,5);
  1075.     cmb[3] = ____AdjacentCombo(cmb,4);
  1076.     for ( cmb[4] = 0; cmb[4] <= 2; cmb[4]++ ) {
  1077.         for ( cmb[5] = 0; cmb[5] <= 4; cmb[5]++ ) {
  1078.             if ( GetLayerComboS(cmb[4], cmb[ cmb[5] ]) > 0 ) return true;
  1079.         }
  1080.     }
  1081. }
  1082.  
  1083.  
  1084. //Constants for AdjacentCombo()
  1085.  
  1086. //const int CMB_UPLEFT    = 0;
  1087. //const int CMB_UP        = 1;
  1088. //const int CMB_UPRIGHT   = 2;
  1089. //const int CMB_RIGHT     = 3;
  1090. //const int CMB_DOWNRIGHT = 4;
  1091. //const int CMB_DOWN      = 5;
  1092. //const int CMB_DOWNLEFT  = 6;
  1093. //const int CMB_LEFT      = 7;
  1094. //const int CMB_LEFTUP    = 0; //Not 8, as those are dir + shield
  1095.  
  1096. //Returns the Nuth combo index of a combo based on a central point, and a direction.
  1097. //For example, combo 22 + COMBO_UPRIGHT returns '7',
  1098. //as combo 7 is to the upper-right of combo 22.
  1099. int ____AdjacentCombo(int cmb, int dir){
  1100.     int combooffsets[13]={-0x10,-0x0F,-0x0E,1,0x10,0x0F,0x0E,-1,-0x10};
  1101.     if ( cmb % 16 == 0 ) combooffsets[9] = 1;
  1102.     if ( (cmb & 15) == 1 ) combooffsets[10] = 1;
  1103.     if ( cmb < 0x10 ) combooffsets[11] = 1;
  1104.     if ( cmb < 0xAF ) combooffsets[12] = 1;
  1105.     if ( combooffsets[9] && ( dir == CMB_LEFT || dir == CMB_UPLEFT || dir == CMB_DOWNLEFT || dir == CMB_LEFTUP ) ) return 0;
  1106.     if ( combooffsets[10] && ( dir == CMB_RIGHT || dir == CMB_UPRIGHT || dir == CMB_DOWNRIGHT ) ) return 0;
  1107.     if ( combooffsets[11] && ( dir == CMB_UP || dir == CMB_UPRIGHT || dir == CMB_UPLEFT || dir == CMB_DOWNLEFT ) ) return 0;
  1108.     if ( combooffsets[12] && ( dir == CMB_DOWN || dir == CMB_DOWNRIGHT || dir == CMB_DOWNLEFT ) ) return 0;
  1109.     else if ( cmb > 0 && cmb < 177 ) return cmb + combooffsets[dir];
  1110.     else return 0;
  1111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement