Skip to content

Conversation

@andreionoie
Copy link
Collaborator

@andreionoie andreionoie commented Dec 20, 2025

  1. We have a category of game logic consisting of one-off ("one shot") events, or repeating but still with limited runtime. These are not the best fit for the core Update() loop, and we also don't want to inline random lambdas inside game logic. Therefore, a separate event registry system centralizes all this configuration, and follows the same inheritance hierarchy as the game entities.
  2. Timestamps stored directly as class members can grow indefinitely, bloating the classes even more as we add functionality. My solution is an Enum-backed generic timestamp registry that can be reused in many places.
  3. Cloned NearbyEntities to avoid being disconnected when battling many mobs.

Implemented retail gameplay features:

  • brief "knocked out" phase before death animation on entities
  • safe logout with countdown based on activity status
  • cooldown on restart here / restart in town
  • restart in town automatically if dead for 3 minutes
  • items release ownership lock and expire after defined intervals

@andreionoie andreionoie changed the title event registry game: add entity event registry and logout countdowns Dec 20, 2025
@andreionoie andreionoie marked this pull request as draft December 20, 2025 22:29
@andreionoie andreionoie added type/feature New content area/game The game app is affected labels Dec 20, 2025
@andreionoie andreionoie marked this pull request as ready for review December 20, 2025 22:54

internal static class SimpleBehaviourUtils
{
// located here as a workaround for readability - omitting qualifiers in main class
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a using static QuantumCore.Game.World.AI.SimpleBehaviourUtils.CombatEvent; at the top of the file, unless you're referring to a different approach? Ideally I would have nested the enum inside SimpleBehaviour but I couldn't lose the qualification that way.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I was confused by the comment. You did lose the qualification didn't you? You can use these constants without the whole type name?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because they are in a different class, if the enum is nested inside the same class I think you cannot

if (spawnedEntity.Health > 0)
{
spawnedEntity.Die();
spawnedEntity.TryScheduleKnockout();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh I don't like how technical the new naming is. Die is way easier to understand than TryScheduleKnochout it implies knowing way more of the whole system. Think about a plugin dev touching c# for the first time?

Copy link
Collaborator Author

@andreionoie andreionoie Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could rename to a simple Knockout(), but this also returns a bool so more explicitly it would be TryKnockout(). I agree it's not very clear what it does, honestly I don't fully understand why the game even implemented this "feature" in the first place.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference in "Knockout" and "Die" in your opinion?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An intermediate state before dead - i would rather switch to an enum over the current bool Dead

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do that but how is knockout different from dead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well in the client they seem different, as this knockout packet shows a kind of dizzy "seeing stars" particle effect, while the dead packet plays the death animation and lays the model flat on the ground. Also IIRC it was also that when in the knockout state, you either wait out the normal delay for death, or you attack earlier and instantly kill the target, so it works like a sort of "fatal / terminal phase" where it is one shot away from death.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never seen that feature in the game. I thought dying was the only thing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/game The game app is affected type/feature New content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants