Please Help me to find correct place to insert Else Condition into this plugin

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
hi guys, i was looking through of the Mog_chaincombo plugin hoped to modify it myself but it's too complicated for me :|
Can you give me a little help? This plugin allow player to force Actor doing another Skill after he's played a skill (if player can press correctly a serial of buttons).

What i want to do is:
I want in the case player failed to chain combo, actors will play a default specified skill (same for all actors)
I assume we just need to insert an "else {force_action.skill(id);}" somewhere inside the plugin

Thank you!
(Plugin attached)
 

Attachments

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
Code:
//==============================
// * Invoke Action
//==============================
var _mog_bchain_bmngr_invokeAction = BattleManager.invokeAction;
BattleManager.invokeAction = function(subject, target) {
    if ($gameTemp._bchainData[1]) {BattleManager.setBchainPosition(subject, target)};
    _mog_bchain_bmngr_invokeAction.call(this,subject, target);   
    if (!target.result.i**** ()) {
        this._subject.forceAction ($dataSkills[x].id, -2);
        $gameTemp.clearBchain();
        BattleManager.processTurn();
    }
};
//==============================
// * execute Chain Action
//==============================
BattleManager.executeChainAction = function() {
    if ($gameTemp._bchainData[10]) {
        this._subject.forceAction($gameTemp._bchainData[1].id, -2);     
        $gameTemp.clearBchain();
        BattleManager.processTurn();
    } else {
    this._subject.forceAction ($dataSkills[x].id, -2);
        $gameTemp.clearBchain();
        BattleManager.processTurn();
    };
};
hopefully it works, I didn't do any testing.
 

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
Hi @Poryg thank you very much it work perfectly! Please it's the last time i bother you on this ( i forgot to mention it early @.@)
That i want the default skill to be played if target get killed too.
I supposed it should be target.isDead() or something but it didn't work
Can i ask where did you find those statement like !target.result.i**** () or $dataSkills[x]
If there is a place to check those maybe next time i can try to solve it myself without bother people @.@
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
Code:
//==============================
// * Check Chain Action
//==============================
BattleManager.checkChainAction = function() {  
    var item = this._subject.currentAction().item();
    var item_notes = item.note.split(/[\r\n]+/);
    item_notes.forEach(function(note) {
         var note_data = note.split(': ')
         if (note_data[0].toLowerCase() == "chain action"){            
             var par = note_data[1].split(':');
             var action = $dataSkills[Number(par[0])];
              var times = Math.min(Math.max(Number(par[1]),1),999);
             var duration = Math.min(Math.max(Number(par[2]),10),999);            
             if (action) {
                $gameTemp._bchainData[1] = action;
                $gameTemp._bchainData[6] = times;
                $gameTemp._bchainData[7] = duration;
             };
         };
    },this);
};

//==============================
// * Invoke Action
//==============================
var _mog_bchain_bmngr_invokeAction = BattleManager.invokeAction;
BattleManager.invokeAction = function(subject, target) {
    if ($gameTemp._bchainData[1]) {BattleManager.setBchainPosition(subject, target)};
    _mog_bchain_bmngr_invokeAction.call(this,subject, target);  
    if (!target.result.i**** () && !target.isDead ()) {
        this._subject.forceAction ($dataSkills[x].id, -2);
        $gameTemp.clearBchain();
        BattleManager.processTurn();
    }else if (target.isDead ()) {
        this._subject.forceAction ($dataSkills[x].id, -1);
        $gameTemp.clearBchain();
        BattleManager.processTurn();
    }
};

//==============================
// * can Use Chain Action
//==============================
BattleManager.canUseChainAction = function() {
    if (!$gameTemp._bchainData[1]) {return false};
    if (!$gameTemp._bchainData[11]) {return false};
    if (!this._subject) {return false};
    if (!this._subject.canInput()) {return false};
    if (this._subject.isDead()) {return false};
    if ($gameParty.isAllDead()) {return false};
    if ($gameTroop.isAllDead()) {return false};
    if (!this._subject.canUse($gameTemp._bchainData[1])) {return false};
    if ($gameTemp._bchainData[1].scope === 1 ||
         $gameTemp._bchainData[1].scope === 7 ||
         $gameTemp._bchainData[1].scope === 9) {
         if (!$gameTemp._bchainData[8]) {return false};
    }
    return true;
};
From the last function I deleted the condition that when the target is dead, it returns false. With that I also had to fix one of the functions, because it would be completely pointless to attack dead enemies, so I set the target to -1 if target is dead, which is a random target.

Can i ask where did you find those statement like !target.result.i**** () or $dataSkills[x]
Simply put, it's knowledge, reading and understanding of the code. If we take a look at the executeChainAction function, we can see that the important line, this._subject.forceAction () takes two parameters, one of them is skill, the second one is target. However, Moghunter inputs $gameTemp._bchainData[1] as his parameter. So if you track $gameTemp._bchainData[1] in the script using Search, you'll see it defined in this function.

Code:
//==============================
// * Check Chain Action
//==============================
BattleManager.checkChainAction = function() {  
    var item = this._subject.currentAction().item();
    var item_notes = item.note.split(/[\r\n]+/);
    item_notes.forEach(function(note) {
         var note_data = note.split(': ')
         if (note_data[0].toLowerCase() == "chain action"){            
             var par = note_data[1].split(':');
             var action = $dataSkills[Number(par[0])];
              var times = Math.min(Math.max(Number(par[1]),1),999);
             var duration = Math.min(Math.max(Number(par[2]),10),999);            
             if (action) {
                $gameTemp._bchainData[1] = action;
                $gameTemp._bchainData[6] = times;
                $gameTemp._bchainData[7] = duration;
             };
         };
    },this);
};
The important line is
Code:
$gameTemp._bchainData[1] = action;
. So when we take a look at what action is (it's defined in the same function), it's
Code:
var action = $dataSkills[Number(par[0])]
. In other words $dataSkills [parameter from the notetag].
That was when I knew how to define the case when you mess up.

When I was searching for the miss, it was a bit harder. Because I had to take a look at a different function. Browsing through the code I found out that the important one was InvokeAction function, because it is responsible for invoking the action (surprisingly). So I went to rpg_managers and searched for BattleManager.invokeAction
Code:
BattleManager.invokeAction = function(subject, target) {
    this._logWindow.push('pushBaseLine');
    if (Math.random() < this._action.itemCnt(target)) {
        this.invokeCounterAttack(subject, target);
    } else if (Math.random() < this._action.itemMrf(target)) {
        this.invokeMagicReflection(subject, target);
    } else {
        this.invokeNormalAction(subject, target);
    }
    subject.setLastTarget(target);
    this._logWindow.push('popBaseLine');
    this.refreshStatus();
};
And saw that there is one if which invokes counterattack, reflection or normal action. Since I wanted to know normal action, I tracked that one.
Code:
BattleManager.invokeNormalAction = function(subject, target) {
    var realTarget = this.applySubstitute(target);
    this._action.apply(realTarget);
    this._logWindow.displayActionResults(subject, realTarget);
};
And of course there is one important line: this._action.apply, which applies the action and leads to the result.
Because this._action suggests the final result is not hidden in rpg_managers (which a search of apply only confirms), but somewhere else. In particular in rpg_objects, because that's where Game_Action.prototype is defined. So let's search for something that might look like what we're searching there.
Code:
Game_Action.prototype.apply = function(target) {
    var result = target.result();
    this.subject().clearResult();
    result.clear();
    result.used = this.testApply(target);
    result.missed = (result.used && Math.random() >= this.itemHit(target));
    result.evaded = (!result.missed && Math.random() < this.itemEva(target));
    result.physical = this.isPhysical();
    result.drain = this.isDrain();
    if (result.i****()) {
        if (this.item().damage.type > 0) {
            result.critical = (Math.random() < this.itemCri(target));
            var value = this.makeDamageValue(target, result.critical);
            this.executeDamage(target, value);
        }
        this.item().effects.forEach(function(effect) {
            this.applyItemEffect(target, effect);
        }, this);
        this.applyItemUserEffect(target);
    }
};
And there is this one if case:
if (result.i**** ()).
Of course result, as we can see at the beginning of the function, means target.result (). So after confirming that it is what I want -
Code:
Game_ActionResult.prototype.i**** = function() {
    return this.used && !this.missed && !this.evaded;
};
I know that if I negate target.result().i**** (the exclam mark in front of that), I achieve that both the cases of miss and evade are covered.

So as you can see it's partially knowledge that lets me know which file do I search for core scripts (although there are 6 files, so it's not like it would take a lot of time), partially understanding of the code (because I need to figure out what each function does and I only do that by backtracking the functions) and huge deal of backtracking and searching. I see one function calls other functions, so I track these called functions and see what's going on. No magic in that.
 
Last edited:

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
Hi @Poryg , thanks for your detail explain and method for searching.
But there is a problem with your modified script, that Player won't perform the default skill but require to input Chaincommand then performing an Normal Attack (or replay the previous command ? )

So i tried to modify it this way:
//==============================

// * Invoke Action

//==============================

var _mog_bchain_bmngr_invokeAction = BattleManager.invokeAction;

BattleManager.invokeAction = function(subject, target) {

if ($gameTemp._bchainData[1]) {BattleManager.setBchainPosition(subject, target)};

_mog_bchain_bmngr_invokeAction.call(this,subject, target);

if ( !target.result().i****() ) {

this._subject.forceAction ($dataSkills[30].id, -2);

$gameTemp.clearBchain();

BattleManager.processTurn();}

};


var cancelme = 0;

//==============================

// * can Use Chain Action

//==============================

BattleManager.canUseChainAction = function() {

if (!$gameTemp._bchainData[1]) {return false};

if (!$gameTemp._bchainData[11]) {return false};

if (!this._subject) {return false};

if (!this._subject.canInput()) {return false};

if (this._subject.isDead()) {return false};

if ($gameParty.isAllDead()) {return false};

if ($gameTroop.isAllDead()) {return false};

if (!this._subject.canUse($gameTemp._bchainData[1])) {return false};

if ($gameTemp._bchainData[1].scope === 1 ||

$gameTemp._bchainData[1].scope === 7 ||

$gameTemp._bchainData[1].scope === 9) {

if (!$gameTemp._bchainData[8]) {return false};

if ($gameTemp._bchainData[8].isDead())

{cancelme = 1; return true;};

}

return true;

};



//==============================

// * execute Chain Action

//==============================

BattleManager.executeChainAction = function() {

if ($gameTemp._bchainData[10]) {

if (cancelme === 0) {

this._subject.forceAction($gameTemp._bchainData[1].id, -2);

$gameTemp.clearBchain();

BattleManager.processTurn();}

else{

this._subject.forceAction ($dataSkills[30].id, -2);

$gameTemp.clearBchain();

BattleManager.processTurn();};

} else {

this._subject.forceAction ($dataSkills[30].id, -2);

$gameTemp.clearBchain();

BattleManager.processTurn(); };

};
it then still asks Player to input Chaincommand but after that it will perform the default skill (30)
My skill 30 actually is an empty skill which only make player return to it Home Position (Yanfly Battle System)
without this skill to be played automatically, if Player Miss/ or if enemy is Dead in middle of a Chaincombo,
the Actor will just stuck standing in front of enemy without moving back unless the new Turn come.

So the only problem remaining now is that to not ask player to input Chaincommand (because that skill will be play automatically and it doesn't do damage anyway)

I assume this happen because since condition set = True, Chaincommand Input will be activated anyway before it check to see what skill to play. But then i can't think of any solution for it @.@
 
Last edited:

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
And wouldn't it just be better to use Yanfly's spritereturnhome function instead?
Code:
//==============================
// * End Action
//==============================
var _mog_bchain_bmngr_endAction = BattleManager.endAction;
BattleManager.endAction = function() {
    if (BattleManager.canUseChainAction()) {
        $gameTemp._bchainData[0] = true;
        $gameTemp._bchainTemp = true;
        if ($gameTemp._bchainData[9]) {this.executeChainAction()};
        return;
      };
      this._subject.spriteReturnHome ();
     _mog_bchain_bmngr_endAction.call(this);
     $gameTemp.clearBchain();
     $gameTemp._bchainTemp = false;
    
};
 

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
Thank @Poryg . It's perfect! Thank you so much, i feel much more relieved now :) many thanks
 

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
sorry @Poryg but i have something else i want to ask
i found this section in Chaincommand plugin:
//==============================

// * Check Chain Action

//==============================

BattleManager.checkChainAction = function() {

var item = this._subject.currentAction().item();

var item_notes = item.note.split(/[\r\n]+/);

item_notes.forEach(function(note) {

var note_data = note.split(': ')

if (note_data[0].toLowerCase() == "chain action"){

var par = note_data[1].split(':');

var action = $dataSkills[Number(par[0])];

var times = Math.min(Math.max(Number(par[1]),1),999);

var duration = Math.min(Math.max(Number(par[2]),10),999);

if (action) {

$gameTemp._bchainData[1] = action;

$gameTemp._bchainData[6] = times;

$gameTemp._bchainData[7] = duration;

};

};

},this);

};
So it doesn't allow dev to use formula in the plugin's note tag but only number
ex: Chain Action: 107:5:5*10 >>> won't work
I want to ask how to use formula there OR, otherwise how to load the user parameter in the plugin
ex: var duration = user.luk * 10
Thank you
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
eval (par[2]) instead of par[2] should work. eval is a js command used to evaluate any chunk of code it receives.
The reason why par[2] doesn't work is because in this case (just like in any case of notetags) "5*10" is a string, not an operation. This is btw. why you see Number(......) - to convert the string to a number.
 

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
hi @Poryg , i insert eval into scripts like this: Math.min(Math.max(Number(eval(par[2])),10),999);
it now works with cases like "5*10" but when i try user.luk it got error"user is undefined" :?
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
Of course user is undefined, because user is defined only to states, skills and items usage. BattleManager uses subject (or this._subject to be concrete) and targets (or this._targets, which is an array).
 

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
thanks @Poryg but then, is there anyway for me to pass user parameters into it?
like: var bparam = user.luk; somewhere inside the plugin scripts
then refer to it like this:
Math.min(Math.max(Number(eval(par[2])),10),999) * bparam;
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
Just use this._subject.luk instead of user.luk, since BattleManager._subject and user are technically two same things, just in two different areas.
 

Isabella Ava

Veteran
Veteran
Joined
Sep 13, 2016
Messages
635
Reaction score
756
First Language
English
Oh, it worked! Thank you very much @Poryg , can you tell me more about what you said above
and targets (or this._targets, which is an array).
Does that mean if i want to refer to target's luk instead of user, i will use: this._targets.luk ?
but about it's an array, what is it mean?
Sorry i just want to understand it a little more
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,637
First Language
Czech
Primarily Uses
RMMV
Array is basic javascript and I won't be teaching you basic javascript, for that there are other sites. My favorite one is sololearn.com. If you want to check it out, feel free. It's free, not too hard and some javascript knowledge would help you.
What the game does is: It takes all applicable targets and puts them in an array and then executes the action on enemies one by one (although it works differently in your case, because you're using Yanfly's battle engine core). So if you wanted to pick a target from an array, it would be this._targets[x].luk. However, in this particular case you won't be able to use targets' luck or anything, because targets are set after checkChainAction is triggered.
You can only influence the formula when the targets are already defined, which, in this case, is invokeAction. And there you won't use this._targets[0].luk, but you'll use target.luk instead, because there the target is explicitly defined as target.
Code:
var _mog_bchain_bmngr_invokeAction = BattleManager.invokeAction;
BattleManager.invokeAction = function(subject, target) {
    Math.round ($gameTemp._bchainData[6] -= ($gameTemp._bchainData[6] * (1/target.luk))
    if ($gameTemp._bchainData[1]) {BattleManager.setBchainPosition(subject, target)};
    _mog_bchain_bmngr_invokeAction.call(this,subject, target);   
};
This would decrease the number of times the function is called by 1/target.luk.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

People1.png & SF_People1.png added!!!!

Adventurer:
"Why your body looks like a bird?"

Stranger:
"Because I'm harpy"

Adventurer:
"Clap along if you feel like a room without a roof"

*Both dancing to Pharrell Williams song*
Stream will be live shortly with a make-up session of the Interactive Text Adventure! Feel free to drop by!
Pootscooter wrote on Pharonix's profile.
Hey @Pharonix, just wondering what you're up to lately and if you've had an opportunity to check out the LTBS thread in the past few days...(a couple of us could really use your expertise). Hope you are well and Happy Thanksgiving!

Forum statistics

Threads
105,506
Messages
1,014,263
Members
137,173
Latest member
zoetsoi
Top