Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Paste your current global script in here
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- // import "std.zh" // Only need this once.
- import "ghost.zh"
- // Passive Subscreen A/B Counter Fix
- // A fix to display the proper counter for the A and B buttons on the passive subscreen when the quest rule "Can Select A-Button Weapon on Subscreen" is on.
- //
- // In your Slot2 (or Active) global script, put SetCountersAB(); before the waitframe.
- // A sample global script is commented out at the bottom.
- //
- // See notes below about the constants used ESPECIALLY if your quest makes use of the Script1-25 item counters. If you're not sure, you'll likely be safe with the defaults.
- //
- // On your passive subscreen, place a Counter object with each Button Item display. Edit the properties.
- // On the Attributes Tab, change Item 1 to the corresponding Script counter - default is A Button = Script 24, B Button = Script 25
- // Leave "Show Zero" and "Only Selected" UNCHECKED.
- //
- // Note: make sure that your item has its Counter Reference declared. Edit the item, Pickup tab.
- // For instance, Arrows are hardcoded to use either rupees or arrows. Unless the Counter Reference is set, the counter won't show.
- // This should point to the item's counter NOT the script counters used by this script.
- //
- // Set these constants to unused Script counters. Valid numbers would be 7-31.
- // By default they are set to the highest values to hopefully avoid interfering with any other scripts.
- // The counter values and associated references are all in std_constants.zh
- // You'll need to know the counter reference number NOT the value. So for the defaults, you'll need to use Script Counters 24 & 25.
- const int CR_ABUTTON = 30; // Script 24 counter reference
- const int CR_BBUTTON = 31; // Script 25 counter reference
- void SetCountersAB(){
- itemdata itemA = Game->LoadItemData(GetEquipmentA());
- itemdata itemB = Game->LoadItemData(GetEquipmentB());
- if(GetEquipmentA()==0){
- Game->Counter[CR_ABUTTON]=0;
- }else if(Game->Counter[CR_ABUTTON]!=Game->Counter[itemA->Counter]){
- Game->Counter[CR_ABUTTON]=Game->Counter[itemA->Counter];
- }
- if(GetEquipmentB()==0){
- Game->Counter[CR_BBUTTON]=0;
- }else if(Game->Counter[CR_BBUTTON]!=Game->Counter[itemB->Counter]){
- Game->Counter[CR_BBUTTON]=Game->Counter[itemB->Counter];
- }
- }
- // global script active{
- // void run(){
- // while(true){
- // Might have other stuff here...
- //
- // SetCountersAB();
- //
- // Waitframe();
- // }
- // }
- //}
- const int SCRIPT_BARRIERS = 1; // Must refer to "Barrier"'s ffc script slot in the quest
- // ID's of barrier-related combos
- // Barriers in raised state
- const int BARRIER_A_RAISED = 32;
- const int BARRIER_B_RAISED = 33;
- // Barriers in lowered state
- const int BARRIER_A_LOWERED = 34;
- const int BARRIER_B_LOWERED = 35;
- // Barriers animating to raised state
- const int BARRIER_A_ANIMRAISE = 36;
- const int BARRIER_B_ANIMRAISE = 37;
- // Barriers animating to lowered state
- const int BARRIER_A_ANIMLOWER = 38;
- const int BARRIER_B_ANIMLOWER = 39;
- // Raised barriers that Link can walk on
- const int BARRIER_A_WALKABLE = 40;
- const int BARRIER_B_WALKABLE = 41;
- // Barrier switches
- const int BARRIER_A_SWITCH = 42;
- const int BARRIER_B_SWITCH = 43;
- const int BARRIER_SWITCH_DUMMY = 177; // ID of a switch hit detection dummy enemy
- const int BARRIER_SWITCH_DUMMY_HP = 32767;
- // Global array to store the state of barriers per dmap
- // If you have more than 16 dmaps you can change the capacity in the []'s
- // You may change the states in other scripts, but the changes will not be visible
- // until there is a new screen, so set them before Barriers_NewScreen() is called.
- bool barriers[16]; // false = blue barriers raised, true = red barriers raised
- // Function that makes preparations for barriers on each screen and starts an FFC script
- void Barriers_NewScreen() {
- // Search for a barrier-related combo
- for (int i = 0; i <= 175; i++) {
- int cd = Screen->ComboD[i];
- if (cd == BARRIER_A_RAISED || cd == BARRIER_A_LOWERED || cd == BARRIER_A_SWITCH ||
- cd == BARRIER_B_RAISED || cd == BARRIER_B_LOWERED || cd == BARRIER_B_SWITCH) {
- // A barrier-related combo was found
- // Make initial changes to combos
- if (barriers[Game->GetCurDMap()]) {
- for (int j = i; j <= 175; j++) {
- int cd = Screen->ComboD[j];
- if (cd == BARRIER_A_RAISED) Screen->ComboD[j] = BARRIER_A_LOWERED;
- else if (cd == BARRIER_B_LOWERED) Screen->ComboD[j] = BARRIER_B_RAISED;
- else if (cd == BARRIER_A_SWITCH) Screen->ComboD[j] = BARRIER_B_SWITCH;}}
- else {
- for (int j = i; j <= 175; j++) {
- int cd = Screen->ComboD[j];
- if (cd == BARRIER_B_RAISED) Screen->ComboD[j] = BARRIER_B_LOWERED;
- else if (cd == BARRIER_A_LOWERED) Screen->ComboD[j] = BARRIER_A_RAISED;
- else if (cd == BARRIER_B_SWITCH) Screen->ComboD[j] = BARRIER_A_SWITCH;}}
- // So run FFCscript to control barriers
- int args[] = {0,0,0,0,0,0,0,0};
- RunFFCScript(SCRIPT_BARRIERS, args);
- break;}
- }}
- // This lets you toggle barriers on any dmap
- bool ToggleBarriers(int dmap) {
- if (dmap == Game->GetCurDMap()) ToggleBarriers();
- else barriers[dmap] = !barriers[dmap];
- return barriers[dmap];}
- // This toggles barriers on the current dmap
- bool ToggleBarriers() {
- int curdmap = Game->GetCurDMap();
- if (!barriers[curdmap]) {
- barriers[curdmap] = true;
- for (int i = 0; i <= 175; i++) {
- int cd = Screen->ComboD[i];
- if (cd == BARRIER_A_RAISED || cd == BARRIER_A_WALKABLE || cd == BARRIER_A_ANIMRAISE) {
- Screen->ComboD[i] = BARRIER_A_ANIMLOWER;}
- else if (cd == BARRIER_B_LOWERED || cd == BARRIER_B_ANIMLOWER) {
- Screen->ComboD[i] = BARRIER_B_ANIMRAISE;}
- else if (cd == BARRIER_A_SWITCH) {Screen->ComboD[i] = BARRIER_B_SWITCH;}}}
- else {
- barriers[curdmap] = false;
- for (int i = 0; i <= 175; i++) {
- int cd = Screen->ComboD[i];
- if (cd == BARRIER_B_RAISED || cd == BARRIER_B_WALKABLE || cd == BARRIER_B_ANIMRAISE) {
- Screen->ComboD[i] = BARRIER_B_ANIMLOWER;}
- else if (cd == BARRIER_A_LOWERED || cd == BARRIER_A_ANIMLOWER) {
- Screen->ComboD[i] = BARRIER_A_ANIMRAISE;}
- else if (cd == BARRIER_B_SWITCH) {Screen->ComboD[i] = BARRIER_A_SWITCH;}}}
- return barriers[curdmap];
- }
- // This script controls barriers on the screen
- // The FFC is automatically created by Barriers_NewScreen()
- ffc script Barriers {
- void run() {
- // Initialize storage for bswitch hit dummies
- int bswitch_count;
- npc bswitch[8];
- for (int i = 0; i <= 175; i++) {
- if (Screen->ComboD[i] == BARRIER_A_SWITCH || Screen->ComboD[i] == BARRIER_B_SWITCH) {
- npc bs = CreateNPCAt(BARRIER_SWITCH_DUMMY, ComboX(i), ComboY(i));
- bs->HitWidth = 8; // Smaller hit box to avoid annoying collisions with Link
- bs->HitHeight = 8;
- bs->HP = BARRIER_SWITCH_DUMMY_HP;
- bswitch[bswitch_count++] = bs;}}
- // Change raised barriers to walkable ones if Link enters screen on a raised barrier
- int lcombo = LinkOnComboD();
- bool onbarrier = (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED);
- if (onbarrier) for (int i = 0; i < 176; i++) {
- if (Screen->ComboD[i] == BARRIER_A_RAISED) {Screen->ComboD[i] = BARRIER_A_WALKABLE;}
- else if (Screen->ComboD[i] == BARRIER_B_RAISED) {Screen->ComboD[i] = BARRIER_B_WALKABLE;}}
- while (true) {
- // Detect hits on bswitches, and change combos accordingly
- for (int j = 0; j < bswitch_count; j++) {
- if (bswitch[j]->HP < BARRIER_SWITCH_DUMMY_HP) {
- bswitch[j]->HP = BARRIER_SWITCH_DUMMY_HP;
- ToggleBarriers();
- break;}} //break so that only one bswitch hit may register per frame
- // Make barriers walkable if Link is on raised barriers, or unwalkable if not
- lcombo = LinkOnComboD();
- if (!onbarrier && (lcombo == BARRIER_A_RAISED || lcombo == BARRIER_B_RAISED)) {
- onbarrier = true;
- for (int i = 0; i <= 175; i++) {
- if (Screen->ComboD[i] == BARRIER_A_RAISED) {Screen->ComboD[i] = BARRIER_A_WALKABLE;}
- else if (Screen->ComboD[i] == BARRIER_B_RAISED) {Screen->ComboD[i] = BARRIER_B_WALKABLE;}}}
- else if (onbarrier && !(lcombo == BARRIER_A_WALKABLE || lcombo == BARRIER_B_WALKABLE)) {
- onbarrier = false;
- for (int i = 0; i <= 175; i++) {
- if (Screen->ComboD[i] == BARRIER_A_WALKABLE) {Screen->ComboD[i] = BARRIER_A_RAISED;}
- else if (Screen->ComboD[i] == BARRIER_B_WALKABLE) {Screen->ComboD[i] = BARRIER_B_RAISED;}}}
- Waitframe();}
- }}
- // A utility function that returns the ID of the combo that Link appears to stand on
- int LinkOnComboD() {
- return Screen->ComboD[ComboAt(Link->X+8, Link->Y+13)];
- }
- //X--------------------X
- //| Bottle Constants |
- //X--------------------X
- const int FFC_SFA = 31; //FFC used for screen freeze A
- const int FFC_SFB = 32; //FFC used for screen freeze B
- const int CMB_SFA = 2; //Combo used for screen freeze A
- const int CMB_SFB = 3; //Combo used for screen freeze B
- const int BOTTLE_SETTING_NO_WATER = 0; //Set to 1 if water shouldn't be bottleable
- const int TIL_BOTTLE = 52020; //First of the tiles used for the bottle items. Should come in four identical rows.
- //Tile order in each row should go as such:
- //Empty, Empty, Red Potion, Green Potion, Blue Potion, Water, Fairy, Bee
- const int REDPOTION_HEARTS = 8; //Hearts the red potion heals
- const int GREENPOTION_MP = 256; //MP the green potion restores
- const int BLUEPOTION_HEARTS = 16; //Hearts the blue potion heals
- const int BLUEPOTION_MP = 256; //MP the blue potion restores
- const int LW_WATER = 31; //LWeapon type used for bottled water. Script 1 by default
- const int SPR_BOTTLEWATER = 88; //Sprite used for bottled water
- const int SFX_BOTTLEWATER = 55; //Sound when water is dumped out
- const int FAIRY_HEARTS = 3; //Hearts healed by a fairy
- const int CMB_FAIRY = 904; //Fairy combo
- const int CS_FAIRY = 8; //Fairy cset
- const int SFX_FAIRY = 64; //Sound that plays when a fairy appears
- const int IC_BOTTLE = 67; //Item class used for bottles. Custom 1 by default.
- const int I_BOTTLE1 = 143; //Item ID for the first bottle (Level 1)
- const int I_BOTTLE2 = 144; //Item ID for the second bottle (Level 2)
- const int I_BOTTLE3 = 145; //Item ID for the second bottle (Level 3)
- const int I_BOTTLE4 = 146; //Item ID for the second bottle (Level 4)
- const int FREQ_HEARTREFILL = 8; //Frequency in frames at which potions/fairies restore hearts
- const int SFX_HEARTREFILL = 22; //Sound when potion/fairy restores a heart
- const int FREQ_MAGICSOUND = 8; //Frequency in frames where the magic refill sound plays
- const int SFX_MAGICREFILL = 61; //Magic refill sound
- const int SFX_ERROR = 62; //Error sound
- const int TIL_BOTTLESWING = 52006; //Tile of a right facing open bottle used when trying to catch something
- const int CS_BOTTLESWING = 11; //CSet of the swinging bottle
- const int SFX_BOTTLESWING = 63; //Sound used for the bottle being swung
- const int I_WATERBOTTLE = 150; //Item for bottle water pickup
- const int I_FAIRYBOTTLE = 151; //Item for bottle fairy pickup
- const int I_BEEBOTTLE = 152; //Item for bottle bee pickup
- const int CMB_BEE = 905; //Combo used for the bee
- const int CS_BEE = 8; //CSet used for the bee
- const int SFX_BEE = 65; //SFX used for the bee
- const int LW_BEE = 32; //Lweapon used for the bee (Script 2 by default)
- const int EW_BEE = 32; //Eweapon used for the bee (Script 2 by default)
- const int DAMAGE_BEE = 4; //Damage the bee deals
- const int FFCM_BEE_SELFDESTRUCT = 0; //FFC misc used to tell the bee to disappear
- const int STR_CANTAFFORD = 2; //Message for when you can't afford an item
- const int STR_NOBOTTLE = 3; //Message for when you don't have a bottle to store a potion in
- const int C_WHITE = 0x01; //The color white
- const int C_BLACK = 0x0F; //The color black
- //X--------------------------X
- //| Screen Freeze Function |
- //X--------------------------X
- void Screen_Freeze(){
- ffc f1 = Screen->LoadFFC(FFC_SFA);
- ffc f2 = Screen->LoadFFC(FFC_SFB);
- f1->Data = CMB_SFA;
- f2->Data = CMB_SFB;
- }
- void Screen_Unfreeze(){
- ffc f1 = Screen->LoadFFC(FFC_SFA);
- ffc f2 = Screen->LoadFFC(FFC_SFB);
- f1->Data = 0;
- f2->Data = 0;
- }
- //X--------------------------X
- //| Empty Bottle Functions |
- //X--------------------------X
- //X--------------------------------------------------------X
- //| These constants don't need to be changed. |
- //| They just define various states of the empty bottle. |
- //| BS_ constants are also used for the potion filling |
- //| pickup item script. Look here to see what to set D2 |
- //| to for that. |
- //X--------------------------------------------------------X
- // |
- const int BS_EMPTY = 0; // |
- const int BS_POTIONRED = 1; // |
- const int BS_POTIONGREEN = 2; // |
- const int BS_POTIONBLUE = 3; // |
- const int BS_WATER = 4; // |
- const int BS_FAIRY = 5; // |
- const int BS_BEE = 6; // |
- // |
- const int BSI_BOTTLEUSED = 4; // |
- const int BSI_BOTTLETIMER = 5; // |
- const int BSI_OLDHP = 6; // |
- const int BSI_OLDMP = 7; // |
- const int BSI_FAIRYTIMER = 8; // |
- const int BSI_FAIRYREVIVE = 9; // |
- // |
- //---------------------------------------------------------X
- int BottleState[12]; //0-3: States of bottles, 4: Bottle used,
- //5: Potion timer, 6: OldHP, 7: OldMP
- //This function should be called at the beginning of your global and
- //refreshes the graphics for the bottles.
- void RefreshBottles(){
- for(int i=0; i<4; i++){
- CopyTile(TIL_BOTTLE+20*i+1+BottleState[i], TIL_BOTTLE+20*i);
- }
- }
- int UsingEmptyBottle(){
- if(Link->PressA){
- int id = GetEquipmentA();
- if(id>0){
- itemdata A = Game->LoadItemData(id);
- if(A->Family==IC_BOTTLE)
- return A->Level-1;
- }
- }
- else if(Link->PressB){
- int id = GetEquipmentB();
- if(id>0){
- itemdata B = Game->LoadItemData(id);
- if(B->Family==IC_BOTTLE)
- return B->Level-1;
- }
- }
- return -1;
- }
- bool CanFillBottle(){
- int bottles[4] = {I_BOTTLE1, I_BOTTLE2, I_BOTTLE3, I_BOTTLE4};
- for(int i=0; i<4; i++){
- if(Link->Item[bottles[i]]&&BottleState[i]==BS_EMPTY)
- return true;
- }
- return false;
- }
- int FillBottle(int state){
- int bottles[4] = {I_BOTTLE1, I_BOTTLE2, I_BOTTLE3, I_BOTTLE4};
- for(int i=0; i<4; i++){
- if(Link->Item[bottles[i]]&&BottleState[i]==BS_EMPTY){
- BottleState[i] = state;
- RefreshBottles();
- return i;
- }
- }
- }
- int HasFairy(){
- int bottles[4] = {I_BOTTLE1, I_BOTTLE2, I_BOTTLE3, I_BOTTLE4};
- for(int i=0; i<4; i++){
- if(Link->Item[bottles[i]]&&BottleState[i]==BS_FAIRY)
- return i;
- }
- return -1;
- }
- //This function goes in the while loop of your global script before waitdraw
- void EmptyBottleGlobal(){
- int bottle = BottleState[BSI_BOTTLEUSED];
- if(BottleState[BSI_BOTTLETIMER]>0){
- if(BottleState[bottle]==BS_POTIONRED){
- if(BottleState[BSI_BOTTLETIMER]%FREQ_HEARTREFILL==0){
- Link->HP += 16;
- Game->PlaySound(SFX_HEARTREFILL);
- if(Link->HP>=Link->MaxHP){
- BottleState[BSI_BOTTLETIMER] = 0;
- }
- }
- }
- else if(BottleState[bottle]==BS_POTIONGREEN){
- Link->MP += 2;
- if(BottleState[BSI_BOTTLETIMER]%FREQ_MAGICSOUND==0)
- Game->PlaySound(SFX_MAGICREFILL);
- if(Link->MP>=Link->MaxMP){
- BottleState[BSI_BOTTLETIMER] = 0;
- }
- }
- else if(BottleState[bottle]==BS_POTIONBLUE){
- if(BottleState[BSI_BOTTLETIMER]%FREQ_HEARTREFILL==0&&Link->HP<BottleState[BSI_OLDHP]+BLUEPOTION_HEARTS*16&&Link->HP<Link->MaxHP){
- Link->HP += 16;
- Game->PlaySound(SFX_HEARTREFILL);
- }
- if(Link->MP<BottleState[BSI_OLDMP]+BLUEPOTION_MP&&Link->MP<Link->MaxMP){
- if(BottleState[BSI_BOTTLETIMER]%FREQ_MAGICSOUND==0)
- Game->PlaySound(SFX_MAGICREFILL);
- Link->MP += 2;
- }
- if(Link->HP>=Link->MaxHP&&Link->MP>=Link->MaxMP){
- BottleState[BSI_BOTTLETIMER] = 0;
- }
- }
- else if(BottleState[bottle]==BS_FAIRY){
- if(BottleState[BSI_BOTTLETIMER]<2&&BottleState[BSI_FAIRYTIMER]<120)
- BottleState[BSI_BOTTLETIMER] = 2;
- BottleState[BSI_FAIRYTIMER]++;
- int X = Link->X+VectorX(16*(BottleState[BSI_FAIRYTIMER]/120), BottleState[BSI_FAIRYTIMER]*8);
- int Y = Link->Y+VectorY(8*(BottleState[BSI_FAIRYTIMER]/120), BottleState[BSI_FAIRYTIMER]*8)-BottleState[BSI_FAIRYTIMER]/8;
- if(BottleState[BSI_FAIRYREVIVE]==1){
- if(BottleState[BSI_FAIRYTIMER]<10||BottleState[BSI_FAIRYTIMER]>110)
- Screen->Rectangle(6, 0, 0, 256, 176, C_BLACK, 1, 0, 0, 0, true, 64);
- else
- Screen->Rectangle(6, 0, 0, 256, 176, C_BLACK, 1, 0, 0, 0, true, 128);
- Screen->FastTile(6, Link->X+Link->DrawXOffset, Link->Y+Link->DrawYOffset, Link->Tile, 6, 128);
- }
- if(BottleState[BSI_FAIRYTIMER]<80||BottleState[BSI_FAIRYTIMER]%2==0)
- Screen->FastCombo(6, X, Y, CMB_FAIRY, CS_FAIRY, 128);
- if(BottleState[BSI_BOTTLETIMER]%FREQ_HEARTREFILL==0&&Link->HP<Link->MaxHP){
- Link->HP += 16;
- Game->PlaySound(SFX_HEARTREFILL);
- }
- if(Link->HP>=Link->MaxHP&&BottleState[BSI_FAIRYTIMER]>=120){
- BottleState[BSI_BOTTLETIMER] = 0;
- }
- }
- BottleState[BSI_BOTTLETIMER]--;
- NoAction();
- if(BottleState[BSI_BOTTLETIMER]<=0){
- BottleState[bottle] = BS_EMPTY;
- BottleState[BSI_BOTTLEUSED] = -1;
- RefreshBottles();
- Screen_Unfreeze();
- }
- }
- else{
- bottle = UsingEmptyBottle();
- if(bottle>-1){
- if(BottleState[bottle]==BS_EMPTY){
- int scriptname[] = "Bottle_Empty";
- int scriptid = Game->GetFFCScript(scriptname);
- int Args[8] = {bottle};
- RunFFCScript(scriptid, Args);
- }
- else if(BottleState[bottle]==BS_POTIONRED){
- if(Link->HP==Link->MaxHP){
- Game->PlaySound(SFX_ERROR);
- }
- else{
- BottleState[BSI_BOTTLEUSED] = bottle;
- BottleState[BSI_BOTTLETIMER] = FREQ_HEARTREFILL*REDPOTION_HEARTS;
- Screen_Freeze();
- }
- }
- else if(BottleState[bottle]==BS_POTIONGREEN){
- if(Link->MP==Link->MaxMP){
- Game->PlaySound(SFX_ERROR);
- }
- else{
- BottleState[BSI_BOTTLEUSED] = bottle;
- BottleState[BSI_BOTTLETIMER] = GREENPOTION_MP/2;
- Screen_Freeze();
- }
- }
- else if(BottleState[bottle]==BS_POTIONBLUE){
- if(Link->HP==Link->MaxHP&&Link->MP==Link->MaxMP){
- Game->PlaySound(SFX_ERROR);
- }
- else{
- BottleState[BSI_BOTTLEUSED] = bottle;
- BottleState[BSI_BOTTLETIMER] = Max(FREQ_HEARTREFILL*BLUEPOTION_HEARTS, BLUEPOTION_MP/2);
- BottleState[BSI_OLDHP] = Link->HP;
- BottleState[BSI_OLDMP] = Link->MP;
- Screen_Freeze();
- }
- }
- else if(BottleState[bottle]==BS_WATER){
- Link->Action = LA_ATTACKING;
- lweapon l = CreateLWeaponAt(LW_WATER, Link->X+InFrontX(Link->Dir, 0), Link->Y+InFrontY(Link->Dir, 0));
- l->UseSprite(SPR_BOTTLEWATER);
- l->DeadState = l->ASpeed*l->NumFrames;
- l->CollDetection = false;
- Game->PlaySound(SFX_BOTTLEWATER);
- BottleState[bottle] = BS_EMPTY;
- RefreshBottles();
- }
- else if(BottleState[bottle]==BS_FAIRY){
- if(Link->HP==Link->MaxHP){
- Game->PlaySound(SFX_ERROR);
- }
- else{
- BottleState[BSI_BOTTLEUSED] = bottle;
- BottleState[BSI_BOTTLETIMER] = FREQ_HEARTREFILL*FAIRY_HEARTS;
- BottleState[BSI_FAIRYTIMER] = 0;
- BottleState[BSI_FAIRYREVIVE] = 0;
- Game->PlaySound(SFX_FAIRY);
- Screen_Freeze();
- }
- }
- else if(BottleState[bottle]==BS_BEE){
- int scriptname[] = "Bottle_Bee";
- int scriptid = Game->GetFFCScript(scriptname);
- int vars[8] = {1};
- RunFFCScript(scriptid, vars);
- BottleState[bottle] = BS_EMPTY;
- RefreshBottles();
- }
- }
- int fairy = HasFairy();
- if(Link->HP<=0&&fairy>-1){
- Link->HP = 1;
- BottleState[BSI_BOTTLEUSED] = fairy;
- BottleState[BSI_BOTTLETIMER] = FREQ_HEARTREFILL*FAIRY_HEARTS;
- BottleState[BSI_FAIRYTIMER] = 0;
- BottleState[BSI_FAIRYREVIVE] = 1;
- Game->PlaySound(SFX_FAIRY);
- Screen_Freeze();
- }
- }
- }
- //X-------------------------------X
- //| Empty Bottle Action Scripts |
- //X-------------------------------X
- ffc script Bottle_Empty{
- void run(int bottleid){
- int Angle = 0;
- if(Link->Dir==DIR_UP)
- Angle = -90;
- else if(Link->Dir==DIR_DOWN)
- Angle = 90;
- else if(Link->Dir==DIR_LEFT)
- Angle = 180;
- Game->PlaySound(SFX_BOTTLESWING);
- Link->Action = LA_ATTACKING;
- int Collected = 0;
- for(int i=-45; i<45; i+=10){
- int X = Link->X+VectorX(12, Angle+i);
- int Y = Link->Y+VectorY(12, Angle+i);
- Screen->DrawTile(2, X, Y, TIL_BOTTLESWING, 1, 1, CS_BOTTLESWING, -1, -1, X, Y, Angle+i+90, 0, true, 128);
- if(Collected==0||Collected==BS_WATER){
- if(OnWater(X+8, Y+8)&&Collected==0&&BOTTLE_SETTING_NO_WATER==0){
- Collected = BS_WATER;
- }
- for(int j=1; j<=Screen->NumItems(); j++){
- item itm = Screen->LoadItem(j);
- if(itm->ID==I_FAIRY||itm->ID==I_FAIRYSTILL){
- if(RectCollision(itm->X+itm->HitXOffset, itm->Y+itm->HitYOffset, itm->X+itm->HitXOffset+itm->HitWidth, itm->Y+itm->HitYOffset+itm->HitHeight, X+4, Y+4, X+11, Y+11)){
- Collected = BS_FAIRY;
- Remove(itm);
- break;
- }
- }
- }
- for(int j=1; j<=32; j++){
- ffc f = Screen->LoadFFC(j);
- int scriptname[] = "Bottle_Bee";
- int scriptid = Game->GetFFCScript(scriptname);
- if(f->Script==scriptid){
- if(RectCollision(X+4, Y+4, X+11, Y+11, f->X+4, f->Y+4, f->X+11, f->Y+11)){
- Collected = BS_BEE;
- f->Misc[FFCM_BEE_SELFDESTRUCT] = 1;
- }
- }
- }
- }
- WaitNoAction();
- }
- if(Collected==BS_WATER){
- BottleState[bottleid] = BS_WATER;
- RefreshBottles();
- item itm = CreateItemAt(I_WATERBOTTLE, Link->X, Link->Y);
- itm->Pickup = IP_HOLDUP;
- }
- else if(Collected==BS_FAIRY){
- BottleState[bottleid] = BS_FAIRY;
- RefreshBottles();
- item itm = CreateItemAt(I_FAIRYBOTTLE, Link->X, Link->Y);
- itm->Pickup = IP_HOLDUP;
- }
- else if(Collected==BS_BEE){
- BottleState[bottleid] = BS_BEE;
- RefreshBottles();
- item itm = CreateItemAt(I_BEEBOTTLE, Link->X, Link->Y);
- itm->Pickup = IP_HOLDUP;
- }
- WaitNoAction(10);
- }
- bool OnWater(int x, int y){
- int ct = Screen->ComboT[ComboAt(x, y)];
- if(ct==CT_WATER||ct==CT_SHALLOWWATER)
- return true;
- return false;
- }
- }
- ffc script Bottle_Bee{
- void run(int friendly){
- this->Data = CMB_BEE;
- this->CSet = CS_BEE;
- if(friendly==1){
- this->X = Link->X;
- this->Y = Link->Y;
- }
- int i; int j; int k;
- int X = this->X;
- int Y = this->Y;
- lweapon lh;
- eweapon eh;
- int Lifespan = Rand(900, 1200);
- for(i=0; i<40; i++){
- Y -= 0.5;
- this->X = X;
- this->Y = Y;
- Waitframe();
- }
- while(Lifespan>0){
- int Angle;
- if(friendly==1){
- int Tx = -1000;
- int Ty = -1000;
- int Dist = 1000;
- for(i=1; i<=Screen->NumNPCs(); i++){
- npc n = Screen->LoadNPC(i);
- if(Distance(X+8, Y+8, CenterX(n), CenterY(n))<Dist){
- Dist = Distance(X+8, Y+8, CenterX(n), CenterY(n));
- Tx = CenterX(n)-8;
- Ty = CenterY(n)-8;
- }
- }
- Angle = Angle(X, Y, Tx, Ty);
- if(Screen->NumNPCs()==0)
- Angle = Angle(X, Y, Link->X, Link->Y);
- }
- else{
- if(Distance(Link->X, Link->Y, X, Y)<80&&Rand(2)==0)
- Angle = Angle(X, Y, Link->X, Link->Y);
- else
- Angle = Rand(360);
- }
- k = Rand(32, 48);
- for(i=0; i<k; i++){
- Lifespan--;
- j = (j+1)%360;
- if(j%30==0)
- Game->PlaySound(SFX_BEE);
- X = Clamp(X+VectorX(2, Angle), -16, 256);
- Y = Clamp(Y+VectorY(2, Angle), -16, 176);
- this->X = X;
- this->Y = Y;
- if(friendly==1){
- if(lh->isValid()){
- lh->X = X;
- lh->Y = Y;
- }
- else{
- lh = CreateLWeaponAt(LW_BEE, X, Y);
- lh->HitXOffset = 4;
- lh->HitYOffset = 4;
- lh->HitWidth = 8;
- lh->HitHeight = 8;
- lh->DrawYOffset = -1000;
- lh->Dir = 8;
- lh->Damage = DAMAGE_BEE;
- }
- }
- else{
- if(eh->isValid()){
- eh->X = X;
- eh->Y = Y;
- }
- else{
- eh = CreateEWeaponAt(EW_BEE, X, Y);
- eh->HitXOffset = 4;
- eh->HitYOffset = 4;
- eh->HitWidth = 8;
- eh->HitHeight = 8;
- eh->DrawYOffset = -1000;
- eh->Dir = 8;
- eh->Damage = DAMAGE_BEE;
- }
- }
- if(this->Misc[FFCM_BEE_SELFDESTRUCT]==1){
- if(lh->isValid())
- lh->DeadState = 0;
- if(eh->isValid())
- eh->DeadState = 0;
- this->Data = 0;
- this->CSet = 0;
- Quit();
- }
- Waitframe();
- }
- }
- if(lh->isValid())
- lh->DeadState = 0;
- if(eh->isValid())
- eh->DeadState = 0;
- this->Data = 0;
- this->CSet = 0;
- for(i=0; i<40; i++){
- if(i%2==0)
- Screen->FastCombo(2, X, Y, CMB_BEE, CS_BEE, 128);
- Waitframe();
- }
- }
- }
- //X----------------------------X
- //| Other Associated Scripts |
- //X----------------------------X
- item script PotionFill{
- void run(int str, int state){
- FillBottle(state);
- Screen->Message(str);
- }
- }
- ffc script ItemShop{
- void run(int id, int strdescription, int price, int potion){
- itemdata ic = Game->LoadItemData(id);
- while(true){
- if(Link->X>this->X-8&&Link->X<this->X+8&&Link->Y>this->Y&&Link->Y<this->Y+10&&Link->Dir==DIR_UP){
- if(Link->PressL){
- Screen->Message(strdescription);
- NoAction();
- }
- else if(Link->PressR){
- if(Game->Counter[CR_RUPEES]+Game->DCounter[CR_RUPEES]>=price){
- if(potion>0&&!CanFillBottle()){
- Screen->Message(STR_NOBOTTLE);
- NoAction();
- }
- else{
- item itm = CreateItemAt(id, Link->X, Link->Y);
- itm->Pickup = IP_HOLDUP;
- Game->DCounter[CR_RUPEES] -= price;
- for(int i=0; i<10; i++){
- WaitNoAction();
- }
- }
- }
- else{
- Screen->Message(STR_CANTAFFORD);
- NoAction();
- }
- }
- }
- DrawPrice(this, price);
- Waitframe();
- }
- }
- void DrawPrice(ffc this, int price){
- int xoff = -2;
- if(price>999)
- xoff = -8;
- else if(price>99)
- xoff = -6;
- else if(price>9)
- xoff = -4;
- Screen->DrawInteger(5, this->X+8+xoff+1, this->Y+18+1, FONT_Z3SMALL, C_BLACK, -1, -1, -1, price, 0, 128);
- Screen->DrawInteger(5, this->X+8+xoff, this->Y+18, FONT_Z3SMALL, C_WHITE, -1, -1, -1, price, 0, 128);
- }
- }
- ffc script BeeGrass{
- void run(int chances){
- int Combo = Screen->ComboD[ComboAt(this->X+8, this->Y+8)];
- while(Screen->ComboD[ComboAt(this->X+8, this->Y+8)]==Combo){
- Waitframe();
- }
- if(Rand(chances)==0){
- int scriptname[] = "Bottle_Bee";
- int scriptid = Game->GetFFCScript(scriptname);
- int i = RunFFCScript(scriptid, 0);
- ffc f = Screen->LoadFFC(i);
- f->X = this->X;
- f->Y = this->Y;
- }
- }
- }
- ffc script WaterTrigger{
- void run(){
- if(!Screen->State[ST_SECRET]){
- while(true){
- for(int i=1; i<=Screen->NumLWeapons(); i++){
- lweapon l = Screen->LoadLWeapon(i);
- if(l->ID==LW_WATER&&Collision(this, l)){
- Screen->TriggerSecrets();
- Game->PlaySound(SFX_SECRET);
- Screen->State[ST_SECRET] = true;
- Quit();
- }
- }
- Waitframe();
- }
- }
- }
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- ///Constants and Variables used by platform script;
- const int DIAGONAL_MOVEMENT = 1; //Enable the option and change this to 0 for nes movement.
- int onplatform; //Global variable use this to check if Link is on a platform for other scripts.
- void NesMovementFix()
- {
- if(DIAGONAL_MOVEMENT==0 && (Link->InputUp || Link->InputDown))
- {
- Link->InputLeft = false;
- Link->InputRight = false;
- }
- }
- void MovingPlatforms()
- {
- onplatform = 0;
- if(Link->Z == 0)
- {
- int buffer[] = "movingplatform";
- for(int i = 1; i <= 32; i++)
- {
- ffc f = Screen->LoadFFC(i);
- if(f->Script != Game->GetFFCScript(buffer)) continue;
- if(Abs(Link->X + 8 - CenterX(f)) >= f->TileWidth*8) continue;
- if(Abs(Link->Y + 12 - CenterY(f)) >= f->TileHeight*8) continue;
- onplatform = FFCNum(f);
- break;
- }
- }
- }
- ffc script MovingPlatform
- {
- void run()
- {
- float oldx = this->X;
- float oldy = this->Y;
- float linkx;
- float linky;
- while(true)
- {
- if(onplatform == FFCNum(this))
- {
- linkx += this->X - oldx;
- linky += this->Y - oldy;
- if(linkx << 0 != 0)
- {
- Link->X += linkx << 0;
- linkx -= linkx << 0;
- }
- if(linky << 0 != 0)
- {
- Link->Y += linky << 0;
- linky -= linky << 0;
- }
- }
- else
- {
- linkx = 0;
- linky = 0;
- }
- oldx = this->X;
- oldy = this->Y;
- Waitframe();
- }
- }
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- int MooshPit[16];
- const int MP_LASTX = 0;
- const int MP_LASTY = 1;
- const int MP_LASTDMAP = 2;
- const int MP_LASTSCREEN = 3;
- const int MP_ENTRYX = 4;
- const int MP_ENTRYY = 5;
- const int MP_ENTRYDMAP = 6;
- const int MP_ENTRYSCREEN = 7;
- const int MP_FALLX = 8;
- const int MP_FALLY = 9;
- const int MP_FALLTIMER = 10;
- const int MP_FALLSTATE = 11;
- const int MP_DAMAGETYPE = 12;
- const int CT_HOLELAVA = 128; //Combo type for pits (No Ground Enemies by default)
- const int CF_LAVA = 98; //Combo flag marking pits as lava (Script 1 by default)
- const int SPR_FALLHOLE = 88; //Sprite for Link falling in a hole
- const int SPR_FALLLAVA = 89; //Sprite for Link falling in lava
- const int SFX_FALLHOLE = 38; //Sound for falling in a hole
- const int SFX_FALLLAVA = 13; //Sound for falling in lava
- const int DAMAGE_FALLHOLE = 8; //How much damage pits deal (1/2 heart default)
- const int DAMAGE_FALLLAVA = 16; //How much damage lava deals (1 heart default)
- const int FFC_MOOSHPIT_AUTOWARPA = 32; //FFC that turns into an auto side warp combo when you fall in a pit
- const int CMB_MOOSHPIT_AUTOWARPA = 2; //Combo number of an invisible Auto Side Warp A combo
- const int SF_MISC_MOOSHPITWARP = 2; //Number of the screen flag under the Misc. section that makes pits warp (Script 1 by default)
- //All pit warps use Side Warp A
- const int MOOSHPIT_MIN_FALL_TIME = 60; //Minimum time for the pit's fall animation, to prevent repeated falling in pits
- const int MOOSHPIT_EXTRA_FALL_TIME = 0; //Extra frames at the end of the falling animation before Link respawns
- //Width and height of Link's hitbox for colliding with pits
- const int MOOSHPIT_LINKHITBOXWIDTH = 2;
- const int MOOSHPIT_LINKHITBOXHEIGHT = 2;
- //Width and height of Link's hitbox for colliding with pits/lava in sideview
- const int MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH = 2;
- const int MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT = 2;
- const int MOOSHPIT_NO_GRID_SNAP = 0; //Set to 1 to prevent Link's falling sprite from snapping to the combo grid.
- bool MooshPit_OnPit(int LinkX, int LinkY, bool countFFCs){
- if(Link->Action==LA_FROZEN)
- return false;
- if(countFFCs){
- if(MooshPit_OnFFC(LinkX, LinkY))
- return false;
- }
- bool sideview;
- if(Screen->Flags[SF_ROOMTYPE]&100b)
- sideview = true;
- //wew lad
- int width = MOOSHPIT_LINKHITBOXWIDTH;
- int height = MOOSHPIT_LINKHITBOXHEIGHT;
- for(int x=0; x<=1; x++){
- for(int y=0; y<=1; y++){
- int X; int Y;
- if(sideview){ //Hitbox functions differently in sideview
- width = MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH;
- height = MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT;
- X = LinkX+7-width/2+width;
- Y = LinkY+7-height/2+height;
- }
- else{
- X = LinkX+7-width/2+width;
- Y = LinkY+11-height/2+height;
- }
- //If one corner of Link's hitbox isn't on a pit, return false
- if(Screen->ComboT[ComboAt(X, Y)]!=CT_HOLELAVA){
- return false;
- }
- }
- }
- return true;
- }
- bool MooshPit_OnFFC(int LinkX, int LinkY){
- for(int i=1; i<=32; i++){ //Cycle through every FFC
- ffc f = Screen->LoadFFC(i);
- //Check if the FFC is solid
- if(f->Data>0&&!f->Flags[FFCF_CHANGER]&&!f->Flags[FFCF_ETHEREAL]){
- //Check if Link collides with the FFC
- if(RectCollision(LinkX+4, LinkY+9, LinkX+11, LinkY+14, f->X, f->Y, f->X+f->EffectWidth-1, f->Y+f->EffectHeight-1)){
- return true;
- }
- }
- }
- //If Link doesn't collide with any FFC, return false
- return false;
- }
- void MooshPit_Init(){
- MooshPit[MP_LASTX] = Link->X;
- MooshPit[MP_LASTY] = Link->Y;
- MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
- MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
- MooshPit[MP_ENTRYX] = Link->X;
- MooshPit[MP_ENTRYY] = Link->Y;
- MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
- MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
- MooshPit[MP_FALLSTATE] = 0;
- MooshPit[MP_FALLTIMER] = 0;
- Link->CollDetection = true;
- Link->Invisible = false;
- }
- void MooshPit_Update(){
- bool isWarp;
- if(Screen->Flags[SF_MISC]&(1<<SF_MISC_MOOSHPITWARP))
- isWarp = true;
- bool sideview;
- if(Screen->Flags[SF_ROOMTYPE]&100b)
- sideview = true;
- if(Link->Action!=LA_SCROLLING){
- //Update the entry point whenever the screen changes
- if(MooshPit[MP_ENTRYDMAP]!=Game->GetCurDMap()||MooshPit[MP_ENTRYSCREEN]!=Game->GetCurDMapScreen()){
- MooshPit[MP_ENTRYX] = Link->X;
- MooshPit[MP_ENTRYY] = Link->Y;
- MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
- MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
- }
- if(MooshPit[MP_FALLSTATE]==0){ //Not falling in pit
- if(Link->Z<=0&&MooshPit_OnPit(Link->X, Link->Y, true)){ //If Link steps on a pit
- int underLink;
- if(!sideview)
- underLink = ComboAt(Link->X+8, Link->Y+12);
- else
- underLink = ComboAt(Link->X+8, Link->Y+8);
- lweapon fall;
- //Check if the combo is lava
- if(ComboFI(underLink, CF_LAVA)){
- //Play sound and display animation
- Game->PlaySound(SFX_FALLLAVA);
- fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
- if(!MOOSHPIT_NO_GRID_SNAP){
- fall->X = ComboX(underLink);
- fall->Y = ComboY(underLink);
- }
- fall->UseSprite(SPR_FALLLAVA);
- fall->CollDetection = false;
- fall->DeadState = fall->ASpeed*fall->NumFrames;
- //Mark as lava damage
- MooshPit[MP_DAMAGETYPE] = 1;
- }
- //Otherwise it's a pit
- else{
- //Play sound and display animation
- Game->PlaySound(SFX_FALLHOLE);
- fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
- if(!MOOSHPIT_NO_GRID_SNAP){
- fall->X = ComboX(underLink);
- fall->Y = ComboY(underLink);
- }
- fall->UseSprite(SPR_FALLHOLE);
- fall->CollDetection = false;
- fall->DeadState = fall->ASpeed*fall->NumFrames;
- //Mark as hole damage
- MooshPit[MP_DAMAGETYPE] = 0;
- }
- MooshPit[MP_FALLX] = Link->X;
- MooshPit[MP_FALLY] = Link->Y;
- //Cooldown should last as long as the fall animation
- MooshPit[MP_FALLSTATE] = 1;
- MooshPit[MP_FALLTIMER] = Max(MOOSHPIT_MIN_FALL_TIME, fall->DeadState+MOOSHPIT_EXTRA_FALL_TIME);
- //Render Link invisible and intangible
- Link->Invisible = true;
- Link->CollDetection = false;
- NoAction();
- }
- else if(!MooshPit_OnPit(Link->X, Link->Y, false)&&Link->Action!=LA_FROZEN){ //All other times, while Link is on solid ground, record Link's last position
- if(sideview){
- //Link has no Z value in sideview, so we check if he's on a platform instead
- if(OnSidePlatform(Link->X, Link->Y)){
- MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
- MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
- MooshPit[MP_LASTX] = Link->X;
- MooshPit[MP_LASTY] = Link->Y;
- }
- }
- else{
- if(Link->Z<=0){
- MooshPit[MP_LASTDMAP] = Game->GetCurDMap();
- MooshPit[MP_LASTSCREEN] = Game->GetCurDMapScreen();
- MooshPit[MP_LASTX] = Link->X;
- MooshPit[MP_LASTY] = Link->Y;
- }
- }
- }
- }
- else if(MooshPit[MP_FALLSTATE]==1){ //Falling animation
- if(MooshPit[MP_FALLTIMER]>0)
- MooshPit[MP_FALLTIMER]--;
- Link->Jump = 0;
- Link->Z = 0;
- //Keep Link invisible just in case
- Link->Invisible = true;
- Link->CollDetection = false;
- NoAction();
- if(MooshPit[MP_FALLTIMER]==0){
- if(!isWarp||MooshPit[MP_DAMAGETYPE]==1){ //If the pit isn't a warp, deal damage and move Link back to the return point
- //If the entry would dump Link back in the pit, dump him out at the failsafe position
- if(MooshPit_OnPit(MooshPit[MP_ENTRYX], MooshPit[MP_ENTRYY], false)){
- Link->X = MooshPit[MP_LASTX];
- Link->Y = MooshPit[MP_LASTY];
- //If the failsafe position was on a different screen, warp there
- if(Game->GetCurDMap()!=MooshPit[MP_LASTDMAP]||Game->GetCurDMapScreen()!=MooshPit[MP_LASTSCREEN]){
- Link->PitWarp(MooshPit[MP_LASTDMAP], MooshPit[MP_LASTSCREEN]);
- }
- Link->Invisible = false;
- Link->CollDetection = true;
- }
- else{
- //Move Link to the start and make him visible
- Link->X = MooshPit[MP_ENTRYX];
- Link->Y = MooshPit[MP_ENTRYY];
- Link->Invisible = false;
- Link->CollDetection = true;
- }
- //Subtract HP based on damage type
- if(MooshPit[MP_DAMAGETYPE]==1)
- Link->HP -= DAMAGE_FALLLAVA;
- else
- Link->HP -= DAMAGE_FALLHOLE;
- //Play hurt sound and animation
- Link->Action = LA_GOTHURTLAND;
- Link->HitDir = -1;
- Game->PlaySound(SFX_OUCH);
- MooshPit[MP_FALLSTATE] = 0;
- }
- else{
- MooshPit[MP_FALLSTATE] = 2;
- MooshPit[MP_FALLTIMER] = 1;
- ffc warp = Screen->LoadFFC(FFC_MOOSHPIT_AUTOWARPA);
- warp->Data = CMB_MOOSHPIT_AUTOWARPA;
- warp->Flags[FFCF_CARRYOVER] = false;
- }
- }
- }
- else if(MooshPit[MP_FALLSTATE]==2){ //Just warped
- if(sideview){
- Link->X = MooshPit[MP_FALLX];
- Link->Y = 0;
- }
- else{
- Link->X = MooshPit[MP_FALLX];
- Link->Y = MooshPit[MP_FALLY];
- Link->Z = 176;
- }
- Link->Invisible = false;
- Link->CollDetection = true;
- MooshPit[MP_FALLSTATE] = 0;
- MooshPit[MP_FALLTIMER] = 0;
- }
- }
- }
- void MooshPit_ResetEntry(){
- MooshPit[MP_ENTRYX] = Link->X;
- MooshPit[MP_ENTRYY] = Link->Y;
- MooshPit[MP_ENTRYDMAP] = Game->GetCurDMap();
- MooshPit[MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- //Standard Version
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- int Pots[176];
- int nPots;
- //Constants used to configure the script
- const int PS_HEIGHT = 2; //hight of sprite
- const int PS_WIDTH = 2; //width of sprite
- const int PS_AFRAMES = 8; //number of animation sprites used
- const int PS_SPEED = 3; //speed of the animation: smaller = faster, don't use 0!
- const int PS_CSET = 7; //cset to be used
- const int PS_LAYER = 3; //layer to be displayed on
- const int PS_ANIMATION = 1300; //the combo ID of the top left of the first frame on the tiles page
- const int PS_SFX = 62; //sound effect to be used
- const int PS_CFLAG = 130; //combo type flag that identifies pots (130 = Slash->Next (Item))
- //see std_constants.zh for other type flags
- void Pot_Script(){
- int w; int h;
- int i; int n;
- int timer = PS_SPEED * PS_AFRAMES; //note that the max is 255 (~4 seconds)
- int x; int y; int aframe;
- int OffsetX = PS_WIDTH * 8 - 8; //center the sprite according to height and width
- int OffsetY = PS_HEIGHT * 8 - 8; //center the sprite according to height and width
- //initialize pots array, the first 8 bits store the position and the second 8 bits store the timer
- if(ScreenChanged){
- i = 0;
- for(n = 0; n < 176; n++)
- if(Screen->ComboT[n] == PS_CFLAG) Pots[i++] = n;
- nPots = i;
- return;
- }
- //scan for broken pots..
- for(n = 0; n < nPots; n++){
- if(Screen->ComboT[Pots[n] & 0xff] == PS_CFLAG)
- continue;
- //we found one! if its timer isn't set, set it and play sound
- if((Pots[n] & 0xff00) == 0){
- Game->PlaySound(PS_SFX);
- Pots[n] |= (timer << 8);
- }
- //now figure out where we are in the animation cycle
- aframe = PS_ANIMATION + PS_WIDTH * Floor((timer - (Pots[n] >> 8)) / PS_SPEED);
- //display tiles
- x = ComboX(Pots[n] & 0xff) - OffsetX;
- y = ComboY(Pots[n] & 0xff) - OffsetY;
- for(w = 0; w < PS_WIDTH; w++){
- for(h = 0; h < PS_HEIGHT; h++){
- Screen->FastTile(PS_LAYER, x + 16 * w, y + 16 * h, aframe + w + 20 * h, PS_CSET, 255);
- }
- }
- //subtract 1 from the timer and remove pot from the array when timer = 0
- Pots[n] -= 0x100;
- if((Pots[n] & 0xff00) == 0) Pots[n] = Pots[--nPots];
- }
- }
- //force ScreenChange to be ture if player dies or F6 continues (ScreenChanged = true; doesn't work)
- //put this into the "onExit" slot
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- // [ITEM] PEGASUS BOOTS -------------------------------------------------------------------------------------------------------------------------------------------
- // (original: Joe123, edits: Zepinho, justin ...................................................................................................................................
- // -------------------------------------------------------------------------------
- // SETUP
- //
- // 1. Add the necessary tiles to your quest file. Dust animation. SFX. etc.
- // 2. Set the following constants
- // 3. Set the size of the Dust_Array in the Global variable section. The formula is provided.
- // Leave the rest of the global variables alone.
- // 4. Create your Pegasus Boot item, custom item class, attach the PegasusBoots item script to the active slot.
- // 5. If you have no other global scripts, ignore this step.
- // If you do, Scroll down to bottom of this script and read instructions on how to add the necessary global functions to your script.
- // 6. Make sure there are no functions / variables you're trying to include twice.
- // constant BIG_LINK come to mind. Marked with !!!!!!!!!!!!!!!
- // Optional setup stuff
- // Jump related - Roc Items, and otherwise
- // 1. If not using can select both A and B button items, OR if not using Roc's feather you should set I_ROCSFEATHER_INCREASER to 0.
- // 2. If using Roc's Feather item setup a second Roc Feather item, and can select A/B items.
- // Roc item class. Equipment item. Height multiplier = a number greater than your Roc feather height. 2 works well if standard Roc Feather HM = 1.
- // Give it the same sprite and SFX as Roc Feather. or can make them different if you'd like.
- // Make note of the item# of the Increaser item, so you can set the constant below.
- // The PegasusBoots script gives and takes the Increaser item automatically, so don't give it in your quest.
- // If already using multiple levels of Roc Item, or if your Roc Feather is NOT the default item number (91), you'll need to modify the script.
- // 3. If you're just keying jumping to another button L/R/EX1/etc, the Roc Increaser won't function. You'll need to modify the script.
- //
- // Swords - extra swords, and non default sword item#s
- // 1. More swords can be added by adding new constants with their item numbers, and sprites.
- // And adding more to the if statement that uses the I_SWORD constants in the PegasusDash function.
- // 2. The script currently uses the default item numbers for swords. If you change those, you'll have to replace the corresponding I_SWORD constant.
- // 3. Dash sword will draw an animated sword if the sprite is animated. EXCEPT when scrolling.
- //
- // Dash Slash related - cutting tall grass, bushes, etc while dashing
- // 1. By default things combo types - Grass, Flowers, Bush, and next versions are set to use the sprites you define. And their default item drop set. (IS_COMBOS = 12)
- // 2. Slash combo types don't have a default sprite, and use the default item sets (IS_COMBOS = 12). Slash->Item which uses its default item set (IS_MAGICLIFE = 10).
- // 3. Continous combo types accounted for at all.
- // 4. The SFX is the same for all of them.
- // 5. If you want to change any of this, find the function DoDashSlash. Easy to find with a row of !!!!!!!!!! above.
- // Edit to your liking.
- // 6. If using any of the Slash combo type with solid combo, you'll have a bug where you can't initiate a dashslash while standing beside it.
- // You can edit the function CanDashSlash to fix it. It is marked by a row of !!!!!!!!!!!!!!!!!
- //
- // Dust drawing related
- // 1. If using the "No screen scrolling" quest rule. You can switch to the old dust drawing code if you wish, and clear up some variables and functions.
- // Uncomment DustDrawLW, and remove DustDrawTile. The ScrollFix function can be removed, with its associated global variables.
- // Dust_Array, the DustDrawTile function, the dashSword while scrolling code, and the dashSword variables can all be safely removed in this case.
- // !!!!!!! this is also used by other scripts, only needs to be included in script file once
- const int BIG_LINK = 0; // Set this constant to 1 if using the Large Link Hit Box feature.
- // Pegasus Boots Constants
- const int CF_DASH = 100; // CF_Script3, ComboFlag that Link can't dash through if walkable, and will break if solid
- // Could be reused for situations where dash is impossible.
- const int INV_COMBO_ID = 14; // Solid DashCombos will break into this
- const int DashSFXLength = 9; // Time between repeating Dash SFX
- const int SFX_DASH = 64; // Dashing SFX
- const int SFX_HITWALL = 137; // Hitting a wall
- const int SFX_PEGASUSBREAK = 66; // SFX to play when breaking a Pegasus Boot block
- const int T_DUST = 27420; // Dust Kick-up tile
- const int DustAFrames = 2; // Dust Kick-up animation frames
- const int DustASpeed = 4; // Dust Kick-up animation speed
- const int DustCSet = 2; // Dust Kick-up CSet
- const int I_ROCSFEATHER_INCREASER = 124; // Roc's feather upgrade, to automatically give to Link when using Pegasus Boots
- const int DASH_SWORD_DMG = 8; // Dash sword deals this regardless of sword damage.
- const int DASH_SWORD_MULT = 0; // Dash sword deals equipped sword damage times this. 0 uses above value. >0 uses this.
- const int SPRITE_SWORD1 = 0; // Set these to the sprite number used by that sword level
- const int SPRITE_SWORD2 = 1;
- const int SPRITE_SWORD3 = 2;
- const int SPRITE_SWORD4 = 3;
- const int NPC_ITEMSET = 177; // ID of a dummy enemy with type different from "none", hp0, itemset overridden by script
- const int SPRITE_BUSH_CUT = 52; // set these to whatever sprites they should correspond to
- const int SPRITE_FLOWER_CUT = 53; // sprites with 0 for either NumFrames or AniSpeed will not show.
- const int SPRITE_GRASS_CUT = 54;
- const int CanDrown = 1; // 0 makes Link stop beside water combos regardless of quest rule, and their walkability
- // Set 0 if not using drownable water, or if you don't want Link to dash into water.
- // Set 1 if using drownable water, and want Link to dash in and either drown or swim.
- //END Pegasus Boots constants
- // -------------------------------------------------------------------------------
- // Global Variables
- // to draw while Scrolling
- int scrollDir;
- int scrollCounter;
- int drawX;
- int drawY;
- //Pegasus Boots Global variables
- int PegasusDash = -1;
- bool PegasusCollision;
- int DashCounter;
- int StoreInput;
- int StoreHP;
- int dashSwordTile = 0; // for drawing dashsword while scrolling, script sets these.
- int dashSwordCSet = 0;
- //!!!!!!!!!!!!! this array size needs to be set, the number inside the []
- int Dust_Array[2]; // Array size should be max number of dust animations active at one time
- // Formula is ( (DustAFrames*DustASpeed) / 4 )
- //END Pegasus Boots global variables
- // -------------------------------------------------------------------------------
- // Pegasus Boots functions
- item script PegasusBoots{
- void run(){
- if(ComboFI(Link->X+8,Link->Y + Cond(BIG_LINK==0, 12, 8),CF_DASH)) Quit(); // can't dash on non-solid dash combos
- if(CanDrown == 0 && IsWater(TouchedComboLoc()) ) Quit(); // stop beside non-drownable water
- if(Link->Action == LA_SWIMMING || Link->Action == LA_DROWNING) Quit(); // can't use dash when in water
- if(IsJumping()) Quit(); // can't initiate dash while jumping
- // Link won't dash if facing up or down in sideview
- if(IsSideview()){
- if(Link->Dir == DIR_UP || Link->Dir == DIR_DOWN) Quit();
- }
- PegasusDash = Link->Dir;
- if(Link->InputB && !Link->InputA) StoreInput = 2;
- else if(Link->InputA && !Link->InputB) StoreInput = 1;
- }
- }
- // Stops dashing, no collision. Easy for other scripts to call.
- void StopDash(){
- PegasusDash = -1;
- DashCounter = 0;
- }
- // takes care of all the PegasusBoots functions
- // call it in your global while loop, above the waitdraw and waitframe.
- void PegasusBoots(){
- lweapon mysword;
- int loc = ComboAt(Link->X+8,Link->Y + Cond(BIG_LINK==0, 12, 8));
- // this fixes the bug that makes Link dive immediately after dashing into water with flippers
- if(DashCounter < 0){
- DashCounter++;
- if(Link->Action == LA_SWIMMING){
- Link->InputA = false;
- }else if(Link->Action == LA_DIVING){
- Link->Action == LA_SWIMMING;
- Link->InputA = false;
- }else{
- DashCounter = 0;
- }
- }
- // fixs a bug with drownable water and diagonal movement off
- if(CanDrown == 1 && IsWater(loc)
- && Link->Action != LA_SWIMMING && Link->Action != LA_DROWNING && Link->Action != LA_DIVING){
- if(Link->Dir == DIR_UP) Link->InputUp = true;
- else if(Link->Dir == DIR_DOWN) Link->InputDown = true;
- else if(Link->Dir == DIR_LEFT) Link->InputLeft = true;
- else if(Link->Dir == DIR_RIGHT) Link->InputRight = true;
- }
- if(PegasusDash >= 0){
- if(!PegasusCollision){
- if( (Link->Action != LA_SCROLLING && ((StoreInput == 1 && !Link->InputA) || (StoreInput == 2 && !Link->InputB)))
- || StoreHP > Link->HP || Link->Action == LA_RAFTING
- || Link->Action == LA_DROWNING || Link->Action == LA_SWIMMING || Link->Action == LA_DIVING
- || (CanDrown == 0 && IsWater(TouchedComboLoc())) || (CanDrown == 1 && IsWater(loc)) ){
- StopDash();
- if(Link->Action == LA_SWIMMING) DashCounter = -20;
- }
- if(!UsingItem(I_ROCSFEATHER_INCREASER))
- NoAction();
- if(Link->Item[I_ROCSFEATHER] && !Link->Item[I_ROCSFEATHER_INCREASER]){
- Link->Item[I_ROCSFEATHER_INCREASER]=true;
- }
- // Link runs on spot for 10 frames before dash happens
- if(Link->Action != LA_SCROLLING && DashCounter > 10){
- if(PegasusDash == DIR_UP && DashCheck(Link->X+8,Link->Y+6,true) != 2){
- Link->Y--;
- drawY--;
- Link->InputUp = true;
- }
- else if(PegasusDash == DIR_DOWN && DashCheck(Link->X+8,Link->Y+17,true) != 2){
- Link->Y++;
- drawY++;
- Link->InputDown = true;
- }
- else if(PegasusDash == DIR_LEFT && DashCheck(Link->X,Link->Y+12,false) != 2){
- Link->X--;
- drawX--;
- Link->InputLeft = true;
- }
- else if(PegasusDash == DIR_RIGHT && DashCheck(Link->X+16,Link->Y+12,false) != 2){
- Link->X++;
- drawX++;
- Link->InputRight = true;
- }
- else{
- PegasusCollision = true;
- DashCounter = 0;
- }
- }//end DashCounter if
- // do stuff if not jumping
- if( !IsJumping() ){
- // handles breaking of solid Pegasus combos
- if(ComboFI(loc,CF_DASH) && Screen->ComboS[loc] == 1111b){
- Screen->ComboD[loc]=INV_COMBO_ID;
- if(Screen->ComboF[loc] == CF_DASH) Screen->ComboF[loc] = 0;
- Game->PlaySound(SFX_PEGASUSBREAK);
- }
- DustDrawTile(); // use new dust draw code that works while scrolling
- // DustDrawLW(); // use old dust draw code that doesn't work while scrolling (quest rule "no screen scrolling" on)
- if(DashCounter%DashSFXLength == 0) Game->PlaySound(SFX_DASH);
- }
- // draws dashSword when scrolling
- if(Link->Action == LA_SCROLLING && dashSwordTile > 0){
- if(PegasusDash == DIR_UP)
- Screen->DrawTile(0,drawX+InFrontX(DIR_UP,6),drawY+InFrontY(DIR_UP,6),
- dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,0,true,128);
- else if(PegasusDash == DIR_DOWN)
- Screen->DrawTile(0,drawX+InFrontX(DIR_DOWN,6),drawY+InFrontY(DIR_DOWN,6),
- dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,3,true,128);
- else if(PegasusDash == DIR_LEFT)
- Screen->DrawTile(0,drawX+InFrontX(DIR_LEFT,6),drawY+InFrontY(DIR_LEFT,6)+3,
- dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,1,true,128);
- else if(PegasusDash == DIR_RIGHT)
- Screen->DrawTile(0,drawX+InFrontX(DIR_RIGHT,6),drawY+InFrontY(DIR_RIGHT,6)+3,
- dashSwordTile,1,1,dashSwordCSet,-1,-1,0,0,0,0,true,128);
- }
- int swordEquip = LinkSwordEquip();
- if(swordEquip > -1 && DashCounter>10){
- // draws dashSword when not scrolling
- mysword = LoadLWeaponOf(LW_SCRIPT3);
- if(!mysword->isValid()) mysword = Screen->CreateLWeapon(LW_SCRIPT3);
- if(swordEquip==I_SWORD4){
- mysword->UseSprite(SPRITE_SWORD4);
- }else if(swordEquip==I_SWORD3){
- mysword->UseSprite(SPRITE_SWORD3);
- }else if(swordEquip==I_SWORD2){
- mysword->UseSprite(SPRITE_SWORD2);
- }else{
- mysword->UseSprite(SPRITE_SWORD1);
- }//end sprite if
- if(DASH_SWORD_MULT > 0){
- itemdata itm = Game->LoadItemData(swordEquip);
- mysword->Damage = itm->Power * DASH_SWORD_MULT;
- }
- else mysword->Damage = DASH_SWORD_DMG;
- mysword->X = Link->X+InFrontX(PegasusDash, 6);
- mysword->Y = Link->Y+InFrontY(PegasusDash, 6);
- mysword->Dir = PegasusDash;
- if(mysword->Dir < 2){ //dir is up or down
- if(mysword->Dir == DIR_DOWN) mysword->Flip = 3;
- }
- else{ //dir is left or right
- mysword->OriginalTile += 1;
- mysword->Tile = mysword->OriginalTile;
- if(mysword->Dir == DIR_LEFT) mysword->Flip = 1;
- mysword->Y += 3;
- }//end dir if
- // save our sword sprite for when scrolling
- dashSwordTile = mysword->Tile;
- dashSwordCSet = mysword->OriginalCSet;
- // slash stuff while dashing with sword
- DoDashSlash(ComboAt(TouchedX()+InFrontX(mysword->Dir,4),TouchedY()+InFrontY(mysword->Dir,4)));
- }
- else{ // we don't have dashSword
- mysword = LoadLWeaponOf(LW_SCRIPT3);
- Remove(mysword);
- dashSwordTile = 0;
- dashSwordCSet = 0;
- }//end mysword if
- }//end !PegasusCollision if
- else{ //is PegasusCollision, DashCounter has been reset to 0.
- NoAction();
- // knockback code
- if(PegasusDash == DIR_UP && DashCheck(Link->X+8,Link->Y+18,true) == 0) Link->Y++;
- else if(PegasusDash == DIR_DOWN && DashCheck(Link->X+8,Link->Y+6,true) == 0) Link->Y--;
- else if(PegasusDash == DIR_LEFT && DashCheck(Link->X+18,Link->Y+8,false) == 0) Link->X++;
- else if(PegasusDash == DIR_RIGHT && DashCheck(Link->X-2,Link->Y+8,false) == 0) Link->X--;
- if(DashCounter == 1){
- Screen->ClearSprites(SL_LWPNS);
- Game->PlaySound(SFX_HITWALL);
- Screen->Quake = 10;
- }
- else if(DashCounter == 10){
- StopDash();
- PegasusCollision = false;
- }
- if(DashCounter < 5) Link->Z++;
- }// end PegasusCollision if/else
- DashCounter++;
- }// end PegasusDash if
- else{ // !PegasusDash
- mysword = LoadLWeaponOf(LW_SCRIPT3);
- Remove(mysword);
- dashSwordTile = 0;
- dashSwordCSet = 0;
- if(Link->Item[I_ROCSFEATHER_INCREASER]) Link->Item[I_ROCSFEATHER_INCREASER]=false;
- }//end PegasusDash if/else
- StoreHP = Link->HP;
- }//end function
- // next two functions draw dust when dashing. first one allows drawing during scrolling. the second is the old code, and currently unused.
- void DustDrawTile(){
- if(PegasusDash < 0) return;
- int dX;
- int dY;
- if(DashCounter%4 == 0){
- for(int i = 0; i < SizeOfArray(Dust_Array); i++){
- if(Dust_Array[i] == 0){
- Dust_Array[i] = 1;
- break;
- }
- }
- }
- for(int i = 0; i < SizeOfArray(Dust_Array); i++){
- if(Dust_Array[i]==0) continue;
- if(PegasusDash == DIR_UP){
- dX = drawX;
- if(Dust_Array[i] < 4) dY = drawY+8;
- else dY = drawY+8+3+(Dust_Array[i]-1);
- }else if(PegasusDash == DIR_DOWN){
- dX = drawX;
- if(Dust_Array[i] < 4) dY = drawY;
- else dY = drawY-3-(Dust_Array[i]-1);
- }else if(PegasusDash == DIR_LEFT){
- if(Dust_Array[i] < 4) dX = drawX;
- else dX = drawX+3+(Dust_Array[i]-1);
- dY = drawY+8;
- }else if(PegasusDash == DIR_RIGHT){
- if(Dust_Array[i] < 4) dX = drawX;
- else dX = drawX-3-(Dust_Array[i]-1);
- dY = drawY+8;
- }
- Screen->FastTile(0, dX, dY, T_DUST+ Floor(Dust_Array[i]/DustASpeed), DustCSet, 128);
- if(Dust_Array[i] == DustAFrames*DustASpeed) Dust_Array[i] = 0;
- else Dust_Array[i]++;
- }
- }
- void DustDrawLW(){
- if(PegasusDash < 0) return;
- lweapon Dust;
- if(DashCounter%4 == 0){
- for(int j=1;j<=Screen->NumLWeapons();j++){
- Dust = Screen->LoadLWeapon(j);
- if(Dust->ID != LW_SCRIPT10) continue;
- if(PegasusDash < 1) Dust->Y-=3;
- else if(PegasusDash < 2) Dust->Y+=3;
- else if(PegasusDash < 3) Dust->X-=3;
- else if(PegasusDash < 4) Dust->X+=3;
- }//end for loop
- Dust = Screen->CreateLWeapon(LW_SCRIPT10);
- Dust->OriginalTile = T_DUST;
- Dust->CSet = DustCSet;
- Dust->Y = Link->Y+8;
- Dust->X = Link->X;
- Dust->NumFrames = DustAFrames;
- Dust->ASpeed = DustASpeed;
- Dust->DeadState = DustAFrames*DustASpeed;
- }//end dust if
- }
- // Check whether Link can dash onto a combo
- int DashCheck(int x, int y, bool xy){
- int xoffset; int yoffset;
- bool Solid;
- if(xy) xoffset = 4;
- else yoffset = 3;
- if(Screen->isSolid(x-xoffset,y-yoffset) || Screen->isSolid(x+xoffset,y+yoffset)) Solid = true;
- if(Solid && CanDashSlash(x,y) ) Solid = false;
- //Not solid and not a Dash combo return 0
- if(!Solid && !ComboFI(x-xoffset,y-yoffset,CF_DASH) && !ComboFI(x+xoffset,y+yoffset,CF_DASH)) return 0;
- //Is solid and is a Dash combo return 1
- else if(Solid && (ComboFI(x-xoffset,y-yoffset,CF_DASH) || ComboFI(x+xoffset,y+yoffset,CF_DASH))) return 1;
- //Is either solid without a Dash combo, or not solid with a Dash combo
- else return 2;
- }
- //fixes a bug where you can't initiate a dash next to a slashable solid combo
- bool CanDashSlash(int x, int y){
- if(LinkSwordEquip() == -1) return false;
- int loc;
- loc = ComboAt(x, y);
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // can add more combo types here by adding || Screen->ComboT[loc] == CT_
- // CT_ types you might consider CT_SLASH, CT_SLASHNEXT, CT_SLASHNEXTITEM if those are solid in your quest
- if(Screen->ComboT[loc] == CT_BUSH || Screen->ComboT[loc] == CT_BUSHNEXT )
- return true;
- return false;
- }
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // replaces the code in old Pegasus boots function for dash cutting through slashable combos.
- // allows easier customization to suit your needs.
- void DoDashSlash(int loc){
- int ctype = Screen->ComboT[loc];
- int sprite;
- int itmset = IS_COMBOS; // item set 12 (tall grass by default)
- bool playsound = false;
- // add sprites to certain types
- if(ctype == CT_BUSH || ctype == CT_BUSHNEXT) sprite = SPRITE_BUSH_CUT;
- else if(ctype == CT_TALLGRASS || ctype == CT_TALLGRASSNEXT) sprite = SPRITE_GRASS_CUT;
- else if(ctype == CT_FLOWERS) sprite = SPRITE_FLOWER_CUT;
- // no sprite is typically associated with Slash type combos, but it could be added.
- // itemset is changed here to the default for these types. could add more item sets based on type
- if(ctype == CT_SLASHITEM || ctype == CT_SLASHNEXTITEM) itmset = 10; // default for these combo types
- //these types default to undercombo
- if(ctype == CT_BUSH || ctype == CT_TALLGRASS || ctype == CT_FLOWERS || ctype == CT_SLASH || ctype == CT_SLASHITEM){
- Screen->ComboD[loc] = Screen->UnderCombo;
- playsound = true;
- }
- //these types default to next combo
- if(ctype == CT_BUSHNEXT || ctype == CT_TALLGRASSNEXT || ctype == CT_FLOWERS || ctype == CT_SLASHNEXT || ctype == CT_SLASHNEXTITEM){
- Screen->ComboD[loc] += 1;
- playsound = true;
- }
- //no functionality added for Continuous type combos.
- if(playsound){
- CreateGraphicAt(sprite,ComboX(loc),ComboY(loc));
- Game->PlaySound(SFX_GRASSCUT); // could have different sounds for different types too by modifyng above.
- ItemSetAt(itmset,loc);
- }//end playsound if
- }
- // END Pegasus Boots functions
- // .............................................................................................................................................................................
- // Utility Functions used by Pegasus Boots and other scripts that might be useful for other things .......................................................................................
- //returns the item# of an equipped sword. checks and returns A button first, then B button. returns -1 if no sword equipped.
- int LinkSwordEquip(){
- itemdata itm = Game->LoadItemData( GetEquipmentA() );
- if(itm->Family==IC_SWORD) return GetEquipmentA();
- itm = Game->LoadItemData(GetEquipmentB());
- if(itm->Family==IC_SWORD) return GetEquipmentB();
- return -1;
- }
- // the combo that link is touching in the direction he's facing
- int TouchedComboLoc(){
- int loc;
- loc = ComboAt( TouchedX(), TouchedY() );
- return loc;
- }
- // the x coord that link is touching in the direction he's facing
- int TouchedX(){
- int x = 0;
- if(Link->Dir == DIR_UP || Link->Dir == DIR_DOWN) x = Link->X+8;
- else if(Link->Dir == DIR_LEFT) x = Link->X-1;
- else if(Link->Dir == DIR_RIGHT) x = Link->X+17;
- return x;
- }
- // the y coord that link is touching in the direction he's facing
- int TouchedY(){
- int y = 0;
- if(Link->Dir == DIR_UP) y = Link->Y+7;
- else if(Link->Dir == DIR_DOWN) y = Link->Y+17;
- else if(Link->Dir == DIR_LEFT || Link->Dir == DIR_RIGHT) y = Link->Y+8;
- return y;
- }
- // draws a sprite as a non-damaging eweapon
- int CreateGraphicAt(int sprite, int x, int y){
- eweapon e = Screen->CreateEWeapon(EW_SCRIPT1);
- e->HitXOffset = 500;
- e->UseSprite(sprite);
- e->DeadState = Max(1,e->NumFrames*e->ASpeed);
- e->X = x;
- e->Y = y;
- return e->DeadState;
- }
- //creates and kills an enemy of type NPC_ITEMSET to fake an itemdropset.
- void ItemSetAt(int itemset,int loc){
- npc e = Screen->CreateNPC(NPC_ITEMSET);
- e->ItemSet = itemset;
- if(e->isValid()){
- e->X = loc%16*16;
- e->Y = loc-loc%16;
- }
- e->HP = HP_SILENT;
- }
- // utility function returns true if Link is jumping, necessary because SideView gravity sucks
- // might need tweaking depending on other SideView scripts you use.
- bool IsJumping(){
- if(IsSideview()){
- if(Link->Action == LA_SWIMMING || Link->Action == LA_DIVING || Link->Action == LA_DROWNING) return false;
- if(Link->Jump != 0) return true;
- if(!OnSidePlatform(Link->X,Link->Y)) return true;
- }
- else{
- if(Link->Z > 0) return true;
- }
- return false;
- }
- // Allows drawing tiles to correct position on Link when scrolling
- // Sets drawX/drawY either to Link X/Y when not scrolling, or the visual position when scrolling.
- // currently only used by Pegasus Boots (which is also setting drawX/drawY to Link's new x/y as he dashes)
- void ScrollFix(){
- //function by Saffith
- if(Link->Action==LA_SCROLLING){
- if(scrollDir==-1)
- {
- if(Link->Y>160)
- {
- scrollDir=DIR_UP;
- scrollCounter=45;
- }
- else if(Link->Y<0)
- {
- scrollDir=DIR_DOWN;
- scrollCounter=45;
- }
- else if(Link->X>240)
- {
- scrollDir=DIR_LEFT;
- scrollCounter=65;
- }
- else
- {
- scrollDir=DIR_RIGHT;
- scrollCounter=65;
- }
- }
- if(scrollDir==DIR_UP && scrollCounter<45 && scrollCounter>4)
- drawY+=4;
- else if(scrollDir==DIR_DOWN && scrollCounter<45 && scrollCounter>4)
- drawY-=4;
- else if(scrollDir==DIR_LEFT && scrollCounter<65 && scrollCounter>4)
- drawX+=4;
- else if(scrollDir==DIR_RIGHT && scrollCounter<65 && scrollCounter>4)
- drawX-=4;
- scrollCounter--;
- }
- else
- {
- drawX=Link->X;
- drawY=Link->Y;
- if(scrollDir!=-1)
- scrollDir=-1;
- }
- }
- //END Utility functions
- // .............................................................................................................................................................................
- // .............................................................................................................................................................................
- // Sample global script using Pegasus Boots.
- // If you aren't using any other global scripts, you can just import this as is.
- //** If you have an existing global script, just add ScrollFix(); the top of the while loop
- //** and PegasusBoots(); below that, but before the Waitdraw(); and Waitframe();
- //** And remove, or comment this global script out.
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- ///Common Constant, only need to define once per script file.
- //const int BIG_LINK = 0; //Set this to 1 if using the Large Link Hit Box feature.
- //Constants used by Ice Combos
- const int CT_ICECOMBO = 142; //The combo type "Script1 by default"
- const int ICE_ACCELERATION = 1;
- const int ICE_DECELERATION = 1;
- const int ICE_MAXSTEP = 150;
- //Declare global variables used by Ice Combos.
- bool isScrolling;
- bool onice;
- float Ice_X;
- float Ice_Y;
- int Ice_XStep;
- int Ice_YStep;
- //End declaration
- //Active Script
- //Initializes global variables used for ice combos.
- void Setup_IceCombos()
- {
- isScrolling = false;
- onice = false;
- Ice_X = 0;
- Ice_Y = 0;
- Ice_XStep = 0;
- Ice_YStep = 0;
- }
- //Adds Ice Combo functionally to CT_ICECOMBO;
- void Update_IceCombos(int oldscreen)
- {
- //Update Variables
- if(Link->Action != LA_SCROLLING)
- {
- if(isScrolling || oldscreen != Game->GetCurScreen() || (!onice && OnIce()))
- {
- Ice_X = Link->X;
- Ice_Y = Link->Y;
- if(isScrolling)
- isScrolling = false;
- else
- {
- Ice_XStep = 0;
- Ice_YStep = 0;
- }
- }
- onice = OnIce();
- }
- else
- {
- isScrolling = true;
- return;
- }
- //Ice Physics
- if(onice)
- {
- //Y Adjustment
- if(Link_Walking() && (Link->InputUp || Link->InputDown))
- {
- if(Link->InputUp && !Link->InputDown)
- Ice_YStep -= ICE_ACCELERATION;
- else if(!Link->InputUp && Link->InputDown)
- Ice_YStep += ICE_ACCELERATION;
- }
- else if(Ice_YStep != 0)
- Ice_YStep = Cond(Abs(Ice_YStep) - ICE_DECELERATION > 0, Ice_YStep - Sign(Ice_YStep)*ICE_DECELERATION, 0);
- Ice_YStep = Clamp(Ice_YStep, -ICE_MAXSTEP, ICE_MAXSTEP);
- //X Adjustment
- if(Link_Walking() && (Link->InputLeft || Link->InputRight))
- {
- if(Link->InputLeft && !Link->InputRight)
- Ice_XStep -= ICE_ACCELERATION;
- else if(!Link->InputLeft && Link->InputRight)
- Ice_XStep += ICE_ACCELERATION;
- }
- else if(Ice_XStep != 0)
- Ice_XStep = Cond(Abs(Ice_XStep) - ICE_DECELERATION > 0, Ice_XStep -Sign(Ice_XStep)*ICE_DECELERATION, 0);
- Ice_XStep = Clamp(Ice_XStep, -ICE_MAXSTEP, ICE_MAXSTEP);
- //Reset the Ice Position to Link's Actual Position if he's hurt or hopping out of water.
- if(Link->Action == LA_GOTHURTLAND || Link->Action == LA_HOPPING)
- {
- Ice_X = Link->X;
- Ice_Y = Link->Y;
- }
- //Initialize variables for solidity checking.
- int newx = (Ice_X + Ice_XStep/100)<<0;
- int newy = (Ice_Y + Ice_YStep/100)<<0;
- //Vertical Edge
- if(newx < Ice_X<<0)
- {
- for(int y = Ice_Y+Cond(BIG_LINK, 0, 8); y < (Ice_Y<<0) + 16 && Ice_XStep != 0; y++)
- {
- if(Screen->isSolid(newx, y))
- Ice_XStep = 0;
- }
- }
- else if(newx > Ice_X<<0)
- {
- for(int y = Ice_Y+8; y < (Ice_Y<<0) + 16 && Ice_XStep != 0; y++)
- {
- if(Screen->isSolid(newx+15, y))
- Ice_XStep = 0;
- }
- }
- //Horizontal Edge
- if(newy < Ice_Y<<0)
- {
- for(int x = Ice_X; x < (Ice_X<<0) + 16 && Ice_YStep != 0; x++)
- {
- if(Screen->isSolid(x, newy+Cond(BIG_LINK, 0, 8)))
- {
- Ice_YStep = 0;
- }
- }
- }
- else if(newy > Ice_Y<<0)
- {
- for(int x = Ice_X; x < (Ice_X<<0) + 16 && Ice_YStep != 0; x++)
- {
- if(Screen->isSolid(x, newy+15))
- {
- Ice_YStep = 0;
- }
- }
- }
- Ice_X += Ice_XStep/100;
- Ice_Y += Ice_YStep/100;
- Link->X = Ice_X;
- Link->Y = Ice_Y;
- }
- else
- {
- Ice_XStep = 0;
- Ice_YStep = 0;
- }
- }
- //Function used to check if Link is over a ice combo.
- bool OnIce()
- {
- if(Link->Z != 0)
- return false;
- else
- {
- int comboLoc = ComboAt(Link->X + 8, Link->Y + 12);
- if(Screen->ComboT[comboLoc] == CT_ICECOMBO)
- return true;
- else if(Screen->LayerScreen(1) != -1 && GetLayerComboT(1, comboLoc) == CT_ICECOMBO)
- return true;
- else if(Screen->LayerScreen(2) != -1 && GetLayerComboT(2, comboLoc) == CT_ICECOMBO)
- return true;
- else
- return false;
- }
- }
- //Returns true, if keyboard input is moving Link.
- bool Link_Walking()
- {
- if(UsingItem(I_HAMMER)) return false;
- else return (Link->Action == LA_WALKING || Link->Action == LA_CHARGING || Link->Action == LA_SPINNING);
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- const int CMB_MINECART = 7688; //Combo of the minecart, first of 16
- //1-4: Minecart, stationary, 4-way
- //5-8: Minecart, moving, 4-way
- //9-12: Minecart, front layer, 4-way
- //13-16: Link riding in minecart, 4-way
- const int CS_MINECART = 2;
- const int CMB_MINECART_TRACK = 7680; //First of a set of 7 minecart track combos.
- //Only these combos when placed on layer 0 will actually function as minecart tracks
- //1: Up/Down
- //2: Left/Right
- //3: Right/Down
- //4: Left/Down
- //5: Right/Up
- //6: Left/Up
- //7: Exit pad
- const int SFX_MINECART = 65; //Looping sound of the minecart on the tracks
- const int MINECART_SFX_FREQ = 30; //How often the sound loops
- const int MINECART_LINKYOFFSET = -10; //Offset Link's sprite is drawn at compared to the minecart
- const int DAMAGE_MINECART_COLLISION = 8; //How much damage the minecart does when it hits enemies
- const int LW_MINECART_DAMAGE = 2; //Weapon type the minecart's hitbox uses. LW_BEAM by default
- int GBCart[80];
- const int GBC_DIR = 65;
- const int GBC_CURID = 66;
- const int GBC_FIRSTLOAD = 67;
- const int GBC_ACTIVEFFC = 68;
- void Minecart_Init(){
- Link->DrawYOffset = 0;
- Link->CollDetection = true;
- GBCart[GBC_DIR] = -1;
- if(GBCart[GBC_FIRSTLOAD]==0){
- for(int i=0; i<64; i++){
- GBCart[i] = -1;
- }
- GBCart[GBC_FIRSTLOAD] = 1;
- }
- }
- void Minecart_Update(){
- if(GBCart[GBC_DIR]>-1){
- int scr[] = "GBMinecart_FFC";
- Link->DrawYOffset = MINECART_LINKYOFFSET;
- Link->CollDetection = false;
- if(Link->Action==LA_SCROLLING){
- GBCart[GBC_ACTIVEFFC] = -1;
- Minecart_Draw(ScrollingLinkX(), ScrollingLinkY(), GBCart[GBC_DIR], true);
- }
- else if(GBCart[GBC_ACTIVEFFC]>0){
- ffc f = Screen->LoadFFC(GBCart[GBC_ACTIVEFFC]);
- if(f->Script==Game->GetFFCScript(scr)){
- Link->X = f->X;
- Link->Y = f->Y;
- }
- }
- if(Minecart_CountFFCs(Game->GetFFCScript(scr), GBCart[GBC_CURID])==0){
- ffc f = Screen->LoadFFC(GBCart[GBC_ACTIVEFFC]);
- if(f->Script!=Game->GetFFCScript(scr)||f->InitD[1]!=GBCart[GBC_CURID]){
- if(Link->X>=0&&Link->X<=240&&Link->Y>=0&&Link->Y<=160){
- int args[8];
- args[0] = GBCart[GBC_DIR];
- args[1] = GBCart[GBC_CURID];
- args[2] = 0;
- args[3] = 1;
- f = Screen->LoadFFC(RunFFCScript(Game->GetFFCScript(scr), args));
- f->CSet = CS_MINECART;
- GBCart[GBC_ACTIVEFFC] = FFCNum(f);
- f->Flags[FFCF_PRELOAD] = true;
- f->X = Link->X;
- f->Y = Link->Y;
- }
- }
- }
- }
- }
- int Minecart_CountFFCs(int scrpt, int id){
- int count;
- for(int i=1; i<=32; i++){
- ffc f = Screen->LoadFFC(i);
- if(f->Script==scrpt&&f->InitD[1]==id&&f->InitD[3]==1)
- count++;
- }
- return count;
- }
- void Minecart_Draw(int x, int y, int dir, bool linkInside){
- int layer = 2;
- if(ScreenFlag(1, 4))
- layer = 1;
- dir = Clamp(dir, 0, 3);
- if(linkInside){
- Screen->FastCombo(layer, x, y, CMB_MINECART+4+dir, CS_MINECART, 128);
- if(Link->Action==LA_WALKING||Link->Action==LA_NONE||Link->Action==LA_SCROLLING){
- Screen->FastCombo(layer, x, y+MINECART_LINKYOFFSET, CMB_MINECART+12+Link->Dir, 6, 128);
- Link->Invisible = true;
- }
- else
- Link->Invisible = false;
- Screen->FastCombo(4, x, y, CMB_MINECART+8+dir, CS_MINECART, 128);
- }
- else{
- Screen->FastCombo(layer, x, y, CMB_MINECART+dir, CS_MINECART, 128);
- }
- }
- ffc script GBMinecart_FFC{
- void run(int startDir, int ID, int start, int spawned){
- int ffcNum = FFCNum(this);
- int tempID;
- if(ID>0)
- tempID = Clamp(ID-1, 0, 63);
- if(GBCart[GBC_DIR]<=-1||GBCart[GBC_CURID]!=ID)
- this->Data = CMB_MINECART+startDir;
- else if(spawned==0){
- if(Link->X<=0||Link->X>=240||Link->Y<=0||Link->Y>=160){
- this->Data = 0;
- Quit();
- }
- else{
- GBCart[GBC_DIR] = -1;
- Waitframe();
- }
- }
- else{
- if(GBCart[GBC_ACTIVEFFC]==-1)
- GBCart[GBC_ACTIVEFFC] = ffcNum;
- }
- if(spawned==0&&GBCart[GBC_DIR]==-1&&ID>0){
- if(GBCart[tempID]==-1){
- if(start){
- GBCart[tempID] = Game->GetCurScreen();
- }
- else{
- this->Data = 0;
- Quit();
- }
- }
- else if(GBCart[tempID]!=Game->GetCurScreen()&&GBCart[GBC_FIRSTLOAD]==1){
- this->Data = 0;
- Quit();
- }
- }
- int lastDir = startDir;
- int sfxCounter;
- lweapon hitbox;
- while(true){
- while(GBCart[GBC_DIR]==-1||GBCart[GBC_CURID]!=ID){
- this->Data = CMB_MINECART+startDir;
- if(Link->Y<this->Y)
- this->Flags[FFCF_OVERLAY] = true;
- else
- this->Flags[FFCF_OVERLAY] = false;
- if(GBMinecart_Collision(this)){
- while(Link->Z>0){
- WaitNoAction();
- }
- this->Flags[FFCF_OVERLAY] = false;
- Link->Dir = AngleDir4(Angle(Link->X, Link->Y, this->X, this->Y));
- Link->Jump = 2;
- Game->PlaySound(SFX_JUMP);
- int angle = Angle(Link->X, Link->Y, this->X, this->Y+MINECART_LINKYOFFSET);
- int dist = Distance(Link->X, Link->Y, this->X, this->Y+MINECART_LINKYOFFSET);
- int linkX = Link->X;
- int linkY = Link->Y;
- for(int i=0; i<26; i++){
- linkX += VectorX(dist/26, angle);
- linkY += VectorY(dist/26, angle);
- Link->X = linkX;
- Link->Y = linkY;
- WaitNoAction();
- }
- Link->DrawYOffset = MINECART_LINKYOFFSET;
- Link->CollDetection = false;
- GBCart[GBC_DIR] = startDir;
- GBCart[GBC_CURID] = ID;
- GBCart[GBC_ACTIVEFFC] = FFCNum(this);
- sfxCounter = 0;
- }
- Waitframe();
- }
- while(GBCart[GBC_DIR]!=-1&&GBCart[GBC_CURID]==ID){
- int cp = ComboAt(this->X+8, this->Y+8);
- lastDir = GBCart[GBC_DIR];
- GBCart[GBC_DIR] = GBMinecart_NextDirection(cp, GBCart[GBC_DIR]);
- for(int i=0; i<8&&GBCart[GBC_DIR]>-1; i++){
- if(sfxCounter==0)
- Game->PlaySound(SFX_MINECART);
- sfxCounter++;
- if(sfxCounter>MINECART_SFX_FREQ)
- sfxCounter = 0;
- if(GBCart[GBC_DIR]==DIR_UP)
- this->Y -= 2;
- else if(GBCart[GBC_DIR]==DIR_DOWN)
- this->Y += 2;
- else if(GBCart[GBC_DIR]==DIR_LEFT)
- this->X -= 2;
- else if(GBCart[GBC_DIR]==DIR_RIGHT)
- this->X += 2;
- this->Data = FFCS_INVISIBLE_COMBO;
- hitbox = GBMinecart_UpdateHitbox(hitbox, this->X, this->Y, true);
- Minecart_Draw(this->X, this->Y, GBCart[GBC_DIR], true);
- Link->X = this->X;
- Link->Y = this->Y;
- Waitframe();
- }
- this->X = GridX(this->X+8);
- this->Y = GridY(this->Y+8);
- if(GBCart[GBC_DIR]<=-1){
- if(GBCart[GBC_DIR]<-1)
- lastDir = Abs(GBCart[GBC_DIR])-2;
- GBCart[GBC_DIR] = -1;
- this->Data = CMB_MINECART+lastDir;
- Link->DrawYOffset = 0;
- Link->Invisible = false;
- Link->CollDetection = true;
- cp = GBMinecart_ComboInFront(cp, lastDir);
- Link->Dir = AngleDir4(Angle(Link->X, Link->Y, ComboX(cp), ComboY(cp)));
- Link->Y += MINECART_LINKYOFFSET;
- Link->Jump = 2;
- Game->PlaySound(SFX_JUMP);
- int angle = Angle(Link->X, Link->Y, ComboX(cp), ComboY(cp));
- int dist = Distance(Link->X, Link->Y, ComboX(cp), ComboY(cp));
- int linkX = Link->X;
- int linkY = Link->Y;
- for(int i=0; i<26; i++){
- linkX += VectorX(dist/26, angle);
- linkY += VectorY(dist/26, angle);
- Link->X = linkX;
- Link->Y = linkY;
- hitbox = GBMinecart_UpdateHitbox(hitbox, this->X, this->Y, false);
- WaitNoAction();
- }
- startDir = OppositeDir(lastDir);
- if(GBCart[GBC_CURID]>0){
- tempID = Clamp(GBCart[GBC_CURID]-1, 0, 63);
- GBCart[tempID] = Game->GetCurScreen();
- }
- //MooshPit_ResetEntry();
- }
- }
- }
- }
- int GBMinecart_NextDirection(int cp, int dir){
- int up[6] = {1, 0, 0, 0, 1, 1};
- int down[6] = {1, 0, 1, 1, 0, 0};
- int left[6] = {0, 1, 0, 1, 0, 1};
- int right[6] = {0, 1, 1, 0, 1, 0};
- int directions[4] = {up, down, left, right};
- int c;
- //Combo under
- c = Screen->ComboD[cp];
- if(c>=CMB_MINECART_TRACK&&c<=CMB_MINECART_TRACK+5)
- c = Clamp(c-CMB_MINECART_TRACK, 0, 5);
- else
- c = -1;
- int frontDir = -1;
- int d = directions[dir];
- if(d[c]==1&&frontDir==-1){
- frontDir = dir;
- }
- else{
- for(int i=0; i<4; i++){
- if(i!=OppositeDir(dir)&&i!=dir){
- d = directions[i];
- if(d[c]==1){
- int c2 = Screen->ComboD[GBMinecart_ComboInFront(cp, i)];
- if(c2>=CMB_MINECART_TRACK&&c2<=CMB_MINECART_TRACK+5)
- return i;
- if(c2==CMB_MINECART_TRACK+6)
- return -2-i;
- else
- return OppositeDir(dir);
- }
- }
- }
- }
- c = Screen->ComboD[GBMinecart_ComboInFront(cp, dir)];
- if(c>=CMB_MINECART_TRACK&&c<=CMB_MINECART_TRACK+6)
- c = Clamp(c-CMB_MINECART_TRACK, 0, 6);
- else
- c = -1;
- if(c==-1)
- return OppositeDir(dir);
- else if(c==6)
- return -1;
- if(frontDir>-1)
- return frontDir;
- return dir;
- }
- int GBMinecart_ComboInFront(int cp, int dir){
- if(cp<16&&dir==DIR_UP)
- return cp;
- else if(cp>159&&dir==DIR_DOWN)
- return cp;
- else if(cp%16==0&&dir==DIR_LEFT)
- return cp;
- else if(cp%16==15&&dir==DIR_RIGHT)
- return cp;
- if(dir==DIR_UP)
- cp -= 16;
- else if(dir==DIR_DOWN)
- cp += 16;
- else if(dir==DIR_LEFT)
- cp--;
- else if(dir==DIR_RIGHT)
- cp++;
- return cp;
- }
- bool GBMinecart_Collision(ffc this){
- if(Abs(Link->X-this->X)<12&&Abs(Link->Y-this->Y)<10)
- return true;
- return false;
- }
- lweapon GBMinecart_UpdateHitbox(lweapon hitbox, int x, int y, bool alive){
- if(hitbox->isValid()){
- hitbox->X = x;
- hitbox->Y = y;
- hitbox->Dir = GBCart[GBC_DIR];
- hitbox->Step = 0;
- hitbox->DeadState = -1;
- hitbox->DrawYOffset = -1000;
- if(!alive){
- hitbox->DeadState = 0;
- }
- }
- else{
- if(alive){
- hitbox = CreateLWeaponAt(LW_MINECART_DAMAGE, x, y);
- hitbox->Dir = GBCart[GBC_DIR];
- hitbox->Damage = DAMAGE_MINECART_COLLISION;
- hitbox->Step = 0;
- hitbox->DeadState = -1;
- hitbox->DrawYOffset = -1000;
- }
- }
- return hitbox;
- }
- }
- ffc script GBMinecart_Shutter{
- void run(){
- int thisData = this->Data;
- int thisCSet = this->CSet;
- this->Data = FFCS_INVISIBLE_COMBO;
- int cp = ComboAt(this->X+8, this->Y+8);
- int underCombo = Screen->ComboD[cp];
- int underCSet = Screen->ComboC[cp];
- int LinkX = Link->X;
- if(LinkX<=0)
- LinkX = 240;
- else if(LinkX>=240)
- LinkX = 0;
- int LinkY = Link->Y;
- if(LinkY<=0)
- LinkY = 160;
- else if(LinkY>=160)
- LinkY = 0;
- if(!(Abs(this->X-LinkX)<20&&Abs(this->Y-LinkY)<20)){
- Screen->ComboD[cp] = thisData;
- Screen->ComboC[cp] = thisCSet;
- while(GBCart[GBC_DIR]==-1||!(Abs(this->X-Link->X)<20&&Abs(this->Y-Link->Y)<20)){
- Waitframe();
- }
- Game->PlaySound(SFX_SHUTTER);
- Screen->ComboD[cp] = underCombo;
- Screen->ComboC[cp] = underCSet;
- this->Data = thisData+1;
- this->CSet = thisCSet;
- Waitframes(4);
- this->Data = FFCS_INVISIBLE_COMBO;
- }
- else{
- Waitframe();
- }
- while(true){
- while(GBCart[GBC_DIR]>-1&&(Abs(this->X-Link->X)<20&&Abs(this->Y-Link->Y)<20)){
- Waitframe();
- }
- Game->PlaySound(SFX_SHUTTER);
- this->Data = thisData+1;
- this->CSet = thisCSet;
- Waitframes(4);
- Screen->ComboD[cp] = thisData;
- Screen->ComboC[cp] = thisCSet;
- this->Data = FFCS_INVISIBLE_COMBO;
- while(GBCart[GBC_DIR]==-1||!(Abs(this->X-Link->X)<20&&Abs(this->Y-Link->Y)<20)){
- Waitframe();
- }
- Game->PlaySound(SFX_SHUTTER);
- Screen->ComboD[cp] = underCombo;
- Screen->ComboC[cp] = underCSet;
- this->Data = thisData+1;
- this->CSet = thisCSet;
- Waitframes(4);
- this->Data = FFCS_INVISIBLE_COMBO;
- }
- }
- }
- ffc script GBMinecart_ResetID{
- void run(int id1, int id2, int id3, int id4, int id5, int id6, int id7, int id8){
- if(Distance(Link->X, Link->Y, this->X, this->Y)<16){
- int ids[8];
- ids[0] = id1;
- ids[1] = id2;
- ids[2] = id3;
- ids[3] = id4;
- ids[4] = id5;
- ids[5] = id6;
- ids[6] = id7;
- ids[7] = id8;
- for(int i=0; i<8; i++){
- int tempID = Clamp(ids[i]-1, 0, 63);
- if(ids[i]>0)
- GBCart[tempID] = -1;
- }
- }
- }
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- const int QUESTRULE_VERYFASTSCROLLING = 1; //Set this to 1 if the Very Fast Scrolling quest rule is enabled
- int scrollingDraws[8];
- const int SD_NSCX = 0;
- const int SD_NSCY = 1;
- const int SD_OSCX = 2;
- const int SD_OSCY = 3;
- const int SD_SAVELASTSCREEN = 4;
- const int SD_LASTSCREEN = 5;
- const int SD_SCROLLDIR = 6;
- const int SD_SCROLLTIMER = 7;
- void ScrollingDraws_Init(){
- scrollingDraws[SD_SAVELASTSCREEN] = Game->GetCurScreen();
- scrollingDraws[SD_SCROLLTIMER] = -1;
- scrollingDraws[SD_NSCX] = -1000;
- scrollingDraws[SD_NSCY] = -1000;
- scrollingDraws[SD_OSCX] = 0;
- scrollingDraws[SD_OSCY] = 0;
- }
- void ScrollingDraws_Update(){
- if(Link->Action==LA_SCROLLING){
- //Try to get the direction the screen is scrolling based on the position of the last screen visited
- if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]-16)
- scrollingDraws[SD_SCROLLDIR] = DIR_UP;
- else if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]+16)
- scrollingDraws[SD_SCROLLDIR] = DIR_DOWN;
- else if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]-1)
- scrollingDraws[SD_SCROLLDIR] = DIR_LEFT;
- else if(Game->GetCurScreen()==scrollingDraws[SD_LASTSCREEN]+1)
- scrollingDraws[SD_SCROLLDIR] = DIR_RIGHT;
- //If Link just started scrolling, reset the timer
- if(scrollingDraws[SD_SCROLLTIMER]==-1){
- scrollingDraws[SD_SCROLLTIMER] = 0;
- }
- //Change max timer frames to account for Fast Scrolling
- int framesX = 64;
- int framesY = 44;
- if(QUESTRULE_VERYFASTSCROLLING){
- framesX = 16;
- framesY = 11;
- }
- //There's a few extra frames after the screen stops visibly scrolling. Clamp the timer to accommodate.
- int i;
- if(scrollingDraws[SD_SCROLLDIR]==DIR_UP||scrollingDraws[SD_SCROLLDIR]==DIR_DOWN)
- i = Clamp(scrollingDraws[SD_SCROLLTIMER], 0, framesY);
- else
- i = Clamp(scrollingDraws[SD_SCROLLTIMER], 0, framesX);
- int newScreenX;
- int newScreenY;
- int oldScreenX;
- int oldScreenY;
- int incrementX = 256/framesX;
- int incrementY = 176/framesY;
- //Set screen positions based on the timer
- if(scrollingDraws[SD_SCROLLDIR]==DIR_UP){
- newScreenX = 0;
- newScreenY = -176+incrementY*i;
- oldScreenX = 0;
- oldScreenY = incrementY*i;
- }
- else if(scrollingDraws[SD_SCROLLDIR]==DIR_DOWN){
- newScreenX = 0;
- newScreenY = 176-incrementY*i;
- oldScreenX = 0;
- oldScreenY = -incrementY*i;
- }
- else if(scrollingDraws[SD_SCROLLDIR]==DIR_LEFT){
- newScreenX = -256+incrementX*i;
- newScreenY = 0;
- oldScreenX = incrementX*i;
- oldScreenY = 0;
- }
- else if(scrollingDraws[SD_SCROLLDIR]==DIR_RIGHT){
- newScreenX = 256-incrementX*i;
- newScreenY = 0;
- oldScreenX = -incrementX*i;
- oldScreenY = 0;
- }
- scrollingDraws[SD_NSCX] = newScreenX;
- scrollingDraws[SD_NSCY] = newScreenY;
- scrollingDraws[SD_OSCX] = oldScreenX;
- scrollingDraws[SD_OSCY] = oldScreenY;
- if(scrollingDraws[SD_SCROLLTIMER]>=0)
- scrollingDraws[SD_SCROLLTIMER]++;
- }
- else{ //Globals are reset when Link isn't scrolling
- scrollingDraws[SD_SAVELASTSCREEN] = Game->GetCurScreen();
- scrollingDraws[SD_SCROLLTIMER] = -1;
- scrollingDraws[SD_NSCX] = -1000;
- scrollingDraws[SD_NSCY] = -1000;
- scrollingDraws[SD_OSCX] = 0;
- scrollingDraws[SD_OSCY] = 0;
- }
- scrollingDraws[SD_LASTSCREEN] = Game->GetCurScreen();
- }
- //Returns the X position of the top left corner of the old screen when scrolling.
- //When not scrolling, returns 0.
- int ScrollingOldX(){
- return scrollingDraws[SD_OSCX];
- }
- //Returns the Y position of the top left corner of the old screen when scrolling.
- //When not scrolling, returns 0.
- int ScrollingOldY(){
- return scrollingDraws[SD_OSCY];
- }
- //Returns the X position of the top left corner of the new screen when scrolling.
- //When not scrolling, returns -1000.
- int ScrollingNewX(){
- return scrollingDraws[SD_NSCX];
- }
- //Returns the Y position of the top left corner of the new screen when scrolling.
- //When not scrolling, returns -1000.
- int ScrollingNewY(){
- return scrollingDraws[SD_NSCY];
- }
- //Returns Link's X position when scrolling.
- //When not scrolling, returns Link's X position on the screen.
- int ScrollingLinkX(){
- if(Link->Action!=LA_SCROLLING)
- return Link->X;
- return scrollingDraws[SD_NSCX]+Link->X;
- }
- //Returns Link's Y position when scrolling.
- //When not scrolling, returns Link's Y position on the screen.
- int ScrollingLinkY(){
- if(Link->Action!=LA_SCROLLING)
- return Link->Y;
- return scrollingDraws[SD_NSCY]+Link->Y;
- }
- //Function for testing the drawing positions
- void ScrollingDraws_TestFunction(){
- if(Link->Action==LA_SCROLLING){
- Screen->FastTile(6, ScrollingLinkX(), ScrollingLinkY(), Link->Tile, 8, 128);
- Screen->FastTile(6, ScrollingOldX(), ScrollingOldY(), Link->Tile, 6, 128);
- Screen->FastTile(6, ScrollingNewX(), ScrollingNewY(), Link->Tile, 7, 128);
- }
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- // uncomment this line (remove the //) if you haven't already imported std.zh in your script file
- //import "std.zh"
- int BetterByrna[8];
- const int BETTERBYRNA_COST = 0;
- const int BETTERBYRNA_MP_TRACKER = 1;
- const int BETTERBYRNA_INVINCIBLE = 2;
- const int BETTERBYRNA_BLOCK_PROJECTILES = 3;
- void BetterByrna()
- {
- if (NumLWeaponsOf(LW_CANEOFBYRNA) > 0)
- {
- // make player invincible
- if (Link->CollDetection && BetterByrna[BETTERBYRNA_INVINCIBLE])
- {
- Link->CollDetection = false;
- }
- // deduct MP cost
- if (BetterByrna[BETTERBYRNA_MP_TRACKER] >= 1)
- {
- if (Link->MP - Floor(BetterByrna[BETTERBYRNA_MP_TRACKER]) >= 0)
- {
- Link->MP -= Floor(BetterByrna[BETTERBYRNA_MP_TRACKER]);
- }
- else
- {
- Link->MP = 0;
- }
- BetterByrna[BETTERBYRNA_MP_TRACKER] -= Floor(BetterByrna[BETTERBYRNA_MP_TRACKER]);
- }
- if (Link->MP == 0)
- {
- lweapon byrna = LoadLWeaponOf(LW_CANEOFBYRNA);
- Remove(byrna);
- }
- else
- {
- BetterByrna[BETTERBYRNA_MP_TRACKER] += BetterByrna[BETTERBYRNA_COST] * (Game->Generic[GEN_MAGICDRAINRATE] * 0.5);
- }
- // block projectiles
- if (BetterByrna[BETTERBYRNA_BLOCK_PROJECTILES])
- {
- for (int i = Screen->NumEWeapons(); i > 0; i--)
- {
- eweapon projectile = Screen->LoadEWeapon(i);
- if (projectile->ID != EW_BOMBBLAST && projectile->ID != EW_SBOMBBLAST)
- {
- for (int j = Screen->NumLWeapons(); j > 0; j--)
- {
- lweapon byrna = Screen->LoadLWeapon(j);
- if (byrna->ID == LW_CANEOFBYRNA && Collision(projectile, byrna))
- {
- Remove(projectile);
- }
- }
- }
- }
- }
- }
- // make player vulnerable again
- else if (!Link->CollDetection)
- {
- Link->CollDetection = true;
- }
- if (Link->MP == 0 && (Link->InputA || Link->InputB))
- {
- itemdata a_button = Game->LoadItemData(GetEquipmentA());
- itemdata b_button = Game->LoadItemData(GetEquipmentB());
- if (Link->InputA && a_button->Family == IC_CBYRNA)
- {
- Link->InputA = false;
- Link->PressA = false;
- }
- if (Link->InputB && b_button->Family == IC_CBYRNA)
- {
- Link->InputB = false;
- Link->PressB = false;
- }
- }
- }
- // D0: reserved for other things, like pickup message scripts
- // D1: MP cost per frame
- // D2: 1 for invincible while cane is in use
- // D3: 1 to block enemy projectiles
- item script BetterByrnaItem
- {
- void run(int foo, int cost, int invincible, int block_projectiles)
- {
- BetterByrna[BETTERBYRNA_COST] = cost;
- BetterByrna[BETTERBYRNA_INVINCIBLE] = invincible;
- BetterByrna[BETTERBYRNA_BLOCK_PROJECTILES] = block_projectiles;
- }
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- const int CUSTOM_LENS_HINTS_MAX_LAYERS = 0; //Maximum layers to check screens for lens hints
- //Global script example.
- //Main custom lens hint drawing function. Put this into main loop of "Action" global script.
- void DrawCustomLensHints(){
- if (Link->MP<=0) return;
- if (!UsingItem(I_LENS))return;
- //Add lens hints here.
- DrawCustomLensHint(0, 120, 1028, 8, 1);//Draw combo#1028 with cset 8 on all combos of type 120 (damage 8 hearts)
- DrawCustomLensHint(1, 98, 1029, 7, 1);//Draw combo#1029 with cset 7 on all combos with inherent or placed flag 98 (Script 1)
- DrawCustomLensHint(2, 55, 1030, 6, 1);//Draw combo#1030 with cset 6 on all NPC`s with ID#55 (Arrow Pols Voices)
- //Add more lens hints here.
- }
- //Lenstype: 0-combo type, 1-combo flag, 2 - NPC.
- //miscvalue1: depends on lenstype:
- // 0 - combo type ID
- // 1 - combo flag ID
- // 2 - NPC ID
- //cmb - combo to draw, cset - cset to use for hint drawing
- //minlevel - minimum item level for Lens-like item needed to be used to reveal this hint.
- void DrawCustomLensHint(int lenstype, int miscvalue1, int cmb, int cset, int minlevel){
- int lens = GetCurrentItem(IC_LENS);
- itemdata it = Game->LoadItemData(lens);
- if (it->Level<minlevel) return;
- if (lenstype==0){//combo types
- for (int l=0; l<=CUSTOM_LENS_HINTS_MAX_LAYERS; l++){
- if (l==0){
- for (int c=0;c<176;c++){
- if (Screen->ComboT[c]==miscvalue1) Screen->FastCombo(0, ComboX(c), ComboY(c), cmb, cset, OP_OPAQUE);
- }
- if ((Screen->LayerMap(l)==-1)||(Screen->LayerScreen(l)==-1))continue;
- for (int c=0;c<176;c++){
- int lc = GetLayerComboT(l, c);
- if (Screen->ComboT[lc]==miscvalue1) Screen->FastCombo(l, ComboX(lc), ComboY(lc), cmb, cset, OP_OPAQUE);
- }
- }
- }
- return;
- }
- else if (lenstype==1){//combo flags
- for (int l=0; l<=CUSTOM_LENS_HINTS_MAX_LAYERS; l++){
- if (l==0){
- for (int c=0;c<176;c++){
- if (ComboFI(c, miscvalue1)) Screen->FastCombo(0, ComboX(c), ComboY(c), cmb, cset, OP_OPAQUE);
- }
- if ((Screen->LayerMap(l)==-1)||(Screen->LayerScreen(l)==-1))continue;
- for (int c=0;c<176;c++){
- int lc = GetLayerComboT(l, c);
- if (ComboFI(lc, miscvalue1)) Screen->FastCombo(l, ComboX(lc), ComboY(lc), cmb, cset, OP_OPAQUE);
- }
- }
- }
- return;
- }
- else if (lenstype==2){//enemies
- for (int i=1; i<= Screen->NumNPCs(); i++ ){
- npc lensie= Screen->LoadNPC(i);
- if (lensie->ID==miscvalue1) Screen->FastCombo(6, lensie->X, lensie->Y-lensie->Z, cmb, cset, OP_OPAQUE);
- }
- }
- }
- //Draws Lens hints on FFC`s if FFC runs given script and has specific value set in checked Init D variable.
- void DrawFFCLensHint(int scr, int dreg, int dvalue, int cmb, int cset, int minlevel){
- int lens = GetCurrentItem(IC_LENS);
- itemdata it = Game->LoadItemData(lens);
- if (it->Level<minlevel) return;
- for (int i=1;i<=32;i++){
- ffc lensie = Screen->LoadFFC(i);
- if (lensie->Script!=scr) continue;
- if (lensie->InitD[dreg]!=dvalue) continue;
- Screen->FastCombo(0, CenterX(lensie), CenterY(lensie), cmb, cset, OP_OPAQUE);
- }
- }
- //FFC version of custom lens hints.
- //D0 - Lenstype: 0-combo type, 1-combo flag, 2 - NPC.
- //D1: depends on lenstype:
- // 0 - combo type ID
- // 1 - combo flag ID
- // 2 - NPC ID
- //D2 - combo to draw,
- //D3 - cset to use for hint drawing
- //D4 - minimum item level for Lens-like item needed to be used to reveal this hint.
- ffc script CustomLensHints{
- void run (int lenstype, int miscvalue1, int cmb, int cset, int minlevel){
- while (true){
- DrawCustomLensHint(lenstype, miscvalue1, cmb, cset, minlevel);
- Waitframe();
- }
- }
- }
- //========================================
- // Global Globals/Functions/Constants
- //========================================
- //Better Stone of Agony
- const int BetterAgony_ID = 123; //item ID
- const int BetterAgony_DetectionRadius = 32; //the secret detection radius in pixels
- const int BetterAgony_DetectionFlag = 98; //script flag number to use for secret detection
- const int BetterAgony_Vibrate = 1; //wether or not it makes link vibrate. 0 = no, 1 = yes
- const int BetterAgony_SFX = 61; //sound effect to play. leave as 0 if unneeded
- const int BetterAgony_SFXRepeatRate = 30; //how fast to repeat the sound effect, in frames
- const int BetterAgony_ComboID = 8; //combo to draw above links head as an indicator. leave as 0 if unneeded.
- const int BetterAgony_ComboCSet = 7; //cset to use for the combo
- //D0: How to detect secrets
- //0 = Detect trigger flags
- //1 = Detect the script flag
- //2 = Detect both trigger flags and the script flag
- //D1: Condition for detecting secrets
- //0 = Always detect
- //1 = Don't detect if permanent secrets are activated
- ffc script BetterStoneOfAgony{
- void run(int type, int condition){
- bool SecretDetected;
- bool OtherFrame;
- int LinkVibration;
- bool LinkOffset;
- int SFXRepeat;
- while(true){
- while( !Link->Item[BetterAgony_ID] || (condition == 1 && Screen->State[ST_SECRET]) ) { //halt the script
- LinkVibration = 0;
- if ( LinkOffset )
- Link->DrawYOffset ++; //revert drawoffset
- LinkOffset = false;
- SFXRepeat = 0;
- Waitframe();
- }
- if ( OtherFrame ) { //only check every other frame to prevent slowdown
- SecretDetected = false;
- for(int i = 0; i <= 6; i++) { //for all layers
- if ( i == 0 || Screen->LayerMap(i) != -1 ) { //dont check unvalid layers
- for(int j = 0; j <= 175; j++) { //all combos
- if ( Distance(Link->X, Link->Y, ComboX(j), ComboY(j)) <= BetterAgony_DetectionRadius ) //check distance
- if ( (IsATriggerFlag(GetLayerComboF(i, j)) && type != 1)
- || (GetLayerComboF(i, j) == BetterAgony_DetectionFlag && type != 0) ) //check flag
- SecretDetected = true;
- }
- }
- }
- }
- if ( OtherFrame )
- OtherFrame = false;
- else
- OtherFrame = true;
- if ( SecretDetected ) {
- if ( BetterAgony_Vibrate == 1 ) { //link vibrates using drawoffset
- if ( LinkVibration == 0 ) {
- Link->DrawYOffset --;
- LinkOffset = true;
- }
- if ( LinkVibration == 3 ) {
- Link->DrawYOffset ++;
- LinkOffset = false;
- }
- LinkVibration ++;
- if ( LinkVibration > 5 )
- LinkVibration = 0;
- }
- if ( BetterAgony_SFX != 0 ) { //repeatedly played sfx
- if ( SFXRepeat == 0 )
- Game->PlaySound(BetterAgony_SFX);
- SFXRepeat ++;
- if ( SFXRepeat > BetterAgony_SFXRepeatRate )
- SFXRepeat = 0;
- }
- if ( BetterAgony_ComboID != 0 ) //indicator combo drawn on layer 7 above link
- Screen->FastCombo(7, Link->X, Link->Y-16, BetterAgony_ComboID, BetterAgony_ComboCSet, OP_OPAQUE);
- }
- else { //secrets not detected
- LinkVibration = 0;
- if ( LinkOffset )
- Link->DrawYOffset ++; //revert drawoffset
- LinkOffset = false;
- SFXRepeat = 0;
- }
- Waitframe();
- }
- }
- }
- bool IsATriggerFlag(int f) {
- if ( (f >= 3 && f <= 6) || f == 11 || (f >= 68 && f <= 90) ) //trigger flags
- return true;
- else
- return false;
- }
- global script Main2{
- void run(){
- //=================
- // Global Init
- //=================
- // Initialize variables used to listen on screen changes
- int curscreen = -1;
- //=================
- // Global Init
- //=================
- MooshPit_Init();
- //Setup variables for ice combos.
- Setup_IceCombos();
- //Variable that stores Game->GetCurScreen() the previous frame.
- int oldscreen = Game->GetCurScreen();
- //Main Loop
- //=================
- // Global Init
- //=================
- ScrollingDraws_Init();
- Minecart_Init();
- //=================
- // Global Init
- //=================
- ScrollingDraws_Init();
- StartGhostZH();
- //=================
- // Global Init
- //=================
- int BetterAgony_LastDMap = Game->GetCurDMap();
- int BetterAgony_LastScreen = Game->GetCurDMapScreen();
- while(true){
- //=====================
- // Global Update 1
- //=====================
- // Keep track of screen changes
- // Run a Barrier script on every screen change
- if (Game->GetCurScreen() != curscreen) {
- curscreen = Game->GetCurScreen();
- Barriers_NewScreen();}
- RefreshBottles();
- while(true){
- EmptyBottleGlobal();
- //=====================
- // Global Update 2
- //=====================
- NesMovementFix();
- //=====================
- // Global Update 1
- //=====================
- MooshPit_Update();
- //=====================
- // Global Update 1
- //=====================
- //Call Dungeonmap functions
- if(Game->GetCurDMap()==1){ //Put the dmap-number of your dungeon here
- if(!Link->Item[185]){ //Put the number of the fake-item here
- Link->InputMap = false;
- }
- }
- //=====================
- // Global Update 1
- //=====================
- ScrollFix(); // keep at top of while loop
- PegasusBoots(); // before waitdraw
- //=====================
- // Global Update 1
- //=====================
- ScrollingDraws_Update();
- //=====================
- // Global Update 1
- //=====================
- ScrollingDraws_Update();
- UpdateGhostZH1();
- //=====================
- // Global Update 1
- //=====================
- BetterByrna();
- //=====================
- // Global Update 1
- //=====================
- if ( Game->GetCurDMap() != BetterAgony_LastDMap || Game->GetCurDMapScreen() != BetterAgony_LastScreen )
- Link->DrawYOffset = 0; //fix better stone of agony link draw offset
- BetterAgony_LastDMap = Game->GetCurDMap();
- BetterAgony_LastScreen = Game->GetCurDMapScreen();
- Waitdraw();
- Update_IceCombos(oldscreen);
- oldscreen = Game->GetCurScreen();
- //=====================
- // Global Update 2
- //=====================
- Minecart_Update();
- UpdateGhostZH2();
- //=====================
- // Global Update 2
- //=====================
- DrawCustomLensHints();
- Waitframe();
- ScreenChange_Update();
- Pot_Script();
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement