Files
2019-11-05 20:14:51 +01:00

319 lines
12 KiB
JavaScript

//=============================================================================
// Yanfly Engine Plugins - Battle AI Core Extension - Actor Auto Battle AI
// YEP_X_ActorAutoBattleAI.js
//=============================================================================
var Imported = Imported || {};
Imported.YEP_X_ActorAutoBattleAI = true;
var Yanfly = Yanfly || {};
Yanfly.AABAI = Yanfly.AABAI || {};
Yanfly.AABAI.version = 1.01;
//=============================================================================
/*:
* @plugindesc v1.01 (Req YEP_BattleAICore) Give auto battle actors the same
* type of A.I. that you can assign using the Battle AI Core's notetags.
* @author Yanfly Engine Plugins
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* This plugin requires YEP_BattleAICore. Make sure this plugin is located
* under YEP_BattleAICore in the plugin list.
*
* By default, if an actor has the auto battle trait, it will cycle through
* each one of its learned skills (whether or not it has access to the skill
* type doesn't matter) and selects the hardest hitting skill of them all. This
* setup may work for some auto-battlers but not all of them. What this plugin
* does is it incorporates the A.I. Priority system from the YEP Library's
* Battle A.I. Core for actor auto-battlers.
*
* If you don't have YEP_BattleAICore yet, please download it from here:
* http://yanfly.moe/2015/10/19/yep-16-battle-a-i-core/
*
* ============================================================================
* Plugin Parameters
* ============================================================================
*
* Default AI Level:
* - See 'Actor AI Level' in the Notetags section below.
*
* Bypass Requirement:
* - This is a list of the skills that bypass that requirement to have learned
* the skill in order to use it. This is namely for skills like 'Attack' and/or
* 'Guard' that aren't normally learned by actors, but are available to them
* through the command window.
*
* Curate Skill List:
* - Skills used for Auto Battle can only be skills accessible through
* available skill types. This is a selectable option because sometimes, skills
* that are learned by actors can be used through auto battle despite not
* having access to that skill type. An example of this would be an actor that
* has learned skills in the Knight class, but upon switching to the Mage class
* the actor loses the Knight skill type. Yet, despite that, auto battle would
* let the Mage class use skills from the Knight skill type if it's a part of
* the setup. Turning this on to curate the skill list will remove the ability
* use skills outside of available skill types.
*
* Undecided AI:
* - If no skill is determined through the A.I. Priority list, the actor will
* use the default Auto Battle AI to determine which skill to use. Otherwise,
* the actor perform only a basic attack if the setting is false.
*
* ============================================================================
* Notetags
* ============================================================================
*
* The notetags to setup the auto battle A.I. will go into the class noteboxes.
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Actor AI Level
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Actor AI levels do not determine how smart they are. Instead, they determine
* how strictly they will follow the <AI Priority> lists. An AI Level of 80
* means it has an 80% chance of following the prioritized action on the AI
* Priority list before moving onto the next one where there will be another
* 80% chance and so on. If the AI level is lower, the chance is lower, making
* the AI to be more random.
*
* Class Notetag:
*
* <AI Level: x>
* Sets the actor's AI level to x. The lower x, the more random the actor.
* The higher for x, the more strict the actor is about following the AI
* Priority list found in its notebox, too.
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Actor AI Priority
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* If a class has an AI Priority list, the actor will go down that list from
* top to bottom (giving the actions at the top more priority than the ones at
* the bottom) looking for any actions whose conditions are fulfilled. If that
* condition is fulfilled, then that action will be the action the actor will
* partake in.
*
* To set up a Priority List for the actor, you must place inside the class's
* notebox notetags that match the following format:
*
* <AI Priority> <AI Priority>
* condition: SKILL x, target or condition: skill name, target
* condition: SKILL x, target condition: skill name, target
* </AI Priority> </AI Priority>
*
* Any number of conditions and skills can be placed in between the two
* <AI Priority> tags. You can choose to use skill ID's or the skill names.
* However, if you use the skill names, keep in mind that it is not case
* sensitive and if any skills in your database have matching names, the skill
* with the larger skill ID will be the action used.
*
* ============================================================================
* Conditions
* ============================================================================
*
* The conditions to be used for the <AI Priority> notetag are the same as the
* ones from the YEP_BattleAICore plugin. Please refer to the YEP_BattleAICore
* help file for which conditions can be used with the A.I. setups.
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.01:
* - Fixed a bug that made curated skill types not work.
*
* Version 1.00:
* - Finished Plugin!
*
* ============================================================================
* End of Helpfile
* ============================================================================
*
* @param Default AI Level
* @type number
* @min 0
* @max 100
* @desc This is the default AI level of all actors.
* Level 0: Very Random Level 100: Very Strict
* @default 100
*
* @param Bypass Requirement
* @type skill[]
* @desc This is a list of the skills that bypass that requirement to
* have learned the skill in order to use it.
* @default ["1","2","3","4","5","6","7"]
*
* @param Curate Skill List
* @type boolean
* @on YES
* @off NO
* @desc Skills used for Auto Battle can only be skills accessible
* through available skill types. YES - true NO - false
* @default true
*
* @param Undecided AI
* @type boolean
* @on YES
* @off NO
* @desc If no skill is determined, use the default Auto Battle AI?
* Otherwise, perform only a basic attack.
* @default false
*
*/
//=============================================================================
if (Imported.YEP_BattleAICore) {
//=============================================================================
// Parameter Variables
//=============================================================================
Yanfly.Parameters = PluginManager.parameters('YEP_X_ActorAutoBattleAI');
Yanfly.Param = Yanfly.Param || {};
Yanfly.Param.AABAIDefaultLevel = Number(Yanfly.Parameters['Default AI Level']);
Yanfly.Param.AABAIBypassRequirementSkills =
JSON.parse(Yanfly.Parameters['Bypass Requirement']);
Yanfly.Param.AABAICurate = eval(String(Yanfly.Parameters['Curate Skill List']));
Yanfly.Param.AABAIUndecided = eval(String(Yanfly.Parameters['Undecided AI']));
Yanfly.SetupParameters = function() {
var length = Yanfly.Param.AABAIBypassRequirementSkills.length;
for (var i = 0; i < length; ++i) {
Yanfly.Param.AABAIBypassRequirementSkills[i] =
Number(Yanfly.Param.AABAIBypassRequirementSkills[i]);
}
};
Yanfly.SetupParameters();
//=============================================================================
// DataManager
//=============================================================================
Yanfly.AABAI.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
if (!Yanfly.AABAI.DataManager_isDatabaseLoaded.call(this)) return false;
if (!Yanfly._loaded_YEP_X_ActorAutoBattleAI) {
this.processAABAINotetags1($dataClasses);
Yanfly._loaded_YEP_X_ActorAutoBattleAI = true;
}
return true;
};
DataManager.processAABAINotetags1 = function(group) {
var note1 = /<(?:AI PRIORITY)>/i;
var note2 = /<\/(?:AI PRIORITY)>/i;
var note3 = /<(?:AI CONSIDER TAUNT|ai considers taunts)>/i;
var note4 = /<(?:AI LEVEL):[ ](\d+)>/i;
for (var n = 1; n < group.length; n++) {
var obj = group[n];
var notedata = obj.note.split(/[\r\n]+/);
obj.aiPattern = [];
var aiPatternFlag = false;
obj.aiConsiderTaunt = false;
obj.aiLevel = Yanfly.Param.AABAIDefaultLevel * 0.01;
for (var i = 0; i < notedata.length; i++) {
var line = notedata[i];
if (line.match(note1)) {
aiPatternFlag = true;
} else if (line.match(note2)) {
aiPatternFlag = false;
} else if (aiPatternFlag) {
obj.aiPattern.push(line);
} else if (line.match(note3)) {
obj.aiConsiderTaunt = true;
} else if (line.match(note4)) {
obj.aiLevel = parseFloat(RegExp.$1 * 0.01);
}
}
}
};
//=============================================================================
// AIManager
//=============================================================================
Yanfly.AABAI.AIManager_hasSkill = AIManager.hasSkill;
AIManager.hasSkill = function(skillId) {
if (this.battler() && this.battler().isActor()) {
return this.checkActorHasSkillRequirement(skillId);
} else {
return Yanfly.AABAI.AIManager_hasSkill.call(this, skillId);
}
};
AIManager.checkActorHasSkillRequirement = function(skillId) {
var skill = $dataSkills[skillId];
if (!skill) return false;
if (Yanfly.Param.AABAIBypassRequirementSkills.contains(skillId)) return true;
if (Yanfly.Param.AABAICurate) {
var skillTypes = this.battler().addedSkillTypes();
if (skillTypes && !skillTypes.contains(skill.stypeId)) return false;
}
return Yanfly.AABAI.AIManager_hasSkill.call(this, skillId);
};
//=============================================================================
// Game_Actor
//=============================================================================
Yanfly.AABAI.Game_Actor_makeAutoBattleActions =
Game_Actor.prototype.makeAutoBattleActions;
Game_Actor.prototype.makeAutoBattleActions = function() {
if (this.isConfused()) {
this.makeConfusionActions();
} else if (this.currentClass().aiPattern.length > 0) {
this.setAIPattern();
this.setActionState('waiting');
} else {
Yanfly.AABAI.Game_Actor_makeAutoBattleActions.call(this);
}
};
Game_Actor.prototype.setAIPattern = function() {
Game_Battler.prototype.setAIPattern.call(this);
if (this.numActions() <= 0) return;
AIManager.setBattler(this);
for (var i = 0; i < this.currentClass().aiPattern.length; ++i) {
if (Math.random() > this.aiLevel()) continue;
var line = this.currentClass().aiPattern[i];
if (AIManager.isDecidedActionAI(line)) return;
}
if (Yanfly.Param.AABAIUndecided) {
Yanfly.AABAI.Game_Actor_makeAutoBattleActions.call(this);
} else {
for (var i = 0; i < this.numActions(); i++) {
this._actions[i].setAttack();
}
}
this.setActionState('waiting');
};
Game_Actor.prototype.aiLevel = function() {
return this.currentClass().aiLevel;
};
//=============================================================================
// Error Message
//=============================================================================
} else {
var text = '';
text += 'You are getting this error because you are trying to run ';
text += 'YEP_X_ActorAutoBattleAI without YEP_BattleAICore. Please visit ';
text += 'Yanfly.moe and install YEP_BattleAICore in your game project before ';
text += 'you can use this plugin.';
console.log(text);
require('nw.gui').Window.get().showDevTools();
}; // Imported.YEP_BattleAICore
//=============================================================================
// Error Message
//=============================================================================