#include "std.zh" #include "string.zh" #include "ffcscript.zh" namespace Mani { //code here ffc script Healing_Tile{ void run(int Type){ bool PlayTheSFX = false; while(true){ if(Link->X <= this->X + 3 && Link->X >= this->X - 3 && Link->Y < this->Y + 3 && Link->Y > this->Y - 3 ){ if(Type == 0 || Type == 2){ if(Link->HP < Link->MaxHP){ PlayTheSFX = true; Link->HP ++; } } if(Type == 1 || Type == 2){ if(Link->MP < Link->MaxMP){ PlayTheSFX = true; Link->MP ++; } if(Link->MP < Link->MaxMP)Link->MP ++; if(Link->MP < Link->MaxMP)Link->MP ++; if(Link->MP < Link->MaxMP)Link->MP ++; } } if(PlayTheSFX){ Game->PlaySound(23); PlayTheSFX = false; } Waitframe(); } } } // Item secripts // //Spin attack SFX for the sword const int MW_SPINATTACK_SFX = 54; //Spin attack Charge time const int MW_SWORD_CHARGE = 120; item script ManiSword{ void run(int StabType, int Unused2, int Unused3, int S_DMG, int Range, int SFX, int Variable4){ if(!CounterCost(this->CostCounter, this->Cost) && this->Cost > 0) return; Link->Action = LA_ATTACKING; Game->PlaySound(SFX); int DMG = this->Power; int Sprite = this->Sprites[0]; int ItemID = this->ID; //Check for Stab or Swing based on Input duration int AttackType = 0; // 0 = Default and is Slash. 1 = Stabbing if(StabType == 0){ int Stab = 0; while(Link->Dir == DIR_LEFT && Link->InputLeft && Stab < 4 || Link->Dir == DIR_RIGHT && Link->InputRight && Stab < 4 || Link->Dir == DIR_UP && Link->InputUp && Stab < 4 || Link->Dir == DIR_DOWN && Link->InputDown && Stab < 4){ Stab++; Waitframe(); } if(Stab >= 4) AttackType = 1; // Stabbing time! } else if(StabType == 1){ AttackType = 1; // Stabbing time! } else if(StabType == 2){ AttackType = 0; // Slash Sword } int BaseImg = 0; int BaseCSet = 0; int OrgDir = Link->Dir; int OrgX = Link->X; int OrgY = Link->Y; lweapon Damage; lweapon Sword; Sword = Screen->CreateLWeapon(LW_SCRIPT10); Sword->UseSprite(Sprite); Sword->CollDetection = false; Sword->X = Link->X; Sword->Y = Link->Y; BaseImg = Sword->OriginalTile; BaseCSet = Sword->OriginalCSet; int Sw_Dir = OrgDir; if(AttackType == 1) StabSword(Range * 2 + 2, false, Damage, Sword, Sw_Dir, Range, DMG); else{ SwingSword(2, false, Damage, Sword, Sw_Dir, Range, DMG); } Link->Action = LA_NONE; //cleanup if(Sword->isValid()){ Sword->DeadState = 0; Sword->X = -70000; Sword->Y = -70000; } if(Damage->isValid()){ Damage->DeadState = 0; Damage->X = -70000; Damage->Y = -70000; } //If the special move damage is set to 0, there is no special move. if(S_DMG > 0){ //This function uses S_DMG for MP cost here, rather than damage value, actually not used at all, lol, needs to be not zero //Brings the FFC with you: //this->Flags[FFCF_CARRYOVER] = true; //actually waaaaay too cursed to use. int ChargeUp = 0; while(((GetEquipmentB() == ItemID) && Link->InputB == true) || ((GetEquipmentA() == ItemID) && Link->InputA == true) || (Link->ItemX == ItemID && Link->InputEx1) || (Link->ItemY == ItemID && Link->InputEx2)){ ChargeUp ++; //If the special move have any requirements, this is where you put a check for that in order to play the charge complete SFX. if(ChargeUp == MW_SWORD_CHARGE){ Game->PlaySound(35); } Waitframe(); } //this->Flags[FFCF_CARRYOVER] = false; //This part happens when you have charged long enough and meet the requirements. if(ChargeUp >= MW_SWORD_CHARGE){ Game->PlaySound(SFX); Link->Action = LA_ATTACKING; Sword = Screen->CreateLWeapon(LW_SCRIPT10); Sword->UseSprite(Sprite); Sword->CollDetection = false; Sword->X = Link->X; Sword->Y = Link->Y; SwingSword(5, true, Damage, Sword, Link->Dir, Range, DMG*2); Link->Action = LA_NONE; } } //cleanup if(Sword->isValid()){ Sword->DeadState = 0; Sword->X = -70000; Sword->Y = -70000; } if(Damage->isValid()){ Damage->DeadState = 0; Damage->X = -70000; Damage->Y = -70000; } //this->Data = 0; //this->X = 0; //this->Y = 0; } void SwingSword(int MakeSwings, bool TurnLink, lweapon Damage, lweapon Sword, int Sw_Dir, int Range, int DMG){ int Swings = 0; float SwingAngle = 0; int SwindDistance = Range; int SwingTime = 8; int Swordtile = Sword->Tile; int SwordCSet = Sword->CSet; Sword->UseSprite(BLNK_SPRITE); if(MakeSwings > 2) SwingTime = 6; while(Swings < MakeSwings){ Link->Action = LA_NONE; Link->Action = LA_ATTACKING; for(int i = 0; i < SwingTime; i++){ if(i < 14){ Link->Action = LA_NONE; Link->Action = LA_ATTACKING; } if(Damage->isValid() == false){ Damage = Screen->CreateLWeapon(LW_SCRIPT10); Damage->UseSprite(BLNK_SPRITE); Damage->HitWidth = 16; Damage->HitHeight = 16; Damage->Damage = DMG; Damage->Weapon = LW_SWORD; Damage->Flags[WFLAG_PICKUP_ITEMS] = true; } if(Sw_Dir == DIR_UP){ SwingAngle = 0; //if(i < SwingTime/2) Damage->Dir = DIR_RIGHT; } else if(Sw_Dir == DIR_RIGHT){ SwingAngle = 90; //if(i < SwingTime/2) Damage->Dir = DIR_DOWN; } else if(Sw_Dir == DIR_DOWN){ SwingAngle = 180; //if(i < SwingTime/2) Damage->Dir = DIR_LEFT; } else if(Sw_Dir == DIR_LEFT){ SwingAngle = 270; //if(i < SwingTime/2) Damage->Dir = DIR_UP; } if(TurnLink) Link->Dir = Sw_Dir; Damage->Dir = Link->Dir; SwingAngle = SwingAngle - (i*(90/SwingTime)); Sword->X = Link->X + VectorX(SwindDistance, SwingAngle); Sword->Y = Link->Y + VectorY(SwindDistance, SwingAngle); Damage->X = Link->X + VectorX(SwindDistance + 8, SwingAngle); Damage->Y = Link->Y + VectorY(SwindDistance + 8, SwingAngle); //Screen->PutPixel(6, Sword->X, Sword->Y, 0x44, 0, 0, 0, OP_OPAQUE); if(Sword->X != 0 && Sword->Y != 0) Screen->DrawTile(2, Sword->X - 8, Sword->Y, Swordtile, 2, 1, SwordCSet, -1, -1, Sword->X - 8, Sword->Y, SwingAngle, 0, true, OP_OPAQUE); // ManiCollectItem(Damage); Waitframe(); } Swings++; if(Sw_Dir == DIR_UP) Sw_Dir = DIR_LEFT; else if(Sw_Dir == DIR_RIGHT) Sw_Dir = DIR_UP; else if(Sw_Dir == DIR_DOWN) Sw_Dir = DIR_RIGHT; else if(Sw_Dir == DIR_LEFT) Sw_Dir = DIR_DOWN; if(Damage->isValid()){ Damage->DeadState = 0; //Damage->X = -20000; //Damage->Y = -20000; } } } void StabSword(int StabTime, bool TurnLink, lweapon Damage, lweapon Sword, int Sw_Dir, int Range, int DMG){ float SwingAngle = 0; int SwingDistance = -2; int Swordtile = Sword->Tile; int SwordCSet = Sword->CSet; Sword->UseSprite(BLNK_SPRITE); Link->Action = LA_NONE; Link->Action = LA_ATTACKING; for(int i = 0; i < StabTime; i++){ if(i < 14){ Link->Action = LA_NONE; Link->Action = LA_ATTACKING; } if(Damage->isValid() == false){ Damage = Screen->CreateLWeapon(LW_SCRIPT10); Damage->UseSprite(BLNK_SPRITE); Damage->HitWidth = 16; Damage->HitHeight = 16; Damage->Damage = DMG; Damage->Weapon = LW_SWORD; Damage->Flags[WFLAG_PICKUP_ITEMS] = true; } if(i + (Range/2) + 2 >= StabTime) SwingDistance = SwingDistance - 2; else if(SwingDistance < Range){ SwingDistance = SwingDistance + 2; if(SwingDistance > Range) SwingDistance = Range; } if(Sw_Dir == DIR_UP){ SwingAngle = 270; //if(i < SwingTime/2) Damage->Dir = DIR_RIGHT; } else if(Sw_Dir == DIR_RIGHT){ SwingAngle = 0; //if(i < SwingTime/2) Damage->Dir = DIR_DOWN; } else if(Sw_Dir == DIR_DOWN){ SwingAngle = 90; //if(i < SwingTime/2) Damage->Dir = DIR_LEFT; } else if(Sw_Dir == DIR_LEFT){ SwingAngle = 180; //if(i < SwingTime/2) Damage->Dir = DIR_UP; } if(TurnLink) Link->Dir = Sw_Dir; Damage->Dir = Link->Dir; Sword->X = Link->X + VectorX(SwingDistance, SwingAngle); Sword->Y = Link->Y + VectorY(SwingDistance, SwingAngle); Damage->X = Link->X + VectorX(SwingDistance + 8, SwingAngle); Damage->Y = Link->Y + VectorY(SwingDistance + 8, SwingAngle); //Screen->PutPixel(6, Sword->X, Sword->Y, 0x44, 0, 0, 0, OP_OPAQUE); if(Sword->X != 0 && Sword->Y != 0) Screen->DrawTile(2, Sword->X - 8, Sword->Y, Swordtile, 2, 1, SwordCSet, -1, -1, Sword->X - 8, Sword->Y, SwingAngle, 0, true, OP_OPAQUE); // ManiCollectItem(Damage); Waitframe(); } if(Sw_Dir == DIR_UP) Sw_Dir = DIR_LEFT; else if(Sw_Dir == DIR_RIGHT) Sw_Dir = DIR_UP; else if(Sw_Dir == DIR_DOWN) Sw_Dir = DIR_RIGHT; else if(Sw_Dir == DIR_LEFT) Sw_Dir = DIR_DOWN; if(Damage->isValid()){ Damage->DeadState = 0; //Damage->X = -20000; //Damage->Y = -20000; } } } // FFC Scripts //--------------------------------------// ffc script TriggerOrb{ // Trigger orbs, hit all on screen on the same time to trigger secrets. void run(int WeaponType, int Checker){ int OriginalTile = this->Data; lweapon ValidWeapon; int ThisNumb = FFCNum(this); int FFCs[35]; ffc CheckFFC; int TotalFFCs = 0; //If checker then make array if(Checker > 0){ for(int i = 0; i < 35; i++){ FFCs[i] = -1; } int ArraySpot = 0; for(int i=1; i<=32; i++){ CheckFFC = Screen->LoadFFC(i); if(CheckFFC->Script == this->Script){ FFCs[ArraySpot] = FFCNum(CheckFFC); ArraySpot ++; } } TotalFFCs = ArraySpot; } while(Screen->State[ST_SECRET] == false){ //Check to see if self is hit for(int i = 1; i <= Screen->NumLWeapons(); i++){ ValidWeapon = Screen->LoadLWeapon(i); if(ValidWeapon->Weapon > 0 && ValidWeapon->Weapon == WeaponType && Collision(this, ValidWeapon)) this->Misc[8] = 2; else if(ValidWeapon->ID == WeaponType && Collision(this, ValidWeapon)) this->Misc[8] = 2; } //If checker then check all orbs and trigger secret if(Checker > 0){ int ArraySpot = 0; int ActiveOrbs = 0; for(int i = 0; FFCs[i] != -1; i++){ if(FFCs[i] > -1){ CheckFFC = Screen->LoadFFC(FFCs[i]); if(CheckFFC->Misc[8] > 0) ActiveOrbs ++; } if(ActiveOrbs == TotalFFCs){ Screen->TriggerSecrets(); Screen->State[ST_SECRET] = true; Game->PlaySound(27); } } //Screen->DrawInteger(6, this->X +8, this->Y - 24, 0, 0x0F, -1, -1, -1, TotalFFCs, 0, OP_OPAQUE); //Screen->DrawInteger(6, this->X +8 , this->Y - 16, 0, 0x0F, -1, -1, -1, ActiveOrbs, 0, OP_OPAQUE); } //Visuals of switch and hit frames decreasing if(this->Misc[8] > 0) this->Data = OriginalTile + 1; else if(this->Data != OriginalTile) this->Data = OriginalTile; if(this->Misc[8] > 0) this->Misc[8] --; Waitframe(); } //Setting tile when ending script this->Data = OriginalTile + 2; } } ffc script SecretActivater{ // Triggers secrets when run. void run(){ SecretTrigger(9); } } ffc script ItemCheckSecret{ // Secret trigger if Hero has a variable number of items (from 1 to 7) void run(int D0, int D1, int D2, int D3, int D4, int D5, int D6, int SFX){ while(Screen->State[ST_SECRET] == false){ if(D1 == 0) D1 = D0; if(D2 == 0) D2 = D0; if(D3 == 0) D3 = D0; if(D4 == 0) D4 = D0; if(D5 == 0) D5 = D0; if(D6 == 0) D6 = D0; if(SFX == 0) SFX = 27; if((Link->Item[D0] == true) && (Link->Item[D1] == true) && (Link->Item[D2] == true) && (Link->Item[D3] == true) && (Link->Item[D4] == true) && (Link->Item[D5] == true) && (Link->Item[D6] == true)){ Waitframes(60); Game->PlaySound(SFX); Screen->TriggerSecrets(); Screen->State[ST_SECRET] = true; } Waitframe(); } } } ffc script TenRupeeRoom{ // Oracles style rupee room (very cursed) requires four identical looking rupee items. void run(int LowChance, int MidChamce, int HighChance, int BigRupeeID, int Medium, int Small, int OneRupee){ if(Screen->State[ST_ITEM]) return; int Placed = 1; int CreateID = 0; item Rupee; int X = 16 * 5; int Y = 16 * 3; int Offset = 0; while(Placed <= 34){ // these used: SeedRand() before instead of Rand if(HighChance != 0 && Rand(HighChance) == 1) CreateID = BigRupeeID; else if(MidChamce != 0 && Rand(MidChamce) == 1) CreateID = Medium; else if(LowChance != 0 && Rand(LowChance) == 1) CreateID = Small; else{ CreateID = OneRupee; } Rupee = Screen->CreateItem(CreateID); Rupee->X = X; Rupee->Y = Y; Rupee->Pickup = IP_ST_ITEM; X = X + 16; if(Placed == 6){ X = 16*5 - 8; Y = Y + 16; } else if(Placed == 13){ X = 16*4; Y = Y + 16; } else if(Placed == 21){ X = 16*5 - 8; Y = Y + 16; } else if(Placed == 28){ X = 16*5; Y = Y + 16; } Placed ++; // Waitframe(); } return; } } ffc script TransitionFade{ // Fades the screen after a delay, then warps Hero. void run(int Timer, int Dmap, int Screen, int Colour, int Speed){ while(Timer > 0){ Timer --; Waitframe(); } for(int i = 0; i < 5; i++){ for(int i2 = 0; i < Speed; i++){ FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_TRANS); if(i >= 1) FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_TRANS); if(i >= 2) FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_TRANS); if(i >= 3) FastRectangle(6, 0, -98, 16*17, 16*16, Colour, OP_OPAQUE); NoActionFull(); Waitframe(); } } Link->Warp(Dmap, Screen); } } // Utility Secripts //--------------------------------------// item script Give_MultItem_AND_String{ // Run on pickup to play a string and give more items, a bit obsoloete. void run(int PlayString, int Item1, int Item2, int Item3){ Screen->Message(PlayString); if(Item1 != 0){ Link->Item[Item1] = true; } if(Item2 != 0){ Link->Item[Item2] = true; } if(Item3 != 0){ Link->Item[Item3] = true; } } } item script GiveItemS{ //Gives inventory items on all D0-D7 slots. Considering limited item IDs in ZC, this is better than bundel. void run(int D0, int D1, int D2, int D3, int D4, int D5, int D6, int D7){ if(!Link->Item[D0] && D0 > 0) Link->Item[D0] = true; if(!Link->Item[D1] && D0 > 0) Link->Item[D1] = true; if(!Link->Item[D2] && D0 > 0) Link->Item[D2] = true; if(!Link->Item[D3] && D0 > 0) Link->Item[D3] = true; if(!Link->Item[D4] && D0 > 0) Link->Item[D4] = true; if(!Link->Item[D5] && D0 > 0) Link->Item[D5] = true; if(!Link->Item[D6] && D0 > 0) Link->Item[D6] = true; if(!Link->Item[D7] && D0 > 0) Link->Item[D7] = true; } } // Utility Functions //--------------------------------------// int FrameCount; // see function below void FrameCounter(){ // a simple frame counter for the global scope FrameCount += 1; if(FrameCount >= 60){ FrameCount = 0; } } void NoActFullWaitframe(){ NoActionFull(); Waitframe(); } void NoActionFull(){ Link->InputUp = false; Link->PressUp = false; Link->InputDown = false; Link->PressDown = false; Link->InputLeft = false; Link->PressLeft = false; Link->InputRight = false; Link->PressRight = false; Link->InputStart = false; Link->PressStart = false; Link->InputMap = false; Link->PressMap = false; Link->InputR = false; Link->PressR = false; Link->InputL = false; Link->PressL = false; Link->InputA = false; Link->PressA = false; Link->InputB = false; Link->PressB = false; Link->InputEx1 = false; Link->PressEx1 = false; Link->InputEx2 = false; Link->PressEx2 = false; Link->InputEx3 = false; Link->PressEx3 = false; Link->InputEx4 = false; Link->PressEx4 = false; Link->InputAxisUp = false; Link->PressAxisUp = false; Link->InputAxisDown = false; Link->PressAxisDown = false; Link->InputAxisLeft = false; Link->PressAxisLeft = false; Link->InputAxisRight = false; Link->PressAxisRight = false; } void FasterRupeeDrain(){ // Empties the rupee drain counter faster; Should run every frame from the global scope. if(Game->DCounter[CR_RUPEES]<-50){ Game->DCounter[CR_RUPEES] = Min(0, Game->DCounter[CR_RUPEES]+9); Game->Counter[CR_RUPEES] = Max(0, Game->Counter[CR_RUPEES]-9); } } void FasterCounterDrain(){ // Same as above but for all counters for(int i = 0; i < 30; i++){ if(Game->DCounter[i]<-50){ Game->DCounter[i] = Min(0, Game->DCounter[i]+9); Game->Counter[i] = Max(0, Game->Counter[i]-9); } } } void SecretTrigger(int SFX){ // Triggers the screen secret when run. Game->PlaySound(SFX); Screen->TriggerSecrets(); } void FastInt(int Layer, int X, int Y, int font, int Colour, int Numb){ Screen->DrawInteger(Layer, X, Y, font, Colour, -1, -1, -1, Numb, 0, OP_OPAQUE); } void FasterInt(int Layer, int X, int Y, int Numb){ Screen->DrawInteger(Layer, X, Y, FONT_S2, 0x0E, 0x0F, -1, -1, Numb, 0, OP_OPAQUE); } void FastRectangle(int layer, int x, int y, int x2, int y2, int color, int opacity){ Screen->Rectangle(layer, x, y, x2, y2, color, 1, 0, 0, 0, true, opacity); } bool isSolid_Water(int x, int y){ if(Screen->ComboT[ComboAt(x, y)] == CT_WATER) return false; else{ if(Screen->isSolid(x, y)) return true; } } bool RestrictUseScrnEdg(){ if(Hero->Dir == DIR_LEFT && Hero->X < 16) return true; else if(Hero->Dir == DIR_RIGHT && Hero->X > 16*14) return true; else if(Hero->Dir == DIR_UP && Hero->Y < 16) return true; else if(Hero->Dir == DIR_DOWN && Hero->Y > 16*9) return true; else{ return false; } } bool ChckItmButtonInput(int ItemID){ if(Hero->ItemA == ItemID && Input->Press[CB_A]) return true; else if(Hero->ItemB == ItemID && Input->Press[CB_B]) return true; else if(Hero->ItemX == ItemID && Input->Press[CB_X]) return true; else if(Hero->ItemY == ItemID && Input->Press[CB_Y]) return true; else{ return false; } } } // END OF NAMESPACE