Jump plugin

● ARCHIVED · READ-ONLY
Started by Sulsay 11 posts View original ↗
  1. Current version: 2 (updated dec 1st)

    Version 2:

    Added the option alwaysAllowJumping. If false, the player will not jump if the destination is a tile that he could have reached by simply walking [jumpDistance] tiles forward.

    Version 1:

    Initial release.

    Intro:

    This plugin allows the player to jump on the map.

    You can specify terrain tags that the player can jump over. By default, this terrain tag is number 1. This is configurable. Don't forget to apply this terrain tag to tiles such as water, or your player won't be able to jump over anything.

    Features:

    - Configurable terrain tags that can be jumped over.

    - Directional passage detection (see attachment).

    - Proper handling of looping maps.

    - Optionally jumping over "same level as character" events. The default behavior is configurable and overridable for each event.

    - Ability to toggle the jumping ability on or off.

    - Player can jump onto "below character" events, such as lily pads in the water.

    - Plays nice with other plugins.

    The attachment shows a jumpable path. The player can reach the chest without the need for any events for the jumping. It's all handled by the plugin.

    Configuring the jump key

    This plugin does not include any logic to expand upon RMMV's default keymapping. There are other existing plugins that you can use for that. The sole purpose of the plugin is to enable jumping.

    Download:

    Copy the contents of the code box in the spoiler and simply save it to your plugins folder. The name of the file doesn't matter.

    The plugin is freely available for commercial use.

    Spoiler
    /*:* @author Wouter Alberts (Sulsay)** @plugindesc Enables jumping over specified terrain tags and, optionally, events.** @param alwaysAllowJumping* @desc Boolean - If false, jumping is disabled when pointless, to prevent "bunny hopping" all over te map.* @default true** @param eventsAreJumpableByDefault* @desc Boolean - Determines if events at level "same as character" can be jumped over by default.* @default true** @param jumpableTerrainTags* @desc Integer[] - The terrain tags that can be jumped over. Apply to "low" unpassable tiles such as water.* @default [1]** @param jumpDistance* @desc Integer - The number of tiles to jump. If blocked, player will jump the first available smaller distance.* @default 2** @param jumpKey* @desc String - The button that triggers jumping.* @default "pageup"** @param sound* @desc Object - The sound to play when jumping. "volume", "pitch" and "pan" are optional, defaulting to 100, 100 and 0.* @default {"name": "Jump1"}** @help* Version 2:* - Added the option alwaysAllowJumping. If false, the player will not jump if the destination is a tile that he could have reached by simply walking [jumpDistance] tiles forward.** Version 1:* - Initial release.** Available for commercial use for free.** If you set eventsAreJumpableByDefault to true, you can override this behaviour with an event note containing "<!jumpable>".* Inversely, if eventsAreJumpableByDefault is false, override it with "<jumpable>".* This behaviour only applies to events with priority "Same as character".** To customize the sound that plays when jumping, supply a json object with at least the key "name".** jumpableTerrainTags is an array of integers containing the numbers of terrain tags that your player can jump over.* Apply such a terrain tag to water, holes in the floor and other small obstacles that appear jumpable to the player.** The jumpKey is set to "pageup" (Q) by default. Use a plugin for additional key mappings if you want to have more options than what RMMV supplies by default.* Additional key mappings are not part of this plugin, because a plugin should do as little as possible and minimize the risk of introducing conflicting behaviour.** Plugin commands:* - toggleJumpingEnabled* Toggles the jumping feature on/off. Supply an optional boolean argument (true or false) to enable or disable it.*/(function () {    var fileNameWithoutExtension = document.currentScript.src.split('/').pop().split('.')[0];    var options = PluginManager.parameters(fileNameWithoutExtension);    for (var key in options) {        if (options.hasOwnProperty(key)) {            try {                options[key] = JSON.parse(options[key]);            }            catch (err) {                var stringValue = String(options[key]);                console.warn('Failed to parse parameter "%1", falling back to string value: %2'.format(key, stringValue));                options[key] = stringValue;            }        }    }    var sound = {name: 'Jump1', volume: 100, pitch: 100, pan: 100};    ['name', 'volume', 'pitch', 'pan'].forEach(function (key) {        if (options.sound[key] != null) {            sound[key] = options.sound[key];        }    });    options.sound = sound;    options.eventsAreJumpableByDefault = !!options.eventsAreJumpableByDefault;    var priorityToRevertToOnLand = null, // This is set at the start of a jump, and gets reset to null upon landing.        isJumpingEnabled = true;         // Flag that can be set with the plugin command "toggleJumpingEnabled" (which accepts optional true or false argument).    var Tile = (function () {        function Tile(x, y) {            this.x = x;            this.y = y;            this.adjustXForHorizontalLoop();            this.adjustYForVerticalLoop();        }        Tile.prototype.adjustXForHorizontalLoop = function () {            if ($gameMap.isLoopHorizontal()) {                var mapWidth = $gameMap.width();                this.x += this.x < 0 ? mapWidth : this.x >= mapWidth ? -mapWidth : 0;            }        };        Tile.prototype.adjustYForVerticalLoop = function () {            if ($gameMap.isLoopVertical()) {                var mapHeight = $gameMap.height();                this.y += this.y < 0 ? mapHeight : this.y >= mapHeight ? -mapHeight : 0;            }        };        Tile.prototype.analyze = function (dir) {            var i, terrainTag = $gameMap.terrainTag(this.x, this.y);            this.isLowObstacle = options.jumpableTerrainTags.contains(terrainTag);            this.hasCollidingEvent = $gamePlayer.isCollidedWithEvents(this.x, this.y);            // A valid player position is a tile that can be accessed from at least one direction.            this.isValidPlayerPosition = false;            if (!this.hasCollidingEvent) {                var dirs = [2, 3, 6, 8];                for (i = 0; i < dirs.length; i++) {                    if ($gameMap.isPassable(this.x, this.y, dirs)) {                        this.isValidPlayerPosition = true;                        break;                    }                }            }            var events = $gameMap.eventsXy(this.x, this.y).filter(function (e) {                return e.isNormalPriority() && e.page();            });            this.jumpableNoteIsSet = false;            this.notJumpableNoteIsSet = false;            for (i = 0; i < events.length; i++) {                var note = events.event().note;                if (note.includes('<jumpable')) {                    this.jumpableNoteIsSet = true;                    break;                }                else if (note.includes('<!jumpable')) {                    this.notJumpableNoteIsSet = true;                    break;                }            }            this.isBlockedInDirectionOfMotion = !$gameMap.isPassable(this.x, this.y, dir);            this.isBlockedInOppositeDirection = !$gameMap.isPassable(this.x, this.y, 10 - dir);            // X and Y are already adjusted for looping (if applicable), so a simple bounds check is sufficient:            this.isInsideMap = this.x >= 0 && this.y >= 0 && this.x < $gameMap.width() && this.y < $gameMap.height();            return this;        };        return Tile;    })();    var Jump = (function () {        function Jump() {            this.dir = $gamePlayer.direction();            // Initiate the path (= the potential landing tiles) with the players' current position:            this.path = [new Tile($gamePlayer.x, $gamePlayer.y)];            // The path is to contain jumpDistance + 1 tiles (because it includes the starting position).            while (this.path.length <= options.jumpDistance) {                this.pushPath();            }            // For the option alwaysAllowJumping, maintain a flag indicating if the player could have simply walked to the jump-destination.            this.couldHaveWalked = true;        }        Jump.prototype.pushPath = function () {            var previous = this.path[this.path.length - 1],                x = $gameMap.xWithDirection(previous.x, this.dir),                y = $gameMap.yWithDirection(previous.y, this.dir);            this.path.push(new Tile(x, y));        };        Jump.prototype.determineDestination = function () {            this.destination = this.path.shift().analyze(this.dir);            // Passage of the starting position may be blocked in the direction of the jump. Player will not move forward, but still make the jumping motion.            // A block does not apply if the terrain tag for "low" is assigned.            if (this.destination.isBlockedInDirectionOfMotion && !this.destination.isLowObstacle) {                return this;            }            var previousTileWasBlock = false;            // All positions but the starting position remain to be checked:            while (this.path.length) {                var tile = this.path.shift().analyze(this.dir);                if (!tile.isInsideMap) {                    break;                }                if (tile.isValidPlayerPosition && (!tile.isBlockedInOppositeDirection || tile.isLowObstacle)) {                    // Player can stand here, and reach it.                    this.destination = tile;                    if (previousTileWasBlock) {                        this.couldHaveWalked = false;                    }                }                var canJumpOver = !tile.hasCollidingEvent && (tile.isLowObstacle || (!tile.isBlockedInDirectionOfMotion && !tile.isBlockedInOppositeDirection));                if (!canJumpOver && tile.hasCollidingEvent) {                    // Events can either be jumped over by default, or if a special note is present on the event.                    if ((options.eventsAreJumpableByDefault && !tile.notJumpableNoteIsSet)                        || (!options.eventsAreJumpableByDefault && tile.jumpableNoteIsSet)) {                        canJumpOver = true;                    }                }                if (!canJumpOver) {                    // Obstacles that aren't marked "low" with a customizable terrain tag cannot be jumped over.                    break;                }                if (!tile.isValidPlayerPosition) {                    previousTileWasBlock = true;                }            }            return this;        };        Jump.prototype.getRelative = function () {            if (this._relative == null) {                this._relative = {                    x: this.correctForHorizontalLoop(this.destination.x - $gamePlayer.x),                    y: this.correctForVerticalLoop(this.destination.y - $gamePlayer.y)                }            }            return this._relative;        };        Jump.prototype.correctForHorizontalLoop = function (relativeX) {            if (this.dir === 4 && relativeX > 0) {                // Facing left, jumping to a tile to the right of the player.                return relativeX - $gameMap.width();            }            else if (this.dir === 6 && relativeX < 0) {                // Facing right, jumping to a tile to the left of the player.                return $gameMap.width() + relativeX;            }            // No correction needed:            return relativeX;        };        Jump.prototype.correctForVerticalLoop = function (relativeY) {            if (this.dir === 2 && relativeY < 0) {                // Facing down, jumping to a tile higher than the player.                return $gameMap.height() + relativeY;            }            else if (this.dir === 8 && relativeY > 0) {                // Facing up, jumping to a tile lower than the player.                return relativeY - $gameMap.height();            }            // No correction needed:            return relativeY;        };        Jump.prototype.getDistance = function () {            return this._distance || (this._distance = Math.abs(this.getRelative().x) + Math.abs(this.getRelative().y));        };        return Jump;    })();    var moveByInput = Game_Player.prototype.moveByInput;    Game_Player.prototype.moveByInput = function () {        moveByInput.call(this);        if (isJumpingEnabled && !this.isMoving() && this.canMove() && Input.isTriggered(options.jumpKey)) {            var jump = new Jump(),                relative = jump.determineDestination().getRelative();            if (!options.alwaysAllowJumping) {                // The option alwaysAllowJumping is off. This means that if the player isn't actually jumping over something that would otherwise block him,                // or will remain on the same tile during the jump, the jump will not take place.                if (jump.getDistance() === 0 || jump.couldHaveWalked) {                    return;                }            }            priorityToRevertToOnLand = $gamePlayer._priorityType;            $gamePlayer.setPriorityType(1.1);            this.jump(relative.x, relative.y);            AudioManager.playSe(sound);            // Increment the step counter using the intended method, respecting plugins that extend it.            for (var i = 0; i < jump.getDistance(); i++) {                $gameParty.increaseSteps();            }        }        if (priorityToRevertToOnLand !== null && !this.isJumping()) {            // Player landed.            this.setPriorityType(priorityToRevertToOnLand);            priorityToRevertToOnLand = null;        }    };    var pluginCommand = Game_Interpreter.prototype.pluginCommand;    Game_Interpreter.prototype.pluginCommand = function (command, args) {        if (command === 'toggleJumpingEnabled') {            if (args.length === 1) {                isJumpingEnabled = args[0] === 'true';            }            else {                isJumpingEnabled = !isJumpingEnabled;            }        }        pluginCommand.call(this, command, args);    };})();
    details.gif

    path.gif
  2. Simple, effective... and gets along with Yanfly... SOLD!
  3. Nice plugin. I have one suggestion, would be nice if there was an option to disable jumping when there is nothing to jump over, so the player doesn't go bunny hopping across the whole map.

    IE. If the tile in front of the player is passable there is no reason to jump.
  4. I like those keywords, Loki! That's exactly what I was going for, thanks!  ;)

    clitvin, that sounds like a good option to add, I'll work it in and get back to you!

    Edit: It's in, please check the OP. Version 2 has the option "alwaysAllowJumping" which you can set to false to disallow jumping at meaningless places.
  5. Doesn't seem to be working for me. Not sure if I'm using it right. I got my character jumping, I filled a lake with terrain tag 1, but I can't get my character to jump over to jump over anything.
  6. Please make sure the terrain tag matches one that you have in the jumpableTerrainTags parameter (by default this is terrain tag 1).

    If jumpDistance is two, you should be able to jump a one-tile body of water with said terrain tag.

    Feel free to open the console with F8 and post whatever is logged, maybe some error occurs in this or another plugin that prevents it from working for you.
  7. KlausAidon said:
    Doesn't seem to be working for me. Not sure if I'm using it right. I got my character jumping, I filled a lake with terrain tag 1, but I can't get my character to jump over to jump over anything.
    Did you remember to set up an event to enable jumping? I know I did when I first used it.
  8. It should work out of the box, without the need for a plugin command (the internal flag isJumpingEnabled is true until explicitly overridden).

    KlausAidon, if it's no trouble, I would like to see the console output. I suspect either invalid parameters or a conflict with another plugin, although I thoroughly tested compatability.

    Edit: I updated the plugin to version 2.
  9. is it possible to bind more then 1 key to the jump command?
  10. I would use a keymapper plugin for that, such as Zalerinian's. It allows you to setup your own binding, and map multiple keys to one action.
  11. This plugin is increditably amazing.