//import "std.zh"
//import "string.zh"
//Requires std.zh and string.zh.
// 1. Set up 5 consecutive tiles in a row in Tile Editor as following:
// 1. Full heart.
// 2. 3/4 heart.
// 3. 1/2 heart.
// 4. 1/4 heart.
// 5. Empty heart.
//2. Note down ID of the first tile in the row (the "Full Heart" one).
//A. Set up 3*3 frame for Boss HP meter background, if you want one.
//3. Import and compile the script.
//4. In your boss screen, place the invisible FFC, one for each boss, if multiple bosses are in one screen, and assign the following arguments:
// X and Y position: Position of HP meter.
// CSet - Cset used for drawing the life gauge. Setting value to 0 results in health meter flashing trough all csets.
// D0: ID of the tile you noted down in step 2.
// D1: Slot number of the boss enemy, or his weak spot.
// D2: Hit Points per tile. Larger values means smaller life meter and vise versa.
// D3: Tile, top left of 3*3 frame, used to render background. 0 to disable.
// D4: Quake power on boss introdiction. Best used for jump scares.
// D5: >0 - Logarithmic boss HP meter. Rendered HP is smaller than actual boss HP. A very cuesed and deceiving way to make player waste potions in very hard boss battles.
// D6: Maximum tiles in row before carrying over to nex one. Recommended to be even one.
// D7: String to display at the start of the battle.
// Otherwise, it sets Y position of boss health gauge.
//5. Assign the script to FFC.
//6. Test and enjoy.
const int BOSS_HP_TILE_OFFSET = 8; //Distance between gauge piece positions.
const int FONT_BOSS_NAME = 0; //Font used for boss name string drawing.
const int SHADOW_COLOR_BOSS_NAME = 1; //Drop shadow Color used for boss name string drawing. Set to -1 for no shadow.
const int COLOR_BOSS_NAME = 0; //Color used for boss name string drawing.
const int BKGCOLOR_BOSS_NAME = -1; //Background color used for boss name string drawing. Change to -1 for transparent.
const int FONT_Y_OFFSET = -8; //Y position of the Boss name string drawing relative to gauge position.
const int FONT_X_OFFSET = 0; //X position of the Boss name string drawing relative to gauge position.
const int BACKDROP_TILE = 0;//Tile used for backdrop
const int BACKDROP_CSET = 6; //Cset used for drawing backdrop beneath boss HP meter.
const int BACKDROP_XOFFSET = -16; //Backdrop position offset.
const int BACKDROP_YOFFSET = -8; //relative to gauge`s coordinates.
const int I_STETOSCOPE = 0; //ID of item that is needed to be in Link`s inventory for HP meter to be visible. 0 means always visible
const int BOSS_HP_DRAW_LAYER = 3; //Layer used to draw Boss HP meter
const int INTRO_BOSS_HP_REGENERATION = 1;//Set to >0, to cause boss HP meter to fill up at the start of the boss battle, like in Megeman games.
const int USE_NEW_HP_METER_CAP_TILES = 1;//>0 - Use alternate graphics for left and right caps for boss HP meter. Tiles for left cap are directly below original tiles, and tiles for right cap are directly below tiles for left cap.
ffc script BossHPMeter{
void run (int origtile, int slotnum, int hppertile, int bkgtile, int quake, int log, int overflowX, int string){
if (Screen->State[ST_SECRET])Quit();
if (I_STETOSCOPE>0 && !Link->Item[I_STETOSCOPE])Quit();
int cset= this->CSet;
int xpos = this->X;
int ypos = this->Y;
Waitframes(4*slotnum);
if (string>0){
Screen->Message(string);
Screen->Quake=quake;
}
npc boss;
if (slotnum == 0) boss = Screen->LoadNPC(1);
else boss = Screen->LoadNPC(slotnum);
int buffer[256];
int CSETFLASH[6] = {1,5,7,8,9,11};
boss->GetName(buffer);
int maxhp = boss->HP;
int curhp = boss->HP;
int tilecount=Ceiling(maxhp/hppertile);
int drawhp = curhp;
bool leftcap = true;
int framex = 2;
int framey = 2;
if (tilecount>overflowX){
framex+=overflowX*BOSS_HP_TILE_OFFSET/16;
framey+=Floor(tilecount/overflowX*BOSS_HP_TILE_OFFSET/16)-1;
}
else framex +=Ceiling(tilecount/2);
if (strlen(buffer)>(framex-2)*2)framex = 2+Ceiling(strlen(buffer)/2);
int regen = Cond(INTRO_BOSS_HP_REGENERATION>0, 0, maxhp);
if (INTRO_BOSS_HP_REGENERATION==0)regen = maxhp;
while (boss->isValid()){
if (boss->HP <= 0) break;
curhp = boss->HP;
int backdrawx= xpos+BACKDROP_XOFFSET;
int backdrawy= ypos+BACKDROP_YOFFSET;
if (bkgtile>0) DrawFrame(BOSS_HP_DRAW_LAYER, bkgtile, xpos+BACKDROP_XOFFSET, ypos+BACKDROP_YOFFSET, framex, framey, BACKDROP_CSET, OP_OPAQUE);
int drawcset;
drawhp = Min(regen,curhp);
if (log>0){
for (int i=1; i<=log;i++) drawhp*=curhp/maxhp;
}
int drawmaxhp = maxhp;
int drawxpos = xpos;
int drawypos = ypos;
int tiletodraw = origtile;
if (cset==0) drawcset =CSETFLASH[Rand(6)];
else drawcset = cset;
int namex = xpos + FONT_X_OFFSET;
int namey = ypos + FONT_Y_OFFSET;
if ((FONT_X_OFFSET >= 0)&&(SHADOW_COLOR_BOSS_NAME>=0)) Screen->DrawString(BOSS_HP_DRAW_LAYER, namex+1, namey+1, FONT_BOSS_NAME, COLOR_BOSS_NAME, BKGCOLOR_BOSS_NAME, TF_NORMAL, buffer, OP_OPAQUE);
if (FONT_X_OFFSET >= 0) Screen->DrawString(BOSS_HP_DRAW_LAYER, namex, namey, FONT_BOSS_NAME, SHADOW_COLOR_BOSS_NAME, BKGCOLOR_BOSS_NAME, TF_NORMAL, buffer, OP_OPAQUE);
leftcap=true;
while (drawmaxhp > 0){
int tilechooser = drawhp/hppertile;
if (tilechooser >=1) tiletodraw = origtile;
else if (tilechooser > 0.75) tiletodraw = origtile;
else if (tilechooser> 0.5) tiletodraw = origtile + 1;
else if (tilechooser> 0.25) tiletodraw = origtile + 2;
else if (tilechooser> 0) tiletodraw = origtile + 3;
else tiletodraw = origtile + 4;
if (USE_NEW_HP_METER_CAP_TILES>0 && maxhp>hppertile){
if (leftcap) tiletodraw+=20;
else if (drawmaxhp<=hppertile)tiletodraw+=40;
}
Screen->FastTile(BOSS_HP_DRAW_LAYER, drawxpos, drawypos, tiletodraw,drawcset, OP_OPAQUE);
drawxpos = drawxpos + BOSS_HP_TILE_OFFSET;
if (drawxpos>=(xpos+overflowX*BOSS_HP_TILE_OFFSET)){
drawxpos = xpos;
drawypos +=BOSS_HP_TILE_OFFSET;
}
drawmaxhp -= hppertile;
drawhp -= hppertile;
leftcap=false;
}
if (regen<maxhp){
regen+=hppertile/4;
}
Waitframe();
}
}
//Draws sizable frame using 3*3 tile setup.
//tile - top-left corner of 3*3 tile setup.
//posx, posy - coordinates of top left corner.
//sizex, sizey - frame size, in tiles.
//layer, CSet, opacity - self explanatory.
void DrawFrame(int layer, int tile, int posx, int posy, int sizex, int sizey, int CSet, int opacity){
int drawx = posx;
int drawy = posy;
int xoffset=0;
int yoffset=0;
for (int w=0; w<sizex; w++){
drawx = posx+16*w;
xoffset=0;
if (w>0)xoffset=1;
if (w==sizex-1) xoffset=2;
for (int h=0; h<sizey; h++){
drawy = posy+16*h;
yoffset=0;
if (h>0)yoffset=1;
if (h==sizey-1) yoffset=2;
Screen->FastTile(layer, drawx, drawy, tile +xoffset+20*yoffset, CSet, opacity);
}
}
}
}