Unstacking followers from on top of the player

zzmmorgan

I've used punchcards
Veteran
Joined
Jul 10, 2020
Messages
145
Reaction score
218
First Language
English
Primarily Uses
RMMZ
I spent over two hours searching for how to do this and mostly found non-answers like "it's too hard so you need to do a plugin request" but those non-answers never seemed to come from people who actually write plugins. And one of the actual plugin authors at one point (I think it was Yanfly) mentioned that most of the functionality of their plugins could be accomplished within the event system. And it is, indeed, rather flexible if you take the time to learn it. HOWEVER there are some things that aren't exposed in the event system and Follower settings are a big one not there.

So first this is actually a trivial task. In order to "unstack" the followers when you first transfer into a map you only need to know the direction the player is facing and the X and Y coordinates they are at. Then all you need to do is assign each follower to an appropriate position. This does assume that you setup the player entry position far enough from walls and such that the followers won't be in a strange position.

Since the follower info can't be manipulated directly in the event system we need some javascript to do that. And it's rather trivial as it only requires a SINGLE line of code for each follower. So assuming the standard party size of 4 that's THREE lines of code. When facing down you want each the first follower to have the same X position as the player but -1 to the Y and the second is -2 to the Y and so on.

Your first step is to create an event and it's better to do it someplace where the player and NPCs won't wander on top of it and set it to priority "Below characters" and the Trigger to "Autorun" and then the fun begins.
We can use the event system and game variables to get the player facing and X and Y coordinates like this:
1631469714625.png

Once you get the variables named you need to fill them in like this:
1631469817947.png
in the Control Variables we need to choose the variable like this:
1631469892513.png
And fill it like this:
1631469939659.png
Choose Game Data then select it and grab this:
1631470040650.png
Choose Character, Player and Direction.
Then do the same for the Map X and Map Y to go into the Player X and Player Y variables respectively.
You should end up with this:
1631470258413.png

We need to check the Player direction. I dug into the main javascript files and found this:

Game_Map.prototype.doScroll = function(direction, distance) {
switch (direction) {
case 2:
this.scrollDown(distance);
break;
case 4:
this.scrollLeft(distance);
break;
case 6:
this.scrollRight(distance);
break;
case 8:
this.scrollUp(distance);
break;
}
};

That tells us that Down is 2, Left is 4 and so on. Interesting thing is this implies that we can do diagonals and those would be the odd numbers but we don't need that now :)
So we next need to check for those directions like this:
1631470717801.png
1631470783714.png

We'll want to choose Variable and use our Player Facing variable and select 2 for the down position.
We don't truly need an else which will make this look a little cleaner so leave that checkbox off.
Now the fun part:
1631470881528.png
Right there between the IF and the End we want to add the Script which is on Tab 3
1631470956877.png
more game variables that took some digging to find go in here like this:
$gamePlayer.followers()._data[0].locate($gamePlayer.x, $gamePlayer.y-1);
$gamePlayer.followers()._data[1].locate($gamePlayer.x, $gamePlayer.y-2);
$gamePlayer.followers()._data[2].locate($gamePlayer.x, $gamePlayer.y-3);

That's our 3 lines of code needed and you can copy those from here and paste them into that window like this:
1631471188090.png
and the end result looks like this:
1631471214529.png

So now even if you didn't know javascript before you've advanced from noob to powernoob :)
Once we complete the other directions your event should look like this:
1631471280504.png

I took an extra step and did an Erase Event at the tail end but it's probably unnecessary.
You will see an immediate result when you start the game since that event is autorun and you'll see the followers in their line behind the player like this:
1631471457780.png

And as long as you set your maps up properly and have a copy of that event on each map then when your player transfers to a map everyone will be in their proper spot!

For MZ since it allows more code into the Script window I condensed it much further to one simple script command for the event you can see here:
MZ version simplified
 

Attachments

  • 1631469187158.png
    1631469187158.png
    159.2 KB · Views: 0
  • 1631470153340.png
    1631470153340.png
    125.5 KB · Views: 0
  • 1631470692457.png
    1631470692457.png
    133.9 KB · Views: 0

Dev_With_Coffee

Veteran
Veteran
Joined
Jul 20, 2020
Messages
743
Reaction score
360
First Language
PT-BR
Primarily Uses
RM2k3
Sorry, what is the need for variables 2 and 3?

A tip, it would be more practical to use Javascript in the "Conditional Branches":
Code:
◆If:Script:$gamePlayer._direction == 2
  ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x, $gamePlayer.y-1);
  :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x, $gamePlayer.y-2);
  :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x, $gamePlayer.y-3);
  ◆
:End
◆If:Script:$gamePlayer._direction == 4
  ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x+1, $gamePlayer.y);
  :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x+2, $gamePlayer.y);
  :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x+3, $gamePlayer.y);
  ◆
:End
◆If:Script:$gamePlayer._direction == 6
  ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x-1, $gamePlayer.y);
  :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x-2, $gamePlayer.y);
  :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x-3, $gamePlayer.y);
  ◆
:End
◆If:Script:$gamePlayer._direction == 8
  ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x, $gamePlayer.y+1);
  :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x, $gamePlayer.y+2);
  :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x, $gamePlayer.y+3);
  ◆
:End
◆Wait:3 frames
To avoid the lag I put a "wait" of 3 frames.

I apologize in advance, I'm not a programmer, just to be able to improve.

Good luck
 
Last edited:

zzmmorgan

I've used punchcards
Veteran
Joined
Jul 10, 2020
Messages
145
Reaction score
218
First Language
English
Primarily Uses
RMMZ
I didn't dig far enough to find that locate :)
This wasn't something that was optimized by any stretch. Just a quick and dirty thing I cobbled together when failing to find any way to do it. It was actually easier to do in MZ because I could just throw it into a switch statement but in MV the script box wouldn't hold that many lines of code. And since while I was searching for a solution I found a few questions on MV (without answers sadly) I decided to beat a solution into MV as well :)

Honestly I like to use the system without resorting to code as much as possible as if I'm doing a lot of coding there are much better engines for that. This is my quick and dirty way to do things engine. I actually got RPG Maker when I realized I was coding an RPG in Godot and was unhappy with my adventures in NPC AI......
 

Dev_With_Coffee

Veteran
Veteran
Joined
Jul 20, 2020
Messages
743
Reaction score
360
First Language
PT-BR
Primarily Uses
RM2k3
The effect itself was very strange, because the characters don't walk, they just reappear in different places, the best thing would be to do this repositioning when changing direction:
Code:
◆Control Variables:#0015 Direction Current = Direction of Player
◆If:Direction Current ≠ Direction Change?
  ◆If:Direction Current = 2
    ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x, $gamePlayer.y-1);
    :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x, $gamePlayer.y-2);
    :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x, $gamePlayer.y-3);
    ◆
  :End
  ◆If:Direction Current = 4
    ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x+1, $gamePlayer.y);
    :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x+2, $gamePlayer.y);
    :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x+3, $gamePlayer.y);
    ◆
  :End
  ◆If:Direction Current = 6
    ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x-1, $gamePlayer.y);
    :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x-2, $gamePlayer.y);
    :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x-3, $gamePlayer.y);
    ◆
  :End
  ◆If:Direction Current = 8
    ◆Script:$gamePlayer.followers()._data[0].locate($gamePlayer.x, $gamePlayer.y+1);
    :      :$gamePlayer.followers()._data[1].locate($gamePlayer.x, $gamePlayer.y+2);
    :      :$gamePlayer.followers()._data[2].locate($gamePlayer.x, $gamePlayer.y+3);
    ◆
  :End
  ◆
:End
◆Control Variables:#0016 Direction Change? = Direction of Player
◆Wait:3 frames
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
1,795
Reaction score
924
First Language
English
Primarily Uses
RMMV
@Dev_With_Coffee - maybe I missed something in the original post, as it's not a technique I need for my games, but what is the Wait at the end for?
 

Dev_With_Coffee

Veteran
Veteran
Joined
Jul 20, 2020
Messages
743
Reaction score
360
First Language
PT-BR
Primarily Uses
RM2k3
@ATT_Turan -> When there are many systems due to events in parallel process on the same map, this usually causes loss of frames, so just 1 frame already avoids such accelerated loop.

I assume that the RMMV works differently from the older ones, I still kept this practice.
 

ATT_Turan

Forewarner of the Black Wind
Veteran
Joined
Jul 2, 2014
Messages
1,795
Reaction score
924
First Language
English
Primarily Uses
RMMV
Oh, I didn't see him say that he had other parallel processes running.
 

Dev_With_Coffee

Veteran
Veteran
Joined
Jul 20, 2020
Messages
743
Reaction score
360
First Language
PT-BR
Primarily Uses
RM2k3
As I said, for practice I already insert. What's more, this varies on each computer, this varies on each computer, por isso tenho o costume.
 

zzmmorgan

I've used punchcards
Veteran
Joined
Jul 10, 2020
Messages
145
Reaction score
218
First Language
English
Primarily Uses
RMMZ
My method has NO parallel processes as there isn't a need. It only needs to run when the map first loads. Once the followers are in place it's good until the next map transfer since they gleefully follow the leader once you start moving. :)
 

Dev_With_Coffee

Veteran
Veteran
Joined
Jul 20, 2020
Messages
743
Reaction score
360
First Language
PT-BR
Primarily Uses
RM2k3
Got it, sorry for the misinterpretation.
I encountered a problem, if the player is moved too close to the edges, some followers will get stuck off screen.

Transfer to x:010, y:000 on the map:
-> Only follower 1 will appear.

Transfer to x:010, y:001 on the map:
-> Only followers 1 and 2 will appear.
 

zzmmorgan

I've used punchcards
Veteran
Joined
Jul 10, 2020
Messages
145
Reaction score
218
First Language
English
Primarily Uses
RMMZ
Yeah that's why I said to make sure there's room for the followers. My use case was to mimic chunk loading so each map will have a nice overlap of the adjoining one so it looks like you're moving across a large map rather than jumping between maps. With that use case then the path they're following will be partly copied onto the next map and the player will be far enough from the border it won't be an issue. The initial start position would be the only real problem there as you want to make sure the followers aren't in a wall or off the map. :)
I'm honestly not certain if any of the unanswered questions I saw when I did some Google searches were thinking of this exact use as they only mentioned unbundling the followers or keeping them from bunching up.
My personal use for this is in MZ but I did this because the questions I found were for MV and figured since obviously I wasn't the only one looking for a way to do this and a lot of people are still using MV I'd do this too. Interesting thing is that even though overall MZ is faster than MV the map loading seemed a tiny bit faster in my sample for MV but the maps were a bit smaller so that might have been why.
 

Latest Threads

Latest Posts

Latest Profile Posts

Hot chocolate and music make studying and note-taking much easier :kaoluv:
Until my hand cramps up from writing too much!
Doing RPG Maker News for 21st September 2021


Malak is still waiting for Dark Deception Chapter 4... This was him yesterday after another sugar crash.
Again, he's fine. He's just bored at this point, considering he's exhausted his entire vacation bucket list.
Am I the only one who files custom resources under specific folders to remember who to credit? :kaoswt2:
1632263519730.png
I always smile to myself when I see someone do the "immediate halt and spin around" from forgetting something. I find it sort of endearing how we all do it without ever being taught to.

Forum statistics

Threads
115,265
Messages
1,088,456
Members
149,869
Latest member
ekqul
Top