RMMV Does Yanfly's Battle A.I. Core consider target rate?

coucassi

Veteran
Veteran
Joined
Sep 23, 2019
Messages
188
Reaction score
289
First Language
German
Primarily Uses
RMMV
Hi!
This time it's just a quick question:
Yanfly's Battle A.I. Core lets you set a lot of condition to make your enemies do what you want, however, it also supports some kind of intentional randomness. I'd the enemies who use more random attacks to go more often after the actors with higher target rate, just as in the default system.
Does anybody know if this Plugin works like this? Or is it just completely random, if I don't set a specific target?
 

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,979
Reaction score
2,303
First Language
EN
Primarily Uses
RMMZ
I had a look at the code of YEP_BattleAICore and it looks like it uses this formula for random targets:
JavaScript:
group[Math.floor(Math.random() * group.length)]
That makes all targets equally likely to be chosen, i.e. it ignores Target Rate.

I might have missed something, though. :kaoswt:
 

coucassi

Veteran
Veteran
Joined
Sep 23, 2019
Messages
188
Reaction score
289
First Language
German
Primarily Uses
RMMV
Thanks :)
I suppose it's not that easy as just changing a tiny bit of code to nake the target rate matter again, right? x.x

Maybe I'll use passive states on item/equipment that would rise the target rate instead, to include those in the AI Conditions...

EDIT: Okay, I changed this part:

AIManager.setRandomTarget = function(group) { var target = group[Math.floor(Math.random() * group.length)]; this.action().setTarget(target.index()) };

to

AIManager.setRandomTarget = function(group) { var maintarget = group[Math.floor(Math.random() * group.length)]; for (var i = 0; i < group.length; ++i) { var target = group[i]; if (target.tgr > maintarget.tgr) maintarget = target; } this.action().setTarget(maintarget.index()) };

and it seems to work: If there is no target set, the enemy is always attacking the one with the highest target rate. I'd still like to add a bit of randomness, so that it's just more likely to have them attack the actor with the highest target rate, just as it would be by default. I suppose I need to use a random number again, but I'm not sure how to include that the right way. @caethyril Could you help me out again? x.x (sorry to tag you, but I', not sure, if edits are displayed even in watched threads. Of course I'd be happy for anyone else to help me out too ;) )
 
Last edited:

caethyril

^_^
Global Mod
Joined
Feb 21, 2018
Messages
2,979
Reaction score
2,303
First Language
EN
Primarily Uses
RMMZ
This is the default Game_Unit#randomTarget method from the core scripts (rpg_objects.js):
JavaScript:
Game_Unit.prototype.randomTarget = function() {
    var tgrRand = Math.random() * this.tgrSum();
    var target = null;
    this.aliveMembers().forEach(function(member) {
        tgrRand -= member.tgr;
        if (tgrRand <= 0 && !target) {
            target = member;
        }
    });
    return target;
};
I.e. pick a random number from 0 to the unit's total TGR value and determine the target by subtracting each member's TGR until the number hits 0 (or less). I find it intuitive to think of this sort of thing in terms of a number line split into partitions. :kaohi:

Note that group as used in Yanfly's plugin is not an instance of Game_Unit: it is simply an array of potential targets.

Also, just to mention it: for testing, I recommend using a troop of two targets, one with a TGR value of 0% and the other with TGR more than 0%. Since there's randomness, remember to test multiple times, too!

Also, in v1.15 of YEP_BattleAICore it looks like there are 18 instances of the formula I mentioned. In that case, for consistency I suggest you replace all of them with the same thing. :kaophew:

sorry to tag you, but I', not sure, if edits are displayed even in watched threads.
I didn't get a notification for the @. I don't think any post edits produce notifications, actually...that might be a forum bug? :kaoswt2:
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
2,814
Reaction score
1,647
First Language
English
Primarily Uses
RMMV
So, to change the existing
AIManager.setRandomTarget = function(group)
And have the desired functionality from
Game_Unit.prototype.randomTarget = function()
I suggest:
Code:
AIManager.setRandomTarget = function(group)
{
    var tgrRand = Math.random() * group.reduce((acc, val) => acc + val.tgr);
    var target = null;
    group.forEach(function(member)
    {
        tgrRand-=member.tgr;
        if (tgrRand<=0 && !target)
            target=member;
    });
    this.action().setTarget(target.index())
};

That should preserve the randomness from the original code while using the custom target groups in Yanfly's plugins. As caethyril said, you'll want to find anyplace that does the same thing and paste in something similar.
 

coucassi

Veteran
Veteran
Joined
Sep 23, 2019
Messages
188
Reaction score
289
First Language
German
Primarily Uses
RMMV
Thanks!
As far as I can see, the other instances of the formular are for the other non-random target selections. Here I would like to keep full control over who's being targeted, without randomness or target rate playing a role. Also using your code @ATT_Turan I get an error 'cannot get proberty index of null' when starting the battle. I did just copy and paste though, so maybe I missed something to do?

Before reading your answers I had a very simple:
if (target.tgr * Math.random() > maintarget.tgr * Math.random() ) maintarget = target;
just to try and create some randomness, which seemed to work, but since I've got a very limited knowledge I'd rather go with your suggestions.
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
2,814
Reaction score
1,647
First Language
English
Primarily Uses
RMMV
Also using your code I get an error 'cannot get proberty index of null' when starting the battle.
That's odd, the engine shouldn't be gathering a targeting group when starting the battle, it should only happen when an action is selected to actually target things. The only thing I added was the reduce function, which I thought I used correctly but perhaps I didn't...or perhaps the JS version that MV uses doesn't support it.

Trying replacing the first line with these:
Code:
    var tgrRand=0;

    for (var i=0; i<group.length; i++)
        tgrRand+=group[i].tgr;

    tgrRand*=Math.random();

Maybe @caethyril or @Trihan or someone can offer advice vis a vis reduce.
 

coucassi

Veteran
Veteran
Joined
Sep 23, 2019
Messages
188
Reaction score
289
First Language
German
Primarily Uses
RMMV
Trying replacing the first line with these:
Code:
var tgrRand=0;

for (var i=0; i<group.length; i++)
tgrRand+=group[i].tgr;

tgrRand*=Math.random();
That worked :)
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
3,932
Reaction score
3,161
First Language
English
Primarily Uses
RMMZ
That's odd, the engine shouldn't be gathering a targeting group when starting the battle, it should only happen when an action is selected to actually target things. The only thing I added was the reduce function, which I thought I used correctly but perhaps I didn't...or perhaps the JS version that MV uses doesn't support it.

Trying replacing the first line with these:
Code:
    var tgrRand=0;

    for (var i=0; i<group.length; i++)
        tgrRand+=group[i].tgr;

    tgrRand*=Math.random();

Maybe @caethyril or @Trihan or someone can offer advice vis a vis reduce.
Your issue is that you didn't specify a starting value.

group.reduce((acc, val) => acc + val.tgr, 0)
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
2,814
Reaction score
1,647
First Language
English
Primarily Uses
RMMV
Your issue is that you didn't specify a starting value.

group.reduce((acc, val) => acc + val.tgr, 0)
Well that was a stupid simple fix. Thanks!
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
3,932
Reaction score
3,161
First Language
English
Primarily Uses
RMMZ
Well that was a stupid simple fix. Thanks!
Yeah, it's super easy to miss when you're doing a reduce. If you don't provide an initial value, it uses the first value of the array. So you ended up trying to add the first group member's TGR to the group member object itself, to which the engine went "Uhhhhh no."
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
2,814
Reaction score
1,647
First Language
English
Primarily Uses
RMMV
If you don't provide an initial value, it uses the first value of the array.
See, that's why I never picked up on it - all of the examples I came across just dealt with arrays of numbers, so it was never explicit to me that it would default to the first member in the array (which obviously doesn't work here).
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
3,932
Reaction score
3,161
First Language
English
Primarily Uses
RMMZ
Well every day's a schoolday, right? :D
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
2,814
Reaction score
1,647
First Language
English
Primarily Uses
RMMV
Until you die!
 

coucassi

Veteran
Veteran
Joined
Sep 23, 2019
Messages
188
Reaction score
289
First Language
German
Primarily Uses
RMMV
Some day I'll find the time to really study js and then I'll come back to all those threads and be super proud of myself, when I am finally able to understand what people are talking about : )
 

Latest Threads

Latest Posts

Latest Profile Posts

My new 49" monitor has been dispatched from the warehouse. Will it arrive tomorrow? The day after? I love that we can track packages now, even if it does only tell me when it's left that end and when it's arrived at the local centre. As long as it doesn't end up in Melbourne again, which has happened before ...
My friend's doing a surprise stream of my game Origin Hunt on Twitch here ! Feel free to stop by :yhappy:
Me, designing it a long time ago: Having an optional boss fight as a random chance to trigger when you fish in a certain spot with a certain type of bait is fun! Cool idea!
Me, trying to playtest everything again: oh god just let me see the boss, my bag is so full of fish!
both love and pain have no boundaries

Forum statistics

Threads
117,222
Messages
1,105,621
Members
153,368
Latest member
universalwonder
Top