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 DisableButtonItem(int itm){ if(GetEquipmentA()==itm){ Link->PressA = false; Link->InputA = false; } else if(GetEquipmentB()==itm){ Link->PressB = false; Link->InputB = false; } } void Minecart_DisableItems(){ DisableButtonItem(I_ROCSFEATHER); } void Minecart_Update1(){ if(GBCart[GBC_DIR]>-1){ Minecart_DisableItems(); } } void Minecart_Update2(){ 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); } } global script GBMinecart_Slot2{ void run(){ ScrollingDraws_Init(); Minecart_Init(); while(true){ ScrollingDraws_Update(); Minecart_Update1(); Waitdraw(); Minecart_Update2(); Waitframe(); } } } 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; } } } }