Mega Man Charge Attack script question.

DD Tokki

Well-known member
Code:
void main() {
    if(openborvariant("in_level")){ //Here is the conditional!
      
  void self = getlocalvar("self");

  charge_attack(self,"attack2",rgbcolor(0x00,0x26,0x88),rgbcolor(0x43,0x00,0xDA),rgbcolor(0x00,0xDA,0x0F),openborvariant("game_speed")*6,"ANI_FREESPECIAL17","ANI_FREESPECIAL21","ANI_FREESPECIAL13","data/sounds/dummy.wav",openborvariant("game_speed")*0.2,"cflash",0,0,0);
    }
}
int charge_attack(void self, char key, int color1, int color2, int color3, int max_charge_time, char atk_name1, char atk_name2, char atk_name3, char sound_fx, int sound_duration, char flashing_ent, int flash_frame_length, int on_base_flag, int first_atk_flag) {
    int time = openborvariant("elapsed_time");
    int p = getentityproperty(self,"playerindex");
    int CHARGE_ATK1 = openborconstant(atk_name1);
    int CHARGE_ATK2 = openborconstant(atk_name2);
    int CHARGE_ATK3 = openborconstant(atk_name3);

    if ( playerkeys(self,0,key) ) {
        if ( getlocalvar("charge_time") == NULL() ) { // unsetted time
            if ( time+max_charge_time >= openborconstant("MAX_INT") ) { // time protection
                changeopenborvariant("elapsed_time",0);
                time = openborvariant("elapsed_time");
            }
            setlocalvar("charge_time",time+max_charge_time);
        } else { // setted time
            int time_range = max_charge_time/3;
            int charge_time = time%max_charge_time;

            // FLASHING
            if ( time < getlocalvar("charge_time")-time_range*2 ) {
                flashing_color(self,color1,openborvariant("game_speed")/10,0);
                setlocalvar("charge_atk",0);
            } else if ( time < getlocalvar("charge_time")-time_range*1 ) {
                flashing_color(self,color2,openborvariant("game_speed")/15,0);
                setlocalvar("charge_atk",1);
            } else {
                flashing_color(self,color3,openborvariant("game_speed")/20,0);
                setlocalvar("charge_atk",2);
            }

            // SOUND
            if ( getlocalvar("charge_sound_time") == NULL() ) {
                if ( sound_fx == NULL() || sound_duration == NULL() ) return -1;
                if ( time+max_charge_time >= openborconstant("MAX_INT") ) { // time protection
                    changeopenborvariant("elapsed_time",0);
                    time = openborvariant("elapsed_time");
                }
                playsample(loadsample(sound_fx));
                setlocalvar("charge_sound_time",time+sound_duration);
            } else if ( time > getlocalvar("charge_sound_time") ) setlocalvar("charge_sound_time",NULL());

            // FLASH ENTITY
            if ( getlocalvar("charge_flash_ent") == NULL() ) {
                float x = getentityproperty(self,"x");
                float z = getentityproperty(self,"z");
                float y = getentityproperty(self,"y");
                float base = getentityproperty(self,"base");
                float dir = getentityproperty(self,"direction");
                float height = getentityproperty(self,"height");
                void subent;

                if ( flashing_ent == NULL() ) return -1;

                if ( height == NULL() ) height = 0;
                clearspawnentry();
                setspawnentry("name", flashing_ent);
                subent = spawn();
                changeentityproperty(subent, "no_adjust_base", 1);
                changeentityproperty(subent, "position", x, z, y+(height/2));
                changeentityproperty(subent, "base", y+(height/2));
                changeentityproperty(subent, "direction", dir);
                changeentityproperty(subent, "parent", self);
                setlocalvar("charge_flash_ent",subent);
            } else {
                void subent = getlocalvar("charge_flash_ent");

                if ( getentityproperty(subent,"exists") ) {
                    if ( getentityproperty(subent,"defaultmodel") == flashing_ent ) {
                        if ( flash_frame_length != NULL() ) {
                            if ( getentityproperty(subent,"animpos") >= flash_frame_length ) {
                                killentity(subent);
                                setlocalvar("charge_flash_ent",NULL());
                            }
                        }
                    } else setlocalvar("charge_flash_ent",NULL());
                } else setlocalvar("charge_flash_ent",NULL());
            }
        }
    } else {
        if ( getlocalvar("charge_time") != NULL() ) {
            float y = getentityproperty(self,"y");
            float base = getentityproperty(self,"base");

            if ( first_atk_flag == NULL() ) first_atk_flag = 0;

            // PERFORM AN ATTACK
            if ( getlocalvar("charge_atk") != NULL() ) {
                if ( on_base_flag != NULL() && on_base_flag > 0 && y > base ) return 0;

                if ( getlocalvar("charge_atk") == 0 ) {
                   if ( first_atk_flag ) performattack(self,CHARGE_ATK1,1);
                } else if ( getlocalvar("charge_atk") == 1 ) performattack(self,CHARGE_ATK2,1);
                else performattack(self,CHARGE_ATK3,1);
            }

            // RESET
            clear_flashing(self,0);
            setlocalvar("charge_sound_time",NULL());
            if ( getentityproperty(getlocalvar("charge_flash_ent"),"exists") && getentityproperty(getlocalvar("charge_flash_ent"),"defaultmodel") == flashing_ent ) killentity(getlocalvar("charge_flash_ent"));
            setlocalvar("charge_flash_ent",NULL());
            setlocalvar("charge_atk",NULL());
            setlocalvar("charge_time",NULL());
        }
    }
}

void flashing_color(void self, int colour, int frames, int reset_flag) {
    int time = openborvariant("elapsed_time");
    int flash_frames = frames;
    float time_range = flash_frames/2;
    int no_colour = rgbcolor(0x00,0x00,0x00);
    //int colour1 = rgbcolor(0xFF,0xFF,0x00);
    //int colour2 = rgbcolor(0xFF,0x00,0x00);

    if ( reset_flag == NULL() ) reset_flag = 0;

    time %= flash_frames;

    if ( time <= time_range ) {
        setlocalvar("next_flash_color",colour);
        setlocalvar("step_flash_color", 1);
    } else {
        setlocalvar("next_flash_color", no_colour);
        setlocalvar("step_flash_color", NULL());
    }

    changedrawmethod(self, "enabled", 1);
    if ( reset_flag ) changedrawmethod(self, "reset", 1);

    if ( getlocalvar("step_flash_color") == NULL() ) {
        changedrawmethod(self, "tintmode", 0);
        changedrawmethod(self, "tintcolor", 0);
        changedrawmethod(self, "fillcolor", 0);
    } else if ( getlocalvar("step_flash_color") == 1 ) {
        changedrawmethod(self, "tintmode", 6);
        changedrawmethod(self, "fillcolor", 0);
        changedrawmethod(self, "tintcolor", getlocalvar("next_flash_color"));
    }

    if ( reset_flag ) {
        changedrawmethod(NULL(), "enabled", 0);
        changedrawmethod(NULL(), "reset", 1);
    }
}

void clear_flashing(void self, int reset_flag) {
    setlocalvar("set_flash_time",NULL());
    setlocalvar("next_flash_color",NULL());
    setlocalvar("step_flash_color",NULL());

    if ( reset_flag == NULL() ) reset_flag = 0;

    changedrawmethod(self, "tintmode", 0);
    changedrawmethod(self, "tintcolor", 0);
    changedrawmethod(self, "fillcolor", 0);

    if ( reset_flag ) {
        changedrawmethod(self, "enabled", 0);
        changedrawmethod(self, "reset", 1);
        changedrawmethod(NULL(), "enabled", 0);
        changedrawmethod(NULL(), "reset", 1);
    }
}

name Rock
type Player
health 100
mpset 100 0 0 6 0 0
speed 11
jumpspeed 13
jumpheight 4
jumpmove 3
risetime 100
makeinv 4
riseinv 4
antigravity -50
defense normal 1
falldie 1
noquake 1
candamage enemy

#==============================================================================================================

palette data/sprites/chara/rock/Idle.gif

icon data/sprites/chara/rock/icon.gif
animationscript data/scripts/scripta.c
ondrawscript data/scripts/continue.c
onblockwscript data/scripts/hitwall.c
onblocksscript data/scripts/hitwall.c
keyscript data/scripts/keymovea.c
script data/scripts/charge.c


I saw the Mega Man Charge Attack script in this link.
I saved the script and applied it to the entity, but nothing changed, so I want to know the exact usage.
 
@DD Tokki

I coded a script to replicate Megaman's charge attack some time ago, maybe it can be useful for you. I made some changes to adapt for your game, you can see an example in the video below.

I used both the freespecial3/freespecial4 as a test but you can replace them with other animations. For the freespecial4 you need to apply the jumping status by changing the @cmd jump flag to 1.

C:
anim    freespecial4 #(차지샷2 공중)
    loop    0
    energycost    100
    mponly    1
    jumpframe    0 1.4 -1.4
    delay       20
    offset    12 26
    bbox    5 1 14 26
    sound    data/sounds/blues/buster3.wav
    @cmd    shoot "blues-c" 14 15 0
    @cmd    jump 1
    frame    data/sprites/chara/blues/jump-attack-b01.gif
    delay    999
    offset    9 25
    bbox    2 0 14 26
    frame    data/sprites/chara/blues/jump-attack-b02.gif

The script works in the ondrawscript event, I used the one that already exists in your game (player.c).
The sample will increase speed automatically according to how much time the button is held, you can change it to any other sound if you want.

C:
void chargeAttack()
{//Hold button to make a charged attack, Megaman style
    void self       = getlocalvar("self");
    void vAniID     = getentityproperty(self,"animationID");
    int iPIndex     = getentityproperty(self,"playerindex");
    int height      = getentityproperty(self,"y");
    int base        = getentityproperty(self,"base");
    int tintMode    = 3;
    int tintColor;
    float time      = openborvariant("elapsed_time");
    float rate      = 10;
    float delay     = 370;

    if(playerkeys(iPIndex, 1, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
    
    if(playerkeys(iPIndex, 0, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) == NULL()){
            setglobalvar("chargeStart"+iPIndex, time+delay);
        }
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            if(getglobalvar("chargeStart"+iPIndex) > time){
                if((getglobalvar("chargeStart"+iPIndex) - time) < delay/2){
                    tintColor = openborvariant("elapsed_time") - getglobalvar("chargeStart"+iPIndex);

                    //GRADUAL COLOR INCREMENT
                    changedrawmethod(self, "enabled", 1);
                    changedrawmethod(self, "tintmode", tintMode);
                    changedrawmethod(self, "tintcolor", rgbcolor(tintColor, tintColor, 0));

                    int volume  = openborvariant("effectvol")/3;
                    int speed   = (time-(getglobalvar("chargeStart"+iPIndex)-delay))/2;

                    if(getglobalvar("sampleCharge") == NULL()){
                        setglobalvar("sampleCharge", loadsample("data/sounds/buster.wav"));
                    }

                    if(time%4 == 0){
                        playsample(getglobalvar("sampleCharge"), 0, volume, volume, speed, 0);
                    }
                    drawstring(50, 50, 0, speed);
                }
            }
            else
            {
                //BLINK COLOR WHEN FULL
                changedrawmethod(self, "enabled", 1);
                changedrawmethod(self, "tintmode", tintMode);
                changedrawmethod(self, "tintcolor", rgbcolor(time*rate, time*rate, 0));
            }
        }
    }
    else
    if(playerkeys(iPIndex, 2, "attack")){
        if(openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex)){

            //WHILE IDLING/WALKING/RUNNING
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
                
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL3"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL4"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }
        else
        {
            if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                changedrawmethod(self, "enabled", 0);
                setglobalvar("chargeStart"+iPIndex, NULL());
            }
        }
    }
    else
    {
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
}

As you can see in the test the charged attack can only be used when the charge time is reached, otherwise the charge will be interrupted with no attack.
 
@DD Tokki

I coded a script to replicate Megaman's charge attack some time ago, maybe it can be useful for you. I made some changes to adapt for your game, you can see an example in the video below.

I used both the freespecial3/freespecial4 as a test but you can replace them with other animations. For the freespecial4 you need to apply the jumping status by changing the @cmd jump flag to 1.

C:
anim    freespecial4 #(차지샷2 공중)
    loop    0
    energycost    100
    mponly    1
    jumpframe    0 1.4 -1.4
    delay       20
    offset    12 26
    bbox    5 1 14 26
    sound    data/sounds/blues/buster3.wav
    @cmd    shoot "blues-c" 14 15 0
    @cmd    jump 1
    frame    data/sprites/chara/blues/jump-attack-b01.gif
    delay    999
    offset    9 25
    bbox    2 0 14 26
    frame    data/sprites/chara/blues/jump-attack-b02.gif

The script works in the ondrawscript event, I used the one that already exists in your game (player.c).
The sample will increase speed automatically according to how much time the button is held, you can change it to any other sound if you want.

C:
void chargeAttack()
{//Hold button to make a charged attack, Megaman style
    void self       = getlocalvar("self");
    void vAniID     = getentityproperty(self,"animationID");
    int iPIndex     = getentityproperty(self,"playerindex");
    int height      = getentityproperty(self,"y");
    int base        = getentityproperty(self,"base");
    int tintMode    = 3;
    int tintColor;
    float time      = openborvariant("elapsed_time");
    float rate      = 10;
    float delay     = 370;

    if(playerkeys(iPIndex, 1, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
   
    if(playerkeys(iPIndex, 0, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) == NULL()){
            setglobalvar("chargeStart"+iPIndex, time+delay);
        }
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            if(getglobalvar("chargeStart"+iPIndex) > time){
                if((getglobalvar("chargeStart"+iPIndex) - time) < delay/2){
                    tintColor = openborvariant("elapsed_time") - getglobalvar("chargeStart"+iPIndex);

                    //GRADUAL COLOR INCREMENT
                    changedrawmethod(self, "enabled", 1);
                    changedrawmethod(self, "tintmode", tintMode);
                    changedrawmethod(self, "tintcolor", rgbcolor(tintColor, tintColor, 0));

                    int volume  = openborvariant("effectvol")/3;
                    int speed   = (time-(getglobalvar("chargeStart"+iPIndex)-delay))/2;

                    if(getglobalvar("sampleCharge") == NULL()){
                        setglobalvar("sampleCharge", loadsample("data/sounds/buster.wav"));
                    }

                    if(time%4 == 0){
                        playsample(getglobalvar("sampleCharge"), 0, volume, volume, speed, 0);
                    }
                    drawstring(50, 50, 0, speed);
                }
            }
            else
            {
                //BLINK COLOR WHEN FULL
                changedrawmethod(self, "enabled", 1);
                changedrawmethod(self, "tintmode", tintMode);
                changedrawmethod(self, "tintcolor", rgbcolor(time*rate, time*rate, 0));
            }
        }
    }
    else
    if(playerkeys(iPIndex, 2, "attack")){
        if(openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex)){

            //WHILE IDLING/WALKING/RUNNING
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
               
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL3"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL4"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }
        else
        {
            if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                changedrawmethod(self, "enabled", 0);
                setglobalvar("chargeStart"+iPIndex, NULL());
            }
        }
    }
    else
    {
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
}

As you can see in the test the charged attack can only be used when the charge time is reached, otherwise the charge will be interrupted with no attack.
thank you
Charge shot works well.
It's too much to wish, but I also want to make shots that are not full power when the charge is about 50%.
0%=buster
1% to 99% = charge shot 1
100% = charge shot 2
 
thank you
Charge shot works well.
It's too much to wish, but I also want to make shots that are not full power when the charge is about 50%.
0%=buster
1% to 99% = charge shot 1
100% = charge shot 2
@DD Tokki

Yeah, it's possible. Please, replace the chargeAttack() script you have inside the player.c with this new one.

C:
void chargeAttack()
{//Hold button to make a charged attack, Megaman style
    void self       = getlocalvar("self");
    void vAniID     = getentityproperty(self,"animationID");
    int iPIndex     = getentityproperty(self,"playerindex");
    int height      = getentityproperty(self,"y");
    int base        = getentityproperty(self,"base");
    int tintMode    = 3;
    int tintColor;
    float time      = openborvariant("elapsed_time");
    float rate      = 10;
    float delay     = 370;

    if(playerkeys(iPIndex, 1, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
   
    if(playerkeys(iPIndex, 0, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) == NULL()){
            setglobalvar("chargeStart"+iPIndex, time+delay);
        }
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            if(getglobalvar("chargeStart"+iPIndex) > time){
                if((getglobalvar("chargeStart"+iPIndex) - time) < delay/2){
                    tintColor = openborvariant("elapsed_time") - getglobalvar("chargeStart"+iPIndex);

                    //GRADUAL COLOR INCREMENT
                    changedrawmethod(self, "enabled", 1);
                    changedrawmethod(self, "tintmode", tintMode);
                    changedrawmethod(self, "tintcolor", rgbcolor(tintColor, tintColor, 0));

                    int volume  = openborvariant("effectvol")/3;
                    int speed   = (time-(getglobalvar("chargeStart"+iPIndex)-delay))/2;

                    if(getglobalvar("sampleCharge") == NULL()){
                        setglobalvar("sampleCharge", loadsample("data/sounds/buster.wav"));
                    }

                    if(time%4 == 0){
                        playsample(getglobalvar("sampleCharge"), 0, volume, volume, speed, 0);
                    }
                    drawstring(50, 50, 0, speed);
                }
            }
            else
            {
                //BLINK COLOR WHEN FULL
                changedrawmethod(self, "enabled", 1);
                changedrawmethod(self, "tintmode", tintMode);
                changedrawmethod(self, "tintcolor", rgbcolor(time*rate, time*rate, 0));
            }
        }
    }
    else
    if(playerkeys(iPIndex, 2, "attack")){

        //FULLY CHARGED
        if(openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex)){

            //WHILE IDLING/WALKING/RUNNING (100%)
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
               
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL6"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL7"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }else

        //NOT FULLY CHARGED (0-99%)
        {
            //WHILE IDLING/WALKING/RUNNING
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
               
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL3"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL4"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }
    }
    else
    {
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
}

And add the new freespecials 6 and 7 to the Blues character.

C:
anim    freespecial6 #(차지샷2)
    loop    0
    energycost    100
    mponly    1
    delay       6
    offset    11 24
    bbox    4 1 14 24
    sound    data/sounds/blues/buster3.wav
    @cmd    shoot "blues-c" 14 17 0
    @cmd    shoot "blues-c" 14 7 0
    @cmd    dasher -0.6 0 0
    frame    data/sprites/chara/blues/attack-b01.gif
    @cmd    dasher -0.2 0 0
    frame    data/sprites/chara/blues/attack-b01.gif
    delay    24
    @cmd    stop
    frame    data/sprites/chara/blues/attack-b01.gif
    delay       8
    offset    8 23
    bbox    1 0 14 24
    @cmd    stop
    frame    data/sprites/chara/blues/attack-b02.gif
    delay    20
    offset    9 23
    bbox    2 0 14 24
    frame    data/sprites/chara/blues/idle.gif

anim    freespecial7 #(차지샷2 공중)
    loop    0
    energycost    100
    mponly    1
    jumpframe    0 1.4 -1.4
    delay       20
    offset    12 26
    bbox    5 1 14 26
    sound    data/sounds/blues/buster3.wav
    @cmd    shoot "blues-c" 14 20 0
    @cmd    shoot "blues-c" 14 10 0
    @cmd    jump 1
    frame    data/sprites/chara/blues/jump-attack-b01.gif
    delay    999
    offset    9 25
    bbox    2 0 14 26
    frame    data/sprites/chara/blues/jump-attack-b02.gif

EDIT: You can freely change these animations, I just put as an example by shooting two projectiles instead of one to show that the attack is fully charged.
 
@DD Tokki

Yeah, it's possible. Please, replace the chargeAttack() script you have inside the player.c with this new one.

C:
void chargeAttack()
{//Hold button to make a charged attack, Megaman style
    void self       = getlocalvar("self");
    void vAniID     = getentityproperty(self,"animationID");
    int iPIndex     = getentityproperty(self,"playerindex");
    int height      = getentityproperty(self,"y");
    int base        = getentityproperty(self,"base");
    int tintMode    = 3;
    int tintColor;
    float time      = openborvariant("elapsed_time");
    float rate      = 10;
    float delay     = 370;

    if(playerkeys(iPIndex, 1, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
  
    if(playerkeys(iPIndex, 0, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) == NULL()){
            setglobalvar("chargeStart"+iPIndex, time+delay);
        }
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            if(getglobalvar("chargeStart"+iPIndex) > time){
                if((getglobalvar("chargeStart"+iPIndex) - time) < delay/2){
                    tintColor = openborvariant("elapsed_time") - getglobalvar("chargeStart"+iPIndex);

                    //GRADUAL COLOR INCREMENT
                    changedrawmethod(self, "enabled", 1);
                    changedrawmethod(self, "tintmode", tintMode);
                    changedrawmethod(self, "tintcolor", rgbcolor(tintColor, tintColor, 0));

                    int volume  = openborvariant("effectvol")/3;
                    int speed   = (time-(getglobalvar("chargeStart"+iPIndex)-delay))/2;

                    if(getglobalvar("sampleCharge") == NULL()){
                        setglobalvar("sampleCharge", loadsample("data/sounds/buster.wav"));
                    }

                    if(time%4 == 0){
                        playsample(getglobalvar("sampleCharge"), 0, volume, volume, speed, 0);
                    }
                    drawstring(50, 50, 0, speed);
                }
            }
            else
            {
                //BLINK COLOR WHEN FULL
                changedrawmethod(self, "enabled", 1);
                changedrawmethod(self, "tintmode", tintMode);
                changedrawmethod(self, "tintcolor", rgbcolor(time*rate, time*rate, 0));
            }
        }
    }
    else
    if(playerkeys(iPIndex, 2, "attack")){

        //FULLY CHARGED
        if(openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex)){

            //WHILE IDLING/WALKING/RUNNING (100%)
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
              
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL6"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL7"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }else

        //NOT FULLY CHARGED (0-99%)
        {
            //WHILE IDLING/WALKING/RUNNING
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
              
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL3"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL4"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }
    }
    else
    {
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
}

And add the new freespecials 6 and 7 to the Blues character.

C:
anim    freespecial6 #(차지샷2)
    loop    0
    energycost    100
    mponly    1
    delay       6
    offset    11 24
    bbox    4 1 14 24
    sound    data/sounds/blues/buster3.wav
    @cmd    shoot "blues-c" 14 17 0
    @cmd    shoot "blues-c" 14 7 0
    @cmd    dasher -0.6 0 0
    frame    data/sprites/chara/blues/attack-b01.gif
    @cmd    dasher -0.2 0 0
    frame    data/sprites/chara/blues/attack-b01.gif
    delay    24
    @cmd    stop
    frame    data/sprites/chara/blues/attack-b01.gif
    delay       8
    offset    8 23
    bbox    1 0 14 24
    @cmd    stop
    frame    data/sprites/chara/blues/attack-b02.gif
    delay    20
    offset    9 23
    bbox    2 0 14 24
    frame    data/sprites/chara/blues/idle.gif

anim    freespecial7 #(차지샷2 공중)
    loop    0
    energycost    100
    mponly    1
    jumpframe    0 1.4 -1.4
    delay       20
    offset    12 26
    bbox    5 1 14 26
    sound    data/sounds/blues/buster3.wav
    @cmd    shoot "blues-c" 14 20 0
    @cmd    shoot "blues-c" 14 10 0
    @cmd    jump 1
    frame    data/sprites/chara/blues/jump-attack-b01.gif
    delay    999
    offset    9 25
    bbox    2 0 14 26
    frame    data/sprites/chara/blues/jump-attack-b02.gif

EDIT: You can freely change these animations, I just put as an example by shooting two projectiles instead of one to show that the attack is fully charged.
thank you. Medium charge shots work well too.
 
I forgot a drawstring line in the script, you can erase it because it's used only for debug purposes showing the charge value on the screen.
bor - 0046.png

I'm having a bit of a problem.
The moment you press the Buster button and release it, the Buster and Charge Shot go out together. The charge input starts from 0%, so I guess it's not like that.

NOT FULLY CHARGED (0-99%)

I think I can give 0% a delay of 10~20%, but I don't know which part I need to fix.
 
View attachment 3528

I'm having a bit of a problem.
The moment you press the Buster button and release it, the Buster and Charge Shot go out together. The charge input starts from 0%, so I guess it's not like that.

NOT FULLY CHARGED (0-99%)

I think I can give 0% a delay of 10~20%, but I don't know which part I need to fix.
I need a video to understand what's happening. And I tested in the Blues entity, I don't know how other character works.

Currently any charge amount before full will activate freespecial6 and 7, and only if the charge is full it will activate the freespecial3 and 4. The formula doesn't work in percentage, it's counted using a timer.

EDIT: This code is based on the MVSC Megaman, which does a normal shot first before start charging. There's a delay to start the charge otherwise it will start in any button press.

EDIT2: I suggest to disable the native charge attack too.

C:
anim chargeattack
    chargetime 9999
    loop    0
    delay    1
    offset    62 126
    frame    data/chars/heroes/axel/idle00.png
 
Last edited:
I need a video to understand what's happening. And I tested in the Blues entity, I don't know how other character works.

Currently any charge amount before full will activate freespecial6 and 7, and only if the charge is full it will activate the freespecial3 and 4. The formula doesn't work in percentage, it's counted using a timer.

EDIT: This code is based on the MVSC Megaman, which does a normal shot first before start charging. There's a delay to start the charge otherwise it will start in any button press.
I'll upload a test video later at home.
 
Ok, no problem. After seeing your screenshot maybe you are referring to the gauge bar in the HUD. I didn't apply it, the code is just an example for charge attack and is not complete yet.

Even if you press and release the attack button quickly, the buster and charge shot will go out together in the meantime.
 

Even if you press and release the attack button quickly, the buster and charge shot will go out together in the meantime.
Now I understand, both shots will fire at the same time. I made a fix for it, now the code will check if the charge time is inside the allowed range and only after the initial delay.
Please, replace the old code with this new one.

C:
void chargeAttack()
{//Hold button to make a charged attack, Megaman style
    void self       = getlocalvar("self");
    void vAniID     = getentityproperty(self,"animationID");
    int iPIndex     = getentityproperty(self,"playerindex");
    int height      = getentityproperty(self,"y");
    int base        = getentityproperty(self,"base");
    int tintMode    = 3;
    int tintColor;
    float time      = openborvariant("elapsed_time");
    float rate      = 10;
    float delay     = 370;

    if(playerkeys(iPIndex, 1, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
    
    if(playerkeys(iPIndex, 0, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) == NULL()){
            setglobalvar("chargeStart"+iPIndex, time+delay);
        }
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            if(getglobalvar("chargeStart"+iPIndex) > time){
                if((getglobalvar("chargeStart"+iPIndex) - time) < delay/2){
                    tintColor = openborvariant("elapsed_time") - getglobalvar("chargeStart"+iPIndex);

                    //GRADUAL COLOR INCREMENT
                    changedrawmethod(self, "enabled", 1);
                    changedrawmethod(self, "tintmode", tintMode);
                    changedrawmethod(self, "tintcolor", rgbcolor(tintColor, tintColor, 0));

                    int volume  = openborvariant("effectvol")/3;
                    int speed   = (time-(getglobalvar("chargeStart"+iPIndex)-delay))/2;

                    if(getglobalvar("sampleCharge") == NULL()){
                        setglobalvar("sampleCharge", loadsample("data/sounds/buster.wav"));
                    }

                    if(time%4 == 0){
                        playsample(getglobalvar("sampleCharge"), 0, volume, volume, speed, 0);
                    }
                    drawstring(50, 50, 0, speed);
                }
            }
            else
            {
                //BLINK COLOR WHEN FULL
                changedrawmethod(self, "enabled", 1);
                changedrawmethod(self, "tintmode", tintMode);
                changedrawmethod(self, "tintcolor", rgbcolor(time*rate, time*rate, 0));
            }
        }
    }
    else
    if(playerkeys(iPIndex, 2, "attack")){

        //FULLY CHARGED
        if(openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex)){

            //WHILE IDLING/WALKING/RUNNING (100%)
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
                
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL6"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL7"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }else

        //NOT FULLY CHARGED (0-99%)
        if( openborvariant("elapsed_time") <= getglobalvar("chargeStart"+iPIndex) &&
            openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex) - delay/2){

            //WHILE IDLING/WALKING/RUNNING
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
                
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL3"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL4"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }else

        //ANY OTHER WILL CLEAR ALL VARIABLES
        {
            if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                changedrawmethod(self, "enabled", 0);
                setglobalvar("chargeStart"+iPIndex, NULL());
            }
        }
    }
    else
    {
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
}
 
Now I understand, both shots will fire at the same time. I made a fix for it, now the code will check if the charge time is inside the allowed range and only after the initial delay.
Please, replace the old code with this new one.

C:
void chargeAttack()
{//Hold button to make a charged attack, Megaman style
    void self       = getlocalvar("self");
    void vAniID     = getentityproperty(self,"animationID");
    int iPIndex     = getentityproperty(self,"playerindex");
    int height      = getentityproperty(self,"y");
    int base        = getentityproperty(self,"base");
    int tintMode    = 3;
    int tintColor;
    float time      = openborvariant("elapsed_time");
    float rate      = 10;
    float delay     = 370;

    if(playerkeys(iPIndex, 1, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
   
    if(playerkeys(iPIndex, 0, "attack")){
        if(getglobalvar("chargeStart"+iPIndex) == NULL()){
            setglobalvar("chargeStart"+iPIndex, time+delay);
        }
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            if(getglobalvar("chargeStart"+iPIndex) > time){
                if((getglobalvar("chargeStart"+iPIndex) - time) < delay/2){
                    tintColor = openborvariant("elapsed_time") - getglobalvar("chargeStart"+iPIndex);

                    //GRADUAL COLOR INCREMENT
                    changedrawmethod(self, "enabled", 1);
                    changedrawmethod(self, "tintmode", tintMode);
                    changedrawmethod(self, "tintcolor", rgbcolor(tintColor, tintColor, 0));

                    int volume  = openborvariant("effectvol")/3;
                    int speed   = (time-(getglobalvar("chargeStart"+iPIndex)-delay))/2;

                    if(getglobalvar("sampleCharge") == NULL()){
                        setglobalvar("sampleCharge", loadsample("data/sounds/buster.wav"));
                    }

                    if(time%4 == 0){
                        playsample(getglobalvar("sampleCharge"), 0, volume, volume, speed, 0);
                    }
                    drawstring(50, 50, 0, speed);
                }
            }
            else
            {
                //BLINK COLOR WHEN FULL
                changedrawmethod(self, "enabled", 1);
                changedrawmethod(self, "tintmode", tintMode);
                changedrawmethod(self, "tintcolor", rgbcolor(time*rate, time*rate, 0));
            }
        }
    }
    else
    if(playerkeys(iPIndex, 2, "attack")){

        //FULLY CHARGED
        if(openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex)){

            //WHILE IDLING/WALKING/RUNNING (100%)
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
               
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL6"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL7"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }else

        //NOT FULLY CHARGED (0-99%)
        if( openborvariant("elapsed_time") <= getglobalvar("chargeStart"+iPIndex) &&
            openborvariant("elapsed_time") > getglobalvar("chargeStart"+iPIndex) - delay/2){

            //WHILE IDLING/WALKING/RUNNING
            if( vAniID == openborconstant("ANI_IDLE")       ||
                vAniID == openborconstant("ANI_WALK")       ||
                vAniID == openborconstant("ANI_RUN")        ||
                vAniID == openborconstant("ANI_ATTACK1")    ){
               
                setidle(self, openborconstant("ANI_IDLE"));
                changeentityproperty(self, "velocity", 0, 0, 0);
                performattack(self, openborconstant("ANI_FREESPECIAL3"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }

            //WHILE JUMPING
            if(vAniID == openborconstant("ANI_JUMP")){
                setidle(self, openborconstant("ANI_IDLE"));
                performattack(self, openborconstant("ANI_FREESPECIAL4"), 1);

                if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                    changedrawmethod(self, "enabled", 0);
                    setglobalvar("chargeStart"+iPIndex, NULL());
                }
            }
        }else

        //ANY OTHER WILL CLEAR ALL VARIABLES
        {
            if(getglobalvar("chargeStart"+iPIndex) != NULL()){
                changedrawmethod(self, "enabled", 0);
                setglobalvar("chargeStart"+iPIndex, NULL());
            }
        }
    }
    else
    {
        if(getglobalvar("chargeStart"+iPIndex) != NULL()){
            changedrawmethod(self, "enabled", 0);
            setglobalvar("chargeStart"+iPIndex, NULL());
        }
    }
}
thank you.
You can fire charge shots at will without relying on the mp gauge.
 
thank you.
You can fire charge shots at will without relying on the mp gauge.
Yeah, but for safety in case you don't use the freespecials to fire charged shots anymore, I suggest replacing all of them by "follow" animations because this last one is not triggered by any other routine in the engine and freespecials can be triggered with header commands.

You can even follow the same numbers, like follow3 to freespecial3, follow4 to freespecial4 and so on. In case you do it, don't forget to update the charge script too.
 
Back
Top Bottom