Edge case strike order discussion.

All things Desktop Dungeons

Re: Edge case strike order discussion.

Postby dislekcia on Sat Jun 30, 2018 1:21 pm

That might be a thing worth investigating, I'll log it as a potential bug. I'm never sure in situations like this so many years later if there was a specific reason for that or not - would have to check our commit history.
User avatar
dislekcia
 
Posts: 2291
Joined: Fri Mar 25, 2011 5:58 pm
Location: Cape Town, South Africa

Re: Edge case strike order discussion.

Postby choongmyoung on Sat Jun 30, 2018 3:57 pm

Sorry, you're right. A normal burning kill happens before the levelup. I'm not quite sure what I was confused with.
choongmyoung
 
Posts: 215
Joined: Sun Aug 23, 2015 1:53 pm

Re: Edge case strike order discussion.

Postby choongmyoung on Wed Jul 18, 2018 5:07 am

So, srid, could you explain the order of events please?

- monster's attack
- player's attack
- burning pop on the other monster
- knockback
- on-hit effects (curse, lifesteal, corrosion, etc.)
- other things if it's not clear
choongmyoung
 
Posts: 215
Joined: Sun Aug 23, 2015 1:53 pm

Re: Edge case strike order discussion.

Postby srid on Thu Jul 19, 2018 7:02 am

Oh, yes. Thank you for reminding me, I will try to write it today or tomorrow.
We made an expansion and it is awesome. Really, you should check it out, especially if you're looking for some extra challenge.

Download over at ddmod.weebly.com!
User avatar
srid
 
Posts: 139
Joined: Sun Jan 07, 2018 8:46 pm

Re: Edge case strike order discussion.

Postby srid on Thu Jul 19, 2018 5:05 pm

So, the game works with an Event Queue.

An event can be literraly anything that happen in the game and that can trigger other event.
Most events aren't even noticeable for the player.
Example of events are LevelUpEvent, PlayerPoisonedEvent.

Let's say that the current event queue contains 4 events A, B, C, D.

The first event of the queue, A is taken by the game and passed to a set of Handlers.
A Handler is a piece of logic code that will have effects when certain types of events are passed to it.

Depending on the situation of the game, some handlers can be added or removed.
For instance, each god has its own handler that will manage its interaction (piety gain and loss etc.)
Each dungeon has its own handler (sometimes several), and some items have handlers too that are attached
to the game when you equip or use them, etc.
Each handler has a priority level to determine in which order an even is passed to Handlers.


Anyway, so event A is passed to a bunch of handlers, and some of them will manage various effects,
and they can also add new events to the queue. They are two ways to add events.

The most common one is to add events at the beginning of the queue.
Example: if, when handling event A, the events E, F, G are added to the queue (in that order),
then the new state of the queue will be A, E, F, G, B, C, D (and not G, F, E, B, C, D),
and after A has been fully handled the next event to be handled will be E.

In some cases, a handler may add events at the end of the queue.
Example: if, when handling event A, the events E, F, G are added to the end of the queue (in that order),
the new state of the queue will be A, B, C, D, E, F, G and the next event to be handled will be B.


To mix the two possible state, if you start with a queue A, B, C, D and while handling A you add E and F
at the beginning and G at the end, you will get A, E, F, B, C, D, G.

So now, let's detail the interaction between KnockBack, Death and Burning.
Let us consider the case of your double kill:

First, your attack start a PlayerDealMeleeDamageEvent to the queue.

- This event is first passed to an EnemyDamageHandler:
-- The Indomitable takes damage and loses a DP.
-- An EnemyKnockbackEvent(The Indomitable) is added to the queue because the player has knockback
-- It also adds an EnemyAttemptMeleeDamageEvent(The Indomitable) at the end of the queue
- The PlayerDealMeleeDamageEvent is then passed to a BurningHandler:
-- The Burning Stack Pop and adds a PlayerDealSpellDamageEvent(Count BlahBlah) to the queue

The PlayerDealMeleeDamageEvent is now fully handled and discarded, the queue now is
[EnemyKnockbackEvent(The Indomitable), PlayerDealSpellDamageEvent(Count BlahBlah), EnemyAttemptMeleeDamageEvent(The Indomitable)]

So the EnemyKnockbackEvent(The Indomitable) is now passed to the handlers, and
- The event is passed to a KnockbackHandler:
-- The Indomitable takes knockback damage and dies. This adds an EnemyDeathEvent(The Indomitable) to the queue

the EnemyKnockbackEvent(The Indomitable) is now fully handled and discarded, the queue now is:
[EnemyDeathEvent(The Indomitable), PlayerDealSpellDamageEvent(Count BlahBlah), EnemyAttemptMeleeDamageEvent(The Indomitable)]

(I'm going a bit faster now)
The EnemyDeathEvent(The Indomitable) is handled by a ExperienceHandler that adds an ExperienceEvent(The Indomitable) to the queue.
The queue now is:
[ExperienceEvent(The Indomitable), PlayerDealSpellDamageEvent(Count BlahBlah), EnemyAttemptMeleeDamageEvent(The Indomitable)]

The ExperienceEvent(The Indomitable) is handled by the same ExperienceHandler and a LevelUpEvent is added at the end of the queue.
The queue now is:
[PlayerDealSpellDamageEvent(Count BlahBlah), EnemyAttemptMeleeDamageEvent(The Indomitable), LevelUpEvent]

The PlayerDealSpellDamageEvent(Count BlahBlah) is handled and Count BlahBlah dies, a EnemyDeathEvent is added to the queue
The queue now is:
[EnemyDeathEvent(Count BlahBlah), EnemyAttemptMeleeDamageEvent(The Indomitable), LevelUpEvent]

the EnemyDeathEvent(Count BlahBlah) is handled and adds an ExperienceEvent(Count BlahBlah) to the queue)
The queue now is:
[ExperienceEvent(Count BlahBlah), EnemyAttemptMeleeDamageEvent(The Indomitable), LevelUpEvent]

The ExperienceEvent(Count BlahBlah) adds experience (at this point, your technically still level 1 and get the full XP bonus)
but do not add a second LevelUpEvent because the ExperienceHandler remembers that an one is already pending
(this is a specific case, in general you can have several events of the same type pending).
The queue now is:
[EnemyAttemptMeleeDamageEvent(The Indomitable), LevelUpEvent]

The EnemyAttemptMeleeDamageEvent(The Indomitable) is handled and the Indomitable retaliates (even if he is already dead!)
So technically, the pisorf damage happens before the retaliation, but after the retaliation has been queued.
The queue now is:
[LevelUpEvent]

The LevelUpEvent and you finally level up.

Of course, I focused only on the events we are interested in, but many other things happened outside from that
(for instance, the EnemyDeathEvent(Count BlahBlah) triggered a DungeonWinEvent that spawned the exit, the light, etc.)


So to resume, the events are handled in this order (even if they are added to the queue in a different order)

> PlayerDealMeleeDamageEvent
> The Indomitable takes damage and loses his DP
> EnemyKnockbackEvent(The Indomitable)
> EnemyDeathEvent(The Indomitable)
> ExperienceEvent(The Indomitable)
> Burning Stack Pop: PlayerDealSpellDamageEvent(Count BlahBlah)
> EnemyDeathEvent(Count BlahBlah)
> ExperienceEvent(Count BlahBlah)
> EnemyAttemptMeleeDamageEvent (end of queue)
> LevelUpEvent (end of queue)

I hope I made it clear enough.

When I have more time, I'll explain the First Strike + Curse + Burning Stack kill interaction too.
We made an expansion and it is awesome. Really, you should check it out, especially if you're looking for some extra challenge.

Download over at ddmod.weebly.com!
User avatar
srid
 
Posts: 139
Joined: Sun Jan 07, 2018 8:46 pm

Re: Edge case strike order discussion.

Postby choongmyoung on Fri Jul 20, 2018 2:18 am

srid wrote:The EnemyAttemptMeleeDamageEvent(The Indomitable) is handled and the Indomitable retaliates (even if he is already dead!)

Got'cha! That was why it was so confusing. Let me sum up the order of the events as I understood.

If the player attack first:
1. Player's attack
2. Knockback
3. Burn pop
4. Monster's attack, if he survived 1 (even if he is dead by 2)
5. (And I guess Sorcerer's mana shield happens after the monster's attack)

If the monster attack first:
1. Monster's attack
2. (Mana shield goes here? idk)
3. Player's attack, if he survived 1
4. Knockback
5. Burn pop

srid wrote:When I have more time, I'll explain the First Strike + Curse + Burning Stack kill interaction too.

I'm waiting for it.
choongmyoung
 
Posts: 215
Joined: Sun Aug 23, 2015 1:53 pm

Re: Edge case strike order discussion.

Postby AvovA17 on Fri Jul 20, 2018 2:46 am

Thanks srid, that was a very interesting read.
AvovA17
 
Posts: 213
Joined: Tue Dec 26, 2017 5:38 pm

Re: Edge case strike order discussion.

Postby srid on Fri Jul 20, 2018 11:40 am

AvovA17 wrote:Thanks srid, that was a very interesting read.

You're welcome :-)

choongmyoung wrote:If the player attack first:
1. Player's attack
2. Knockback
3. Burn pop
4. Monster's attack, if he survived 1 (even if he is dead by 2)
5. (And I guess Sorcerer's mana shield happens after the monster's attack)

If the monster attack first:
1. Monster's attack
2. (Mana shield goes here? idk)
3. Player's attack, if he survived 1
4. Knockback
5. Burn pop


Yes, you summarized it perfectly.
And indeed, the Mana Shield event is triggered when the enemy deals damage to you.

So, if you add Curse in the mix , you get (considering that you attack a cursing enemy without killing him and kill another enemy via popping a burn stack):

If the player attack first:
1. Player's attack
2. Burn pop kills the another monster
3. Monster's attack
4. Player get cursed
> 1 curse

If the monster attack first:
1. Monster's attack
2. Player gets cursed
3. Player's attack, if he survived 1
4. Burn pop, other enemy dies
5. Curse is removed
> No curse

Where it gets tricky, is when you deal Fireball damage to an enemy with retaliate:Fireball (or if you have the Avatar Codex), because in that case, the EnemyRetaliation is only added to the beginning of the queue (and not the end of the queue like for physical attacks with first strike)

This leads to the following sequence of event:

1. Player fireball a cursing enemy with Retaliate:Fireball and Curse (e.g. Cursed Oasis's true boss)
(Enemy retaliation is queued (at the beginning of the queue, not the end), Burn Stack pops and Burning damage is queued)
2. If enemy survived 1. he retaliates and the player gets cursed
3. Burn pop damage is applied to another enemy, the enemy dies and curse is removed.
> No curse

It's also easy to reproduce against any cursing enemy with a prepped Avatar Codex.
We made an expansion and it is awesome. Really, you should check it out, especially if you're looking for some extra challenge.

Download over at ddmod.weebly.com!
User avatar
srid
 
Posts: 139
Joined: Sun Jan 07, 2018 8:46 pm

Re: Edge case strike order discussion.

Postby choongmyoung on Sun Jul 22, 2018 7:48 am

*Cumulative Curiousity*
For a interesting addition, I'm adding the Gorgon knockback on the Dancing Blade. https://youtu.be/FcO-M3RNYI8?t=1404
I guess the events work like this.

1. Deathgaze
2. Burn pop
3. Blink
4. Monster's Attack
5. Player's Attack
6. Burn pop
7. Knockback (Yes, it is knocked back even if it is far from the player character)
8. Blink
choongmyoung
 
Posts: 215
Joined: Sun Aug 23, 2015 1:53 pm

Re: Edge case strike order discussion.

Postby dislekcia on Tue Jul 24, 2018 1:22 pm

Never make a roguelike, folks.
User avatar
dislekcia
 
Posts: 2291
Joined: Fri Mar 25, 2011 5:58 pm
Location: Cape Town, South Africa

PreviousNext

Return to Desktop Dungeons

Who is online

Users browsing this forum: No registered users and 7 guests

cron