public

Rpg Maker Developers Group

Simple enough for a child, powerful enough for a developer

2 Followers

MZMulti Party Plugin for MZ

BMM Archive · July 15, 2026

Preserved forum archive. This topic stores the original first post and locally mirrored RPG Maker Web attachments when available. It is posted by the BMMPlay archive account, not by the original creator.

Original Source

  • Original title: Multi Party Plugin for MZ
  • Original author: JefersonTomazella
  • Original date: March 10, 2025
  • Source thread: https://forums.rpgmakerweb.com/threads/multi-party-plugin-for-mz.176124/
  • Source forum path: Game Development Engines > RPG Maker Javascript Plugins > JS Plugin Releases (RMMZ)

Summary

I've been creating a multi party for MZ for some time now, and it's finally on a stable version. This plugin just adds the option to add, manage and swap to other parties, with it's own actors and items. { "lightbox_close": "Close",

Archived First Post

I've been creating a multi party for MZ for some time now, and it's finally on a stable version.

This plugin just adds the option to add, manage and swap to other parties, with it's own actors and items.

ss3.PNG

For now it just works using Plugin Commands on events, but I plan to add a Swap Menu (I'm actually working on that, but I'm getting some problems with parties on different maps).

Just put the TomazellaGames_MultiGroupManager.js file on the js/plugins folder of your project.

The plugin description has instructions on how to use it.

If you want to help me you can give me a tip on itch.io: https://jeftomazella.itch.io/mz-multi-parties

Download the file or get the code here:
JavaScript:
/*:
 * @target MZ
 * @plugindesc Manages multiple parties, allowing switching and visibility (items per group).
 * @author Tomazella Games
 * @help
 * This plugin enables managing multiple groups in RPG Maker MZ.
 * Groups can exchange items and actors, and are visible on the map.
 *
 * This plugin is licensed under GPL-3 license:
 * - License link: https://www.gnu.org/licenses/gpl-3.0.en.html
 * - The plugin is Open Source, and you can change, update, edit,
 *  use for commercial or personal projects, but it always has to use
 *  the same license, and always be open source.
 *
 * Website: https://tomazellagames.com/
 *
 * # How to Use:
 *
 * 1. Open Tools -> Plugin Manager... ⚙️
 * 2. Double click on the TomazellaGames_MultiGroupManager.js.️️
 * 3. On Parameters, double click Extra Groups.️️
 * 4. Double click an empty row to create, or an existing row to edit
 *  (Always Double Click to edit or add an item on the plugins window). ➕/✏️
 * 5. Open Initial Actors and choose what actors start on that group. ➡️
 * 6. Set the Initial Map ID for the group. ️
 * 7. Select the X and Y starting positions. 
 * 8. You can leave the other options as they are, unless you want
 *  to interact with the group since the game start.
 *
 * ## How to find values 
 * - To find the correct `X` and `Y` positions and Map ID:
 *   - Go to the map you want to start the party. ️
 *   - Change to Mode -> Event (or hit F6) ️
 *   - Click the map cell you want to use. ️
 *   - On the bottom right of the program you'll see some informations. ℹ️
 *     - The rightmost information is the `X, Y` position. 
 *     - The next one (to the left) is current Zoom (Usually 100%) 
 *     - Then you have info in the format `MAP_ID:NAME_NAME (WIdth, Height)`,
 *       just get the Map ID. 
 *
 * ## Plugin Commands 
 * You can use the following plugin commands for this plugin:
 *
 * ### Switch Group 
 * Params:
 * - Group Index (default group is 0) 
 * Effect: Change the control to the chosen group. ➡️
 *
 * ### Set Group Discovered ️
 * Params:
 * - Group ID: The group that will be affected by this command 
 * - Discovered: `True` or `False` ✅/❌
 * Effect: Set the discovered state (shown on the Switch Group window) ️
 *
 * ### Set Group Can Swap 
 * Params:
 * - Group ID: The group that will be affected by this command 
 * - Can Swap: `True` or `False` ✅/❌
 * Effect: Set if this group can be swapped to
 *         (can be selected on the Switch Group window) 
 *
 * ### Modify Group Actor 
 * Params:
 * - Group ID: The group that will be affected by this command 
 * - Actor ID: The actor that will be affected by this command 
 * - Action: `add` or `remove` ➕/➖
 * Effect: Adds or Removes the selected actor from the selected group ➡️
 *
 * ### Modify Group Item 
 * Params:
 * - Group ID: The group that will be affected by this command 
 * - Item Type: `Item`, `Weapon` or `Armor`,
 *               the RPG Maker MZ default item types ️/⚔️/
 * - Item ID: The index of the item on the selected item type 
 * - Amount: `Integer` value, the desired quantity of items of that
 *           type and ID the party will have. 
 * Effect: Sets the exact amount of items of that ID and type
 *         to that party. ➡️
 *
 * ### Transport Group 
 * Params:
 * - Group ID: The group that will be affected by this command 
 * - Map ID: The map the group will be transported to ️
 * - X Position: x position on the selected map the group will transfer 
 * - Y Position: y position on the selected map the group will transfer 
 * Effect: Sets the selected group position to the desired map coordinate
 *
 * @command SwitchGroup
 * @text Switch Group
 * @desc Switches to the specified group.
 *
 * @arg groupIndex
 * @text Group Index
 * @type number
 * @min 0
 * @default 0
 * @desc Index of the group to switch to (0 = main group, 1 = extra group 1, etc.).
 *
 * @command SetGroupDiscovered
 * @text Set Group Discovered
 * @desc Changes the "discovered" status of a group.
 *
 * @arg groupId
 * @text Group ID
 * @type number
 * @min 0
 * @default 1
 * @desc The ID of the group to modify.
 *
 * @arg discovered
 * @text Discovered
 * @type boolean
 * @on Yes
 * @off No
 * @default true
 * @desc Whether the group is discovered.
 *
 * @command SetGroupCanSwap
 * @text Set Group Can Swap
 * @desc Changes the "canSwap" status of a group.
 *
 * @arg groupId
 * @text Group ID
 * @type number
 * @min 0
 * @default 1
 * @desc The ID of the group to modify.
 *
 * @arg canSwap
 * @text Can Swap
 * @type boolean
 * @on Yes
 * @off No
 * @default true
 * @desc Whether the group can be swapped.
 *
 * @command ModifyGroupActor
 * @text Modify Group Actor
 * @desc Adds or removes an actor from a group.
 *
 * @arg groupId
 * @text Group ID
 * @type number
 * @min 0
 * @default 0
 * @desc The ID of the group to modify.
 *
 * @arg actorId
 * @text Actor ID
 * @type actor
 * @desc The actor to add or remove.
 *
 * @arg action
 * @text Action
 * @type select
 * @option Add
 * @value add
 * @option Remove
 * @value remove
 * @default add
 * @desc Whether to add or remove the actor.
 *
 * @command ModifyGroupItem
 * @text Modify Group Item
 * @desc Adds or removes an item, weapon, or armor from a group.
 *
 * @arg groupId
 * @text Group ID
 * @type number
 * @min 0
 * @default 0
 * @desc The ID of the group to modify.
 *
 * @arg itemType
 * @text Item Type
 * @type select
 * @option Item
 * @value item
 * @option Weapon
 * @value weapon
 * @option Armor
 * @value armor
 * @default item
 * @desc The type of item to modify.
 *
 * @arg itemId
 * @text Item ID
 * @type number
 * @default 1
 * @desc The ID of the item, weapon, or armor to modify.
 *
 * @arg amount
 * @text Amount
 * @type number
 * @default 1
 * @desc The quantity to add or remove (use negative values to remove).
 *
 * @command TransportGroup
 * @text Transport Group
 * @desc Transports a group to a position on any map.
 *
 * @arg groupId
 * @text Group ID
 * @type number
 * @min 0
 * @default 0
 * @desc The ID of the group to transport.
 *
 * @arg mapId
 * @text Map ID
 * @type number
 * @min 1
 * @default 1
 * @desc The ID of the map to transport to.
 *
 * @arg x
 * @text X Position
 * @type number
 * @default 0
 * @desc The X position to transport to.
 *
 * @arg y
 * @text Y Position
 * @type number
 * @default 0
 * @desc The Y position to transport to.
 *
 * @param extraGroups
 * @text Extra Groups
 * @type struct<Group>[]
 * @desc Define extra groups and their starting positions.
 * @default []
 *
 * @param textGroupSwitchPrompt
 * @text Group Switch Prompt
 * @type text
 * @desc Text shown when asking the player to switch groups.
 * @default Switch to this group?
 *
 * @param textGroupSwitchPrompt
 * @text Group Switch Prompt
 * @type text
 * @desc Text shown when asking the player to switch groups.
 * @default Switch to this group?
 *
 * @param enableGroupSwitch
 * @text Enable Group Switching
 * @type boolean
 * @on Yes
 * @off No
 * @desc Enable or disable group switching directly by the player.
 * @default true
 *
 * @param enableGroupCollision
 * @text Enable Group Collision
 * @type boolean
 * @on Yes
 * @off No
 * @desc Enable or disable collision between groups.
 * @default true
 */

/*~struct~Group:
 * @param actors
 * @text Initial Actors
 * @type actor[]
 * @desc Initial actors of this group.
 *
 * @param startMapId
 * @text Initial Map ID
 * @type number
 * @min 1
 * @desc Map ID where the group starts.
 * @default 1
 *
 * @param startX
 * @text Initial X Position
 * @type number
 * @desc X-coordinate where the group starts.
 * @default 0
 *
 * @param startY
 * @text Initial Y Position
 * @type number
 * @desc Y-coordinate where the group starts.
 * @default 0
 *
 * @param discovered
 * @text Is discovered at start
 * @type boolean
 * @on Yes
 * @off No
 * @desc Whether the group can be seen in the swap group menu from the start of the game.
 * @default false
 *
 * @param canSwap
 * @text Can Swap at Start
 * @type boolean
 * @on Yes
 * @off No
 * @desc Whether the group can be swapped at the start of the game.
 * @default false
 */

(() => {
    const pluginName = "TomazellaGames_MultiGroupManager";
    const parameters = PluginManager.parameters(pluginName);

    // Plugin parameters
    const extraGroups = JSON.parse(parameters["extraGroups"] || "[]").map(group => JSON.parse(group));
    const enableGroupSwitch = JSON.parse(parameters["enableGroupSwitch"] || "true");
    const enableGroupCollision = JSON.parse(parameters["enableGroupCollision"] || "true");
    const textGroupSwitchPrompt = parameters["textGroupSwitchPrompt"] || "Switch to this group?";
    
    // Namespace for all TomazellaGames plugins
    window.TomazellaGames = window.TomazellaGames || {};

    // Groups and related properties
    window.groups = [];
    window.currentGroupIndex = 0;
    window.wantToChangeToGroupIndex = -1;
    window.wantToChangeGroupFromAnotherMap = false;
    const groupEventExtraId = 90;
    // const targetSelfSwitch = "D";
    window.savedDataMapEvents = null;
    window.savedGameMapEvents = null;
    window.savedGroupPositions = {};
    window.savedEventsMapId = -1;
    
    TomazellaGames.MultiGroupManager = {
        resetSavedEvents() {
            window.savedDataMapEvents = null;
            window.savedGameMapEvents = null;
            window.savedGroupPositions = {};
            window.savedEventsMapId = -1;
            console.log("Reseting saved events for map", $gameMap.mapId());
        },
    };

    /**
     * Initializes groups with parameters and starting values.
     */
    function initializeGroups() {
        groups = [{
            id: 0,
            actors: $dataSystem.partyMembers,
            mapId: $dataSystem.startMapId,
            x: $dataSystem.startX,
            y: $dataSystem.startY,
            inventory: { items: {}, weapons: {}, armors: {}, gold: $dataSystem.startGold || 0 },
            discovered: true,
            canSwap: true
        }];
        extraGroups.forEach((group, index) => {
            try {
                const parsedActors = JSON.parse(group.actors);
                if (Array.isArray(parsedActors)) {
                    const discovered = !!(group.discovered === "true");
                    const canSwap = !!(group.canSwap === "true");
                    groups.push({
                        id: index + 1,
                        actors: parsedActors.map(Number),
                        mapId: Number(group.startMapId),
                        x: Number(group.startX),
                        y: Number(group.startY),
                        inventory: { items: {}, weapons: {}, armors: {}, gold: 0 },
                        discovered: discovered,
                        canSwap: canSwap && discovered
                    });
                } else {
                    console.error(`Error initializing group ${index + 1}: actors is not an array`, group.actors);
                }
            } catch (e) {
                console.error("Error analysing group.actors:", e);
            }
        });
    }

    /**
     * Make sure map contents are up to changes
     */
    function refreshEvents() {
        $gameMap.refresh();
    }

    // TODO make this work on different maps
    /**
     * Switches to the specified group, saving and restoring relevant data.
     * @param {number} forceGroupId - The group ID to switch to. If not specified, cycles to the next group.
     */
    window.switchGroup = function (forceGroupId = -1) {
        let targetGroupIndex = forceGroupId % groups.length;
        if (forceGroupId < 0) targetGroupIndex = (currentGroupIndex + 1) % groups.length;
        if (targetGroupIndex === currentGroupIndex) return;
        
        const lastGroup = groups[currentGroupIndex];
        lastGroup.x = $gamePlayer.x;
        lastGroup.y = $gamePlayer.y;
        lastGroup.mapId = $gameMap.mapId();
        
        const targetGroup = groups[targetGroupIndex];
        
        if (!targetGroup.canSwap || !targetGroup.discovered || !lastGroup.canSwap) {
            SoundManager.playBuzzer();
            return;
        }
        
        // if (lastGroup.mapId !== targetGroup.mapId) {
            // $gamePlayer.reserveTransfer(targetGroup.mapId, targetGroup.x, targetGroup.y, $gamePlayer.direction(), 0);
            // $gamePlayer.performTransfer();
        // }
        
        // Determine the next group to switch to
        currentGroupIndex = targetGroupIndex;
        
        // Save current group's inventory
        saveInventory(lastGroup.inventory);
         // Restore the inventory of the new active group
        loadInventory(targetGroup.inventory);
        
        // Remove all actors from the current group
        $gameParty.members().forEach(actor => {
            $gameParty.removeActor(actor.actorId());
        });
        // Add actors from the new active group
        targetGroup.actors.forEach(actorId => {
            $gameParty.addActor(actorId);
        });
        
        // refresh event positions
        toggleEventForGroup(lastGroup);
        toggleEventForGroup(targetGroup);
        refreshEvents();
        
        // Transfer the player to the new group's position
        $gamePlayer.reserveTransfer(targetGroup.mapId, targetGroup.x, targetGroup.y, $gamePlayer.direction(), 0);
        
        if (lastGroup.mapId !== targetGroup.mapId) {
            setTimeout(() => {
                $gamePlayer.performTransfer();
                
                targetGroup.x = $gamePlayer.x;
                targetGroup.y = $gamePlayer.y;
                targetGroup.mapId = $gameMap.mapId();
                
                groups.forEach((group, index) => {
                    createEventForGroup(group);
                    toggleEventForGroup(group);
                });
                refreshEvents();
                
                if (SceneManager._scene._spriteset) {
                    SceneManager._scene._spriteset.refreshCharacterSprites();
                }
            }, 0);
        } else {
            $gamePlayer.performTransfer();
                
            targetGroup.x = $gamePlayer.x;
            targetGroup.y = $gamePlayer.y;
            targetGroup.mapId = $gameMap.mapId();
            
            // groups.forEach((group, index) => {
                // createEventForGroup(group);
                // toggleEventForGroup(group);
            // });
            // refreshEvents();
            
            if (SceneManager._scene._spriteset) {
                SceneManager._scene._spriteset.refreshCharacterSprites();
            }
        }
        
        
        
        // if (SceneManager._scene._spriteset) {
            // SceneManager._scene._spriteset.refreshCharacterSprites();
        // }
        
        // Refresh character sprites to avoid visual glitches
        // if (lastGroup.mapId === targetGroup.mapId) {
            // refreshEvents();
            // SceneManager._scene._spriteset.refreshCharacterSprites();
        // } else {
            // // TomazellaGames.MultiGroupManager.resetSavedEvents();
            // // groups.forEach((group, index) => {
                // // createEventForGroup(group);
                // // toggleEventForGroup(group);
            // // });
            // // refreshEvents();
        // }
        
        // Play switch sound
        SoundManager.playRecovery();
        console.log("Changed to %s, from %s | Map: %s", currentGroupIndex, lastGroup.id, $gameMap.mapId());
    }
    
    /**
     * Saves the inventory of the current group.
     * @param {Object} inventory - The inventory to save.
     */
    function saveInventory(inventory) {
        inventory.items = JSON.parse(JSON.stringify($gameParty._items));
        inventory.weapons = JSON.parse(JSON.stringify($gameParty._weapons));
        inventory.armors = JSON.parse(JSON.stringify($gameParty._armors));
        inventory.gold = $gameParty.gold();
    }
    
    /**
     * Loads the inventory of the active group.
     * @param {Object} inventory - The inventory to load.
     */
    function loadInventory(inventory) {
        $gameParty._items = JSON.parse(JSON.stringify(inventory.items));
        $gameParty._weapons = JSON.parse(JSON.stringify(inventory.weapons));
        $gameParty._armors = JSON.parse(JSON.stringify(inventory.armors));
        $gameParty._gold = inventory.gold;
    }
    
    /**
     * Creates an event for a specific group with appropriate properties.
     * @param {Object} group - The group for which the event is created.
     */
    function createEventForGroup(group) {
        const mainActorId = group.actors[0];
        const mainActorData = $dataActors[mainActorId];
        let characterName = mainActorData ? mainActorData.characterName : "";
        let characterIndex = mainActorData ? mainActorData.characterIndex : 0;
        if (!characterName) {
            console.warn(`Main actor for group ${group.id} doesn't have a sprite. Using default image.`);
            characterName = "Actor1";
        }
        createEvent(group.x, group.y, group.id, characterName, characterIndex);
    };
    
    /**
     * Toggles visibility of a group event.
     * @param {Object} group - The group whose event should be toggled.
     * @param {boolean} show - Whether to show or hide the event.
     */
    function toggleEventForGroup(group) {
        let id = group.id + groupEventExtraId;
        const event = $gameMap.event(id);
        if (event) {
            event.locate(group.x, group.y);
        } else {
            createEventForGroup(group);
        }
        refreshEvents();
    }
    
    /**
     * Creates a new event dynamically with specified properties.
     * @param {number} x - X-coordinate of the event.
     * @param {number} y - Y-coordinate of the event.
     * @param {number} id - Unique ID for the event.
     * @param {string} characterName - Character graphic filename.
     * @param {number} characterIndex - Character graphic index.
     * @param {Array} commands - Event commands.
     * @param {string} eventName - Name of the event.
     */
    function createEvent(x, y, groupId, characterName = "", characterIndex = 0) {
        const event_name = `Group[${groupId}]`;
        const id = groupId + groupEventExtraId;
        if ($dataMap.events[id]) {
            const existingEvent = $dataMap.events[id];
            if (
                existingEvent.name === event_name &&
                existingEvent.x === x &&
                existingEvent.y === y &&
                existingEvent.pages?.length > 0
            ) {
                return;
            } else {
                console.warn(`Evento ${id} está corrompido ou incompleto. Recriando...`);
            }
        }
        
        const sameMap = `groups[${groupId}]?.mapId === $gameMap.mapId()`;
        const otherGroup = `${groupId} !== window.currentGroupIndex`;
        const discovered = `groups[${groupId}]?.discovered === true`;
        const condition = discovered + " && " + otherGroup + " && " + sameMap;
        
        const canSwapCondition = condition + ` && groups[${groupId}]?.canSwap === true`;
        
        const eventData = {
            id: id,
            name: event_name,
            x: x,
            y: y,
            pages: [
                {
                    conditions: { switch1Valid: false, switch2Valid: false, variableValid: false, selfSwitchValid: false },
                    image: { tileId: 0, characterName: "", characterIndex: 0, direction: 2, pattern: 0 },
                    moveType: 0,
                    trigger: 0,
                    list: [],
                    directionFix: false,
                    priorityType: 0,
                    walkAnime: false,
                    stepAnime: false,
                    moveSpeed: 0,
                    moveFrequency: 0
                },
                {
                    conditions: {
                        switch1Valid: false, switch2Valid: false,
                        variableValid: false,
                        customCondition: condition
                    },
                    image: { tileId: 0, characterName: characterName || "", characterIndex: characterIndex, direction: 2, pattern: 0 },
                    moveType: 0,
                    trigger: enableGroupCollision ? 0 : 1,
                    list: [
                        { code: 102, indent: 0, parameters: [["Can't switch to this group now"], 2] },
                        { code: 402, indent: 0, parameters: [0] },
                        { code: 0, indent: 0 }
                    ],
                    directionFix: false,
                    priorityType: enableGroupCollision ? 1 : 0,
                    walkAnime: true,
                    stepAnime: true,
                    moveSpeed: 3,
                    moveFrequency: 3
                },
                {
                    conditions: {
                        switch1Valid: false, switch2Valid: false,
                        variableValid: false,
                        customCondition: canSwapCondition
                    },
                    image: { tileId: 0, characterName: characterName || "", characterIndex: characterIndex, direction: 2, pattern: 0 },
                    moveType: 0,
                    trigger: enableGroupCollision ? 0 : 1,
                    list: [
                        { code: 102, indent: 0, parameters: [[textGroupSwitchPrompt], 2] },
                        { code: 402, indent: 0, parameters: [0] },
                        { code: 355, indent: 1, parameters: [`switchGroup(${groupId});`] },
                        { code: 0, indent: 0 }
                    ],
                    directionFix: false,
                    priorityType: enableGroupCollision ? 1 : 0,
                    walkAnime: true,
                    stepAnime: true,
                    moveSpeed: 3,
                    moveFrequency: 3
                }
            ]
        };
        if (!$dataMap.events[id]) {
            $dataMap.events[id] = eventData;
        } else {
            Object.assign($dataMap.events[id], eventData);
        }
        $gameMap.setupEvents();
        refreshEvents();
    }
    
    /**
     * Call the plugin command from events
     */
    const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);
    };
    
    /**
     * Updates current group inventory as soon as we change items
     */
    const _Game_Party_gainItem = Game_Party.prototype.gainItem;
    Game_Party.prototype.gainItem = function(item, amount, includeEquip) {
        _Game_Party_gainItem.call(this, item, amount, includeEquip);
        
        if (groups) {
            const currentGroup = groups[currentGroupIndex];
            if (currentGroup) {
                currentGroup.inventory.items = JSON.parse(JSON.stringify(this._items));
                currentGroup.inventory.weapons = JSON.parse(JSON.stringify(this._weapons));
                currentGroup.inventory.armors = JSON.parse(JSON.stringify(this._armors));
                currentGroup.inventory.gold = this.gold();
            }
        }
    };

    /**
     * Adds the groups events to the current map
     */
    const _Game_Map_setup = Game_Map.prototype.setup;
    Game_Map.prototype.setup = function(mapId) {
        _Game_Map_setup.call(this, mapId);
        if (SceneManager._scene instanceof Scene_Map) {
            groups.forEach((group, index) => {
                createEventForGroup(group);
                toggleEventForGroup(group);
            });
            refreshEvents();
            console.log("Criou grupos para o mapa", $gameMap.mapId());
        }
        
    };
    
    /**
     * Release current sprites and update the correct ones
     */
    Spriteset_Map.prototype.refreshCharacterSprites = function() {
        // Remove current sprites
        if (this._characterSprites) {
            this._characterSprites.forEach(sprite => {
                if (sprite.parent) {
                    sprite.parent.removeChild(sprite);
                }
            });
        }
        // Restore characters sprites
        this.createCharacters();
    };
    
    /**
     * Save current map events so groups sprites and events are not lost when opening menu
     */
    const _Scene_Menu_create = Scene_Menu.prototype.create;
    Scene_Menu.prototype.create = function() {
        window.savedEventsMapId = $gameMap.mapId();
        savedDataMapEvents = JSON.parse(JSON.stringify($dataMap.events));
        savedGameMapEventIds = $gameMap._events.map(event => event ? event.eventId() : null);
        savedGroupPositions = groups.map(group => ({
            mapId: group.mapId,
            x: group.x,
            y: group.y
        }));
        _Scene_Menu_create.call(this);
    };

    /**
     * Overriding Scene_Map.start to handle restoring events
     */
    const _Scene_Map_start = Scene_Map.prototype.start;
    Scene_Map.prototype.start = function() {
        console.warn("Scene_Map.prototype.start START", $gameMap.mapId());
        console.log("window.savedEventsMapId %s | $gameMap.mapId() %s", window.savedEventsMapId, $gameMap.mapId());
        if (window.savedEventsMapId == $gameMap.mapId() && !window.wantToChangeGroupFromAnotherMap) {
            if (savedDataMapEvents && savedGameMapEventIds) {
                // Restore events in $dataMap
                $dataMap.events = JSON.parse(JSON.stringify(savedDataMapEvents));
                // Restore events in $gameMap as instances of Game_Event
                $gameMap._events = savedGameMapEventIds.map(eventId => {
                    if (eventId !== null && $dataMap.events[eventId]) {
                        const eventData = $dataMap.events[eventId];
                        if (eventData && typeof eventData.x === "number" && typeof eventData.y === "number") {
                            try {
                                return new Game_Event($gameMap.mapId(), eventId);
                            } catch (error) {
                                console.error(`Error creating the event ${eventId}:`, error);
                                return null;
                            }
                        } else {
                            console.warn(`Event ${eventId} doesn't have valid coordinates.`);
                            return null;
                        }
                    }
                    console.warn(`Event ${eventId} not found or invalid.`);
                    return null;
                });
                $gameMap.refresh();
                this._spriteset.refreshCharacterSprites(); // Clear and recreate the sprites
            }
            if (savedGroupPositions && savedGroupPositions.length > 0) {
                groups.forEach((group, index) => {
                    const position = savedGroupPositions[index];
                    if (position) {
                        group.mapId = position.mapId;
                        group.x = position.x;
                        group.y = position.y;
                    }
                });
                groups.forEach(group => {
                    // createEventForGroup(group);
                    toggleEventForGroup(group);
                });
                refreshEvents();
            }
        } else {
            TomazellaGames.MultiGroupManager.resetSavedEvents();
            window.wantToChangeGroupFromAnotherMap = false;
            // groups.forEach((group, index) => {
                // createEventForGroup(group);
                // toggleEventForGroup(group);
            // });
            // refreshEvents();
            // console.log("Criou grupos para o mapa", $gameMap.mapId());
        }
        
        // if (wantToChangeToGroupIndex >= 0 && wantToChangeToGroupIndex != currentGroupIndex) {
            // console.log("Is going to change to %s, from %s", wantToChangeToGroupIndex, currentGroupIndex);
            // switchGroup(wantToChangeToGroupIndex);
        // }
        // wantToChangeToGroupIndex = -1;
        
        _Scene_Map_start.call(this);
        
        if (wantToChangeToGroupIndex >= 0 && wantToChangeToGroupIndex != currentGroupIndex) {
            console.log("Is going to change to %s, from %s", wantToChangeToGroupIndex, currentGroupIndex);
            switchGroup(wantToChangeToGroupIndex);
        }
        wantToChangeToGroupIndex = -1;
        console.warn("Scene_Map.prototype.start END", $gameMap.mapId());
    };
    
    /**
     * Add the option to switch groups
     */
    const _Scene_Map_update = Scene_Map.prototype.update;
    Scene_Map.prototype.update = function() {
        _Scene_Map_update.call(this);
        if (enableGroupSwitch && Input.isTriggered('pageup')) {
            switchGroup(currentGroupIndex - 1);
        }
        if (enableGroupSwitch && Input.isTriggered('pagedown')) {
            switchGroup();
        }
        
        // if (wantToChangeToGroupIndex >= 0 && wantToChangeToGroupIndex != currentGroupIndex) {
            // console.log("Is going to change to %s, from %s", wantToChangeToGroupIndex, currentGroupIndex);
            // switchGroup(wantToChangeToGroupIndex);
            // wantToChangeToGroupIndex = -1;
        // }
    };

    /**
     * Initialize the groups when a new game is created.
     */
    const _Scene_Title_commandNewGame = Scene_Title.prototype.commandNewGame;
    Scene_Title.prototype.commandNewGame = function() {
        _Scene_Title_commandNewGame.call(this);
        initializeGroups();
    };
    
    /**
     * Adds the ability to check custom conditions in events. Only accessible by code.
     */
    const _Game_Event_meetsConditions = Game_Event.prototype.meetsConditions;
    Game_Event.prototype.meetsConditions = function(page) {
        if (!_Game_Event_meetsConditions.call(this, page)) {
            return false;
        }

        if (page.conditions.customCondition) {
            try {
                const result = eval(page.conditions.customCondition); // Avalia a condição
                return !!result; // Garante que o resultado seja um valor booleano
            } catch (error) {
                console.error("Erro ao avaliar a condição personalizada:", page.conditions.customCondition, error);
                return false; // Retorna `false` para evitar travar o jogo
            }
        }

        // Todas as condições foram atendidas
        return true;
    };

    
    /**
     * Save groups data to persist through game sessions
     */
    const _DataManager_makeSaveContents = DataManager.makeSaveContents;
    DataManager.makeSaveContents = function() {
        const contents = _DataManager_makeSaveContents.call(this);
        contents.groups = window.groups; // Salvar os grupos
        contents.currentGroupIndex = window.currentGroupIndex; // Salvar o índice do grupo atual
        return contents;
    };
    
    /**
     * Overload load data to get groups data
     */
    const _DataManager_extractSaveContents = DataManager.extractSaveContents;
    DataManager.extractSaveContents = function(contents) {
        _DataManager_extractSaveContents.call(this);
        window.groups = contents.groups || groups;
        window.wantToChangeToGroupIndex = contents.currentGroupIndex || -1;
    };
    
    // Plugin commands ----------------------------------------
    
    /**
     * Plugin command to switch groups
     */
    PluginManager.registerCommand(pluginName, "SwitchGroup", args => {
        const groupIndex = Number(args.groupIndex) - 1;
        if (!isNaN(groupIndex) && groups[groupIndex]) {
            switchGroup(groupIndex);
        } else {
            console.error(`Grupo inválido: ${groupIndex}`);
        }
    });
    
    PluginManager.registerCommand(pluginName, "SetGroupDiscovered", args => {
        const groupId = Number(args.groupId);
        const discovered = args.discovered === "true";
        const group = groups[groupId];
        if (group) {
            group.discovered = discovered;
            group.canSwap = discovered && group.canSwap; // Ensure "canSwap" is only true if "discovered" is true.
            if (discovered) {
                createEventForGroup(group);
            }
            console.log(`Group ${groupId} discovered status set to: ${discovered}`);
        } else {
            console.error(`Group ${groupId} not found.`);
        }
    });

    PluginManager.registerCommand(pluginName, "SetGroupCanSwap", args => {
        const groupId = Number(args.groupId);
        const canSwap = args.canSwap === "true";
        const group = groups[groupId];
        if (group) {
            group.canSwap = canSwap;
            createEventForGroup(group);
            console.log(`Group ${groupId} canSwap status set to: ${canSwap}`);
        } else {
            console.error(`Group ${groupId} not found.`);
        }
    });

    PluginManager.registerCommand(pluginName, "ModifyGroupActor", args => {
        const groupId = Number(args.groupId);
        const actorId = Number(args.actorId);
        const action = args.action;
        const group = groups[groupId];
        if (group) {
            if (action === "add" && !group.actors.includes(actorId)) {
                group.actors.push(actorId);
                console.log(`Actor ${actorId} added to group ${groupId}.`);
                createEventForGroup(group);
            } else if (action === "remove" && group.actors.includes(actorId)) {
                group.actors = group.actors.filter(id => id !== actorId);
                console.log(`Actor ${actorId} removed from group ${groupId}.`);
                createEventForGroup(group);
            } else {
                console.warn(`Action "${action}" on actor ${actorId} for group ${groupId} could not be completed.`);
            }
        } else {
            console.error(`Group ${groupId} not found.`);
        }
    });
    
    PluginManager.registerCommand(pluginName, "ModifyGroupItem", args => {
        const groupId = Number(args.groupId);
        const itemType = args.itemType;
        const itemId = Number(args.itemId);
        const amount = Number(args.amount);
        const group = groups[groupId];
        if (group) {
            let inventory;
            if (itemType === "item") {
                inventory = group.inventory.items;
            } else if (itemType === "weapon") {
                inventory = group.inventory.weapons;
            } else if (itemType === "armor") {
                inventory = group.inventory.armors;
            } else {
                console.error(`Invalid item type: ${itemType}`);
                return;
            }
            inventory[itemId] = (inventory[itemId] || 0) + amount;
            if (inventory[itemId] <= 0) delete inventory[itemId]; // Remove item if quantity is zero or less.
            console.log(`${itemType.charAt(0).toUpperCase() + itemType.slice(1)} ${itemId} quantity changed by ${amount} for group ${groupId}.`);
        } else {
            console.error(`Group ${groupId} not found.`);
        }
    });

    PluginManager.registerCommand(pluginName, "TransportGroup", args => {
        const groupId = Number(args.groupId);
        const mapId = Number(args.mapId);
        const x = Number(args.x);
        const y = Number(args.y);
        const group = groups[groupId];
        if (group) {
            group.mapId = mapId;
            group.x = x;
            group.y = y;
            console.log(`Group ${groupId} transported to Map ${mapId}, X: ${x}, Y: ${y}.`);
            createEventForGroup(group);
        } else {
            console.error(`Group ${groupId} not found.`);
        }
    });

    PluginManager.registerCommand(pluginName, "InitializeGroups", initializeGroups);
})();

Downloads / Referenced Files

Log in to download

Log in, then follow the RPG Maker Developers Group to see these download links.

Log in to download

License / Terms Note

* This plugin is licensed under GPL-3 license: * - License link: https://www.gnu.org/licenses/gpl-3.0.en.html * - The plugin is Open Source, and you can change, update, edit, * use for commercial or personal projects, but it always has to use

Creator Claims / Removal

If you are the original creator and want this listing reassigned, edited, or removed, join BMMPlay and contact the moderators with proof that matches the original RPG Maker Web profile, linked GitHub, itch.io page, or another public creator identity.

#039#rmmz#plugin-archive

Replies (0)

No replies yet.

0 replies 1 view

Log in to reply.

User Avatar