Advertisement
MkNish

[RMMV Plugin] Advanced Move Route

Nov 29th, 2015
591
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //=============================================================================
  2. // μ'ki's Advanced Move Route v1.02
  3. // MK_AdvancedMove.js
  4. //=============================================================================
  5.  
  6. var Imported = Imported || {};
  7. Imported.MK_AdvancedMove = true;
  8. var Maki = Maki || {};
  9. Maki.AM = Maki.AM || {};
  10.  
  11. //=============================================================================
  12. /*:
  13.  * @plugindesc v1.02 Advanced Move Route
  14.  * @author μ'ki
  15.  *
  16.  * @param Pathfinding Limit
  17.  * @desc A* pathfinding search depth limit (0 = unlimited).
  18.  * @default 12
  19.  *
  20.  * @param Pathfinding MTC
  21.  * @desc Move/jump towards character using pathfinding (true/false).
  22.  * @default true
  23.  *
  24.  * @param Player M/J Switch
  25.  * @desc Switch ID to toggle player move(OFF)/jump(ON).
  26.  * @default 1
  27.  *
  28.  * @param 8-directional Mode
  29.  * @desc Allows player and events move in 8 directions (true/false).
  30.  * @default false
  31.  *
  32.  * @help
  33.  * ============================================================================
  34.  * Introduction
  35.  * ============================================================================
  36.  * μ'ki's Advanced Move Route is remake from my previous work, Alissa Advanced
  37.  * Move Route (for RPG Maker XP & VX), for RPG Maker MV. It also overrides
  38.  * the Move Toward Player route command to use pathfinding, like my another
  39.  * previous work, Listra Pathfinder Module, does. However, here it uses the A*
  40.  * pathfinding algorithm that already exists in the RPG MV game system, with
  41.  * a little mod to adjust/omit the search limit.
  42.  *
  43.  * For information about Alissa Advanced Move Route, search the thread at
  44.  * RPGMakerID forum (http://rmid.forumotion.net). Sorry, I don't know if it
  45.  * exists, maybe because it has been several years ago.
  46.  *
  47.  * For information about Listra Pathfinder Module:
  48.  * http://prodig.forumotion.net/t478-rgss-rgss2-listra-pathfinder-module
  49.  *
  50.  * Contact me for support/bug report:
  51.  * listra92[at]gmail.com
  52.  * https://www.facebook.com/don.listRA92
  53.  *
  54.  * ============================================================================
  55.  * Features and Usages
  56.  * ============================================================================
  57.  *  - Adjusts A* pathfinding search depth limit (by default set to 12), if the
  58.  *    shortest path to the destination is longer than that value, the character
  59.  *    may stop in front of an obstacle.
  60.  *  - Adjusts whether to use pathfinding for Move toward Player (and other
  61.  *    characters) instead of naive movement that doesn't avoid obstacles.
  62.  *  - Move towards point, just add script in the movement route:
  63.  *    this.moveTowardPoint(X, Y);
  64.  *  - Jump left(4), right(6), up(8), down(2) (one step, triggering Player/Event
  65.  *    Touch): this.jumpStraight(direction[, turn_ok = true]);
  66.  *  - Jump diagonally: this.jumpDiagonally(h, v[, turn_ok = true]);
  67.  *  - Jump towards point (per step): this.jumpTowardPoint(X, Y);
  68.  *  - Jump towards char (player/event): this.jumpTowardCharacter(character);
  69.  *  - this.jumpTowardPlayer();
  70.  *  - this.jumpAwayFromCharacter();
  71.  *  - this.jumpRandom();
  72.  *  - this.jumpForward();
  73.  *  - this.jumpBackward();
  74.  *  - this.eraseEvent(event);
  75.  *  - Flow label: this.label(label_name);
  76.  *  - Jump to label with condition: this.jumpLabel(label_name[, cond = "true"]);
  77.  *  - this.endRoute();
  78.  *
  79.  * ============================================================================
  80.  * Coming in the Next Version
  81.  * ============================================================================
  82.  *  - More movement route commands.
  83.  *
  84.  * ============================================================================
  85.  * Changelog
  86.  * ============================================================================
  87.  * v1.02:
  88.  *  - Prepared for compatibility to MK_Pathfinding.js plugin.
  89.  *
  90.  * v1.01b:
  91.  *  - 8-direction support for the pathfinding algorithm.
  92.  *
  93.  * v1.01:
  94.  *  - Improved the A* algorithm that lagged when targeting a character, since
  95.  *    it isn't passable and causes the algorithm search entire pathable tiles.
  96.  *  - Fixed followers not moving when the player character is in jump mode.
  97.  *  - 8-direction player movement.
  98.  *
  99.  */
  100. //=============================================================================
  101.  
  102. //=============================================================================
  103. // Parameter Variables
  104. //=============================================================================
  105.  
  106. Maki.AM.Parameters = PluginManager.parameters('MK_AdvancedMove');
  107.  
  108. Maki.AM.DepthLimit = Number(Maki.AM.Parameters['Pathfinding Limit']);
  109. Maki.AM.PMTC = !!eval(String(Maki.AM.Parameters['Pathfinding MTC']));
  110. Maki.AM.MJS = Number(Maki.AM.Parameters['Player M/J Switch']);
  111. Maki.AM.Dir8 = !!eval(String(Maki.AM.Parameters['8-directional Mode']));
  112.  
  113. //=============================================================================
  114. // Game_Character
  115. //=============================================================================
  116.  
  117. Game_Character.prototype.searchLimit = function() {
  118.     return Maki.AM.DepthLimit;
  119. };
  120.  
  121. Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
  122.     var searchLimit = this.searchLimit();
  123.     var mapWidth = $gameMap.width();
  124.     var nodeList = [];
  125.     var openList = [];
  126.     var closedList = [];
  127.     var start = {};
  128.     var best = start;
  129.  
  130.     if (this.x === goalX && this.y === goalY) {
  131.         return 0;
  132.     }
  133.  
  134.     start.parent = null;
  135.     start.x = this.x;
  136.     start.y = this.y;
  137.     start.g = 0;
  138.     start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
  139.     nodeList.push(start);
  140.     openList.push(start.y * mapWidth + start.x);
  141.  
  142.     var SQ2 = Math.sqrt(2);
  143.     while (nodeList.length > 0) {
  144.         var bestIndex = 0;
  145.         for (var i = 0; i < nodeList.length; i++) {
  146.             if (nodeList[i].f < nodeList[bestIndex].f) {
  147.                 bestIndex = i;
  148.             }
  149.         }
  150.  
  151.         var current = nodeList[bestIndex];
  152.         var x1 = current.x;
  153.         var y1 = current.y;
  154.         var pos1 = y1 * mapWidth + x1;
  155.         var g1 = current.g;
  156.  
  157.         nodeList.splice(bestIndex, 1);
  158.         openList.splice(openList.indexOf(pos1), 1);
  159.         closedList.push(pos1);
  160.  
  161.         if (current.x === goalX && current.y === goalY) {
  162.             best = current;
  163.             goaled = true;
  164.             break;
  165.         }
  166.  
  167.         if (g1 >= searchLimit && searchLimit > 0) {
  168.             continue;
  169.         }
  170.  
  171.         for (var j = 1; j <= 9; j++) {
  172.             var direction = j;
  173.             if (direction === 5) continue;
  174.             if (direction % 2 > 0 && !Maki.Params.Dir8) continue;
  175.             var x2 = $gameMap.roundXWithDirection(x1, ((direction-1) % 3)+4);
  176.             var y2 = $gameMap.roundYWithDirection(y1, Math.floor((direction-1)/3)*3+2);
  177.             var pos2 = y2 * mapWidth + x2;
  178.             if (closedList.contains(pos2)) {
  179.                 continue;
  180.             }
  181.             if (direction % 2 > 0 && Maki.AM.Dir8) {
  182.                 if (!this.canPassDiagonally(x1, y1,
  183.                     (direction % 6)+3, Math.floor(direction/6)*6+2) &&
  184.                     $gameMap.distance(x1, y1, goalX, goalY) > 1.5) {
  185.                     continue;
  186.                 }
  187.             } else {
  188.                 if (!this.canPass(x1, y1, direction) &&
  189.                     $gameMap.distance(x1, y1, goalX, goalY) > 1) {
  190.                     continue;
  191.                 }
  192.             }
  193.  
  194.             var g2 = g1;
  195.             if (direction % 2 > 0) {
  196.                 g2 += SQ2;
  197.             } else {
  198.                 g2 += 1;
  199.             }
  200.             var index2 = openList.indexOf(pos2);
  201.  
  202.             if (index2 < 0 || g2 < nodeList[index2].g) {
  203.                 var neighbor;
  204.                 if (index2 >= 0) {
  205.                     neighbor = nodeList[index2];
  206.                 } else {
  207.                     neighbor = {};
  208.                     nodeList.push(neighbor);
  209.                     openList.push(pos2);
  210.                 }
  211.                 neighbor.parent = current;
  212.                 neighbor.x = x2;
  213.                 neighbor.y = y2;
  214.                 neighbor.g = g2;
  215.                 neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
  216.                 if (!best || neighbor.f - neighbor.g < best.f - best.g) {
  217.                     best = neighbor;
  218.                 }
  219.             }
  220.         }
  221.     }
  222.  
  223.     var node = best;
  224.     while (node.parent && node.parent !== start) {
  225.         node = node.parent;
  226.     }
  227.  
  228.     var deltaX1 = $gameMap.deltaX(node.x, start.x);
  229.     var deltaY1 = $gameMap.deltaY(node.y, start.y);
  230.     if (deltaX1 !== 0) deltaX1 /= Math.abs(deltaX1);
  231.     if (deltaY1 !== 0) deltaY1 /= Math.abs(deltaY1);
  232.     return 5 - deltaY1 * 3 + deltaX1;
  233. };
  234.  
  235. if(Maki.AM.PMTC){
  236. Game_Character.prototype.moveTowardCharacter = function(character) {
  237.     direction = this.findDirectionTo(character.x,character.y);
  238.     if (direction % 2 > 0) {
  239.         this.moveDiagonally((direction % 6)+3, Math.floor(direction/6)*6+2);
  240.     } else {
  241.         this.moveStraight(direction);
  242.     }
  243. };
  244. }
  245.  
  246. Game_Character.prototype.moveTowardPoint = function(x, y) {
  247.     this.moveStraight(this.findDirectionTo(x, y));
  248. };
  249.  
  250. Game_Character.prototype.jumpStraight = function(d, turn_ok) {
  251.     if (turn_ok === undefined) {
  252.         turn_ok = true;
  253.     }
  254.     this.setMovementSuccess(this.canPass(this._x, this._y, d));
  255.     if (this.isMovementSucceeded()) {
  256.         if (turn_ok) this.setDirection(d);
  257.         this._x = $gameMap.roundXWithDirection(this._x, d);
  258.         this._y = $gameMap.roundYWithDirection(this._y, d);
  259.         this._realX = $gameMap.xWithDirection(this._x, this.reverseDir(d));
  260.         this._realY = $gameMap.yWithDirection(this._y, this.reverseDir(d));
  261.         this._jumpPeak = 11 - this.realMoveSpeed();
  262.         this._jumpCount = this._jumpPeak * 2 - (this._dashing ? 2 : 0);
  263.         this.straighten();
  264.         this.increaseSteps();
  265.     } else {
  266.         if (turn_ok) this.setDirection(d);
  267.         this.checkEventTriggerTouchFront(d);
  268.     }
  269.     return this.isMovementSucceeded();
  270. };
  271.  
  272. Game_Character.prototype.jumpDiagonally = function(h, v, turn_ok) {
  273.     if (turn_ok === undefined) {
  274.         turn_ok = true;
  275.     }
  276.     this.setMovementSuccess(this.canPassDiagonally(this._x, this._y, h, v));
  277.     if (this.isMovementSucceeded()) {
  278.         this._x = $gameMap.roundXWithDirection(this._x, h);
  279.         this._y = $gameMap.roundYWithDirection(this._y, v);
  280.         this._realX = $gameMap.xWithDirection(this._x, this.reverseDir(h));
  281.         this._realY = $gameMap.yWithDirection(this._y, this.reverseDir(v));
  282.         this._jumpPeak = 11 - this.realMoveSpeed();
  283.         this._jumpCount = this._jumpPeak * 2 - (this._dashing ? 2 : 0);
  284.         this.straighten();
  285.         this.increaseSteps();
  286.     }
  287.     if (turn_ok) {
  288.         if (this._direction === this.reverseDir(h)) this.setDirection(h);
  289.         if (this._direction === this.reverseDir(v)) this.setDirection(v);
  290.     }
  291.     return this.isMovementSucceeded();
  292. };
  293.  
  294. Game_Player.prototype.jumpStraight = function(d, turn_ok) {
  295.     if (this.canPass(this.x, this.y, d)) {
  296.         this._followers.updateMove();
  297.     }
  298.     Game_Character.prototype.jumpStraight.call(this, d, turn_ok);
  299. };
  300.  
  301. Game_Player.prototype.jumpDiagonally = function(h, v, turn_ok) {
  302.     if (this.canPassDiagonally(this.x, this.y, h, v)) {
  303.         this._followers.updateMove();
  304.     }
  305.     Game_Character.prototype.jumpDiagonally.call(this, h, v, turn_ok);
  306. };
  307.  
  308.  
  309. Game_Character.prototype.jumpTowardPoint = function(x, y) {
  310.     if (Maki.AM.PMTC){
  311.         direction = this.findDirectionTo(x, y);
  312.         if (direction % 2 > 0) {
  313.             this.jumpDiagonally((direction % 6)+3, Math.floor(direction/6)*6+2);
  314.         } else {
  315.             this.jumpStraight(direction);
  316.         }
  317.     } else {
  318.         var sx = this.deltaXFrom(x);
  319.         var sy = this.deltaYFrom(y);
  320.         if (Math.abs(sx) > Math.abs(sy)) {
  321.             if (!this.jumpStraight(sx > 0 ? 4 : 6) && sy !== 0) {
  322.                 this.jumpStraight(sy > 0 ? 8 : 2);
  323.             }
  324.         } else if (sy !== 0) {
  325.             if (!this.jumpStraight(sy > 0 ? 8 : 2, true) && sx !== 0) {
  326.                 this.jumpStraight(sx > 0 ? 4 : 6);
  327.             }
  328.         }
  329.     }
  330. };
  331.  
  332. Game_Character.prototype.jumpTowardCharacter = function(character) {
  333.     this.jumpTowardPoint(character.x, character.y);
  334. };
  335.  
  336. Game_Character.prototype.jumpAwayFromCharacter = function(character) {
  337.     this.turnAwayFromCharacter(character);
  338.     this.jumpStraight(this._direction);
  339. };
  340.  
  341. Game_Character.prototype.jumpTowardPlayer = function() {
  342.     this.jumpTowardCharacter($gamePlayer);
  343. };
  344.  
  345. Game_Character.prototype.jumpRandom = function() {
  346.     var dir = 2+2*Math.randomInt(4);
  347.     this.jumpStraight(dir);
  348. };
  349.  
  350. Game_Character.prototype.jumpForward = function() {
  351.     this.jumpStraight(this._direction, false);
  352. };
  353.  
  354. Game_Character.prototype.jumpBackward = function() {
  355.     this.jumpStraight(this.reverseDir(this._direction), false);
  356. };
  357.  
  358. Game_Character.prototype.eraseEvent = function(event) {
  359.     if (event > 0) {
  360.         $gameMap._events[event].erase();
  361.     }
  362. };
  363.  
  364. Game_Character.prototype.label = function(label_name) {
  365.     this._moveRoute.list[this._moveRouteIndex].code = 46;
  366.     this._moveRoute.list[this._moveRouteIndex].parameters[0] = label_name;
  367. };
  368.  
  369. Game_Character.prototype.jumpLabel = function(label_name,cond) {
  370.     if (cond === undefined) cond = "true";
  371.     for (var i = 0; i < this._moveRoute.list.length; i++) {
  372.         if (this._moveRoute.list[i].code == 46 &&
  373.             this._moveRoute.list[i].parameters[0] == label_name) {
  374.             if (eval(cond)) {
  375.                 this._moveRouteIndex = i;
  376.                 return;
  377.             }
  378.         }
  379.     }
  380. };
  381.  
  382. Game_Character.prototype.endRoute = function() {
  383.     this._moveRoute.list[this._moveRouteIndex].code = 0;
  384.     this._moveRouteIndex -= 1;
  385. };
  386.  
  387. Game_Follower.prototype.chaseCharacter = function(character) {
  388.     var sx = this.deltaXFrom(character.x);
  389.     var sy = this.deltaYFrom(character.y);
  390.     if (sx !== 0 && sy !== 0) {
  391.         if ($gameSwitches.value(Maki.AM.MJS)) {
  392.             this.jumpDiagonally(sx > 0 ? 4 : 6, sy > 0 ? 8 : 2);
  393.         } else {
  394.             this.moveDiagonally(sx > 0 ? 4 : 6, sy > 0 ? 8 : 2);
  395.         }
  396.     } else if (sx !== 0) {
  397.         if ($gameSwitches.value(Maki.AM.MJS)) {
  398.             this.jumpStraight(sx > 0 ? 4 : 6);
  399.         } else {
  400.             this.moveStraight(sx > 0 ? 4 : 6);
  401.         }
  402.     } else if (sy !== 0) {
  403.         if ($gameSwitches.value(Maki.AM.MJS)) {
  404.             this.jumpStraight(sy > 0 ? 8 : 2);
  405.         } else {
  406.             this.moveStraight(sy > 0 ? 8 : 2);
  407.         }
  408.     }
  409.     this.setMoveSpeed($gamePlayer.realMoveSpeed());
  410. };
  411.  
  412. Maki.AM.PlayerUpdateDashing = Game_Player.prototype.updateDashing;
  413. Game_Player.prototype.updateDashing = function() {
  414.     Maki.AM.PlayerUpdateDashing.call(this);
  415.     thePlayer = this;
  416.     this._followers.forEach(function(follower) {
  417.         follower._dashing = thePlayer._dashing;
  418.     }, this._followers);
  419. };
  420.  
  421. Game_Player.prototype.getInputDirection = function() {
  422.     if (Maki.AM.Dir8) {
  423.         return Input.dir8;
  424.     } else {
  425.         return Input.dir4;
  426.     }
  427. };
  428.  
  429. Game_Player.prototype.executeMove = function(direction) {
  430.     if (direction % 2 > 0) {
  431.         if ($gameSwitches.value(Maki.AM.MJS)) {
  432.             this.jumpDiagonally((direction % 6)+3, Math.floor(direction/6)*6+2);
  433.         } else {
  434.             this.moveDiagonally((direction % 6)+3, Math.floor(direction/6)*6+2);
  435.         }
  436.     } else {
  437.         if ($gameSwitches.value(Maki.AM.MJS)) {
  438.             this.jumpStraight(direction);
  439.         } else {
  440.             this.moveStraight(direction);
  441.         }
  442.     }
  443. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement