khanhdu

Galv's Timed Message Popups

Apr 24th, 2017
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //-----------------------------------------------------------------------------
  2. //  Galv's Timed Message Popups
  3. //-----------------------------------------------------------------------------
  4. //  For: RPGMAKER MV
  5. //  GALV_TimedMessagePopups.js
  6. //-----------------------------------------------------------------------------
  7. //  2017-02-01 - Version 1.7 - Hid popups when menu opens and battle starts
  8. //  2016-07-13 - Version 1.6 - Added script call to remove popups from screen.
  9. //                           - Timed popups now work in default battle
  10. //  2016-03-31 - Version 1.5 - fixed minor mistake
  11. //  2016-03-27 - Version 1.4 - added faces, arrows, Y offset bug fix and
  12. //                           - window positioning over target
  13. //  2016-03-24 - Version 1.3 - added ability to specify follower actor and
  14. //                           - set windowskin
  15. //  2016-03-23 - Version 1.2 - changed code to use | to split x|y coords
  16. //  2016-03-23 - Version 1.1 - added "delay" setting and follower targeting
  17. //  2016-03-23 - Version 1.0 - release
  18. //-----------------------------------------------------------------------------
  19. // Terms can be found at:
  20. // galvs-scripts.com
  21. //-----------------------------------------------------------------------------
  22.  
  23. var Imported = Imported || {};
  24. Imported.Galv_MessageCaptions = true;
  25.  
  26. var Galv = Galv || {};            // Galv's main object
  27. Galv.Mpup = Galv.Mpup || {};        // Galv's stuff
  28.  
  29. //-----------------------------------------------------------------------------
  30. /*:
  31.  * @plugindesc (v.1.7) Display popup message boxes on screen that do not stop gameplay and auto close after a set time.
  32.  *
  33.  * @author Galv - galvs-scripts.com
  34.  *
  35.  * @param Y Offset
  36.  * @desc Offset Y position by this much when popup is displayed over a character.
  37.  * @default -60
  38.  *
  39.  * @param Default Windowskin
  40.  * @desc Windowskin file from /img/system/ that popup messages use by default
  41.  * @default Window
  42.  *
  43.  * @param Use Arrows
  44.  * @desc Use windowskin arrows to point at target of the popup message
  45.  * @default true
  46.  *
  47.  * @param Windowskin Back Opacity
  48.  * @desc Used for all custom windowskins (i.e: not 'Window.png').
  49.  * 0 - 255
  50.  * @default 255
  51.  *
  52.  * @param Text Outline Width
  53.  * @desc Default text has an outline. Change this for all custom windows (not Window.png). default 4
  54.  * @default 0
  55.  *
  56.  * @help
  57.  *   Galv's Timed Message Popups
  58.  * ----------------------------------------------------------------------------
  59.  * Creates timed message popup boxes that can appear at a position on the
  60.  * screen or at a character's location. These popups do not stop player
  61.  * movement and you can display as many of them at one time as needed.
  62.  *
  63.  * To activate a message popup, inside a "Show Text" box, you will need to
  64.  * include a tag on the first line of the message:
  65.  *
  66.  *    <c:target,time,delay,windowskin>
  67.  *
  68.  * target  = the ID of an event (0 for current event) OR
  69.  *           x|y screen coordinates OR
  70.  *           negatives for followers (-1 being leader, -2 for second, etc.)
  71.  *           OR... you can use a1, a2, a3, etc. to specify certain actor.
  72.  *           If follower/actor is not in party, message won't display.
  73.  * time    = frames the caption will be displayed before it closes
  74.  * delay   = frames the caption will remain invisible before opening
  75.  * windowskin = filename of new windowskin located in /img/system/
  76.  *              do not include this to use normal windowskin.
  77.  *
  78.  * EXAMPLES:
  79.  * <c:4,160,0>     // Message on event 4 for 160 frames
  80.  * <c:-1,60,10>    // After 10 frames, message on player for 60 frames
  81.  * <c:-3,80,20>    // After 20 frames, message on party member 3 for 80 frames
  82.  * <c:a7,60,0>     // Message on actor 7 for 60 frames if actor is a follower
  83.  * <c:0,100,0>     // Message on current event for 100 frames
  84.  * <c:100|100,80,5>  // After 5 frames, message at screen x100 y100 for 80 fr
  85.  * <c:0|0,90,0,Window2>  // message at screen x0 y0 for 90 frames using
  86.  *                       // /img/system/Window2.png windowskin file.
  87.  *
  88.  * Show Text message box settings for position bottom, middle and top will
  89.  * change where the window displays over the target.
  90.  *
  91.  * Note that when the player opens the menu, even messages that were created
  92.  * with a delay will be removed.
  93.  *
  94.  * ----------------------------------------------------------------------------
  95.  *   SCRIPT CALL
  96.  * ----------------------------------------------------------------------------
  97.  *
  98.  *   Galv.Mpup.clear();          // Remove all message popups on screen
  99.  *
  100.  * ----------------------------------------------------------------------------
  101.  *   Note tag for ENEMIES and ACTORS
  102.  * ----------------------------------------------------------------------------
  103.  *    <msgY:x>      // x being the amount of pixels to move vertically for
  104.  *                  // timed messages in BATTLE. Leaving this tag out will use
  105.  *                  // default position Galv set up for default battle.
  106.  */
  107.  
  108. //-----------------------------------------------------------------------------
  109. //  CODE STUFFS
  110. //-----------------------------------------------------------------------------
  111.  
  112.  
  113. (function() {
  114.  
  115. Galv.Mpup.thisEvent = null;
  116. Galv.Mpup.yOffset = Number(PluginManager.parameters('Galv_TimedMessagePopups')['Y Offset']);
  117. Galv.Mpup.windowskin = PluginManager.parameters('Galv_TimedMessagePopups')['Default Windowskin'];
  118. Galv.Mpup.arrows = PluginManager.parameters('Galv_TimedMessagePopups')['Use Arrows'].toLowerCase() == 'true' ? true : false;
  119. Galv.Mpup.opac = Number(PluginManager.parameters('Galv_TimedMessagePopups')['Windowskin Back Opacity']);
  120. Galv.Mpup.outlineWidth = Number(PluginManager.parameters('Galv_TimedMessagePopups')['Text Outline Width']);
  121.  
  122.  
  123.  
  124.  
  125. Galv.Mpup.Game_Interpreter_command101 = Game_Interpreter.prototype.command101;
  126. Game_Interpreter.prototype.command101 = function() {
  127.     var cap = this._list[this._index + 1].parameters[0].match(/<c:(.*)>/i);
  128.  
  129.     var pos = 2; //this._params[3];
  130.     var data = this._params.clone();
  131.    
  132.     if (!cap) {
  133.         Galv.Mpup.Game_Interpreter_command101.call(this);
  134.     } else {
  135.         this.createCaption(cap,pos,data);
  136.     };
  137. };
  138.  
  139.  
  140. Game_Interpreter.prototype.createCaption = function(cap,pos,data) {
  141.     Galv.Mpup.thisEvent = this._eventId;
  142.     var txtArray = [];
  143.  
  144.     // get all text:
  145.     while (this.nextEventCode() === 401) {  // Text data
  146.         this._index++;
  147.         txtArray.push(this.currentCommand().parameters[0]);
  148.     };
  149.  
  150.     txtArray[0] = txtArray[0].replace(cap[0],"");
  151.    
  152.     var o = cap[1].split(",");
  153.         var windowskin = o[3];
  154.         if (windowskin) ImageManager.loadSystem(windowskin);
  155.        
  156.     if (o[0].contains("|")) {
  157.         // X Y LOCATION
  158.         var xy = o[0].split("|");
  159.         var target = [Number(xy[0]),Number(xy[1])];
  160.     } else if (o[0].contains("a")) {
  161.         // ACTOR
  162.         var actorIndex = $gameActors.actor(Number(o[0].replace("a",""))).index();
  163.         if (actorIndex < 0) return;
  164.         var target = -(actorIndex + 1);
  165.     } else {
  166.         var target = Number(o[0]);
  167.     };
  168.     var time = Number(o[1]);
  169.     var delay = Number(o[2]) || 0;
  170.  
  171.     SceneManager._scene.createCaptionWindow(target,time,txtArray,data,delay,windowskin);
  172. };
  173.  
  174.  
  175. Galv.Mpup.clear = function() {
  176.     SceneManager._scene.removeCaptionWindows();
  177. };
  178.  
  179.  
  180. // Scene Base
  181. //-----------------------------------------------------------------------------
  182.  
  183. Scene_Base.prototype.updateCaptionBoxes = function() {
  184.     for (var i = 0; i < this._captionWindows.length; i++) {
  185.         if (!this._captionWindows[i] || !this._captionWindows[i].active) {
  186.             this._windowLayer.removeChild(this._captionWindows[i]);
  187.             this._captionWindows[i] = null;    
  188.             this._captionWindows.splice(i, 1);
  189.             i--;
  190.         };
  191.     };
  192. };
  193.  
  194. Scene_Base.prototype.createCaptionWindow = function(target,time,textArray,data,delay,windowskin) {};
  195. Scene_Base.prototype.removeCaptionWindows = function() {};
  196.  
  197.  
  198. // Scene Map
  199. //-----------------------------------------------------------------------------
  200.  
  201. Galv.Mpup.Scene_Map_initialize = Scene_Map.prototype.initialize;
  202. Scene_Map.prototype.initialize = function() {
  203.     Galv.Mpup.Scene_Map_initialize.call(this);
  204.     this._captionWindows = [];
  205. };
  206.  
  207. Galv.Mpup.Scene_Map_update = Scene_Map.prototype.update;
  208. Scene_Map.prototype.update = function() {
  209.     Galv.Mpup.Scene_Map_update.call(this);
  210.     this.updateCaptionBoxes();
  211. };
  212.  
  213. Scene_Map.prototype.createCaptionWindow = function(target,time,textArray,data,delay,windowskin) {
  214.     var p = new Window_GalvCaption(target,time,textArray,data,delay,windowskin);
  215.     this._captionWindows.push(p);
  216.     this.addWindow(p);
  217. };
  218.  
  219. Galv.Mpup.Scene_Map_startEncounterEffect = Scene_Map.prototype.startEncounterEffect;
  220. Scene_Map.prototype.startEncounterEffect = function() {
  221.     Galv.Mpup.Scene_Map_startEncounterEffect.call(this);
  222.     this.removeCaptionWindows();
  223. };
  224.  
  225. Galv.Mpup.Scene_Map_terminate = Scene_Map.prototype.terminate;
  226. Scene_Map.prototype.terminate = function() {
  227.     for (var i = 0; i < this._captionWindows.length; i++) {
  228.         this._captionWindows[i].visible = false;
  229.     };
  230.     Galv.Mpup.Scene_Map_terminate.call(this);
  231. };
  232.  
  233. Scene_Base.prototype.removeCaptionWindows = function() {
  234.     for (var i = 0; i < this._captionWindows.length; i++) {
  235.         this._captionWindows[i].active = false;
  236.     };
  237. };
  238.  
  239.  
  240.  
  241. // Scene Battle
  242. //-----------------------------------------------------------------------------
  243.  
  244. Galv.Mpup.Scene_Battle_initialize = Scene_Battle.prototype.initialize;
  245. Scene_Battle.prototype.initialize = function() {
  246.     Galv.Mpup.Scene_Battle_initialize.call(this);
  247.     this._captionWindows = [];
  248. };
  249.  
  250. Galv.Mpup.Scene_Battle_update = Scene_Battle.prototype.update;
  251. Scene_Battle.prototype.update = function() {
  252.     Galv.Mpup.Scene_Battle_update.call(this);
  253.     this.updateCaptionBoxes();
  254. };
  255.  
  256. Scene_Battle.prototype.createCaptionWindow = function(target,time,textArray,data,delay,windowskin) {
  257.     var p = new Window_GalvCaption(target,time,textArray,data,delay,windowskin);
  258.     this._captionWindows.push(p);
  259.     this.addWindow(p);
  260. };
  261.  
  262.  
  263. // Game_BattlerBase
  264. //-----------------------------------------------------------------------------
  265.  
  266.  
  267.  
  268.  
  269. // Caption Window
  270. //-----------------------------------------------------------------------------
  271.  
  272. function Window_GalvCaption() {
  273.     this.initialize.apply(this, arguments);
  274. }
  275.  
  276. Window_GalvCaption.prototype = Object.create(Window_Base.prototype);
  277. Window_GalvCaption.prototype.constructor = Window_GalvCaption;
  278.  
  279. Window_GalvCaption.prototype.initialize = function(target,time,textArray,data,delay,windowskin) {
  280.     // target = [x,y] or event id or 0 for player
  281.     this._pos = data[3];  // bottom is 2, top is 0, middle is 1
  282.     if (data[0] != "") {
  283.         this._faceBitmap = ImageManager.loadFace(data[0]);
  284.         this._faceName = data[0];
  285.         this._faceIndex = data[1];
  286.     };
  287.     this.skin = windowskin || Galv.Mpup.windowskin;
  288.  
  289.     if (SceneManager._scene.constructor.name == 'Scene_Map') {
  290.         this.setMapTarget(target);
  291.     } else {
  292.         this.setBattleTarget(target);
  293.     };
  294.  
  295.     this._time = time + delay || 160;
  296.     this._delayTime = this._time - delay;
  297.     this._txtArray = textArray;
  298.     var h = this.fittingHeight(this._txtArray.length);
  299.     h = this._faceName ? Math.max(h, Window_Base._faceHeight + this.standardPadding() * 2) : h;
  300.  
  301.     Window_Base.prototype.initialize.call(this, this.targetX, this.targetY, Graphics.width, h);
  302.     this.windowskin = ImageManager.loadSystem(this.skin);
  303.     if (this.skin != "Window") this.backOpacity = Galv.Mpup.opac;
  304.     this._downArrowSprite.visible = false;
  305.     this._upArrowSprite.visible = false;
  306.     this.checkImages();
  307.     this.openness = 0;
  308.    
  309.     if (!this._disable) this.active = true;
  310. };
  311.  
  312.  
  313. Window_GalvCaption.prototype.setMapTarget = function(target) {
  314.     this._heightY = Galv.Mpup.yOffset;
  315.     if (Number.isInteger(target)) {
  316.         // event ID or player
  317.         if (target >= -1) {
  318.             switch (target) {
  319.                 case 0:
  320.                     // Current event
  321.                     this.target = $gameMap.event(Galv.Mpup.thisEvent);
  322.                     break;
  323.                 case -1:
  324.                     // Player
  325.                     this.target = $gamePlayer;
  326.                     break;
  327.                 default:
  328.                     // Event
  329.                     this.target = $gameMap.event(target);
  330.                     break;
  331.             };
  332.        
  333.         } else {
  334.             // Follower
  335.             var f = Math.abs(target) - 2;
  336.             this.target = $gamePlayer._followers.follower(f);
  337.             if (f > $gameParty.battleMembers().length) this._disable = true;
  338.         };
  339.         Galv.Mpup.thisEvent = null;
  340.         this.follow = true; // follow the object in update
  341.     } else {
  342.         this.targetX = target[0];
  343.         this.targetY = target[1];
  344.         this.toScreen = true;
  345.     };
  346. };
  347.  
  348.  
  349.  
  350.  
  351. Window_GalvCaption.prototype.setBattleTarget = function(target) {
  352.     Galv.Mpup.thisEvent = null;
  353. //  this._heightY = 0;
  354.     if (Number.isInteger(target)) {
  355.         // event ID or player
  356.         if (target >= -1) {
  357.             switch (target) {
  358.                 case -1:
  359.                     // battle leader
  360.                     this.target = $gameParty.battleMembers()[Math.abs(target) - 1];
  361.                     if (!this.target || this.target.isDead()) this._disable = true;
  362.                     break;
  363.                 default:
  364.                     // enemy index
  365.                     this.target = $gameTroop.members()[target];
  366.                     if (!this.target || this.target.isDead()) this._disable = true;
  367.                     break;
  368.             };
  369.        
  370.         } else {
  371.             // battle actors
  372.             var mem = Math.abs(target) - 2;
  373.  
  374.             this.target = $gameparty.members()[mem];
  375.             if (mem > $gameparty.members().length) this._disable = true;
  376.         };
  377.         if (!this.toScreen) this.follow = true; // follow the object in update
  378.     } else {
  379.         this.targetX = target[0];
  380.         this.targetY = target[1];
  381.         this.toScreen = true;
  382.        
  383.     };
  384.  
  385.     this._heightY = this.target ? this.target._offsetmsgY : 0;
  386.    
  387.     // Target has no screen pos functions?
  388.     if (this.target && !this.target.screenX) {
  389.         this.target.screenX = function() {return this._msgX || 0};
  390.         this.target.screenY = function() {return this._msgY || 0};
  391.     };
  392. };
  393.  
  394.  
  395.  
  396.  
  397. Window_GalvCaption.prototype.loadWindowskin = function() {
  398.     this.windowskin = ImageManager.loadSystem(this.skin);
  399. };
  400.  
  401. Window_GalvCaption.prototype.setWindowDimensions = function() {
  402.     var w = 10;
  403.     this.contents.clear();
  404.     // Calc max width and line height to get dimensions
  405.    
  406.     var xO = this._faceName ? Window_Base._faceWidth + 10 : 0;
  407.    
  408.     for (var i = 0; i < this._txtArray.length; i++) {
  409.         var lineWidth = this.textWidthEx(this._txtArray[i]) + this.standardPadding() * 2;
  410.         if (w < lineWidth) {
  411.             w = lineWidth;
  412.         };
  413.         if (this.skin != 'Window') this.contents.outlineWidth = Galv.Mpup.outlineWidth;
  414.         this.drawTextEx(this._txtArray[i], xO, this.lineHeight() * i);
  415.     }
  416.     this.width = w + xO;
  417.    
  418.    
  419.     // face?
  420.     if (this._faceName) {
  421.         this.drawFace(this._faceName, this._faceIndex, 0, 0);
  422.     };
  423.    
  424.    
  425.     this._offsetY = 0;
  426.  
  427.     if (this._pos == 0) {
  428.         this._offsetY += -this.height + this._heightY;
  429.     } else if (this._pos == 1) {
  430.         this._offsetY += -this.height / 2 - 24;
  431.     } else if (this._pos == 2) {
  432.         this._offsetY += Math.abs(this._heightY * 0.2);
  433.     };
  434. };
  435.  
  436.  
  437. Window_GalvCaption.prototype.textWidthEx = function(text) {
  438.     return this.drawTextEx(text, 0, this.contents.height);
  439. };
  440.  
  441. Window_GalvCaption.prototype.update = function() {
  442.     Window_Base.prototype.update.call(this);
  443.     if (this._disable) return;
  444.     if (!this.imagesLoaded) this.checkImages();
  445.    
  446.     if (this._time == this._delayTime && !this._disable) {this.open()};
  447.     if (this._time <= 0) {
  448.         if (this._time == 0) {
  449.             this.close();
  450.         } else if (this.openness == 0) {
  451.             this.active = false;
  452.         };
  453.     };
  454.     this._time -= 1;
  455.    
  456.     if (this.follow) {
  457.         var centX = this.target.screenX() - this.width / 2;
  458.         this.x = centX;
  459.         this.y = this.target.screenY() + this._offsetY;
  460.     };
  461. };
  462.  
  463. Window_GalvCaption.prototype.checkImages = function() {
  464.     if (this.windowskin.isReady()) {
  465.         if (!this._faceBitmap || this._faceBitmap && this._faceBitmap.isReady()) {
  466.             this.setWindowDimensions();
  467.             this.imagesLoaded = true;
  468.             this._faceBitmap = null;
  469.         };
  470.     };
  471. };
  472.  
  473. if (Galv.Mpup.arrows) {
  474.     Window_GalvCaption.prototype._updateArrows = function() {
  475.         if (this.toScreen) { return };
  476.         if (this._pos == 0) { // top
  477.             this._downArrowSprite.visible = this.isOpen() && this._pos == 0;
  478.             this._downArrowSprite.anchor.y = -0.8;
  479.         } else if (this._pos == 2) { // bottom
  480.             this._upArrowSprite.visible = this.isOpen() && this._pos == 2;
  481.             this._upArrowSprite.anchor.y = 1.7;
  482.         };
  483.     };
  484. };
  485.  
  486.  
  487. // Get note offsets
  488. Galv.Mpup.Game_Enemy_setup = Game_Enemy.prototype.setup;
  489. Game_Enemy.prototype.setup = function(enemyId, x, y) {
  490.     Galv.Mpup.Game_Enemy_setup.call(this,enemyId,x,y);
  491.     var n = this.enemy().note.match(/<msgY:(.*)>/i);
  492.     this._offsetmsgY = n ? Number(n[1]) : -150;
  493. };
  494.  
  495. Galv.Mpup.Game_Actor_setup = Game_Actor.prototype.setup;
  496. Game_Actor.prototype.setup = function(actorId) {
  497.     Galv.Mpup.Game_Actor_setup.call(this,actorId);
  498.     var n = this.actor().note.match(/<msgY:(.*)>/i);
  499.     this._offsetmsgY = n ? Number(n[1]) : -40;
  500. };
  501.  
  502.  
  503.  
  504. // Get battler positions for messages
  505. Galv.Mpup.Sprite_Battler_updatePosition = Sprite_Battler.prototype.updatePosition;
  506. Sprite_Battler.prototype.updatePosition = function() {
  507.     Galv.Mpup.Sprite_Battler_updatePosition.call(this);
  508.     this._battler._msgX = this.x;
  509.     this._battler._msgY = this.y + this._battler._offsetmsgY;
  510. };
  511.  
  512. })();
Advertisement
Add Comment
Please, Sign In to add comment