global script hpmpcounters{
	void run(){
	InitializeGhostZHData();
	int whipCooldownTimer = 0;
	int LinkX = Link->X;
    int LinkY = Link->Y;
	int fastWalkTimer;
        int lastScreen = Game->GetCurDMapScreen();
        int lastDMap = Game->GetCurDMap();
		
		
		while(true)
		{
			Game->Counter[CR_SCRIPT2] = Link->HP;
			Game->Counter[CR_SCRIPT3] = Link->MP;
			Game->Counter[CR_SCRIPT4] = Link->MaxHP;
			Game->Counter[CR_SCRIPT5] = Link->MaxMP;
			UpdateEWeapons();
            CleanUpGhostFFCs(); // Only needed if __GH_USE_DRAWCOMBO is 0

			UpdateLWeapons();
			UpdateLastItem();
			//if (Link->PressB) {LastItemUsed = GetEquipmentB();}
			//if (Link->PressA) {LastItemUsed = GetEquipmentA();}
			
		if ( LinkSeen ){
			Link->Invisible = false;
			}
		else if ( !LinkSeen ){
			Link->Invisible = true;
			}
		
//		if ( itemActivate ){
//			UseItemOnB(65);
//			itemActivate = false;
//			}
//		else if ( !itemActivate ){
//			}
		
		//Whip Cooldown Timer
            if ( whipCooldownTimer > 0 )
                whipCooldownTimer--;
			
            if ( gogglesOn && Link->MP ){                
                //Decrement magic
                gogglesTimer = (gogglesTimer+1) % TIME_PER_MP;
                if ( !gogglesTimer ) Link->MP--;
				Screen->Rectangle(6, 0, 0, 256, 172, 4, 1, 0, 0, 0, true, 64);
                
                if ( Link->MP <= 0 //If magic ran out
				&& Link->Item[I_AMULET1] )
                { //Take off goggles.
                    gogglesOn = false;
                    Link->Item[I_AMULET1] = false;
				//	Waitframes(1);
                }

            }
            else if ( !gogglesOn && Link->Item[I_AMULET1] ){ //Disable Goggles
                Link->Item[I_AMULET1] = false;
				//Waitframes(1);
            }
			
            Waitdraw();
            
            AutoGhost();
            DrawGhostFFCs();
			{
			if (Link->Item[231] == true) //If Link has the fake item designated in D0
			{
				Link->Item[230] = false; //Removes the fake item user selects in D0
				Link->Item[231] = false; //Removes the item the user selects in in D1   
				Link->MP += 256; //Increases MP by value of D3
				Link->MaxMP += 256; //Increases Max MP by value of D2
			}
			else (Link->Item[230] == true); //Gives Link the specified item in D4.{
           
			}
			{
     
      if(SecretTimer > -1) {
        SecretTimer--;
        if (SecretTimer == -1) {
          Screen->TriggerSecrets();
		  Game->PlaySound(27);}}
			}



			float angle;
			{
				if (usebombodo == 1)
				{            
					slower ++;
					if (slower == 5)
					{  
						rad++;
						slower = 0;
					}  
					angle = (angle + ORBIT_SPEED) % 360;          
					f1 = 100 + rad * Cos(angle);
					f2 = 100 + rad * Sin(angle);
	//				Screen->FastCombo(6, f1, f2, 95, 2, 128);
					
					r1 = 40+Rand(150);
					r2 = 40+Rand(100);
					
					slowera++;
					if (slowera  == 20)
					{
						slowera = 0;
						if (bombs < 30)
						{
							bombs ++;  
							lweapon bomb = CreateLWeaponAt(LW_BOMBBLAST, r1, r2);
							Game->PlaySound(SFX_BOMB);
							if (bombs == 30) usebombodo = 0;
						}
					}
				}
				
				///////////////////////
				/// BEHIN XP SCRIPT ///
				///////////////////////
				
				//Exp gain and level up
            if ( Game->Counter[CR_SCRIPT7] < EXP_MAX_LEVEL ){ //Disable if level is maxed
                setMaxHP();
                checkEnemiesKilled();
            //    expMeter();
            }
            
            //Fast walk
            if ( Link->Item[I_FASTWALK] ){
                fastWalkTimer++;
                fastWalkTimer %= EXP_FASTWALKRATE;
                if ( fastWalkTimer == 0 )
                    fastWalk(1);
            }
            
            //Treasure Hunter
            if ( Link->Item[I_TREASUREHUNTER] //If skill learned
                && (lastScreen != Game->GetCurDMapScreen() || lastDMap != Game->GetCurDMap()) //If new screen
                && checkScreenFlag(SF_TREASURE) //And flag active
                && !Screen->State[ST_ITEM] //And item not taken
                && !Screen->State[ST_CHEST]
                && !Screen->State[ST_LOCKEDCHEST]
                && !Screen->State[ST_BOSSCHEST]
            ){
                Game->PlaySound(SFX_TREASURESCREEN); //Play SFX
            }
            lastScreen = Game->GetCurDMapScreen(); //Update last screen/DMap
            lastDMap = Game->GetCurDMap();
			
			/////////////////////
			/// END XP SCRIPT ///
			/////////////////////	
				
				Waitframe();
				
				if(EquipB > 0){
				SetItemB(EquipB);
				EquipB = 0;
				}
				
			}
			if ( ringOn && Link->MP ){                
                //Decrement magic
                ringTimer = (ringTimer+1) % ringTimePerMP;
                if ( !ringTimer ) Link->MP--;
				
				//Draw shadow under Link
                //Screen->FastTile( 2, Link->X, Link->Y, ringShadowTile, ringShadowCset, OP_TRANS );
                
                if ( Link->MP <= 0 //If magic ran out
               
                ){ //Take off ring
                    ringOn = false;
                    Link->CollDetection = true;
                    Link->Invisible = false;
                }

            }
            else if ( !ringOn ){ //Disable ring
                Link->CollDetection = true;
                Link->Invisible = false;
				
            }
			
			//////////////
			///END RING///
			//////////////
			
			/////////////////////////
			///BEGIN CANE OF BYRNA///
			/////////////////////////
			
			 if ( byrnaOn && Link->MP ){                
                //Decrement magic
                byrnaTimer = (byrnaTimer+1) % byrnaTimePerMP;
                if ( !byrnaTimer ) Link->MP--;
                
                if ( Link->MP <= 0 //If magic ran out
                
                ){ //Take off ring
                    byrnaOn = false;
 

                }

            }
            else if ( !byrnaOn ){ //Disable ring


			
            }
			
			///////////////////////
			///END CANE OF BYRNA///
			///////////////////////
			
			/////////////////
			///BEGIN BOOTS///
			/////////////////
			
			 if ( bootsOn && Link->MP ){                
                //Decrement magic
                bootsTimer = (bootsTimer+1) % bootsTimePerMP;
                if ( !bootsTimer ) Link->MP--;
                
                if ( Link->MP <= 0 //If magic ran out
                || Link->Action == LA_SCROLLING //Or left screen
                ){ //Take off ring
                    bootsOn = false;

                }

            }
            else if ( !bootsOn ){ //Disable ring

            }
			
			///////////////
			///END BOOTS///
			///////////////
		}
	}
}

//////////////////////
/// BEGIN LEVELING ///
//////////////////////


//Check for new enemies and set their max HP
void setMaxHP(){
    for ( int i = Screen->NumNPCs(); i > 0; i-- ){
        npc enem = Screen->LoadNPC(i);
        if ( enem->Misc[NPC_MISC_MAXHP] == 0 )
            enem->Misc[NPC_MISC_MAXHP] = enem->HP;
    }
}

void checkEnemiesKilled(){
    for ( int i = Screen->NumNPCs(); i > 0; i-- ){
        npc enem = Screen->LoadNPC(i);
        if ( enem->HP <= 0 && enem->HP > HP_DEAD ){
            enem->HP = HP_DEAD;
            int worth = enemyEXPWorth(enem);
            
            //Leadership: Chance to increase EXP worth
            if ( Link->Item[I_LEADERSHIP] && Rand(EXP_LEADERSHIPCHANCE) == 0 )
                worth++;
                
            giveEXP(worth);
        }
    }
}

//void expMeter(){
//    int length = EXP_METER_LENGTH * Game->Counter[CR_SCRIPT6] / EXP_PER_LEVEL;
//    Screen->Rectangle(7, EXP_METER_X, EXP_METER_Y, EXP_METER_X + length, EXP_METER_Y + EXP_METER_WIDTH, EXP_METER_COLOR, 1, 0, 0, 0, true, OP_OPAQUE);
//}

int enemyEXPWorth(npc enem){
    return Max(1, enem->Misc[NPC_MISC_MAXHP] / EXP_HP_RATIO);
}

void giveEXP(int amount){
    //Give EXP
    Game->Counter[CR_SCRIPT6] += amount;
    
    //Enough EXP to level up
    if ( Game->Counter[CR_SCRIPT6] > EXP_PER_LEVEL ){
        Game->Counter[CR_SCRIPT6] -= EXP_PER_LEVEL;
        Game->Counter[CR_SCRIPT7]++;
        Game->PlaySound(SFX_LEVEL);
        
        //Level 20: Super Quake
        if ( Game->Counter[CR_SCRIPT7] >= EXP_MAX_LEVEL ){
            Link->Item[I_QUAKESCROLL2] = true;
            Game->Counter[CR_SCRIPT6] = 0; //Also reset EXP
        }
        
        //Level 18: Cross beams
        else if ( Game->Counter[CR_SCRIPT7] == 18 ){
            Link->Item[I_CROSSSCROLL] = true;
        }
        
        //Level 15: Hurricane Spin
        else if ( Game->Counter[CR_SCRIPT7] == 15 ){
            Link->Item[I_SPINSCROLL2] = true;
        }
        
        //Level 13: Treasure Hunter
        else if ( Game->Counter[CR_SCRIPT7] == 13 ){
            Link->Item[I_TREASUREHUNTER] = true;
        }
        
        //Level 12: Peril Beam
        else if ( Game->Counter[CR_SCRIPT7] == 12 ){
            Link->Item[I_PERILSCROLL] = true;
        }
        
        //Level 10: Leadership
        else if ( Game->Counter[CR_SCRIPT7] == 10 ){
            Link->Item[I_LEADERSHIP] = true;
        }
        
        //Level 9: Quake Hammer
        else if ( Game->Counter[CR_SCRIPT7] == 9 ){
            Link->Item[I_QUAKESCROLL1] = true;
        }
        
        //Level 6: Spin Attack
        else if ( Game->Counter[CR_SCRIPT7] == 6 ){
            Link->Item[I_SPINSCROLL1] = true;
        }
        
        //Level 5: Fast Walk
        else if ( Game->Counter[CR_SCRIPT7] == 5 ){
            Link->Item[I_FASTWALK] = true;
        }
        
        //Level 3: Slash
        else if ( Game->Counter[CR_SCRIPT7] == 3 ){
            Game->Generic[GEN_CANSLASH] = 1;
        }
    }
}

//Makes Link walk faster in addition to normal walking speed
void fastWalk ( int speed ){
    //Up
    if( Link->InputUp
    && !Screen->isSolid(Link->X,Link->Y+6) //NW
    && !Screen->isSolid(Link->X+7,Link->Y+6) //N
    && !Screen->isSolid(Link->X+15,Link->Y+6) //NE
    )
        Link->Y -= speed;
    //Down
    else if( Link->InputDown
    && !Screen->isSolid(Link->X,Link->Y+17) //SW
    && !Screen->isSolid(Link->X+7,Link->Y+17) //S
    && !Screen->isSolid(Link->X+15,Link->Y+17) //SE
    )
        Link->Y += speed;
    //Left
    else if( Link->InputLeft
    && !Screen->isSolid(Link->X-2,Link->Y+8) //NW
    && !Screen->isSolid(Link->X-2,Link->Y+15) //SW
    )
        Link->X -= speed;
    //Right
    else if( Link->InputRight
    && !Screen->isSolid(Link->X+17,Link->Y+8) //NE
    && !Screen->isSolid(Link->X+17,Link->Y+15) //SE
    )
        Link->X += speed;
}

bool checkScreenFlag(int flag){
    return Screen->Flags[SF_MISC] & (4<<flag);
}

////////////////////
/// END LEVELING ///
////////////////////


////////////////
//// Updates every LWeapon on screen. Call in the active script.
void UpdateLWeapons() {
  for (int i = 1; i <= Screen->NumLWeapons(); i++) {
    UpdateLWeapon(Screen->LoadLWeapon(i));}}
 
////////////////
//// Update a given LWeapon.
void UpdateLWeapon(lweapon lw) {

  // If the weapon does not have it's source item marked, mark it as
  // being created by the last item that Link has used.
  if (lw->Misc[MISC_LWEAPON_ITEM] == 0) {
    lw->Misc[MISC_LWEAPON_ITEM] = LastItemUsed;}}
 
////////////////
//// Updates the LastItemUsed variable to our best guess at what was
//// most recently used. This should be called at the end of the loop,
//// right before Waitdraw or Waitframe, because the item marked in
//// LastItemUsed isn't actually used until after the Waitdraw or
//// Waitframe.
void UpdateLastItem() {

  // Since we don't know which button has priority if both are pressed
  // at once, cancel the B button press if A has also been pressed
  // this frame.
  if (Link->PressA && Link->PressB) {Link->PressB = false;}

  // If Link is currently in an action where he obviously can't use
  // items, then ignore his button presses.
  if (Link->Action != LA_NONE &&
      Link->Action != LA_WALKING) {
    return;}

  // Check which button is being pressed, if any. Also check for the
  // appopriate Jinx.
  if (Link->PressA && Link->SwordJinx == 0) {
    LastItemUsed = GetEquipmentA();}
  else if (Link->PressB && Link->ItemJinx == 0) {
    LastItemUsed = GetEquipmentB();}}
	
////////////////
//// Return true if the given lweapon is from the given item.
bool IsFromItem(lweapon lw, int itemNumber) {
  return lw->Misc[MISC_LWEAPON_ITEM] == itemNumber;}
 
////////////////
//// Return true if the given lweapon is from the given item class.
bool IsFromItemClass(lweapon lw, int itemClass) {
  itemdata data = Game->LoadItemData(lw->Misc[MISC_LWEAPON_ITEM]);
  return data->Family == itemClass;}
  
  
  // Cooldown timers for each button. Button presses are cancelled
// unless their cooldown timer is <= 0
int Cooldown_ATimer = -1;
int Cooldown_BTimer = -1;

// Place in the Active script's main loop.
void Cooldown_Update() {

  // Countdown the timers.
  if (Cooldown_ATimer >= 0) {Cooldown_ATimer--;}
  if (Cooldown_BTimer >= 0) {Cooldown_BTimer--;}

  // Block inputs.
  if (Cooldown_ATimer > 0) {
    Link->InputA = false;
    Link->PressA = false;}
  if (Cooldown_BTimer > 0) {
    Link->InputB = false;
    Link->PressB = false;}}
	

//void DropItems(int drop, int loc) {
//  DropItems(drop, ComboX(loc), ComboY(loc));}
  
// Drop an item from a dropset.
// int dropset: The number of a dropset.
// int x, int y or int loc: location of the drop.
void DropItemSet(int drop, int x, int y) {
  npc n = CreateNPCAt(DROP_ENEMY_ID, x, y);
  n->HP = HP_SILENT;
  n->ItemSet = drop;
  }

  
  // Drop an item from a dropset.
// int dropset: The number of a dropset.
// int x, int y or int loc: location of the drop.
void DropItemSet(ffc this, int drop) {
    npc n = CreateNPCAt(DROP_ENEMY_ID, this->X, this->Y);
    n->HP = HP_SILENT;
    n->ItemSet = drop;
}

// Drop an item from a dropset.
// int dropset: The number of a dropset.
// int x, int y or int loc: location of the drop.
void DropItemExplode(ffc this, int drop) {
    DropItemSet(this, drop);
    eweapon explosion = CreateEWeaponAt(EW_BOMBBLAST, this->X, this->Y);
    //explosion->CollDetection = true; //This is true by default
    explosion->Damage = 10;
}

// Drop an item from a dropset.
// int dropset: The number of a dropset.
// int x, int y or int loc: location of the drop.
void DropItemExplodeBig(ffc this, int drop) {
    DropItemSet(this, drop);
	// One explosion every 16 frames, 15 times
    for(int i=0; i<15; i++)
    {
		eweapon explosion = CreateEWeaponAt(EW_SBOMBBLAST, this->X, this->Y);
		//explosion->CollDetection = true; //This is true by default
		explosion->Damage = 10;
	}
}

