HentHighSchool Development Forum

Game Development => HHS+ => HHS+ Development => Topic started by: TBBle on Feb 18, 2023, 06:08 AM

Title: VEE Introspection in VEE
Post by: TBBle on Feb 18, 2023, 06:08 AM
So, I was prototyping a mod to let you skip waiting periods on events: https://henthighschool.net/hhs-mods/mod-1-10-4-2-proof-of-concept-violet-beauregarde/

The intended operation was roughly that by checking the engine-based stuff (PersonAttached/Location/etc) and then remote-calling an event's Try, you could then determine that the event _would_ run if scheduled, and reschedule it for "now".

As an example of what I came up with, wrapping Location\Your Home\Neighbor3.

Neighbour3.png

There's a couple of things I wanted to note about this, in case there's either easier ways to do it, or things that the engine could expose to VEE to make it easier.

Location check: Since it's wrapping a location-based event, it checks you're in the correct location. This'll be a little messy for things like School Hallway Shared and similar meta-locations, and it'd be nice if this (and the type of event too) was exposed as a property on the Event. Event Property node appears to only offer ChoiceString and CategoryString.

Maybe Get Property By Name can do this, but I haven't tried to work out how. I suspect that would require reimplementing the logic from the scheduler of "Does this event apply to current location"...

Try call: It seems from my testing that Remote-Try on an event that is not scheduled always rejects, so this core idea turned out to be a non-starter. Is that deliberate/necessary? I would have expected most Remote-Try calls to be on unscheduled events, managed only by Remote-Try and Remote-Execute.

On the other hand, I realise now perhaps Remote-Try on a location-based event will also do the Location check? In my case that'd be desirable, and if it could be told "Ignore schedule", then this would make things super-simple.

Schedule check: There's no distinction I can find here between "Event scheduled for next week", or "Event scheduled for >9999". I think a "descheduled" state would be better than the current "+9999" convention, but even being able to fetch the time-until-scheduled for an event would let me check, say, <1000 as being "future", and >1000 being "unscheduled".

Execution: I originally wanted to "Set Remote Schedule 0" and then "Wait 0" to let the event auto-trigger, but I think that's not possible, the player needs to hit a button in the UX to scan for new events? In theory, this direct-execute seems fine, as barring bugs/mistakes we've manually checked all the 'Try' checks except the schedule already.

Event references: Having made a few typos, I'd probably want to use an Object reference to the target event, rather than the string-reference on each RemoteX node, if I could parse this Event down to just the Try/Schedule/Execute calls.



Since I was using Sayako's chain, which is fairly old, it also highlighted a couple of oddities in the events which made this a bit messy:


I'm pretty sure the 1st and 3rd of these are currently-deprecated practices. The middle one is annoying for gameplay purposes too, as unlucky dice-rolls could greatly-delay her quest. (I had 8 fails in a row while testing this, and if you only pass through your home during the relevant time-period once per day, that's a whole extra week!)

I was also under the impression that there's been an event-design preference away from Random-chance quest events, as it can be super-unclear to the player if something's not happening but they have met all the criteria. There's already a randomisation in all schedules after the first.

I don't really plan to push on this mod any more, as it's a bit fiddly to create wrapper events due to the above.

It was mostly an experiment to see if I could abuse RemoteEvent to introspect Events, and that didn't pan out. It was close though, and I'd definitely be interested in knowing if I had missed anything that would have made it even closer to feasible.

I'd love to have a generic event do-nower as then maintaining such a mod would be feasible.



Also, what's the Test Remote Event node do? It seems to have the help text from Call Remote Event, which doesn't make sense as it doesn't have Argument inputs.
Title: Re: VEE Introspection in VEE
Post by: barteke22 on Feb 18, 2023, 12:06 PM
Pretty much everything you want to accomplish (timing, event type etc) can already be done by use of 'Get Property by Name > VisualEvent' yes.
- There'd be a lot to explain, but you can find most of this there, or under some other variable's properties.
- Usually when a type starts with hhs_. (and it sounds like an Enum, like TriggerType) you can find an 'Integer Enum' variable for it.

You could also get and test events dynamically instead of hard-coding them by using their event objects (using the Dynamic Ops).
Deriving the location dynamically would be a few extra steps, but you can probably do it by cross-referencing the VisualEvent's EventPath with a location's EventDirectory.

You can use 'Check Event Execution' to test & execute location events the same way entering a location does.

You can suppress error messages by encasing them in a 'Comment Box' starting with @SuppressWarnings.

Remote Events are no different than regular events (same logic). Events are not directly aware of what triggers them, they're triggered by something rather than trigger for something. Entering/passing time in a Location will Try all events belonging to its EventDirectories that aren't 'Fast Schedule Check'ed + unscheduled.

'Fast Schedule Check' is the reason the event instantly rejects, because it's a newer optimisation that prevents checking logic of unscheduled Try phases. It's preferable over the regular IsScheduled check (for events that don't have IsScheduled(false) logic paths).


---
Sayako's chain there's not really much to comment on, it's one of the most outdated chains, needing a full remake from scratch when someone has time for that within the next century xD

Newer chains do move away from pure RNG to favour more accurate condition checks, though for Sayoko that'd be harder as is, since she doesn't actually exist currently. Newer generic events tend to have 20% chance combined with per location + sex level scheduling, this is a cheap (performance wise) sanity check to avoid content spam / level imbalance.

While the new GlobalVar Bitfields are preferable for chains, there's also situations where a numeric value isn't enough to track something (though not really the case here).

Events that start scheduled are either old, or have logic that kicks in when not scheduled / don't use scheduling at all.

Keep in mind that there's also plenty of older chains that rely only on being scheduled (starting with 9999). Scheduling those prematurely could break such a chain.


Not really sure what the 'Test Remote Event' Op is for, perhaps an old artefact for location specific (argumentless) tests.
Title: Re: VEE Introspection in VEE
Post by: TBBle on Feb 18, 2023, 02:12 PM
Quote from: barteke22 on Feb 18, 2023, 12:06 PMYou can suppress error messages by encasing them in a 'Comment Box' starting with @SuppressWarnings.

I tried that, and it didn't seem to work. Unless I made a mistake:

NotSuppressedError.png

Quick edit: Stretching the comment-box down by about a line of text's height starts supressing the error. So I guess the check for "node is inside box" is using a bounding box for the node that is larger than the actual visible node?

Quote from: barteke22 on Feb 18, 2023, 12:06 PM'Fast Schedule Check' is the reason the event instantly rejects, because it's a newer optimisation that prevents checking logic of unscheduled Try phases. It's preferable over the regular IsScheduled check (for events that don't have IsScheduled(false) logic paths).

Oh, is that what "Fast Schedule Check" is? Yeah, that makes sense, and since these are older events, it makes sense they still have the IsScheduled test at the start of their Try. I hadn't realised that a non-Fast-Schedule event will have its Try line called even if not scheduled.

However, that does suggest that what I'm trying to do here is not generally feasible, as non-Fast-Schedule events may do nearly-arbitrary things in VEE Try path that mean "Try" doesn't answer the question I want to ask, and fast-schedule events would need to be able to override that state when I call their Try to see if they _would_ otherwise run.

Actually, being able to say "Try, but pretend the schedule/location/etc matches" would solve both cases. But that seems an overly-specific engine-level feature just for this wild idea. And maybe isn't sufficient for this use-case anyway. (The other approach that'd occurred to me would be to capture the event's current schedule, schedule it, Try it, and if it fails, reinstate the existing schedule. That's pretty awful, though.)

Quote from: barteke22 on Feb 18, 2023, 12:06 PMKeep in mind that there's also plenty of older chains that rely only on being scheduled (starting with 9999). Scheduling those prematurely could break such a chain.

Yeah, avoiding that was the main reason I noted that I'd like to be able to differentiate 9999-scheduled events from intentionally scheduled events, whether by game-start like Neighbor1, or by Set (Remote) Schedule in Neighbor2 onwards. The intent was to never schedule anything that wasn't already scheduled to run, i.e. its preconditions were already met.

Right now, such an event would require its wrapper to check it's "How was it scheduled" condition (i.e the logic of the caller of Set Remote Schedule), much like all the wrappers needed to check the "What puts this back to 9999?" logic to not resuscitate a completed questline step.

I picked Sayako because it was going to be easy to test, but they're also relatively simple quests in their Try and Set Remote Schedule logic.

Thinking about that, how wide-spread are non-Fast-Schedule events? Maybe there'd be independent value to have either kind of event flag itself as "Completed/Disabled", allowing them to be completely dropped from various lists? The benefits for Fast-Schedule events are likely minimal, but perhaps still visible in something like the Player's Home or Principal's Office, or other high-traffic and high-quest-event-count locations. And any non-Fast-Schedule events would give them Fast-Schedule-like behaviour in this case, of their Try never being called again.

Side-thought, any IsSchedule(false)-handling event could be refactored into an always-scheduled event and a scheduled event, both with Fast Schedule Check enabled. I think that would be nice, but that's mostly because I really hate scrolling around multi-reentry mega-events in VEE trying to make sense of them. coughYoungLoverPAcough. I assume a split version that can use Fast Schedule Check is more efficient too, but only assume so.



Having done this experiment, I learned what I wanted.

The underlying point of the exercise was "Can I build this in a way that won't break anything, and isn't a cheat-mod for anything except time-schedules". What I have now works but requires significant hand-curating for each added event. The side-question was "Can I make this boilerplate, or eliminate it?"


I think if I wanted to make this sort of thing work, what I'd need is a way to determine if something is scheduled less than 700 days into the future; if it is, schedule it for now, and Try/Execute normally. It'll either execute now, and we're good, or it'll fail for non-schedule reasons (stats, etc) and it's still on the player to get the appropriate state set for the event to run.

That bypasses a lot of concerns, because it won't schedule _unscheduled_ events, just accelerate scheduled events. The only risk that jumps out at me is if events are scheduling themselves for specific days by VEE logic for SetRemoteSchedule, rather than relying on Try-checks.

(Also, I have completely ignored the time argument of SetRemoteSchedule. I honestly don't recall seeing it used anywhere, compared to VEE Try checks for time or school-period)

That's not quite the mod I wanted to create, but it'd help with the underlying need of "I don't want to wait four weeks for rumours about Carmen and Oliver to percolate".

Maybe I can extract current schedule from Get Property From Name. That could almost be generic since if I'm going that way, I can perhaps even scape the current location for any "Scheduled but not yet" events. Although an IsScheduled(false)-using event that expects to set some stuff up and then self-schedule would still get broken by this.

Bleh. To be clear, I'm not really planning on advancing this further at this time, I think I extracted all the readily-extracted fun from this exercise already.