Just a reminder:
Events with Autonomous Movements will stop moving when the Player directly interacts with them, and will move again from where they left off afterwards (if bug fix in previous post is implemented).
Events with Autonomous Movements will keep moving during Autorun or Parallel Process events, and if you change their movement via a Set Move Route call, they will go back to their Autonomous route immediately after Set Move Route is over.
To prevent this, leave Autonomous Movement on Fixed. Or if you require them to move autonomously outside the Autorun event, have two event pages - one with the custom Autonomous route, and one with the Fixed route - and ensure the page with the Fixed route is active during Autorun.
Showing posts with label Events. Show all posts
Showing posts with label Events. Show all posts
Saturday, 6 May 2017
Restore Move Route Bug Fix
I found a bug in RPG Maker VX Ace that I am really surprised I haven't come across a fix for already on the internet.
It's something I noticed before, but didn't really look into until now.
If you have an event with a repeating Custom Autonomous Movement, and some logic when you interact with them that makes a Set Move Route call, once the interaction is over one of two things may happen:
It's something I noticed before, but didn't really look into until now.
If you have an event with a repeating Custom Autonomous Movement, and some logic when you interact with them that makes a Set Move Route call, once the interaction is over one of two things may happen:
- they return to their autonomous movement, but not where they left off when they were interrupted (meaning their original route gets totally screwed up), or
- they stop moving completely.
It turns out, which one happens depends on where they were in their move route when you interacted with them. If you interact with them at the end of their Custom Autonomous Move Route cycle, the second one happens. Any other time, the first one happens.
The Way Movement Works
Events move around via an update_routine_move method that is called continuously (until you interact with them). The move route is the list of move commands, and it keeps track of the current movement via an index that is manually incremented.
In other words, the code retrieves the current move command from the route via the index, processes the command, then advances the index. Pretty standard stuff. This method is also called for Set Move Route commands within the event logic, which actually overwrites the original move route.
But once Player interaction ends, the event is supposed to go back to its original move route. So the code stores (or "memorises") the Custom Autonomous Move Route prior to any Set Move Route call. It also stores the index so it can "remember" where it was up to when interrupted.
Then, when Set Move Route is done, it simply restores the original move route and the original index from memory.
The bug is: it doesn't restore this index correctly.
The problem code is in one of two places, depending how you look at it.
Either:
class Game_Character
#--------------------------------------------------------------
# * Restore Move Route
#--------------------------------------------------------------
def restore_move_route
@move_route = @original_move_route
@move_route_index = @original_move_route_index
@original_move_route = nil
end
end
OR
class Game_Character
#--------------------------------------------------------------
# * Process Move Route End
#--------------------------------------------------------------
def process_route_end
if @move_route.repeat
@move_route_index = -1
elsif @move_route_forcing
@move_route_forcing = false
restore_move_route
end
end
end
It all looks correct and innocent enough, but the giveaway is that the index is set back to -1 and not 0 if the move route is set to repeat.
The reason for this is, the code processes the end of the move route as another command in the list. And as we discovered earlier, after a command is processed, it then advances the index. So when it goes back to the start, the index has been advanced back to 0 and we're good to go.
When it restores the move route, however, it doesn't take this into account. Therefore, the index is out by 1 when the original route is restored.
What this means is if the event was in the middle of the move route when interrupted, it skips the command it was up to and goes to the next one, which is why the original route gets messed up. If the event was at the end of its route when interrupted, the index is then increased to be greater than the number of commands in the list, so when the code goes to process the next command, it simply doesn't find one and the event stops moving.
The Fix
For all that, the fix is very simple. The move route index simply needs to be decreased by 1 when restoring it back to the original route. This can be done in either of the two methods above. It makes more sense to me to do it in process_route_end but it's easier with aliasing to do it in restore_move_route.
IMPORTANT: Choose one or the other, not both.
Either:
class Game_Character
#--------------------------------------------------------------
# * Alias method - Restore Move Route
# Only needed if the overwritten method below isn't used
#--------------------------------------------------------------
alias rtp_bug_fix_restore_move_route restore_move_route
def restore_move_route
rtp_bug_fix_restore_move_route
@move_route_index -= 1
end
end
OR
class Game_Character
#----------------------------------------------------------------
# * Overwrite Method - Process Move Route End
# Only needed if the alias method above isn't used
#--------------------------------------------------------------
def process_route_end
if @move_route.repeat
@move_route_index = -1
elsif @move_route_forcing
@move_route_forcing = false
restore_move_route
@move_route_index -= 1
end
end
end
Saturday, 3 September 2016
Player Touch Trigger
The Player Touch trigger behaves differently depending on what Priority you give to your Event, and also depending on whether the Event has Through ON. It's pretty straight forward when the map tile beneath the Event is a passable one, and Through is OFF:
(Where Through is mentioned, it is always referring to the Through setting for the Event unless specifically stated otherwise.)
Events on Passable Map Tiles
Priority = Below Characters
The Player can move on top of the Event, and the Event triggers when the Player does so. The Event's Through setting has no effect on the Player.
Priority = Same As Characters
With Through OFF, the Event will trigger when the Player touches the Event by pressing the arrow keys, but the Player does not and cannot move on to the Event.
With Through ON, the Player can freely pass through the Event, but never actually touches it. Hence, the Event is never triggered. Kind of like an illusion, or a ghost. (The same thing happens if the Player has Through ON.)
HOWEVER, if the logic within the Event sets Through ON (when it's triggered), then the Player can touch the Event, trigger the Event, and pass through the Event. BUT from then on, until Through is set back to OFF, the Event will no longer be touchable or triggerable.
Priority = Above Characters
The Player can move beneath the Event, and the Event triggers when the Player does so. The Event's Through setting has no effect on the Player.
Events on Impassable Map Tiles
Some unexpected behaviour may occur when the map tile the Event is sitting on is impassable.
Priority = Below Characters OR Above Characters
Since the Player cannot move on to the map tile where the Event sits, the Event will never be triggered (even if Through is ON).
Priority = Same As Characters
The Event will trigger when the Player touches the Event by pressing the arrow keys, but of course the Player still does not and cannot move on to the Event.
This is true even if the Event has Through ON or the Event logic turns Through ON when triggered. (Makes sense, since the Player runs into an impassable map tile.)
Check out what this means for Doors and Secret Passages.
Doors
For an explanation of how Player Touch works with different Priority settings, be sure to read this post about the Player Touch Trigger.
With Priority set to Same as Characters, the Door Event itself is actually impassable, which is why the Door Event sets Through ON when it is opened (to make the Event passable).
It gets more complicated when there is an impassable wall tile above the door, which leads us to Secret Passages.
Doors
| Priority and Trigger settings for a Door |
Doors work by placing a passable map tile (usually a black entrance tile) over the top of an impassable wall tile (which makes the map tile passable, as well as for aesthetics), and having your Door Event on top of that.
The reason Priority is set to Same as Characters and not either of the others is purely for aesthetic and animation reasons:
| From left to right: Priority = Above, Same, Below Above is incorrect when beneath the door. Below is incorrect when on the door. |
Priority = Above Characters
If set to Above Characters, the Player will walk underneath the door, the door will open on top of them, and they will remain underneath the door as they walk through it.
Priority = Below Characters
If set to Below Characters, the Player will walk on top of the door, and then the door will open beneath them (if it's a trap door in the floor that they're falling through then this is a good thing).
Priority = Same As Characters
When set to Same as Characters, however, the Player will be in front of the door when coming from the bottom, and then will automatically switch to being behind the door once they're on the same tile. This makes it actually look like they are passing through a doorway, and things like door frames will be correctly drawn above the character.
Another key difference with Same as Characters is that the Player will open the Door before moving onto the Door tile, rather than moving onto it and then opening it either on top of them or beneath them.
Event Logic
This is the logic supplied by RPG Maker's Quick Event Creation -> Door feature:
| The logic supplied by Quick Event Creation > Door |
With Priority set to Same as Characters, the Door Event itself is actually impassable, which is why the Door Event sets Through ON when it is opened (to make the Event passable).
If you read this post about the Player Touch Trigger, you'll recall that an Event set to Same as Characters will not trigger if it has Through ON.
For doors that transfer the Player to a completely different map, this does not matter because the Event resets when the Player returns. Of course, these doors also don't have any closing logic on them, either.
Closing Doors
So if you want doors or gates for aesthetics (eg. inside, or on a castle's exterior wall) that the Player can open, close, and pass through without being transferred to a different map, then you have to make sure to add closing logic and turn Through OFF when the door is closed.
| Closing logic |
It gets more complicated when there is an impassable wall tile above the door, which leads us to Secret Passages.
Player Touch Trigger
The Player Touch trigger behaves differently depending on what Priority you give to your Event, and also depending on whether the Event has Through ON. It's pretty straight forward when the map tile beneath the Event is a passable one, and Through is OFF:
(Where Through is mentioned, it is always referring to the Through setting for the Event.)
Events on Passable Map Tiles
Priority = Below Characters
The Player can move on top of the Event, and the Event triggers when the Player does so. The Event's Through setting has no effect on the Player.
Priority = Same As Characters
With Through OFF, the Event will trigger when the Player touches the Event by pressing the arrow keys, but the Player does not and cannot move on to the Event.
With Through ON, the Player can freely pass through the Event, but never actually touches it. Hence, the Event is never triggered. Kind of like an illusion, or a ghost.
HOWEVER, if the logic within the Event sets Through ON (when it's triggered), then the Player can touch the Event, trigger the Event, and pass through the Event. BUT from then on, until Through is set back to OFF, the Event will no longer be touchable or triggerable.
Priority = Above Characters
The Player can move beneath the Event, and the Event triggers when the Player does so. The Event's Through setting has no effect on the Player.
Events on Impassable Map Tiles
Some unexpected behaviour may occur when the map tile the Event is sitting on is impassable.
Priority = Below Characters OR Above Characters
Since the Player cannot move on to the map tile where the Event sits, the Event will never be triggered (even if Through is ON).
Priority = Same As Characters
The Event will trigger when the Player touches the Event by pressing the arrow keys, but of course the Player still does not and cannot move on to the Event.
This is true even if the Event has Through ON or the Event logic turns Through ON when triggered. (Makes sense, since the Player runs into an impassable map tile.)
Check out what this means for Doors and Secret Passages.
Monday, 11 July 2016
How to make NPCs stay where you put them
Problem: My NPC doesn't stay where I put him!
Every time the Player enters a map, all events return back to where they were originally placed.
This means that any NPCs you manually moved while the Player was on the map are right back where they started.
This is fine for random townsfolk who move about randomly or just repeat the same route, but if you have cut scenes or any interaction that causes an NPC to change locations (and/or change their behaviour) then it can really stuff you up.
Solution 1
If the NPC is supposed to vanish, the easiest way to get them to remain vanished when the Player comes back is to set a Self Switch (or Switch, if controlling them from a different Event) that switches their behaviour to a new Event Page with no graphic. (Self Switches and Switches maintain their state globally.)
(This solution can also be used to change their Autonomous Movement, if you just want their move route to change.)
Solution 2
If you need your NPC to be in a totally new location, however, the only way to do this without scripts is to create an Event with its Trigger set to Parallel Process. Insert Set Event Location commands and set up each NPC with its new coordinates.
Once all commands are set, use an Erase Event command. This will terminate the Parallel Process after it has run once, and since Erase Event commands don't actually delete the Event, it will reset every time the Player returns to the map, and all those Set Event Location commands will happen again.
![]() |
| This only runs when the set condition is true |
Subscribe to:
Posts (Atom)
