Advertisement
ZoriaRPG

ZScript Z3 Mirror, Cape, Cane of Byrna v0.2

Nov 23rd, 2016
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 27.72 KB | None | 0 0
  1. ///////////////////////
  2. /// Z3 Magic Mirror ///
  3. /// v0.3.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.  //! 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. //Options
  38. const int WARP_RETURNS_ON_INJURY        = 1;
  39. const int REQUIRE_MOON_PEARL            = 1;
  40. const int MIRROR_RETURNS_TO_DUNGEON_ENTRANCE    = 1; //This requires placing a warp return square on dungeon entrance screens.
  41.  
  42. const int MIRROR_POST_WARP_TIMER_NUM_FRAMES = 75; // Number of frames afer warping, before Link may use a warp return sparkle.
  43.  
  44. const int POST_WARP_LINK_IS_INVINCIBLE      = 0;     //If se tto '1', Link->CollDetection will be disabled for a number of
  45.                         //frames equal to:
  46.  
  47. const int WARP_INVULNERABILITY_FRAMES       = 90; //Number of frames that Link is invulnerable after warping.
  48.  
  49. //!! Caution: This may conflict with other items that grant invulnerability!
  50.  
  51. const int SF_FORBID_MIRROR = 0; //A script screen flag to forbid usin the mirror.
  52.  
  53. ///Constants for Array Indices of Mirror[]
  54.  
  55. const int IS_WARPING        = 0;
  56. const int AFTER_WARP        = 1;
  57. const int RETURN_WARP       = 2;
  58. const int AFTER_RETURN_WARP     = 3;
  59.  
  60. const int WARP_SPARKLE          = 10;
  61. const int WARP_SPARKLE_DMAP         = 11;
  62. const int WARP_SPARKLE_SCREEN       = 12;
  63. const int WARP_SPARKLE_X        = 13;
  64. const int WARP_SPARKLE_Y        = 14;
  65. const int WARP_SPARKLE_RETURN_DMAP  = 15;
  66.  
  67. const int WARP_LINK_X           = 20;
  68. const int WARP_LINK_Y           = 21;
  69. const int WARP_LINK_Z           = 22;
  70. const int WARP_LINK_HP          = 23;
  71. const int WARP_LINK_TEMP_INVULNERABILITY = 24;
  72.  
  73. const int MIRROR_SPARKLE_COMBO_FRAME = 30; //Mirror array index
  74. const int MIRROR_POST_WARP_TIMER = 40;
  75.  
  76.  
  77.  
  78. //Settings
  79.  
  80. //Sounds
  81. const int SFX_WARP_ERROR    = 67;
  82. const int SFX_WARP      = 73;
  83. const int SFX_WARP_DUNGEON  = 16;
  84.  
  85. const int WARP_WAVE_DUR     = 100; //Duration of warp wavy animation (overworld)
  86. const int WARP_WAVE_DUR_DUNGEON = 100; //Duration of warp wavy animation (inside dungeons)
  87.  
  88. const int WARP_DUR      = 60;
  89. const int POST_WARP_DELAY   = 15;
  90.  
  91.  
  92.  
  93. //Mirror Sparkle Settings
  94. const int MIRROR_SPARKLE_COMBO      = 32596; // COmbo of sparkle or other warp return effect.
  95. const int MIRROR_SPARKLE_COMBO_LAYER    = 2;
  96. const int MIRROR_SPARKLE_COMBO_W    = 1;
  97. const int MIRROR_SPARKLE_COMBO_H    = 1;
  98. const int MIRROR_SPARKLE_COMBO_CSET     = 0;
  99. const int MIRROR_SPARKLE_COMBO_XSCALE   = -1;
  100. const int MIRROR_SPARKLE_COMBO_YSCALE   = -1;
  101. const int MIRROR_SPARKLE_COMBO_RX   = 0;
  102. const int MIRROR_SPARKLE_COMBO_RY   = 0;
  103. const int MIRROR_SPARKLE_COMBO_RANGLE   = 0;
  104.  
  105. const int MIRROR_SPARKLE_COMBO_FLIP     = 0;
  106. const int MIRROR_SPARKLE_COMBO_OPACITY  = 64;
  107.  
  108. const int MIRROR_SPARKLE_COMBO_NUM_FRAMES = 4;
  109. const int MIRROR_SPARKLE_COMBO_INIT_FRAME = 1;
  110.  
  111.  
  112.  
  113.  
  114. //Accessors
  115. int IsWarping(){ return Mirror[IS_WARPING]; }
  116. void IsWarping(bool state){ if ( state ) Mirror[IS_WARPING] = 1; else Mirror[IS_WARPING] = 0; }
  117.  
  118. int AfterWarp(){ return Mirror[AFTER_WARP]; }
  119. void AfterWarp(bool state){ if ( state ) Mirror[AFTER_WARP] = 1; else Mirror[AFTER_WARP] = 0; }
  120.  
  121. int IsReturnWarping(){ return Mirror[RETURN_WARP]; }
  122. void IsReturnWarping(bool state){ if ( state ) Mirror[RETURN_WARP] = 1; else Mirror[RETURN_WARP] = 0; }
  123.  
  124. int AfterReturnWarp(){ return Mirror[AFTER_RETURN_WARP]; }
  125. void AfterReturnWarp(bool state){ if ( state ) Mirror[AFTER_RETURN_WARP] = 1; else Mirror[AFTER_RETURN_WARP] = 0; }
  126.  
  127. int WarpSparkle(){ return Mirror[WARP_SPARKLE]; }
  128. void WarpSparkle(bool state){ if ( state ) Mirror[WARP_SPARKLE] = 1; else Mirror[WARP_SPARKLE] = 0; }
  129.  
  130. int WarpSparkleReturn(){ return Mirror[WARP_SPARKLE_RETURN_DMAP]; }
  131. void WarpSparkleReturn(int dmap){ Mirror[WARP_SPARKLE_RETURN_DMAP] = dmap; }
  132.  
  133. int WarpSparkleDMap(){ return Mirror[WARP_SPARKLE_DMAP]; }
  134. void WarpSparkleDMap(int dmap){ Mirror[WARP_SPARKLE_DMAP] = dmap; }
  135.  
  136. int WarpSparkleX(){ return Mirror[WARP_SPARKLE_X]; }
  137. void WarpSparkleX(int x){ Mirror[WARP_SPARKLE_X] = x; }
  138.  
  139. int WarpSparkleY(){ return Mirror[WARP_SPARKLE_Y]; }
  140. void WarpSparkleY(int y){ Mirror[WARP_SPARKLE_Y] = y; }
  141.  
  142. int WarpSparkleScreen(){ return Mirror[WARP_SPARKLE_SCREEN]; }
  143. void WarpSparkleScreen(int screen){ Mirror[WARP_SPARKLE_SCREEN] = screen; }
  144.  
  145. //The following four functions are used to manipulate,a nd check the post-warp timer,
  146. //that prevents Link from being sent back by a sparkle as soon as he finishes warping.
  147.  
  148. int WarpReturnWait(){ return Mirror[MIRROR_POST_WARP_TIMER]; }
  149. void ReducePostWarpTimer(){ if ( Mirror[MIRROR_POST_WARP_TIMER] > 0 ) Mirror[MIRROR_POST_WARP_TIMER]--; }
  150. void SetPostWarpTimer(){ Mirror[MIRROR_POST_WARP_TIMER] = MIRROR_POST_WARP_TIMER_NUM_FRAMES; }
  151. void ClearPostWarpTimer(){ Mirror[MIRROR_POST_WARP_TIMER] = 0; }
  152.  
  153.  
  154. //Functions
  155.  
  156. //Checks the present DMap and returns irts counterpart.
  157. //!! You must set up the arrays inside this function, for it to work.
  158. int GetOtherworldlyDMap(int dmap){
  159.     int q[4];
  160.     int LightWorldDMaps[]={3,-1,-1,-1,-1}; //Populate these two arrays with the IDs of your light and dark world dmaps
  161.     int DarkWorldDMaps[]={8,-1,-1,-1,-1}; //in matched pairs.
  162.     for ( q[0] = 0; q[0] < SizeOfArray(LightWorldDMaps); q[0]++ ) {
  163.         q[1] = LightWorldDMaps[ q[0] ];
  164.         q[2] = DarkWorldDMaps[ q[0] ];
  165.         if ( dmap == q[1] ) return DarkWorldDMaps[ q[0] ];
  166.         if ( dmap == q[2] ) return LightWorldDMaps[ q[0] ];
  167.     }
  168.     return -1;
  169. }
  170.  
  171. //Returns if the present dmap is a dark world dmap
  172. //!! You must set up the arrays inside this function, for it to work.
  173. bool IsDarkWorld(){
  174.     int DarkWorldDMaps[]={8,-1,-1,-1,-1};
  175.     for ( int q = 0; q < SizeOfArray(DarkWorldDMaps); q++ ) {
  176.         if ( Game->GetCurDMap() == DarkWorldDMaps[q] ) return true;
  177.     }
  178.     return false;
  179. }
  180.  
  181. //Generates coordinates for the warp return sparkle.
  182. //this is set when we use the mirror.
  183. void SetWarpReturn(){
  184.     WarpSparkle(true);
  185.     WarpSparkleX(Link->X);
  186.     WarpSparkleY(Link->Y);
  187.     WarpSparkleDMap( GetOtherworldlyDMap( Game->GetCurDMap() ) );
  188.     WarpSparkleScreen(Game->GetCurScreen());
  189.     WarpSparkleReturn(Game->GetCurDMap());
  190. }
  191.  
  192. //Removes the warp sparkle, after using it.
  193. void ClearWarpSparkle(){
  194.     WarpSparkle(false);
  195.     WarpSparkleX(-100);
  196.     WarpSparkleY(-100);
  197.     WarpSparkleDMap(-1);
  198.     WarpSparkleScreen(-1);
  199.     WarpSparkleReturn(-1);
  200. }
  201.  
  202. //Returns if Link is in a dungeon based on the array dungeonDMaps[]
  203. //!! You must set up the array inside this function, for it to work.
  204. bool IsDungeonDMap(){
  205.     int dungeonDMaps[]={20,21,22};//List all dungeon DMaps here
  206.     for ( int q = 0; q < SizeOfArray(dungeonDMaps); q++ ) {
  207.         if ( Game->GetCurDMap() == dungeonDMaps[q] ) return true;
  208.         return false;
  209.     }
  210. }
  211.  
  212. //Returns if the warp destination is solid, prior to warping.
  213. bool ___WarpDestSolid(int x, int y, int screen, int map){
  214.     return ( Game->GetComboSolid(map, screen, ComboAt(x,y)) );
  215. }
  216.    
  217.  
  218. //A very precise way to check if the warp destination is solid, based on Link's standard hitbox.
  219. //Checks if any of Link's corners or axis positions are on a solid combo, and if a
  220. bool WarpDestSolid(){
  221.     if ( Screen->isSolid(Link->X+4, Link->Y) ||
  222.         Screen->isSolid(Link->X+8, Link->Y+8) ||
  223.         Screen->isSolid(Link->X+4, Link->Y+8) ||
  224.         Screen->isSolid(Link->X+8, Link->Y) ||
  225.         Screen->isSolid(Link->X+8, Link->Y+15) ||
  226.         Screen->isSolid(Link->X+15, Link->Y+8)  || 
  227.         Screen->isSolid(Link->X+15, Link->Y) ||
  228.         Screen->isSolid(Link->X+4, Link->Y+15) ||
  229.         Screen->isSolid(Link->X+15, Link->Y+15)) return true;
  230.     return false;
  231. }
  232. //! Main Functions to Call before Waitdraw()
  233.  
  234. //Handles the initial warp routines.
  235. void MirrorWarpLink() {
  236.     if ( IsWarping() ){
  237.         Link->X = Mirror[WARP_LINK_X];
  238.         Link->Y = Mirror[WARP_LINK_Y];
  239.         SetPostWarpTimer();
  240.         NoAction();
  241.         Game->PlaySound(SFX_WARP);
  242.         Link->PitWarp(GetOtherworldlyDMap(Game->GetCurDMap()), Game->GetCurScreen());
  243.         Screen->Wavy = WARP_WAVE_DUR;
  244.        
  245.         //Freeze all enemies and ghost scripts
  246.         for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY); q > 0; q--){
  247.             NoAction();
  248.             Waitframe();
  249.         }
  250.         //resume npcs and ghost scripts
  251.        
  252.         IsWarping(false);
  253.         //for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY) / 2; q > 0; q--){
  254.         //  NoAction();
  255.         //  Waitframe();
  256.         //}
  257.         AfterWarp(true);
  258.     }
  259.    
  260.     if (IsReturnWarping() ){
  261.         Mirror[WARP_LINK_HP] = Link->HP;
  262.  
  263.         Link->X = WarpSparkleX();
  264.         Link->Y = WarpSparkleY();
  265.         NoAction();
  266.        
  267.         Link->PitWarp(WarpSparkleReturn(), WarpSparkleScreen());
  268.         Game->PlaySound(SFX_WARP);
  269.         Screen->Wavy = WARP_WAVE_DUR;
  270.         //Freeze all enemies and ghost scripts
  271.         for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY); q > 0; q--){
  272.             NoAction();
  273.             Waitframe();
  274.         }
  275.         //resume npcs and ghost scripts
  276.        
  277.        
  278.         IsReturnWarping(false);
  279.         //for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY) / 2; q > 0; q--){
  280.         //  NoAction();
  281.         //  Waitframe();
  282.         //}
  283.         AfterReturnWarp(true);
  284.     }
  285. }
  286.  
  287. //Post-warp cleanup, and bounce.
  288. void WarpFinish() {
  289.     if (AfterWarp()){
  290.         if ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) Link->HitDir = -1;
  291.         //SetWarpReturn();
  292.         //If the destination is solid, send Link back.
  293.         if ( WarpDestSolid() ) {
  294.             ClearWarpSparkle();
  295.             Game->PlaySound(SFX_WARP_ERROR);
  296.             WaitNoAction();
  297.             Screen->Wavy = WARP_WAVE_DUR;
  298.             //freeze all enemies and ghost scripts.
  299.             for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY); q > 0; q--){
  300.                 NoAction();
  301.                 Waitframe();
  302.             }
  303.             //resume npcs and ghost scripts
  304.             Link->X = Mirror[WARP_LINK_X];
  305.             Link->Y = Mirror[WARP_LINK_Y];
  306.             Link->PitWarp(GetOtherworldlyDMap(Game->GetCurDMap()), Game->GetCurScreen());
  307.             //Screen->Wavy = WARP_WAVE_DUR;
  308.            
  309.             AfterWarp(false);
  310.             for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY); q > 0; q--){
  311.                 NoAction();
  312.                 Waitframe();
  313.             }
  314.         }
  315.         if ( Link->HP < Mirror[WARP_LINK_HP] && WARP_RETURNS_ON_INJURY) { //If Link is injured, send him back.
  316.             Link->HP = Mirror[WARP_LINK_HP];
  317.             Game->PlaySound(SFX_WARP);
  318.             Screen->Wavy = WARP_WAVE_DUR;
  319.             //freeze all enemies and ghost scripts.
  320.             for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY) / 2; q > 0; q--){
  321.                 NoAction();
  322.                 Waitframe();
  323.             }
  324.             //resume npcs and ghost scripts
  325.             Link->X = Mirror[WARP_LINK_X];
  326.             Link->Y = Mirror[WARP_LINK_Y];
  327.             Link->PitWarp(WarpSparkleReturn(), Game->GetCurScreen());
  328.  
  329.             Link->X = Mirror[WARP_LINK_X];
  330.             Link->Y = Mirror[WARP_LINK_Y];
  331.             Link->HP = Mirror[WARP_LINK_HP];
  332.            
  333.             AfterWarp(false);
  334.             for(int q = (WARP_WAVE_DUR + POST_WARP_DELAY) / 2; q > 0; q--){
  335.                 NoAction();
  336.                 Waitframe();
  337.             }
  338.         }
  339.         else {
  340.             Link->X = Mirror[WARP_LINK_X];
  341.             Link->Y = Mirror[WARP_LINK_Y];
  342.             //SetPostWarpTimer();
  343.             //Mirror[WARP_LINK_TEMP_INVULNERABILITY] = WARP_INVULNERABILITY_FRAMES;
  344.             AfterWarp(false);
  345.         }
  346.     }
  347.    
  348.     if (AfterReturnWarp()){
  349.         if ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) Link->HitDir = -1;
  350.         ClearWarpSparkle();
  351.         Mirror[WARP_LINK_TEMP_INVULNERABILITY] = WARP_INVULNERABILITY_FRAMES;
  352.         AfterReturnWarp(false);
  353.         ClearPostWarpTimer();
  354.            
  355.     }
  356.    
  357.     if ( POST_WARP_LINK_IS_INVINCIBLE ) {
  358.         if ( Mirror[WARP_LINK_TEMP_INVULNERABILITY] ) {
  359.             //If we find a way to Flicker Link, it goes here.
  360.             Link->CollDetection = false;
  361.             Mirror[WARP_LINK_TEMP_INVULNERABILITY]--;
  362.         }
  363.         if ( !Mirror[WARP_LINK_TEMP_INVULNERABILITY] ) Link->CollDetection = true;
  364.     }
  365.    
  366.     //if ( Mirror[MIRROR_POST_WARP_TIMER] > 0 ) Mirror[MIRROR_POST_WARP_TIMER]--;
  367. }
  368.  
  369.  
  370. //Creates the mirror return sparkle.
  371. void MirrorSparkle(){
  372.     if ( Game->GetCurDMap() == WarpSparkleDMap() && Game->GetCurScreen() == WarpSparkleScreen() ) {
  373.         Screen->DrawCombo(  MIRROR_SPARKLE_COMBO_LAYER, WarpSparkleX(), WarpSparkleY(),
  374.             MIRROR_SPARKLE_COMBO, MIRROR_SPARKLE_COMBO_H, MIRROR_SPARKLE_COMBO_W, MIRROR_SPARKLE_COMBO_CSET,
  375.             MIRROR_SPARKLE_COMBO_XSCALE, MIRROR_SPARKLE_COMBO_YSCALE, MIRROR_SPARKLE_COMBO_RX,
  376.             MIRROR_SPARKLE_COMBO_RY, MIRROR_SPARKLE_COMBO_RANGLE, Mirror[MIRROR_SPARKLE_COMBO_FRAME],
  377.             MIRROR_SPARKLE_COMBO_FLIP, true, MIRROR_SPARKLE_COMBO_OPACITY) ; //Mirror sparkle
  378.        
  379.         //Reduce the frames
  380.         if ( Mirror[MIRROR_SPARKLE_COMBO_FRAME] >= MIRROR_SPARKLE_COMBO_NUM_FRAMES ) Mirror[MIRROR_SPARKLE_COMBO_FRAME] = MIRROR_SPARKLE_COMBO_INIT_FRAME;
  381.         else Mirror[MIRROR_SPARKLE_COMBO_FRAME]++;
  382.            
  383.         if ( !WarpReturnWait() && !IsTempInvincible() ){
  384.            
  385.             if ( Abs( Link->X - WarpSparkleX()) < 8 && Abs(Link->Y - WarpSparkleY()) < 8 )
  386.             {
  387.                 //Reurn Link via the portal
  388.                 IsReturnWarping(true);
  389.             }
  390.         }
  391.     }
  392. }
  393.  
  394. bool IsTempInvincible(){
  395.     if ( Mirror[WARP_LINK_TEMP_INVULNERABILITY] && POST_WARP_LINK_IS_INVINCIBLE ) return true;
  396.     if ( !Mirror[WARP_LINK_TEMP_INVULNERABILITY] || !POST_WARP_LINK_IS_INVINCIBLE ) return false;
  397. }
  398.  
  399. void TestSparkle(){
  400.     int x = WarpSparkleX();
  401.     int y = WarpSparkleY();
  402.     if ( x < 0 ) x = 0;
  403.     if ( y < 0 ) y = 0;
  404.     Screen->DrawCombo(  MIRROR_SPARKLE_COMBO_LAYER, x, y,
  405.             MIRROR_SPARKLE_COMBO, MIRROR_SPARKLE_COMBO_H, MIRROR_SPARKLE_COMBO_W, MIRROR_SPARKLE_COMBO_CSET,
  406.             MIRROR_SPARKLE_COMBO_XSCALE, MIRROR_SPARKLE_COMBO_YSCALE, MIRROR_SPARKLE_COMBO_RX,
  407.             MIRROR_SPARKLE_COMBO_RY, MIRROR_SPARKLE_COMBO_RANGLE, Mirror[MIRROR_SPARKLE_COMBO_FRAME],
  408.             MIRROR_SPARKLE_COMBO_FLIP, true, MIRROR_SPARKLE_COMBO_OPACITY) ; //Mirror sparkle
  409.        
  410.         //Reduce the frames
  411.         if ( Mirror[MIRROR_SPARKLE_COMBO_FRAME] >= MIRROR_SPARKLE_COMBO_NUM_FRAMES ) Mirror[MIRROR_SPARKLE_COMBO_FRAME] = MIRROR_SPARKLE_COMBO_INIT_FRAME;
  412.         else Mirror[MIRROR_SPARKLE_COMBO_FRAME]++;
  413. }
  414.  
  415.  
  416. //Runs the moon pearl bunny sprite change, and halts using any item other than the mirror.
  417. void MoonPearl(){
  418.     if ( IsDarkWorld() && !Link->Item[I_MOONPEARL] && !Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = true;
  419.     if ( !IsDarkWorld() && Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = false;
  420.     if ( IsDarkWorld() && Link->Item[I_MOONPEARL] && Link->Item[I_BUNNYRING] ) Link->Item[I_BUNNYRING] = false;
  421.     if ( Link->Item[I_BUNNYRING] ) {
  422.         if ( Link->PressA && GetEquipmentA() != I_MIRROR ) Link->PressA = false;
  423.         if ( Link->PressB && GetEquipmentB() != I_MIRROR ) Link->PressB = false;
  424.     }
  425. }
  426.  
  427. /// Items
  428.  
  429. item script Mirror{
  430.     void run(){
  431.         int cmb[4];
  432.         cmb[0] = Screen->ComboT[ComboAt(Link->X+8, Link->Y+8)];
  433.         cmb[1] = GetLayerComboT(1,cmb[0]);
  434.         cmb[2] = GetLayerComboT(2,cmb[0]);
  435.         if ( IsDungeonDMap() && MIRROR_RETURNS_TO_DUNGEON_ENTRANCE ) {
  436.             //Warp to dungeon entrance.
  437.             Game->PlaySound(SFX_WARP_DUNGEON);
  438.             Screen->Wavy = WARP_WAVE_DUR_DUNGEON;
  439.             Link->Warp(Game->GetCurDMap(), Game->DMapContinue[Game->GetCurDMap()]);
  440.         }
  441.        
  442.        
  443.         else {
  444.             if ( IsDarkWorld() ) {
  445.                 for ( cmb[3] = 0; cmb[3] <= 3; cmb[3]++ ) {
  446.                     if ( cmb[ cmb[3] ] == CT_CAVE || cmb[ cmb[3] ] == CT_CAVE2 || cmb[ cmb[3] ] == CT_CAVEB
  447.                         || cmb[ cmb[3] ] == CT_CAVEC || cmb[ cmb[3] ] == CT_CAVED ||
  448.                         cmb[ cmb[3] ] == CT_CAVE2B || cmb[ cmb[3] ] == CT_CAVE2C ||cmb[ cmb[3] ] == CT_CAVE2D )
  449.                     {
  450.                         Game->PlaySound(SFX_WARP_ERROR);
  451.                         Quit();
  452.                     }
  453.                 }
  454.                 SetPostWarpTimer();
  455.                 //Mirror[MIRROR_POST_WARP_TIMER] = MIRROR_POST_WARP_TIMER_NUM_FRAMES;
  456.                 Mirror[WARP_LINK_X] = Link->X;
  457.                 Mirror[WARP_LINK_Y] = Link->Y;
  458.                 Mirror[WARP_LINK_HP] = Link->HP;
  459.                 SetWarpReturn();
  460.                 IsWarping(true);
  461.             }
  462.             //Warp to other world
  463.             if ( !IsDarkWorld() && SFX_WARP_ERROR ) Game->PlaySound(SFX_WARP_ERROR);
  464.         }
  465.     }
  466. }
  467.  
  468. //Global Script Example
  469.  
  470. global script Z3_Mirror{
  471.     void run(){
  472.         while(true){
  473.             if ( REQUIRE_MOON_PEARL ) MoonPearl();
  474.             ReducePostWarpTimer();
  475.             MirrorWarpLink();
  476.            
  477.             //if ( TEST_MIRROR_SPARKLE ) TestSparkle();
  478.             //if ( MIRROR_SPARKLE_BEFORE_WAITDRAW ) MirrorSparkle();
  479.             WarpFinish();
  480.             Waitdraw();
  481.            
  482.             //if ( !MIRROR_SPARKLE_BEFORE_WAITDRAW ) MirrorSparkle();
  483.             if ( WarpSparkle() ) MirrorSparkle(); //Call only if it exists.
  484.             Waitframe();
  485.         }
  486.     }
  487. }
  488.  
  489. //Deprecated
  490.  
  491. const int SOLIDITY_CHECK_DISTANCE = 8;
  492.  
  493. bool TouchingSolid(int x, int y) {
  494.     if ( Screen->isSolid(x,y) ||
  495.         Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y) ||
  496.         Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y+SOLIDITY_CHECK_DISTANCE) ||
  497.         Screen->isSolid(x + SOLIDITY_CHECK_DISTANCE, y-SOLIDITY_CHECK_DISTANCE) ||
  498.         Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y) ||
  499.         Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y+SOLIDITY_CHECK_DISTANCE) ||
  500.         Screen->isSolid(x - SOLIDITY_CHECK_DISTANCE, y-SOLIDITY_CHECK_DISTANCE) ) {
  501.         return true;
  502.     }
  503.     return false;
  504. }
  505.  
  506. bool TouchingSolid(){
  507.     if ( Screen->isSolid(Link->X,Link->Y) ||
  508.         Screen->isSolid(Link->X + 15, Link->Y) ||
  509.         Screen->isSolid(Link->X + 15, Link->Y+15) ||
  510.         Screen->isSolid(Link->X + 15, Link->Y-15) ||
  511.         Screen->isSolid(Link->X - 15, Link->Y) ||
  512.         Screen->isSolid(Link->X - 15, Link->Y+15) ||
  513.         Screen->isSolid(Link->X - 15, Link->Y-15) )
  514.     {
  515.         return true;
  516.     }
  517.     return false;
  518. }
  519.  
  520.  
  521.  
  522. //Cape
  523.  
  524.  
  525. void CapeOfInvisibility(){}
  526.  
  527.  
  528.  
  529. //if ( Mirror[CAPE_ON] ) {
  530. //  CapeCost();
  531. //  DoCape();
  532. //}
  533.  
  534. void DoCape(){
  535.     int scale = Rand(13,15);
  536.     int flip;
  537.     if ( Link->Dir == DIR_DOWN ) flip = 1;
  538.     else if ( Link->Dir == DIR_LEFT ) flip = 7;
  539.     else if ( Link->Dir == DIR_DOWN ) flip = ;
  540.     else flip = 0;
  541.     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);
  542. }
  543.  
  544. const int CAPE_SHADOW_LAYER = 2;
  545. const int CAPE_SHADOW_X_OFFSET = 0;
  546. const int CAPE_SHADOW_Y_OFFSET = 4;
  547. const int CAPE_SHADOW_TILE = 2001;
  548. const int CAPE_SHADOW_CSET = 0;
  549. const int CAPE_SHADOW_OPACITY = 64;
  550.  
  551.  
  552.  
  553.  
  554.  
  555. item script CapeOfInvisibility{
  556.     void run(){
  557.         if ( Mirror[CAPE_ON] ) { Mirror[CAPE_ON] = 0; }
  558.         else {
  559.             InitCapeTimer(); //Should we start at 0 to ensure a magic cost?
  560.             Mirror[CAPE_ON] = 1;
  561.         }
  562.     }
  563. }
  564.  
  565. void InitCapeTimer() { Mirror[CAPE_TIMER] = CAPE_MAGIC_USE_RATE; }
  566.  
  567.  
  568.  
  569. //! I need to include these, along with IsInvisible() and IsInvincible() to ensure that there ar eno comflicts between this and other cape/cane scripts.
  570.  
  571.  
  572.  
  573. const int CAPE_ON = 50;
  574.  
  575.  
  576.  
  577. const int CAPE_MAGIC_COST = 3; //Cost per rate
  578. const int CAPE_MAGIC_USE_RATE = 50; //frames per cost unit
  579.  
  580.  
  581.  
  582. //cAPE ARRAY INDICES
  583. const int CAPE_TIMER = 60;
  584. const int CAPE_SHADOW_WAVER_TIMER = 61;
  585.  
  586.  
  587. //Cape Settingds
  588. const int CAPE_SHADOW_TILE = 2100;
  589.  
  590. /////////////////////
  591. /// Cane of Byrna ///
  592. /////////////////////
  593.  
  594. void InitByrnaTimer() { Mirror[BYRNA_TIMER] = BYRNA_MAGIC_USE_RATE; }
  595.  
  596. void ByrnaCost(){
  597.     if ( Mirror[BYRNA_TIMER] > 0 ) Mirror[BYRNA_TIMER]--;
  598.     if ( Mirror[BYRNA_TIMER] <= 0 ) {
  599.         Game->MCounter[CR_MAGIC] -= ( CAPE_MAGIC_COST * Game->Generic[GEN_MAGICDRAINRATE]; //Allow half magic
  600.         InitByrnaTimer();
  601.     }
  602. }
  603.  
  604.  
  605. //Byrna Array Indices
  606. const int BYRNA_ON = 51;
  607.  
  608. const int BYRNA_TIMER = 70;
  609.  
  610. //The true z3 cane has only one orbit
  611. const int BYRNA_BEAM_SPRITE         = 80;
  612. const int BYRNA_BEAM_1_ORBIT_X      = 81;
  613. const int BYRNA_BEAM_1_ORBIT_Y      = 82;
  614. const int BYRNA_BEAM_1_ORBIT_CX     = 83;
  615. const int BYRNA_BEAM_1_ORBIT_CY     = 84;
  616. const int BYRNA_BEAM_1_ORBIT_VELOCITY   = 85;
  617. const int BYRNA_BEAM_1_ORBIT_ANG1   = 86;
  618. const int BYRNA_BEAM_1_ORBIT_ANG2   = 87;
  619. const int BYRNA_BEAM_1_ORBIT_RADIUS     = 88;
  620. const int BYRNA_BEAM_1_ORBIT_RADIUS2    = 89;
  621. const int BYRNA_BEAM_1_ORBIT_FRAME  = 90;
  622. const int BYRNA_ORBIT_SOUND_TIMER   = 91;
  623.  
  624. void ByrnaSound(){
  625.     if ( Mirror[BYRNA_ORBIT_SOUND_TIMER] > 0 ) Mirror[BYRNA_ORBIT_SOUND_TIMER]--;
  626.     else {
  627.         Mirror[BYRNA_ORBIT_SOUND_TIMER] = BYRNA_ORBIT_SOUND_LOOP_TIME;
  628.         if ( SFX_BYRNA_ORBIT ) Game->PlaySound(SFX_BYRNA_ORBIT);
  629.     }
  630. }
  631.  
  632.  
  633. //const int BYRNA_BEAM_2_ORBIT_X        = 86;
  634. //const int BYRNA_BEAM_2_ORBIT_Y        = 87;
  635. //const int BYRNA_BEAM_2_ORBIT_VELOCITY     = 88;
  636. //const int BYRNA_BEAM_2_ORBIT_SIN  = 89;
  637. //const int BYRNA_BEAM_2_ORBIT_COSIN    = 90;
  638.  
  639. //const int BYRNA_BEAM_3_ORBIT_X        = 91;
  640. //const int BYRNA_BEAM_3_ORBIT_Y        = 92;
  641. //const int BYRNA_BEAM_3_ORBIT_VELOCITY     = 93;
  642. //const int BYRNA_BEAM_3_ORBIT_SIN  = 94;
  643. //const int BYRNA_BEAM_3_ORBIT_COSIN    = 95;
  644.  
  645. //const int BYRNA_BEAM_4_ORBIT_X        = 96;
  646. //const int BYRNA_BEAM_4_ORBIT_Y        = 97;
  647. //const int BYRNA_BEAM_4_ORBIT_VELOCITY     = 98;
  648. //const int BYRNA_BEAM_4_ORBIT_SIN  = 99;
  649. //const int BYRNA_BEAM_4_ORBIT_COSIN    = 100;
  650.  
  651. const int BYRNA_COST = 4;
  652. const int BYRNA_MAGIC_USE_RATE = 120; //frames per unit of cost
  653.  
  654. const int WDS_BYRNABLOCKED = 0; //Deadstate for eweapons blocked by the byrna beam.
  655. const int BYRNA_BEAMS_REFLECT_WEAPONS = 1;
  656. const int BYRNA_DAMAGE = 2;
  657. const int LW_CUSTOMBYRNA = 20; //The weapon type to spoof.
  658.  
  659. const int BYRNA_NUM_ORBITS = 1;
  660.  
  661. const int BYRNA_ORBIT_RADIUS = 40;
  662. const int BYRNA_ORBIT_SPEED = 120;
  663. const int BYRNA_ORBIT_COMBO = 2002;
  664. const int BYRNA_ORBIT_NUM_FRAMES = 4;
  665. const int BYRNA_ORBIT_COMBO_LAYER = 6;
  666. const int BYRNA_ORBIT_COMBO_H = 1;
  667. const int BYRNA_ORBIT_COMBO_W = 1;
  668. const int BYRNA_ORBIT_COMBO_CSET = 0;
  669. const int BYRNA_ORBIT_COMBO_RY = 0;
  670. const int BYRNA_ORBIT_COMBO_RX = 0;
  671. const int BYRNA_ORBIT_COMBO_RANGLE = 0;
  672. const int BYRNA_ORBIT_COMBO_FLIP = 0;
  673. const int BYRNA_ORBIT_COMBO_OPACITY = 128;
  674. const int BYRNA_ORBIT_COMBO_XSCALE = -1;
  675. const int BYRNA_ORBIT_COMBO_YSCALE = -1;
  676. const int BYRNA_ORBIT_INIT_FRAME = 1;
  677.  
  678.  
  679. const int SFX_BYRNA_ON = 63;
  680. const int SFX_BYRNA_OFF = 64;
  681. const int SFX_BYRNA_ORBIT = 65;
  682. const int BYRNA_ORBIT_SOUND_LOOP_TIME = 90;
  683.  
  684. //Handles the cost calcs.
  685. void ByrnaCost(){
  686.     if ( Mirror[BYRNA_TIMER] > 0 ) Mirror[BYRNA_TIMER]--;
  687.     if ( Mirror[BYRNA_TIMER] <= 0 ) {
  688.         Game->MCounter[CR_MAGIC] -= ( CAPE_MAGIC_COST * Game->Generic[GEN_MAGICDRAINRATE]; //Allow half magic
  689.         InitByrnaTimer();
  690.     }
  691. }
  692.  
  693.  
  694. //Prime the vars for orbiting. Call this only from the item script, when enabling.
  695. void InitByrna(){
  696.     Mirror[BYRNA_BEAM_1_ORBIT_RADIUS] = BYRNA_ORBIT_RADIUS;
  697.     Mirror[BYRNA_BEAM_1_ORBIT_VELOCITY] = BYRNA_ORBIT_SPEED;
  698.     if ( Mirror[BYRNA_BEAM_1_ORBIT_RADIUS2] == 0 ) Mirror[BYRNA_BEAM_1_ORBIT_RADIUS2] = Mirror[BYRNA_BEAM_1_ORBIT_RADIUS]; //Circle
  699.         if ( Mirror[BYRNA_BEAM_1_ORBIT_ANG1] < 0 ) Mirror[BYRNA_BEAM_1_ORBIT_ANG1] = Rand(360); //Random Start
  700.         Mirror[BYRNA_BEAM_1_ORBIT_CX] = Mirror[BYRNA_BEAM_1_ORBIT_X];
  701.         Mirror[BYRNA_BEAM_1_ORBIT_CY] = Mirror[BYRNA_BEAM_1_ORBIT_Y];
  702. }
  703.  
  704.  
  705.  
  706. //Call before Waitdraw to make the orbits, as if ( Mirror[BYRNA_ON] ) DoByrna();
  707. void DoByrna(){
  708.  
  709.     int q[8];  
  710.    
  711.     Mirror[BYRNA_BEAM_1_ORBIT_ANG1] += Mirror[BYRNA_BEAM_1_ORBIT_VELOCITY];
  712.     if ( Mirror[BYRNA_BEAM_1_ORBIT_ANG1] < -360) Mirror[BYRNA_BEAM_1_ORBIT_ANG1] += 360; //Wraping happens
  713.     else if ( Mirror[BYRNA_BEAM_1_ORBIT_ANG1] > 360) Mirror[BYRNA_BEAM_1_ORBIT_ANG1] -= 360;
  714.            
  715.     Mirror[BYRNA_BEAM_1_ORBIT_X] = Mirror[BYRNA_BEAM_1_ORBIT_CX] + VectorX(Mirror[BYRNA_BEAM_1_ORBIT_RADIUS],
  716.         Mirror[BYRNA_BEAM_1_ORBIT_ANG1]);
  717.  
  718.     Mirror[BYRNA_BEAM_1_ORBIT_Y] = Mirror[BYRNA_BEAM_1_ORBIT_CY] + VectorY(Mirror[BYRNA_BEAM_1_ORBIT_RADIUS2],
  719.         Mirror[BYRNA_BEAM_1_ORBIT_ANG1]);
  720.     //Create the beams and have them orbit Link
  721.     //track their positions in Misc indices
  722.     Screen->DrawCombo(  BYRNA_ORBIT_COMBO_LAYER, Mirror[BYRNA_BEAM_1_ORBIT_X], Mirror[BYRNA_BEAM_1_ORBIT_Y],
  723.             BYRNA_ORBIT_COMBO, BYRNA_ORBIT_COMBO_H, BYRNA_ORBIT_COMBO_W, BYRNA_ORBIT_COMBO_CSET,
  724.             BYRNA_ORBIT_COMBO_XSCALE, BYRNA_ORBIT_COMBO_YSCALE, BYRNA_ORBIT_COMBO_RX,
  725.             BYRNA_ORBIT_COMBO_RY, BYRNA_ORBIT_COMBO_RANGLE, Mirror[BYRNA_BEAM_1_ORBIT_FRAME],
  726.             BYRNA_ORBIT_COMBO_FLIP, true, BYRNA_ORBIT_COMBO_OPACITY) ; //Mirror sparkle
  727.        
  728.     //Reduce the frames
  729.     if ( Mirror[BYRNA_BEAM_1_ORBIT_FRAME] >= BYRNA_ORBIT_NUM_FRAMES ) Mirror[BYRNA_BEAM_1_ORBIT_FRAME] = BYRNA_ORBIT_INIT_FRAME;
  730.     else Mirror[BYRNA_BEAM_1_ORBIT_FRAME]++;
  731.    
  732.        
  733.     //No, wait, the beams need to be drawn tiles and we need TileCollision.
  734.    
  735.     q[4] = Screen->NummNPCs(); q[5] = Screen->NumEWeapons();
  736.     //int loops = Max(npcs,
  737.     for ( q[0] = Max(q[4], q[5]); q > 0; q-- ) {
  738.         if ( q[0] < q[4] ) npc n = Screen->LoadNPC(q[0]);
  739.         if ( q[0] < q[5] ) eweapon e = Screen->LoadEWeapon(q[0]);
  740.         for ( q[1] = 0; q[1] < BYRNA_NUM_ORBITS; q[1]++ ) { //for each beam
  741.            
  742.             if ( q[0] < q[4] ) {
  743.                 if ( Abs( n->X - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 && Abs(n->Y - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 )
  744.                 {
  745.                     beam[ q[0] ] = Screen->CreateLWeapon(LW_CUSTOMBYRNA);
  746.                     beam[ q[0] ]-> X = n->X;
  747.                     beam[ q[0] ]-> Y = n->Y; //Spawn a weapon n the npc
  748.                     beam[ q[0] ]->Damage = BYRNA_DAMAGE;
  749.                 }
  750.             }
  751.             if ( q[0] < q[5] ) {   
  752.                 if ( Abs( e->X - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 && Abs(e->Y - Mirror[BYRNA_BEAM_1_ORBIT_X]) < 8 )
  753.                 {
  754.                     //block/reflect
  755.                     if ( BYRNA_BEAMS_REFLECT_WEAPONS ) ReflectWeapon(e);
  756.                     else e->DeasDtate = WDS_BYRNABLOCKED:
  757.                 }
  758.             }
  759.         }
  760.     }
  761.    
  762. }
  763.  
  764. item script CaneOfByrna{
  765.     void run(){
  766.         if ( Mirror[BYRNA_ON] ) { Mirror[BYRNA_ON] = 0; }
  767.         else { InitByrna(); Mirror[BYRNA_ON] = 1; }
  768.     }
  769. }
  770.  
  771. //The main byrna function. Call directly, prior to Waitdraw();
  772. void CaneOfByrna(){ ByrnaCost(); DoByrna(); ByrnaSound();}
  773.  
  774.  
  775.  
  776.  
  777. bool IsInvisible(){
  778.     if ( Mirror[CAPE_ON] ) return true;
  779.     return false;
  780. }
  781.  
  782. bool IsInvincible(){
  783.     if ( Mirror[BYRNA_ON] || Mirror[WARP_LINK_TEMP_INVULNERABILITY] ) return true;
  784.     return false;
  785. }
  786.  
  787. void HandleInvisibilityAndInvincibility(){
  788.     if ( IsInvisible() ) Link->Invisible = true;
  789.     else Link->Invisible = false;
  790.     if ( IsInvincible() ) Link->CollDetection = false;
  791.     else Link->CollDetection = true;
  792. }
  793.  
  794. //! We can tighten this down baed on Link's proximity to the grid.
  795. bool LinkTouchingSolidCombo(){
  796.     int cmb[6];
  797.     cmb[0] = ComboAt(Link->X, Link->Y);
  798.     cmb[1] = ____AdjacentCombo(cmb,3);
  799.     cmb[2] = ____AdjacentCombo(cmb,5);
  800.     cmb[3] = ____AdjacentCombo(cmb,4);
  801.     for ( cmb[4] = 0; cmb[4] <= 2; cmb[4]++ ) {
  802.         for ( cmb[5] = 0; cmb[5] <= 4; cmb[5]++ ) {
  803.             if ( GetLayerComboS(cmb[4], cmb[ cmb[5] ]) > 0 ) return true;
  804.         }
  805.     }
  806. }
  807.  
  808.  
  809. //Constants for AdjacentCombo()
  810.  
  811. //const int CMB_UPLEFT    = 0;
  812. //const int CMB_UP        = 1;
  813. //const int CMB_UPRIGHT   = 2;
  814. //const int CMB_RIGHT     = 3;
  815. //const int CMB_DOWNRIGHT = 4;
  816. //const int CMB_DOWN      = 5;
  817. //const int CMB_DOWNLEFT  = 6;
  818. //const int CMB_LEFT      = 7;
  819. //const int CMB_LEFTUP    = 0; //Not 8, as those are dir + shield
  820.  
  821. //Returns the Nuth combo index of a combo based on a central point, and a direction.
  822. //For example, combo 22 + COMBO_UPRIGHT returns '7',
  823. //as combo 7 is to the upper-right of combo 22.
  824. int ____AdjacentCombo(int cmb, int dir){
  825.     int combooffsets[13]={-0x10,-0x0F,-0x0E,1,0x10,0x0F,0x0E,-1,-0x10};
  826.     if ( cmb % 16 == 0 ) combooffsets[9] = 1;
  827.     if ( (cmb & 15) == 1 ) combooffsets[10] = 1;
  828.     if ( cmb < 0x10 ) combooffsets[11] = 1;
  829.     if ( cmb < 0xAF ) combooffsets[12] = 1;
  830.     if ( combooffsets[9] && ( dir == CMB_LEFT || dir == CMB_UPLEFT || dir == CMB_DOWNLEFT || dir == CMB_LEFTUP ) ) return 0;
  831.     if ( combooffsets[10] && ( dir == CMB_RIGHT || dir == CMB_UPRIGHT || dir == CMB_DOWNRIGHT ) ) return 0;
  832.     if ( combooffsets[11] && ( dir == CMB_UP || dir == CMB_UPRIGHT || dir == CMB_UPLEFT || dir == CMB_DOWNLEFT ) ) return 0;
  833.     if ( combooffsets[12] && ( dir == CMB_DOWN || dir == CMB_DOWNRIGHT || dir == CMB_DOWNLEFT ) ) return 0;
  834.     else if ( cmb > 0 && cmb < 177 ) return cmb + combooffsets[dir];
  835.     else return 0;
  836. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement