Hime-Works / Requests

Bug reports and requests that may require longer discussions and is not suitable to leave on the blog
http://himeworks.com/
GNU General Public License v2.0
7 stars 9 forks source link

Region Events (Similar to Reference Events + Trigger Labels) #64

Closed Roguedeus closed 10 years ago

Roguedeus commented 10 years ago

I was just remarking to myself how much easier it would be to just have the ability to assign a default event to be triggered like Event Trigger Labels, when the player is inside a specific region.

What do you think?

Note: http://forums.rpgmakerweb.com/index.php?/topic/17306-region-common-events/

I found a script by 'Shaz' that is a common event trigger, upon region entry, or region face, but the way I would see this working best is much like the way your current Reference Events functions. Also, I wouldn't want events to auto trigger unless they where meant to, by having the player_touch trigger set.

Preferably I think it would work best if paired with the Event Trigger Labels functionality. That way when a player walks up to a body of water, for example, the reactions to using an item via the trigger label, would have a multitude of possible reactions, and those reaction would be dependent on the item used. Possibly even allowing an event to 'change' its reference event dynamically, via script call.

Example: Pouring a potion into a body of water, may PERMANENTLY change that water into a healing spring, that heals every time its drank. Or, upgraded to heal more or add special effects to the drink, etc... Really up to the developers imagination. Personally, I would use it as a way to allow the player to interact with the water, such as fishing, or just filling bottles, etc... But different for every body of water.

In a way this is sorta already done via the random encounter mechanic. Though it triggers troops randomly rather than controlling specific map events.

Roguedeus commented 10 years ago

To be clear. I don't mean that the script would create an event like the Reference Events script does, but would simply activate THAT event its referencing. As if the event where at that location physically. Maybe it could be moved there?

HimeWorks commented 10 years ago

That would make sense.

Region events behave just like reference events, except of course you don't create an event object explicitly. All region events obey page trigger methods. For example, if Event 2 is action triggered, then whenever you press the ok key anywhere on a Region 1 tile, it will activate Event 2.

Region events are not "real" events. They are simply a way to remotely activate another event.

Roguedeus commented 10 years ago

What about when a real event is in a region with a region event? Which is triggered first?

HimeWorks commented 10 years ago

That is up to the event trigger system to decide. They will all be triggered, but I'd probably check region events last.

HimeWorks commented 10 years ago

Another issue to consider is whether they should be triggered if you're standing on it, or if you're standing in front of it. I will assume below character priority means you must stand on it, and same as character priority means you must stand in front of it.

In the case of your healing spring example, you probably want to be able to choose whether players stand in the water or not.

HimeWorks commented 10 years ago

I've finished the script. This is how you create region events

  1. Suppose you have event 2
  2. Add a comment with the note-tag
<region event: 1>
  1. Setup your event as usual
  2. Tile your map with some region 1

Now, whenever you interact with a region 1 tile, it will activate event 2.

Another way to specify the actual region events is to note-tag the map note box. There are two flavors depending on your preferences:

Compact note-tag

<region event: 1 2>
<region event: 2 5>

Extended note-tag

<region events>
 1: 2
 2: 5
</region events>

Up to developers what they prefer. There are advantages and disadvantages to map notes or event notes in terms of development, but they all do exactly the same thing in the end.

Changing region event references is as simple as

set_region_event(region_id, event_id)
remove_region_event(region_id)

So for example, if you changed region 1 to point to event 5, then whenever you activate region event 1, event 5 will run.

Roguedeus commented 10 years ago

Sounds great to me. :)

HimeWorks commented 10 years ago

Real events are going to be a problem.

If you have a real event in front of you, and you're standing on a region event, the default behavior is to check what's under you first before checking what's in front of you.

But again, this script does not care how events are triggered, it just tells you that region events exist and add them to the list of events to be checked as needed.

Roguedeus commented 10 years ago

Would it be feasible to allow for an optional flag that can be turned on/off that makes real events take precedence?

Perhaps temporarily disabling the Region Event mechanic, for the next trigger and then auto-toggles back to normal?

Perhaps even a variable that counts down to ZERO and then re-enables the region mechanic? Like ignore the next X triggers... or something.

Just brain storming.

HimeWorks commented 10 years ago

The checks are done as follows

  1. Check here
  2. Check there, if no events are running from previous step

I could modify the trigger system to do the region event checks separately from the "real" events, assuming no real events are running, but that would require more thought.

HimeWorks commented 10 years ago

http://himeworks.wordpress.com/2013/12/29/region-events/

Roguedeus commented 10 years ago

Like I said. In Awe.

That alone would likely have taken me a number of days JUST to work out how to make happen, let alone do it reliably and without any hiccups. You did it in a few hours.

The community, and MYSELF, are so lucky you are doing what you do.

Roguedeus commented 10 years ago

BTW, initial testing shows that this works PERFECTLY.

I will kick it some more in the next day or so and see if I can't break it somehow. :p

HimeWorks commented 10 years ago

It is important to note that this is simply region-based activation. It doesn't have logic like "region enter" or "region leave". I haven't thought how that would be integrated with the event system.

There is the idea of a special "on region enter" page that will be run when you first enter a region, and an "on region exit" page that will run when you leave the region.

So for example, when you enter the region, you might turn on self-switch A so that the same page doesn't get run again and again, and when you leave the region, the self-switch would be turned off so you can activate the previous page again.

This would give you more control over your region events, and I would consider it to be "essential" functionality.

Roguedeus commented 10 years ago

This script has turned out to be MUCH more handy than I had first anticipated.

Thanks for making it!

Roguedeus commented 10 years ago

Small hiccup. Not sure if its unavoidable or an oversight on our part.

Region events function as expected, until you try to combine a 'player touch' trigger on a 'same as player' priority with a 'below player' map tile... The player is never 'blocked' and thus the 'same as player' priority is never executed.

This same situation, with a below player priority, and a player touch trigger, works fine.

HimeWorks commented 10 years ago

To me it doesn't make sense to have same as player priority region event, so the behavior is undefined. I think I wrote something about this in the header.

Roguedeus commented 10 years ago

It works when the tile is also same as player. Which is why I mentioned it. If I set an unpassable tile, as a region event, and the same as player and player touch it works. But if the tile is also below player or port 1 I think, then the event wont function.

Essentially I am using it as a makeshift boundary that becomes passable if a switch is true. Instead of placing a dozen events, I just paint a region and a region event. But as it works now, I have to make the event below and player touch then back up the player using set route... It looks bad, in my opinion, so I think I'm just going to use regular events.

HimeWorks commented 10 years ago

Well, the problem is this in Game_Player

  def check_event_trigger_here(triggers)
    start_map_event(@x, @y, triggers, false)
  end

Supposedly, the only time you can be standing on top of an event, is if the event's priority is below character. You could solve the problem by saying maybe

  def check_event_trigger_here(triggers)
    start_map_event(@x, @y, triggers, false)
    start_map_event(@x, @y, triggers, true)
  end

Because an event on a tile cannot be both below priority and normal priority. This approach only works assuming the trigger checks are not modified.

I have not thought about whether that is a suitable solution or not though.

We don't need to consider event touch unless your regions also move around (so for example, if you wanted to create a sensor script using regions as the sensor).

Of course, because you can only have one region per tile, overlapping sensors would pretty much break things. However, a custom region-like idea can be used to implement sensors...which gives me an idea.

Roguedeus commented 10 years ago

Regions flagged as region events no longer process default encounters... Dunno if that's intended or not.

HimeWorks commented 10 years ago

Works fine for me. Made my whole map region 1, assigned an action trigger event to region 1, and my slime encounter still occurs.

Doesn't run when you have a player/event touch trigger, but I don't really know what you would expect.

Roguedeus commented 10 years ago

Hmmmm, I was afraid of that. :)

Roguedeus commented 10 years ago

Whatever it is it is fixed by removing this script.

noticed that the Game_Player > encounter_progress_value method never gets called when inside an Event Region. Which made me check it by turning default encounters on for that region.

Taking a closer look.

Roguedeus commented 10 years ago

Found it...

Region Events with Below_Player as priority, break region encounters.

Roguedeus commented 10 years ago

I really wish that close button wasn't right next to the comment button... BAD DESIGN.

HimeWorks commented 10 years ago

You'll have to give me a more detailed setup, in a new project, with bare bones implementation.

I have a single event with no graphic, below character priority, on action trigger. The entire map is region 1, and I set it as region event 1.

I have a slime encounter that occurs on 5 steps. It still encounters on action trigger and parallel process.

Roguedeus commented 10 years ago

Sure thing.

Roguedeus commented 10 years ago

The sand is the encounter region 1. Encounter will work as its set up. But change the Event Region to the Encounter Region (1 instead of 2) and the encounter region stops functioning.

Demo: http://www.roguedeus.com/Stuff/Region%20Events%20Test.zip

HimeWorks commented 10 years ago

That's cause you're using player-touch trigger.

Game_player

def encounter
    return false if $game_map.interpreter.running? # <------
    return false if $game_system.encounter_disabled
    return false if @encounter_count > 0
    make_encounter_count
    troop_id = make_encounter_troop_id
    return false unless $data_troops[troop_id]
    BattleManager.setup(troop_id)
    BattleManager.on_encounter
    return true
  end
Roguedeus commented 10 years ago

Thanks for noticing that. I looked there and didn't catch the connection.

Do you think there is a simple way to track the encounter count while the interpreter is running and then pause the next player-touch trigger till after the encounter? Like an action queue?

Not being able to blanket player-touch events with conditionals will seriously over complicate things for what I have planned... :(

HimeWorks commented 10 years ago

It's easy, but I don't know what the consequences are. For example, you touch a regular event but then an encounter occurs and therefore it takes precedence, and your event runs...after the encounter somehow?

Roguedeus commented 10 years ago

It would only be for Event Region overlap, on below player priority. Nothing else needs to be touched does it?

If you don't have time I'll add it to my ToDo list, to poke at it and see what I can find.

HimeWorks commented 10 years ago

Current solution in mind:

  1. Perform region event checks after encounter processing has been checked
  2. Extend it to allow players to tag an event to have it take precedence over encounter processing
Roguedeus commented 10 years ago

There is another check for game interpreter running? long before encounters are processed...

  #--------------------------------------------------------------------------
  # * Processing When Not Moving
  #     last_moving : Was it moving previously?
  #--------------------------------------------------------------------------
  def update_nonmoving(last_moving)
    return if $game_map.interpreter.running?
    if last_moving
      $game_party.on_player_walk
      return if check_touch_event
    end
    if movable? && Input.trigger?(:C)
      return if get_on_off_vehicle
      return if check_action_event
    end
    update_encounter if last_moving
  end

This is going to be interesting.

HimeWorks commented 10 years ago

That sounds like an indirect way to overwrite a method, if any other scripts rely on last_moving being true.

Roguedeus commented 10 years ago

I shouldn't have deleted that last comment. I didn't expect a response so soon. I was going to poke at it and re-ask...

Towards your answer, it would only be if the bool check is true. Or it never gets preempted. So it will only break other scripts checking last_move if its wanted. And only for that one frame update, in order to track the encounter steps that one time.

Roguedeus commented 10 years ago

I am poking at it...

Roguedeus commented 10 years ago

It works. Checking to see if anything other than the default nonmoving method touches last_moving

The only script in all 200 of my list that touch last_moving is your trigger labels, and its only to pass through the alias. That flag seems specifically designed to prevent encounters from triggering when something else is supposed to be happening when the player initially enters a new tile, such as a player touch event. So temporarily overriding it to process encounters anyway, seems reasonable.

Roguedeus commented 10 years ago

I can imagine that should someone want a player_touch event to fire on a tile that just happens to also coincide with the last step in the encounter step count, it would skip that event... So I'll have to see what I can do to recheck for that coincidence and go ahead and process the event after the encounter.

I hope I am not missing anything.

Roguedeus commented 10 years ago

Preliminary solution...

  alias :update_nonmoving_rdd :update_nonmoving
  def update_nonmoving(last_moving)
    if in_danger?
      puts(">>> in_danger")
      update_encounter if last_moving
      update_nonmoving_rdd(false)
    else
      update_nonmoving_rdd(last_moving)
    end
  end
HimeWorks commented 10 years ago

Honestly I don't know why they couldn't just do an update_lastmoving lol

Yes, it looks like (touch) event processing should always take precedence over encounters (or player input)

Roguedeus commented 10 years ago

I was wrong. The fix will completely ignore ALL touch_events, including the region event itself, no matter what the encounter process... /sigh... gonna have to think about this.

Roguedeus commented 10 years ago

Ok, not so fast... I gotta stop making posts before I am sure of something. Nope I was right... this fixes it. 100%.

  alias :update_nonmoving_rdd :update_nonmoving
  def update_nonmoving(last_moving)
    if in_danger?
      puts(">>> in_danger")
      update_encounter if last_moving
      check_touch_event if last_moving
      update_nonmoving_rdd(false)
    else
      update_nonmoving_rdd(last_moving)
    end
  end

Now region events process, encounters process when a bool is flagged, and normal placed touch events process even when an encounter happens. :)

Roguedeus commented 10 years ago

Damn that close button!!

Roguedeus commented 10 years ago

If its not obvious I am using region events as a way to zone areas for special random encounters.

I am soooo glad I got that to work without to much pain. :)

Roguedeus commented 10 years ago

However, it does seem to break Trigger Labels... I'll need to support it as your method skips checking the label if interpreter is running.

Roguedeus commented 10 years ago

Better yet, its much more complicated... Your label trigger is canceled by several things. A few of which are an active touch event... So anywhere inside a Region Event with the player touch trigger, will cancel trigger labels.

So even without region events, if the player happens to be standing on a player_touch event, even if its not doing anything, the trigger label wont execute.

Would you be willing to add an exception to your script? As other users may find that an issue.

Roguedeus commented 10 years ago

Moved to a new topic... #106