Advertisement
ZoriaRPG

Zaxarone: Fixed Shields

May 19th, 2017
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 43.90 KB | None | 0 0
  1. import "std.zh"
  2. import "string.zh"
  3. import "ghost.zh"
  4. import "ffcscript.zh"
  5. import "stdextra.zh"
  6. import "laser.zh"
  7. //global constants, arrays etc, etc...
  8. const int SFX_GBSHIELD = 17; //Shield active SFX
  9.  
  10. //Arrays -Z: Needs new save for this version.
  11. int ___GRAM[1024]; //Global RAM
  12. bool Owns[256];
  13.  
  14. //Array Index Constants.
  15. const int SHIELD_BUTTON = 500; //Array Index
  16. const int SHIELD_USES_L = 1;
  17. const int SHIELD_USES_R = 2;
  18. const int SHIELD_CRRENT_ITEM = 501;
  19.  
  20.  
  21. int MooshPit[16];
  22. const int MP_LASTX = 0;
  23. const int MP_LASTY = 1;
  24. const int MP_LASTDMAP = 2;
  25. const int MP_LASTSCREEN = 3;
  26. const int MP_ENTRYX = 4;
  27. const int MP_ENTRYY = 5;
  28. const int MP_ENTRYDMAP = 6;
  29. const int MP_ENTRYSCREEN = 7;
  30. const int MP_FALLX = 8;
  31. const int MP_FALLY = 9;
  32. const int MP_FALLTIMER = 10;
  33. const int MP_FALLSTATE = 11;
  34. const int MP_DAMAGETYPE = 12;
  35.  
  36. const int CT_HOLELAVA = 128; //Combo type for pits (No Ground Enemies by default)
  37. const int CF_LAVA = 98; //Combo flag marking pits as lava (Script 1 by default)
  38.  
  39. const int SPR_FALLHOLE = 88; //Sprite for Link falling in a hole
  40. const int SPR_FALLLAVA = 89; //Sprite for Link falling in lava
  41.  
  42. const int SFX_FALLHOLE = 38; //Sound for falling in a hole
  43. const int SFX_FALLLAVA = 13; //Sound for falling in lava
  44.  
  45. const int DAMAGE_FALLHOLE = 8; //How much damage pits deal (1/2 heart default)
  46. const int DAMAGE_FALLLAVA = 16; //How much damage lava deals (1 heart default)
  47.  
  48. const int FFC_MOOSHPIT_AUTOWARPA = 32; //FFC that turns into an auto side warp combo when you fall in a pit
  49. const int CMB_MOOSHPIT_AUTOWARPA = 2; //Combo number of an invisible Auto Side Warp A combo
  50. const int SF_MISC_MOOSHPITWARP = 2; //Number of the screen flag under the Misc. section that makes pits warp (Script 1 by default)
  51.                                     //All pit warps use Side Warp A
  52.                                
  53. //Width and height of Link's hitbox for colliding with pits
  54. const int MOOSHPIT_LINKHITBOXWIDTH = 2;
  55. const int MOOSHPIT_LINKHITBOXHEIGHT = 2;
  56.  
  57. //Width and height of Link's hitbox for colliding with pits/lava in sideview
  58. const int MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH = 2;
  59. const int MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT = 2;
  60.  
  61.  
  62. //moosh pit constsants
  63. global script Active{
  64.     void run(){
  65.     bool shieldOn;
  66.         StartGhostZH();
  67.         MooshPit_Init();
  68.        
  69.         while(true){
  70.             DoShield( CurShield() );
  71.             UpdateGhostZH1();
  72.             MooshPit_Update();
  73.             Waitdraw();
  74.             UpdateGhostZH2();
  75.             Waitframe();
  76.         }
  77.     }
  78. }
  79.  
  80. //global funtions go here
  81.  
  82.  
  83. //Sets the btton sed by the shield.
  84. void ShieldButton(int button){
  85.     ___GRAM[SHIELD_BUTTON] = button;
  86. }
  87.  
  88. //Gets crrent shield btton.
  89. int ShieldButton(){ return ___GRAM[SHIELD_BUTTON]; }
  90.  
  91. //Checks if the player is pressing a button for a shield.
  92. bool PressShield(){
  93.     if ( ( ShieldButton()== SHIELD_USES_L && Link->InputL ) || ( ShieldButton() == SHIELD_USES_R && Link->InputR ) ) { return true; }
  94.     return false;
  95. }
  96.  
  97. //Checks or sets the current shield item.
  98. int CurShield(){ return ___GRAM[SHIELD_CRRENT_ITEM]; }
  99. void CurShield(int itm){ ___GRAM[SHIELD_CRRENT_ITEM] = itm; }
  100.  
  101. //Runs shield on button press.
  102. void DoShield(int itm){
  103.     if ( PressShield() && !Link->Item[itm] ) { Link->Item[itm] = true; Game->PlaySound(SFX_GBSHIELD); }
  104.     if ( !PressShield() && Link->Item[itm] ) { Link->Item[itm] = false; Game->PlaySound(SFX_GBSHIELD); }
  105. }
  106.  
  107.  
  108. bool Owns(int itm){ return Owns[itm]; }
  109.  
  110. bool MooshPit_OnPit(int LinkX, int LinkY){
  111.     if(MooshPit_OnFFC(LinkX, LinkY)){
  112.         return false;
  113.     }
  114.    
  115.     bool sideview;
  116.     if(Screen->Flags[SF_ROOMTYPE]&100b)
  117.         sideview = true;
  118.     //wew lad
  119.     int width = MOOSHPIT_LINKHITBOXWIDTH;
  120.     int height = MOOSHPIT_LINKHITBOXHEIGHT;
  121.     for(int x=0; x<=1; x++){
  122.         for(int y=0; y<=1; y++){
  123.             int X; int Y;
  124.             if(sideview){ //Hitbox functions differently in sideview
  125.                 width = MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH;
  126.                 height = MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT;
  127.                 X = LinkX+7-width/2+width;
  128.                 Y = LinkY+7-height/2+height;
  129.             }
  130.             else{
  131.                 X = LinkX+7-width/2+width;
  132.                 Y = LinkY+11-height/2+height;
  133.             }
  134.            
  135.             //If one corner of Link's hitbox isn't on a pit, return false
  136.             if(Screen->ComboT[ComboAt(X, Y)]!=CT_HOLELAVA){
  137.                 return false;
  138.             }
  139.         }
  140.     }
  141.     return true;
  142. }
  143.  
  144. bool MooshPit_OnFFC(int LinkX, int LinkY){
  145.     for(int i=1; i<=32; i++){ //Cycle through every FFC
  146.         ffc f = Screen->LoadFFC(i);
  147.         //Check if the FFC is solid
  148.         if(f->Data>0&&!f->Flags[FFCF_CHANGER]&&!f->Flags[FFCF_ETHEREAL]){
  149.             //Check if Link collides with the FFC
  150.             if(RectCollision(LinkX+4, LinkY+9, LinkX+11, LinkY+14, f->X, f->Y, f->X+f->EffectWidth-1, f->Y+f->EffectHeight-1)){
  151.                 return true;
  152.             }
  153.         }
  154.     }
  155.     //If Link doesn't collide with any FFC, return false
  156.     return false;
  157. }
  158.  
  159. void MooshPit_Init(){
  160.     MooshPit[MP_LASTX] = Link->X;
  161.     MooshPit[MP_LASTY] = Link->Y;
  162.     MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
  163.     MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
  164.     MooshPit[MP_ENTRYX] = Link->X;
  165.     MooshPit[MP_ENTRYY] = Link->Y;
  166.     MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
  167.     MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  168.     MooshPit[MP_FALLSTATE] = 0;
  169.     MooshPit[MP_FALLTIMER] = 0;
  170.     Link->CollDetection = true;
  171.     Link->Invisible = false;
  172. }
  173.  
  174. void MooshPit_Update(){
  175.     bool isWarp;
  176.     if(Screen->Flags[SF_MISC]&(1<<SF_MISC_MOOSHPITWARP))
  177.         isWarp = true;
  178.    
  179.     bool sideview;
  180.     if(Screen->Flags[SF_ROOMTYPE]&100b)
  181.         sideview = true;
  182.    
  183.     if(Link->Action!=LA_SCROLLING){
  184.         //Update the entry point whenever the screen changes
  185.         if(MooshPit[MP_ENTRYDMAP]!=Game->GetCurDMap()||MooshPit[MP_ENTRYSCREEN]!=Game->GetCurDMapScreen()){
  186.             MooshPit[MP_ENTRYX] = Link->X;
  187.             MooshPit[MP_ENTRYY] = Link->Y;
  188.             MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
  189.             MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  190.         }
  191.        
  192.         if(MooshPit[MP_FALLSTATE]==0){ //Not falling in pit
  193.             if(Link->Z<=0&&MooshPit_OnPit(Link->X, Link->Y)){ //If Link steps on a pit
  194.                 int underLink;
  195.                 if(!sideview)
  196.                     underLink = ComboAt(Link->X+8, Link->Y+12);
  197.                 else
  198.                     underLink = ComboAt(Link->X+8, Link->Y+8);
  199.            
  200.                 lweapon fall;
  201.                
  202.                 Link->X = ComboX(underLink);
  203.                 Link->Y = ComboY(underLink);
  204.                
  205.                 //Check if the combo is lava
  206.                 if(ComboFI(underLink, CF_LAVA)){
  207.                     //Play sound and display animation
  208.                     Game->PlaySound(SFX_FALLLAVA);
  209.                     fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  210.                     fall->UseSprite(SPR_FALLLAVA);
  211.                     fall->CollDetection = false;
  212.                     fall->DeadState = fall->ASpeed*fall->NumFrames;
  213.                
  214.                     //Mark as lava damage
  215.                     MooshPit[MP_DAMAGETYPE] = 1;
  216.                 }
  217.                 //Otherwise it's a pit
  218.                 else{
  219.                     //Play sound and display animation
  220.                     Game->PlaySound(SFX_FALLHOLE);
  221.                     fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  222.                     fall->UseSprite(SPR_FALLHOLE);
  223.                     fall->CollDetection = false;
  224.                     fall->DeadState = fall->ASpeed*fall->NumFrames;
  225.                
  226.                     //Mark as hole damage
  227.                     MooshPit[MP_DAMAGETYPE] = 0;
  228.                 }
  229.                
  230.                 MooshPit[MP_FALLX] = Link->X;
  231.                 MooshPit[MP_FALLY] = Link->Y;
  232.                
  233.                 //Cooldown should last as long as the fall animation
  234.                 MooshPit[MP_FALLSTATE] = 1;
  235.                 MooshPit[MP_FALLTIMER] = fall->DeadState;
  236.                
  237.                 //Render Link invisible and intangible
  238.                 Link->Invisible = true;
  239.                 Link->CollDetection = false;
  240.                
  241.                 NoAction();
  242.             }
  243.             else{ //All other times, while Link is on solid ground, record Link's last position
  244.                 if(sideview){
  245.                     //Link has no Z value in sideview, so we check if he's on a platform instead
  246.                     if(OnSidePlatform(Link->X, Link->Y)){
  247.                         MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
  248.                         MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
  249.                         MooshPit[MP_LASTX] = Link->X;
  250.                         MooshPit[MP_LASTY] = Link->Y;
  251.                     }
  252.                 }
  253.                 else{
  254.                     if(Link->Z<=0){
  255.                         MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
  256.                         MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
  257.                         MooshPit[MP_LASTX] = Link->X;
  258.                         MooshPit[MP_LASTY] = Link->Y;
  259.                     }
  260.                 }
  261.             }
  262.         }
  263.         else if(MooshPit[MP_FALLSTATE]==1){ //Falling animation
  264.             if(MooshPit[MP_FALLTIMER]>0)
  265.                 MooshPit[MP_FALLTIMER]--;
  266.        
  267.             Link->Jump = 0;
  268.             Link->Z = 0;
  269.            
  270.             //Keep Link invisible just in case
  271.             Link->Invisible = true;
  272.             Link->CollDetection = false;
  273.             NoAction();
  274.             if(MooshPit[MP_FALLTIMER]==0){
  275.                 if(!isWarp||MooshPit[MP_DAMAGETYPE]==1){ //If the pit isn't a warp, deal damage and move Link back to the return point
  276.                     //If the entry would dump Link back in the pit, dump him out at the failsafe position
  277.                     if(MooshPit_OnPit(MooshPit[MP_ENTRYX], MooshPit[MP_ENTRYY])){
  278.                         Link->X = MooshPit[MP_LASTX];
  279.                         Link->Y = MooshPit[MP_LASTY];
  280.                         //If the failsafe position was on a different screen, warp there
  281.                         if(Game->GetCurDMap()!=MooshPit[MP_LASTDMAP]||Game->GetCurDMapScreen()!=MooshPit[MP_LASTSCREEN]){
  282.                             Link->PitWarp(MooshPit[MP_LASTDMAP], MooshPit[MP_LASTSCREEN]);
  283.                         }
  284.                
  285.                         Link->Invisible = false;
  286.                         Link->CollDetection = true;
  287.                     }
  288.                     else{
  289.                         //Move Link to the start and make him visible
  290.                         Link->X = MooshPit[MP_ENTRYX];
  291.                         Link->Y = MooshPit[MP_ENTRYY];
  292.                        
  293.                         Link->Invisible = false;
  294.                         Link->CollDetection = true;
  295.                     }
  296.                    
  297.                     //Subtract HP based on damage type
  298.                     if(MooshPit[MP_DAMAGETYPE]==1)
  299.                         Link->HP -= DAMAGE_FALLLAVA;
  300.                     else
  301.                         Link->HP -= DAMAGE_FALLHOLE;
  302.                     //Play hurt sound and animation
  303.                     Link->Action = LA_GOTHURTLAND;
  304.                     Link->HitDir = -1;
  305.                     Game->PlaySound(SFX_OUCH);
  306.                    
  307.                     MooshPit[MP_FALLSTATE] = 0;
  308.                 }
  309.                 else{
  310.                     MooshPit[MP_FALLSTATE] = 2;
  311.                     MooshPit[MP_FALLTIMER] = 1;
  312.                     ffc warp = Screen->LoadFFC(FFC_MOOSHPIT_AUTOWARPA);
  313.                     warp->Data = CMB_MOOSHPIT_AUTOWARPA;
  314.                     warp->Flags[FFCF_CARRYOVER] = false;
  315.                 }
  316.             }
  317.         }
  318.         else if(MooshPit[MP_FALLSTATE]==2){ //Just warped
  319.             if(sideview){
  320.                 Link->X = MooshPit[MP_FALLX];
  321.                 Link->Y = 0;
  322.             }
  323.             else{
  324.                 Link->X = MooshPit[MP_FALLX];
  325.                 Link->Y = MooshPit[MP_FALLY];
  326.                 Link->Z = 176;
  327.             }
  328.             Link->Invisible = false;
  329.             Link->CollDetection = true;
  330.            
  331.             MooshPit[MP_FALLSTATE] = 0;
  332.             MooshPit[MP_FALLTIMER] = 0;
  333.         }
  334.     }
  335. }
  336.  
  337. //ffc scripts------------------------------------------------------------------------------------------------------------@ffcs
  338. const int RESET_NPC_LAYER_ON_ENTRY = 1; //This fix will replace all CMB_NPC_SOLID tiles with CMB_NPC_HIDDEN
  339.                                         //when entering the screen. This should prevent problems with shared
  340.                                         //layers. If you don't want this fix, set it to 0.
  341.  
  342. const int LAYER_NPC = 2; //The layer NPCs use for solid combos
  343. const int CMB_NPC_HIDDEN = 4; //Non-solid combo used for hidden NPCs
  344. const int CMB_NPC_SOLID = 1; //Solid combo placed under visible NPCs
  345.  
  346. const int LAYER_NPC_CANTALK = 4; //The layer used for the speech bubble
  347. const int CMB_NPC_CANTALK = 0; //The combo used for the speech bubble
  348. const int CS_NPC_CANTALK = 8; //The CSet used for the speech bubble
  349.  
  350. const int NPCBT_NONE = 0; //Regular NPCs
  351. const int NPCBT_FACELINK = 1; //NPCs that turn to face Link
  352. const int NPCBT_GUARDH = 2; //NPCs that move along a horizontal path
  353. const int NPCBT_GUARDV = 3; //NPCs that move along a vertical path
  354.  
  355. ffc script NPCScript{
  356.     void run(int String, int ItemCheck, int Type, int Arg1, int Arg2, int NoSolid, int Script){
  357.         //Stores the NPC's combo, hides it
  358.         int Combo = this->Data;
  359.         this->Data = CMB_NPC_HIDDEN;
  360.         //Waits until the NPC should appear and shows it
  361.         if(ItemCheck<0){
  362.             while(!Link->Item[Abs(ItemCheck)]){
  363.                 Waitframe();
  364.             }
  365.             this->Data = Combo;
  366.             if(Type==NPCBT_FACELINK){
  367.                 this->Data = Combo + Arg1;
  368.             }
  369.         }
  370.         else if(ItemCheck>0){
  371.             if(!Link->Item[Abs(ItemCheck)]){
  372.                 this->Data = Combo;
  373.                 if(Type==NPCBT_FACELINK){
  374.                     this->Data = Combo + Arg1;
  375.                 }
  376.             }
  377.         }
  378.         else if(ItemCheck==0){
  379.             this->Data = Combo;
  380.             if(Type==NPCBT_FACELINK){
  381.                 this->Data = Combo + Arg1;
  382.             }
  383.         }
  384.         //Saves the width and height of the FFC for collision checks
  385.         int Width = 16;
  386.         int Height = 16;
  387.         if(this->EffectWidth!=16)
  388.             Width = this->EffectWidth;
  389.         else if(this->TileWidth>1)
  390.             Width = this->TileWidth*16;
  391.         if(this->EffectHeight!=16)
  392.             Height = this->EffectHeight;
  393.         else if(this->TileHeight>1)
  394.             Height = this->TileHeight*16;
  395.         //Wait until the screen is done scrolling to avoid a weird ZC crashing bug
  396.         Waitframe();
  397.         while(Link->Action==LA_SCROLLING){
  398.             Waitframe();
  399.         }
  400.         //Shared Layer Fix
  401.         if(RESET_NPC_LAYER_ON_ENTRY==1){
  402.             if(Screen->LoadFFC(FindFFCRunning(this->Script))==this){
  403.                 for(int i=0; i<176; i++){
  404.                     if(GetLayerComboD(LAYER_NPC, i)==CMB_NPC_SOLID){
  405.                         SetLayerComboD(LAYER_NPC, i, CMB_NPC_HIDDEN);
  406.                     }
  407.                 }
  408.             }
  409.         }
  410.         //Sets the space below the NPC or the space a guard NPC occupies to be solid
  411.         if(LAYER_NPC>-1&&NoSolid==0){
  412.             if(Type==NPCBT_GUARDH){
  413.                 for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
  414.                     for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  415.                         SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  416.                     }
  417.                 }
  418.             }
  419.             else if(Type==NPCBT_GUARDV){
  420.                 for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  421.                     for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
  422.                         SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  423.                     }
  424.                 }
  425.             }
  426.             else{
  427.                 for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  428.                     for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  429.                         SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  430.                     }
  431.                 }
  432.             }
  433.         }
  434.         while(true){
  435.             //Removes NPCs if Link has the required item
  436.             if(ItemCheck>0){
  437.                 if(Link->Item[ItemCheck]){
  438.                     this->Data = CMB_NPC_HIDDEN;
  439.                     if(LAYER_NPC>-1&&NoSolid==0){
  440.                         if(Type==NPCBT_GUARDH){
  441.                             for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
  442.                                 for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  443.                                     SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  444.                                 }
  445.                             }
  446.                         }
  447.                         else if(Type==NPCBT_GUARDV){
  448.                             for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  449.                                 for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
  450.                                     SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  451.                                 }
  452.                             }
  453.                         }
  454.                         else{
  455.                             for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  456.                                 for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  457.                                     SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  458.                                 }
  459.                             }
  460.                         }
  461.                     }
  462.                     Quit();
  463.                 }
  464.             }
  465.             //Handles animation for turning NPCs
  466.             if(Type==NPCBT_FACELINK&&(Link->X>0&&Link->X<240&&Link->Y>0&&Link->Y<160)){
  467.                 if(Distance(CenterLinkX(), CenterLinkY(), CenterX(this), CenterY(this))<Arg2)
  468.                     this->Data = Combo + AngleDir4(Angle(CenterX(this), CenterY(this), CenterLinkX(), CenterLinkY()));
  469.                 else
  470.                     this->Data = Combo + Arg1;
  471.             }
  472.             //Handles movement for guard NPCs
  473.             else if(Type==NPCBT_GUARDH){
  474.                 if(Link->X>16*Arg1-32&&Link->X<16*Arg2+32&&Link->Y>this->Y-32&&Link->Y<this->Y+32){
  475.                     this->X = Clamp(this->X+(-this->X + Link->X)/4, 16*Arg1, 16*Arg2);
  476.                 }
  477.             }
  478.             else if(Type==NPCBT_GUARDV){
  479.                 if(Link->X>this->X-32&&Link->X<this->X+32&&Link->Y>16*Arg1-32&&Link->Y<16*Arg2+32){
  480.                     this->Y = Clamp(this->Y+(-this->Y + Link->Y)/4, 16*Arg1, 16*Arg2);
  481.                 }
  482.             }
  483.             //Facing Up
  484.             if(Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  485.                 if(CMB_NPC_CANTALK>0)
  486.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  487.                 if(Link->PressA){
  488.                     Link->InputA = false;
  489.                     Link->PressA = false;
  490.                     Screen->Message(String);
  491.                     if(Script>0){
  492.                         RunFFCScript(Script, 0);
  493.                     }
  494.                 }
  495.             }
  496.             //Facing Down
  497.             else if(Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  498.                 if(CMB_NPC_CANTALK>0)
  499.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  500.                 if(Link->PressA){
  501.                     Link->InputA = false;
  502.                     Link->PressA = false;
  503.                     Screen->Message(String);
  504.                     if(Script>0){
  505.                         RunFFCScript(Script, 0);
  506.                     }
  507.                 }
  508.             }
  509.             //Facing Left
  510.             else if(Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
  511.                 if(CMB_NPC_CANTALK>0)
  512.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  513.                 if(Link->PressA){
  514.                     Link->InputA = false;
  515.                     Link->PressA = false;
  516.                     Screen->Message(String);
  517.                     if(Script>0){
  518.                         RunFFCScript(Script, 0);
  519.                     }
  520.                 }
  521.             }
  522.             //Facing Right
  523.             else if(Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
  524.                 if(CMB_NPC_CANTALK>0)
  525.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  526.                 if(Link->PressA){
  527.                     Link->InputA = false;
  528.                     Link->PressA = false;
  529.                     Screen->Message(String);
  530.                     if(Script>0){
  531.                         RunFFCScript(Script, 0);
  532.                     }
  533.                 }
  534.             }
  535.             Waitframe();
  536.         }
  537.     }
  538. }
  539.  
  540. ffc script NPCScript_Simple{
  541.     void run(int String, int Script, int D0, int D1, int D2, int D3, int D4, int D5){
  542.         //Saves the width and height of the FFC for collision checks
  543.         int Width = 16;
  544.         int Height = 16;
  545.         if(this->EffectWidth!=16)
  546.             Width = this->EffectWidth;
  547.         else if(this->TileWidth>1)
  548.             Width = this->TileWidth*16;
  549.         if(this->EffectHeight!=16)
  550.             Height = this->EffectHeight;
  551.         else if(this->TileHeight>1)
  552.             Height = this->TileHeight*16;
  553.         while(true){
  554.             //Facing Up
  555.             if(Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  556.                 if(CMB_NPC_CANTALK>0)
  557.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  558.                 if(Link->PressA){
  559.                     Link->InputA = false;
  560.                     Link->PressA = false;
  561.                     Screen->Message(String);
  562.                     if(Script>0){
  563.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  564.                         RunFFCScript(Script, Args);
  565.                     }
  566.                 }
  567.             }
  568.             //Facing Down
  569.             else if(Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  570.                 if(CMB_NPC_CANTALK>0)
  571.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  572.                 if(Link->PressA){
  573.                     Link->InputA = false;
  574.                     Link->PressA = false;
  575.                     Screen->Message(String);
  576.                     if(Script>0){
  577.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  578.                         RunFFCScript(Script, Args);
  579.                     }
  580.                 }
  581.             }
  582.             //Facing Left
  583.             else if(Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
  584.                 if(CMB_NPC_CANTALK>0)
  585.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  586.                 if(Link->PressA){
  587.                     Link->InputA = false;
  588.                     Link->PressA = false;
  589.                     Screen->Message(String);
  590.                     if(Script>0){
  591.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  592.                         RunFFCScript(Script, Args);
  593.                     }
  594.                 }
  595.             }
  596.             //Facing Right
  597.             else if(Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
  598.                 if(CMB_NPC_CANTALK>0)
  599.                     Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  600.                 if(Link->PressA){
  601.                     Link->InputA = false;
  602.                     Link->PressA = false;
  603.                     Screen->Message(String);
  604.                     if(Script>0){
  605.                         int Args[8] = {D0, D1, D2, D3, D4, D5};
  606.                         RunFFCScript(Script, Args);
  607.                     }
  608.                 }
  609.             }
  610.             Waitframe();
  611.         }
  612.     }
  613. }
  614.  
  615. const int D_TRADE = 0; //Screen->D value used for the trade sequence state
  616.  
  617. ffc script TradeSequence{
  618.     void run(int CheckItem, int TradeItem, int NoItemString, int HasItemString, int TradedString){
  619.         //Check if the player has already traded
  620.         if(Screen->D[D_TRADE]==0){
  621.             //If player hasn't traded and has the required item, play HasItemString, give the new item, and take the old item
  622.             if(Link->Item[CheckItem]){
  623.                 Screen->Message(HasItemString);
  624.                 WaitNoAction();
  625.                 item itm = CreateItemAt(TradeItem, Link->X, Link->Y);
  626.                 itm->Pickup = IP_HOLDUP;
  627.                 Link->Item[CheckItem] = false;
  628.                 Screen->D[D_TRADE] = 1;
  629.                 WaitNoAction();
  630.             }
  631.             //If player hasn't traded and doesn't have the required item, play NoItemString
  632.             else{
  633.                 Screen->Message(NoItemString);
  634.                 WaitNoAction();
  635.             }
  636.         }
  637.         //If the player has already traded, play TradedString
  638.         else{
  639.             Screen->Message(TradedString);
  640.             WaitNoAction();
  641.         }
  642.     }
  643. }
  644. // D0: Set this to 1 if you have a Normal Item set.
  645. // D1: Set this to 1 if you have a Special Item set.
  646. // D2: Set this to 1 if you have a Normal Chest set.
  647. // D3: Set this to 1 if you have a Locked Chest set.
  648. // D4: Set this to 1 if you have a Boss Chest set.
  649. const int COMPASS_SFX = 65;
  650. ffc script NyroxCompassBeep{
  651.      void run(int arg1, int arg2, int arg3, int arg4, int arg5){
  652.           if(GetLevelItem(LI_COMPASS)){
  653.                if(!Screen->State[ST_ITEM] && (arg1 == 1)){
  654.                     Game->PlaySound(COMPASS_SFX);
  655.                }
  656.                else if(!Screen->State[ST_SPECIALITEM]&& (arg2 == 1)){
  657.                     Game->PlaySound(COMPASS_SFX);
  658.                }
  659.                else if(!Screen->State[ST_CHEST]&& (arg3 == 1)){
  660.                     Game->PlaySound(COMPASS_SFX);
  661.                }
  662.                else if (!Screen->State[ST_LOCKEDCHEST] && (arg4 == 1)){
  663.                     Game->PlaySound(COMPASS_SFX);
  664.                }
  665.                else if(!Screen->State[ST_BOSSCHEST]&& (arg5 == 1)){
  666.                     Game->PlaySound(COMPASS_SFX);
  667.                }
  668.  
  669.           }
  670.      }
  671. }
  672.  
  673. //item scripts-----------------------------------------------------------------------------------------------------@Item
  674.  
  675. //Shield Pick-up. D0 is the message, D1 is the ID of this item.
  676. item script Zoria_Shield_Pickup{
  677.     void run(int msg, int item_id){
  678.         if ( msg > 0 ) { Screen->Message(msg); }
  679.         if ( item_id > 0 && item_id < 256 ) { Owns[item_id] = true; }
  680.         CurShield(item_id);
  681.     }
  682. }
  683.  
  684. //Modified to use new system. -Z
  685. item script gbshield{
  686.     void run ( int shield , int buttonsfx ){
  687.         CurShield(shield);
  688.         if ( ShieldButton() == SHIELD_USES_L ) { ShieldButton(SHIELD_USES_R); if ( buttonsfx > 0 ) Game->PlaySound(buttonsfx); }
  689.         else { ShieldButton(SHIELD_USES_L); if ( buttonsfx > 0 ) Game->PlaySound(buttonsfx); }
  690.     }
  691. }
  692.  
  693.  
  694. item script Message{
  695.     void run(int m){
  696.         Screen->Message(m);
  697.     }
  698. }
  699.  
  700. //enemy scirpts--------------------------------------------------------------------------------------------------@enemy
  701. //Three colors used for the lasers
  702. const int C_EZB_LASER1 = 0x77;
  703. const int C_EZB_LASER2 = 0x76;
  704. const int C_EZB_LASER3 = 0x7C;
  705.  
  706. const int SFX_EZB_TELEPORT = 66; //Sound when a boss teleports
  707. const int SFX_EZB_LASER = 37; //Sound when a laser is fired
  708.  
  709.  
  710. const int EZBF_4WAY         = 00000001b;
  711. const int EZBF_8WAY         = 00000010b;
  712. const int EZBF_FLYING       = 00000100b;
  713. const int EZBF_AQUATIC      = 00001000b;
  714. const int EZBF_NOFALL       = 00010000b;
  715. const int EZBF_EXPLODEEATH  = 00100000b;
  716. const int EZBF_FACELINK     = 01000000b;
  717. const int EZBF_UNBLOCKABLE  = 10000000b;
  718.  
  719. ffc script EZBoss{
  720.     void run(int enemyid){
  721.         int i; int j; int k; int angle; int dist; int x; int y;
  722.        
  723.         npc ghost = Ghost_InitAutoGhost(this, enemyid);
  724.        
  725.         int movementStyle = ghost->Attributes[0];
  726.         int attack1 = ghost->Attributes[1];
  727.         int attack2 = ghost->Attributes[2];
  728.         int attack3 = ghost->Attributes[3];
  729.         int special = ghost->Attributes[5];
  730.         int size = ghost->Attributes[6];
  731.         int fireSFX = ghost->Attributes[7];
  732.         int fireSPR = ghost->Attributes[8];
  733.         int flags = ghost->Attributes[9];
  734.        
  735.         int w = size&1111b;
  736.         int h = (size>>4)&1111b;
  737.         if(h==0)
  738.             h = w;
  739.         w = Clamp(w, 1, 4);
  740.         h = Clamp(h, 1, 4);
  741.            
  742.         int combo = ghost->Attributes[10];
  743.         Ghost_Transform(this, ghost, -1, -1, w, h);
  744.        
  745.         if(flags&EZBF_8WAY)
  746.             Ghost_SetFlag(GHF_8WAY);
  747.         else if(flags&EZBF_4WAY)
  748.             Ghost_SetFlag(GHF_4WAY);
  749.         if(flags&EZBF_NOFALL)
  750.             Ghost_SetFlag(GHF_NO_FALL);
  751.         if(flags&EZBF_FLYING){
  752.             Ghost_SetFlag(GHF_IGNORE_ALL_TERRAIN);
  753.             Ghost_SetFlag(GHF_FLYING_ENEMY);
  754.         }
  755.         else if(flags&EZBF_AQUATIC){
  756.             Ghost_SetFlag(GHF_WATER_ONLY);
  757.         }
  758.        
  759.         int stepCounter = -1;
  760.         int attackCooldown = ghost->Haltrate*10;
  761.         int stepAngle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  762.         int vX; int vY;
  763.        
  764.         if(movementStyle==4){
  765.             angle = Rand(360);
  766.             vX = VectorX(ghost->Step/100, angle);
  767.             vY = VectorY(ghost->Step/100, angle);
  768.         }
  769.        
  770.         while(true){
  771.             bool attackCond = false;
  772.             //Handle Movement
  773.             if(movementStyle==0){ //4 Way Halting Walk
  774.                 stepCounter = Ghost_HaltingWalk4(stepCounter, ghost->Step, ghost->Rate, ghost->Homing, ghost->Hunger, ghost->Haltrate, 48);
  775.                 if(stepCounter==16)
  776.                     attackCond = true;
  777.             }
  778.             else if(movementStyle==1){ //4 Way Constant Walk
  779.                 stepCounter = Ghost_ConstantWalk4(stepCounter, ghost->Step, ghost->Rate, ghost->Homing, ghost->Hunger);
  780.                 if(attackCooldown>0)
  781.                     attackCooldown--;
  782.                 else if(Rand(24)==0)
  783.                     attackCond = true;
  784.             }
  785.             else if(movementStyle==2){ //8 Way Constant Walk
  786.                 stepCounter = Ghost_ConstantWalk8(stepCounter, ghost->Step, ghost->Rate, ghost->Homing, ghost->Hunger);
  787.                 if(attackCooldown>0)
  788.                     attackCooldown--;
  789.                 else if(Rand(24)==0)
  790.                     attackCond = true;
  791.             }
  792.             else if(movementStyle==3){ //Homing in on Link
  793.                 if(Distance(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY())>8){
  794.                     EZB_FaceLink(this, ghost);
  795.                     Ghost_MoveAtAngle(Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY()), ghost->Step/100, 0);
  796.                 }
  797.                 if(attackCooldown>0)
  798.                     attackCooldown--;
  799.                 else if(Rand(24)==0)
  800.                     attackCond = true;
  801.             }
  802.             else if(movementStyle==4){ //Wall Bounce
  803.                 Ghost_MoveXY(vX, vY, 0);
  804.                 if((vX<0&&!Ghost_CanMove(DIR_LEFT, 1, 0)) || (vX>0&&!Ghost_CanMove(DIR_RIGHT, 1, 0)))
  805.                     vX = -vX;
  806.                 if((vY<0&&!Ghost_CanMove(DIR_UP, 1, 0)) || (vY>0&&!Ghost_CanMove(DIR_DOWN, 1, 0)))
  807.                     vY = -vY;
  808.                    
  809.                 Ghost_Dir = EZB_AngleDir(this, ghost, Angle(0, 0, vX*10, vY*10));
  810.                 if(flags&EZBF_FACELINK)
  811.                     EZB_FaceLink(this, ghost);
  812.                 if(attackCooldown>0)
  813.                     attackCooldown--;
  814.                 else if(Rand(24)==0)
  815.                     attackCond = true;
  816.             }
  817.             else if(movementStyle==5){ //Periodic Reaim
  818.                 Ghost_MoveAtAngle(stepAngle, ghost->Step/100, 0);
  819.                 Ghost_Dir = EZB_AngleDir(this, ghost, stepAngle);
  820.                 if(flags&EZBF_FACELINK)
  821.                     EZB_FaceLink(this, ghost);
  822.                    
  823.                 if(attackCooldown>0)
  824.                     attackCooldown--;
  825.                 else if(Rand(24)==0)
  826.                     attackCond = true;
  827.                    
  828.                 stepCounter++;
  829.                 if(stepCounter>80&&Rand(10)==0){
  830.                     stepAngle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  831.                     stepCounter = 0;
  832.                 }
  833.             }
  834.             else if(movementStyle==6){ //Lazy chase
  835.                 float homing = ghost->Homing*0.001;
  836.                 float topSpeed = ghost->Step*0.01;
  837.                 vX = Clamp(vX+Sign(CenterLinkX()-CenterX(ghost))*homing, -topSpeed, topSpeed);
  838.                 vY = Clamp(vY+Sign(CenterLinkY()-CenterY(ghost))*homing, -topSpeed, topSpeed);
  839.                 Ghost_MoveXY(vX, vY, 0);
  840.                 if((vX<0&&!Ghost_CanMove(DIR_LEFT, 1, 0)) || (vX>0&&!Ghost_CanMove(DIR_RIGHT, 1, 0)))
  841.                     vX = -vX;
  842.                 if((vY<0&&!Ghost_CanMove(DIR_UP, 1, 0)) || (vY>0&&!Ghost_CanMove(DIR_DOWN, 1, 0)))
  843.                     vY = -vY;
  844.                    
  845.                 Ghost_Dir = EZB_AngleDir(this, ghost, Angle(0, 0, vX*10, vY*10));
  846.                 if(flags&EZBF_FACELINK)
  847.                     EZB_FaceLink(this, ghost);
  848.                 if(attackCooldown>0)
  849.                     attackCooldown--;
  850.                 else if(Rand(24)==0)
  851.                     attackCond = true;
  852.             }
  853.             else if(movementStyle==7){ //Hopping
  854.                 EZB_Waitframes(this, ghost, Choose(24, 32, 48));
  855.                 stepAngle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY())+Rand(-30, 30);
  856.                 Game->PlaySound(SFX_JUMP);
  857.                 Ghost_Jump = 2.6;
  858.                 while(Ghost_Jump>0||Ghost_Z>0){
  859.                     Ghost_Dir = EZB_AngleDir(this, ghost, stepAngle);
  860.                     Ghost_MoveAtAngle(stepAngle, ghost->Step/100, 0);
  861.                     if(flags&EZBF_FACELINK)
  862.                         EZB_FaceLink(this, ghost);
  863.                     EZB_Waitframe(this, ghost);
  864.                 }
  865.                 if(Rand(ghost->Rate)==0)
  866.                     attackCond = true;
  867.             }
  868.             else if(movementStyle==8){ //Teleport
  869.                 EZB_Waitframes(this, ghost, Choose(32, 48, 96));
  870.                 EZB_Teleport(this, ghost);
  871.                 if(Rand(ghost->Rate)==0)
  872.                     attackCond = true;
  873.             }
  874.            
  875.             if(attackCond&&attack1){
  876.                 //Select an attack
  877.                 int attack;
  878.                 if(attack2==0)
  879.                     attack = attack1;
  880.                 else if(attack3==0)
  881.                     attack = Choose(attack1, attack2);
  882.                 else
  883.                     attack = Choose(attack1, attack2, attack3);
  884.            
  885.                 if(attack==1){ //Dash
  886.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  887.                     EZB_FaceLink(this, ghost);
  888.                     EZB_Waitframes(this, ghost, 30);
  889.                     while(EZB_CanMoveAngle(angle)){
  890.                         Ghost_MoveAtAngle(angle, 5, 0);
  891.                         EZB_Trail(this, ghost);
  892.                         EZB_Waitframe(this, ghost);
  893.                     }
  894.                 }
  895.                 else if(attack==2){ //Shoot (Directional)
  896.                     EZB_FiringAnim(this, ghost);
  897.                     EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, EZB_DirAngle(Ghost_Dir), 150);
  898.                     EZB_Waitframes(this, ghost, 24);
  899.                 }
  900.                 else if(attack==3){ //Shoot (Angular)
  901.                     EZB_FaceLink(this, ghost);
  902.                     EZB_FiringAnim(this, ghost);
  903.                     EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY()), 150);
  904.                     EZB_Waitframes(this, ghost, 24);
  905.                 }
  906.                 else if(attack==4){ //Tri Shot (Directional)
  907.                     EZB_FiringAnim(this, ghost);
  908.                     for(i=-1; i<=1; i++){
  909.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, EZB_DirAngle(Ghost_Dir)+30*i, 250);
  910.                     }
  911.                     EZB_Waitframes(this, ghost, 24);
  912.                 }
  913.                 else if(attack==5){ //Tri Shot (Angular)
  914.                     EZB_FaceLink(this, ghost);
  915.                     EZB_FiringAnim(this, ghost);
  916.                     for(i=-1; i<=1; i++){
  917.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY())+30*i, 250);
  918.                     }
  919.                     EZB_Waitframes(this, ghost, 24);
  920.                 }
  921.                 else if(attack==6){ //Stream (Directional)
  922.                     EZB_FiringAnim(this, ghost);
  923.                     angle = EZB_DirAngle(Ghost_Dir);
  924.                     EZB_Waitframes(this, ghost, 12);
  925.                     for(i=0; i<10; i++){
  926.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle, 350);
  927.                         EZB_Waitframes(this, ghost, 8);
  928.                     }
  929.                     EZB_Waitframes(this, ghost, 12);
  930.                 }
  931.                 else if(attack==7){ //Stream (Angular)
  932.                     EZB_FaceLink(this, ghost);
  933.                     EZB_FiringAnim(this, ghost);
  934.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  935.                     EZB_Waitframes(this, ghost, 12);
  936.                     for(i=0; i<10; i++){
  937.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle, 350);
  938.                         EZB_Waitframes(this, ghost, 8);
  939.                     }
  940.                     EZB_Waitframes(this, ghost, 12);
  941.                 }
  942.                 else if(attack==8){ //Breath (Directional)
  943.                     EZB_FiringAnim(this, ghost);
  944.                     angle = EZB_DirAngle(Ghost_Dir);
  945.                     EZB_Waitframes(this, ghost, 24);
  946.                     for(i=0; i<24; i++){
  947.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle+Rand(-30, 30), 250);
  948.                         EZB_Waitframes(this, ghost, 4);
  949.                     }
  950.                 }
  951.                 else if(attack==9){ //Breath (Angular)
  952.                     EZB_FaceLink(this, ghost);
  953.                     EZB_FiringAnim(this, ghost);
  954.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  955.                     EZB_Waitframes(this, ghost, 24);
  956.                     for(i=0; i<24; i++){
  957.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle+Rand(-30, 30), 250);
  958.                         EZB_Waitframes(this, ghost, 4);
  959.                     }
  960.                 }
  961.                 else if(attack==10){ //Sweep (Directional)
  962.                     EZB_FiringAnim(this, ghost);
  963.                     k = Choose(-1, 1);
  964.                     angle = EZB_DirAngle(Ghost_Dir)-45*k;
  965.                     for(i=0; i<18; i++){
  966.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle, 250);
  967.                         angle += k*5;
  968.                         EZB_Waitframes(this, ghost, 2);
  969.                     }
  970.                 }
  971.                 else if(attack==11){ //Sweep (Angular)
  972.                     EZB_FaceLink(this, ghost);
  973.                     EZB_FiringAnim(this, ghost);
  974.                     k = Choose(-1, 1);
  975.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY())-45*k;
  976.                     for(i=0; i<18; i++){
  977.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle, 250);
  978.                         angle += k*5;
  979.                         EZB_Waitframes(this, ghost, 2);
  980.                     }
  981.                 }
  982.                 else if(attack==12){ //Bullet Barrage
  983.                     EZB_FaceLink(this, ghost);
  984.                     EZB_FiringAnim(this, ghost);
  985.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY())-45*k;
  986.                     for(i=0; i<3; i++){
  987.                         for(j=-4; j<=4; j+=2){
  988.                             EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle+16*j, 150);
  989.                         }
  990.                         EZB_Waitframes(this, ghost, 16);
  991.                         for(j=-5; j<=5; j+=2){
  992.                             EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle+16*j, 150);
  993.                         }
  994.                         EZB_Waitframes(this, ghost, 24);
  995.                     }
  996.                     EZB_Waitframes(this, ghost, 24);
  997.                 }
  998.                 else if(attack==13){ //Bullet swirl
  999.                     EZB_FaceLink(this, ghost);
  1000.                     EZB_FiringAnim(this, ghost);
  1001.                     k = Choose(-1, 1);
  1002.                     angle = Rand(360);
  1003.                     for(i=0; i<20; i++){
  1004.                         for(j=0; j<5; j++){
  1005.                             EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, angle+72*j, 150);
  1006.                         }
  1007.                         angle += 4*k;
  1008.                         EZB_Waitframes(this, ghost, 4);
  1009.                     }
  1010.                     EZB_Waitframes(this, ghost, 24);
  1011.                 }
  1012.                 else if(attack==14){ //Random bullet burst
  1013.                     EZB_FaceLink(this, ghost);
  1014.                     EZB_FiringAnim(this, ghost);
  1015.                     for(i=0; i<40; i++){
  1016.                         EZB_Fire(this, ghost, CenterX(ghost)-8, CenterY(ghost)-8, Rand(360), 250);
  1017.                         EZB_Waitframes(this, ghost, 2);
  1018.                     }
  1019.                     EZB_Waitframes(this, ghost, 24);
  1020.                 }
  1021.                 else if(attack==15){ //Laser
  1022.                     EZB_FaceLink(this, ghost);
  1023.                     EZB_FiringAnim(this, ghost);
  1024.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  1025.                     for(i=0; i<30; i++){
  1026.                         if(i%4<2){
  1027.                             DrawLaser(4, CenterX(ghost), CenterY(ghost), 8, angle, C_EZB_LASER3);
  1028.                         }
  1029.                         EZB_Waitframe(this, ghost);
  1030.                     }
  1031.                     Game->PlaySound(SFX_EZB_LASER);
  1032.                     for(i=0; i<20; i++){
  1033.                         Laser3Color(4, CenterX(ghost), CenterY(ghost), 8, angle, ghost->WeaponDamage, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1034.                         EZB_Waitframe(this, ghost);
  1035.                     }
  1036.                 }
  1037.                 else if(attack==16){ //Big Laser
  1038.                     EZB_FaceLink(this, ghost);
  1039.                     EZB_FiringAnim(this, ghost);
  1040.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  1041.                     for(i=0; i<60; i++){
  1042.                         if(i%4<2){
  1043.                             DrawLaser(4, CenterX(ghost), CenterY(ghost), 40, angle, C_EZB_LASER3);
  1044.                         }
  1045.                         EZB_Waitframe(this, ghost);
  1046.                     }
  1047.                     Game->PlaySound(SFX_EZB_LASER);
  1048.                     for(i=0; i<40; i++){
  1049.                         Laser3Color(4, CenterX(ghost), CenterY(ghost), 40, angle, ghost->WeaponDamage*2, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1050.                         EZB_Waitframe(this, ghost);
  1051.                     }
  1052.                 }
  1053.                 else if(attack==17){ //Laser Spread
  1054.                     EZB_FaceLink(this, ghost);
  1055.                     EZB_FiringAnim(this, ghost);
  1056.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY());
  1057.                     for(i=0; i<30; i++){
  1058.                         for(j=-2; j<=2; j++){
  1059.                             if(i%4<2){
  1060.                                 DrawLaser(4, CenterX(ghost), CenterY(ghost), 6, angle+30*j, C_EZB_LASER3);
  1061.                             }
  1062.                         }
  1063.                         EZB_Waitframe(this, ghost);
  1064.                     }
  1065.                     Game->PlaySound(SFX_EZB_LASER);
  1066.                     for(i=0; i<20; i++){
  1067.                         for(j=-2; j<=2; j++){
  1068.                             Laser3Color(4, CenterX(ghost), CenterY(ghost), 6, angle+30*j, ghost->WeaponDamage, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1069.                         }
  1070.                         EZB_Waitframe(this, ghost);
  1071.                     }
  1072.                 }
  1073.                 else if(attack==18){ //Laser Spin
  1074.                     EZB_FaceLink(this, ghost);
  1075.                     EZB_FiringAnim(this, ghost);
  1076.                     k = Choose(-1, 1);
  1077.                     angle = Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY())+45;
  1078.                     Game->PlaySound(SFX_EZB_LASER);
  1079.                     for(i=0; i<30; i++){
  1080.                         for(j=0; j<4; j++){
  1081.                             Laser3Color(4, CenterX(ghost), CenterY(ghost), 6, angle+90*j, ghost->WeaponDamage, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1082.                         }
  1083.                         EZB_Waitframe(this, ghost);
  1084.                     }
  1085.                     for(i=0; i<30; i++){
  1086.                         for(j=0; j<4; j++){
  1087.                             Laser3Color(4, CenterX(ghost), CenterY(ghost), 6, angle+90*j, ghost->WeaponDamage, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1088.                         }
  1089.                         angle += k;
  1090.                         EZB_Waitframe(this, ghost);
  1091.                     }
  1092.                     for(i=0; i<120; i++){
  1093.                         for(j=0; j<4; j++){
  1094.                             Laser3Color(4, CenterX(ghost), CenterY(ghost), 6, angle+90*j, ghost->WeaponDamage, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1095.                         }
  1096.                         angle += k*1.5;
  1097.                         EZB_Waitframe(this, ghost);
  1098.                     }
  1099.                     for(i=0; i<30; i++){
  1100.                         for(j=0; j<4; j++){
  1101.                             Laser3Color(4, CenterX(ghost), CenterY(ghost), 6, angle+90*j, ghost->WeaponDamage, C_EZB_LASER1, C_EZB_LASER2, C_EZB_LASER3);
  1102.                         }
  1103.                         angle += k;
  1104.                         EZB_Waitframe(this, ghost);
  1105.                     }
  1106.                 }
  1107.                
  1108.                
  1109.                 Ghost_Data = combo;
  1110.                
  1111.                 attackCooldown = ghost->Haltrate*10;
  1112.                 if(movementStyle==4){ //Wall bounce
  1113.                     angle = Rand(360);
  1114.                     vX = VectorX(ghost->Step/100, angle);
  1115.                     vY = VectorY(ghost->Step/100, angle);
  1116.                 }
  1117.             }
  1118.             EZB_Waitframe(this, ghost);
  1119.         }
  1120.     }
  1121.     bool EZB_CanMoveAngle(int angle){
  1122.         int vx = VectorX(10, angle);
  1123.         int vy = VectorY(10, angle);
  1124.         if((vx<0&&!Ghost_CanMove(DIR_LEFT, 1, 0))||(vx>0&&!Ghost_CanMove(DIR_RIGHT, 1, 0)))
  1125.             return false;
  1126.         if((vy<0&&!Ghost_CanMove(DIR_UP, 1, 0))||(vy>0&&!Ghost_CanMove(DIR_DOWN, 1, 0)))
  1127.             return false;
  1128.         return true;
  1129.     }
  1130.     void EZB_FiringAnim(ffc this, npc ghost){
  1131.         int flags = ghost->Attributes[9];
  1132.         int combo = ghost->Attributes[10];
  1133.         if(flags&EZBF_8WAY)
  1134.             Ghost_Data = combo+8;
  1135.         else if(flags&EZBF_4WAY)
  1136.             Ghost_Data = combo+4;
  1137.         else
  1138.             Ghost_Data = combo+1;
  1139.     }
  1140.     void EZB_Trail(ffc this, npc ghost){
  1141.         int flags = ghost->Attributes[9];
  1142.         int tile = Game->ComboTile(Ghost_Data);
  1143.         if(flags&EZBF_4WAY||flags&EZBF_8WAY)
  1144.             tile = Game->ComboTile(Ghost_Data+Ghost_Dir);
  1145.         lweapon trail = CreateLWeaponAt(LW_SCRIPT10, ghost->X+ghost->DrawXOffset, ghost->Y+ghost->DrawYOffset);
  1146.         trail->Extend = 3;
  1147.         trail->TileWidth = ghost->TileWidth;
  1148.         trail->TileHeight = ghost->TileHeight;
  1149.         trail->DrawYOffset = 0;
  1150.         trail->CSet = this->CSet;
  1151.         trail->Tile = tile;
  1152.         trail->OriginalTile = tile;
  1153.         trail->DrawStyle = DS_PHANTOM;
  1154.         trail->DeadState = 8;
  1155.     }
  1156.     int EZB_DirAngle(int dir){
  1157.         if(dir==DIR_UP)
  1158.             return -90;
  1159.         else if(dir==DIR_DOWN)
  1160.             return 90;
  1161.         else if(dir==DIR_LEFT)
  1162.             return 180;
  1163.         else if(dir==DIR_LEFTUP)
  1164.             return -135;
  1165.         else if(dir==DIR_RIGHTUP)
  1166.             return -45;
  1167.         else if(dir==DIR_LEFTDOWN)
  1168.             return 135;
  1169.         else if(dir==DIR_RIGHTDOWN)
  1170.             return 45;
  1171.         else
  1172.             return 0;
  1173.     }
  1174.     eweapon EZB_Fire(ffc this, npc ghost, int x, int y, int angle, int step){
  1175.         int flags = ghost->Attributes[9];
  1176.         int type = WeaponTypeToID(ghost->Weapon);
  1177.         int wflags;
  1178.         if(flags&EZBF_UNBLOCKABLE)
  1179.             wflags |= EWF_UNBLOCKABLE;
  1180.         if(type==EW_BEAM||type==EW_ARROW||type==EW_MAGIC||type==EW_BOMB||type==EW_SBOMB)
  1181.             wflags |= EWF_ROTATE;
  1182.            
  1183.         int fireSFX = ghost->Attributes[7];
  1184.         int fireSPR = ghost->Attributes[8];
  1185.         int sfx = fireSFX;
  1186.         if(fireSFX<=0)
  1187.             sfx = -1;
  1188.         int spr = fireSPR;
  1189.         if(fireSPR<=0)
  1190.             spr = -1;
  1191.            
  1192.         eweapon e = FireEWeapon(type, x, y, DegtoRad(angle), step, ghost->WeaponDamage, spr, sfx, wflags);
  1193.         return e;
  1194.     }
  1195.     void EZB_Teleport(ffc this, npc ghost){
  1196.         int size = ghost->Attributes[6];
  1197.         int w = size&1111b;
  1198.         int h = (size>>4)&1111b;
  1199.         if(h==0)
  1200.             h = w;
  1201.         w = Clamp(w, 1, 4);
  1202.         h = Clamp(h, 1, 4);
  1203.        
  1204.         Game->PlaySound(SFX_EZB_TELEPORT);
  1205.         int tc;
  1206.         ghost->CollDetection = false;
  1207.         for(int i=0; i<16; i++){
  1208.             if(i%2==0)
  1209.                 ghost->DrawYOffset = -1000;
  1210.             else
  1211.                 ghost->DrawYOffset = -2;
  1212.             EZB_Waitframe(this, ghost);
  1213.         }
  1214.         ghost->DrawYOffset = -1000;
  1215.         tc = Rand(176);
  1216.         for(int i=0; i<352&&(!EZB_CanPlace(this, ghost, ComboX(tc), ComboY(tc))||Distance(ComboX(tc)+ghost->HitWidth/2, ComboY(tc)+ghost->HitHeight/2, CenterLinkX(), CenterLinkY())<((w+h)/2)*8+32); i++){
  1217.             if(i>=176)
  1218.                 tc = i-176;
  1219.             else
  1220.                 tc = Rand(176);
  1221.         }
  1222.         Ghost_X = ComboX(tc);
  1223.         Ghost_Y = ComboY(tc);
  1224.         EZB_Waitframe(this, ghost);
  1225.         EZB_FaceLink(this, ghost);
  1226.         for(int i=0; i<16; i++){
  1227.             if(i%2==0)
  1228.                 ghost->DrawYOffset = -1000;
  1229.             else
  1230.                 ghost->DrawYOffset = -2;
  1231.             EZB_Waitframe(this, ghost);
  1232.         }
  1233.         ghost->DrawYOffset = -2;
  1234.         ghost->CollDetection = true;
  1235.     }  
  1236.     int EZB_AngleDir(ffc this, npc ghost, int angle){
  1237.         int flags = ghost->Attributes[9];
  1238.         if(flags&EZBF_8WAY)
  1239.             return AngleDir8(angle);
  1240.         else
  1241.             return AngleDir4(angle);
  1242.     }
  1243.     void EZB_FaceLink(ffc this, npc ghost){
  1244.         int flags = ghost->Attributes[9];
  1245.         if(flags&EZBF_8WAY)
  1246.             Ghost_Dir = AngleDir8(Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY()));
  1247.         else
  1248.             Ghost_Dir = AngleDir4(Angle(CenterX(ghost), CenterY(ghost), CenterLinkX(), CenterLinkY()));
  1249.     }
  1250.     bool EZB_CanPlace(ffc this, npc ghost, int X, int Y){
  1251.         for(int x=ghost->HitXOffset; x<=ghost->HitXOffset+ghost->HitWidth-1; x=Min(x+8, ghost->HitXOffset+ghost->HitWidth-1)){
  1252.             for(int y=ghost->HitYOffset; y<=ghost->HitYOffset+ghost->HitHeight-1; y=Min(y+8, ghost->HitYOffset+ghost->HitHeight-1)){
  1253.                 if(!Ghost_CanMovePixel(X+x, Y+y))
  1254.                     return false;
  1255.                 if(y==ghost->HitYOffset+ghost->HitHeight-1)
  1256.                     break;
  1257.             }
  1258.             if(x==ghost->HitXOffset+ghost->HitWidth-1)
  1259.                 break;
  1260.         }
  1261.         return true;
  1262.     }
  1263.     void EZB_Waitframes(ffc this, npc ghost, int frames){
  1264.         for(int i=0; i<frames; i++){
  1265.             EZB_Waitframe(this, ghost);
  1266.         }
  1267.     }
  1268.     void EZB_Waitframe(ffc this, npc ghost){
  1269.         int flags = ghost->Attributes[9];
  1270.         if(flags&EZBF_EXPLODEEATH)
  1271.             Ghost_Waitframe(this, ghost, 1, true);
  1272.         else
  1273.             Ghost_Waitframe(this, ghost);
  1274.     }
  1275. }
  1276.  
  1277.  
  1278. ffc script gbmold
  1279. {
  1280.     void run(int enemyID)
  1281.     {
  1282.         npc ghost = Ghost_InitAutoGhost(this, enemyID);
  1283.         Ghost_SetFlag(GHF_FULL_TILE_MOVEMENT);
  1284.         Ghost_SetFlag(GHF_REDUCED_KNOCKBACK);
  1285.         npc segment[2];
  1286.         int Xtrack[160];
  1287.         int Ytrack[160];
  1288.         int vars [16] = {Xtrack,Ytrack};
  1289.         for(int i=0;i<2;i++)
  1290.             {
  1291.                 segment[i] = CreateNPCAt(NPC_ENEMYFIRE,Ghost_X,Ghost_Y);
  1292.                 Ghost_SetAllDefenses(segment[i],NPCDT_IGNORE);
  1293.                 segment[i]->DrawYOffset = -1000;
  1294.                 segment[i]->Damage= ghost->Damage;
  1295.             }
  1296.         for(int i=0; i<SizeOfArray(Xtrack); i++)
  1297.             {
  1298.                 Xtrack[i] = Ghost_X;
  1299.                 Ytrack[i] = Ghost_Y;
  1300.             }
  1301.             int angle = Rand(600);
  1302.             int turndir = Choose(-1,0,1);
  1303.             int turncounter = Choose(-1,0,1);
  1304.             ghost->DrawYOffset = -1000;
  1305.         while (true)
  1306.         {
  1307.             angle = WrapDegrees(angle+turndir*4);
  1308.             Ghost_Dir = AngleDir8(angle);
  1309.             Ghost_MoveAtAngle(angle, ghost->Step/100, 0);
  1310.             if(turncounter>0)
  1311.                 turncounter--;
  1312.             else
  1313.                 turndir = Choose(-1, 0, 1);
  1314.             int vx = VectorX(10, angle);
  1315.             int vy = VectorY(10, angle);
  1316.             if((vx<0&&!Ghost_CanMove(DIR_LEFT, 1, 0))||(vx>0&&!Ghost_CanMove(DIR_RIGHT, 1, 0))){
  1317.                 vx = -vx;
  1318.             }
  1319.             if((vy<0&&!Ghost_CanMove(DIR_UP, 1, 0))||(vy>0&&!Ghost_CanMove(DIR_DOWN, 1, 0))){
  1320.                 vy = -vy;
  1321.             }
  1322.             angle = Angle(0, 0, vx, vy);
  1323.             Mold_Waitframe(this, ghost, segment, vars);
  1324.         }
  1325.         Mold_Waitframe(this,ghost,segment,vars);
  1326.     }
  1327.  
  1328.     void Mold_Waitframe(ffc this, npc ghost,npc segment,int vars)
  1329.     {
  1330.         Mold_UpdateTrack(vars);
  1331.         Mold_Draw(this,ghost,segment,vars);
  1332.         if(!Ghost_Waitframe(this, ghost, false, false))
  1333.         {
  1334.             ghost->DrawYOffset = -2;
  1335.             Mold_UpdateTrack(vars);
  1336.             Mold_Draw(this, ghost, segment,vars);
  1337.             Ghost_Waitframe(this, ghost);
  1338.            
  1339.         }
  1340.     }
  1341.  
  1342.     void Mold_UpdateTrack(int vars)
  1343.     {
  1344.     int Xtrack=vars[0];
  1345.     int Ytrack=vars[1];
  1346.         for(int i=SizeOfArray(Xtrack)-1;i>=1;i--)
  1347.         {
  1348.             Xtrack[i] = Xtrack[i-1];
  1349.             Ytrack[i] = Ytrack[i-1];
  1350.         }
  1351.             Xtrack[0] = Ghost_X;
  1352.             Ytrack[0] = Ghost_Y;
  1353.     }
  1354.     void Mold_Draw(ffc this,npc ghost, npc segment, int vars)
  1355.     {
  1356.         int Xtrack=vars[0];
  1357.         int Ytrack=vars[1];
  1358.         int combo = ghost->Attributes[10];
  1359.         for (int i=1; i>=0; i--)
  1360.         {
  1361.             if(segment[i]->isValid())
  1362.             {
  1363.                    
  1364.                 if(ghost->HP<=0)
  1365.                 {
  1366.                     segment[i]->HP=-1000;
  1367.                 }
  1368.                
  1369.                 else
  1370.                 {
  1371.                     int spacing = 10;
  1372.                     int x = Xtrack[spacing+spacing*i];
  1373.                     int y = Ytrack[spacing+spacing*i];
  1374.                     segment[i]->X = x;
  1375.                     segment[i]->Y = y;
  1376.                     Screen->FastCombo(2,x,y,combo+8+i,this->CSet,128);
  1377.                 }
  1378.             }
  1379.         }
  1380.         //ghost->DrawYOffset = -1000;
  1381.         Screen->FastCombo(2,Ghost_X,Ghost_Y,combo+Ghost_Dir, this->CSet,128);
  1382.     }  
  1383. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement