/*:
 * @plugindesc (v1.09)宠物系统
 * @author 小c
 * @version 1.0.9
* @date4/18/2020
*
* @param Base Params
* @text ---- 基本数据信息 ----
*
* @param Catch Pet State
* @text 捕捉宠物添加状态
* @parent Base Params
* @type state
* @desc 捕捉成功时添加的状态
* 捕捉技能不需要设置【添加状态】内容
* @default 0
*
* @param Pet Added Code
* @text 添加宠物额外代码
* @parent Base Params
* @type note
* @desc 宠物添加时执行的额外代码，比如自动出战
* @default "//pet.addState(15);"
*
* @param Pet Exit Time
* @text 宠物死亡退场时间
* @parent Base Params
* @type number
* @min 0
* @desc 宠物退场死亡时的消失时间【帧】，0表示不消失。
* @default 60
*
* @param Pet Change Code
* @text 宠物替换额外代码
* @parent Base Params
* @type note
* @desc 宠物替换时执行的额外代码
* @default "//变量oldPet表示下场宠物，newPet表示新进场宠物\n//oldItem和newItem分别表示他们对应的召唤物品或技能"
*
* @param Pet Die Code
* @text 宠物死亡额外代码
* @parent Base Params
* @type note
* @desc 宠物死亡时执行的额外代码，比如直接退场
* @default "pet.rest();\npet.removeState(pet.deathStateId());"
*
* @param Battle Ended Code
* @text 战斗结束额外代码
* @parent Base Params
* @type note
* @desc 战斗结束时执行的额外代码，比如移除宠物
* @default "//此处this指向$gameParty"
*
* @param Pet Auto Battle
* @text 宠物自动战斗
* @parent Base Params
* @type boolean
* @on 自动战斗
* @off 手动操作
* @desc 宠物默认是否自动战斗，如果为false，是否自动战斗取决于宠物属性
* @default false
*
* @param Pet AI Level
* @text 宠物AI等级
* @parent Base Params
* @type number
* @min 0
* @max 100
* @desc 宠物AI等级，标准参考YEP_BattleAICore
* @default 80
*
* @param Default Pet Class
* @text 宠物默认职业
* @parent Base Params
* @type class
* @desc 宠物默认关联职业
* @default 0
*
* @param Pet Max Level
* @text 宠物最高等级
* @parent Base Params
* @type number
* @min 1
* @desc 默认宠物最高等级
* @default 99
*
* @param Max Pets Number
* @text 宠物最大数量
* @parent Base Params
* @type number
* @min 1
* @desc 队伍中宠物数量，包括不出战宠物，不包括仓库。
* @default 5
*
* @param Max Battle Pets Number
* @text 战斗宠物最大数量
* @parent Base Params
* @type number
* @min 1
* @desc 队伍中出战宠物数量。
* @default 5
*
* @param Defeat When Only Pets Alive
* @text 仅剩宠物存活时判定战斗失败
* @parent Base Params
* @type boolean
* @on 是
* @off 否
* @desc 队伍全灭仅剩宠物时是否认定为全灭【战斗失败】
* @default false
*
* @param Pet Sprite Position
* @text 召唤宠物坐标
* @parent Base Params
* @type note
* @desc 宠物的显示位置，master表示召唤者
* @default "x = master.x - 96 * index;\ny = master.y + 12 * index;"
*
* @param Info Params
* @text---- 消息数据信息 ----
*
* @param Catch Sucess Info
* @text 抓捕成功信息
* @parent Info Params
* @desc 抓捕宠物成功的提示信息
* @default 抓捕成功！开花~
*
* @param Catch Failure Info
* @text 抓捕失败信息
* @parent Info Params
* @desc 抓捕宠物失败的提示信息
* @default 哎呀，抓捕失败，害！
*
* @param Scene Params
* @text ---- 界面数据信息 ----
*
* @param Use This Scene
* @text 使用此界面
* @parent Scene Params
* @type boolean
* @on 使用
* @off 不使用
* @desc 是否使用默认UI
* @default true
*
* @param Change Window Data
* @text 宠物替换窗口属性
* @parent Scene Params
* @type struct<ChangeWindow>
* @desc 宠物替换选择窗口的属性，此参数必需，且与默认UI无关
* @default {"x":"Graphics.boxWidth / 2 - 150","y":"Graphics.boxHeight / 2 - 100","width":"300","height":"200","text":"要替换哪个宠物？"}
* 
* @param Pet Command Name
* @text 宠物菜单名称
* @parent Scene Params
* @desc 主菜单中宠物系统的菜单名称
* @default 宠物
*
* @param Help Window Text
* @text 帮助窗口显示文字
* @parent Scene Params
* @desc 显示在帮助窗口中的文字信息
* @default 宠物信息系统。
*
* @param Fight Help Text
* @text 出战提示文字
* @parent Scene Params
* @desc 宠物出战时的提示信息
* @default %1已出战！奥利给！
*
* @param Rest Help Text
* @text 休息提示文字
* @parent Scene Params
* @desc 宠物休息时的提示信息
* @default %1下场休息了，感谢他的贡献！
*
* @param Depository In Help Text
* @text 存仓库提示文字
* @parent Scene Params
* @desc 宠物存仓库时的提示信息
* @default %1已存入仓库，让我们欢送他！
*
* @param Depository Out Help Text
* @text 取仓库提示文字
* @parent Scene Params
* @desc 宠物存仓库时的提示信息
* @default %1已从仓库取出，让他和我们并肩作战！
*
* @param Release Help Text
* @text 放生提示文字
* @parent Scene Params
* @desc 宠物放生时的提示信息
* @default %1已放生，他自由了！
*
* @param Type Window Width
* @text 左侧窗口宽度
* @parent Scene Params
* @desc 宠物类型窗口宽度公式
* @default Graphics.boxWidth / 4
*
* @param Type Window Height Plus
* @text 宠物类型窗口高度修正值
* @parent Scene Params
* @type number
* @desc 宠物类型窗口高度调整值，默认为0表示高度为两行文字的高度
* @default 0
*
* @param Status Window Height
* @text 状态窗口高度
* @parent Scene Params
* @desc 宠物简单状态窗口高度公式，this指向scene
* @default this._typeWindow.height * 2
*
* @param Command Window Height Plus
* @text 命令窗口高度修正值
* @parent Scene Params
* @type number
* @desc 命令窗口高度修正值，默认为0吧=表示高度为一行文字的高度，此窗口变高会导致信息窗口高度降低
* @default 0
*
* @param Pet List Name
* @text 宠物类型指令名称
* @parent Scene Params
* @desc 宠物列表指令的显示名称
* @default 宠物
*
* @param Pet Depository Name
* @text 宠物仓库指令名称
* @parent Scene Params
* @desc 宠物仓库指令的显示名称
* @default 仓库
*
* @param Show Pet Level
* @text 显示宠物等级
* @parent Scene Params
* @type boolean
* @on 显示
* @off 不显示
* @desc 宠物列表及替换列表显示宠物等级
* @default true
*
* @param Pet Level Name
* @text 宠物【等级】显示名称
* @parent Scene Params
* @desc 宠物列表中宠物等级的表述文字
* @default 等级 
*
* @param Pet List Battle Color
* @text 出战宠物文字颜色
* @parent Scene Params
* @type number
* @min 0
* @desc 宠物列表中处于出战状态的宠物的文字颜色
* @default 6
*
* @param Fight Rest Command Useable
* @text 出战、休息指令可用性
* @parent Scene Params
* @type boolean
* @on 可用
* @off 不可用
* @desc 命令窗口出战、休息的可用性，有些情况下不允许在战斗外改变战斗状态，请禁止
* @default true
*
* @param Pet Command Fight Name
* @text 宠物出战指令名称
* @parent Scene Params
* @desc 宠物出战指令名称
* @default 出战
*
* @param Pet Command Rest Name
* @text 宠物休息指令名称
* @parent Scene Params
* @desc 宠物休息指令名称
* @default 休息
*
* @param Pet Command In Depository Name
* @text 宠物存仓库指令名称
* @parent Scene Params
* @desc 宠物存仓库指令名称
* @default 存入仓库
*
* @param Pet Command Out Depository Name
* @text 宠物取仓库指令名称
* @parent Scene Params
* @desc 宠物取仓库指令名称
* @default 取出仓库
*
* @param Pet Command Release Name
* @text 宠物放生指令名称
* @parent Scene Params
* @desc 宠物放生指令名称
* @default 放生
*
* @param Release Confirm Info
* @text 放生确认信息
* @parent Scene Params
* @desc 宠物放生时提示框的提示信息
* @default 确认放生宠物%1吗？放生后无法找回！
*
* @param Release Confirm Yes Info
* @text 放生确认指令名称
* @parent Scene Params
* @desc 放生确认窗口中确认的指令名称
* @default 确定
*
* @param Release Confirm No Info
* @text 放生取消指令名称
* @parent Scene Params
* @desc 放生确认窗口中取消的指令名称
* @default 取消
*
* @param Release Confirm X Offset
* @text 放生确认窗口X偏移量
* @parent Scene Params
* @type number
* @desc 此偏移量越大。窗口右移越大
* @default -100
*
* @param Release Confirm Y Offset
* @text 放生确认窗口Y偏移量
* @parent Scene Params
* @type number
* @desc 此偏移量越大。窗口右移越大
* @default 0
*
* @param Detail Item Width
* @text 信息窗口项目密度
* @parent Scene Params
* @type number
* @desc 信息窗口显示项目的密度，数据越大项目越紧密
* @default 24
* 
 * @help
 * 宠物系统，以敌人为标准构建队友。
 * 若使用YEP_BattleAICore，请将此插件放在它的下面，宠物AI才会正常运行。
 *
 * 本插件预留的代码接口如下：
 * 宠物召唤入场 宠物死亡退场 宠物替换 战斗结束
 * 前两者有敌人标签可设置新代码，当没有标签时以插件参数为准
 * 后两者仅可通过插件参数修改。
 *
 * 敌人标签
 * 职业
 * <Pet Class: x> 宠物关联职业
 * 没有此标签，关联职业以插件参数为准
 * 关联职业影响宠物附属属性，装备槽等。
 * <Pet Class Affect Param> 宠物属性由职业决定
 * 默认宠物基础属性与职业无关
 *
 * 捕捉
 * <Cannot Be Caught> 此敌人禁止捕捉
 *
 * 图片
 * <Pet Character: name, index>宠物的角色图
 * <Pet Face: name, index> 宠物脸图
 * <Pet Battler: name> 角色战斗图
 *
 * 等级 装备
 * <Pet Init Level: x> 宠物初始等级为x
 * <Pet Max Level: x> 最大等级为x
 * <Pet Init Equips: x, x, x>宠物初始装备组，其按装备槽顺序配置
 * <Pet Init Equips: 1, 1, 2, 3, 4>
 * 表示装备为：武器1 防具1 防具2 防具3 防具4
 * 0表示没有装备
 *
 * 基础属性
 * <Custom Pet Params>
 * mhp = base.mhp + 10 * level;
 * mmp = base.atk;
 * </Custom Pet Params>
 * 自定义基础属性，base对象储存了在敌人数据库的数据
 * level表示当前宠物等级
 *
 * 召唤宠物坐标
 * <Pet Sprite Position>
 * x = master.x - 80 * index;
 * y = master.y + 12 * index;
 * </Pet Sprite Position>
 * 其中 index 表示当前宠物在主人宠物队列的位置。
 * 即【此宠物是主人召唤的第index个宠物】
 * 插件参数中也可以使用此index
 *
 * <Default Pet Position> 采用系统默认坐标
 *
 * 自动战斗
 * <Pet Auto Battle> 宠物自动战斗
 * 没有此标签以插件参数为准，若最终值为false，是否自动战斗取决于角色属
 * 性
 * 
 * <Pet AI Level: x>宠物AI等级
 * <Pet AI Priority>
 * ai list
 * </Pet AI Priority>
 * 宠物AI配置，AI序列参见YEP_BattleAICore
 * 此标签需YEP_BattleAICore支持
 *
 * 宠物入场
 * <Pet Added Code>
 * //JavaScript code
 * $gameParty.gainGold(1000);
 * </Pet Added Code>
 * 宠物入场时执行额外代码
 * 包括物品/技能召唤以及插件指令入场等
 * 没有标签将执行插件参数
 *
 * 宠物死亡
 * <Pet Exit Time: x> 宠物退场消失时间，单位【帧】
 * 指定时间后宠物消失，执行死亡代码
 * 若时间为0，则不消失，直接执行死亡代码
 *
 * <Pet Die Code>
 * //JavaScript code
 * pet.rest();
 * </Pet Die Code>
 * 宠物死亡时的响应代码
 *
 * 技能 物品标签
 * <Add Pet Enemy ID: x> 指定技能物品召唤的宠物对应的敌人id
 *
 * <Catch Pet Chance: x> (0 < x < 1)
 * 技能捕捉成功率为x
 * <Catch Pet Chance Eval>
 * chance = (user.hpRate() - target.hpRate() + 1) / 2;
 * </Catch Pet Chance Eval>
 * 技能捕捉成功率动态运算
 * 如果没有这两个标签中的任何一个，技能物品不属于捕捉行动
 *
 * 角色变量修正
 * YEP角色变量对角色的配置同时对宠物生效
 * 角色变量插件在Actor上的标签若配置在Enemy中对宠物有效
 * 宠物角色变量的默认值以YEP角色变量插件的参数为准
 *
 * 插件指令
 * ShowPetScene 显示宠物界面【Scene_Pet】
 * 如果不使用默认界面，请自行构建此Scene，否则调用此插件指令会出错
 * AddPet enemyId [masterId] [autoFight] 召唤指定敌人的宠物
 * enemyId 必需，指定宠物的基础敌人编号
 * masterId 可选，此宠物的召唤者，未指定时为我方第一人
 * autoFight 可选，召唤完成即进入战斗队列
 * 例：AddPet 2 2 autoFight
 *
 * DefeatWhenPetsAlive true / false
 * 只剩宠物存活时是否认定战斗失败的设置修改
 * 例：DefeatWhenPetsAlive true
 *
 * PetBeCaught [index] can/cannot
 * 强制修改敌人索引index的敌人的可抓捕状态
 * PetBeCaught 1 cannot
 *
 * JS函数
 * pet = $gameParty.addPet(enemyId, masterId)
 * 添加以指定敌人为基准的宠物，返回值为宠物id
 * $gameActors.actor(petId) 可以得到这个宠物
 * 若宠物已满，此函数会抛出错误
 *
 * $gameParty.battleMembersNotPets() 得到除了宠物之外的战斗者
 * $gameParty.pets() 得到所有宠物对象，包括未出战宠物，不包括仓库
 * $gameParty.battlePets() 得到所有出战宠物对象
 * $gameParty.aliveBattleActors() 得到所有存活的非宠物角色
 * 
 * $gameParty.clearPets() 清除【放生】所有宠物
 * $gameParty.clearAllPets() 清除【放生】所有宠物【包括仓库】
 *
 * pet.baseItem() 返回宠物对象的召唤物品/技能/装备
 *
 * 更新日志
 * v1.00
 * 插件完成
 *
 * v1.01
 * 新增宠物自动战斗AI配置，需YEP_BattleAICore支持
 *
 * v1.02
 * 追加宠物出场、死亡时的自定义代码
 * 使用者可禁止宠物界面中【出战】【休息】指令
 *
 * v1.03
 * 修复本插件与YEP动作序列冲突的问题
 * 引入仅剩宠物时判定战斗失败的设置
 *
 * v1.04
 * 增加抓捕宠物的功能
 *
 * v1.05
 * 修复横版战斗时角色站位错误的问题
 * 添加召唤宠物替换已有宠物的功能
 * 注意：如果宠物数已满，再次召唤宠物时，被替换的宠物将被放生，永久消失
 *
 * v1.06
 * 修复选择窗口响应取消异常的问题
 * 宠物满时替换宠物，旧宠物将存入仓库而不是放生
 * 增加宠物替换时的响应接口
 *
 * v1.07
 * 添加显示宠物界面的插件指令
 *
 * v1.08
 * 解决与YEP角色变量插件的冲突问题
 * 添加类型窗口和命令窗口高度的调整参数
 * 解决与本人插件CP_UseEquip的兼容性问题
 *
 * v1.09
 * 仓库中的宠物被修改为禁止放生
 */
/*~struct~ChangeWindow:
 * @param x
 * @text 窗口x坐标
 * @default Graphics.boxWidth / 2 - 150
 * @parent Object Selectors
 *
 * @param y
 * @text 窗口y坐标
 * @default Graphics.boxHeight / 2 - 100
 * @parent Object Selectors
 *
 * @param width
 * @text 窗口宽度
 * @default 300
 * @parent Object Selectors
 *
 * @param height
 * @text 窗口高度
 * @default 200
 * @parent Object Selectors
 *
 * @param text
 * @text 窗口提示信息
 * @desc 选择替换宠物时的提示信息
 * @default 要替换哪个宠物？
 *
  */

var Imported = Imported || {};
Imported.CP_PetCore = true;

var params = PluginManager.parameters("CP_PetCore");

var CP = CP || {};
CP.PetManager = CP.PetManager || {};

CP.PetManager._catchAction = null;

CP.PetManager.CATCH_PET_STATE = Number(params["Catch Pet State"]) || 0;
CP.PetManager.PET_EXIT_TIME = Number(params["Pet Exit Time"]) || 0;
CP.PetManager.PET_ADDED_CODE = JSON.parse(params["Pet Added Code"]);
CP.PetManager.PET_CHANGE_CODE = JSON.parse(params["Pet Change Code"]);
CP.PetManager.PET_DIE_CODE = JSON.parse(params["Pet Die Code"]);
CP.PetManager.BATTLE_ENDED_CODE = JSON.parse(params["Battle Ended Code"]);
CP.PetManager.PET_AI_LEVEL = Number(params["Pet AI Level"]) || 0;
CP.PetManager.DEFAULT_PET_CLASS = Number(params["Default Pet Class"]) || 0;
CP.PetManager.MAX_PETS_NUMBER = Number(params["Max Pets Number"]) || 1;
CP.PetManager.MAX_BATTLE_PETS_NUMBER = Number(params["Max Battle Pets Number"]) || 1;
if(CP.PetManager.MAX_BATTLE_PETS_NUMBER > CP.PetManager.MAX_PETS_NUMBER)
	CP.PetManager.MAX_BATTLE_PETS_NUMBER = CP.PetManager.MAX_PETS_NUMBER;
CP.PetManager.MAX_PET_LEVEL = Number(params["Pet Max Level"]) || 1;
CP.PetManager.PET_AUTO_BATTLE = eval(params["Pet Auto Battle"]) || false;
CP.PetManager.DEFEAT_WHEN_ONLY_PETS_ALIVE = eval(params["Defeat When Only Pets Alive"]) || false;

CP.PetManager.PET_SPRITE_POSITION = JSON.parse(params["Pet Sprite Position"]);

CP.PetManager.CATCH_SUCCESS_INFO = params["Catch Sucess Info"];
CP.PetManager.CATCH_FAILURE_INFO = params["Catch Failure Info"];

CP.PetManager.USE_SCENE = eval(params["Use This Scene"]);
CP.PetManager.SHOW_PET_LEVEL = eval(params["Show Pet Level"]) || false;
CP.PetManager.FIGHT_REST_COMMAND_USABLE = eval(params["Fight Rest Command Useable"]) || false;
CP.PetManager.HELP_WINDOW_TEXT = params["Help Window Text"];
CP.PetManager.PET_COMMAND_NAME = params["Pet Command Name"];
CP.PetManager.TYPE_WINDOW_WIDTH = params["Type Window Width"];
CP.PetManager.TYPE_WINDOW_HEIGHT_PLUS = Number(params["Type Window Height Plus"]) || 0;
CP.PetManager.STATUS_WINDOW_HEIGHT = params["Status Window Height"];
CP.PetManager.COMMAND_WINDOW_HEIGHT_PLUS = Number(params["Command Window Height Plus"]) || 0;

CP.PetManager.FIGHT_HELP_TEXT = params["Fight Help Text"];
CP.PetManager.REST_HELP_TEXT = params["Rest Help Text"];
CP.PetManager.DEPOSITORY_IN_HELP_TEXT = params["Depository In Help Text"];
CP.PetManager.DEPOSITORY_OUT_HELP_TEXT = params["Depository Out Help Text"];
CP.PetManager.RELEASE_HELP_TEXT = params["Release Help Text"];

CP.PetManager.PET_LIST_NAMES = new Array(2);
CP.PetManager.PET_LIST_NAMES[0] = params["Pet List Name"];
CP.PetManager.PET_LIST_NAMES[1] = params["Pet Depository Name"];
CP.PetManager.PET_LEVEL_NAME = params["Pet Level Name"];
CP.PetManager.PET_LIST_BATTLE_COLOR = Number(params["Pet List Battle Color"]) || 0;

CP.PetManager.PET_COMMAND_FIGHT_NAME = params["Pet Command Fight Name"];
CP.PetManager.PET_COMMAND_REST_NAME = params["Pet Command Rest Name"];
CP.PetManager.PET_COMMAND_IN_DEPOSITORY_NAME = params["Pet Command In Depository Name"];
CP.PetManager.PET_COMMAND_OUT_DEPOSITORY_NAME = params["Pet Command Out Depository Name"];
CP.PetManager.PET_COMMAND_RELEASE_NAME = params["Pet Command Release Name"];
CP.PetManager.RELEASE_CONFIRM_INFO = params["Release Confirm Info"];
CP.PetManager.RELEASE_CONFIRM_X_OFFSET = Number(params["Release Confirm X Offset"]) || 0;
CP.PetManager.RELEASE_CONFIRM_Y_OFFSET = Number(params["Release Confirm Y Offset"]) || 0;

CP.PetManager.RELEASE_CONFIRM_COMMAND_INFOS = new Array(2);
CP.PetManager.RELEASE_CONFIRM_COMMAND_INFOS[0] = params["Release Confirm Yes Info"];
CP.PetManager.RELEASE_CONFIRM_COMMAND_INFOS[1] = params["Release Confirm No Info"];

CP.PetManager.DETAIL_ITEM_WIDTH = Number(params["Detail Item Width"]) || 0;

CP.PetManager.CHANGE_WINDOW_DATA = JSON.parse(params["Change Window Data"]);

CP.PetManager._loaded = false;
CP.PetManager.DATABASE_LOADED = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function(){
	if(!CP.PetManager.DATABASE_LOADED.call(this)) return false;

	CP.PetManager.loadPetAdd();
	CP.PetManager.loadPetHomePosition();
	CP.PetManager.loadPetEquips();
	CP.PetManager.loadPetLevelAndClass();
	CP.PetManager.loadPetImages();
	CP.PetManager.loadPetCustomParam();
	CP.PetManager.loadPetDie();
	if(Imported.YEP_BattleAICore)
		CP.PetManager.loadPetAI();

	CP.PetManager.loadItemSkillPetAdded($dataItems);
	CP.PetManager.loadItemSkillPetAdded($dataSkills);
	CP.PetManager.loadCatchPetChance($dataSkills);
	CP.PetManager.loadCatchPetChance($dataItems);

	if(Imported.YEP_X_ActorVariables && !CP.PetManager._loaded){
		DataManager.processAVarNotetags($dataEnemies);
		CP.PetManager._loaded = true;
	}

	return true;
};

CP.PetManager.loadPetHomePosition = function(){
	var reg = /<Pet Sprite Position>([\s\S]+)<\/Pet Sprite Position>/;
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		pet.defaultPetPosition = false;
		pet.homePosition = CP.PetManager.PET_SPRITE_POSITION;

		if(Imported.YEP_BattleEngineCore){
			pet.anchorX = Yanfly.Param.BECAnchorX;
			pet.anchorY = Yanfly.Param.BECAnchorY;
		}

		if(pet.meta["Default Pet Position"])
			pet.defaultPetPosition = true;

		if(reg.exec(pet.note)){
			pet.homePosition = RegExp.$1;
		}
	}
}

CP.PetManager.loadPetEquips = function(){
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		pet.equips = new Array($dataSystem.equipTypes.length - 1);
		var equips = pet.meta["Pet Init Equips"];
		if(equips)
			equips = equips.split(",");

		for(var j = 0; j < pet.equips.length; j++){
			if(equips && equips[j])
				pet.equips[j] = Number(equips[j]) || 0;
			else
				pet.equips[j] = 0;
		}
	}
};

CP.PetManager.loadPetLevelAndClass = function(){
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		pet.petClassId = CP.PetManager.DEFAULT_PET_CLASS;
		pet.classAffectParam = false;
		pet.initLevel = 1;
		pet.petMaxLevel = CP.PetManager.MAX_PET_LEVEL;
		pet.petAutoBattle = CP.PetManager.PET_AUTO_BATTLE;
		
		if(pet.meta["Pet Class"])
			pet.petClassId = Number(pet.meta["Pet Class"]) || 0;
		if(pet.petClassId > 0 && pet.meta["Pet Class Affect Param"])
			pet.classAffectParam = true;

		if(pet.meta["Pet Init Level"])
			pet.initLevel = Number(pet.meta["Pet Init Level"]) || 0;
		if(pet.meta["Pet Max Level"])
			pet.petMaxLevel = Number(pet.meta["Pet Max Level"]) || 0;
		if(pet.meta["Pet Auto Battle"])
			pet.petAutoBattle = true;
	}
};

CP.PetManager.loadPetCustomParam = function(){
	var reg = /<Custom Pet Params>([\s\S]*)<\/Custom Pet Params>/;
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];

		pet.customParamCode = null;

		if(reg.exec(pet.note))
			pet.customParamCode = RegExp.$1;
	}
};

CP.PetManager.loadPetImages = function(){
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		this.loadPetCharacter(pet);
		this.loadPetFace(pet);
		this.loadPetBattler(pet);
	}
};

CP.PetManager.loadPetCharacter = function(pet){
	pet.characterName = "";
	pet.characterIndex = 0;

	var reg = /<Pet Character: ([\S\s]+?), (\d+)>/;
	if(reg.exec(pet.note)){
		pet.characterName = RegExp.$1;
		pet.characterIndex = Number(RegExp.$2) || 0;
	}
};

CP.PetManager.loadPetFace = function(pet){
	pet.faceName = "";
	pet.faceIndex = 0;

	var reg = /<Pet Face: ([\S\s]+?), (\d+)>/;
	if(reg.exec(pet.note)){
		pet.faceName = RegExp.$1;
		pet.faceIndex = Number(RegExp.$2) || 0;
	}
};

CP.PetManager.loadPetBattler = function(pet){
	pet.petBattlerName = "";

	if(pet.meta["Pet Battler"])
		pet.petBattlerName = pet.meta["Pet Battler"].trim();
};

CP.PetManager.loadItemSkillPetAdded = function(array){
	for(var i = 1; i < array.length; i++){
		var item = array[i];
		item.petAddedInfo = null;

		if(item.meta["Add Pet Enemy ID"]){
			if(!item.petAddedInfo)
				item.petAddedInfo = {};
			item.petAddedInfo.enemyId = Number(item.meta["Add Pet Enemy ID"]) || 0;
			item.petAddedInfo.animationId = Number(item.meta["Add Pet Animation"]) || 0;
		}
	}
};

CP.PetManager.loadCatchPetChance = function(array){
	var reg = /<Catch Pet Chance Eval>([\S\s]+)<\/Catch Pet Chance Eval>/;
	for(var i = 1; i < array.length; i++){
		var item = array[i];
		item.catchPetChance = 0;
		item.catchPetChanceEval = null;

		if(item.meta["Catch Pet Chance"])
			item.catchPetChance = Number(item.meta["Catch Pet Chance"]) || 0;

		if(reg.exec(item.note))
			item.catchPetChanceEval = RegExp.$1;
	}
};

CP.PetManager.loadPetAdd = function(){
	var reg = /<Pet Added Code>([\s\S]+)<\/Pet Added Code>/;
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		pet.petAddedCode = CP.PetManager.PET_ADDED_CODE;
		pet.canBeCaught = true;

		if(reg.exec(pet.note))
			pet.petAddedCode = RegExp.$1;

		if(pet.meta["Cannot Be Caught"])
			pet.canBeCaught = false;
	}
};

CP.PetManager.loadPetDie = function(){
	var reg = /<Pet Die Code>([\s\S]+)<\/Pet Die Code>/;
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		pet.petDieCode = CP.PetManager.PET_DIE_CODE;
		pet.petExitTime = CP.PetManager.PET_EXIT_TIME;

		if(pet.meta["Pet Exit Time"])
			pet.petExitTime = Number(pet.meta["Pet Exit Time"]) || 0;

		if(reg.exec(pet.note))
			pet.petDieCode = RegExp.$1;
	}
};

CP.PetManager.loadPetAI = function(){
	var reg = /<Pet AI Priority>\n([\s\S]+)\n<\/Pet AI Priority>/;
	for(var i = 1; i < $dataEnemies.length; i++){
		var pet = $dataEnemies[i];
		pet.petAiPattern = pet.aiPattern;
		pet.petAiLevel = CP.PetManager.PET_AI_LEVEL;

		if(pet.meta["Pet AI Level"])
			pet.petAiLevel = Number(pet.meta["Pet AI Level"]) || 0;
		pet.petAiLevel *= 0.01;

		if(reg.exec(pet.note)){
			pet.petAiPattern = RegExp.$1.split("\n");
		}
	}
};

CP.PetManager.isCatchItem = function(item){
	if(!DataManager.isItem(item) && !DataManager.isSkill(item))
		return false;

	if(item.catchPetChance > 0 || item.catchPetChanceEval)
		return true;

	return false;
};

CP.PetManager.setCatchAction = function(action){
	this._catchAction = action;
};

CP.PetManager.catchAction = function(){
	return this._catchAction;
};

CP.PetManager.isAddPetItem = function(item){
	if(item && Imported.CP_UseEquip)
		item = CP.UseEquipManager.getRealUseItem(item);

	if(!DataManager.isItem(item) && !DataManager.isSkill(item))
		return false;

	if(item.petAddedInfo && item.petAddedInfo.enemyId > 0)
		return true;

	return false;
};

CP.PetManager.canUseAddPetItem = function(item){
	var petActionCount = BattleManager.petActionNum();
	if($gameParty.battlePets().length + petActionCount >= $gameParty.maxBattlePets()){
		if($gameParty.battlePets().length === $gameParty.maxBattlePets() && petActionCount > 1)
			return false;
		else if($gameParty.battlePets().length < $gameParty.maxBattlePets())
			return false;
	}

	return true;
};

//--------------------------------
// BattleManager
//---------------------------------
CP.PetManager.SETUP_BATTLE = BattleManager.setup;
BattleManager.setup = function(troopId, canEscape, canLose){
	CP.PetManager.SETUP_BATTLE.call(this, troopId, canEscape, canLose);

	$gameParty.battleMembersNotPets().forEach(function(actor){
		actor.orderPets();
	});
};

BattleManager.petActionNum = function(){
	var num = 0;

	$gameParty.battleMembers().forEach(function(actor){
		var action = actor.currentAction();
		if(action && action.isAddPetAction())
			num++;
	});

	return num;
};

if(!Imported.YEP_BattleEngineCore){

BattleManager.registerSprite = function(battler, sprite) {
  if (!this._registeredSprites) this._registeredSprites = {};
  if (battler.isActor()) var id = 100000 + battler.actorId();
  if (battler.isEnemy()) var id = 200000 + battler.index();
  this._registeredSprites[id] = sprite;
};

BattleManager.getSprite = function(battler) {
  if (!this._registeredSprites) this._registeredSprites = {};
  if (battler.isActor()) var id = 100000 + battler.actorId();
  if (battler.isEnemy()) var id = 200000 + battler.index();
  return this._registeredSprites[id];
};

//---------------------------------
//   Game_Battler
//--------------------------------
Game_Battler.prototype.setBattler = function(sprite){
	BattleManager.registerSprite(this, sprite);
};

Game_Battler.prototype.battler = function(){
	return BattleManager.getSprite(this);
};
}

//---------------------------------
//   Game_BattlerBase
//--------------------------------
Game_BattlerBase.prototype.isPet = function() {
    return false;
};

Game_BattlerBase.prototype.hasBeenCaught = function(){
	return false;
};

Game_BattlerBase.prototype.canBeCaught = function(){
	return false;
};

//捕捉状态
Game_BattlerBase.prototype.catchPetStateId = function(){
	return CP.PetManager.CATCH_PET_STATE;
};

//--------------------------------
// Game_Enemy
//---------------------------------
CP.PetManager.INIT_ENEMY = Game_Enemy.prototype.initialize;
Game_Enemy.prototype.initialize = function(enemyId, x, y) {
    CP.PetManager.INIT_ENEMY.call(this, enemyId, x, y);

    this.setHasBeenCaught(false);
    this.setCanBeCaught($dataEnemies[enemyId].canBeCaught);
};

Game_Enemy.prototype.setHasBeenCaught = function(caught){
	this._hasBeenCaught = caught;
};

Game_Enemy.prototype.hasBeenCaught = function(){
	return !!this._hasBeenCaught;
};

Game_Enemy.prototype.setCanBeCaught = function(caught){
	this._canBeCaught = caught;
};

Game_Enemy.prototype.canBeCaught = function(){
	return !!this._canBeCaught;
};

CP.PetManager.ADD_ENEMY_NEW_STATE = Game_Battler.prototype.addNewState;
CP.PetManager.REMOVE_ENEMY_STATE = Game_Battler.prototype.removeState;
CP.PetManager.IS_ENEMY_STATE_ADDABLE = Game_Battler.prototype.isStateAddable;
if(Imported.CP_SubdueEnemy){
	CP.PetManager.ADD_ENEMY_NEW_STATE = Game_Enemy.prototype.addNewState;
	CP.PetManager.REMOVE_ENEMY_STATE = Game_Enemy.prototype.removeState;
	CP.PetManager.IS_ENEMY_STATE_ADDABLE = Game_Enemy.prototype.isStateAddable;
}

Game_Enemy.prototype.isStateAddable = function(stateId){
	var result = CP.PetManager.IS_ENEMY_STATE_ADDABLE.call(this, stateId);

	if(stateId === this.catchPetStateId() && !this.canBeCaught())
		result = false;

	return true;
};

Game_Enemy.prototype.addNewState = function(stateId){
	if(stateId === this.catchPetStateId()){
		if(this.addCatchStateEffect()){
			CP.PetManager.ADD_ENEMY_NEW_STATE.call(this, stateId);
			this.die();
		}
	}else
		CP.PetManager.ADD_ENEMY_NEW_STATE.call(this, stateId);
};

Game_Enemy.prototype.addCatchStateEffect = function(){
	var petId = -1;
	var masterId = -1;
	var action = CP.PetManager.catchAction();

	if(action.subject().isActor())
		masterId = action.subject().actorId();

	if(masterId > 0)
		petId = $gameParty.addPet(this.enemyId(), masterId);
	if(petId > 0)
		this.setHasBeenCaught(true);

	return petId > 0;
};

Game_Enemy.prototype.removeState = function(stateId){
	if(stateId === this.deathStateId() && this.hasBeenCaught()) return;

	CP.PetManager.REMOVE_ENEMY_STATE.call(this, stateId);
};

Game_Enemy.prototype.isStateAddable = function(stateId) {
    var result = CP.PetManager.IS_ENEMY_STATE_ADDABLE.call(this, stateId);
    if(stateId === this.catchPetStateId() && !this.canBeCaught())
    	result = false;

    return result;
};

//--------------------------------
// Game_Actors
//---------------------------------
Game_Actors.prototype.isPetId = function(actorId){
	return actorId >= $dataActors.length;
};

Game_Actors.prototype.newPetId = function() {
    var id = $dataActors.length;
    while(!!this._data[id]) id++;
    return id;
};

CP.PetManager.ACTORS_ACTOR = Game_Actors.prototype.actor;
Game_Actors.prototype.actor = function(actorId) {
    if (this.isPetId(actorId)) return this._data[actorId];
    return CP.PetManager.ACTORS_ACTOR.call(this, actorId);
};

Game_Actors.prototype.addPet = function(enemyId) {
    var petId = this.newPetId();
    this._data[petId] = new Game_Pet(petId, enemyId);
    return petId;
};

Game_Actors.prototype.deletePet = function(petId){
	if(!this.isPetId(petId))
		return false;

	this._data[petId] = null;
	return true;
};

//---------------------------------
//   Game_Actor
//--------------------------------
Game_Actor.prototype.getPets = function(){
	var pets = new Array();
	for(var i = 0; i < $gameParty.battlePets().length; i++){
		var pet = $gameParty.battlePets()[i];
		if(pet.master() === this)
			pets.push(pet);
	}

	return pets;
};

Game_Actor.prototype.orderPets = function(){
	var pets = this.getPets();
	for(var i = 0; i < pets.length; i++){
		var pet = pets[i];
		pet.setIndexForMaster(i + 1);
	}
};

//---------------------------------
//   Game_Pet
//--------------------------------
function Game_Pet() {
    this.initialize.apply(this, arguments);
};

Game_Pet.prototype = Object.create(Game_Actor.prototype);
Game_Pet.prototype.constructor = Game_Pet;

Game_Pet.prototype.initialize = function(petId, enemyId){
	Game_Actor.prototype.initialize.call(this, enemyId);

	this._petId = petId;
	this._masterActorId = 0; //召唤主体
	this._indexForMaster = 0;//宠物序列号【与主体排序】
	this._inBattle = false; //是否出战
	this._petDying = false;
	this._dieOpacity = 255;
	this._baseItem = null;//召唤物【道具/装备/技能】
};

Game_Pet.prototype.setBaseItem = function(item){
	this._baseItem = item;
};

Game_Pet.prototype.baseItem = function(){
	return this._baseItem;
};

Game_Pet.prototype.isPet = function(){
	return true;
};

Game_Pet.prototype.isInBattle = function(){
	return !!this._inBattle;
};

Game_Pet.prototype.startDie = function(){
	this._petDying = true;
};

Game_Pet.prototype.endDie = function(){
	this._petDying = false;
};

Game_Pet.prototype.isPetDying = function(){
	return this._petDying;
};

Game_Pet.prototype.setDieOpacity = function(opacity){
	this._dieOpacity = opacity;
};

Game_Pet.prototype.dieOpacity = function(){
	return this._dieOpacity;
};

Game_Pet.prototype.master = function(){
	return $gameActors.actor(this._masterActorId);
};

Game_Pet.prototype.setMaster = function(masterId){
	this._masterActorId = masterId;
};

Game_Pet.prototype.setIndexForMaster = function(index){
	this._indexForMaster = index;
};

Game_Pet.prototype.indexForMaster = function(){
	return this._indexForMaster;
};

Game_Pet.prototype.canFight = function(){
	return $gameParty.canFightPet() && !this.isInBattle();
};

//出战
Game_Pet.prototype.fight = function(){
	this._inBattle = true;
};

Game_Pet.prototype.canRest = function(){
	return this.isInBattle();
};

//休息
Game_Pet.prototype.rest = function(){
	this._inBattle = false;
};

Game_Pet.prototype.setup = function(enemyId){
    var pet = $dataEnemies[enemyId];
    this._baseId = enemyId;
    this._name = pet.name;
    this._classId = pet.petClassId;
    this._level = pet.initLevel || 0;
    this.initImages();
    this.initExp();
    this.initSkills();
    this.initEquips(pet.equips);
    this.clearParamPlus();
    this.recoverAll();
};

Game_Pet.prototype.isAutoBattle = function() {
    return Game_Actor.prototype.isAutoBattle.call(this) || this.pet().petAutoBattle;
};

Game_Pet.prototype.initImages = function(){
	Game_Actor.prototype.initImages.call(this);

	this._battlerName = this.pet().petBattlerName;
};

Game_Pet.prototype.pet = function(){
	return $dataEnemies[this._baseId];
};

Game_Pet.prototype.actor = function(){
	return this.pet();
};

Game_Pet.prototype.petId = function(){
	return this._petId;
};

Game_Pet.prototype.actorId = function(){
	return this.petId();
};

Game_Pet.prototype.paramBase = function(paramId) {
    var pet = this.pet();
    if(pet.classAffectParam)
    	return this.currentClass().params[paramId][this._level];
    else if(!!pet.customParamCode)
    	return this.customParam(paramId);
    else
    	return pet.params[paramId];
};

Game_Pet.prototype.customParam = function(paramId){
	var pet = this.pet();
	var base = {};
	base.mhp = pet.params[0];
	base.mmp  = pet.params[1];
	base.atk = pet.params[2];
	base.def = pet.params[3];
	base.mat = pet.params[4];
	base.mdf = pet.params[5];
	base.agi = pet.params[6];
	base.luk = pet.params[7];

	var level = this._level;
	var mhp = base.mhp;
	var mmp = base.mmp;
	var atk = base.atk;
	var def = base.def;
	var mat = base.mat;
	var mdf = base.mdf;
	var agi = base.agi;
	var luk = base.luk;

	try{
		eval(pet.customParamCode);

		switch(paramId){
			case 0:
				return mhp;
			case 1:
				return mmp;
			case 2:
				return atk;
			case 3:
				return def;
			case 4:
				return mat;
			case 5:
				return mdf;
			case 6:
				return agi;
			case 7:
				return luk;
			default:
				return 0;
		}
	}catch(err){
		console.error(err);
		return 0;
	}
};

Game_Pet.prototype.maxLevel = function(){
	return this.pet().petMaxLevel;
};

//死亡额外代码
Game_Pet.prototype.die = function(){
	Game_Actor.prototype.die.call(this);

	this.setDieOpacity(this.battler().opacity);
	this.startDie();
};

Game_Pet.prototype.initSkills = function() {
    this._skills = [];
    var skillList = this.pet().actions;

    skillList.forEach(function(action){
    	if(action.skillId > 1)
    		this.learnSkill(action.skillId);
    }, this);
};

Game_Pet.prototype.skills = function(){
	var skills = Game_Actor.prototype.skills.call(this);

	if(Imported.YEP_BattleAICore && this.isAutoBattle())
		skills = AIManager.getPatternSkills(skills, this.pet().petAiPattern);

	return skills;
};

if(Imported.YEP_BattleAICore){
//AI
Game_Pet.prototype.setAIPattern = function(){
    Game_Battler.prototype.setAIPattern.call(this);

    if (this.numActions() <= 0) return;
    AIManager.setBattler(this);
    for(var i = 0; i < this.pet().petAiPattern.length; ++i){
    	if(Math.random() > this.aiLevel()) continue;
    	var line =  this.pet().petAiPattern[i];
    	if(AIManager.isDecidedActionAI(line)) return;
    }
   
   Game_Actor.prototype.makeAutoBattleActions.call(this);
};

Game_Pet.prototype.makeAutoBattleActions = function(){
	if(this.isConfused()){
  		this.makeConfusionActions();
 	}else if (this.pet().petAiPattern.length > 0) {
   		this.setAIPattern();
		this.setActionState('waiting');
 	}else {
    	Game_Actor.prototype.makeAutoBattleActions.call(this);
    }
};

Game_Pet.prototype.aiLevel = function(){
	return this.pet().petAiLevel;
};

}


//--------------------------------
// Game_Party
//---------------------------------
CP.PetManager.INIT_ALL_PARTY_ITEMS = Game_Party.prototype.initAllItems;
Game_Party.prototype.initAllItems = function() {
    CP.PetManager.INIT_ALL_PARTY_ITEMS.call(this);

    this._pets = [];//宠物
    this._petsDepository = [];//宠物仓库
    this._changingPet = false;
};

Game_Party.prototype.startChangePet = function(){
	this._changingPet = true;
};

Game_Party.prototype.finishChangePet = function(){
	this._changingPet = false;
};

Game_Party.prototype.isChangingPet = function(){
	return !!this._changingPet;
};

Game_Party.prototype.pets = function(){
	return this._pets.map(function(petId){
		return $gameActors.actor(petId);
	});
};

Game_Party.prototype.petsDepository = function(){
	return this._petsDepository.map(function(petId){
		return $gameActors.actor(petId);
	});
};

Game_Party.prototype.clearPets = function(){
	var pets = JSON.parse(JSON.stringify(this._pets));
	pets.forEach(function(petId){
		this.releasePet(petId);
	}, this);
};

Game_Party.prototype.clearAllPets = function(){
	this._pets = this._pets.concat(this._petsDepository);
	this.clearPets();
};

Game_Party.prototype.battlePets = function(){
	return this.pets().filter(function(pet){
		return pet.isInBattle();
	});
};

Game_Party.prototype.aliveBattleActors = function(){
	return this.battleMembersNotPets().filter(function(actor){
		return actor.isAlive();
	});
};

Game_Party.prototype.maxPets = function(){
	return CP.PetManager.MAX_PETS_NUMBER;
};

Game_Party.prototype.maxBattlePets = function(){
	return CP.PetManager.MAX_BATTLE_PETS_NUMBER;
};

CP.PetManager.PARTY_MAX_BATTLE_MEMBERS = Game_Party.prototype.maxBattleMembers;
Game_Party.prototype.maxBattleMembers = function() {
    return CP.PetManager.PARTY_MAX_BATTLE_MEMBERS.call(this) + this.maxBattlePets();
};

Game_Party.prototype.canAddPet = function(){
	var length = this.maxPets();
	if(this.isChangingPet())
		length++;
	return this._pets.length < length;
};

Game_Party.prototype.canAddFightPet = function(){
	var length = this.maxBattlePets();
	if(this.isChangingPet())
		length++;
	return this.battlePets().length < length;
};

Game_Party.prototype.canFightPet = function(){
	return this.battlePets().length < this.maxBattlePets();
};

Game_Party.prototype.addPet = function(enemyId, masterId){
	if(!this.canAddPet())
		return -1;

	var petId = $gameActors.addPet(enemyId);
	this.setMasterForPet(petId, masterId);
	this._pets.push(petId);

	this.onPetAdded(petId);

	return petId;
};

Game_Party.prototype.setMasterForPet = function(petId, masterId){
	var pet = $gameActors.actor(petId);
	var master = $gameActors.actor(masterId);
	pet.setMaster(masterId);

	var masterPets = master.getPets();
	if(!masterPets.contains(pet))
		pet.setIndexForMaster(masterPets.length + 1);
};

Game_Party.prototype.onPetAdded = function(petId){
	var pet = $gameActors.actor(petId);

	try{
		eval(pet.pet().petAddedCode);
	}catch(err){
		console.error(err);
	}
};

//移除宠物包括两种操作，存仓库和放生
Game_Party.prototype.removePet = function(petId){
	var index = this._pets.indexOf(petId);
	if(index >= 0){
		this._pets.splice(index, 1);
		return true;
	}

	return false;
};

//放生
Game_Party.prototype.releasePet = function(petId){
	if(this.removePet(petId))
		$gameActors.deletePet(petId);
};

//交换
Game_Party.prototype.changePet = function(petId1, petId2, needDepository){
	var pet1 = $gameActors.actor(petId1);
	var pet2 = $gameActors.actor(petId2);

	if(!pet1 || !pet2)  return false;
	if(!pet1.isInBattle() || pet2.isInBattle())  return false;

	var masterId = pet1.master().actorId();
	pet1.rest();
	pet2.setMaster(masterId);
	pet2.setIndexForMaster(pet1.indexForMaster());
	pet2.fight();

	if(needDepository)
		$gameParty.addPetsDepository(petId1);

	this.onPetChanged(pet1, pet2);

	return true;
};

Game_Party.prototype.onPetChanged = function(oldPet, newPet){
	var oldItem = oldPet.baseItem();
	var newItem = newPet.baseItem();
	try{
		eval(CP.PetManager.PET_CHANGE_CODE);
	}catch(err){
		console.error(err);
	}
};

//放仓库
Game_Party.prototype.addPetsDepository = function(petId){
	if(this.removePet(petId)){
		this._petsDepository.push(petId);

		$gameActors.actor(petId).rest();
	}
};

//取仓库
Game_Party.prototype.getPetFromDepository = function(petId){
	var index = this._petsDepository.indexOf(petId);
	if(index >= 0){
		this._petsDepository.splice(index, 1);
		this._pets.push(petId);
	}
};

CP.PetManager.PARTY_ALL_MEMBERS = Game_Party.prototype.allMembers;
Game_Party.prototype.allMembers = function(){
    return CP.PetManager.PARTY_ALL_MEMBERS.call(this).concat(this.battlePets());
};

Game_Party.prototype.battleMembersNotPets = function(){
	return this.battleMembers().filter(function(member){
		return !member.isPet();
	});
};

Game_Party.prototype.petsDepository = function(){
	return this._petsDepository.map(function(petId){
		return $gameActors.actor(petId);
	});
};

Game_Party.prototype.onBattleEnd = function(){
	Game_Unit.prototype.onBattleEnd.call(this);

	this.onBattleEndPetEffect();
};

Game_Party.prototype.onBattleEndPetEffect = function(){
	try{
		eval(CP.PetManager.BATTLE_ENDED_CODE);
	}catch(err){
		console.error(err);
	}
};

CP.PetManager.PARTY_ALL_DEAD = Game_Party.prototype.isAllDead;
Game_Party.prototype.isAllDead = function() {
    if(CP.PetManager.PARTY_ALL_DEAD.call(this))
    	return true;

    if($gameSystem.defeatWhenOnlyPetsAlive() && this.aliveBattleActors().length === 0)
    	return true;

    return false;
};

//--------------------------------
// Game_Action
//---------------------------------
CP.PetManager.INIT_BATTLE_ACTION = Game_Action.prototype.initialize;
Game_Action.prototype.initialize = function(subject, forcing){
    CP.PetManager.INIT_BATTLE_ACTION.call(this, subject, forcing);

    this.setChangePetId(0);
};

Game_Action.prototype.setChangePetId = function(id){
	this._changePetId = id;
};

Game_Action.prototype.petNeedChange = function(){
	return $gameActors.actor(this._changePetId);
};

Game_Action.prototype.canChangePet = function(){
	return this._changePetId > 0;
};

Game_Action.prototype.isPetCaught = function(){
	return CP.PetManager.isCatchItem(this.item());
};

Game_Action.prototype.isAddPetAction = function(){
	return CP.PetManager.isAddPetItem(this.item());
};

//捕捉基础成功率
Game_Action.prototype.baseCatchPetChance = function(target){
	var user = this.subject();
	var item = this.item();
	var chance = 0;

	if(item.catchPetChance > 0)
		chance = item.catchPetChance;

	if(item.catchPetChanceEval){
		try{
			eval(item.catchPetChanceEval);
		}catch(err){
			console.error(err);
			chance = item.catchPetChance;
		}
	}

	return chance > 0 ? chance : 0;
};

Game_Action.prototype.catchPetChance = function(target){
	return this.baseCatchPetChance(target) * target.stateRate(target.catchPetStateId()) * this.lukEffectRate(target);
};

CP.PetManager.MAKE_ACTION_TARGETS = Game_Action.prototype.makeTargets;
Game_Action.prototype.makeTargets = function(){
	if(this.isAddPetAction())
		$gameParty.startChangePet();
	if(this.isAddPetAction() && $gameParty.canAddFightPet()){
		return this.createOrChangePet(this.item().petAddedInfo.enemyId);
	}
	else
		return CP.PetManager.MAKE_ACTION_TARGETS.call(this);
};

Game_Action.prototype.createOrChangePet = function(enemyId){
	var result = [];
	if(this.canChangePet()){
		result = this.changeNewPet(enemyId);
		this.setChangePetId(0);
	}else
		result = this.createPet(enemyId);

	return result;
};

Game_Action.prototype.createPet = function(enemyId){
	var result = [];
	var pet = null;
	
	var petId = $gameParty.addPet(enemyId, this.subject().actorId());
	pet = $gameActors.actor(petId);

	if(pet){
		var item = this.item();
		if(Imported.CP_UseEquip && this.equipItem())
			item = this.equipItem();
		pet.setBaseItem(item);
		pet.fight();
		result.push(pet);
	}

	return result;
};

Game_Action.prototype.changeNewPet = function(enemyId){
	var result = [];
	var pet = null;
	
	var petId = $gameParty.addPet(enemyId, this.subject().actorId());
	pet = $gameActors.actor(petId);

	if(pet){
		var item = this.item();
		if(Imported.CP_UseEquip && this.equipItem())
			item = this.equipItem();
		pet.setBaseItem(item);
		result.push(pet);
		$gameParty.changePet(this.petNeedChange().petId(), petId);
	}

	$gameParty.finishChangePet();

	return result;
};

CP.PetManager.APPLY_ACTION = Game_Action.prototype.apply;
Game_Action.prototype.apply = function(target){
	CP.PetManager.APPLY_ACTION.call(this, target);

	$gameParty.finishChangePet();

	if(this.isPetCaught()){
		CP.PetManager.setCatchAction(this);
		this.proocessCatch(target);
	}
};

Game_Action.prototype.proocessCatch = function(target){
	var chance = this.catchPetChance(target);
	var addable = target.isStateAddable(target.catchPetStateId());
	if(addable && Math.random() + chance > 1){
		target.addState(target.catchPetStateId());
		BattleManager._logWindow.displayCatchSuccess();
	}else
		BattleManager._logWindow.displayCatchFailure();
};

//--------------------------------
// Game_System
//---------------------------------
CP.PetManager.INIT_SYS = Game_System.prototype.initialize;
Game_System.prototype.initialize = function(){
	CP.PetManager.INIT_SYS.call(this);

	this._defeatWhenOnlyPetsAlive = CP.PetManager.DEFEAT_WHEN_ONLY_PETS_ALIVE;
};

Game_System.prototype.defeatWhenOnlyPetsAlive = function(){
	return !!this._defeatWhenOnlyPetsAlive;
};

Game_System.prototype.setDefeatWhenOnlyPetsAlive = function(defeat){
	this._defeatWhenOnlyPetsAlive = defeat;
};

//--------------------------------
// Game_Interpreter
//---------------------------------
CP.PetManager.PLUGIN_COMMAND = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args){
    CP.PetManager.PLUGIN_COMMAND.call(this, command, args);

    if(command == 'AddPet'){
    	var enemyId = Number(args[0]) || 0;
    	var master = Number(args[1]) || 0;
    	var autoFight = false;
    	if(args[2] && args[2] == "autoFight")
    		autoFight = true;

    	if(enemyId > 0){
    		if(master <= 0)
    			 master = $gameParty.leader().actorId();
    		var petId = $gameParty.addPet(enemyId, master);
    		if(petId > 0){
    			var pet = $gameActors.actor(petId);
    			if(autoFight)
    				pet.fight();
    		}
    	}
    }

    if($gameParty.inBattle() && command == 'PetBeCaught'){
    	var index = Number(args[0]) || 0;
    	var mode = args[1].trim().toLowerCase();

    	var target = $gameTroop.members()[index - 1];
    	if(target){
    		if(mode == "can")
    			target.setCanBeCaught(true);
    		if(mode == "cannot")
    			target.setCanBeCaught(false);
    	}
    }

    if(command == 'ShowPetScene')
    	SceneManager.push(Scene_Pet);
};

//--------------------------------
// Spriteset_Battle
//---------------------------------
CP.PetManager.CREATE_BATTLE_ACTOR_SPRITES = Spriteset_Battle.prototype.createActors;
Spriteset_Battle.prototype.createActors = function(){
	CP.PetManager.CREATE_BATTLE_ACTOR_SPRITES.call(this);
	this.createPets();
};

Spriteset_Battle.prototype.createPets = function(){
	this._petSprites = [];
	for(var i = 0; i < $gameParty.maxPets(); i++){
		this._petSprites[i] = new Sprite_Pet();
		this._battleField.addChild(this._petSprites[i]);
	}
};

CP.PetManager.SPRITESET_BATTLER_SPRITES = Spriteset_Battle.prototype.battlerSprites;
Spriteset_Battle.prototype.battlerSprites = function() {
    return CP.PetManager.SPRITESET_BATTLER_SPRITES.call(this).concat(this._petSprites);
};

Spriteset_Battle.prototype.getMasterSprite = function(battler){
	for(var i = 0; i < this._actorSprites.length; i++){
		var sprite = this._actorSprites[i];
		var master = battler.master();
		if(sprite._actor === master)
			return sprite;
	}

	return null;
};

Spriteset_Battle.prototype.updateActors = function(){
	this.updateMasterActors();
	this.updatePets();
};

Spriteset_Battle.prototype.updateMasterActors = function() {
    var members = $gameParty.battleMembersNotPets();
    for (var i = 0; i < this._actorSprites.length; i++) {
        this._actorSprites[i].setBattler(members[i]);
    }
};

Spriteset_Battle.prototype.updatePets = function(){
	var members = $gameParty.battlePets();
	for(var i = 0; i < members.length; i++)
		this._petSprites[i].setBattler(members[i]);
};

//--------------------------------
// Sprite_Battler
//---------------------------------
Sprite_Battler.prototype.isPetSprite = function() {
    return false;
};

CP.PetManager.SET_BATTLER_SPRITE = Sprite_Battler.prototype.setBattler;
Sprite_Battler.prototype.setBattler = function(battler){
	CP.PetManager.SET_BATTLER_SPRITE.call(this, battler);

	if(!Imported.YEP_BattleEngineCore && battler)
		battler.setBattler(this);
};

//--------------------------------
// Sprite_Actor
//---------------------------------
CP.PetManager.SET_ACTOR_SPRITE_HOME = Sprite_Actor.prototype.setActorHome;
Sprite_Actor.prototype.setActorHome = function(index){
	if(Imported.YEP_BattleEngineCore)
		this.setActorHomeForYEBattleEngine(index);
	else{
		CP.PetManager.SET_ACTOR_SPRITE_HOME.call(this, index);
		this.moveToStartPosition();
	}
};

Sprite_Actor.prototype.setActorHomeForYEBattleEngine = function(index){
	var screenWidth = Graphics.boxWidth;
    var screenHeight = Graphics.boxHeight;
    var maxSize = $gameParty.maxBattleMembers() - $gameParty.maxBattlePets();
    var partySize = $gameParty.battleMembers().length - $gameParty.maxBattlePets();
    var statusHeight = eval(Yanfly.Param.BECCommandRows);
    statusHeight *= Window_Base.prototype.lineHeight.call(this);
    statusHeight += Window_Base.prototype.standardPadding.call(this) * 2;
    if ($gameSystem.isSideView()) {
      var code = Yanfly.Param.BECHomePosX;
      try {
        var homeX = eval(code);
      } catch (e) {
        var homeX = 0;
        Yanfly.Util.displayError(e, code, 'SIDE VIEW HOME X FORMULA ERROR');
      }
      var code = Yanfly.Param.BECHomePosY;
      try {
        var homeY = eval(code);
      } catch (e) {
        var homeY = 0;
        Yanfly.Util.displayError(e, code, 'SIDE VIEW HOME Y FORMULA ERROR');
      }
    } else {
      var code = Yanfly.Param.BECFrontPosX;
      try {
        var homeX = eval(code);
      } catch (e) {
        var homeX = 0;
        Yanfly.Util.displayError(e, code, 'FRONT VIEW HOME X FORMULA ERROR');
      }
      var code = Yanfly.Param.BECFrontPosY;
      try {
        var homeY = eval(code);
      } catch (e) {
        var homeY = 0;
        Yanfly.Util.displayError(e, code, 'FRONT VIEW HOME Y FORMULA ERROR');
      }
    }
    this._checkAliveStatus = false;
    if ($gameParty.battleMembers()[index]) {
      var actor = $gameParty.battleMembers()[index];
      if (actor.isAlive()) this._checkAliveStatus = true;
    }
    this.setHome(homeX, homeY);
    this.moveToStartPosition();
};

//--------------------------------
// Sprite_Pet
//---------------------------------
function Sprite_Pet(){
	this.initialize.apply(this, arguments);
};

Sprite_Pet.prototype = Object.create(Sprite_Actor.prototype);
Sprite_Pet.prototype.constructor = Sprite_Pet;

Sprite_Pet.prototype.initialize = function(){
	Sprite_Actor.prototype.initialize.apply(this, arguments);
};

Sprite_Pet.prototype.masterSprite = function(){
	return this._actor.master().battler();
};

Sprite_Pet.prototype.isPetSprite = function() {
    return true;
};

Sprite_Pet.prototype.setActorHome = function(index){
	var index = this._actor.indexForMaster();
	var pet = this._actor.pet();
	var x = 0;
	var y = 0;

	if(pet.defaultPetPosition)
		Sprite_Actor.prototype.setActorHome.call(this, index);
	else{
		try{
			var master = this.masterSprite();
			eval(pet.homePosition);
			if(!Imported.YEP_BattleEngineCore && $gameTroop.turnCount() === 0)
				x -= 300;

			this.setHome(x, y);
			this.moveToStartPosition();
		}catch(err){
			console.error(err);
			Sprite_Actor.prototype.setActorHome.call(this, index);
		}
	}
};

Sprite_Pet.prototype.update = function(){
	Sprite_Actor.prototype.update.call(this);

	if(this._actor && this._actor.isPetDying())
		this.updatePetOpacity();
};

Sprite_Pet.prototype.updatePetOpacity = function(){
	var opacity = this._actor.dieOpacity();
	var speed = Math.round(opacity / this._actor.pet().petExitTime);
	if(speed < 1)
		speed = 1;

	if(speed === Infinity){
		this.onExitEnd();
		this._actor.endDie();
		return;
	}

	this.opacity -= speed;
	if(this.opacity <= 0){
		this.onExitEnd();
		this._actor.endDie();
	}
};

Sprite_Pet.prototype.onExitEnd = function(){
	var pet = this._actor;
	try{
		if(pet)
			eval(pet.pet().petDieCode);
	}catch(err){
		console.error(err);
	}
};

//--------------------------------
// Window_BattleLog
//---------------------------------
Window_BattleLog.prototype.displayCatchSuccess = function(){
	this.push("addText", CP.PetManager.CATCH_SUCCESS_INFO);
};

Window_BattleLog.prototype.displayCatchFailure = function(){
	this.push("addText", CP.PetManager.CATCH_FAILURE_INFO);
};

//--------------------------------
// Window_PetList
//---------------------------------
function Window_PetList(){
	this.initialize.apply(this, arguments);
};

Window_PetList.prototype = Object.create(Window_Selectable.prototype);
Window_PetList.prototype.constructor = Window_PetList;

Window_PetList.prototype.initialize = function(x, y, height){
	var width = this.windowWidth();

	Window_Selectable.prototype.initialize.call(this, x, y, width, height);
	this.deselect();
	this.deactivate();
};

Window_PetList.prototype.windowWidth = function(){
	return eval(CP.PetManager.TYPE_WINDOW_WIDTH);
};

Window_PetList.prototype.maxItems = function(){
	return !!this._list ? this._list.length :  0;
};

Window_PetList.prototype.refreshPetList = function(){
	if(!this._list)
		this._list = [];

	switch(this.parent.parent.typeIndex()){
		case 0:
			this._list = $gameParty.pets();
			break;
		case 1:
			this._list = $gameParty.petsDepository();
			break;
	}
};

Window_PetList.prototype.setSelectCallback = function(callback){
	this._selectCallback = callback;
};

Window_PetList.prototype.refresh = function(){
	this.refreshPetList();

	Window_Selectable.prototype.refresh.call(this);
};

Window_PetList.prototype.currentPet = function(){
	if(!this._list)
		return null;
	return this._list[this.index()];
};

Window_PetList.prototype.drawItem = function(index){
	var pet = this._list[index];
	var rect = this.itemRect(index);

	this.resetTextColor();
	if(pet.isInBattle())
		this.changeTextColor(this.fightColor());
	this.drawText(pet.name(), rect.x, rect.y, rect.width / 2, "left");

	if(CP.PetManager.SHOW_PET_LEVEL)
		this.drawText(CP.PetManager.PET_LEVEL_NAME + pet.level, rect.x + rect.width / 2, rect.y, rect.width / 2, "right");
};

Window_PetList.prototype.select = function(index){
	Window_Selectable.prototype.select.call(this, index);

	if(this._selectCallback)
		this._selectCallback.call(this);
};

Window_PetList.prototype.fightColor = function(){
	return this.textColor(CP.PetManager.PET_LIST_BATTLE_COLOR);
};

if(CP.PetManager.USE_SCENE){

//--------------------------------
// Window_MenuCommand
//---------------------------------
CP.PetManager.ADD_MENU_ORIGINAL_COMMANDS = Window_MenuCommand.prototype.addOriginalCommands;
Window_MenuCommand.prototype.addOriginalCommands = function(){
	CP.PetManager.ADD_MENU_ORIGINAL_COMMANDS.call(this);

	this.addPetCommand();
};

Window_MenuCommand.prototype.addPetCommand = function(){
	this.addCommand(CP.PetManager.PET_COMMAND_NAME, "pet");
};

//--------------------------------
// Scene_Menu
//---------------------------------
CP.PetManager.CREATE_SCENE_COMMAND_WINDOW = Scene_Menu.prototype.createCommandWindow;
Scene_Menu.prototype.createCommandWindow = function(){
	CP.PetManager.CREATE_SCENE_COMMAND_WINDOW.call(this);

	this._commandWindow.setHandler("pet", this.onPetCommand.bind(this));
};

Scene_Menu.prototype.onPetCommand = function(){
	SceneManager.push(Scene_Pet);
};

//--------------------------------
// Scene_Pet
//---------------------------------
function Scene_Pet(){
	this.initialize.apply(this, arguments);
};

Scene_Pet.prototype = Object.create(Scene_MenuBase.prototype);
Scene_Pet.prototype.constructor = Scene_Pet;

Scene_Pet.prototype.initialize = function(){
	Scene_MenuBase.prototype.initialize.call(this);

	this.setPet(0);
};

Scene_Pet.prototype.setPet = function(petId){
	this._petId = petId;
};

Scene_Pet.prototype.pet = function(){
	return $gameActors.actor(this._petId);
};

Scene_Pet.prototype.create = function(){
	Scene_MenuBase.prototype.create.call(this);

	this.createHelpWindow();
	this.createTypeWindow();
	this.createListWindow();
	this.createCommandWindow();
	this.createStatusWindow();
	this.createDetailWindow();
	this.createConfirmWindow();
	this.reserveFaceImages();
};

Scene_Pet.prototype.createHelpWindow = function(){
	Scene_MenuBase.prototype.createHelpWindow.call(this);

	this.resetHelpText();
};

Scene_Pet.prototype.createTypeWindow = function(){
	var y = this._helpWindow.height;
	this._typeWindow = new Window_PetTypeSelect(0, y);

	this._typeWindow.setHandler("cancel", this.popScene.bind(this));
	this._typeWindow.setHandler("ok", this.onTypeOk.bind(this));

	this.addWindow(this._typeWindow);
};

Scene_Pet.prototype.typeIndex = function(){
	return this._typeWindow.index();
};

Scene_Pet.prototype.createListWindow = function(){
	var y = this._typeWindow.y + this._typeWindow.height;
	var height = Graphics.boxHeight - y;
	this._listWindow = new Window_PetList(0, y, height);

	this._listWindow.setHandler("cancel", this.onListCancel.bind(this));
	this._listWindow.setHandler("ok", this.onListOk.bind(this));
	this._listWindow.setSelectCallback(this.onListSelect.bind(this));

	this.addWindow(this._listWindow);
	this._listWindow.refresh();
};

Scene_Pet.prototype.createStatusWindow = function(){
	var x = this._typeWindow.width;
	var y = this._helpWindow.height;
	var width = Graphics.boxWidth - x;
	var height = eval(CP.PetManager.STATUS_WINDOW_HEIGHT);

	this._statusWindow = new Window_PetStatus(x, y, width, height);
	this.addWindow(this._statusWindow);
};

Scene_Pet.prototype.createDetailWindow = function(){
	var x = this._listWindow.width + this._listWindow.x;
	var y = this._statusWindow.y + this._statusWindow.height;
	var width = Graphics.boxWidth - x;
	var height = this._commandWindow.y - y;

	this._detailWindow = new Window_PetDetail(x, y, width, height);
	this.addWindow(this._detailWindow);
};

Scene_Pet.prototype.createCommandWindow = function(){
	var x = this._listWindow.x + this._listWindow.width;
	var height = Window_Base.prototype.lineHeight() * 2 + CP.PetManager.COMMAND_WINDOW_HEIGHT_PLUS;
	var width = Graphics.boxWidth - x;
	var y = Graphics.boxHeight - height;
	this._commandWindow = new Window_PetCommand(x, y, width, height);

	this._commandWindow.setHandler("cancel", this.onCommandCancel.bind(this));
	this._commandWindow.setHandler("fight", this.onCommandFight.bind(this));
	this._commandWindow.setHandler("rest", this.onCommandRest.bind(this));
	this._commandWindow.setHandler("depository", this.onCommandDepository.bind(this));
	this._commandWindow.setHandler("release", this.onCommandRelease.bind(this));

	this.addWindow(this._commandWindow);
};

Scene_Pet.prototype.createConfirmWindow = function(){
	var y = Math.round(Graphics.boxHeight / 2 - Window_Base.prototype.standardPadding() * 2) + CP.PetManager.RELEASE_CONFIRM_Y_OFFSET;

	this._confirmWindow = new Window_ReleaseConfirm(0, y);
	var x = Math.round(Graphics.boxWidth / 2 - this._confirmWindow.textWidth(CP.PetManager.RELEASE_CONFIRM_INFO) / 2) 
		+ CP.PetManager.RELEASE_CONFIRM_X_OFFSET;
	this._confirmWindow.x = x;
	this._confirmWindow.setHandler("ok", this.onConfirmOk.bind(this));
	this._confirmWindow.setHandler("cancel", this.onConfirmCancel.bind(this));

	this.addWindow(this._confirmWindow);
};

Scene_Pet.prototype.onTypeOk = function(){
	this._typeWindow.deactivate();
	this._listWindow.activate();
	this._listWindow.select(0);
};

Scene_Pet.prototype.onListCancel = function(){
	this._listWindow.deselect();
	this._listWindow.deactivate();
	this._typeWindow.activate();
};

Scene_Pet.prototype.onListSelect = function(){
	var pet = this._listWindow.currentPet();
	if(pet)
		this.setPet(pet.petId());
	else
		this.setPet(0);

	this._statusWindow.refresh();

	this._commandWindow.setPet(this._petId);
	this._detailWindow.setPet(this._petId);
	this._commandWindow.refresh();
	this._detailWindow.refresh();
};

Scene_Pet.prototype.onListOk = function(){
	this._listWindow.deactivate();
	
	this._commandWindow.activate();
	this._commandWindow.select(0);
};

Scene_Pet.prototype.goToListFromCommand = function(){
	this._listWindow.activate();
	this._listWindow.refresh();
	this._commandWindow.deselect();
	this._commandWindow.deactivate();

	this._statusWindow.refresh();
	this._detailWindow.refresh();
};

Scene_Pet.prototype.onCommandFight = function(){
	this.pet().fight();

	this.goToListFromCommand();
	this.setHelpText(CP.PetManager.FIGHT_HELP_TEXT.format(this.pet().name()));
};

Scene_Pet.prototype.onCommandRest = function(){
	this.pet().rest();

	this.goToListFromCommand();
	this.setHelpText(CP.PetManager.REST_HELP_TEXT.format(this.pet().name()));
};

Scene_Pet.prototype.onCommandDepository = function(){
	var petId = this.pet().petId();
	var name = this.pet().name();

	if(this.typeIndex() === 1){
		$gameParty.getPetFromDepository(petId);
		this.setHelpText(CP.PetManager.DEPOSITORY_OUT_HELP_TEXT.format(name));
	}
	else{
		$gameParty.addPetsDepository(petId);
		this.setHelpText(CP.PetManager.DEPOSITORY_IN_HELP_TEXT.format(name));
	}

	this.goToListFromCommand();
};

Scene_Pet.prototype.onCommandRelease = function(){
	this._commandWindow.deactivate();
	this._confirmWindow.setPet(this.pet().petId());
	this._confirmWindow.show();
	this._confirmWindow.open();
	this._confirmWindow.refresh();
	this._confirmWindow.select(0);
	this._confirmWindow.activate();
};

Scene_Pet.prototype.onCommandCancel = function(){
	this._commandWindow.deselect();
	this._commandWindow.deactivate();
	this._listWindow.activate();
};

Scene_Pet.prototype.onConfirmOk = function(){
	var pet = this.pet();
	if(pet){
		$gameParty.releasePet(pet.petId());
		this.setHelpText(CP.PetManager.RELEASE_HELP_TEXT.format(pet.name()));
	}

	this._confirmWindow.deselect();
	this._confirmWindow.deactivate();
	this._confirmWindow.close();
	this._listWindow.refresh();
	this._listWindow.activate();
	this._listWindow.reselect();
};

Scene_Pet.prototype.onConfirmCancel = function(){
	this._confirmWindow.deselect();
	this._confirmWindow.deactivate();
	this._confirmWindow.close();
	this._commandWindow.activate();
};

Scene_Pet.prototype.setHelpText = function(text){
	this._helpWindow.setText(text);
};

Scene_Pet.prototype.resetHelpText = function(){
	this.setHelpText(CP.PetManager.HELP_WINDOW_TEXT);
};

Scene_Pet.prototype.refreshPetList = function(){
	this._listWindow.refresh();
};

Scene_Pet.prototype.refreshCommandList = function(){
	this._commandWindow.refresh();
};

Scene_Pet.prototype.reserveFaceImages = function(){
   var pets = $gameParty.pets().concat($gameParty.petsDepository());
   pets.forEach(function(pet){
   		if(pet)
        	ImageManager.reserveFace(pet.faceName());
    });
};

//--------------------------------
// Window_PetTypeSelect
//---------------------------------
function Window_PetTypeSelect(){
	this.initialize.apply(this, arguments);
};

Window_PetTypeSelect.prototype = Object.create(Window_Selectable.prototype);
Window_PetTypeSelect.prototype.constructor = Window_PetTypeSelect;

Window_PetTypeSelect.prototype.initialize = function(x, y){
	var width = this.windowWidth();
	var height = this.windowHeight();

	Window_Selectable.prototype.initialize.call(this, x, y, width, height);
	this.refresh();
	this.activate();
	this.select(0);
};

Window_PetTypeSelect.prototype.maxItems = function(){
	return 2;
};

Window_PetTypeSelect.prototype.windowHeight = function(){
	return (this.maxRows() + 1) * this.itemHeight() + CP.PetManager.TYPE_WINDOW_HEIGHT_PLUS;
};

Window_PetTypeSelect.prototype.windowWidth = function(){
	return eval(CP.PetManager.TYPE_WINDOW_WIDTH);
};

Window_PetTypeSelect.prototype.drawItem = function(index){
	var name = CP.PetManager.PET_LIST_NAMES[index];
	var rect = this.itemRect(index);
	this.drawText(name, rect.x, rect.y, rect.width, "left");
};

Window_PetTypeSelect.prototype.select = function(index){
	Window_Selectable.prototype.select.call(this, index);

	if(this.parent && this.parent.parent){
		this.parent.parent.refreshPetList();
		this.parent.parent.refreshCommandList();
	}
};

//--------------------------------
// Window_PetStatus
//---------------------------------
function Window_PetStatus(){
	this.initialize.apply(this, arguments);
};

Window_PetStatus.prototype = Object.create(Window_Base.prototype);
Window_PetStatus.prototype.constructor = Window_PetStatus;

Window_PetStatus.prototype.initialize = function(x, y, width, height){
	Window_Base.prototype.initialize.call(this, x, y, width, height);

	this.refresh();
};

Window_PetStatus.prototype.refresh = function() {
    if (this.contents) {
        this.contents.clear();
        if(this.parent && this.parent.parent){
        	this.drawStatus();
        }
    }
};

Window_PetStatus.prototype.drawStatus = function(){
	var pet =  this.parent.parent.pet();
	var x = Window_Base._faceWidth;
	var width = this.width - x - 32;
	
	if(pet){
		this.drawActorFace(pet, 0, 0, Window_Base._faceWidth, Window_Base._faceHeight);
		this.drawActorSimpleStatus(pet, x, 0, width);
	}
};

//--------------------------------
// Window_PetCommand
//---------------------------------
function Window_PetCommand(){
	this.initialize.apply(this, arguments);
};

Window_PetCommand.prototype = Object.create(Window_HorzCommand.prototype);
Window_PetCommand.prototype.constructor = Window_PetCommand;

Window_PetCommand.prototype.initialize = function(x, y, width, height){
	this._realWidth = width;
	this._realHeight = height;

	Window_HorzCommand.prototype.initialize.call(this, x, y);

	this.deselect();
	this.deactivate();
};

Window_PetCommand.prototype.windowWidth = function() {
    return this._realWidth;
};

Window_PetCommand.prototype.windowHeight = function() {
    return this._realHeight;
};

Window_PetCommand.prototype.setPet = function(petId){
	this._petId = petId;
};

Window_PetCommand.prototype.pet = function(){
	return $gameActors.actor(this._petId);
};

Window_PetCommand.prototype.makeCommandList = function(){
	Window_Command.prototype.makeCommandList.call(this);

	var pet = this.pet();
	var isDepository = false;
	if(this.parent && this.parent.parent && this.parent.parent.typeIndex() === 1)
		isDepository = true;

	if(CP.PetManager.FIGHT_REST_COMMAND_USABLE){
		this.addCommand(CP.PetManager.PET_COMMAND_FIGHT_NAME, "fight", !!pet && pet.canFight() && !isDepository);
		this.addCommand(CP.PetManager.PET_COMMAND_REST_NAME, "rest", !!pet && pet.canRest());
	}
	
	if(isDepository)
		this.addCommand(CP.PetManager.PET_COMMAND_OUT_DEPOSITORY_NAME, "depository", !!pet);
	else
		this.addCommand(CP.PetManager.PET_COMMAND_IN_DEPOSITORY_NAME, "depository", !!pet);
	this.addCommand(CP.PetManager.PET_COMMAND_RELEASE_NAME, "release", !!pet && !isDepository);
};


//--------------------------------
// Window_ReleaseConfirm
//---------------------------------
function Window_ReleaseConfirm(){
	this.initialize.apply(this, arguments);
};

Window_ReleaseConfirm.prototype = Object.create(Window_HorzCommand.prototype);
Window_ReleaseConfirm.prototype.constructor = Window_ReleaseConfirm;

Window_ReleaseConfirm.prototype.initialize = function(x, y){
	Window_HorzCommand.prototype.initialize.call(this, x, y);

	this.setPet(0);
	this.hide();
	this.deactivate();
	this.close();
};

Window_ReleaseConfirm.prototype.setPet = function(petId){
	this._petId = petId;
};

Window_ReleaseConfirm.prototype.pet = function(){
	return $gameActors.actor(this._petId);
};

Window_ReleaseConfirm.prototype.infoText = function(){
	var pet = this.pet();
	if(pet)
		return CP.PetManager.RELEASE_CONFIRM_INFO.format(pet.name());
	else
		return "";
};

Window_ReleaseConfirm.prototype.windowWidth = function(){
	if(this._windowContentsSprite)
		return this.textWidth(this.infoText()) + this.standardPadding() * 5;
	return Window_HorzCommand.prototype.windowWidth.call(this);
};

Window_ReleaseConfirm.prototype.windowHeight = function(){
	return this.itemRect(0).height * 3;
};

Window_ReleaseConfirm.prototype.refresh = function(){
	this.width = this.windowWidth();

	Window_HorzCommand.prototype.refresh.call(this);
};

Window_ReleaseConfirm.prototype.makeCommandList = function(){
	Window_HorzCommand.prototype.makeCommandList.call(this);

	this.addCommand(CP.PetManager.RELEASE_CONFIRM_COMMAND_INFOS[0], "ok");
	this.addCommand(CP.PetManager.RELEASE_CONFIRM_COMMAND_INFOS[1], "cancel");
};

Window_ReleaseConfirm.prototype.itemRect = function(index){
	var rect = Window_HorzCommand.prototype.itemRect.call(this, index);

	rect.x = index * this.width / 2;
	rect.y += this.lineHeight();
	rect.width = this.width / 2 - this.standardPadding();

	return rect;
};

Window_ReleaseConfirm.prototype.drawAllItems = function(){
	this.drawInfoText();
	Window_HorzCommand.prototype.drawAllItems.call(this);
};

Window_ReleaseConfirm.prototype.drawInfoText = function(){
	var rect = this.itemRect(0);
	this.resetTextColor();
	this.drawText(this.infoText(), rect.x, rect.y - this.lineHeight(), this.width, "center");	
};

//--------------------------------
// Window_PetDetail
//---------------------------------
function Window_PetDetail(){
	this.initialize.apply(this, arguments);
};

Window_PetDetail.prototype = Object.create(Window_Selectable.prototype);
Window_PetDetail.prototype.constructor = Window_PetDetail;

Window_PetDetail.prototype.initialize = function(x, y, width, height){
	Window_Selectable.prototype.initialize.call(this, x, y, width, height);

	this.setPet(0);
	this.deselect();
	this.deactivate();
};

Window_PetDetail.prototype.setPet = function(petId){
	this._petId = petId;
};

Window_PetDetail.prototype.pet = function(){
	return $gameActors.actor(this._petId);
};

Window_PetDetail.prototype.maxItems = function(){
	return 8;
};

Window_PetDetail.prototype.maxCols = function(){
	return 2;
};

Window_PetDetail.prototype.itemRect = function(index){
	var rect = Window_Selectable.prototype.itemRect.call(this, index);
	var xIndex = index % this.maxCols();
	var yIndex = Math.floor(index / this.maxCols());

	rect.width = Math.floor(this.width / this.maxCols());
	rect.height = Math.floor(this.height / this.maxRows() - CP.PetManager.DETAIL_ITEM_WIDTH);
	rect.x = rect.width * xIndex;
	rect.y = Math.round(this.height / this.maxRows()) + rect.height * yIndex;

	return rect;
};

Window_PetDetail.prototype.drawAllItems = function(){
	Window_Selectable.prototype.drawAllItems.call(this);

	this.drawPetSimpleInfo();
};

Window_PetDetail.prototype.drawPetSimpleInfo = function(){
	var pet = this.pet();
	if(!pet)
		return;

	var x = this.standardPadding();
	var y = this.standardPadding();
	this.drawActorName(pet, x, y);
	this.drawActorLevel(pet, x + this.width / 3, y);
};

Window_PetDetail.prototype.drawItem = function(index){
	Window_Selectable.prototype.drawItem.call(this, index);
	var pet = this.pet();
	if(!pet)
		return;

	var rect = this.itemRect(index);
	this.changeTextColor(this.systemColor());
	this.drawText(TextManager.param(index), rect.x, rect.y, rect.width / 2, "left");
	this.resetTextColor();
	this.drawText(pet.param(index), rect.x + rect.width / 2, rect.y, rect.width / 2, "changeTextColor");
};

}

//--------------------------------
// Scene_Battle
//---------------------------------
CP.PetManager.CREATE_ALL_BATTLE_WINDOWS = Scene_Battle.prototype.createAllWindows;
Scene_Battle.prototype.createAllWindows = function(){
	CP.PetManager.CREATE_ALL_BATTLE_WINDOWS.call(this);

	this.createPetChangeWindow();
};

Scene_Battle.prototype.createPetChangeWindow = function(){
	var x = eval(CP.PetManager.CHANGE_WINDOW_DATA.x);
	var y = eval(CP.PetManager.CHANGE_WINDOW_DATA.y);
	var width = eval(CP.PetManager.CHANGE_WINDOW_DATA.width);
	var height = eval(CP.PetManager.CHANGE_WINDOW_DATA.height);
	this._changePetWindow = new Window_PetChange(x, y, width, height);

	this._changePetWindow.setHandler("ok", this.onPetChangeOk.bind(this));
	this._changePetWindow.setHandler("cancel", this.onPetChangeCancel.bind(this));
	this.addWindow(this._changePetWindow);
};

Scene_Battle.prototype.onPetChangeOk = function(){
	var pet = this._changePetWindow.currentPet();
	var action = BattleManager.inputtingAction();
	action.setChangePetId(pet.petId());

	this._changePetWindow.hide();
	this._changePetWindow.deselect();
	this._changePetWindow.deactivate();
	this.selectNextCommand();
};

Scene_Battle.prototype.onPetChangeCancel = function(){
	this._changePetWindow.hide();
	this._changePetWindow.deactivate();

	this._actorCommandWindow.show();
	this._actorCommandWindow.reselect();
	this._actorCommandWindow.activate();
};

CP.PetManager.ON_BATTLE_SELECT_ACTION = Scene_Battle.prototype.onSelectAction;
Scene_Battle.prototype.onSelectAction = function(){
	var action = BattleManager.inputtingAction();

    if(action.isAddPetAction() && !$gameParty.canAddFightPet())
    	this.onChangePet(action);
    else
    	CP.PetManager.ON_BATTLE_SELECT_ACTION.call(this);
};

Scene_Battle.prototype.onChangePet = function(action){
	this._itemWindow.hide();
	this._skillWindow.hide();
	this._changePetWindow.show();
	this._changePetWindow.refresh();
	this._changePetWindow.activate();
	this._changePetWindow.select(0);
};

CP.PetManager.ANY_BATTLE_INPUT_WINDOW_ACTIVE = Scene_Battle.prototype.isAnyInputWindowActive;
Scene_Battle.prototype.isAnyInputWindowActive = function() {
	return CP.PetManager.ANY_BATTLE_INPUT_WINDOW_ACTIVE.call(this) || this._changePetWindow.active;
};

//--------------------------------
// Window_PetChange
//---------------------------------
function Window_PetChange(){
	this.initialize.apply(this, arguments);
};

Window_PetChange.prototype = Object.create(Window_PetList.prototype);
Window_PetChange.prototype.constructor = Window_PetChange;

Window_PetChange.prototype.initialize = function(x, y, width, height){
	this._realWidth = width;

	Window_PetList.prototype.initialize.call(this, x, y, height);

	this.setSelectCallback(null);
	this.refreshPetList();
	this.hide();
};

Window_PetChange.prototype.windowWidth = function(){
	return this._realWidth;
};

Window_PetChange.prototype.refreshPetList = function(){
	if(!this._list)
		this._list = [];
	this._list = $gameParty.battlePets();
};

Window_PetChange.prototype.fightColor = function(){
	return this.normalColor();
};

Window_PetChange.prototype.itemRect = function(index){
	var rect = Window_PetList.prototype.itemRect.call(this, index);

	rect.y += this.lineHeight();

	return rect;
};

Window_PetChange.prototype.drawAllItems = function(){
	this.drawInfoText();
	Window_PetList.prototype.drawAllItems.call(this);
};

Window_PetChange.prototype.drawInfoText = function(){
	var rect = this.itemRect(0);

	this.resetTextColor();
	this.drawText(CP.PetManager.CHANGE_WINDOW_DATA.text, rect.x, rect.y - this.lineHeight(), rect.width);
};

//--------------------------------
// Window_BattleItem
//---------------------------------
CP.PetManager.INCLUDES_BATTLE_ITEM = Window_BattleItem.prototype.includes;
Window_BattleItem.prototype.includes = function(item){
	var result = CP.PetManager.INCLUDES_BATTLE_ITEM.call(this, item);
	if(CP.PetManager.isAddPetItem(item))
		result = result && CP.PetManager.canUseAddPetItem(item);

	return result;
};

//--------------------------------
// Window_BattleSkill 
//---------------------------------
Window_BattleSkill.prototype.isEnabled = function(item) {
	var result = Window_SkillList.prototype.isEnabled.call(this, item);
	if(CP.PetManager.isAddPetItem(item))
		result = result && CP.PetManager.canUseAddPetItem(item);

	return result;
};