Solved A MP bar in two phases

Question that is answered or resolved.

16-bit Fighter

Active member
I'd like to create a MP bar system in two phases. In the first one, the background bar is black and the growing bar is blue (from 0 MP to 100 MP). Once the growing bar reaches 100MP and the end of the bar size in the same time, then the blue bar disappears and the background bar gets dark blue and a new growing bar starting (from 100 MP to Max MP) which is colored in light purple. At the end of the 2nd phase the max MP is reached and thus the MP bar is full and gets colored in a darker purple. The MP bar is 96px wide and 4px in height.

An example with a 900 Max MP character. Of course the 2nd phase is longer to be done since 800 MP (900-100) is way bigger than 100 MP.
Possible colors :
►►#000000 1rst background
►►#2969B0 1rst MP bar
►►#28324E 2nd background
►►#9365B8 2nd MP bar
►►#553982 Full MP bar

0 MP
==========

40 MP
==========

80 MP
==========

100 MP (First phase done)
==========

180 MP
==========

340 MP
==========

660 MP
==========

900 MP (Max MP and 2nd phase done)
==========

Thanks for any helps!
 
Your ASCII bar example is hard to read at glance. I had to view it thoroughly to see what you mean.
But anyways, here's my script suggestion:
MPBar2xc:
C:
void main()
{//Two phases MP bar
  void self = getlocalvar("self");        //get calling entity
  int MP = getentityproperty(self,"mp");    // get current mp
  int BarLen = 96;                // define bar's length
  int BarWid = 4;                // define bar's width
  int Bx = 35; int By = 45;            // bar's coords
  int Per;

  if(MP == 900){ // maximum MP
    drawbox(Bx, By, BarLen, BarWid,200,rgbcolor(40,50,78),0);
    drawbox(Bx, By, BarLen, BarWid,300,rgbcolor(85,57,130),0);
  } else if(MP >= 100 && MP<900){ // second phase MP
    Per = BarLen*(MP-100)/900;

    drawbox(Bx, By, BarLen, BarWid,200,rgbcolor(40,50,78),0);
    drawbox(Bx, By, Per, BarWid,300,rgbcolor(147,101,184),0);
  } else if(MP < 100){ // first phase MP
    Per = BarLen*MP/100;

    drawbox(Bx, By, BarLen, BarWid,200,rgbcolor(0,0,0),0);
    drawbox(Bx, By, Per, BarWid,300,rgbcolor(41,105,176),0);
  }
}

save this as name above and put it in data/scripts folder.
To use this, declare this line in character's header text:
ondrawscript data/scripts/MPBar2x.c

That reminds me, do you want this MP display script as default display for all players or just for some players?
 
I had to view it thoroughly to see what you mean.
Sorry for this and big thanks Bloodbane, it works fine!
I think I'll change the colors but that's my problem. ^^

I'd just know how make the MP bar invisible in the selection screen though, please.

That reminds me, do you want this MP display script as default display for all players or just for some players?
Yes, for all players and thus I added a MP max parameter since players probably won't have the same. What did you have in mind for asking this question? Kratus proposed me another way by using the updated.c file. Is it better, then?
 
Yes, for all players and thus I added a MP max parameter since players probably won't have the same. What did you have in mind for asking this question? Kratus proposed me another way by using the updated.c file. Is it better, then?
For individual entities, the @Bloodbane's method is the best way to go through the ondraw script event, plus working for npc and enemies too. As an alternative, in case you want a global method for all players at the same time using automatic hud positioning, here's my suggestion.

C:
void main()
{
    void player1 = getplayerproperty(0, "entity");
    void player2 = getplayerproperty(1, "entity");
    
    //CHECK IF THE GAME IS IN-LEVEL TO AVOID SELECT SCREEN AND OTHER EVENTS
    //CHECK IF THE GAME IS NOT PAUSED TO PREVENT POSSIBLE EFFECTS (OR SCRIPTED REFILL) FROM WORKING DURING PAUSE MENU
    if(openborvariant("in_level") && !openborvariant("pause")){
        drawMp(player1, 0);
        drawMp(player2, 1);
    }
}

void drawMp(void player, int pIndex)
{//Draw custom mp bar

    //DOUBLE-CHECK FOR SAFE, CONFIRM IF THE PLAYER IS NOT NULL AND IF EXISTS
    if(player != NULL()){
        if(getentityproperty(player, "exists")){
            int maxMp        = getentityproperty(player, "maxmp");
            int currentMp    = getentityproperty(player, "mp");
            int xPos        = 1; //BASE X POSITION USED BY PLAYER 1
            int xDif        = 120; //DIFFERENCE IN X AXIS BETWEEN EACH PLAYER HUD (FOR 480X272 RESOLUTION, SPLIT THE SCREEN IN 4 PARTS)
            int xAdd        = xDif*pIndex; //CALCULATE THE X POSITION OF EACH PLAYER MP BAR AUTOMATICALLY
            int xSize        = 100; //BAR SIZE IN X AXIS
            int yPos        = 40; //BASE Y POSITION USED BY ALL PLAYERS
            int ySize        = 5; //BAR SIZE IN Y AXIS
            int backLayer    = 40000; //BACKFILL LAYER
            int barLayer    = 50000; //MP BAR LAYER
            int black        = rgbcolor(0,0,0);
            int blue        = rgbcolor(0,0,255);
            int purple        = rgbcolor(255,0,255);
            int darkBlue    = rgbcolor(0,0,100);
            int darkpurple    = rgbcolor(100,0,100);

            //PHASE 1
            if(currentMp <= xSize){

                //FORMULA
                maxMp        = 100;
                currentMp    = (currentMp*xSize)/maxMp; //CALCULATE REMAINING MP BAR SIZE

                //DRAW BACK FILL
                drawbox(xPos+xAdd, yPos, xSize, ySize, backLayer, black);

                //DRAW CURRENT MP
                if(currentMp > 0){drawbox(xPos+xAdd, yPos, currentMp, ySize, barLayer, blue);}
            }else

            //PHASE 2
            if(currentMp > xSize && currentMp < xSize*9){

                //FORMULA
                maxMp        = 900;
                currentMp    = (currentMp*xSize)/maxMp; //CALCULATE REMAINING MP BAR SIZE

                //DRAW BACK FILL
                drawbox(xPos+xAdd, yPos, xSize, ySize, backLayer, darkBlue);

                //DRAW CURRENT MP
                drawbox(xPos+xAdd, yPos, currentMp, ySize, barLayer, purple);
            }else

            //FULL
            if(currentMp >= xSize*9){

                //FORMULA
                maxMp        = 900;
                currentMp    = (currentMp*xSize)/maxMp; //CALCULATE REMAINING MP BAR SIZE

                //DRAW CURRENT MP
                drawbox(xPos+xAdd, yPos, currentMp, ySize, barLayer, darkpurple);
            }

            //REFILL MP WITH SCRIPT
            int refilRate = 2;
            
            if(openborvariant("elapsed_time")%refilRate == 0){
                changeentityproperty(player, "mp", getentityproperty(player, "mp")+1);
            }

            //SHOW THE CURRENT MP IN NUMBERS, ERASE IT WHEN ALL TESTS ARE DONE
            drawstring(xPos, yPos+yPos/4, 0, getentityproperty(player, "mp"));
        }
    }
}

 
Thank you again @Kratus!
I made some changes, in part because of my characters will probably not have the same Max MP nor the same MP recovery thant others' ones and thus I keep the char's mpset and remove your MP recovery code. But your code has a growing MP bar fluider than my current one though, since mp recovey of mpset makes evolve the MP bar only each second. If I want to have your fluidity again I guess I should add two parameters like "if the char's name is blabla or blabla then MP max is XX" in the code, one for MP Max and another for MP recovery. Unless you have a better idea.
 
If I want to have your fluidity again
The fluidity is due to the recovery code I added at the end of the script, this way you can adjust not only how much mp will be recovered but also the delay between every recovery cycle.

add two parameters like "if the char's name is blabla or blabla then MP max is XX" in the code, one for MP Max and another for MP recovery. Unless you have a better idea
Yes, I think your idea is the right way to go. You can first check the entity name and then define all other parameters based on it. You can create many different MP profiles based on every entity name.
 
The fluidity is due to the recovery code I added at the end of the script, this way you can adjust not only how much mp will be recovered but also the delay between every recovery cycle.
Yes, I'm aware of it. I am not sure to be able to determine how fast you parameter in this script, though. One cycle every 50ms, I guess.

Yes, I think your idea is the right way to go. You can first check the entity name and then define all other parameters based on it. You can create many different MP profiles based on every entity name.
Okay, thanks. I wasn't familiar with the updated.c but it's good to know it can centralize this kind of parameters.
 
Yes, I'm aware of it. I am not sure to be able to determine how fast you parameter in this script, though. One cycle every 50ms, I guess.


Okay, thanks. I wasn't familiar with the updated.c but it's good to know it can centralize this kind of parameters.
I updated the code and commented on the most important parts where, and yes you can define the amount to be changed and the recovery rate in seconds separately.

After some tests I think you may not need to get the character's name, because once you change the mp at the character header the script will adapt automatically to it. However, everything will be based on a formula that splits the mp in 9 parts, so if you have a character with 600 mp max, the first bar phase will be 66 and not 100. You can see some examples on the video below.

C:
void main()
{
    void player1 = getplayerproperty(0, "entity");
    void player2 = getplayerproperty(1, "entity");
    
    //CHECK IF THE GAME IS IN-LEVEL TO AVOID SELECT SCREEN AND OTHER EVENTS
    //CHECK IF THE GAME IS NOT PAUSED TO PREVENT POSSIBLE EFFECTS (OR SCRIPTED REFILL) FROM WORKING DURING PAUSE MENU
    if(openborvariant("in_level") && !openborvariant("pause")){
        drawMp(player1, 0);
        drawMp(player2, 1);
    }
}

void drawMp(void player, int pIndex)
{//Draw custom mp bar

    //DOUBLE-CHECK FOR SAFE, CONFIRM IF THE PLAYER IS NOT NULL AND IF EXISTS
    if(player != NULL()){
        if(getentityproperty(player, "exists")){
            int maxMp        = getentityproperty(player, "maxmp");
            int mp            = getentityproperty(player, "mp");
            int xPos        = 1; //BASE X POSITION USED BY PLAYER 1
            int xDif        = 120; //DIFFERENCE IN X AXIS BETWEEN EACH PLAYER HUD (FOR 480X272 RESOLUTION, SPLIT THE SCREEN IN 4 PARTS)
            int xAdd        = xDif*pIndex; //CALCULATE THE X POSITION OF EACH PLAYER MP BAR AUTOMATICALLY
            int xSize        = 100; //BAR SIZE IN X AXIS
            int yPos        = 40; //BASE Y POSITION USED BY ALL PLAYERS
            int ySize        = 5; //BAR SIZE IN Y AXIS
            int backLayer    = 40000; //BACKFILL LAYER
            int barLayer    = 50000; //MP BAR LAYER
            int black        = rgbcolor(0,0,0);
            int blue        = rgbcolor(0,0,255);
            int purple        = rgbcolor(255,0,255);
            int darkBlue    = rgbcolor(0,0,100);
            int darkpurple    = rgbcolor(100,0,100);
            int currentMp;
            int currentMax;

            //PHASE 1, DETECT IF THE MP IS LOWER THAN 1/9
            if(mp <= maxMp/9){

                //FORMULA
                currentMax    = maxMp/9; //GET THE CHARACTER MAX MP AND SPLIT BY 9, REACHING THE VALUE OF 100
                currentMp    = (mp*xSize)/currentMax; //CALCULATE REMAINING MP BAR USING THE PREVIOUSLY DEFINED SIZE

                //DRAW BACK FILL
                drawbox(xPos+xAdd, yPos, xSize, ySize, backLayer, black);

                //DRAW CURRENT MP
                if(currentMp > 0){drawbox(xPos+xAdd, yPos, currentMp, ySize, barLayer, blue);}
            }else

            //PHASE 2, DETECT IF THE MP IS HIGHER THAN 1/9 BUT LOWER THAN 9/9
            if(mp > maxMp/9 && mp < maxMp){

                //FORMULA
                currentMax    = maxMp; //GET THE CHARACTER MAX MP AND USE IT IN ITS TOTAL VALUE OF 900
                currentMp    = (mp*xSize)/currentMax; //CALCULATE REMAINING MP BAR USING THE PREVIOUSLY DEFINED SIZE

                //DRAW BACK FILL
                drawbox(xPos+xAdd, yPos, xSize, ySize, backLayer, darkBlue);

                //DRAW CURRENT MP
                drawbox(xPos+xAdd, yPos, currentMp, ySize, barLayer, purple);
            }else

            //FULL MP
            if(mp >= maxMp){

                //FORMULA
                currentMax    = maxMp; //GET THE CHARACTER MAX MP AND USE IT IN ITS TOTAL VALUE OF 900
                currentMp    = (mp*xSize)/currentMax; //CALCULATE REMAINING MP BAR USING THE PREVIOUSLY DEFINED SIZE

                //DRAW CURRENT MP
                drawbox(xPos+xAdd, yPos, currentMp, ySize, barLayer, darkpurple);
            }

            //REFILL MP WITH SCRIPT
            float time            = openborvariant("elapsed_time");
            float centiseconds    = 200;
            float rate            = 0.005; //RECOVERY CYCLE DURATION IN SECONDS, YOU CAN USE FLOAT VALUES SMALLER THAN 1 TO INCREASE THE RECOVERY SPEED
            float delay            = centiseconds*rate;
            float recoveryTime    = getentityvar(player, "recoveryTime");
            int amount            = 1; //MP AMOUNT RECOVERED AT EACH CYCLE

            //START THE "RECOVERY TIME" VARIABLE
            if(recoveryTime == NULL()){setentityvar(player, "recoveryTime", time+delay);}
            
            //ADD MP AMOUNT AT EACH CYCLE IF SMALLER THAN MAX
            if(mp < maxMp){
                if(time > recoveryTime){
                    changeentityproperty(player, "mp", mp+amount);
                    setentityvar(player, "recoveryTime", time+delay);
                }
            }

            //SHOW THE CURRENT MP IN NUMBERS, ERASE IT WHEN ALL TESTS ARE DONE
            drawstring(xPos, yPos+yPos/4, 0, mp);
        }
    }
}

 
Thank you buddy for your tests and detailed explanations! :D
I'll need time to understand well your code and maybe I'll ask questions about it. I should have written my own code last time to show other differences even though it's not big changes. My MP bar is 96px length and the second MP bar shows only from 100mp to max mp (it's below).

JavaScript:
void drawMp(void player, int pIndex)
{//Draw mp bar

    //USED FOR PLAYERS ALREADY IN-GAME
    if(player != NULL()){
        void type    = getentityproperty(player, "type");
        int exists    = getentityproperty(player, "exists");
       
        //DETECTS IF THE DEFINED PLAYER IS IN-GAME AND ALIVE
        if(exists){
            int realmaxMp        = getentityproperty(player, "maxmp");
            int maxMp        = getentityproperty(player, "maxmp");
            int currentMp    = getentityproperty(player, "mp");
            int xPos        = 25;
            int xDif        = 120;
            int xAdd        = xDif*pIndex;
            int xSize        = 96;
            int yPos        = 20;
            int yAdd        = 28;
            int ySize        = 4;
            int layer1        = 40000;
            int layer2        = 50000;
            int black        = rgbcolor(0,0,0);
            int blue        = rgbcolor(0,0,255);
            int purple        = rgbcolor(255,0,255);
            int darkBlue    = rgbcolor(0,0,100);
            int darkpurple    = rgbcolor(100,0,100);

            //PHASE 1
            if(currentMp < 100){

                //FORMULA
                maxMp        = 100;
                currentMp    = (currentMp*xSize)/(maxMp); //CALCULATE REMAINING MP BAR SIZE

                //DRAW BACK FILL
                drawbox(xPos+xAdd, yPos, xSize, ySize, layer1, black);

                //DRAW CURRENT MP
                if(currentMp > 0){drawbox(xPos+xAdd, yPos, currentMp, ySize, layer2, blue);}
            }else

            //PHASE 2
            if(currentMp >= 100 && currentMp < realmaxMp){

                //FORMULA
                //maxMp        = realmaxMp;
                currentMp    = ((currentMp-100)*xSize)/(realmaxMp-100); //CALCULATE REMAINING MP BAR SIZE

                //DRAW BACK FILL
                drawbox(xPos+xAdd, yPos, xSize, ySize, layer1, darkBlue);

                //DRAW CURRENT MP
                drawbox(xPos+xAdd, yPos, currentMp, ySize, layer2, purple);
            }else

            //FULL
            if(currentMp >= realmaxMp){

                //FORMULA
                maxMp        = realmaxMp;
                currentMp    = (currentMp*xSize)/(realmaxMp); //CALCULATE REMAINING MP BAR SIZE

                //DRAW CURRENT MP
                drawbox(xPos+xAdd, yPos, currentMp, ySize, layer2, darkpurple);
            }

            //REFILL MP WITH SCRIPT
            //int refilRate = 2;
           
            //if(openborvariant("elapsed_time")%refilRate == 0){
            //    changeentityproperty(player, "mp", getentityproperty(player, "mp")+1);
            //}

            //SHOW THE CURRENT MP IN NUMBERS, ERASE IT WHEN ALL TESTS ARE DONE
            drawstring(xPos, yPos+yPos/4, 0, getentityproperty(player, "mp"));
        }
    }
}

After some tests I think you may not need to get the character's name, because once you change the mp at the character header the script will adapt automatically to it.
Yes, but about MP rate I don't know how to deal without character's name since all character's MP rate header are 0.

However, everything will be based on a formula that splits the mp in 9 parts, so if you have a character with 600 mp max, the first bar phase will be 66 and not 100. You can see some examples on the video below.
It's where I need time to think about if it could be ok. Initially the goal is to make all the characters have the same special attacks energy cost and that matches with the amount of the first phase MP bar.
 
Back
Top Bottom