Activating parallel process events based on distance from player

AmVa

Villager
Member
Joined
Jul 6, 2022
Messages
15
Reaction score
3
First Language
English
Primarily Uses
RMMV
I've read a few threads with similar questions here but didn't find something that fits exactly what I need. Hope someone can suggest an idea.

I want to have several parallel process events running on the map (let's call them "monsters") that would normally have random movement, but then activate a second page and change their movement to chase the player once the player is in their range (for the sake of example, say a distance of 3 tiles).
Once the player leaves this range, the "monster" event should trigger again and turn itself back to the first page where it moves randomly.

I've tried a few ways to do this but can't figure it out yet. Using variables to calculate the distance is great for one monster, but I need several monsters running simultanously. They all calculate the variables at the same time, so they mess up each other's distances. I also have other events on the map that check the player's location which are impacted.
I also tried to use a plugin that was made for player touch trigger for the first page of the event, which was a step forward, but the second page still has to be a parallel process.

I do not have any scripting knowledge but if that's the only solution, I'll be happy for instructions on how to implement that into the event. Thanks!
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
36,679
Reaction score
9,857
First Language
German
Primarily Uses
RMMV
yanfly has a plugin for that, but I don't remember the name
 

Another Fen

Veteran
Veteran
Joined
Jan 23, 2013
Messages
646
Reaction score
357
First Language
German
Primarily Uses
Can't point to a plugin right now, but since you asked for instructions too:

Probably not that relevant these days, but "Parallel Processes" are still executed in deterministic potions one after another, meaning you can use the same variables between them under certain circumstances.

Generally updating an event each frame works by executing event commands in order until the end of the command list is reached or one event command causes the procedure to "wait" (Message commands, Menu Calls, Player Transfer, Change Tileset, "Wait" and anything with "Wait for Completion" enabled, and of course possibly Plugin- and Script commands depending on their contents). Only after that will the game switch to the next event.

Anything else is guaranteed to be executed without interruption by other parallel events.

In MV there are two other exceptions: Hitting 10000 event commands in one frame (unlikely to happen under normal circumstances, it prevents the game to freeze if you feed it an empty loop command) and "Jump to Label" for some reason (seemingly unintended; MZ fixes that one and makes it instant again).
 

AmVa

Villager
Member
Joined
Jul 6, 2022
Messages
15
Reaction score
3
First Language
English
Primarily Uses
RMMV
Generally updating an event each frame works by executing event commands in order until the end of the command list is reached or one event command causes the procedure to "wait" (Message commands, Menu Calls, Player Transfer, Change Tileset, "Wait" and anything with "Wait for Completion" enabled, and of course possibly Plugin- and Script commands depending on their contents). Only after that will the game switch to the next event.

So if I understand what you're getting at, I could add a "wait" command to each monster with a different number of frames in order to dictate an order in which they alter the variables?

monster #1 will process first, monster #2 waits 1 frame before processing, monster #3 waits 2 frames and so on... all using the same four variables (their own XY cords and player's XY cords)?
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
36,679
Reaction score
9,857
First Language
German
Primarily Uses
RMMV
I could add a "wait" command to each monster with a different number of frames
yes and no, that would only work for the first loop.

the internal function of the wait is telling the engine to skip processing that event for x frames.

and usually your enemy events will loop to get multiple steps, so if you give one event a wait 1 it will be processed every loop, if you give an event a wait 2 it will be processed every other frame, with wait 3 every third frame and so on.
so in the sixth frame you'll have all three events processed again in the same frame.

there are two solutions for your problem:
1) control all enemies in the same parallel event one after another.
this is actually the theoretically best solution because you can use the same variables one after another and don't mess the game loop up with multiple parallel processes, but it does require careful handling of one monster after another and the event is always map-dependent.

2) use of self-variables to store the monster coordinates
however that is a different plugin that is needed in this case as the default engine has no self-variables.
 

AmVa

Villager
Member
Joined
Jul 6, 2022
Messages
15
Reaction score
3
First Language
English
Primarily Uses
RMMV
Thanks!
2) use of self-variables to store the monster coordinates
however that is a different plugin that is needed in this case as the default engine has no self-variables.

I think I'll try this one first because I want the player to be able to deal with the monsters in any order

I just came across this tutorial as well: https://forums.rpgmakerweb.com/inde...f-reach-objects-in-front-of-you-mv-mz.144369/

I feel like the same scripting that is applied in this tutorial to check for neaby events can be used for my case too, but instead of moving events in the proximity, it could switch between the monster's event pages?
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
36,679
Reaction score
9,857
First Language
German
Primarily Uses
RMMV
because I want the player to be able to deal with the monsters in any order
nothing stops you doing that with the first solution either.
 

AmVa

Villager
Member
Joined
Jul 6, 2022
Messages
15
Reaction score
3
First Language
English
Primarily Uses
RMMV
1) control all enemies in the same parallel event one after another.

Didn't work so far, but probably because I'm using a single switch to change the monsters into their second page. Is there no way around setting an individual switch for each monster?
 

Another Fen

Veteran
Veteran
Joined
Jan 23, 2013
Messages
646
Reaction score
357
First Language
German
Primarily Uses
So if I understand what you're getting at, I could add a "wait" command to each monster with a different number of frames in order to dictate an order in which they alter the variables?
Not quite. As long as you are only using commands that are instantly executed (like a bunch of Control Variables and Conditional Branches to calculate your distances) and you don't care what happens to the variable afterwards you don't actually need to worry about parallel processes. Parallel events are updated one after another and will not randomly interfere with each other.

In praxis you need to be careful with this, and using scripts/plugins is usually way more comfortable for this, it might still be a useful trick if you are in a situation where you can't script something for some reason.

This might work for any number of parallel events for example (minus the console.log scripts unless you like to get spammed.^^ They are just there to demonstrate that start to finish is indeed executed in the same frame):
DistanceCheck.jpg


Edit:
The code in the example only checks a single tile at a time for events, which would definitely be servicable. Once you have an event ID stored in a variable (variable 1 in this example) you can always use
Code:
let key = [$gameMap.mapId(), $gameVariables.value(1), "A"];
$gameSelfSwitches.setValue(key, true);
to activate that events self switch "A" for example.


Alternatively you can put the entire distance calculation for this event into a single script:
This would activate Self Switch A of "this event" if the Manhattan distance (sum of X- and Y- distance) to the player is 3 tiles or less (as an example, modify as needed):

Code:
let event = this.character(0);
if (event) {
    let player = $gamePlayer;
    let distance = Math.abs(player.x - event.x) + Math.abs(player.y - event.y);
    if (distance <= 3) {
        // 3 Tiles or less:
        $gameSelfSwitches.setValue([this._mapId, this._eventId, "A"], true);
    }
}

This code also works if you want to check multiple events instead of just "this event":
Code:
let eventIds = [2, 3, 4, 5, 7];  // <- Event IDs
eventIds.forEach(id => {
    let event = this.character(id);
    if (event) {
        let player = $gamePlayer;
        let distance = Math.abs(player.x - event.x) + Math.abs(player.y - event.y);
        if (distance <= 3) {
            // 3 Tiles or less:
            $gameSelfSwitches.setValue([this._mapId, id, "A"], true);
        }
    }
}, this);
 
Last edited:

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
36,679
Reaction score
9,857
First Language
German
Primarily Uses
RMMV
but probably because I'm using a single switch to change the monsters into their second page. Is there no way around setting an individual switch for each monster?
depends on what exactly you're doing, because usually that is what self-switches instead of general switches are for.

it would probably help if you show us what you do in your enemy events, why you need a second page and so on.
 

AmVa

Villager
Member
Joined
Jul 6, 2022
Messages
15
Reaction score
3
First Language
English
Primarily Uses
RMMV
it would probably help if you show us what you do in your enemy events, why you need a second page and so on.

the monsters themselves are dummy events as I'm trying your first solution, they only have different autonomous movement (first page they move randomly, second page they chase the player)

◆Control Variables:#0014 PLocationInCombat-X = Map X of Player
◆Control Variables:#0015 PLocationInCombat-Y = Map Y of Player
◆Control Variables:#0010 EnemyLocation-X = Map X of dummy1
◆Control Variables:#0011 EnemyLocation-Y = Map Y of dummy1
◆If:PLocationInCombat-X > EnemyLocation-X
◆Control Variables:#0014 PLocationInCombat-X -= EnemyLocation-X
◆If:PLocationInCombat-X ≤ 3
◆If:PLocationInCombat-Y = EnemyLocation-Y
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Variables:#0010 EnemyLocation-X -= PLocationInCombat-X
◆If:EnemyLocation-X ≤ 3
◆If:PLocationInCombat-Y = EnemyLocation-Y
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:End
◆If:PLocationInCombat-Y > EnemyLocation-Y
◆Control Variables:#0015 PLocationInCombat-Y -= EnemyLocation-Y
◆If:PLocationInCombat-Y ≤ 3
◆If:PLocationInCombat-X = EnemyLocation-X
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Variables:#0011 EnemyLocation-Y -= PLocationInCombat-Y
◆If:EnemyLocation-Y ≤ 3
◆If:PLocationInCombat-X = EnemyLocation-X
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:End

◆Wait:1 frame (this is the wait between each monster...)
◆Control Variables:#0014 PLocationInCombat-X = Map X of Player
◆Control Variables:#0015 PLocationInCombat-Y = Map Y of Player
◆Control Variables:#0010 EnemyLocation-X = Map X of dummy2
◆Control Variables:#0011 EnemyLocation-Y = Map Y of dummy2
◆If:PLocationInCombat-X > EnemyLocation-X
◆Control Variables:#0014 PLocationInCombat-X -= EnemyLocation-X
◆If:PLocationInCombat-X ≤ 3
◆If:PLocationInCombat-Y = EnemyLocation-Y
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Variables:#0010 EnemyLocation-X -= PLocationInCombat-X
◆If:EnemyLocation-X ≤ 3
◆If:PLocationInCombat-Y = EnemyLocation-Y
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:End
◆If:PLocationInCombat-Y > EnemyLocation-Y
◆Control Variables:#0015 PLocationInCombat-Y -= EnemyLocation-Y
◆If:PLocationInCombat-Y ≤ 3
◆If:PLocationInCombat-X = EnemyLocation-X
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Variables:#0011 EnemyLocation-Y -= PLocationInCombat-Y
◆If:EnemyLocation-Y ≤ 3
◆If:PLocationInCombat-X = EnemyLocation-X
◆Control Switches:#0023 Player in Enemy range = ON

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:Else
◆Control Switches:#0023 Player in Enemy range = OFF

:End

:End
 

Latest Threads

Latest Posts

Latest Profile Posts

I don’t believe in astrology. I’m a Sagittarius and we’re skeptical.
senary_concept_art.png
The concept art for the sprite of Senary, a major character in my upcoming (as-of-yet-unnamed) project. She is known as the Timelord because she can "stop time" by making eye contact with a person; Paralyzing them for a short period of time through a type of hypnosis. Tell me what you think about her. I'm thinking of changing the color of her coat.

Forum statistics

Threads
124,368
Messages
1,163,107
Members
163,165
Latest member
kpopenewscom
Top