Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
| //============================================================================= | |
| // QABS | |
| //============================================================================= | |
| var Imported = Imported || {}; | |
| if (!Imported.QMovement || !QPlus.versionCheck(Imported.QMovement, '1.4.0')) { | |
| alert('Error: QABS requires QMovement 1.4.0 or newer to work.'); | |
| throw new Error('Error: QABS requires QMovement 1.4.0 or newer to work.'); | |
| } | |
| Imported.QABS = '1.7.0'; | |
| //============================================================================= | |
| /*: | |
| * @plugindesc <QABS> | |
| * Action Battle System for QMovement | |
| * @version 1.7.0 | |
| * @author Quxios | Version 1.7.0 | |
| * @site https://quxios.github.io/ | |
| * @updateurl https://quxios.github.io/data/pluginsMin.json | |
| * | |
| * @repo https://github.com/quxios/QABS | |
| * | |
| * @requires QMovement | |
| * | |
| * @video TODO | |
| * | |
| * @param Attack Settings | |
| * | |
| * @param Quick Target | |
| * @parent Attack Settings | |
| * @desc Ground target skills will instantly cast at mouse location | |
| * @type Boolean | |
| * @default false | |
| * | |
| * @param Lock when Targeting | |
| * @parent Attack Settings | |
| * @desc Player can't move when using Ground / Select targeting skills | |
| * @type Boolean | |
| * @on Can't Move | |
| * @off Can Move | |
| * @default false | |
| * | |
| * @param Aim with Mouse | |
| * @parent Attack Settings | |
| * @desc All actions will be used towards your mouse location | |
| * @type Boolean | |
| * @on Towards mouse | |
| * @off Towards player direction | |
| * @default false | |
| * | |
| * @param Aim with Analog | |
| * @parent Attack Settings | |
| * @desc All actions will be used towards right analog stick when using a | |
| * gamepad. | |
| * @type Boolean | |
| * @on Towards right analog | |
| * @off Towards player direction | |
| * @default false | |
| * | |
| * @param Move Resistance Rate Stat | |
| * @parent Attack Settings | |
| * @desc Which stat to use for Move Resistance Rate | |
| * Default: xparam(1) // This is Evasion | |
| * @default xparam(1) | |
| * | |
| * @param Loot Settings | |
| * | |
| * @param Loot Decay | |
| * @parent Loot Settings | |
| * @desc How long until the loot disappears, in frames. | |
| * @type Number | |
| * @min 1 | |
| * @default 600 | |
| * | |
| * @param AoE Loot | |
| * @parent Loot Settings | |
| * @desc Collect nearby loot or pick up one at a time. | |
| * @type Boolean | |
| * @default true | |
| * | |
| * @param Loot Touch Trigger | |
| * @parent Loot Settings | |
| * @desc Pick up loot on player touch | |
| * @type Boolean | |
| * @default false | |
| * | |
| * @param Gold Icon | |
| * @parent Loot Settings | |
| * @desc Icon Index to display for gold loot | |
| * Default: 314 | |
| * @default 314 | |
| * | |
| * @param Level Animation | |
| * @parent Loot Settings | |
| * @desc The animation ID to play on level up. | |
| * Default: 52 | |
| * @type Animation | |
| * @default 52 | |
| * | |
| * @param Enemy AI | |
| * | |
| * @param AI Default Sight Range | |
| * @parent Enemy AI | |
| * @desc Default range for enemies to go after player, in pixels | |
| * Default: 240 | |
| * @type Number | |
| * @min 1 | |
| * @default 240 | |
| * | |
| * @param AI Action Wait | |
| * @parent Enemy AI | |
| * @desc How many frames to wait before running AI for next skill | |
| * Default: 30 | |
| * @min 1 | |
| * @default 30 | |
| * | |
| * @param AI Uses QSight | |
| * @parent Enemy AI | |
| * @desc Set to true or false if AI should use QSight | |
| * May decrease performance | |
| * @type Boolean | |
| * @default true | |
| * | |
| * @param AI uses QPathfind | |
| * @parent Enemy AI | |
| * @desc Set to true or false if AI should use QPathfind | |
| * May decrease performance | |
| * @type Boolean | |
| * @default true | |
| * | |
| * @param Default Skills | |
| * @type Struct<SkillKey>[] | |
| * @default [] | |
| * | |
| * @help | |
| * ============================================================================ | |
| * ## About | |
| * ============================================================================ | |
| * A collider based action battle system for QMovement. *Note* This is not | |
| * your simple rpg maker action battle system. Using this plugin you can | |
| * create more advance like action games. | |
| * | |
| * For a demo visit the steamwork shop or Github repo | |
| * - http://steamcommunity.com/sharedfiles/filedetails/?id=952886994 | |
| * - https://github.com/quxios/QMV-ABS-Demo | |
| * | |
| * **_Plugin files in the repo are always kept up to date_** | |
| * ============================================================================ | |
| * ## Is this for you? | |
| * ============================================================================ | |
| * First, this is a very complex action battle system. If you're looking for | |
| * something that you can spend less than an hour to set up then this plugin | |
| * is not for you. | |
| * | |
| * To make full use of this plugin you need to know how to properly use and | |
| * setup QMovement. If you don't know what that plugin is or what colliders | |
| * are then again, this plugin is not for you. | |
| * | |
| * There are a lot of actions for skill sequences so you can create some pretty | |
| * crazy skills. Learning how to use the actions may take awhile since there | |
| * are a lot of actions, and maybe more to come. | |
| * | |
| * Enemies have a very basic AI. If you want to create more AI styles, you | |
| * will need to know how to JS and create a plugin / extend this plugin. | |
| * ============================================================================ | |
| * ## Skill Keys | |
| * ============================================================================ | |
| * **Default Skill keys** | |
| * ---------------------------------------------------------------------------- | |
| * For the player to be able to use a skill from a hotkey, you will first need | |
| * to create a skill key in the plugin parameter `Default Skills`. | |
| * | |
| *  | |
| * | |
| * When creating a skill key you have 4 parameters: | |
| * | |
| * - #### Keyboard Input: | |
| * * The keyboard input that will trigger this skill, set this to `mouse1` for | |
| * left click, and `mouse2` for right click. | |
| * - #### Gamepad Input: | |
| * * The gamepad input that will trigger this skill. | |
| * - #### Rebind: | |
| * * If this is true, the skill that's assigned to this skill key can be | |
| * reassigned. | |
| * - #### Skill Id: | |
| * * The skill that this skill key will use when triggered. | |
| * | |
| * **_Note_** for input values those are the button values; `ok`, `cancel`, ect. Or | |
| * if you're using an input plugin, use their value. For example in QInput you can | |
| * use the `#A` for the a key or `#tab` for tab, ect. | |
| * | |
| * **_Note_** that rebind doesn't do much as this doesn't have a rebinding feature. | |
| * But the ground work is there so it can easily be created for an addon. | |
| * | |
| * **_Note_** that the `Skill Key Number` is the number next to the skill key you created. | |
| * `Skill Key Number` will be referenced later. | |
| * | |
| *  | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * **Class Skill keys** | |
| * ---------------------------------------------------------------------------- | |
| * You can change the players skill keys based on their class by adding the notetag: | |
| * ~~~ | |
| * <skillKeys> | |
| * [SKILL KEY NUMBER]: [SKILL ID] [REBIND?] | |
| * </skillKeys> | |
| * ~~~ | |
| * - #### SKILL KEY NUMBER: | |
| * * The skill key that you want to change | |
| * - #### SKILL ID: | |
| * * The skill to assign to this skill key number | |
| * - #### REBIND?: | |
| * * Set to true or false if this can be reassigned | |
| * | |
| * If the skill key that you are trying to change has its `Rebind` value set to false, | |
| * nothing will happen since it can't be reassigned. | |
| * | |
| * **_Important!_** make sure the skill key you are trying to set is created in the | |
| * plugin parameters `Default Skills`. If it's not, the game will have an error. | |
| * | |
| * Example: | |
| * ~~~ | |
| * <skillKeys> | |
| * 1: 2 | |
| * 3: 15 | |
| * 4: 16 | |
| * </skillKeys> | |
| * ~~~ | |
| * Class Skill keys will replace the default skill keys. So if you set up skill | |
| * keys 1 through 9 in the parameters and a class changes the skills for skill | |
| * keys 1, 3, 4. The over all skill keys will be, 1, 3, 4 from the class and | |
| * the rest are from the default values. | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * **Weapon Skill keys** | |
| * ---------------------------------------------------------------------------- | |
| * Weapons can also change the skill keys. For example you might want to change | |
| * the main attack to use a range skill if the player has a bow equipped! To do | |
| * this you use a similar tag as the class, but in the weapon | |
| * ~~~ | |
| * <skillKeys> | |
| * [SKILL KEY NUMBER]: [SKILL ID] | |
| * </skillKeys> | |
| * ~~~ | |
| * - #### SKILL KEY NUMBER: | |
| * * The skill key that you want to change | |
| * - #### SKILL ID: | |
| * * The skill to assign to this skill key number | |
| * | |
| * **_Important!_** make sure the skill key you are trying to set is created in the | |
| * plugin parameters `Default Skills`. If it's not, the game will have an error. | |
| * | |
| * Example: | |
| * ~~~ | |
| * <skillKeys> | |
| * 1: 3 | |
| * </skillKeys> | |
| * ~~~ | |
| * Weapon skill keys take top priority, so they will replace both class keys | |
| * and the default keys! This example will replace skill key 1 with the skill | |
| * id 3 | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * **Override Skill keys** | |
| * ---------------------------------------------------------------------------- | |
| * You can manually override a skill key with a plugin command. Override skill keys | |
| * take priority over weapon, class and default skill keys. | |
| * | |
| * Plugin command: | |
| * ~~~ | |
| * qabs override SKILLKEYNUMBER SKILLID | |
| * ~~~ | |
| * - #### SKILLKEYNUMBER: | |
| * * The skill key that you want to change | |
| * - #### SKILLID: | |
| * * The skill to assign to this skill key number. Set to -1 if you want to | |
| * remove this override | |
| * | |
| * **_Important!_** make sure the skill key you are trying to set is created in the | |
| * plugin parameters `Default Skills`. If it's not, the game will have an error. | |
| * | |
| * **_Note_** that the player still needs to know the skill to be able to use it. | |
| * Assigning it won't let him use it if he doesn't know it. | |
| * | |
| * Example: | |
| * ~~~ | |
| * qabs override 1 3 | |
| * ~~~ | |
| * Will override skill key 1 and assign the skill with id 3. To remove this | |
| * override later on use the plugin command: | |
| * ~~~ | |
| * qabs override 1 -1 | |
| * ~~~ | |
| * | |
| * ============================================================================ | |
| * ## Skills | |
| * ============================================================================ | |
| * **Skill Settings** | |
| * ---------------------------------------------------------------------------- | |
| * Each skill should have a skill settings tag. This tag can change the settings | |
| * for the skills cooldown, through, and other effects. The tag is: | |
| * ~~~ | |
| * <absSettings> | |
| * [SETTINGS]: [VALUE] | |
| * </absSettings> | |
| * ~~~ | |
| * Here's a list of all the settings: | |
| * ~~~ | |
| * collider: [SHAPE], [WIDTH], [HEIGHT] | |
| * collides: [STRING] | |
| * cooldown: [NUMBER] | |
| * infront: [TRUE or FALSE] | |
| * rotate: [TRUE or FALSE] | |
| * through: [0, 1, 2 or 3] | |
| * throughTerrain: [LIST OF TERRAINS IT CAN GO THROUGH] | |
| * groundtarget: [NUMBER] | |
| * selecttarget: [NUMBER] | |
| * ~~~ | |
| * - #### collider: | |
| * * Set this to the collider this skill will use. See QMovement help for details | |
| * on colliders. | |
| * * Default: The users collider | |
| * * Format is: `shape, width, height` | |
| * - #### collides: | |
| * * Set this to which collider type to check for against skill hit. If you | |
| * want to use a custom collider, use the `<colliders></colliders>` tag | |
| * * Default: collision | |
| * - #### cooldown: | |
| * * Set to the number of frames until you can use this skill again. | |
| * * Default: 0 | |
| * - #### infront: | |
| * * Set to true or false. When true, the collider will appear in front of the user. | |
| * When false the collider will be centered on the user. | |
| * * Default: false | |
| * - #### rotate: | |
| * * Set to true or false. When true, the collider will rotate based on the users | |
| * direction when skill is starting. Default: false | |
| * - #### through: | |
| * * Set to 0, 1, 2, or 3. Default: 0 | |
| * - 0: Goes through events and tiles | |
| * - 1: Goes through tiles but stops when it hits an event | |
| * - 2: Goes through events but stops when it hits a tile | |
| * - 3: Stops when it hits an event or tile | |
| * - #### throughTerrain: | |
| * * Set to a list of tile terrains it can go through, separate each terrain with a comma | |
| * - #### groundtarget: | |
| * * Set to the max distance, in pixels, for the ground target. If value is 0 ground | |
| * targeting will not be used. | |
| * * Default: 0 | |
| * - #### selecttarget: | |
| * * Set to the max distance, in pixels, for the select target. If value is 0 select | |
| * targeting will not be used. | |
| * * Default: 0 | |
| * ---------------------------------------------------------------------------- | |
| * **Skill Sequence** | |
| * ---------------------------------------------------------------------------- | |
| * When a skill is used, it's sequence will run. You will need to configure | |
| * a sequence to tell the skill what it should do or it won't do anything. | |
| * | |
| * This can be done with the notetag: | |
| * ~~~ | |
| * <absSequence> | |
| * [ACTION] | |
| * </absSequence> | |
| * ~~~ | |
| * There are a bunch of actions. Each action needs to be on a different line. | |
| * | |
| * Here's a list of all the actions: | |
| * ~~~ | |
| * user casting [TRUE or FALSE] | |
| * user lock | |
| * user unlock | |
| * user speed [INC or DEC] [VALUE] | |
| * user move [FORWARD or BACKWARD] [DIST] [WAIT? TRUE or FALSE] | |
| * user moveHere [WAIT? TRUE or FALSE] | |
| * user jump [FORWARD or BACKWARD] [DIST] [WAIT? TRUE or FALSE] | |
| * user jumpHere [WAIT? TRUE or FALSE] | |
| * user teleport | |
| * user setDirection [DIR] | |
| * user directionFix [TRUE or FALSE] | |
| * user pose [POSE NAME] [WAIT? TRUE or FALSE] | |
| * user forceSkill [SKILL ID] [ANGLE OFFSET IN DEGREES] | |
| * user animation [ANIMATION ID] | |
| * user qaudio [NAME] [QAUDIO OPTIONS] | |
| * store | |
| * move [FORWARD or BACKWARD] [DIST] [DURATION] [WAIT? TRUE or FALSE] | |
| * moveToStored [DURATION] [WAIT? TRUE or FALSE] | |
| * wave [FORWARD or BACKWARD] [AMPLITUDE] [HARM] [DIST] [DURATION] [WAIT? TRUE or FALSE] | |
| * waveToStored [AMPLITUDE] [HARM] [DURATION] [WAIT? TRUE or FALSE] | |
| * trigger | |
| * adjustAim | |
| * wait [DURATION] | |
| * picture [FILE NAME] [ROTATABLE? TRUE or FALSE] [BASE DIRECTION] | |
| * trail [FILE NAME] [ROTATABLE? TRUE or FALSE] [BASE DIRECTION] | |
| * collider [SHOW or HIDE] | |
| * animation [ANIMATION ID] | |
| * se [NAME] [VOLUME] [PITCH] [PAN] | |
| * qaudio [NAME] [QAUDIO OPTIONS] | |
| * forceSkill [SKILL ID] [ANGLE OFFSET IN DEGREES] | |
| * globalLock | |
| * globalUnlock | |
| * ~~~ | |
| * - #### user casting [TRUE or FALSE] | |
| * * Set the user casting state. If the user is casting, this skill can be | |
| * ended early if they get hit with a skill that has `user cancel` in it's | |
| * `absOnDamage` | |
| * | |
| * - #### user lock | |
| * * Locks the users movement. The user can't move or use any actions until | |
| * `user unlock` is called. | |
| * * `user unlock` is called automatically after every skill ends to ensure | |
| * the user can move again if the skill ended. | |
| * | |
| * - #### user unlock | |
| * * Unlocks the users movement. The user is unlocked if it was locked and can | |
| * move and use actions again. | |
| * * `user unlock` is called automatically after every skill ends to ensure | |
| * the user can move again if the skill ended. | |
| * | |
| * - #### user speed [INC or DEC] [VALUE] | |
| * * Changes the users move speed. | |
| * * INC or DEC: | |
| * - Set to `inc` to increase movespeed | |
| * - Set to `dec` to decrease move speed | |
| * * VALUE: Set to a number to inc or dec the movespeed by. | |
| * | |
| * - #### user move [FORWARD or BACKWARD] [DIST] [WAIT? TRUE or FALSE] | |
| * * The user will move forward or backwards by X distance. | |
| * * FORWARD or BACKWARD: | |
| * - Set to `forward` to move towards the direction the user is facing | |
| * - Set to `backward` to move towards the opposite direction the user is facing | |
| * * DIST: Set to the distance the user should move, in pixels | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the move | |
| * is complete before going to the next action | |
| * | |
| * - #### user moveHere [WAIT? TRUE or FALSE] | |
| * * The user will move to the skills current location | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the move | |
| * is complete before going to the next action | |
| * | |
| * - #### user jump [FORWARD or BACKWARD] [DIST] [WAIT? TRUE or FALSE] | |
| * * The user will jump forward or backwards by X distance. | |
| * * FORWARD or BACKWARD: | |
| * - Set to `forward` to jump towards the direction the user is facing | |
| * - Set to `backward` to jump towards the opposite direction the user is facing | |
| * * DIST: Set to the distance the user should jump, in pixels | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the jump | |
| * is complete before going to the next action | |
| * | |
| * - #### user jumpHere [WAIT? TRUE or FALSE] | |
| * * The user will jump to the skills current location | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the jump | |
| * is complete before going to the next action | |
| * | |
| * - #### user teleport | |
| * * The user will be placed at the skills current location. Similar to an | |
| * event transfer command. | |
| * | |
| * - #### user setDirection [DIR] | |
| * * Change the users direction | |
| * * DIR: Set to: 2, 4, 6 or 8. For diagonals; 1, 3, 7, or 9 | |
| * | |
| * - #### user directionFix [TRUE or FALSE] | |
| * * Sets the users direction fix. | |
| * * TRUE or FALSE: Set to `true` or `false`. When true the users direction can't change | |
| * | |
| * - #### user pose [POSE NAME] [WAIT? TRUE or FALSE] | |
| * * **_Requires QSprite plugin_** | |
| * * If the user is a QSprite, it will play the pose | |
| * * POSE NAME: The pose to play | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the pose | |
| * is done playing before going to the next action | |
| * | |
| * - #### user forceSkill [SKILL ID] [ANGLE OFFSET IN DEGREES] | |
| * * Forces the user to use a skill. | |
| * * SKILL ID: The ID of the skill to use | |
| * * ANGLE OFFSET: Lets you offset the angle, in degrees, that this skill be used | |
| * towards. This is optional and can be left out. | |
| * - Default: 0 | |
| * | |
| * - #### user animation [ANIMATION ID] | |
| * * Plays an animation on the user | |
| * * ANIMATION ID: The ID of the animation to play | |
| * | |
| * - #### user qaudio [NAME] [QAUDIO OPTIONS] | |
| * * **_Requires QAudio plugin_** | |
| * * Binds a QAudio to the user | |
| * * NAME: The name of the audio file to use | |
| * * QAUDIO OPTIONS: any of the QAudio options besides; xX, yY, bindToCHARAID. | |
| * View QAudio help for more details | |
| * | |
| * - #### store | |
| * * Stores the skills current location. This location value is used when | |
| * the actions `moveToStored` or 'waveToStored' are used. | |
| * | |
| * - #### move [FORWARD or BACKWARD] [DIST] [DURATION] [WAIT? TRUE or FALSE] | |
| * * Moves the skill forward or backwards by X dist in Y frames | |
| * * FORWARD or BACKWARD: | |
| * - Set to `forward` to move towards the direction the skill is currently moving | |
| * - Set to `backward` to move towards the opposite direction the skill is current moving | |
| * * DIST: The distance you want the skill to move, in pixels. | |
| * * DURATION: How long should it take to complete this move, in frames. | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the skill | |
| * is done moving before going to the next action | |
| * | |
| * - #### moveToStored [DURATION] [WAIT? TRUE or FALSE] | |
| * * Moves the skill to the stored position | |
| * * DURATION: How long should it take to complete this move, in frames. | |
| * * WAIT: Set to `true` or `false`. If true the sequencer will wait until the skill | |
| * is done moving before going to the next action | |
| * | |
| * - #### wave [FORWARD or BACKWARD] [AMPLITUDE] [HARM] [DIST] [DURATION] [WAIT? TRUE or FALSE] | |
| * | |
| * - #### waveToStored [AMPLITUDE] [HARM] [DURATION] [WAIT? TRUE or FALSE] | |
| * | |
| * - #### trigger | |
| * * Activates the skill at it's current location | |
| * | |
| * - #### adjustAim | |
| * * Recalculates the direction the skill should move. This is only works | |
| * when the skill is used from an enemy. | |
| * | |
| * - #### wait [DURATION] | |
| * * The sequencer will wait before moving to the next action | |
| * * DURATION: How long should the wait last, in frames | |
| * | |
| * - #### picture [FILE NAME] [ROTATABLE? TRUE or FALSE] [BASE DIRECTION] | |
| * * Bind a picture to the skill | |
| * * FILE NAME: The file name of the picture. Should be located in the | |
| * Pictures folder. For an animated picture it should have the format: | |
| * - %[COLS-SPEED] | |
| * - COLS: The number of slices in the picture | |
| * - SPEED: The time to wait between frames | |
| * * ROTATABLE: Set to `true` or `false`. If true the picture will rotate based | |
| * on the direction the skill is moving | |
| * * BASE DIRECTION: The direction the skill is facing by default. The directions | |
| * should be 2, 4, 6, or 8 | |
| * | |
| * - #### trail [FILE NAME] [ROTATABLE? TRUE or FALSE] [BASE DIRECTION] | |
| * * Binds a picture that stretches from the user to the skills position | |
| * * FILE NAME: The file name of the picture. Should be located in the | |
| * Pictures folder. | |
| * * ROTATABLE: Set to `true` or `false`. If true the picture will rotate based | |
| * on the direction the skill is moving | |
| * * BASE DIRECTION: The direction the skill is facing by default. The directions | |
| * should be 2, 4, 6, or 8 | |
| * | |
| * - #### collider [SHOW or HIDE] | |
| * * Shows the skills collider | |
| * * SHOW or HIDE: | |
| * - Set to `show` to show the skills collider | |
| * - Set to `hide` to hide the skills collider | |
| * | |
| * - #### animation [ANIMATION ID] | |
| * * Play an animation at the skills current location | |
| * * ANIMATION ID: The ID of the animation to play | |
| * | |
| * - #### se [NAME] [VOLUME] [PITCH] [PAN] | |
| * * Play an se | |
| * * NAME: The name of the SE to play | |
| * * VOLUME: The volume of the SE, default: 90 | |
| * * PITCH: The pitch of the SE, default: 100 | |
| * * PAN: The pan of the SE, default: 0 | |
| * | |
| * - #### qaudio [NAME] [QAUDIO OPTIONS] | |
| * * Play a qAudio at the skills location | |
| * * NAME: The name of the audio file | |
| * * QAUDIO OPTIONS: Visit the QAudio help for information. The options | |
| * are the same from the plugin commands. x, y, bindTo options will not work. | |
| * | |
| * - #### forceSkill [SKILL ID] [ANGLE OFFSET] | |
| * * Force a skill at the skills current location | |
| * * SKILL ID: The ID of the skill to use | |
| * * ANGLE OFFSET: Lets you offset the angle, in degrees, this skill be used towards. | |
| * This is optional and can be left out. | |
| * | |
| * - #### globalLock | |
| * * Locks all characters movement | |
| * | |
| * - #### globalUnlock | |
| * * Unlocks all characters movement | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * **Skill On Damage** | |
| * ---------------------------------------------------------------------------- | |
| * Whenever a skill hits a target you can run another sequence. This is done | |
| * by using the notetag: | |
| * ~~~ | |
| * <absOnDamage> | |
| * [ACTION] | |
| * </absOnDamage> | |
| * ~~~ | |
| * There are a few actions you can add here: | |
| * ~~~ | |
| * target move [TOWARDS or AWAY or INTO] [DIST] | |
| * target jump [TOWARDS or AWAY or INTO] [DIST] | |
| * target pose [POSE] | |
| * target cancel | |
| * target qaudio [NAME] [QAUDIO OPTIONS] | |
| * user forceSkill [SKILL ID] [ANGLE OFFSET IN DEGREES] | |
| * animationTarget [0 or 1] | |
| * ~~~ | |
| * - #### target move [TOWARDS or AWAY or INTO] [DIST] | |
| * * The target will move X distance. | |
| * * TOWARDS or AWAY or INTO: | |
| * - Set to `towards` to move towards the user of the skill | |
| * - Set to `away` to move away from the user of the skill | |
| * - Set to `into` to move towards the skill center | |
| * * DIST: Set to the distance the target should move, in pixels | |
| * | |
| * - #### target jump [TOWARDS or AWAY or INTO] [DIST] | |
| * * The target will jump X distance. | |
| * * TOWARDS or AWAY or INTO: | |
| * - Set to `towards` to jump towards the user of the skill | |
| * - Set to `away` to jump away from the user of the skill | |
| * - Set to `into` to jump towards the skill position | |
| * * DIST: Set to the distance the target should jump, in pixels | |
| * | |
| * - #### target pose [POSE] | |
| * * **_Requires QSprite plugin_** | |
| * * If the target is a QSprite, it will play the pose | |
| * * POSE NAME: The pose to play | |
| * | |
| * - #### target cancel | |
| * * If the target is `casting`, it will cancel the skill | |
| * | |
| * - #### target qaudio [NAME] [QAUDIO OPTIONS] | |
| * * **_Requires QAudio plugin_** | |
| * * Binds a QAudio to the target | |
| * * NAME: The name of the audio file to use | |
| * * QAUDIO OPTIONS: any of the QAudio options besides; xX, yY, bindToCHARAID. | |
| * View QAudio help for more details | |
| * | |
| * - #### user forceSkill [SKILL ID] [ANGLE OFFSET IN DEGREES] | |
| * * Forces the user to use a skill. | |
| * * SKILL ID: The ID of the skill to use | |
| * * ANGLE OFFSET: Lets you offset the angle, in degrees, that this skill be used | |
| * towards. This is optional and can be left out. | |
| * - Default: 0 | |
| * | |
| * - #### animationTarget [0 or 1] | |
| * * Sets where to play the skill animation | |
| * * 0 or 1: | |
| * - When 0, the animation will play at the current location. | |
| * Animation will only play once if the skill hit multiple targets | |
| * - When 1, the animation will play on the target | |
| * Animation will play on all targets it hits | |
| * | |
| * ============================================================================ | |
| * ## Enemies | |
| * ============================================================================ | |
| * **Event** | |
| * ---------------------------------------------------------------------------- | |
| * To mark an event as an enemy, add the notetag to the event | |
| * ~~~ | |
| * <enemy:X> | |
| * ~~~ | |
| * Where X is the ID of the enemy in the database. | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * **Enemy Database** | |
| * ---------------------------------------------------------------------------- | |
| * #### To set the enemies respawn time | |
| * ~~~ | |
| * <respawn:X> | |
| * ~~~ | |
| * - X: How long until it respawns, in frames. | |
| * | |
| * #### To change the team of the enemy | |
| * ~~~ | |
| * <team:X> | |
| * ~~~ | |
| * Set X to the team number | |
| * - 0: Neutral | |
| * - 1: Player team | |
| * - 2: Enemy team | |
| * - 3+ can also be used | |
| * | |
| * **_Note_** teams don't do much because there is no team based AI | |
| * | |
| * #### To set an Enemies AI type | |
| * ~~~ | |
| * <AIType:TYPE> | |
| * ~~~ | |
| * - TYPE: The AI type, set this to `none` to disable AI. | |
| * | |
| * **_Note_** There's only 1 type of AI, so for now that AI is only to disable AI | |
| * | |
| * #### To set it's AI range | |
| * ~~~ | |
| * <range:X> | |
| * ~~~ | |
| * - X: The range in pixels | |
| * | |
| * #### To disable damage popups on this enemy | |
| * ~~~ | |
| * <noPopup> | |
| * ~~~ | |
| * | |
| * #### To add an offset to the popup's y use: | |
| * ~~~ | |
| * <popupOY:Y> | |
| * ~~~ | |
| * - Y: The y offset in pixels, can be negative | |
| * | |
| * #### To keep the event around after it dies | |
| * ~~~ | |
| * <dontErase> | |
| * ~~~ | |
| * | |
| * #### To run some JS when the enemy dies | |
| * ~~~ | |
| * <onDeath> | |
| * javascript code | |
| * </onDeath> | |
| * ~~~ | |
| * | |
| * #### To auto gain the enemies loot | |
| * ~~~ | |
| * <autoLoot> | |
| * ~~~ | |
| * | |
| * ============================================================================ | |
| * ## Disabling QABS | |
| * ============================================================================ | |
| * You can disable the QABS or disable certain events with a plugin command. | |
| * | |
| * #### To disable the QABS for everything use the plugin command | |
| * ~~~ | |
| * qabs disable | |
| * ~~~ | |
| * | |
| * #### To re-enable use the plugin command: | |
| * ~~~ | |
| * qabs enable | |
| * ~~~ | |
| * | |
| * #### To disable certain event(s) use the plugin command | |
| * ~~~ | |
| * qabs disable [LIST OF CHARAIDS TO DISABLE] | |
| * ~~~ | |
| * - CHARAID: The character identifier. | |
| * * For events: EVENTID, eEVENTID, eventEVENTID or this for the event that | |
| * called this (replace EVENTID with a number) | |
| * | |
| * Where each CHARAID is separated with a space. CHARAID can only be for events. | |
| * | |
| * #### Example: | |
| * ~~~ | |
| * qabs disable event1 e2 4 | |
| * ~~~ | |
| * Will disable events 1, 2 and 4. Used different types of CHARAIDs as an example | |
| * but you can use whichever one you like | |
| * | |
| * #### To re-enable event(s) use the plugin command | |
| * ~~~ | |
| * qabs enable [LIST OF CHARAIDS TO DISABLE] | |
| * ~~~ | |
| * | |
| * **_Note_** that disabling ABS doesn't remove it from the event, it just "pauses" | |
| * it until it's re-enabled. | |
| * | |
| * ============================================================================ | |
| * ## States | |
| * ============================================================================ | |
| * To have a state affect the characters move speed use: | |
| * ~~~ | |
| * <moveSpeed:X> | |
| * ~~~ | |
| * Set X to the value to modify the move speed by. Can be negative. | |
| * | |
| * To disable a characters actions, use the following notetag. When disabled | |
| * the character can't use any skills until the state is removed. | |
| * ~~~ | |
| * <stun> | |
| * | |
| * ~~~ | |
| * ============================================================================ | |
| * ## Popups | |
| * ============================================================================ | |
| * All of the popups are powered with the QPopup plugin. If you want to change | |
| * any styles of the popups you can edit their presets in that plugins parameters | |
| * or using the plugin commands from the QPopup plugin. | |
| * | |
| * The following are the qPopup presets this ABS uses: | |
| * - QABS-LEVEL | |
| * - QABS-EXP | |
| * - QABS-ITEM | |
| * - QABS-MISSED | |
| * - QABS-DMG | |
| * - QABS-DMG-CRIT | |
| * - QABS-HEAL | |
| * - QABS-HEAL-CRIT | |
| * - QABS-MP | |
| * - QABS-MP-CRIT | |
| * | |
| * ============================================================================ | |
| * ## Showcase | |
| * ============================================================================ | |
| * This section is for user created stuff. If you created a video, game, tutorial, | |
| * or an addon for QABS feel free to send me a link and I'll showcase it here! | |
| * | |
| * ============================================================================ | |
| * ## Links | |
| * ============================================================================ | |
| * Formated Help: | |
| * | |
| * https://quxios.github.io/plugins/QABS | |
| * | |
| * RPGMakerWebs: | |
| * | |
| * http://forums.rpgmakerweb.com/index.php?threads/qplugins.73023/ | |
| * | |
| * Terms of use: | |
| * | |
| * https://github.com/quxios/QMV-Master-Demo/blob/master/readme.md | |
| * | |
| * Like my plugins? Support me on Patreon! | |
| * | |
| * https://www.patreon.com/quxios | |
| * | |
| * @tags QM-Addon, ABS, Battle | |
| */ | |
| /*~struct~SkillKey: | |
| * @param Keyboard Input | |
| * @desc Set to which keyboard input to use for this skill | |
| * @default | |
| * | |
| * @param Gamepad Input | |
| * @desc Set to which gamepad input to use for this skill | |
| * @default | |
| * | |
| * @param Rebind | |
| * @desc Can this skill be reassigned? | |
| * @type Boolean | |
| * @on Yes | |
| * @off No | |
| * @default true | |
| * | |
| * @param Skill Id | |
| * @desc Which skill does this skill use | |
| * @type skill | |
| * @default | |
| */ | |
| //============================================================================= | |
| //============================================================================= | |
| // QABS Static Class | |
| function QABS() { | |
| throw new Error('This is a static class'); | |
| } | |
| (function() { | |
| var _PARAMS = QPlus.getParams('<QABS>', { | |
| 'Default Skills': [] | |
| }); | |
| QABS.quickTarget = _PARAMS['Quick Target']; | |
| QABS.lockTargeting = _PARAMS['Lock when Targeting']; | |
| QABS.towardsMouse = _PARAMS['Aim with Mouse']; | |
| QABS.towardsAnalog = _PARAMS['Aim with Analog'] | |
| QABS.radianAtks = QMovement.offGrid; | |
| QABS.lootDecay = _PARAMS['Loot Decay']; | |
| QABS.aoeLoot = _PARAMS['AoE Loot']; | |
| QABS.lootTrigger = _PARAMS['Loot Touch Trigger'] ? 2 : 0; | |
| QABS.goldIcon = _PARAMS['Gold Icon']; | |
| QABS.levelAni = _PARAMS['Level Animation']; | |
| QABS.showDmg = _PARAMS['Show Damage']; | |
| QABS.mrst = _PARAMS['Move Resistance Rate Stat']; | |
| QABS.aiLength = _PARAMS['AI Default Sight Range']; | |
| QABS.aiWait = _PARAMS['AI Action Wait']; | |
| QABS.aiSight = _PARAMS['AI Uses QSight']; | |
| QABS.aiPathfind = _PARAMS['AI uses QPathfind']; | |
| QABS.getDefaultSkillKeys = function() { | |
| var obj = {}; | |
| var skills = _PARAMS['Default Skills']; | |
| for (var i = 0; i < skills.length; i++) { | |
| var skill = skills[i]; | |
| obj[i + 1] = { | |
| input: [skill['Keyboard Input'].trim(), skill['Gamepad Input'].trim()], | |
| rebind: skill.Rebind, | |
| skillId: skill['Skill Id'] | |
| } | |
| } | |
| return obj; | |
| }; | |
| QABS.skillKey = QABS.getDefaultSkillKeys(); | |
| QABS.stringToSkillKeyObj = function(string) { | |
| var obj = QPlus.stringToObj(string); | |
| for (var key in obj) { | |
| var data = String(obj[key]).split(' ').filter(function(i) { | |
| return i !== ''; | |
| }).map(function(i) { | |
| return i.trim(); | |
| }); | |
| var skillId = Number(data[0]) || 0; | |
| var rebind = data[1] === 'true'; | |
| var msg; | |
| if (skillId && !$dataSkills[skillId]) { | |
| msg = 'ERROR: Attempted to apply a Skill Id that does not exist in database.\n'; | |
| msg += 'Skill Key Number: ' + key; | |
| alert(msg); | |
| delete obj[key]; | |
| continue; | |
| } | |
| if (!QABS.skillKey[key]) { | |
| msg = 'ERROR: Attempted to apply a skill key that has not been setup '; | |
| msg += 'in the plugin parameters.\n'; | |
| msg += 'Skill Key Number: ' + key; | |
| alert(msg); | |
| delete obj[key]; | |
| continue; | |
| } | |
| obj[key] = { | |
| input: QABS.skillKey[key].input.clone(), | |
| skillId: skillId, | |
| rebind: rebind | |
| } | |
| } | |
| return obj; | |
| }; | |
| QABS._skillSettings = {}; | |
| QABS.getSkillSettings = function(skill) { | |
| if (!this._skillSettings.hasOwnProperty(skill.id)) { | |
| var settings = skill.qmeta.absSettings; | |
| this._skillSettings[skill.id] = { | |
| cooldown: 0, | |
| through: 0, | |
| groundTarget: false, | |
| selectTarget: false, | |
| throughTerrain: [] | |
| } | |
| if (settings) { | |
| // TODO change this, hate how it looks | |
| settings = QPlus.stringToObj(settings); | |
| Object.assign(settings, { | |
| cooldown: Number(settings.cooldown) || 0, | |
| through: Number(settings.through) || 0, | |
| groundTarget: settings.groundtarget && !settings.selecttarget, | |
| selectTarget: !settings.groundtarget && settings.selecttarget, | |
| throughTerrain: settings.throughTerrain || '' | |
| }); | |
| if (settings.throughTerrain.constructor !== Array) { | |
| settings.throughTerrain = [settings.throughTerrain]; | |
| } | |
| if (settings.groundtarget) var range = Number(settings.groundtarget); | |
| if (settings.selecttarget) var range = Number(settings.selecttarget); | |
| settings.range = range || 0; | |
| this._skillSettings[skill.id] = settings; | |
| } | |
| } | |
| return this._skillSettings[skill.id]; | |
| }; | |
| QABS._skillSequence = {}; | |
| QABS.getSkillSequence = function(skill) { | |
| if (!this._skillSequence.hasOwnProperty(skill.id)) { | |
| var settings = skill.qmeta.absSequence; | |
| this._skillSequence[skill.id] = []; | |
| if (settings) { | |
| settings = settings.split('\n'); | |
| var actions = []; | |
| for (var i = 0; i < settings.length; i++) { | |
| if (settings[i].trim() !== '') { | |
| actions.push(settings[i].trim()); | |
| } | |
| } | |
| actions.push('collider hide'); | |
| actions.push('user unlock'); | |
| actions.push('user casting false'); | |
| this._skillSequence[skill.id] = actions; | |
| } | |
| } | |
| return this._skillSequence[skill.id].clone(); | |
| }; | |
| QABS._skillOnDamage = {}; | |
| QABS.getSkillOnDamage = function(skill) { | |
| if (!this._skillOnDamage.hasOwnProperty(skill.id)) { | |
| var settings = skill.qmeta.absOnDamage; | |
| var actions = []; | |
| actions.push('animation 0'); | |
| if (settings) { | |
| settings = settings.split('\n'); | |
| for (var i = 0; i < settings.length; i++) { | |
| if (settings[i].trim() !== '') { | |
| actions.push(settings[i].trim()); | |
| } | |
| } | |
| } | |
| this._skillOnDamage[skill.id] = actions; | |
| } | |
| return this._skillOnDamage[skill.id].clone(); | |
| }; | |
| QABS._weaponSkills = {}; | |
| QABS.weaponSkills = function(id) { | |
| if (!this._weaponSkills[id]) { | |
| var skills = $dataWeapons[id].qmeta.skillKeys || $dataWeapons[id].qmeta.absSkills; | |
| this._weaponSkills[id] = {}; | |
| if (skills) { | |
| this._weaponSkills[id] = this.stringToSkillKeyObj(skills); | |
| } | |
| } | |
| return this._weaponSkills[id]; | |
| }; | |
| QABS._aiRange = {}; | |
| QABS.getAIRange = function(skill) { | |
| if (!this._aiRange.hasOwnProperty(skill.id)) { | |
| this._aiRange[skill.id] = this.calcAIRange(skill); | |
| } | |
| return this._aiRange[skill.id]; | |
| }; | |
| QABS.calcAIRange = function(skill) { | |
| var settings = this.getSkillSettings(skill); | |
| if (settings.range) { | |
| return settings.range; | |
| } | |
| var actions = this.getSkillSequence(skill); | |
| var currDist = 0; | |
| var stored = 0; | |
| var maxDist = 0; | |
| actions.forEach(function(action) { | |
| var move = /^(?:move|wave) (.*)/i.exec(action); | |
| if (move) { | |
| move = move[1].trim().split(' '); | |
| if (move[0] === 'forward') { | |
| currDist += Number(move[1]) || 0; | |
| } else { | |
| currDist -= Number(move[1]) || 0; | |
| } | |
| maxDist = Math.max(currDist, maxDist); | |
| } | |
| var store = /^store/i.exec(action); | |
| if (store) { | |
| stored = currDist; | |
| } | |
| var toStore = /^(?:move|wave)ToStored/i.exec(action); | |
| if (toStore) { | |
| currDist = stored; | |
| maxDist = Math.max(currDist, maxDist); | |
| } | |
| var userForce = /^user forceSkill (.*)/i.exec(action); | |
| if (userForce) { | |
| userForce = Number(userForce[1].trim().split(' ')[0]); | |
| var dist2 = QABS.getAIRange($dataSkills[userForce]); | |
| maxDist = Math.max(dist2, maxDist); | |
| } | |
| var skillForce = /^forceSkill (.*)/i.exec(action); | |
| if (skillForce) { | |
| skillForce = Number(skillForce[1].trim().split(' ')[0]); | |
| var dist3 = QABS.getAIRange($dataSkills[skillForce]); | |
| dist3 += currDist; | |
| maxDist = Math.max(dist3, maxDist); | |
| } | |
| }); | |
| return maxDist; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // QABS Manager Static Class | |
| function QABSManager() { | |
| throw new Error('This is a static class'); | |
| } | |
| (function() { | |
| QABSManager.clear = function() { | |
| this._animations = []; | |
| this._pictures = []; | |
| this._mapId = $gameMap._mapId; | |
| }; | |
| QABSManager.getTargets = function(item, self) { | |
| return ColliderManager.getCharactersNear(item.collider, function(chara) { | |
| if (typeof chara.battler !== 'function' || !chara.battler()) return false; | |
| if (chara.battler().isDeathStateAffected()) return false; | |
| if (chara.isFriendly(self) && [1, 2, 3, 4, 5, 6].contains(item.data.scope)) { | |
| return false; | |
| } | |
| if (!chara.isFriendly(self) && [7, 8, 9, 10].contains(item.data.scope)) { | |
| return false; | |
| } | |
| if (item.data.scope === 11 && chara !== self) return false; | |
| var type = item.settings.collides || 'collision'; | |
| return item.collider.intersects(chara.collider(type)); | |
| }); | |
| }; | |
| QABSManager.bestAction = function(userId) { | |
| var chara = QPlus.getCharacter(userId); | |
| if (!chara.battler()) return null; | |
| var targets; | |
| var skills = chara.usableSkills().filter(function(skillId) { | |
| if (!skillId) return false; | |
| targets = QABSManager.skillWillHit(skillId, userId); | |
| if (targets && targets.length > 0) { | |
| return true; | |
| } | |
| return false; | |
| }) | |
| if (skills.length === 0) return null; | |
| return skills[Math.floor(Math.random() * skills.length)]; | |
| }; | |
| QABSManager.skillWillHit = function(skillId, userId) { | |
| var skill = $dataSkills[skillId]; | |
| var chara = QPlus.getCharacter(userId); | |
| var settings = QABS.getSkillSettings(skill); | |
| var collider = chara.collider('collision'); | |
| var skillCollider = chara.makeSkillCollider(settings); | |
| var w1 = settings.collider[1] || chara.collider('collision').width; | |
| var h1 = settings.collider[2] || chara.collider('collision').height; | |
| var x1 = chara.cx() - w1 / 2; | |
| var y1 = chara.cy() - h1 / 2; | |
| var targets = []; | |
| var aiRange = QABS.getAIRange(skill); | |
| if (aiRange > 0) { | |
| var r1 = aiRange * 2; | |
| range = new Circle_Collider(w1 + r1, h1 + r1); | |
| range.moveTo(x1 - r1 / 2, y1 - r1 / 2); | |
| targets = this.getTargets({ | |
| settings: settings, | |
| data: skill, | |
| collider: range | |
| }, chara); | |
| ColliderManager.draw(range, QABS.aiWait / 2); | |
| } else { | |
| targets = this.getTargets({ | |
| settings: settings, | |
| data: skill, | |
| collider: skillCollider | |
| }, chara); | |
| ColliderManager.draw(skillCollider, QABS.aiWait / 2); | |
| } | |
| return targets; | |
| }; | |
| QABSManager.startAction = function(self, targets, item) { | |
| if (!item.animationTarget || targets.length === 0) { | |
| this.startAnimation(item.data.animationId, item.collider.center.x, item.collider.center.y); | |
| } | |
| self._agro.placeInCombat(); | |
| var action = new Game_ABSAction(self.battler(), true); | |
| action.setSkill(item.data.id); | |
| for (var i = 0; i < targets.length; i++) { | |
| if (item.animationTarget === 1) { | |
| var x = targets[i].cx(); | |
| var y = targets[i].cy(); | |
| this.startAnimation(item.data.animationId, x, y); | |
| } | |
| action.absApply(targets[i].battler()); | |
| targets[i].addAgro(self.charaId(), item.data); | |
| } | |
| action.applyGlobal(); | |
| }; | |
| QABSManager.startPopup = function(type, options) { | |
| if (!Imported.QPopup) return; | |
| var preset = $gameSystem.qPopupPreset(type); | |
| Object.assign(options, { | |
| style: preset.style, | |
| transitions: preset.transitions | |
| }) | |
| if (!options.duration) options.duration = 80; | |
| if (!options.transitions) { | |
| var start = options.duration - 30; | |
| var end = start + 30; | |
| var fadeout = start + ' 30 fadeout'; | |
| var slideup = '0 ' + end + ' slideup 24'; | |
| options.transitions = [fadeout, slideup]; | |
| } | |
| return QPopup.start(options); | |
| }; | |
| QABSManager._animations = []; | |
| QABSManager.startAnimation = function(id, x, y) { | |
| var scene = SceneManager._scene; | |
| if (scene.constructor !== Scene_Map) return; | |
| if (id < 0) id = 1; | |
| if (id <= 0) return; | |
| var animation = $dataAnimations[id]; | |
| var temp = new Sprite_MapAnimation(animation); | |
| temp.move(x, y); | |
| this._animations.push(temp); | |
| scene._spriteset._tilemap.addChild(temp); | |
| }; | |
| QABSManager.removeAnimation = function(sprite) { | |
| var scene = SceneManager._scene; | |
| if (scene.constructor !== Scene_Map) return; | |
| var i = this._animations.indexOf(sprite); | |
| if (i < 0) return; | |
| this._animations[i] = null; | |
| this._animations.splice(i, 1); | |
| scene._spriteset._tilemap.removeChild(sprite); | |
| }; | |
| QABSManager._pictures = []; | |
| QABSManager.addPicture = function(sprite) { | |
| var scene = SceneManager._scene; | |
| if (scene.constructor !== Scene_Map) return; | |
| this._pictures.push(sprite); | |
| scene._spriteset._tilemap.addChild(sprite); | |
| }; | |
| QABSManager.removePicture = function(sprite) { | |
| var scene = SceneManager._scene; | |
| if (scene.constructor !== Scene_Map) return; | |
| var i = this._pictures.indexOf(sprite); | |
| if (i < 0) return; | |
| this._pictures[i] = null; | |
| this._pictures.splice(i, 1); | |
| scene._spriteset._tilemap.removeChild(sprite); | |
| }; | |
| QABSManager.createItem = function(x, y, itemId, type) { | |
| var loot = new Game_Loot(x, y); | |
| var data = $dataItems; | |
| if (type === 1) data = $dataWeapons; | |
| if (type === 2) data = $dataArmors; | |
| loot.setItem(data[itemId]); | |
| return loot; | |
| }; | |
| QABSManager.createGold = function(x, y, value) { | |
| var loot = new Game_Loot(x, y); | |
| loot.setGold(value); | |
| return loot; | |
| }; | |
| QABSManager._freeEventIds = []; | |
| QABSManager.addEvent = function(event) { | |
| var id = this._freeEventIds.unshift() || 0; | |
| if (!id || $gameMap._events[id]) { | |
| id = $gameMap._events.length; | |
| } | |
| event._eventId = id; | |
| $gameMap._events[id] = event; | |
| if (!event._noSprite) { | |
| var scene = SceneManager._scene; | |
| if (scene === Scene_Map) { | |
| var spriteset = scene._spriteset; | |
| var sprite = new Sprite_Character(event); | |
| spriteset._characterSprites.push(sprite); | |
| spriteset._tilemap.addChild(sprite); | |
| } | |
| } | |
| }; | |
| QABSManager.removeEvent = function(event) { | |
| var id = event._eventId; | |
| if (!id || !$gameMap._events[id]) return; | |
| event.removeColliders(); | |
| if (!event._noSprite) { | |
| var scene = SceneManager._scene; | |
| if (scene === Scene_Map) { | |
| var spriteset = scene._spriteset; | |
| var spriteCharas = spriteset._characterSprites; | |
| for (var i = 0; i < spriteCharas.length; i++) { | |
| if (spriteCharas[i] && spriteCharas[i]._character === event) { | |
| spriteset._tilemap.removeChild(spriteCharas[i]); | |
| spriteCharas.splice(i, 1); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| $gameMap._events[id].clearABS(); | |
| $gameMap._events[id] = null; | |
| this._freeEventIds.push(id); | |
| }; | |
| QABSManager.preloadSkill = function(skill) { | |
| var aniId = skill.animationId; | |
| aniId = aniId < 0 ? 1 : aniId; | |
| var ani = $dataAnimations[aniId]; | |
| if (ani) { | |
| ImageManager.loadAnimation(ani.animation1Name, ani.animation1Hue); | |
| ImageManager.loadAnimation(ani.animation2Name, ani.animation2Hue); | |
| } | |
| var sequence = QABS.getSkillSequence(skill); | |
| for (var i = 0; i < sequence.length; i++) { | |
| var action = sequence[i]; | |
| var ani = /^animation (.*)/i.exec(action); | |
| var pic = /^picture (.*)/i.exec(action); | |
| var forced = /forceSkill (\d+)/i.exec(action); | |
| if (ani) { | |
| ani = ani[1].trim(); | |
| ani = $dataAnimations[ani]; | |
| if (ani) { | |
| ImageManager.loadAnimation(ani.animation1Name, ani.animation1Hue); | |
| ImageManager.loadAnimation(ani.animation2Name, ani.animation2Hue); | |
| } | |
| } | |
| if (pic) { | |
| pic = QPlus.makeArgs(pic[1])[0]; | |
| ImageManager.loadPicture(pic); | |
| } | |
| if (forced) { | |
| var forcedSkill = $dataSkills[Number(forced[1])]; | |
| if (forcedSkill) this.preloadSkill(forcedSkill); | |
| } | |
| } | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Skill_Sequencer | |
| function Skill_Sequencer() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Skill_Sequencer.prototype.initialize = function(character, skill) { | |
| this._character = character; | |
| this._skill = skill; | |
| }; | |
| Skill_Sequencer.prototype.startAction = function(action) { | |
| var cmd = action.shift().toLowerCase(); | |
| switch (cmd) { | |
| case 'user': { | |
| this.startUserAction(action); | |
| break; | |
| } | |
| case 'store': { | |
| this.actionStore(); | |
| break; | |
| } | |
| case 'move': { | |
| this.actionMove(action); | |
| break; | |
| } | |
| case 'movetostored': { | |
| this.actionMoveToStored(action); | |
| break; | |
| } | |
| case 'wave': { | |
| this.actionWave(action); | |
| break; | |
| } | |
| case 'wavetostored': { | |
| this.actionWaveToStored(action); | |
| break; | |
| } | |
| case 'damage': | |
| case 'trigger': { | |
| this.actionTrigger(action); | |
| break; | |
| } | |
| case 'adjustaim': { | |
| this.actionAdjustAim(action); | |
| break; | |
| } | |
| case 'wait': { | |
| this.actionWait(action); | |
| break; | |
| } | |
| case 'picture': { | |
| this.actionPicture(action); | |
| break; | |
| } | |
| case 'trail': { | |
| this.actionTrail(action); | |
| break; | |
| } | |
| case 'collider': { | |
| this.actionCollider(action); | |
| break; | |
| } | |
| case 'animation': { | |
| this.actionAnimation(action); | |
| break; | |
| } | |
| case 'se': { | |
| this.actionSE(action); | |
| break; | |
| } | |
| case 'qaudio': { | |
| this.actionQAudio(action); | |
| break; | |
| } | |
| case 'forceskill': { | |
| this.actionForceSkill(action); | |
| break; | |
| } | |
| case 'globallock': { | |
| $gameMap.globalLock(null, 0, 1); | |
| break; | |
| } | |
| case 'globalunlock': { | |
| $gameMap.globalUnlock(null, 0, 0); | |
| break; | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.startUserAction = function(action) { | |
| var cmd = action.shift().toLowerCase(); | |
| switch (cmd) { | |
| case 'casting': { | |
| this.userCasting(action); | |
| break; | |
| } | |
| case 'lock': { | |
| this.userLock(); | |
| break; | |
| } | |
| case 'unlock': { | |
| this.userUnlock(); | |
| break; | |
| } | |
| case 'speed': { | |
| this.userSpeed(action); | |
| break; | |
| } | |
| case 'move': { | |
| this.userMove(action); | |
| break; | |
| } | |
| case 'movehere': { | |
| this.userMoveHere(action); | |
| break; | |
| } | |
| case 'jump': { | |
| this.userJump(action); | |
| break; | |
| } | |
| case 'jumphere': { | |
| this.userJumpHere(action); | |
| break; | |
| } | |
| case 'teleport': { | |
| this.userTeleport(); | |
| break; | |
| } | |
| case 'setdirection': { | |
| this.userSetDirection(action); | |
| break; | |
| } | |
| case 'directionfix': { | |
| this.userDirectionFix(action); | |
| break; | |
| } | |
| case 'pose': { | |
| this.userPose(action); | |
| break; | |
| } | |
| case 'forceskill': { | |
| this.userForceSkill(action); | |
| break; | |
| } | |
| case 'animation': { | |
| this.userAnimation(action); | |
| break; | |
| } | |
| case 'qaudio': { | |
| this.userQAudio(action); | |
| break; | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.startOnDamageAction = function(action, targets) { | |
| var cmd = action.shift().toLowerCase(); | |
| switch (cmd) { | |
| case 'target': { | |
| this.startOnDamageTargetAction(action, targets); | |
| break; | |
| } | |
| case 'user': { | |
| this.startOnDamageUserAction(action, targets); | |
| break; | |
| } | |
| case 'animationtarget': { | |
| this._skill.animationTarget = Number(action[1]) || 0; | |
| break; | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.startOnDamageTargetAction = function(action, targets) { | |
| var cmd = action.shift().toLowerCase(); | |
| switch (cmd) { | |
| case 'move': { | |
| this.targetMove(action, targets); | |
| break; | |
| } | |
| case 'jump': { | |
| this.targetJump(action, targets); | |
| break; | |
| } | |
| case 'pose': { | |
| this.targetPose(action, targets); | |
| break; | |
| } | |
| case 'cancel': { | |
| this.targetCancel(action, targets); | |
| break; | |
| } | |
| case 'qaudio': { | |
| this.targetQAudio(action, targets); | |
| break; | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.startOnDamageUserAction = function(action, targets) { | |
| var cmd = action.shift().toLowerCase(); | |
| switch (cmd) { | |
| case 'forceskill': { | |
| this.userForceSkill(action); | |
| break; | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.userCasting = function(action) { | |
| if (!this._skill.forced) { | |
| this._character._casting = action[0] === 'true' ? this._skill : false; | |
| } | |
| }; | |
| Skill_Sequencer.prototype.userLock = function() { | |
| var i = this._character._skillLocked.indexOf(this._skill); | |
| if (i >= 0) return; | |
| this._character._skillLocked.push(this._skill); | |
| }; | |
| Skill_Sequencer.prototype.userUnlock = function() { | |
| var i = this._character._skillLocked.indexOf(this._skill); | |
| if (i >= 0) { | |
| this._character._skillLocked.splice(i, 1); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.userSpeed = function(action) { | |
| var amt = Number(action[1]) || 1; | |
| var spd = this._character.moveSpeed(); | |
| if (action[0] === 'inc') { | |
| this._character.setMoveSpeed(spd + amt); | |
| } else if (action[0] === 'dec') { | |
| this._character.setMoveSpeed(spd - amt); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.userMove = function(action) { | |
| var dist = Number(action[1]) || this._character.moveTiles(); | |
| var route = { | |
| list: [], | |
| repeat: false, | |
| skippable: true, | |
| wait: false | |
| } | |
| var radian = oldRadian = this._character._radian; | |
| if (action[0] === 'backward') { | |
| radian -= Math.PI; | |
| } | |
| route.list.push({ | |
| code: Game_Character.ROUTE_SCRIPT, | |
| parameters: ['qmove2(' + radian + ',' + dist + ')'] | |
| }); | |
| if (action[0] === 'backward') { | |
| route.list.unshift({ | |
| code: Game_Character.ROUTE_DIR_FIX_OFF | |
| }); | |
| route.list.push({ | |
| code: this._character.isDirectionFixed() ? | |
| Game_Character.ROUTE_DIR_FIX_ON : Game_Character.ROUTE_DIR_FIX_OFF | |
| }); | |
| } | |
| route.list.push({ | |
| code: Game_Character.ROUTE_END | |
| }); | |
| this._character.forceMoveRoute(route); | |
| this._character.updateRoutineMove(); | |
| this._waitForUserMove = action[2] ? action[2] === 'true' : false; | |
| }; | |
| Skill_Sequencer.prototype.userMoveHere = function(action) { | |
| var center = this._character.centerWithCollider(this._skill.collider); | |
| var final = this._character.adjustPosition(center.x, center.y); | |
| var dx = final.x - this._character.px; | |
| var dy = final.y - this._character.py; | |
| var radian = Math.atan2(dy, dx); | |
| var dist = Math.sqrt(dx * dx + dy * dy); | |
| var route = { | |
| list: [], | |
| repeat: false, | |
| skippable: true, | |
| wait: false | |
| } | |
| route.list.push({ | |
| code: Game_Character.ROUTE_SCRIPT, | |
| parameters: ['qmove2(' + radian + ',' + dist + ')'] | |
| }); | |
| route.list.push({ | |
| code: Game_Character.ROUTE_END | |
| }); | |
| this._character.forceMoveRoute(route); | |
| this._character.updateRoutineMove(); | |
| this._waitForUserMove = action[0] ? action[0] === 'true' : false; | |
| }; | |
| Skill_Sequencer.prototype.userJump = function(action) { | |
| var dist = Number(action[1]) || 0; | |
| var x1 = this._character.px; | |
| var y1 = this._character.py; | |
| var radian = oldRadian = this._character._radian; | |
| if (action[0] === 'backward') { | |
| radian -= Math.PI; | |
| } | |
| var x2 = x1 + Math.cos(radian) * dist; | |
| var y2 = y1 + Math.sin(radian) * dist; | |
| var final = this._character.adjustPosition(x2, y2); | |
| var dx = final.x - x1; | |
| var dy = final.y - y1; | |
| var lastDirectionFix = this._character.isDirectionFixed(); | |
| if (action[0] === 'backward') { | |
| this._character.setDirectionFix(true); | |
| } | |
| this._character.pixelJump(dx, dy); | |
| this._character.setDirectionFix(lastDirectionFix); | |
| this._character.setRadian(oldRadian); | |
| this._waitForUserJump = action[2] ? action[2] === 'true' : false; | |
| }; | |
| Skill_Sequencer.prototype.userJumpHere = function(action) { | |
| var center = this._character.centerWithCollider(this._skill.collider); | |
| var final = this._character.adjustPosition(center.x, center.y); | |
| var dx = final.x - this._character.px; | |
| var dy = final.y - this._character.py; | |
| this._character.pixelJump(dx, dy); | |
| this._waitForUserJump = action[0] ? action[0] === 'true' : false; | |
| }; | |
| Skill_Sequencer.prototype.userTeleport = function() { | |
| var x1 = this._skill.collider.x; | |
| var y1 = this._skill.collider.y; | |
| this._character.setPixelPosition(x1, y1); | |
| }; | |
| Skill_Sequencer.prototype.userSetDirection = function(action) { | |
| var dir = Number(action[0]); | |
| if (dir) { | |
| this._character.setDirection(dir); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.userDirectionFix = function(action) { | |
| this._character.setDirectionFix(action[0] === 'true'); | |
| }; | |
| Skill_Sequencer.prototype.userPose = function(action) { | |
| if (Imported.QSprite) { | |
| this._character.playPose(action[0]); | |
| this._waitForUserPose = action[1] === 'true'; | |
| } | |
| }; | |
| Skill_Sequencer.prototype.userForceSkill = function(action) { | |
| var id = Number(action[0]); | |
| var angleOffset = Number(action[1]); | |
| var radian = this._character._radian; | |
| if (angleOffset) { | |
| radian += angleOffset * Math.PI / 180; | |
| } | |
| var skill = this._character.forceSkill(id, true); | |
| skill.radian = radian; | |
| skill._target = this._skill._target; | |
| }; | |
| Skill_Sequencer.prototype.userAnimation = function(action) { | |
| var id = Number(action[0]); | |
| var x = this._character.cx(); | |
| var y = this._character.cy(); | |
| QABSManager.startAnimation(id, x, y); | |
| }; | |
| Skill_Sequencer.prototype.userQAudio = function(action) { | |
| if (!Imported.QAudio) return; | |
| var id = Game_Interpreter.prototype.getUniqueQAudioId.call(); | |
| var name = action[0]; | |
| var loop = !!QPlus.getArg(action, /^loop$/i); | |
| var dontPan = !!QPlus.getArg(action, /^noPan$/i); | |
| var fadein = QPlus.getArg(action, /^fadein(\d+)/i); | |
| var type = QPlus.getArg(action, /^(bgm|bgs|me|se)$/i) || 'bgm'; | |
| type = type.toLowerCase(); | |
| var max = QPlus.getArg(action, /^max(\d+)/i); | |
| if (max === null) { | |
| max = 90; | |
| } | |
| max = Number(max) / 100; | |
| var radius = QPlus.getArg(action, /^radius(\d+)/i); | |
| if (radius === null) { | |
| radius = 5; | |
| } | |
| var audio = { | |
| name: name, | |
| volume: 100, | |
| pitch: 0, | |
| pan: 0 | |
| } | |
| AudioManager.playQAudio(id, audio, { | |
| type: type, | |
| loop: loop, | |
| maxVolume: Number(max), | |
| radius: Number(radius), | |
| bindTo: this._character.charaId(), | |
| doPan: !dontPan, | |
| fadeIn: Number(fadein) || 0 | |
| }); | |
| }; | |
| Skill_Sequencer.prototype.actionStore = function() { | |
| this._stored = new Point(this._skill.collider.x, this._skill.collider.y); | |
| }; | |
| Skill_Sequencer.prototype.actionMove = function(action) { | |
| var dir = action[0]; | |
| var distance = Number(action[1]); | |
| var duration = Number(action[2]); | |
| ColliderManager.draw(this._skill.collider, duration); | |
| var radian = this._skill.radian; | |
| if (dir === 'backward') { | |
| radian -= Math.PI; | |
| } | |
| radian += radian < 0 ? Math.PI * 2 : 0; | |
| this._waitForMove = action[3] === 'true'; | |
| this.setSkillRadian(Number(radian)); | |
| this.actionMoveSkill(distance, duration); | |
| }; | |
| Skill_Sequencer.prototype.actionMoveToStored = function(action) { | |
| if (this._stored) { | |
| var x1 = this._skill.collider.x; | |
| var y1 = this._skill.collider.y; | |
| var x2 = this._stored.x; | |
| var y2 = this._stored.y; | |
| var dx = x2 - x1; | |
| var dy = y2 - y1; | |
| var dist = Math.sqrt(dx * dx + dy * dy); | |
| this._skill.radian = Math.atan2(y2 - y1, x2 - x1); | |
| this._skill.radian += this._skill.radian < 0 ? Math.PI * 2 : 0; | |
| this.actionMove(['forward', dist, action[0], action[1]]); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.actionWave = function(action) { | |
| var dir = action[0]; | |
| var amp = Number(action[1]); | |
| var harm = Number(action[2]); | |
| var distance = Number(action[3]); | |
| var duration = Number(action[4]); | |
| ColliderManager.draw(this._skill.collider, duration); | |
| var radian = this._skill.radian; | |
| if (dir === 'backward') { | |
| radian -= Math.PI; | |
| } | |
| radian += radian < 0 ? Math.PI * 2 : 0; | |
| this.setSkillRadian(Number(radian)); | |
| this.actionWaveSkill(amp, harm, distance, duration); | |
| this._waitForMove = action[5] === "true"; | |
| }; | |
| Skill_Sequencer.prototype.actionWaveToStored = function(action) { | |
| if (this._stored) { | |
| var x1 = this._skill.collider.x; | |
| var y1 = this._skill.collider.y; | |
| var x2 = this._stored.x; | |
| var y2 = this._stored.y; | |
| var dx = x2 - x1; | |
| var dy = y2 - y1; | |
| var dist = Math.sqrt(dx * dx + dy * dy); | |
| this._skill.radian = Math.atan2(dy, dx); | |
| this.actionWave(['forward', action[0], action[1], dist, action[2], action[3]]); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.actionTrigger = function() { | |
| this._skill.targets = QABSManager.getTargets(this._skill, this._character); | |
| this.updateSkillDamage(); | |
| }; | |
| Skill_Sequencer.prototype.actionAdjustAim = function() { | |
| if (!this._skill._target) return; | |
| var x1 = this._skill.collider.x; | |
| var y1 = this._skill.collider.y; | |
| var forward = this._skill._target.forwardV(); | |
| var dt = Math.randomInt(5) || 1; | |
| var x2 = this._skill._target.px + forward.x * dt; | |
| var y2 = this._skill._target.py + forward.y * dt; | |
| var dx = x2 - x1; | |
| var dy = y2 - y1; | |
| this._skill.radian = Math.atan2(dy, dx); | |
| }; | |
| Skill_Sequencer.prototype.actionWait = function(action) { | |
| var duration = Number(action[0]); | |
| ColliderManager.draw(this._skill.collider, duration); | |
| this._waitCount = duration; | |
| }; | |
| Skill_Sequencer.prototype.actionPicture = function(action) { | |
| this._skill.picture = new Sprite_SkillPicture(); | |
| this._skill.picture.bitmap = ImageManager.loadPicture(action[0]); | |
| this._skill.picture.rotatable = action[1] === 'true'; | |
| this._skill.picture.originDirection = Number(action[2]); | |
| this._skill.picture.z = 3; | |
| this._skill.picture.anchor.x = 0.5; | |
| this._skill.picture.anchor.y = 0.5; | |
| var isAnimated = /%\[(\d+)-(\d+)\]/.exec(action[0]); | |
| if (isAnimated) { | |
| var frames = Number(isAnimated[1]); | |
| var speed = Number(isAnimated[2]); | |
| this._skill.picture.setupAnim(frames, speed); | |
| } | |
| this.setSkillPictureRadian(this._skill.picture, this._skill.radian); | |
| var x = this._skill.collider.center.x; | |
| var y = this._skill.collider.center.y; | |
| this._skill.picture.move(x, y); | |
| this._skill.picture.bitmap.addLoadListener(function() { | |
| QABSManager.addPicture(this); | |
| }.bind(this._skill.picture)); | |
| }; | |
| Skill_Sequencer.prototype.actionTrail = function(action) { | |
| this._skill.trail = new Sprite_SkillTrail(); | |
| this._skill.trail.bitmap = ImageManager.loadPicture(action[0]); | |
| this._skill.trail.move(0, 0, Graphics.width, Graphics.height); | |
| this._skill.trail.rotatable = action[1] === 'true'; | |
| this._skill.trail.originDirection = Number(action[2]); | |
| this._skill.trail.z = 3; | |
| this.setSkillPictureRadian(this._skill.trail, this._skill.radian); | |
| var x = this._skill.collider.center.x; | |
| var y = this._skill.collider.center.y; | |
| this._skill.trail.startX = x; | |
| this._skill.trail.startY = y; | |
| this._skill.trail.bitmap.addLoadListener(function() { | |
| var w = this.bitmap.width; | |
| var h = this.bitmap.height; | |
| this.move(x, y, w, h); | |
| QABSManager.addPicture(this); | |
| }.bind(this._skill.trail)); | |
| }; | |
| Skill_Sequencer.prototype.actionCollider = function(action) { | |
| var display = action[0]; | |
| if (display === 'show') { | |
| this._skill.pictureCollider = new Sprite_SkillCollider(this._skill.collider); | |
| QABSManager.addPicture(this._skill.pictureCollider); | |
| } else if (display === 'hide' && this._skill.pictureCollider) { | |
| QABSManager.removePicture(this._skill.pictureCollider); | |
| this._skill.pictureCollider = null; | |
| } | |
| }; | |
| Skill_Sequencer.prototype.actionAnimation = function(action) { | |
| var id = Number(action[0]); | |
| var x = this._skill.collider.center.x; | |
| var y = this._skill.collider.center.y; | |
| QABSManager.startAnimation(id, x, y); | |
| }; | |
| Skill_Sequencer.prototype.actionSE = function(action) { | |
| var se = {}; | |
| se.name = action[0]; | |
| se.volume = Number(action[1]) || 90; | |
| se.pitch = Number(action[2]) || 100; | |
| se.pan = Number(action[3]) || 0; | |
| AudioManager.playSe(se); | |
| }; | |
| Skill_Sequencer.prototype.actionQAudio = function(action) { | |
| if (!Imported.QAudio) return; | |
| var x = this._skill.collider.center.x; | |
| var y = this._skill.collider.center.x; | |
| var id = Game_Interpreter.prototype.getUniqueQAudioId.call(); | |
| var name = action[0]; | |
| var loop = !!QPlus.getArg(action, /^loop$/i); | |
| var dontPan = !!QPlus.getArg(action, /^noPan$/i); | |
| var fadein = QPlus.getArg(action, /^fadein(\d+)/i); | |
| var type = QPlus.getArg(action, /^(bgm|bgs|me|se)$/i) || 'bgm'; | |
| type = type.toLowerCase(); | |
| var max = QPlus.getArg(action, /^max(\d+)/i); | |
| if (max === null) { | |
| max = 90; | |
| } | |
| max = Number(max) / 100; | |
| var radius = QPlus.getArg(action, /^radius(\d+)/i); | |
| if (radius === null) { | |
| radius = 5; | |
| } | |
| var audio = { | |
| name: name, | |
| volume: 100, | |
| pitch: 0, | |
| pan: 0 | |
| } | |
| AudioManager.playQAudio(id, audio, { | |
| type: type, | |
| loop: loop, | |
| maxVolume: Number(max), | |
| radius: Number(radius), | |
| x: x / QMovement.tileSize, | |
| y: y / QMovement.tileSize, | |
| doPan: !dontPan, | |
| fadeIn: Number(fadein) || 0 | |
| }); | |
| }; | |
| Skill_Sequencer.prototype.actionForceSkill = function(action) { | |
| var id = Number(action[0]); | |
| var angleOffset = Number(action[1]); | |
| var radian = this._skill.radian; | |
| if (angleOffset) { | |
| radian += angleOffset * Math.PI / 180; | |
| } | |
| var center = this._skill.collider.center; | |
| var skill = this._character.makeSkill(id); | |
| var w = skill.collider.width; | |
| var h = skill.collider.height; | |
| skill.collider.moveTo(center.x - w / 2, center.y - w / 2); | |
| skill.radian = radian; | |
| skill._target = this._skill._target; | |
| this._character._activeSkills.push(skill); | |
| this._character._skillCooldowns[id] = skill.settings.cooldown; | |
| }; | |
| Skill_Sequencer.prototype.actionMoveSkill = function(distance, duration) { | |
| var instant = duration === 0; | |
| if (duration <= 0) duration = 1; | |
| this._skill.newX = this._skill.collider.x + Math.round(distance * Math.cos(this._skill.radian)); | |
| this._skill.newY = this._skill.collider.y + Math.round(distance * Math.sin(this._skill.radian)); | |
| this._skill.speed = Math.abs(distance / duration); | |
| this._skill.speedX = Math.abs(this._skill.speed * Math.cos(this._skill.radian)); | |
| this._skill.speedY = Math.abs(this._skill.speed * Math.sin(this._skill.radian)); | |
| this._skill.moving = true; | |
| if (instant) { | |
| this.updateSkillPosition(); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.actionWaveSkill = function(amp, harmonics, distance, duration) { | |
| this._skill.amp = amp; | |
| this._skill.distance = distance; | |
| this._skill.waveLength = harmonics * Math.PI; | |
| this._skill.waveSpeed = this._skill.waveLength / duration; | |
| this._skill.theta = 0; | |
| this._skill.xi = this._skill.collider.x; | |
| this._skill.yi = this._skill.collider.y; | |
| this._skill.waving = true; | |
| this._skill.moving = true; | |
| }; | |
| Skill_Sequencer.prototype.targetMove = function(action, targets) { | |
| var dist = Number(action[1]) || this._character.moveTiles(); | |
| for (var i = 0; i < targets.length; i++) { | |
| var dist2 = dist - dist * eval('targets[i].battler().' + QABS.mrst); | |
| if (dist2 <= 0) return; | |
| var dx = targets[i].cx() - this._character.cx(); | |
| var dy = targets[i].cy() - this._character.cy(); | |
| var radian = Math.atan2(dy, dx); | |
| radian += radian < 0 ? Math.PI * 2 : 0; | |
| if (action[0] === 'towards') { | |
| radian += Math.PI; | |
| } else if (action[0] === 'into' || action[0] === 'towardsSkill') { | |
| var dxi = this._skill.collider.center.x - targets[i].cx(); | |
| var dyi = this._skill.collider.center.y - targets[i].cy(); | |
| radian = Math.atan2(dyi, dxi); | |
| dist2 = Math.min(dist2, Math.sqrt(dxi * dxi + dyi * dyi)); | |
| } else if (action[0] === 'awayFromSkill') { | |
| var dxi = targets[i].cx() - this._skill.collider.center.x; | |
| var dyi = targets[i].cy() - this._skill.collider.center.y; | |
| radian = Math.atan2(dyi, dxi); | |
| } | |
| var route = { | |
| list: [], | |
| repeat: false, | |
| skippable: true, | |
| wait: false | |
| } | |
| route.list.push({ | |
| code: Game_Character.ROUTE_DIR_FIX_ON | |
| }); | |
| route.list.push({ | |
| code: Game_Character.ROUTE_SCRIPT, | |
| parameters: ['qmove2(' + radian + ',' + dist + ')'] | |
| }); | |
| if (!targets[i].isDirectionFixed()) { | |
| route.list.push({ | |
| code: Game_Character.ROUTE_DIR_FIX_OFF | |
| }); | |
| } | |
| route.list.push({ | |
| code: Game_Character.ROUTE_SCRIPT, | |
| parameters: ['this.setRadian(' + targets[i]._radian + ')'] | |
| }); | |
| route.list.push({ | |
| code: Game_Character.ROUTE_END | |
| }); | |
| targets[i].forceMoveRoute(route); | |
| targets[i].updateRoutineMove(); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.targetJump = function(action, targets) { | |
| var dist = Number(action[1]) || 0; | |
| for (var i = 0; i < targets.length; i++) { | |
| var dist2 = dist - dist * eval('targets[i].battler().' + QABS.mrst); | |
| if (dist2 <= 0) return; | |
| var dx = targets[i].cx() - this._character.cx(); | |
| var dy = targets[i].cy() - this._character.cy(); | |
| var radian = Math.atan2(dy, dx); | |
| radian += radian < 0 ? Math.PI * 2 : 0; | |
| if (action[0] === 'towards') { | |
| radian += Math.PI; | |
| } else if (action[0] === 'into' || action[0] === 'towardsSkill') { | |
| var dxi = this._skill.collider.center.x - targets[i].cx(); | |
| var dyi = this._skill.collider.center.y - targets[i].cy(); | |
| radian = Math.atan2(dyi, dxi); | |
| dist2 = Math.min(dist2, Math.sqrt(dxi * dxi + dyi * dyi)); | |
| } else if (action[0] === 'awayFromSkill') { | |
| var dxi = targets[i].cx() - this._skill.collider.center.x; | |
| var dyi = targets[i].cy() - this._skill.collider.center.y; | |
| radian = Math.atan2(dyi, dxi); | |
| dist2 = Math.min(dist2, Math.sqrt(dxi * dxi + dyi * dyi)); | |
| } | |
| var x1 = targets[i].px; | |
| var y1 = targets[i].py; | |
| var x2 = x1 + Math.round(dist2 * Math.cos(radian)); | |
| var y2 = y1 + Math.round(dist2 * Math.sin(radian)); | |
| var final = targets[i].adjustPosition(x2, y2); | |
| dx = final.x - x1; | |
| dy = final.y - y1; | |
| var lastDirectionFix = targets[i].isDirectionFixed(); | |
| var prevRadian = targets[i]._radian; | |
| targets[i].setDirectionFix(true); | |
| targets[i].pixelJump(dx, dy); | |
| targets[i].setDirectionFix(lastDirectionFix); | |
| targets[i].setRadian(prevRadian); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.targetPose = function(action, targets) { | |
| var pose = action[0]; | |
| if (Imported.QSprite) { | |
| for (var i = 0; i < targets.length; i++) { | |
| targets[i].playPose(pose); | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.targetCancel = function(action, targets) { | |
| for (var i = 0; i < targets.length; i++) { | |
| if (targets[i]._casting) { | |
| targets[i]._casting.break = true; | |
| } | |
| } | |
| }; | |
| Skill_Sequencer.prototype.targetQAudio = function(action, targets) { | |
| if (!Imported.QAudio) return; | |
| var id = Game_Interpreter.prototype.getUniqueQAudioId.call(); | |
| var name = action[0]; | |
| var loop = !!QPlus.getArg(action, /^loop$/i); | |
| var dontPan = !!QPlus.getArg(action, /^noPan$/i); | |
| var fadein = QPlus.getArg(action, /^fadein(\d+)/i); | |
| var type = QPlus.getArg(action, /^(bgm|bgs|me|se)$/i) || 'bgm'; | |
| type = type.toLowerCase(); | |
| var max = QPlus.getArg(action, /^max(\d+)/i); | |
| if (max === null) { | |
| max = 90; | |
| } | |
| max = Number(max) / 100; | |
| var radius = QPlus.getArg(action, /^radius(\d+)/i); | |
| if (radius === null) { | |
| radius = 5; | |
| } | |
| var audio = { | |
| name: name, | |
| volume: 100, | |
| pitch: 0, | |
| pan: 0 | |
| } | |
| for (var i = 0; i < targets.length; i++) { | |
| AudioManager.playQAudio(id, audio, { | |
| type: type, | |
| loop: loop, | |
| maxVolume: Number(max), | |
| radius: Number(radius), | |
| bindTo: targets[i].charaId(), | |
| doPan: !dontPan, | |
| fadeIn: Number(fadein) || 0 | |
| }); | |
| }; | |
| }; | |
| Skill_Sequencer.prototype.setSkillRadian = function(radian) { | |
| var rotate = this._skill.settings.rotate === true; | |
| this._skill.radian = radian; | |
| this._skill.collider.setRadian(Math.PI / 2 + radian); | |
| if (this._skill.picture) { | |
| this.setSkillPictureRadian(this._skill.picture, this._skill.radian); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.setSkillPictureRadian = function(picture, radian) { | |
| if (!picture.rotatable) return; | |
| var originDirection = picture.originDirection; | |
| var originRadian = this._character.directionToRadian(originDirection); | |
| picture.rotation = originRadian + radian; | |
| }; | |
| Skill_Sequencer.prototype.canSkillMove = function() { | |
| var collided = false; | |
| var through = this._skill.settings.through; | |
| var targets = QABSManager.getTargets(this._skill, this._character); | |
| if (targets.length > 0) { | |
| for (var i = targets.length - 1; i >= 0; i--) { | |
| if (!this._skill.targetsHit.contains(targets[i].charaId())) { | |
| this._skill.targetsHit.push(targets[i].charaId()); | |
| } else { | |
| targets.splice(i, 1); | |
| } | |
| } | |
| if (targets.length > 0) { | |
| this._skill.targets = targets; | |
| if (through === 1 || through === 3) { | |
| collided = true; | |
| // TODO select the nearest target | |
| this._skill.targets = [targets[0]]; | |
| } | |
| this.updateSkillDamage(); | |
| } | |
| } | |
| if (collided) return false; | |
| var edge = this._skill.collider.gridEdge(); | |
| var maxW = $gameMap.width(); | |
| var maxH = $gameMap.height(); | |
| if (!$gameMap.isLoopHorizontal()) { | |
| if (edge.x2 < 0 || edge.x1 >= maxW) return false; | |
| } | |
| if (!$gameMap.isLoopVertical()) { | |
| if (edge.y2 < 0 || edge.y1 >= maxH) return false; | |
| } | |
| if (through === 2 || through === 3) { | |
| ColliderManager.getCollidersNear(this._skill.collider, function(collider) { | |
| if (collider === this.collider) return false; | |
| if (this.settings.throughTerrain.contains(collider.terrain)) { | |
| return false; | |
| } | |
| if (this.collider.intersects(collider)) { | |
| collided = true; | |
| return 'break'; | |
| } | |
| }.bind(this._skill)); | |
| } | |
| if (through === 1 || through === 3) { | |
| ColliderManager.getCharactersNear(this._skill.collider, function(chara) { | |
| if (chara === this._character || chara.isThrough() || !chara.isNormalPriority()) return false; | |
| if (chara.isLoot || chara._erased || chara.isDead) return false; | |
| if (this._skill.collider.intersects(chara.collider('collision'))) { | |
| collided = true; | |
| return 'break'; | |
| } | |
| }.bind(this)); | |
| } | |
| return !collided; | |
| }; | |
| Skill_Sequencer.prototype.isWaiting = function() { | |
| return this._waitCount > 0 || this._waitForMove || | |
| this._waitForUserMove || this._waitForUserJump || | |
| this._waitForUserJump || this._waitForUserPose; | |
| }; | |
| Skill_Sequencer.prototype.onBreak = function() { | |
| var i = this._character._skillLocked.indexOf(this._skill); | |
| if (i >= 0) { | |
| this._character._skillLocked.splice(i, 1); | |
| } | |
| this._character._casting = false; | |
| this.onEnd(); | |
| }; | |
| Skill_Sequencer.prototype.onEnd = function() { | |
| this._skill.collider.kill = true; | |
| QABSManager.removePicture(this._skill.picture); | |
| QABSManager.removePicture(this._skill.trail); | |
| QABSManager.removePicture(this._skill.pictureCollider); | |
| var i = this._character._activeSkills.indexOf(this._skill); | |
| this._character._activeSkills.splice(i, 1); | |
| }; | |
| Skill_Sequencer.prototype.update = function() { | |
| if (this._skill.break || this._character.battler().isStunned()) { | |
| return this.onBreak(); | |
| } | |
| if (this._skill.moving) { | |
| this.updateSkillPosition(); | |
| } | |
| if (!this.isWaiting()) { | |
| this.updateSequence(); | |
| } else { | |
| this.updateWait(); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.updateWait = function() { | |
| if (this._waitCount > 0) { | |
| this._waitCount--; | |
| } | |
| if (this._waitForUserMove && !this._character.isMoving()) { | |
| this._waitForUserMove = false; | |
| } | |
| if (this._waitForUserJump && !this._character.isJumping()) { | |
| this._waitForUserJump = false; | |
| } | |
| if (this._waitForUserPose && !this._character._posePlaying) { | |
| this._waitForUserPose = false; | |
| } | |
| }; | |
| Skill_Sequencer.prototype.updateSequence = function() { | |
| var sequence = this._skill.sequence; | |
| while (sequence.length !== 0) { | |
| var action = QPlus.makeArgs(sequence.shift()); | |
| this.startAction(action); | |
| if (this.isWaiting()) { | |
| break; | |
| } | |
| } | |
| if (this._skill.sequence.length === 0 && !this._skill.moving) { | |
| return this.onEnd(); | |
| } | |
| }; | |
| Skill_Sequencer.prototype.updateSkillDamage = function() { | |
| var targets = this._skill.targets; | |
| for (var i = 0; i < this._skill.ondmg.length; i++) { | |
| var action = this._skill.ondmg[i].split(' '); | |
| this.startOnDamageAction(action, targets); | |
| } | |
| QABSManager.startAction(this._character, targets, this._skill); | |
| }; | |
| Skill_Sequencer.prototype.updateSkillPosition = function() { | |
| if (this._skill.waving) { | |
| return this.updateSkillWavePosition(); | |
| } | |
| var collider = this._skill.collider; | |
| var x1 = collider.x; | |
| var x2 = this._skill.newX; | |
| var y1 = collider.y; | |
| var y2 = this._skill.newY; | |
| if (x1 < x2) x1 = Math.min(x1 + this._skill.speedX, x2); | |
| if (x1 > x2) x1 = Math.max(x1 - this._skill.speedX, x2); | |
| if (y1 < y2) y1 = Math.min(y1 + this._skill.speedY, y2); | |
| if (y1 > y2) y1 = Math.max(y1 - this._skill.speedY, y2); | |
| collider.moveTo(x1, y1); | |
| var x3 = collider.center.x; | |
| var y3 = collider.center.y; | |
| if (this._skill.picture) { | |
| this._skill.picture.move(x3, y3); | |
| } | |
| if (this._skill.trail) { | |
| var x4 = this._skill.trail.startX; | |
| var y4 = this._skill.trail.startY; | |
| var x5 = x4 - x3; | |
| var y5 = y4 - y3; | |
| var dist = Math.sqrt(x5 * x5 + y5 * y5); | |
| var radian = this._skill.trail.rotation; | |
| var w = this._skill.trail.bitmap.width; | |
| var h = this._skill.trail.bitmap.height; | |
| var ox = w * Math.sin(radian); | |
| var oy = (h / 2) * -Math.cos(radian); | |
| x4 += dist * -Math.cos(radian) + ox; | |
| y4 += dist * -Math.sin(radian) + oy; | |
| this._skill.trail.move(x4, y4, dist, h); | |
| } | |
| if (!this.canSkillMove() || (x1 === x2 && y1 === y2)) { | |
| this._skill.targetsHit = []; | |
| this._skill.moving = false; | |
| this._waitForMove = false; | |
| } | |
| }; | |
| Skill_Sequencer.prototype.updateSkillWavePosition = function() { | |
| var collider = this._skill.collider; | |
| var x1 = this._skill.xi; | |
| var y1 = this._skill.yi; | |
| var x2 = (this._skill.theta / this._skill.waveLength * this._skill.distance); | |
| var y2 = this._skill.amp * -Math.sin(this._skill.theta); | |
| var h = Math.sqrt(y2 * y2 + x2 * x2); | |
| var radian = Math.atan2(y2, x2); | |
| radian += this._skill.radian; | |
| var x3 = h * Math.cos(radian); | |
| var y3 = h * Math.sin(radian); | |
| collider.moveTo(x1 + x3, y1 + y3); | |
| var x4 = collider.center.x; | |
| var y4 = collider.center.y; | |
| if (this._skill.picture) { | |
| this._skill.picture.move(x4, y4); | |
| } | |
| if (!this.canSkillMove() || this._skill.theta >= this._skill.waveLength) { | |
| this._skill.targetsHit = []; | |
| this._skill.waving = false; | |
| this._skill.moving = false; | |
| this._waitForMove = false; | |
| } | |
| this._skill.theta += this._skill.waveSpeed; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Interpreter | |
| (function() { | |
| var Alias_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand; | |
| Game_Interpreter.prototype.pluginCommand = function(command, args) { | |
| if (command.toLowerCase() === 'qabs') { | |
| return this.qABSCommand(QPlus.makeArgs(args)); | |
| } | |
| Alias_Game_Interpreter_pluginCommand.call(this, command, args); | |
| }; | |
| Game_Interpreter.prototype.qABSCommand = function(args) { | |
| var cmd = args.shift().toLowerCase(); | |
| if (cmd === 'disable' || cmd === 'enable') { | |
| if (args.length === 0) { | |
| $gameSystem._absEnabled = cmd === 'enable'; | |
| } else { | |
| for (var i = 0; i < args.length; i++) { | |
| var chara = QPlus.getCharacter(args[i]); | |
| if (chara.constructor === Game_Event) { | |
| var id = chara.eventId(); | |
| var mapId = chara._mapId; | |
| if (cmd === 'enable') { | |
| $gameSystem.enableEnemy(mapId, id); | |
| } else { | |
| $gameSystem.disableEnemy(mapId, id); | |
| } | |
| } | |
| } | |
| } | |
| return; | |
| } | |
| if (cmd === 'override') { | |
| var key = Number(args.shift()); | |
| var skillId = Number(args.shift()); | |
| if (skillId === -1) { | |
| skillId = null; | |
| } | |
| $gameSystem.changeABSOverrideSkill(key, skillId); | |
| return; | |
| } | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_System | |
| (function() { | |
| var Alias_Game_System_initialize = Game_System.prototype.initialize; | |
| Game_System.prototype.initialize = function() { | |
| Alias_Game_System_initialize.call(this); | |
| this._absKeys = QABS.getDefaultSkillKeys(); | |
| this._absClassKeys = {}; | |
| this._absWeaponKeys = {}; | |
| this._absOverrideKeys = {}; | |
| this._absEnabled = true; | |
| this._disabledEnemies = {}; | |
| this.checkAbsMouse(); | |
| }; | |
| Game_System.prototype.disableEnemy = function(mapId, eventId) { | |
| if (!this._disabledEnemies[mapId]) { | |
| this._disabledEnemies[mapId] = []; | |
| } | |
| this._disabledEnemies[mapId][eventId] = true; | |
| }; | |
| Game_System.prototype.enableEnemy = function(mapId, eventId) { | |
| if (!this._disabledEnemies[mapId]) { | |
| this._disabledEnemies[mapId] = []; | |
| } | |
| this._disabledEnemies[mapId][eventId] = false; | |
| }; | |
| Game_System.prototype.isDisabled = function(mapId, eventId) { | |
| if (!this._disabledEnemies[mapId]) { | |
| return false; | |
| } | |
| return this._disabledEnemies[mapId][eventId] || !this._absEnabled; | |
| }; | |
| Game_System.prototype.loadClassABSKeys = function() { | |
| if (!$gameParty.leader()) return; | |
| var playerClass = $gameParty.leader().currentClass(); | |
| var classKeys = /<skillKeys>([\s\S]*)<\/skillKeys>/i.exec(playerClass.note); | |
| if (classKeys && classKeys[1].trim() !== '') { | |
| this._absClassKeys = QABS.stringToSkillKeyObj(classKeys[1]); | |
| this.resetABSKeys(); | |
| } | |
| }; | |
| Game_System.prototype.resetABSKeys = function() { | |
| this._absKeys = QABS.getDefaultSkillKeys(); | |
| for (var key in this._absKeys) { | |
| Object.assign( | |
| this._absKeys[key], | |
| this._absClassKeys[key] || {}, | |
| this._absWeaponKeys[key] || {}, | |
| this._absOverrideKeys[key] || {} | |
| ); | |
| } | |
| this.preloadAllSkills(); | |
| this.checkAbsMouse(); | |
| }; | |
| Game_System.prototype.absKeys = function() { | |
| return this._absKeys; | |
| }; | |
| Game_System.prototype.changeABSOverrideSkill = function(skillNumber, skillId, forced) { | |
| var absKeys = this.absKeys(); | |
| var override = this._absOverrideKeys; | |
| if (!absKeys[skillNumber]) return; | |
| if (!forced && !absKeys[skillNumber].rebind) return; | |
| if (!override[skillNumber]) { | |
| override[skillNumber] = {}; | |
| } | |
| if (skillId !== null) { | |
| if (skillId > 0) { | |
| for (var key in absKeys) { | |
| if (absKeys[key].skillId === skillId) { | |
| if (!override[key]) { | |
| override[key] = {}; | |
| } | |
| override[key].skillId = null; | |
| } | |
| } | |
| } | |
| override[skillNumber].skillId = skillId; | |
| } else { | |
| delete override[skillNumber].skillId; | |
| } | |
| this.resetABSKeys(); | |
| }; | |
| Game_System.prototype.changeABSWeaponSkills = function(skillSet) { | |
| this._absWeaponKeys = skillSet; | |
| this.resetABSKeys(); | |
| }; | |
| Game_System.prototype.changeABSSkillInput = function(skillNumber, input) { | |
| var absKeys = this.absKeys(); | |
| var override = this._absOverrideKeys; | |
| if (!absKeys[skillNumber]) return; | |
| if (!override[skillNumber]) { | |
| override[skillNumber] = {}; | |
| } | |
| for (var key in absKeys) { | |
| var i = absKeys[key].input.indexOf(input); | |
| if (i !== -1) { | |
| if (!override[key]) { | |
| override[key] = { | |
| input: absKeys[key].input.clone() | |
| }; | |
| } | |
| override[key].input.splice(i, 1); | |
| break; | |
| } | |
| } | |
| var i = /^\$/.test(input) ? 1 : 0; | |
| override[skillNumber].input[i] = input; | |
| this.checkAbsMouse(); | |
| }; | |
| Game_System.prototype.preloadAllSkills = function() { | |
| var absKeys = this.absKeys(); | |
| for (var key in absKeys) { | |
| var skill = $dataSkills[absKeys[key].skillId]; | |
| if (skill) QABSManager.preloadSkill(skill); | |
| } | |
| }; | |
| Game_System.prototype.anyAbsMouse = function() { | |
| return this._absMouse1; | |
| }; | |
| Game_System.prototype.anyAbsMouse2 = function() { | |
| return this._absMouse2; | |
| }; | |
| Game_System.prototype.checkAbsMouse = function() { | |
| this._absMouse1 = false; | |
| this._absMouse2 = false; | |
| var keys = this.absKeys(); | |
| for (var key in keys) { | |
| if (keys[key].input[0] === 'mouse1') { | |
| this._absMouse1 = true; | |
| } | |
| if (keys[key].input[0] === 'mouse2') { | |
| this._absMouse2 = true; | |
| } | |
| } | |
| }; | |
| var Alias_Game_System_onBeforeSave = Game_System.prototype.onBeforeSave; | |
| Game_System.prototype.onBeforeSave = function() { | |
| Alias_Game_System_onBeforeSave.call(this); | |
| $gameMap.compressBattlers(); | |
| QABS._needsUncompress = true; | |
| }; | |
| var Alias_Game_System_onAfterLoad = Game_System.prototype.onAfterLoad; | |
| Game_System.prototype.onAfterLoad = function() { | |
| Alias_Game_System_onAfterLoad.call(this); | |
| QABS._needsUncompress = true; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Map | |
| (function() { | |
| var Alias_Game_Map_setup = Game_Map.prototype.setup; | |
| Game_Map.prototype.setup = function(mapId) { | |
| Alias_Game_Map_setup.call(this, mapId); | |
| if (mapId !== QABSManager._mapId) { | |
| QABSManager.clear(); | |
| } | |
| }; | |
| var Alias_Game_Map_update = Game_Map.prototype.update; | |
| Game_Map.prototype.update = function(sceneActive) { | |
| Alias_Game_Map_update.call(this, sceneActive); | |
| if (QABS._needsUncompress) { | |
| this.uncompressBattlers(); | |
| QABS._needsUncompress = false; | |
| } | |
| }; | |
| Game_Map.prototype.compressBattlers = function() { | |
| for (var i = 0; i < this.events().length; i++) { | |
| if (this.events()[i]._battler) { | |
| var oldRespawn = this.events()[i]._respawn; | |
| this.events()[i].clearABS(); | |
| this.events()[i]._battler = null; | |
| this.events()[i]._respawn = oldRespawn; | |
| } | |
| if (this.events()[i].constructor === Game_Loot) { | |
| QABSManager.removePicture(this.events()[i]._itemIcon); | |
| QABSManager.removeEvent(this.events()[i]); | |
| } | |
| } | |
| $gamePlayer.clearABS(); | |
| QABSManager.clear(); | |
| }; | |
| Game_Map.prototype.uncompressBattlers = function() { | |
| for (var i = 0; i < this.events().length; i++) { | |
| if (this.events()[i]._respawn >= 0) { | |
| var wasDead = true; | |
| var oldRespawn = this.events()[i]._respawn; | |
| } | |
| this.events()[i].setupBattler(); | |
| if (wasDead) { | |
| this.events()[i].clearABS(); | |
| this.events()[i]._battler = null; | |
| this.events()[i]._respawn = oldRespawn; | |
| } | |
| } | |
| // TODO setup player? | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Action | |
| function Game_ABSAction() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Game_ABSAction.prototype = Object.create(Game_Action.prototype); | |
| Game_ABSAction.prototype.constructor = Game_ABSAction; | |
| Game_ABSAction.prototype.setSubject = function(subject) { | |
| Game_Action.prototype.setSubject.call(this, subject); | |
| this._realSubject = subject; | |
| }; | |
| Game_ABSAction.prototype.subject = function() { | |
| return this._realSubject; | |
| }; | |
| Game_ABSAction.prototype.absApply = function(target) { | |
| var result = target.result(); | |
| this._realSubject.clearResult(); | |
| result.clear(); | |
| result.physical = this.isPhysical(); | |
| result.drain = this.isDrain(); | |
| if (this.item().damage.type > 0) { | |
| result.critical = (Math.random() < this.itemCri(target)); | |
| var value = this.makeDamageValue(target, result.critical); | |
| this.executeDamage(target, value); | |
| target.startDamagePopup(); | |
| } | |
| this.item().effects.forEach(function(effect) { | |
| this.applyItemEffect(target, effect); | |
| }, this); | |
| this.applyItemUserEffect(target); | |
| }; | |
| var Alias_Game_ActionResult_clear = Game_ActionResult.prototype.clear; | |
| Game_ActionResult.prototype.clear = function() { | |
| Alias_Game_ActionResult_clear.call(this); | |
| this.damageIcon = null; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_BattlerBase | |
| (function() { | |
| var Alias_Game_BattlerBase_resetStateCounts = Game_BattlerBase.prototype.resetStateCounts; | |
| Game_BattlerBase.prototype.resetStateCounts = function(stateId) { | |
| Alias_Game_BattlerBase_resetStateCounts.call(this, stateId); | |
| this._stateSteps[stateId] = $dataStates[stateId].stepsToRemove || 0; | |
| }; | |
| var Alias_Game_BattlerBase_addNewState = Game_BattlerBase.prototype.addNewState; | |
| Game_BattlerBase.prototype.addNewState = function(stateId) { | |
| Alias_Game_BattlerBase_addNewState.call(this, stateId); | |
| if ($dataStates[stateId].meta.moveSpeed) { | |
| this._moveSpeed += Number($dataStates[stateId].meta.moveSpeed) || 0; | |
| } | |
| if ($dataStates[stateId].meta.stun) { | |
| this._isStunned++; | |
| } | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Battler | |
| (function() { | |
| var Alias_Game_Battler_initMembers = Game_Battler.prototype.initMembers; | |
| Game_Battler.prototype.initMembers = function() { | |
| Alias_Game_Battler_initMembers.call(this); | |
| this._isStunned = 0; | |
| this._moveSpeed = 0; | |
| this._damageQueue = []; | |
| }; | |
| var Alias_Game_Battler_startDamagePopup = Game_Battler.prototype.startDamagePopup; | |
| Game_Battler.prototype.startDamagePopup = function() { | |
| this._damageQueue.push(Object.assign({}, this._result)); | |
| Alias_Game_Battler_startDamagePopup.call(this); | |
| }; | |
| Game_Battler.prototype.updateABS = function() { | |
| var states = this.states(); | |
| for (var i = 0; i < states.length; i++) { | |
| this.updateStateSteps(states[i]); | |
| } | |
| //this.showAddedStates(); //Currently does nothing, so no need to run it | |
| //this.showRemovedStates(); //Currently does nothing, so no need to run it | |
| }; | |
| Game_Battler.prototype.stepsForTurn = function() { | |
| return 60; | |
| }; | |
| Game_Battler.prototype.updateStateSteps = function(state) { | |
| if (!state.removeByWalking) return; | |
| if (this._stateSteps[state.id] >= 0) { | |
| if (this._stateSteps[state.id] % this.stepsForTurn() === 0) { | |
| this.onTurnEnd(); | |
| this.result().damageIcon = $dataStates[state.id].iconIndex; | |
| this.startDamagePopup(); | |
| if (this._stateSteps[state.id] === 0) this.removeState(state.id); | |
| } | |
| this._stateSteps[state.id]--; | |
| } | |
| }; | |
| Game_Battler.prototype.showAddedStates = function() { | |
| // TODO | |
| this.result().addedStateObjects().forEach(function(state) { | |
| // does nothing | |
| }, this); | |
| }; | |
| Game_Battler.prototype.showRemovedStates = function() { | |
| // TODO | |
| this.result().removedStateObjects().forEach(function(state) { | |
| // Popup that state was removed? | |
| }, this); | |
| }; | |
| var Alias_Game_Battler_removeState = Game_Battler.prototype.removeState; | |
| Game_Battler.prototype.removeState = function(stateId) { | |
| if (this.isStateAffected(stateId)) { | |
| if ($dataStates[stateId].meta.moveSpeed) { | |
| this._moveSpeed -= Number($dataStates[stateId].meta.moveSpeed) || 0; | |
| } | |
| if ($dataStates[stateId].meta.stun) { | |
| this._isStunned--; | |
| } | |
| } | |
| Alias_Game_Battler_removeState.call(this, stateId); | |
| }; | |
| Game_Battler.prototype.moveSpeed = function() { | |
| return this._moveSpeed; | |
| }; | |
| Game_Battler.prototype.isStunned = function() { | |
| return this._isStunned > 0; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Actor | |
| (function() { | |
| var Alias_Game_Actor_setup = Game_Actor.prototype.setup; | |
| Game_Actor.prototype.setup = function(actorId) { | |
| Alias_Game_Actor_setup.call(this, actorId); | |
| var meta = this.actor().qmeta; | |
| this._popupOY = Number(meta.popupOY) || 0; | |
| }; | |
| var Alias_Game_Actor_changeClass = Game_Actor.prototype.changeClass; | |
| Game_Actor.prototype.changeClass = function(classId, keepExp) { | |
| Alias_Game_Actor_changeClass.call(this, classId, keepExp); | |
| if (this === $gameParty.leader()) $gameSystem.loadClassABSKeys(); | |
| }; | |
| Game_Actor.prototype.initWeaponSkills = function() { | |
| var equips = this._equips; | |
| for (var i = 0; i < equips.length; i++) { | |
| if (equips[i].object()) { | |
| var equipId = equips[i].object().baseItemId || equips[i].object().id; | |
| if (equips[i].isWeapon() && equipId) { | |
| this.changeWeaponSkill(equipId); | |
| } | |
| } | |
| } | |
| }; | |
| var Alias_Game_Actor_changeEquip = Game_Actor.prototype.changeEquip; | |
| Game_Actor.prototype.changeEquip = function(slotId, item) { | |
| if (this !== $gameParty.leader()) { | |
| return Alias_Game_Actor_changeEquip.call(this, slotId, item); | |
| } | |
| var equips = this._equips; | |
| var oldId, newId = 0; | |
| var wasWeapon; | |
| if (equips[slotId] && equips[slotId].object()) { | |
| oldId = equips[slotId].object().baseItemId || equips[slotId].object().id; | |
| wasWeapon = equips[slotId].isWeapon(); | |
| } | |
| Alias_Game_Actor_changeEquip.call(this, slotId, item); | |
| if (equips[slotId] && equips[slotId].object()) { | |
| newId = equips[slotId].object().baseItemId || equips[slotId].object().id; | |
| } | |
| if (newId && newId !== oldId && equips[slotId].isWeapon()) { | |
| this.changeWeaponSkill(newId); | |
| } else if (wasWeapon) { | |
| this.changeWeaponSkill(0); | |
| } | |
| }; | |
| Game_Actor.prototype.changeWeaponSkill = function(id) { | |
| if (this !== $gameParty.leader()) return; | |
| var weaponSkills; | |
| if (!$dataWeapons[id]) { | |
| weaponSkills = {}; | |
| } else { | |
| weaponSkills = QABS.weaponSkills(id); | |
| } | |
| $gameSystem.changeABSWeaponSkills(weaponSkills); | |
| }; | |
| Game_Actor.prototype.displayLevelUp = function(newSkills) { | |
| QABSManager.startPopup('QABS-LEVEL', { | |
| x: $gamePlayer.cx(), | |
| y: $gamePlayer.cy(), | |
| string: 'Level Up!' | |
| }) | |
| QABSManager.startAnimation(QABS.levelAnimation, $gamePlayer.cx(), $gamePlayer.cy()); | |
| }; | |
| Game_Actor.prototype.onPlayerWalk = function() { | |
| this.clearResult(); | |
| this.checkFloorEffect(); | |
| }; | |
| Game_Actor.prototype.updateStateSteps = function(state) { | |
| Game_Battler.prototype.updateStateSteps.call(this, state); | |
| }; | |
| Game_Actor.prototype.showAddedStates = function() { | |
| Game_Battler.prototype.showAddedStates.call(this); | |
| }; | |
| Game_Actor.prototype.showRemovedStates = function() { | |
| Game_Battler.prototype.showRemovedStates.call(this); | |
| }; | |
| Game_Actor.prototype.resetStateCounts = function(stateId) { | |
| Game_Battler.prototype.resetStateCounts.call(this, stateId); | |
| }; | |
| Game_Actor.prototype.stepsForTurn = function() { | |
| return Game_Battler.prototype.stepsForTurn.call(this); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Enemy | |
| (function() { | |
| var Alias_Game_Enemy_setup = Game_Enemy.prototype.setup; | |
| Game_Enemy.prototype.setup = function(enemyId, x, y) { | |
| Alias_Game_Enemy_setup.call(this, enemyId, x, y); | |
| var meta = this.enemy().qmeta; | |
| this._aiType = (meta.AIType || 'simple').toLowerCase(); | |
| this._aiRange = Number(meta.range) || 0; | |
| this._noPopup = !!meta.noPopup; | |
| this._popupOY = Number(meta.popupOY) || 0; | |
| this._onDeath = meta.onDeath || ''; | |
| this._dontErase = !!meta.dontErase; | |
| this._team = Number(meta.team || 2); | |
| }; | |
| Game_Enemy.prototype.clearStates = function() { | |
| Game_Battler.prototype.clearStates.call(this); | |
| this._stateSteps = {}; | |
| }; | |
| Game_Enemy.prototype.eraseState = function(stateId) { | |
| Game_Battler.prototype.eraseState.call(this, stateId); | |
| delete this._stateSteps[stateId]; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_CharacterAgro | |
| function Game_CharacterAgro() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Game_CharacterAgro.agroTimer = 300; | |
| Game_CharacterAgro.prototype.initialize = function(charaId) { | |
| this._charaId = charaId; | |
| this.clear(); | |
| }; | |
| Game_CharacterAgro.prototype.clear = function() { | |
| this._agrod = 0; | |
| this._points = {}; | |
| this._tick = {}; | |
| this._total = 0; | |
| this._highest = null; | |
| this._recalcHighest = false; | |
| }; | |
| Game_CharacterAgro.prototype.has = function(charaId) { | |
| return !!this._points[charaId]; | |
| }; | |
| Game_CharacterAgro.prototype.inCombat = function() { | |
| return this._agrod > 0 || this._total > 0; | |
| }; | |
| Game_CharacterAgro.prototype.character = function() { | |
| return QPlus.getCharacter(this._charaId) || null; | |
| }; | |
| Game_CharacterAgro.prototype.highest = function() { | |
| if (this._recalcHighest) { | |
| this.calcHighest(); | |
| } | |
| return this._highest; | |
| }; | |
| Game_CharacterAgro.prototype.add = function(charaId, amount) { | |
| this._points[charaId] = this._points[charaId] ? this._points[charaId] + amount : amount; | |
| this._tick[charaId] = Game_CharacterAgro.agroTimer; | |
| var points = this._points[charaId]; | |
| this._total += amount; | |
| this._recalcHighest = true; | |
| }; | |
| Game_CharacterAgro.prototype.remove = function(charaId) { | |
| this._total -= this._points[charaId] || 0; | |
| delete this._points[charaId]; | |
| delete this._tick[charaId]; | |
| this._recalcHighest = true; | |
| }; | |
| Game_CharacterAgro.prototype.placeInCombat = function() { | |
| this._agro = Game_CharacterAgro.agroTimer; | |
| }; | |
| Game_CharacterAgro.prototype.calcHighest = function() { | |
| var highest = 0; | |
| var highestId = null; | |
| for (var charaId in this._points) { | |
| if (this._points[charaId] > highest) { | |
| highest = this._points[charaId]; | |
| highestId = charaId; | |
| } | |
| } | |
| this._highest = highestId ? QPlus.getCharacter(highestId) : null; | |
| this._recalcHighest = false; | |
| }; | |
| Game_CharacterAgro.prototype.update = function() { | |
| for (var charaId in this._tick) { | |
| this._tick[charaId] = this._tick[charaId] - 1; | |
| if (this._tick[charaId] === 0) { | |
| this.remove(charaId); | |
| } | |
| } | |
| if (this._agro > 0) this._agro--; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_CharacterBase | |
| (function() { | |
| Game_CharacterBase.prototype.battler = function() { | |
| return null; | |
| }; | |
| Game_CharacterBase.prototype.clearABS = function() { | |
| if (this._activeSkills && this._activeSkills.length > 0) { | |
| this.clearSkills(); | |
| } | |
| this.clearAgro(); | |
| this._activeSkills = []; | |
| this._skillCooldowns = {}; | |
| this._casting = null; | |
| this._skillLocked = []; | |
| }; | |
| Game_CharacterBase.prototype.clearSkills = function() { | |
| for (var i = this._activeSkills.length - 1; i >= 0; i--) { | |
| var skill = this._activeSkills[i]; | |
| QABSManager.removePicture(skill.picture); | |
| QABSManager.removePicture(skill.trail); | |
| QABSManager.removePicture(skill.pictureCollider); | |
| this._activeSkills.splice(i, 1); | |
| } | |
| }; | |
| Game_CharacterBase.prototype.team = function() { | |
| return 0; | |
| }; | |
| Game_CharacterBase.prototype.isFriendly = function(target) { | |
| return target.team() === this.team(); | |
| }; | |
| Game_CharacterBase.prototype.inCombat = function() { | |
| if (!this.battler()) return false; | |
| return this._inCombat; | |
| }; | |
| Game_CharacterBase.prototype.isCasting = function() { | |
| if (this._casting) { | |
| if (this._casting.break) { | |
| this._casting = null; | |
| return false; | |
| } | |
| return true; | |
| } | |
| return false; | |
| }; | |
| var Alias_Game_CharacterBase_canMove = Game_CharacterBase.prototype.canMove; | |
| Game_CharacterBase.prototype.canMove = function() { | |
| if (this.battler()) { | |
| if (this._skillLocked.length > 0) return false; | |
| if (this.battler().isStunned()) return false; | |
| } | |
| if (this.realMoveSpeed() <= 0) return false; | |
| return Alias_Game_CharacterBase_canMove.call(this); | |
| }; | |
| Game_CharacterBase.prototype.canInputSkill = function(fromEvent) { | |
| if (this._globalLocked > 0) return false; | |
| if (!fromEvent && $gameMap.isEventRunning()) return false; | |
| if (!$gameSystem._absEnabled) return false; | |
| if (!this.battler()) return false; | |
| if (this.battler().isDead()) return false; | |
| if (this.battler().isStunned()) return false; | |
| if (this.isCasting()) return false; | |
| if (this._skillLocked.length > 0) return false; | |
| return true; | |
| }; | |
| Game_CharacterBase.prototype.canUseSkill = function(id) { | |
| var skill = $dataSkills[id]; | |
| return this.usableSkills().contains(id) && this.battler().canPaySkillCost(skill); | |
| }; | |
| Game_CharacterBase.prototype.usableSkills = function() { | |
| return []; | |
| }; | |
| var Alias_Game_CharacterBase_realMoveSpeed = Game_CharacterBase.prototype.realMoveSpeed; | |
| Game_CharacterBase.prototype.realMoveSpeed = function() { | |
| var value = Alias_Game_CharacterBase_realMoveSpeed.call(this); | |
| if (this.battler()) { | |
| value += this.battler().moveSpeed(); | |
| } | |
| return value; | |
| }; | |
| Game_CharacterBase.prototype.inCombat = function() { | |
| if (!this._agro) return false; | |
| return this._agro.inCombat(); | |
| }; | |
| Game_CharacterBase.prototype.addAgro = function(from, skill) { | |
| var chara = QPlus.getCharacter(from); | |
| if (!chara || chara === this || !chara._agro) { | |
| return; | |
| } | |
| if (this.isFriendly(chara) || !this._agro) { | |
| return; | |
| } | |
| var amt = skill ? skill.agroPoints || 1 : 1; | |
| this._agro.add(from, amt); | |
| }; | |
| Game_CharacterBase.prototype.removeAgro = function(from) { | |
| if (!this._agro) { | |
| return; | |
| } | |
| this._agro.remove(from); | |
| }; | |
| Game_CharacterBase.prototype.clearAgro = function() { | |
| if (this._agro) { | |
| var agrod = this._agro._agrodList; | |
| for (var charaId in agrod) { | |
| var chara = QPlus.getCharacter(charaId); | |
| if (chara) chara.removeAgro(this.charaId()); | |
| } | |
| this._agro.clear(); | |
| } else { | |
| this._agro = new Game_CharacterAgro(this.charaId()); | |
| } | |
| }; | |
| Game_CharacterBase.prototype.bestTarget = function() { | |
| if (!this._agro) { | |
| return null; | |
| } | |
| return this._agro.highest(); | |
| }; | |
| var Alias_Game_CharacterBase_update = Game_CharacterBase.prototype.update; | |
| Game_CharacterBase.prototype.update = function() { | |
| Alias_Game_CharacterBase_update.call(this); | |
| if (this.battler() && $gameSystem._absEnabled) this.updateABS(); | |
| }; | |
| Game_CharacterBase.prototype.updateABS = function() { | |
| if (this.battler().isDead()) { | |
| if (!this._isDead) { | |
| this.onDeath(); | |
| } | |
| return; | |
| } | |
| this._agro.update(); | |
| this.updateSkills(); | |
| this.battler().updateABS(); | |
| }; | |
| Game_CharacterBase.prototype.onDeath = function() { | |
| // Placeholder method, overwritten in Game_Player and Game_Event | |
| }; | |
| Game_CharacterBase.prototype.updateSkills = function() { | |
| if (this._groundTargeting) this.updateTargeting(); | |
| if (this._activeSkills.length > 0) this.updateSkillSequence(); | |
| this.updateSkillCooldowns(); | |
| }; | |
| Game_CharacterBase.prototype.updateTargeting = function() { | |
| return this.onTargetingEnd(); | |
| }; | |
| Game_CharacterBase.prototype.updateSkillSequence = function() { | |
| for (var i = this._activeSkills.length - 1; i >= 0; i--) { | |
| this._activeSkills[i].sequencer.update(); | |
| } | |
| }; | |
| Game_CharacterBase.prototype.updateSkillCooldowns = function() { | |
| for (var id in this._skillCooldowns) { | |
| if (this._skillCooldowns[id] === 0) { | |
| delete this._skillCooldowns[id]; | |
| } else { | |
| this._skillCooldowns[id]--; | |
| } | |
| } | |
| }; | |
| Game_CharacterBase.prototype.onTargetingEnd = function() { | |
| var skill = this._groundTargeting; | |
| this.battler().paySkillCost(skill.data); | |
| this._activeSkills.push(skill); | |
| this._skillCooldowns[skill.id] = skill.settings.cooldown; | |
| ColliderManager.draw(skill.collider, skill.sequence.length + 60); | |
| this.onTargetingCancel(); | |
| }; | |
| Game_CharacterBase.prototype.onTargetingCancel = function() { | |
| QABSManager.removePicture(this._groundTargeting.picture); | |
| this._groundTargeting.targeting.kill = true; | |
| this._groundTargeting = null; | |
| this._selectTargeting = null; | |
| }; | |
| Game_CharacterBase.prototype.useSkill = function(skillId, fromEvent) { | |
| if (!this.canInputSkill(fromEvent)) return null; | |
| if (!this.canUseSkill(skillId)) return null; | |
| if (this._groundTargeting) { | |
| this.onTargetingCancel(); | |
| } | |
| var skill = this.forceSkill(skillId); | |
| if (!this._groundTargeting) { | |
| this.battler().paySkillCost($dataSkills[skillId]); | |
| } | |
| return skill; | |
| }; | |
| Game_CharacterBase.prototype.beforeSkill = function(skill) { | |
| // Runs before the skills sequence and collider are made | |
| var before = skill.data.qmeta.beforeSkill || ''; | |
| if (before !== '') { | |
| try { | |
| eval(before); | |
| } catch (e) { | |
| console.error('Error with `beforeSkill` meta inside skill ' + skill.data.id, e); | |
| } | |
| } | |
| }; | |
| Game_CharacterBase.prototype.forceSkill = function(skillId, forced) { | |
| var skill = this.makeSkill(skillId, forced); | |
| if (skill.settings.groundTarget || skill.settings.selectTarget) { | |
| return this.makeTargetingSkill(skill); | |
| } | |
| this._activeSkills.push(skill); | |
| this._skillCooldowns[skillId] = skill.settings.cooldown; | |
| ColliderManager.draw(skill.collider, skill.sequence.length + 60); | |
| return skill; | |
| }; | |
| Game_CharacterBase.prototype.makeSkill = function(skillId, forced) { | |
| var data = $dataSkills[skillId]; | |
| var skill = { | |
| id: skillId, | |
| data: data, | |
| settings: QABS.getSkillSettings(data), | |
| sequence: QABS.getSkillSequence(data), | |
| ondmg: QABS.getSkillOnDamage(data), | |
| radian: this._radian, | |
| targetsHit: [], | |
| forced: forced | |
| } | |
| this.beforeSkill(skill); | |
| skill.sequencer = new Skill_Sequencer(this, skill); | |
| skill.collider = this.makeSkillCollider(skill.settings); | |
| return skill; | |
| }; | |
| Game_CharacterBase.prototype.makeSkillCollider = function(settings) { | |
| var w1 = this.collider('collision').width; | |
| var h1 = this.collider('collision').height; | |
| settings.collider = settings.collider || ['box', w1, h1]; | |
| var collider = ColliderManager.convertToCollider(settings.collider); | |
| var infront = settings.infront === true; | |
| var rotate = settings.rotate === true; | |
| if (rotate) { | |
| if (QABS.radianAtks) { | |
| collider.rotate(Math.PI / 2 + this._radian); | |
| } else { | |
| collider.rotate(Math.PI / 2 + this.directionToRadian(this._direction)); | |
| } | |
| } | |
| var x1 = this.cx() - collider.center.x; | |
| var y1 = this.cy() - collider.center.y; | |
| if (infront) { | |
| var w2 = collider.width; | |
| var h2 = collider.height; | |
| var radian; | |
| if (QABS.radianAtks) { | |
| radian = this._radian; | |
| } else { | |
| radian = this.directionToRadian(this._direction); | |
| } | |
| var w3 = Math.cos(radian) * w1 / 2 + Math.cos(radian) * w2 / 2; | |
| var h3 = Math.sin(radian) * h1 / 2 + Math.sin(radian) * h2 / 2; | |
| x1 += w3; | |
| y1 += h3; | |
| } | |
| collider.moveTo(x1, y1); | |
| return collider; | |
| }; | |
| Game_CharacterBase.prototype.makeTargetingSkill = function(skill) { | |
| this._groundTargeting = skill; | |
| this._selectTargeting = this.constructor === Game_Event ? true : skill.settings.selectTarget; | |
| var collider = skill.collider; | |
| var diameter = skill.settings.range * 2; | |
| skill.targeting = new Circle_Collider(diameter, diameter); | |
| skill.targeting.moveTo(this.cx() - diameter / 2, this.cy() - diameter / 2); | |
| ColliderManager.draw(skill.targeting, -1); | |
| skill.collider = skill.targeting; | |
| skill.targets = QABSManager.getTargets(skill, this); | |
| skill.collider = collider; | |
| skill.picture = new Sprite_SkillCollider(skill.collider); | |
| if (this._selectTargeting) { | |
| if (skill.targets.length === 0) { | |
| return this.onTargetingCancel(); | |
| } | |
| skill.collider.color = '#00ff00'; | |
| skill.index = 0; | |
| } | |
| QABSManager.addPicture(skill.picture); | |
| return skill; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Player | |
| (function() { | |
| var Alias_Game_Player_refresh = Game_Player.prototype.refresh; | |
| Game_Player.prototype.refresh = function() { | |
| Alias_Game_Player_refresh.call(this); | |
| if (this.battler() && this._battlerId !== this.battler()._actorId) { | |
| this.setupBattler(); | |
| } | |
| }; | |
| Game_Player.prototype.battler = function() { | |
| return this.actor(); | |
| }; | |
| Game_Player.prototype.setupBattler = function() { | |
| if (!this.battler()) return; | |
| this.clearABS(); | |
| this._battlerId = this.battler()._actorId; | |
| this.battler()._charaId = 0; | |
| $gameSystem.loadClassABSKeys(); | |
| $gameSystem.changeABSWeaponSkills({}); | |
| this.battler().initWeaponSkills(); | |
| this._isDead = false; | |
| }; | |
| Game_Player.prototype.team = function() { | |
| return 1; | |
| }; | |
| var Alias_Game_Player_performTransfer = Game_Player.prototype.performTransfer; | |
| Game_Player.prototype.performTransfer = function() { | |
| if (this.isTransferring()) { | |
| if (this._newMapId !== $gameMap.mapId() || this._needsMapReload) { | |
| if (this._agro) this._agro.clear(); | |
| } | |
| } | |
| Alias_Game_Player_performTransfer.call(this); | |
| }; | |
| var Alias_Game_Player_canMove = Game_Player.prototype.canMove; | |
| Game_Player.prototype.canMove = function() { | |
| if (QABS.lockTargeting && this._groundTargeting) return false; | |
| return Alias_Game_Player_canMove.call(this); | |
| }; | |
| Game_Player.prototype.canInput = function() { | |
| if ($gameMap.isEventRunning() || $gameMessage.isBusy()) { | |
| return false; | |
| } | |
| return this.canInputSkill() && !this._groundTargeting; | |
| }; | |
| Game_Player.prototype.usableSkills = function() { | |
| return this.battler().skills().filter(function(skill) { | |
| return !this._skillCooldowns[skill.id]; | |
| }, this).map(function(skill) { | |
| return skill.id; | |
| }); | |
| }; | |
| Game_Player.prototype.onDeath = function() { | |
| this.clearABS(); | |
| this._isDead = true; | |
| SceneManager.goto(Scene_Gameover); | |
| }; | |
| var Alias_Game_Player_onPositionChange = Game_Player.prototype.onPositionChange; | |
| Game_Player.prototype.onPositionChange = function() { | |
| Alias_Game_Player_onPositionChange.call(this); | |
| if (this._groundTargeting && !QABS.lockTargeting) { | |
| this.onTargetingCancel(); | |
| } | |
| }; | |
| var Alias_Game_Player_collidesWithEvent = Game_Player.prototype.collidesWithEvent; | |
| Game_Player.prototype.collidesWithEvent = function(event, type) { | |
| if (event.constructor === Game_Loot) { | |
| return event.collider('interaction').intersects(this.collider(type)); | |
| } | |
| return Alias_Game_Player_collidesWithEvent.call(this, event, type); | |
| }; | |
| Game_Player.prototype.updateABS = function() { | |
| if (this._isDead) return; | |
| if (this.battler() && this.canInput()) this.updateABSInput(); | |
| Game_CharacterBase.prototype.updateABS.call(this); | |
| if (this._battlerId !== this.actor()._actorId) { | |
| this.clearABS(); | |
| this.setupBattler(); | |
| } | |
| }; | |
| Game_Player.prototype.updateABSInput = function() { | |
| var absKeys = $gameSystem.absKeys(); | |
| for (var key in absKeys) { | |
| if (!absKeys[key]) continue; | |
| var inputs = absKeys[key].input; | |
| for (var i = 0; i < inputs.length; i++) { | |
| var input = inputs[i]; | |
| if (Input.isTriggered(input) || Input.isPressed(input)) { | |
| Input.stopPropagation(); | |
| this.useSkill(absKeys[key].skillId); | |
| break; | |
| } | |
| if (input === 'mouse1' && (TouchInput.isTriggered() || TouchInput.isPressed()) && this.canClick()) { | |
| TouchInput.stopPropagation(); | |
| this.useSkill(absKeys[key].skillId); | |
| break; | |
| } | |
| if (input === 'mouse2' && TouchInput.isCancelled() && this.canClick()) { | |
| TouchInput.stopPropagation(); | |
| this.useSkill(absKeys[key].skillId); | |
| break; | |
| } | |
| } | |
| } | |
| }; | |
| Game_Player.prototype.updateTargeting = function() { | |
| return this._selectTargeting ? this.updateSelectTargeting() : this.updateGroundTargeting(); | |
| }; | |
| Game_Player.prototype.updateSelectTargeting = function() { | |
| // TODO add mouse support | |
| if (Input.isTriggered('pageup')) { | |
| Input.stopPropagation(); | |
| this._groundTargeting.index++; | |
| this.updateSkillTarget(); | |
| } | |
| if (Input.isTriggered('pagedown')) { | |
| Input.stopPropagation(); | |
| this._groundTargeting.index--; | |
| this.updateSkillTarget(); | |
| } | |
| if (Input.isTriggered('ok')) { | |
| Input.stopPropagation(); | |
| this.onTargetingEnd(); | |
| } | |
| if (Input.isTriggered('escape') || TouchInput.isCancelled()) { | |
| TouchInput.stopPropagation(); | |
| Input.stopPropagation(); | |
| this.onTargetingCancel(); | |
| } | |
| }; | |
| Game_Player.prototype.updateSkillTarget = function() { | |
| var skill = this._groundTargeting; | |
| if (skill.index < 0) skill.index = skill.targets.length - 1; | |
| if (skill.index >= skill.targets.length) skill.index = 0; | |
| var target = skill.targets[skill.index]; | |
| var w = skill.collider.width; | |
| var h = skill.collider.height; | |
| var x = target.cx() - w / 2; | |
| var y = target.cy() - h / 2; | |
| skill.collider.moveTo(x, y); | |
| }; | |
| Game_Player.prototype.updateGroundTargeting = function() { | |
| this.updateGroundTargetingPosition(); | |
| if (Input.isTriggered('escape') || TouchInput.isCancelled()) { | |
| TouchInput.stopPropagation(); | |
| Input.stopPropagation(); | |
| this.onTargetingCancel(); | |
| } | |
| if (Input.isTriggered('ok') || (this.canClick() && TouchInput.isTriggered()) || | |
| QABS.quickTarget) { | |
| if (!this._groundTargeting.isOk) { | |
| TouchInput.stopPropagation(); | |
| Input.stopPropagation(); | |
| this.onTargetingCancel(); | |
| } else { | |
| this.onTargetingEnd(); | |
| } | |
| } | |
| }; | |
| Game_Player.prototype.updateGroundTargetingPosition = function() { | |
| var skill = this._groundTargeting; | |
| var w = skill.collider.width; | |
| var h = skill.collider.height; | |
| if (Imported.QInput && Input.preferGamepad()) { | |
| var x1 = skill.collider.center.x; | |
| var y1 = skill.collider.center.y; | |
| x1 += Input._dirAxesB.x * 5; | |
| y1 += Input._dirAxesB.y * 5; | |
| } else { | |
| var x1 = $gameMap.canvasToMapPX(TouchInput.x); | |
| var y1 = $gameMap.canvasToMapPY(TouchInput.y); | |
| } | |
| var x2 = x1 - w / 2; | |
| var y2 = y1 - h / 2; | |
| this.setRadian(Math.atan2(y1 - this.cy(), x1 - this.cx())); | |
| skill.radian = this._radian; | |
| skill.collider.moveTo(x2, y2); | |
| var dx = Math.abs(this.cx() - x2 - w / 2); | |
| var dy = Math.abs(this.cy() - y2 - h / 2); | |
| var distance = Math.sqrt(dx * dx + dy * dy); | |
| skill.isOk = distance <= skill.settings.range; | |
| skill.collider.color = skill.isOk ? '#00ff00' : '#ff0000'; | |
| }; | |
| Game_Player.prototype.beforeSkill = function(skill) { | |
| var meta = skill.data.qmeta; | |
| var isGamepad = Imported.QInput && Input.preferGamepad(); | |
| if (!meta.dontTurn) { | |
| if (isGamepad && QABS.towardsAnalog) { | |
| var horz = Input._dirAxesB.x; | |
| var vert = Input._dirAxesB.y; | |
| if (horz !== 0 || vert !== 0) { | |
| this.setRadian(Math.atan2(vert, horz)); | |
| skill.radian = this._radian; | |
| } | |
| } else if (!isGamepad && QABS.towardsMouse) { | |
| var x1 = $gameMap.canvasToMapPX(TouchInput.x); | |
| var y1 = $gameMap.canvasToMapPY(TouchInput.y); | |
| var x2 = this.cx(); | |
| var y2 = this.cy(); | |
| this.setRadian(Math.atan2(y1 - y2, x1 - x2)); | |
| skill.radian = this._radian; | |
| } | |
| } | |
| if (meta.towardsMove) { | |
| var radian; | |
| if (isGamepad) { | |
| var horz = Input._dirAxesA.x; | |
| var vert = Input._dirAxesA.y; | |
| if (horz === 0 && vert === 0) { | |
| radian = skill.radian; | |
| } else { | |
| radian = Math.atan2(vert, horz); | |
| } | |
| } else { | |
| var direction = QMovement.diagonal ? Input.dir8 : Input.dir4; | |
| if (direction === 0) { | |
| radian = skill.radian; | |
| } else { | |
| radian = this.directionToRadian(direction); | |
| } | |
| } | |
| skill.radian = radian; | |
| } | |
| Game_CharacterBase.prototype.beforeSkill.call(this, skill); | |
| }; | |
| Game_Player.prototype.makeTargetingSkill = function(skill) { | |
| Game_CharacterBase.prototype.makeTargetingSkill.call(this, skill); | |
| if (this._selectTargeting) { | |
| this.updateSkillTarget(); | |
| } | |
| }; | |
| var Alias_Game_Player_requestMouseMove = Game_Player.prototype.requestMouseMove; | |
| Game_Player.prototype.requestMouseMove = function() { | |
| if ($gameSystem.anyAbsMouse()) return this.clearMouseMove(); | |
| if (this._groundTargeting) return this.clearMouseMove(); | |
| Alias_Game_Player_requestMouseMove.call(this); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Event | |
| (function() { | |
| var Alias_Game_Event_initialize = Game_Event.prototype.initialize; | |
| Game_Event.prototype.initialize = function(mapId, eventId) { | |
| Alias_Game_Event_initialize.call(this, mapId, eventId); | |
| this.setupBattler(); | |
| }; | |
| Game_Event.prototype.battler = function() { | |
| return this._battler; | |
| }; | |
| Game_Event.prototype.setupBattler = function() { | |
| var foe = /<enemy:([0-9]*?)>/i.exec(this.notes()); | |
| if (foe) { | |
| this.clearABS(); | |
| this._battlerId = Number(foe[1]); | |
| this._battler = new Game_Enemy(this._battlerId, 0, 0); | |
| this._battler._charaId = this.charaId(); | |
| this._skillList = []; | |
| this._aiType = this._battler._aiType; | |
| this._aiRange = this._battler._aiRange || QABS.aiLength; | |
| this._aiWait = 0; | |
| this._aiPathfind = Imported.QPathfind && QABS.aiPathfind && this.validAI(); | |
| this._aiSight = Imported.QSight && QABS.aiSight && this.validAI(); | |
| if (this._aiSight) { | |
| this.setupSight({ | |
| shape: 'circle', | |
| range: this._aiRange / QMovement.tileSize, | |
| handler: 'AI', | |
| targetId: '0' | |
| }); | |
| } | |
| var actions = this._battler.enemy().actions; | |
| for (var i = 0; i < actions.length; i++) { | |
| this._skillList.push(actions[i].skillId); | |
| } | |
| this._respawn = -1; | |
| this._onDeath = this._battler._onDeath; | |
| this._noPopup = this._battler._noPopup; | |
| this._dontErase = this._battler._dontErase; | |
| this._team = this._battler._team; | |
| this._isDead = false; | |
| } | |
| }; | |
| var Alias_Game_Event_comments = Game_Event.prototype.comments; | |
| Game_Event.prototype.comments = function(withNotes) { | |
| var comments = Alias_Game_Event_comments.call(this, withNotes); | |
| if (!this._aiSight) return comments; | |
| var range = this._aiRange / QMovement.tileSize; | |
| return comments + '<sight:circle,' + range + ', AI, 0>'; | |
| }; | |
| Game_Event.prototype.canSeeThroughChara = function(chara) { | |
| if (typeof chara.team === 'function' && chara.team() === this.team()) { | |
| return true; | |
| } else if (this._isDead || (typeof chara.battler === 'function' && chara.battler() && chara.battler().isDead())) { | |
| return true; | |
| } | |
| return Game_CharacterBase.prototype.canSeeThroughChara.call(this, chara); | |
| }; | |
| Game_Event.prototype.disableEnemy = function() { | |
| $gameSystem.disableEnemy(this._mapId, this._eventId); | |
| this.clearABS(); | |
| this._battler = null; | |
| }; | |
| Game_Event.prototype.team = function() { | |
| return this._battler ? this._team : 0; | |
| }; | |
| Game_Event.prototype.usableSkills = function() { | |
| if (!this._battler) return []; | |
| return this._skillList.filter(function(skillId) { | |
| return !this._skillCooldowns[skillId]; | |
| }, this); | |
| }; | |
| var Alias_Game_Event_bestTarget = Game_Event.prototype.bestTarget; | |
| Game_Event.prototype.bestTarget = function() { | |
| var best = Alias_Game_Event_bestTarget.call(this); | |
| if (!best && this.team() === 2) { | |
| return $gamePlayer; | |
| } | |
| return best; | |
| }; | |
| Game_Event.prototype.updateABS = function() { | |
| if ($gameSystem.isDisabled(this._mapId, this._eventId)) return; | |
| Game_CharacterBase.prototype.updateABS.call(this); | |
| if (this.page() && !this._isDead && this.isNearTheScreen() && this.validAI()) { | |
| return this.updateAI(this._aiType); | |
| } | |
| if (this._respawn >= 0) { | |
| this.updateRespawn(); | |
| } | |
| }; | |
| Game_Event.prototype.validAI = function() { | |
| // if added new AI types, expand here with its name so the | |
| // updateAI will run | |
| return this._aiType === "simple"; | |
| }; | |
| Game_Event.prototype.updateAI = function(type) { | |
| if (type === 'simple') { | |
| return this.updateAISimple(); | |
| } | |
| // to add more AI types, alias this function | |
| // and do something similar to above | |
| }; | |
| Game_Event.prototype.updateAISimple = function() { | |
| var bestTarget = this.bestTarget(); | |
| if (!bestTarget) return; | |
| var targetId = bestTarget.charaId(); | |
| if (!this.AISimpleInRange(bestTarget)) return; | |
| this.AISimpleAction(bestTarget, this.AISimpleGetAction(bestTarget)); | |
| }; | |
| Game_Event.prototype.removeAgro = function(charaId) { | |
| if (!this._agro) return; | |
| Game_CharacterBase.prototype.removeAgro.call(this, charaId); | |
| if (!this.inCombat() && !this._endWait) { | |
| this.endCombat(); | |
| } | |
| }; | |
| Game_Event.prototype.AISimpleInRange = function(bestTarget) { | |
| var targetId = bestTarget.charaId(); | |
| if (this.isTargetInRange(bestTarget)) { | |
| this._agro.placeInCombat(); | |
| if (!this._agro.has(targetId)) { | |
| this._aiWait = QABS.aiWait; | |
| this.addAgro(targetId); | |
| if (this._aiPathfind) { | |
| this.clearPathfind(); | |
| } | |
| } | |
| if (this._endWait) { | |
| this.removeWaitListener(this._endWait); | |
| this._endWait = null; | |
| } | |
| return true; | |
| } else { | |
| if (this._agro.has(targetId)) { | |
| if (this._aiPathfind) { | |
| this.clearPathfind(); | |
| } | |
| this._endWait = this.wait(90).then(function() { | |
| this._endWait = null; | |
| this.endCombat(); | |
| }.bind(this)); | |
| this.removeAgro(targetId); | |
| } | |
| if (this._endWait && this.canMove()) { | |
| this.moveTowardCharacter(bestTarget); | |
| } | |
| return false; | |
| } | |
| return false; | |
| }; | |
| Game_Event.prototype.AISimpleGetAction = function(bestTarget) { | |
| var bestAction = null; | |
| if (this._aiWait >= QABS.aiWait) { | |
| this.turnTowardCharacter(bestTarget); | |
| bestAction = QABSManager.bestAction(this.charaId()); | |
| this._aiWait = 0; | |
| } else { | |
| this._aiWait++; | |
| } | |
| return bestAction; | |
| }; | |
| Game_Event.prototype.AISimpleAction = function(bestTarget, bestAction) { | |
| if (bestAction) { | |
| var skill = this.useSkill(bestAction); | |
| if (skill) skill._target = bestTarget; | |
| } else if (this.canMove()) { | |
| if (this._aiPathfind) { | |
| var dx = bestTarget.cx() - this.cx(); | |
| var dy = bestTarget.cy() - this.cy(); | |
| var mw = this.collider('collision').width + bestTarget.collider('collision').width; | |
| var mh = this.collider('collision').height + bestTarget.collider('collision').height; | |
| if (Math.abs(dx) <= mw && Math.abs(dy) <= mh) { | |
| this.clearPathfind(); | |
| this.moveTowardCharacter(bestTarget); | |
| } else { | |
| this.initChase(bestTarget.charaId()); | |
| } | |
| } else { | |
| this.moveTowardCharacter(bestTarget); | |
| } | |
| } | |
| }; | |
| Game_Event.prototype.isTargetInRange = function(target) { | |
| if (!target) return false; | |
| if (this._aiSight) { | |
| var prev = this._sight.range; | |
| if (this.inCombat()) { | |
| this._sight.range = this._aiRange + QMovement.tileSize * 3; | |
| } else { | |
| this._sight.range = this._aiRange; | |
| } | |
| this._sight.range /= QMovement.tileSize; | |
| if (prev !== this._sight.range) { | |
| if (this._sight.base) { | |
| this._sight.base.kill = true; | |
| this._sight.base.id = 'sightOld' + this.charaId(); | |
| } | |
| this._sight.base = null; | |
| this._sight.reshape = true; | |
| } | |
| if (this._sight.targetId !== target.charaId()) { | |
| delete this._sight.cache.charas[this._sight.targetId]; | |
| this._sight.targetId = target.charaId(); | |
| this._sight.reshape = true; | |
| } | |
| if (this._sight.reshape) { | |
| this.updateSight(); | |
| } | |
| var key = [this._mapId, this._eventId, this._sight.handler]; | |
| return $gameSelfSwitches.value(key); | |
| } | |
| var dx = Math.abs(target.cx() - this.cx()); | |
| var dy = Math.abs(target.cy() - this.cy()); | |
| var range = this._aiRange + (this.inCombat() ? 96 : 0); | |
| return dx <= range && dy <= range; | |
| }; | |
| Game_Event.prototype.updateRespawn = function() { | |
| if (this._respawn === 0) { | |
| this.respawn(); | |
| } else { | |
| this._respawn--; | |
| } | |
| }; | |
| Game_Event.prototype.respawn = function() { | |
| this._erased = false; | |
| this.refresh(); | |
| this.findRespawnLocation(); | |
| this.setupBattler(); | |
| }; | |
| Game_Event.prototype.endCombat = function() { | |
| if (this._aiPathfind) { | |
| this.clearPathfind(); | |
| } | |
| this.clearAgro(); | |
| if (this._aiPathfind || Imported.QPathfind) { | |
| var x = this.event().x * QMovement.tileSize; | |
| var y = this.event().y * QMovement.tileSize; | |
| this.initPathfind(x, y, { | |
| smart: 1, | |
| adjustEnd: true | |
| }); | |
| } else { | |
| this.findRespawnLocation(); | |
| } | |
| this.refresh(); | |
| }; | |
| Game_Event.prototype.findRespawnLocation = function() { | |
| var x = this.event().x * QMovement.tileSize; | |
| var y = this.event().y * QMovement.tileSize; | |
| if (this.canPixelPass(x, y, 5)) { | |
| this.setPixelPosition(x, y); | |
| this.straighten(); | |
| this.refreshBushDepth(); | |
| return; | |
| } | |
| var dist = Math.min(this.collider('collision').width, this.collider('collision').height); | |
| dist = Math.max(dist / 2, this.moveTiles()); | |
| var open = [x + ',' + y]; | |
| var closed = []; | |
| var current; | |
| var x2; | |
| var y2; | |
| while (open.length) { | |
| current = open.shift(); | |
| closed.push(current); | |
| current = current.split(',').map(Number); | |
| var passed; | |
| for (var i = 1; i < 5; i++) { | |
| var dir = i * 2; | |
| x2 = Math.round($gameMap.roundPXWithDirection(current[0], dir, dist)); | |
| y2 = Math.round($gameMap.roundPYWithDirection(current[1], dir, dist)); | |
| if (this.canPixelPass(x2, y2, 5)) { | |
| passed = true; | |
| break; | |
| } | |
| var key = x2 + ',' + y2; | |
| if (!closed.contains(key) && !open.contains(key)) { | |
| open.push(key); | |
| } | |
| } | |
| if (passed) break; | |
| } | |
| this.setPixelPosition(x2, y2); | |
| this.straighten(); | |
| this.refreshBushDepth(); | |
| }; | |
| Game_Event.prototype.onDeath = function() { | |
| if (this._onDeath) { | |
| try { | |
| eval(this._onDeath); | |
| } catch (e) { | |
| var id = this.battler()._enemyId; | |
| console.error('Error with `onDeath` meta inside enemy ' + id, e); | |
| } | |
| } | |
| if (this._agro.has(0)) { | |
| var exp = this.battler().exp(); | |
| $gamePlayer.battler().gainExp(exp); | |
| if (exp > 0) { | |
| QABSManager.startPopup('QABS-EXP', { | |
| x: $gamePlayer.cx(), y: $gamePlayer.cy(), | |
| string: 'Exp: ' + exp | |
| }); | |
| } | |
| this.setupLoot(); | |
| } | |
| this.clearABS(); | |
| this._respawn = Number(this.battler().enemy().meta.respawn) || -1; | |
| this._isDead = true; | |
| if (!this._dontErase) this.erase(); | |
| }; | |
| Game_Event.prototype.setupLoot = function() { | |
| var x, y; | |
| var loot = []; | |
| this.battler().makeDropItems().forEach(function(item) { | |
| x = this.x + (Math.random() / 2) - (Math.random() / 2); | |
| y = this.y + (Math.random() / 2) - (Math.random() / 2); | |
| var type = 0; | |
| if (DataManager.isWeapon(item)) type = 1; | |
| if (DataManager.isArmor(item)) type = 2; | |
| loot.push(QABSManager.createItem(x, y, item.id, type)); | |
| }.bind(this)); | |
| if (this.battler().gold() > 0) { | |
| x = this.x + (Math.random() / 2) - (Math.random() / 2); | |
| y = this.y + (Math.random() / 2) - (Math.random() / 2); | |
| loot.push(QABSManager.createGold(x, y, this.battler().gold())); | |
| } | |
| if (this.battler().enemy().meta.autoLoot) { | |
| var prevAoeLoot = QABS.aoeLoot; | |
| QABS.aoeLoot = false; | |
| loot.forEach(function(loot) { | |
| loot.collectDrops(); | |
| }); | |
| } | |
| }; | |
| Game_Event.prototype.onTargetingEnd = function() { | |
| var skill = this._groundTargeting; | |
| var target = skill.targets[Math.floor(Math.random() * skill.targets.length)]; | |
| var w = skill.collider.width; | |
| var h = skill.collider.height; | |
| var x = target.cx() - w / 2; | |
| var y = target.cy() - h / 2; | |
| skill.collider.moveTo(x, y); | |
| skill.picture.move(x + w / 2, y + h / 2); | |
| Game_CharacterBase.prototype.onTargetingEnd.call(this); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Game_Loot | |
| function Game_Loot() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Game_Loot.prototype = Object.create(Game_Event.prototype); | |
| Game_Loot.prototype.constructor = Game_Loot; | |
| Game_Loot.prototype.initialize = function(x, y) { | |
| Game_Character.prototype.initialize.call(this); | |
| this.isLoot = true; | |
| this._decay = QABS.lootDecay; | |
| this._eventId = -1; | |
| this._gold = null; | |
| this._loot = null; | |
| this._noSprite = true; | |
| this.locate(x, y); | |
| QABSManager.addEvent(this); | |
| this.refresh(); | |
| }; | |
| Game_Loot.prototype.event = function() { | |
| return { | |
| note: '' | |
| } | |
| }; | |
| Game_Loot.prototype.shiftY = function() { | |
| return 0; | |
| }; | |
| Game_Loot.prototype.setGold = function(value) { | |
| this._gold = value; | |
| this.setIcon(QABS.goldIcon); | |
| }; | |
| Game_Loot.prototype.setItem = function(item) { | |
| this._loot = item; | |
| this.setIcon(item.iconIndex); | |
| }; | |
| Game_Loot.prototype.setIcon = function(iconIndex) { | |
| this._iconIndex = iconIndex; | |
| this._itemIcon = new Sprite_Icon(iconIndex); | |
| this._itemIcon.move(this._px, this._py); | |
| this._itemIcon.z = 1; | |
| this._itemIcon._isFixed = true; | |
| QABSManager.addPicture(this._itemIcon); | |
| }; | |
| Game_Loot.prototype.page = function() { | |
| if (!this._lootPage) { | |
| this._lootPage = { | |
| conditions: { | |
| actorId: 1, actorValid: false, | |
| itemId: 1, itemValid: false, | |
| selfSwitchCh: 'A', selfSwitchValid: false, | |
| switch1Id: 1, switch1Valid: false, | |
| switch2Id: 1, switch2Valid: false, | |
| variable1Id: 1, variable1Valid: false, variableValue: 0 | |
| }, | |
| image: { | |
| characterIndex: 0, characterName: '', | |
| direction: 2, pattern: 1, tileId: 0 | |
| }, | |
| moveRoute: { | |
| list: [{ code: 0, parameters: [] }], | |
| repeat: false, skippable: false, wait: false | |
| }, | |
| list: [], | |
| directionFix: false, | |
| moveFrequency: 4, | |
| moveSpeed: 3, | |
| moveType: 0, | |
| priorityType: 0, | |
| stepAnime: false, | |
| through: true, | |
| trigger: QABS.lootTrigger, | |
| walkAnime: true | |
| }; | |
| this._lootPage.list = []; | |
| this._lootPage.list.push({ | |
| code: 355, | |
| indent: 0, | |
| parameters: ['this.character().collectDrops();'] | |
| }); | |
| this._lootPage.list.push({ | |
| code: 0, | |
| indent: 0, | |
| parameters: [0] | |
| }); | |
| } | |
| return this._lootPage; | |
| }; | |
| Game_Loot.prototype.findProperPageIndex = function() { | |
| return 0; | |
| }; | |
| Game_Loot.prototype.collectDrops = function() { | |
| if (QABS.aoeLoot) { | |
| return this.aoeCollect(); | |
| } | |
| if (this._loot) $gameParty.gainItem(this._loot, 1); | |
| if (this._gold) $gameParty.gainGold(this._gold); | |
| var string = this._gold ? String(this._gold) : this._loot.name; | |
| if (this._iconIndex) { | |
| string = '\\I[' + this._iconIndex + ']' + string; | |
| } | |
| QABSManager.startPopup('QABS-ITEM', { | |
| x: this.cx(), y: this.cy(), | |
| string: string | |
| }); | |
| this.erase(); | |
| QABSManager.removeEvent(this); | |
| QABSManager.removePicture(this._itemIcon); | |
| }; | |
| Game_Loot.prototype.aoeCollect = function() { | |
| var loot = ColliderManager.getCharactersNear(this.collider(), function(chara) { | |
| return chara.constructor === Game_Loot && | |
| chara.collider().intersects(this.collider()); | |
| }.bind(this)); | |
| var x = this.cx(); | |
| var y = this.cy(); | |
| var totalLoot = []; | |
| var totalGold = 0; | |
| var i; | |
| for (i = 0; i < loot.length; i++) { | |
| if (loot[i]._loot) totalLoot.push(loot[i]._loot); | |
| if (loot[i]._gold) totalGold += loot[i]._gold; | |
| QABSManager.removeEvent(loot[i]); | |
| QABSManager.removePicture(loot[i]._itemIcon); | |
| } | |
| var display = {}; | |
| for (i = 0; i < totalLoot.length; i++) { | |
| var item = totalLoot[i]; | |
| $gameParty.gainItem(item, 1); | |
| display[item.name] = display[item.name] || {}; | |
| display[item.name].iconIndex = item.iconIndex; | |
| display[item.name].total = display[item.name].total + 1 || 1; | |
| } | |
| for (var name in display) { | |
| var iconIndex = display[name].iconIndex; | |
| var string = 'x' + display[name].total + ' ' + name; | |
| if (iconIndex) { | |
| string = '\\I[' + iconIndex + ']' + string; | |
| } | |
| QABSManager.startPopup('QABS-ITEM', { | |
| x: x, y: y, | |
| string: string | |
| }); | |
| y += 22; | |
| } | |
| if (totalGold > 0) { | |
| $gameParty.gainGold(totalGold); | |
| var string = String(totalGold); | |
| if (QABS.goldIcon) { | |
| string = '\\I[' + QABS.goldIcon + ']' + string; | |
| } | |
| QABSManager.startPopup('QABS-ITEM', { | |
| x: x, y: y, | |
| string: string | |
| }); | |
| } | |
| }; | |
| Game_Loot.prototype.update = function() { | |
| if (this._decay <= 0) { | |
| this.erase(); | |
| QABSManager.removeEvent(this); | |
| QABSManager.removePicture(this._itemIcon); | |
| return; | |
| } | |
| this._decay--; | |
| }; | |
| Game_Loot.prototype.defaultColliderConfig = function() { | |
| return 'box,48,48,-8,-8'; | |
| }; | |
| Game_Loot.prototype.castsShadow = function() { | |
| return false; | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Scene_Map | |
| (function() { | |
| var Alias_Scene_Map_initialize = Scene_Map.prototype.initialize; | |
| Scene_Map.prototype.initialize = function() { | |
| Alias_Scene_Map_initialize.call(this); | |
| $gameSystem.preloadAllSkills(); | |
| }; | |
| var Alias_Scene_Map_isMenuCalled = Scene_Map.prototype.isMenuCalled; | |
| Scene_Map.prototype.isMenuCalled = function() { | |
| if ($gameSystem.anyAbsMouse2()) return Input.isTriggered('menu'); | |
| return Alias_Scene_Map_isMenuCalled(this); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Sprite_Character | |
| (function() { | |
| var Alias_Sprite_Character_initMembers = Sprite_Character.prototype.initMembers; | |
| Sprite_Character.prototype.initMembers = function() { | |
| Alias_Sprite_Character_initMembers.call(this); | |
| this.createStateSprite(); | |
| }; | |
| Sprite_Character.prototype.createStateSprite = function() { | |
| this._stateSprite = new Sprite_StateOverlay(); | |
| this.addChild(this._stateSprite); | |
| }; | |
| var Alias_Sprite_Character_update = Sprite_Character.prototype.update; | |
| Sprite_Character.prototype.update = function() { | |
| Alias_Sprite_Character_update.call(this); | |
| if (this._character) this.updateBattler(); | |
| if (this._battler) this.updateDamagePopup(); | |
| }; | |
| Sprite_Character.prototype.updateDamagePopup = function() { | |
| this.setupDamagePopup(); | |
| }; | |
| Sprite_Character.prototype.updateBattler = function() { | |
| if (this._battler !== this._character.battler()) { | |
| this.setBattler(this._character.battler()); | |
| } | |
| }; | |
| Sprite_Character.prototype.setBattler = function(battler) { | |
| this._battler = battler; | |
| this._stateSprite.setup(this._battler); | |
| }; | |
| Sprite_Character.prototype.setupDamagePopup = function() { | |
| if (!Imported.QPopup || this._character._noPopup) return; | |
| if (this._battler._damageQueue.length > 0) { | |
| var string; | |
| var fill = '#ffffff'; | |
| var result = this._battler._damageQueue.shift(); | |
| var type = 'DMG'; | |
| if (result.missed || result.evaded) { | |
| string = 'Missed'; | |
| type = 'MISSED'; | |
| } else if (result.hpAffected) { | |
| var dmg = result.hpDamage; | |
| string = String(Math.abs(dmg)); | |
| if (dmg >= 0) { | |
| type = 'DMG'; | |
| } else { | |
| type = 'HEAL'; | |
| } | |
| } else if (result.mpDamage) { | |
| string = String(result.mpDamage); | |
| type = 'MP'; | |
| } | |
| if (!string && string !== '0') return; | |
| var iconIndex = result.damageIcon; | |
| if (iconIndex) { | |
| string = '\\I[' + iconIndex + ']' + string; | |
| } | |
| if (result.critical) { | |
| type += '-CRIT'; | |
| } | |
| QABSManager.startPopup('QABS-' + type, { | |
| string: string, | |
| oy: this._battler._popupOY, | |
| bindTo: this._character.charaId(), | |
| duration: 80 | |
| }); | |
| this._battler.clearDamagePopup(); | |
| this._battler.clearResult(); | |
| } | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Sprite_Icon | |
| function Sprite_Icon() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Sprite_Icon.prototype = Object.create(Sprite.prototype); | |
| Sprite_Icon.prototype.constructor = Sprite_Icon; | |
| Sprite_Icon.prototype.initialize = function(index, sheet, w, h) { | |
| Sprite.prototype.initialize.call(this); | |
| this._iconIndex = index; | |
| this._iconSheet = sheet || 'IconSet'; | |
| this._iconW = w || 32; | |
| this._iconH = h || 32; | |
| this._realX = this.x; | |
| this._realY = this.y; | |
| this._isFixed = false; | |
| this.setBitmap(); | |
| }; | |
| Sprite_Icon.prototype.setBitmap = function() { | |
| this.bitmap = ImageManager.loadSystem(this._iconSheet); | |
| var pw = this._iconW; | |
| var ph = this._iconH; | |
| var sx = this._iconIndex % 16 * pw; | |
| var sy = Math.floor(this._iconIndex / 16) * ph; | |
| this.setFrame(sx, sy, pw, ph); | |
| }; | |
| Sprite_Icon.prototype.update = function() { | |
| Sprite.prototype.update.call(this); | |
| if (this._isFixed) this.updatePosition(); | |
| }; | |
| Sprite_Icon.prototype.updatePosition = function() { | |
| this.x = this._realX; | |
| this.x -= $gameMap.displayX() * QMovement.tileSize; | |
| this.y = this._realY; | |
| this.y -= $gameMap.displayY() * QMovement.tileSize; | |
| }; | |
| Sprite_Icon.prototype.move = function(x, y) { | |
| Sprite.prototype.move.call(this, x, y); | |
| this._realX = x; | |
| this._realY = y; | |
| this.updatePosition(); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Sprite_SkillPicture | |
| function Sprite_SkillPicture() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Sprite_SkillPicture.prototype = Object.create(Sprite.prototype); | |
| Sprite_SkillPicture.prototype.constructor = Sprite_SkillPicture; | |
| Sprite_SkillPicture.prototype.initialize = function() { | |
| Sprite.prototype.initialize.call(this); | |
| this._maxFrames = 1; | |
| this._speed = 0; | |
| this._isAnimated = false; | |
| this._tick = 0; | |
| this._frameI = 0; | |
| this._lastFrameI = null; | |
| this._realX = this.x; | |
| this._realY = this.y; | |
| }; | |
| Sprite_SkillPicture.prototype.setupAnim = function(frames, speed) { | |
| this._isAnimated = true; | |
| this._maxFrames = frames; | |
| this._speed = speed; | |
| }; | |
| Sprite_SkillPicture.prototype.update = function() { | |
| Sprite.prototype.update.call(this); | |
| this.updatePosition(); | |
| if (this._isAnimated) this.updateAnimation(); | |
| this.updateFrame(); | |
| }; | |
| Sprite_SkillPicture.prototype.updatePosition = function() { | |
| this.x = this._realX; | |
| this.x -= $gameMap.displayX() * QMovement.tileSize; | |
| this.y = this._realY; | |
| this.y -= $gameMap.displayY() * QMovement.tileSize; | |
| }; | |
| Sprite_SkillPicture.prototype.updateAnimation = function() { | |
| if (this._tick % this._speed === 0) { | |
| this._frameI = (this._frameI + 1) % this._maxFrames; | |
| } | |
| this._tick = (this._tick + 1) % this._speed; | |
| }; | |
| Sprite_SkillPicture.prototype.updateFrame = function() { | |
| if (this._lastFrameI !== null) { | |
| if (this._lastFrameI === this._frameI) return; | |
| } | |
| var i = this._frameI; | |
| var pw = this.bitmap.width / this._maxFrames; | |
| var ph = this.bitmap.height; | |
| var sx = i * pw; | |
| this.setFrame(sx, 0, pw, ph); | |
| this._lastFrameI = i; | |
| }; | |
| Sprite_SkillPicture.prototype.move = function(x, y) { | |
| Sprite.prototype.move.call(this, x, y); | |
| this._realX = x; | |
| this._realY = y; | |
| this.updatePosition(); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Sprite_SkillTrail | |
| function Sprite_SkillTrail() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Sprite_SkillTrail.prototype = Object.create(TilingSprite.prototype); | |
| Sprite_SkillTrail.prototype.constructor = Sprite_SkillTrail; | |
| Sprite_SkillTrail.prototype.initialize = function() { | |
| TilingSprite.prototype.initialize.call(this); | |
| this._realX = this.x; | |
| this._realY = this.y; | |
| }; | |
| Sprite_SkillTrail.prototype.update = function() { | |
| TilingSprite.prototype.update.call(this); | |
| this.updatePosition(); | |
| }; | |
| Sprite_SkillTrail.prototype.updatePosition = function() { | |
| this.x = this._realX; | |
| this.x -= $gameMap.displayX() * QMovement.tileSize; | |
| this.y = this._realY; | |
| this.y -= $gameMap.displayY() * QMovement.tileSize; | |
| }; | |
| Sprite_SkillTrail.prototype.move = function(x, y, width, height) { | |
| TilingSprite.prototype.move.call(this, x, y, width, height); | |
| this._realX = x; | |
| this._realY = y; | |
| this.updatePosition(); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Sprite_MapAnimation | |
| function Sprite_MapAnimation() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Sprite_MapAnimation.prototype = Object.create(Sprite_Base.prototype); | |
| Sprite_MapAnimation.prototype.constructor = Sprite_MapAnimation; | |
| Sprite_MapAnimation.prototype.initialize = function(animation) { | |
| Sprite_Base.prototype.initialize.call(this); | |
| this.z = 8; | |
| this._realX = this.x; | |
| this._realY = this.y; | |
| this._animation = animation; | |
| this._hasStarted = false; | |
| }; | |
| Sprite_MapAnimation.prototype.update = function() { | |
| Sprite_Base.prototype.update.call(this); | |
| this.updatePosition(); | |
| if (!this._hasStarted && this.parent) { | |
| this.startAnimation(this._animation, false, 0); | |
| this._hasStarted = true; | |
| } | |
| if (this._hasStarted && !this.isAnimationPlaying()) { | |
| QABSManager.removeAnimation(this); | |
| } | |
| }; | |
| Sprite_MapAnimation.prototype.updatePosition = function() { | |
| this.x = this._realX; | |
| this.x -= $gameMap.displayX() * QMovement.tileSize; | |
| this.y = this._realY; | |
| this.y -= $gameMap.displayY() * QMovement.tileSize; | |
| }; | |
| Sprite_MapAnimation.prototype.move = function(x, y) { | |
| Sprite_Base.prototype.move.call(this, x, y); | |
| this._realX = x; | |
| this._realY = y; | |
| this.updatePosition(); | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Sprite_SkillCollider | |
| function Sprite_SkillCollider() { | |
| this.initialize.apply(this, arguments); | |
| } | |
| (function() { | |
| Sprite_SkillCollider.prototype = Object.create(Sprite_Collider.prototype); | |
| Sprite_SkillCollider.prototype.constructor = Sprite_SkillCollider; | |
| Sprite_SkillCollider.prototype.initialize = function(collider) { | |
| Sprite_Collider.prototype.initialize.call(this, collider, -1); | |
| this.z = 2; | |
| this.alpha = 0.4; | |
| this.anchor.x = 0.5; | |
| this.anchor.y = 0.5; | |
| this._frameCount = 0; | |
| }; | |
| Sprite_SkillCollider.prototype.update = function() { | |
| Sprite_Collider.prototype.update.call(this); | |
| this.updateAnimation(); | |
| }; | |
| Sprite_SkillCollider.prototype.updateAnimation = function() { | |
| this._frameCount++; | |
| if (this._frameCount > 30) { | |
| this.alpha += 0.2 / 30; | |
| this.scale.x += 0.1 / 30; | |
| this.scale.y = this.scale.x; | |
| if (this._frameCount === 60) this._frameCount = 0; | |
| } else { | |
| this.alpha -= 0.2 / 30; | |
| this.scale.x -= 0.1 / 30; | |
| this.scale.y = this.scale.x; | |
| } | |
| }; | |
| })(); | |
| //----------------------------------------------------------------------------- | |
| // Spriteset_Map | |
| (function() { | |
| var Alias_Spriteset_Map_createLowerLayer = Spriteset_Map.prototype.createLowerLayer; | |
| Spriteset_Map.prototype.createLowerLayer = function() { | |
| Alias_Spriteset_Map_createLowerLayer.call(this); | |
| this._pictures = []; | |
| this._tempAnimations = []; | |
| }; | |
| Spriteset_Map.prototype.addPictures = function() { | |
| this._pictures = QABSManager._pictures; | |
| if (this._pictures.length === 0) return; | |
| for (var i = 0; i < this._pictures.length; i++) { | |
| if (this.children.indexOf(this._pictures[i]) !== -1) continue; | |
| this._tilemap.addChild(this._pictures[i]); | |
| } | |
| }; | |
| Spriteset_Map.prototype.addAnimations = function() { | |
| this._tempAnimations = QABSManager._animations; | |
| if (this._tempAnimations.length === 0) return; | |
| for (var i = 0; i < this._tempAnimations.length; i++) { | |
| if (this.children.indexOf(this._tempAnimations[i]) !== -1) continue; | |
| this._tilemap.addChild(this._tempAnimations[i]); | |
| if (this._tempAnimations[i].isAnimationPlaying()) { | |
| for (var j = 0; j < this._tempAnimations[i]._animationSprites.length; j++) { | |
| this._tilemap.addChild(this._tempAnimations[i]._animationSprites[j]); | |
| } | |
| } | |
| } | |
| }; | |
| var Alias_Spriteset_Map_updateTilemap = Spriteset_Map.prototype.updateTilemap; | |
| Spriteset_Map.prototype.updateTilemap = function() { | |
| Alias_Spriteset_Map_updateTilemap.call(this); | |
| if (this._pictures !== QABSManager._pictures) this.addPictures(); | |
| if (this._tempAnimations !== QABSManager._animations) this.addAnimations(); | |
| }; | |
| })(); |