Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Core/Spells): Adding CCDelay #1969

Closed
wants to merge 8 commits into from
Closed

Conversation

Shard-MW
Copy link
Member

Implementing CCDelay

ISSUES ADDRESSED:

Closes #1968

TESTS PERFORMED:

Tests performed are explained in the issue

Target branch(es):

Master

if (_spell->Id == 49376)
return delayForInstantSpells;
// Maim
if (_spell->Id == 22570 || 49802)
Copy link
Contributor

Choose a reason for hiding this comment

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

if (_spell->Id == 22570 || _spell->Id == 49802)

Copy link
Member

Choose a reason for hiding this comment

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

Yes, yes

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks @lineagedr fixed !
And it passed Travis build... Strange

if (_spell->Id == 9005 || _spell->Id == 9823 || _spell->Id == 9827 || _spell->Id == 27006 || _spell->Id == 49803)
return delayForOpenerStuns;
// Entangling roots
if (_spell->Id == 339 || _spell->Id == 1062 || _spell->Id == 5195 || _spell->Id == 5196 || _spell->Id == 9852 || _spell->Id == 9853 || _spell->Id == 26989 || _spell->Id == 53308)
Copy link
Contributor

Choose a reason for hiding this comment

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

Entire code could be improved there's no need to check for all of these spells where you could do:

if (_spell->Mechanic == MECHANIC_ROOT)

And for stuns

if (_spell->Mechanic == MECHANIC_STUN) And so on and so fourth. Take a look at: https://github.com/azerothcore/azerothcore-wotlk/blob/master/src/server/game/Miscellaneous/SharedDefines.h#L1203

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true but some spells like Dragon's Breath, Frost Nova, Mage - Pet - Freeze, Felguard's Intercept and more doesn't have any mechanic assigned, so I prefered to keep the basic functioning by doing case by case.
Plus, there is some spells like hunter traps, or priest's Mind Control that don't require a delay.
I know if there is a delay on Mind Control and the targeted player use Repentance at the same time, priest will get 1min cc instead of 10sec.

Copy link
Contributor

@lineagedr lineagedr Jun 14, 2019

Choose a reason for hiding this comment

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

For spells such as Dragon's Breath you can use
if (_spell->SpellIconID == 1548)
Frost nova:
MECHANIC_ROOT
Water Elemental Freeze:
if (_spell->Id == 33395)

It's fine to use Ids for spells that have no mechanic or special cases such as the hunter traps where they share MECHANIC_STUN, but using this:

// Entangling roots
if (_spell->Id == 339 || _spell->Id == 1062 || _spell->Id == 5195 || _spell->Id == 5196 || _spell->Id == 9852 || _spell->Id == 9853 || _spell->Id == 26989 || _spell->Id == 53308)

Instead of this:

// Entangling roots 
if (_spell->Mechanic == MECHANIC_ROOT)

Is madness.

Copy link
Member Author

Choose a reason for hiding this comment

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

@lineagedr Should be better now

@BarbzYHOOL
Copy link
Member

Can you run the bash script here https://github.com/azerothcore/azerothcore-wotlk/tree/master/apps/git_tools ? it's to help with writing commits

And thank you for the PR (you said you would open it and you did, a man of his word!)

@BarbzYHOOL
Copy link
Member

@lineagedr another review ? please :P

@lineagedr
Copy link
Contributor

lineagedr commented Jun 15, 2019

@BarbzYHOOL

The code is the same. Maybe worse than before because now it's unorganized. It's still using dozens of spell ids instead of their mechanic.

@Shard-MW
Copy link
Member Author

@BarbzYHOOL
The code is the same. Maybe worse than before because now it's unorganized. It's still using dozens of spell ids instead of their mechanic.

@lineagedr
I agreed with your previous comments, but this one is absurd.
It seems you don't know how switch statement and spells works.

As I said, _spell->Mechanic is the 4th column of Spell.dbc (https://wowdev.wiki/DB/Spell) and in a lot of cases it's not filled up with a mechanic even if the spell applies one.
So, the best way to check if the spell has a cc mechanic is to use HasAura like I'm doing in the default case.

// src/server/game/Spells/SpellInfo.cpp     L. 867
bool SpellInfo::HasAura(AuraType aura) const
{
    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
        if (Effects[i].IsAura(aura))
            return true;
    return false;
}

Switch's have the same access time on all elements, so it's better to use it rather than a loop + if / else chaining like HasAura does.
We can also remove the default case if we don't want the CCDelay applied on creature's spells as it's mainly configured for the class spells (for PvP).

Moreover, saying "this code is worse" without giving details or solution is completely useless. So please, next time you want to correct someone, make yourself more useful and show him how to do :)

@robens
Copy link
Contributor

robens commented Jun 17, 2019

Checking by ids is really the way to go here in most cases.

Is this affecting spells casted by creatures? Can this break boss encounters?

@Shard-MW
Copy link
Member Author

Just a small question, is this affecting spells casted by creatures? Can this break boss encounters?

@GitVerge
It does affect spell casted by creatures only if they applies a cc aura like stuns, fear etc. And nope, it'll not break boss encounter, it's just going to add an extra time between when the effect is cast and when it reaches its target.
If you don't want to apply the delay on creature's spells, you can comment/remove the default case

@robens
Copy link
Contributor

robens commented Jun 17, 2019

@GitVerge
It does affect spell casted by creatures only if they applies a cc aura like stuns, fear etc. And nope, it'll not break boss encounter, it's just going to add an extra time between when the effect is cast and when it reaches its target.
If you don't want to apply the delay on creature's spells, you can comment/remove the default case

Yup I'll do that, thanks.

@lineagedr
Copy link
Contributor

@Shard-MW I've already showed you how to do it. And I've said that for the spells that have no mechanic you can use their Ids:

Look at your code:
And you're telling me that this:

case 339: // Druid - Entangling roots
case 1062:
case 5195:
case 5196:
case 9852:
case 9853:
case 26989:
case 53308:

Is better than this lol:

if (_spell->Mechanic == MECHANIC_ROOT)

I've rewritten your code: https://pastebin.com/9p5MkDZt

You can see the difference.

@Shard-MW
Copy link
Member Author

@lineagedr
Since a switch statement doesn't check for each value, it's better than having a lot of if.

And nope, I'm saying that, this :

case 339: // Druid - Entangling roots
case 1062:
case 5195:
case 5196:
case 9852:
case 9853:
case 26989:
case 53308:

is better than this :

case SPELLFAMILY_DRUID:
        if (_spell->Mechanic == MECHANIC_BANISH)        // Cyclone
            return delayForBanishes;
        if (_spell->Mechanic == MECHANIC_ROOT)          // Entangling Root
            return delayForRoots;
        if (_spell->Mechanic == MECHANIC_STUN)          // Bash, Maim, Feral charge - Bear
            return delayForStuns;
        if (_spell->Mechanic == MECHANIC_SLEEP)         // Hibernate
            return delayForDisorients;
        if (_spell->SpellIconID == 495)                 // Pounce
            return delayForStuns;
        break;

because you'll have to check the familyName + check 5 if for Pounce for example.
Read pls https://www.geeksforgeeks.org/switch-vs-else/

And if you truly want to use CCDelay based on mechanics only,

for (uint8 i = 0; i < CCDArraySize; ++i)
     if (_spell->HasAura(auraWithCCD[i]))
          return auraCCDelay[i];

is enough to produce the same result as your entire (re)code.

@lineagedr
Copy link
Contributor

lineagedr commented Jun 17, 2019

@lineagedr
Since a switch statement doesn't check for each value, it's better than having a lot of if.

And nope, I'm saying that, this :

case 339: // Druid - Entangling roots
case 1062:
case 5195:
case 5196:
case 9852:
case 9853:
case 26989:
case 53308:

is better than this :

case SPELLFAMILY_DRUID:
        if (_spell->Mechanic == MECHANIC_BANISH)        // Cyclone
            return delayForBanishes;
        if (_spell->Mechanic == MECHANIC_ROOT)          // Entangling Root
            return delayForRoots;
        if (_spell->Mechanic == MECHANIC_STUN)          // Bash, Maim, Feral charge - Bear
            return delayForStuns;
        if (_spell->Mechanic == MECHANIC_SLEEP)         // Hibernate
            return delayForDisorients;
        if (_spell->SpellIconID == 495)                 // Pounce
            return delayForStuns;
        break;

because you'll have to check the familyName + check 5 if for Pounce for example.
Read pls https://www.geeksforgeeks.org/switch-vs-else/

And if you truly want to use CCDelay based on mechanics only,

for (uint8 i = 0; i < CCDArraySize; ++i)
     if (_spell->HasAura(auraWithCCD[i]))
          return auraCCDelay[i];

is enough to produce the same result as your entire (re)code.

No, this:

for (uint8 i = 0; i < CCDArraySize; ++i)
     if (_spell->HasAura(auraWithCCD[i]))
          return auraCCDelay[i];

Is for ALL spells with certain mods: Including creature spells.
Where the recode is for player spells and then for other spells

@Shard-MW
Copy link
Member Author

@lineagedr
Other spells are including creature spells, and you're doing it here...

// Other
for (uint8 i = 0; i < (sizeof(auraWithCCD) / sizeof(*auraWithCCD)); ++i)
     if (_spell->HasAura(auraWithCCD[i]))
          return delayForInstantSpells;   

And what's the point of using switch + conditions if you're doing the same treatment on player's and other's spells? T_T

@lineagedr
Copy link
Contributor

@Shard-MW How is it doing the same treatment? Above the loop the player spells have custom delay. If every player spell was returning the delayForInstantSpells then it would be the same treatment.

Anyway here's a version with switches: https://pastebin.com/TYGLj9eu:

@talamortis
Copy link
Contributor

I do understand the way that @Shard-MW has done this, as some spell don't contain mechanics, but i have implented my own version of this into Oregoncore

talamortis/OregonCore@0b074fc

This way i have done it, reads the mechanics of the spell by using a loop for each spell to check the max effects and then returns the value.

I will go through this code when i have more time for a better review (most likely Friday) and can leave some feedback

@Viste
Copy link
Contributor

Viste commented Jun 19, 2019

make a case for each spell - good choice(no). for now best option at @talamortis oregon
btw you can also use spell ATTRS for this ;)
@lineagedr https://github.com/Expecto/Patchs/blob/master/Wotlk(TrinityCore)/CCDelay.diff this is old fucking hack and that hack break some spells, @Shard-MW do the shit more dirty but more right

@lineagedr
Copy link
Contributor

@Viste If I may ask, which spells does it break?

@talamortis
Copy link
Contributor

make a case for each spell - good choice(no). for now best option at @talamortis oregon
btw you can also use spell ATTRS for this ;)
@lineagedr https://github.com/Expecto/Patchs/blob/master/Wotlk(TrinityCore)/CCDelay.diff this is old fucking hack and that hack break some spells, @Shard-MW do the shit more dirty but more right

also are you saying my way is incorrect?

@Viste
Copy link
Contributor

Viste commented Jun 20, 2019

make a case for each spell - good choice(no). for now best option at @talamortis oregon
btw you can also use spell ATTRS for this ;)
@lineagedr https://github.com/Expecto/Patchs/blob/master/Wotlk(TrinityCore)/CCDelay.diff this is old fucking hack and that hack break some spells, @Shard-MW do the shit more dirty but more right

also are you saying my way is incorrect?

no you way is best for now

@Shard-MW
Copy link
Member Author

@Viste
Actually, @talamortis 's code is my default case :

for (uint8 i = 0; i < CCDArraySize; ++i)
if (_spell->HasAura(auraWithCCD[i]))
return auraCCDelay[i];

I'm using the first switch to :

  • Don't break non-wanted spells like Priest's [Mind Control] or Hunter traps...
  • List all player's spells and allow people to easily config their CCDelay
  • Maybe add a config later to apply CCDelay or not, on creature's spells (default case)
  • Because a switch is faster than multiple loops + if/else statements (even if it's micro optimization) since it have the same access time to all his elements

@mik1893
Copy link
Contributor

mik1893 commented Aug 13, 2019

@Yehonal yes correct, it is a queue of actions. The weird thing is that because it impacts spells but not gameobject movement, that will generate some behaviours the classic players are familiar with but might confuse people. E.g. a spell evaluation happening before cast will happen at time X, but actually spell is cast at X + 400 where the player conditions changed - but still the spell will land.
Checks that are done AFTER target hit will instead be correctly based on when the action happens.

In WOTLK anyway, this "diff" time is not 400 MS. after a lot of research on videos by a group of tester in my old project, we came up with 150 to 200 ms as the correct number.

@Shard-MW Shard-MW closed this Oct 2, 2019
@Shard-MW Shard-MW deleted the patch-3 branch October 2, 2019 21:49
@Yehonal
Copy link
Member

Yehonal commented Oct 3, 2019

If you create a module we could directly add it inside the AC project as "officially supported module" and it can be enabled by default (but disabled on demand too) You could adapt this PR eventually. Module would be better instead of directly inject the code in core. We should do same thing also for features like ahbot and such things. So we could start from it.

after i've said it, why you closed it?

i don't understand why it's so difficult to move code in modules for you...we've such amazing possibility to keep the core clean and fixed (with module workarounds) at the same time...meh

@BarbzYHOOL
Copy link
Member

i feel like it's a git accident but not sure yet

@Shard-MW
Copy link
Member Author

Shard-MW commented Oct 3, 2019

@Yehonal Keep calm, it's just an accident. I'll reopen it and all my others PR. I've just deleted some of my branch by mistake...

@Shard-MW Shard-MW restored the patch-3 branch October 3, 2019 18:13
@Shard-MW Shard-MW reopened this Oct 3, 2019
@Yehonal
Copy link
Member

Yehonal commented Feb 4, 2020

Any news about the module? :)

@PkllonG
Copy link
Contributor

PkllonG commented Feb 19, 2020

I used to have about a month and it feels pretty good now what state it is

@Yehonal
Copy link
Member

Yehonal commented Feb 19, 2020 via email

@BarbzYHOOL
Copy link
Member

what mikk said looks to me like it was an official feature as I expected, and not really "custom"

however if it's considered custom, @Shard-MW could make it into a module, but please answer something

@Yehonal
Copy link
Member

Yehonal commented Feb 20, 2020 via email

@BarbzYHOOL

This comment has been minimized.

Copy link
Member

@Yehonal Yehonal left a comment

Choose a reason for hiding this comment

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

This must be moved under a module that can be used as a workaround until the queue will be implemented

@Shard-MW
Copy link
Member Author

Shard-MW commented Feb 24, 2020

I'll do it, I just don't have time yet
But, about :

This must be moved under a module that can be used as a workaround until the queue will be implemented

I don't think it's a good idea to implement the 400ms batch cuz players will feel the game more slower (and that's why it has been deleted in MoP? retail feels more dynamic now)

@Kitzunu
Copy link
Member

Kitzunu commented Jul 17, 2020

Any update?

@Goatform
Copy link
Contributor

Here are some interesting sources:

https://github.com/magey/classic-warrior/wiki/Spell-batching

Evolvee/Spell-Delay-Research#1

Blizzard forum:
Screenshot_10

@Voxstrasza
Copy link
Contributor

Any updates on this?

@Si1ker Si1ker added Merge Conflicts There are merge conflicts that need to be solved PR NOT COMPLETED labels Mar 23, 2021
@Si1ker Si1ker closed this Mar 23, 2021
@Blaiseum
Copy link

I really interested in this fix. As result of this thread, this behavior is indeed correct aligned with the official (even if an emulation).

This behavior really makes difference on PvP experience.

I can volunteer to re-open the PR and work on improvements in order to merge this on mainline. Just I would need help/directives from maintainers

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Merge Conflicts There are merge conflicts that need to be solved
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implementing CC Delay