Project 1999

Go Back   Project 1999 > Server Issues > Bugs

Reply
 
Thread Tools Display Modes
  #1  
Old 12-04-2021, 07:55 PM
azxten azxten is offline
Fire Giant

azxten's Avatar

Join Date: May 2010
Posts: 754
Default Channeling Fix

Channeling rate on P99 seems to be inaccurately high particularly at lower levels. This was previously discussed in another thread but I'm starting a new one for visibility.

EVIDENCE

Old bug report:

https://www.project1999.com/forums/s...d.php?t=343453

Torven TAKP discussion on changing to the decompiled methodology:

https://www.takproject.net/forums/in...68/#post-72810

Dolalin private message to me repeating statement from TAKP dev:

Quote:
Mackal is the EQEmu developer who decompiled our client. (our client is circa November 2002)
EQ Lead developer discussing when they found out they had broken channeling and reverted back to old mechanic:

https://web.archive.org/web/20061207...sage.id=239994
https://web.archive.org/web/20061011...cending&page=3

Quote:
Now its back to working how it used to, which is based on your skill, but caps at 90%. One thing to note here is that your chance to channel is better if you are casting spells lower level than yourself, which is generally when you'd hit that cap.
Quote:
Correct, for each hit you take, you make the roll. The more you're getting hit, the harder it is to continue casting a spell.
Quote:
The only way that the level of the NPC hitting you gets factored in is that lower con NPCs have a harder time hitting you in the first place. But if you take damage while casting a spell, you have to make a channeling roll to continue casting regardless of what it was that hit you. At that point, it doesn't care where the damage came from. The only "level" that factors into the equation at all is a bonus that gets applied if you are casting spells whose required level to cast them is lower than what you are currently.
Quote:
You're right. I just took another look at it and there is some wiggle room in there. If you move more than a few inches, but less than what it takes to automatically break the spell (which is about 1 foot), you get a channeling check to keep the spell. So to answer the other person's question, if you moved a little, but not enough to automatically lose the spell, and got hit at the same time, that would be two channeling checks you'd have to succeed to keep the spell. That'd be why sticking your back up against a wall helps you get spells off easier.
Arguably these posts by Rashere imply slight differences from the client decompile. The decompile shows 370/391 max roll which is 95% cap instead of the mentioned 90%. He also says the only way level matters is spell scribe to player level difference but the decompile also adds a bonus of your player level in addition to that. Finally he confirms that distance moved is a separate channeling check roll. Currently in EQEmu code and in my modified code a penalty is applied to your channeling chance based on distance moved up to a limit where it is guaranteed to fail. All three of these changes would make channeling even more difficult if added and are contentious based on the decompile code. Rashere had previously stated distanced moved was not a separate check so he does admit he made a few mis statements. This archived thread may be worth reviewing further but I did not see any additional posts by him but I also didn't look much.

EQEMU

This is because the EQEmu code starts with a guaranteed ~30% success rate, scales up too quickly with channeling skill improvements, does a 100 roll, and only does a single channeling check roll for a spell cast which is modified by the number of times you are hit. It is widely known that the EQEmu code is based on nothing.

Classic evidence compiled from archived live EQ developer forum posts and decompiled EQ Mac client code by an EQEmu developer indicates this is incorrect. Forum posts support that a channeling roll is done separately for every time you are hit. The client decompile gives us near exact methodology for channeling during classic era.

This methodology can be summed up in the following code which is based on Dolalin's LUA pseudo code provided by the EQEmu developer who reverse engineered the classic client. I used that exact same methodology but converted to C++ code and replacing the existing spells.cpp logic.

+ spell_level_diff_bonus = GetLevel() - spells[spell_id].classes[GetClass()-1];
+ if(spell_level_diff_bonus < 6) {
+ spell_level_diff_bonus = 0;
+ } else {
+ spell_level_diff_bonus = spell_level_diff_bonus * 3;
+ }
+ channelchance = GetSkill(EQ::skills::SkillChanneling) + GetLevel() + spell_level_diff_bonus;
+ if(channelchance > 370) {
+ channelchance = 370;
+ }

+ if(!spells[spell_id].uninterruptable) {
+ LogSpells("Channel chance: [{}]", channelchance);
+ int channel_checks = attacked_count;
+ for(channel_checks; channel_checks > 0; channel_checks--) {
+ int interruptchance = zone->random.Real(0, 391);
+ LogSpells("Interrupt roll: [{}] Check Number: [{}]", interruptchance, channel_checks);
+ if(interruptchance > channelchance && interruptchance > 39) {
+ LogSpells("Casting of [{}] canceled: interrupted", spell_id);
+ InterruptSpell();
+ return;
+ }
+ }
}

METHODOLOGY

First, we get the difference between the player level and the spell scribe level. For my Enchanter example I am level 20 using a level 12 spell so the value is 9 inclusion of the scribe level.

Second, we check if the difference value is 6 or more. If not, no modifier is applied. If yes, a bonus to channeling chance is created which is 3x the difference and in this example would be 9*3 or 27.

Third, we calculate our channeling chance which is your channeling skill level, plus your player level, plus the spell scribe/player level difference bonus. In this example that is 100 channeling skill, plus level 20, plus a 27 bonus for casting a level 12 spell (Choke) giving us a chance of 147.

Fourth, we check if our channeling chance is greater than 370 and if so set it back to 370 which is the maximum chance you can have as an interrupt is always a possibility.

Fifth, once you cast this spell a count is obtained of the number of times you are attacked. At the end of the cast a separate interrupt chance roll is done for every time you were attacked. The EQEmu code caps this attack count at 15 and I have left this alone, it is unknown if classic had a cap but the decompile doesn't seem to indicate there was one. The roll value is 391 compared to your channeling chance which in this case is 147 for a level 20 Enchanter casting Choke.

This means if you are hit once the interrupt roll of 391 must be less than your channeling chance of 147. If it is higher you are interrupted. A level 20 Enchanter has a 38% chance to cast Choke through 1 attack. A level 20 Enchanter has a 31% chance to cast a level 20 spell through 1 attack. A level 50 Enchanter has a 78% chance to cast through 1 attack.

This gives the new function:

X = times hit during cast, capped at 15
Y = player level
Z = scribe level to player level difference if >=6

channel_chance(x, y, z)

((Y * 5 + 5 + Y + Z * 3) / 391)^X = A


Or for our level 20 Enchanter casting a level 12 spell and being hit 1-4 times and 15 or more times...

channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 9 * 3) / 391)^1 = 39% success rate
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 9 * 3) / 391)^2 = 15%
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 9 * 3) / 391)^3 = 6%
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 9 * 3) / 391)^4 = 2%
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 9 * 3) / 391)^15 = .0000007%

Level 20 Enchanter casting a level 20 spell and being hit 1-4 times and 15 or more times...

channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 0 * 3) / 391)^1 = 32% success rate
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 0 * 3) / 391)^2 = 10%
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 0 * 3) / 391)^3 = 3%
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 0 * 3) / 391)^4 = 1%
channel_chance(1, 20, 9) = ((20 * 5 + 5 + 20 + 0 * 3) / 391)^15 = .00000004%

A level 50 Enchanter casting a level 49 spell and being hit 1-4 times and 15 or more times...

channel_chance(1, 20, 9) = ((50 * 5 + 5 + 50 + 0 * 3) / 391)^1 = 78% success rate
channel_chance(1, 20, 9) = ((50 * 5 + 5 + 50 + 0 * 3) / 391)^2 = 60%
channel_chance(1, 20, 9) = ((50 * 5 + 5 + 50 + 0 * 3) / 391)^3 = 47%
channel_chance(1, 20, 9) = ((50 * 5 + 5 + 50 + 0 * 3) / 391)^4 = 37%
channel_chance(1, 20, 9) = ((50 * 5 + 5 + 50 + 0 * 3) / 391)^15 = 2%

This is the existing EQEmu formula and again X is capped at 15 attacks:

((30 + Y / 400 * 100) - X * 2) / 100 = A


Currently on P99 a level 1 character casting a level 1 spell and being hit 1 times with 5 channeling skill has a 29% success rate.
Level 20 casting a level 20 spell and being hit 1 times has a 54% success rate.
Level 20 casting a level 20 spell and being hit 4 times has a 48% success rate.
Level 20 casting a level 20 spell and being hit 15 or more times has a 26% success rate.
Level 50 casting a level 49 spell and being hit 1 times has a 92% success rate.
Level 50 casting a level 49 spell and being hit 4 times has a 86% success rate.
Level 50 casting a level 20 spell and being hit 15 or more times has a 64% success rate.

SUMMARY

This demonstrates how broken channeling is using the EQEmu code compared to classic decompiled channeling and developer forum post supported code changes.

A level 1 Enchanter casting a level 1 spell after being hit 1 time has a 29% success rate on EQEmu code compared to 10% on proposed classic code.
A level 20 Enchanter casting a level 20 spell after being hit 15 or more times has a 26% success rate on EQEmu code compared to .00000004% on proposed classic code.
A level 50 Enchanter casting a level 50 spell after being hit 15 or more times has a 64% success rate on EQEmu code compared to 2% on proposed classic code.

Making channeling classic would represent a fundamental change to P99 gameplay mechanics which will reintroduce difficulty at all levels of the game and likely put an end to a lot of existing "cheesy" strategies. It may also even allow reverting AE group nerf changes as AE killing mobs would be significantly more challenging. This change will reintroduce a lot of the difficulty involved in soloing in particular especially indoors or without SoW/Jboots and in theory should encourage more grouping and social behaviour which I feel is lacking on P99 due to the ease of soloing and primarily related to channeling ability. It may also add to the difficulty of high level play including raiding and especially in situations where players are currently relying on being able to cast while being attacked by multiple high level mobs.

NOTE: Dolalin mentioned he has provided the LUA code from EQEmu dev who decompiled the classic client. I have this as well but won't post it since he probably wanted it kept private for a reason and will leave that up to him to repost if needed. A patch file is attached for my code changes.

NOTE2:
I also change the NPC channeling chance from EQEmu 85 to 391 in my patch because the channeling roll changes from 100 to 391 which means NPC channeling also needs to conform to this higher roll. The NPC channeling chance on P99 already seems to be modified so that would need to be reviewed by devs to ensure this change doesn't interfere. I don't know how NPCs calculate distance moved channeling check or if they are using the EQEmu code, I imagine they're using a different code base.

NOTE3: There is also a "&& interruptchance > 39" in the code which I didn't mention above. This is the lower limit of channeling chance from the classic decompile which effectively sets your channeling chance to 39 and was likely to help lower level players. A level 3 player with the formula above has a 6% chance to channel through 1 hit for example, level 1 is only 3% chance. This bit of code raises the channel success rate to 10% for level 1-5 and then at level 6 the formula scales to higher than 10%.

NOTE4: I have done no validation for Bard songs, NPCs, etc because that code seems to be handled by separate code blocks within the same function. Might be worth checking before making this live.

NOTE5: The reason I left the attack cap at 15 attacks is due to performance concerns. I have not stress tested or validated performance changes due to this code change. A character being hit 1,000 times would previously do 1 random, now they will do 15, without a cap they would do 1,000. This seems like it has some potential to degrade performance but limiting to 15 per character should avoid that while still approaching a near 0% success rate. It may be worth considering adding something like if attack count is > 30 we just guarantee an interrupt of the spell. This would avoid rolls where players are hit >30 times instead of doing the 15 rolls and would guarantee that if players are being hit excessively they will fail rather than giving them that small chance of success which according to the decompile and dev statements doesn't exist.

NOTE6: Although I enjoy trolling Enchanters this change is intended to make P99 more classic and my quest to fix this began when I was just bored with P99. I saw too many people soloing, power leveling up alts due to the ease of leveling, and generally being unsocial jerks in the game. I knew live EQ was much more challenging to solo on any caster class and that this is a big part of why grouping was more popular except for the few classes like Necro, Druid, etc who had ways to avoid channeling checks via pets, run speed buffs, etc.

I'll end with archived Enchanter tears from the archived thread above where an Enchanter was crying that now they won't be able to crowd control as easily since the old channeling code is being restored. This matches the live Enchanter experience where Enchanters died more than any other class and were in short supply for that reason as no one wanted to play it. Enchanter is powerful but also should be much more difficult to play well and their power is primarily level 50+.

Quote:
Enchanters need to be able to cast under fire to be able to perform crowd control duties properly. This was already a problem area for enchanters before this change.
Last edited by azxten; 12-04-2021 at 08:23 PM..
Reply With Quote
  #2  
Old 12-04-2021, 08:00 PM
azxten azxten is offline
Fire Giant

azxten's Avatar

Join Date: May 2010
Posts: 754
Default

Patch file:

https://www.pastefile.com/2969hw

Quote:
--- spells.cpp 2021-12-04 13:17:30.931386378 -0800
+++ /home/eqemu/server_source/zone/spells.cpp 2021-12-04 13:11:13.223277487 -0800
@@ -1130,11 +1122,11 @@
// but cap it so it's not that large a factor
if(attacked_count > 15) attacked_count = 15;

- float channelchance, distance_moved, d_x, d_y, distancemod;
+ float channelchance, channelbonuses, spell_level_diff_bonus, distance_moved, d_x, d_y, distancemod;

if(IsClient())
{
- float channelbonuses = 0.0f;
+ channelbonuses = 0.0f;
//AA that effect Spell channel chance are no longer on live. http://everquest.allakhazam.com/hist...es-2006-2.html
//No harm in maintaining the effects regardless, since we do check for channel chance.
if (IsFromItem)
@@ -1142,9 +1134,17 @@
else
channelbonuses += spellbonuses.ChannelChanceSpells + itembonuses.ChannelChanceSpells + aabonuses.ChannelChanceSpells;

- // max 93% chance at 252 skill
- channelchance = 30 + GetSkill(EQ::skills::SkillChanneling) / 400.0f * 100;
- channelchance -= attacked_count * 2;
+ //
+ spell_level_diff_bonus = GetLevel() - spells[spell_id].classes[GetClass()-1];
+ if(spell_level_diff_bonus < 6) {
+ spell_level_diff_bonus = 0;
+ } else {
+ spell_level_diff_bonus = spell_level_diff_bonus * 3;
+ }
+ channelchance = GetSkill(EQ::skills::SkillChanneling) + GetLevel() + spell_level_diff_bonus;
+ if(channelchance > 370) {
+ channelchance = 370;
+ }
channelchance += channelchance * channelbonuses / 100.0f;
}
#ifdef BOTS
@@ -1164,7 +1164,7 @@
#endif //BOTS
else {
// NPCs are just hard to interrupt, otherwise they get pwned
- channelchance = 85;
+ channelchance = 391;
channelchance -= attacked_count;
}

@@ -1174,13 +1174,13 @@
{
d_x = std::abs(std::abs(GetX()) - std::abs(GetSpellX()));
d_y = std::abs(std::abs(GetY()) - std::abs(GetSpellY()));
- if(d_x < 5 && d_y < 5)
+ if(d_x < 3 && d_y < 3)
{
//avoid the square root...
distance_moved = d_x * d_x + d_y * d_y;
// if you moved 1 unit, that's 25% off your chance to regain.
// if you moved 2, you lose 100% off your chance
- distancemod = distance_moved * 25;
+ distancemod = distance_moved * 100;
channelchance -= distancemod;
}
else
@@ -1189,13 +1189,22 @@
}
}

- LogSpells("Checking Interruption: spell x: [{}] spell y: [{}] cur x: [{}] cur y: [{}] channelchance [{}] channeling skill [{}]\n", GetSpellX(), GetSpellY(), GetX(), GetY(), channelchance, GetSkill(EQ::skills::SkillChanneling));
+ LogSpells("Checking Interruption: spell x: [{}] spell y: [{}] cur x: [{}] cur y: [{}] channelchance [{}] channeling skill [{}] channelbonuses [{}] channel_checks [{}] level diff bonus [{}] \n", GetSpellX(), GetSpellY(), GetX(), GetY(), channelchance, GetSkill(EQ::skills::SkillChanneling), channelbonuses, attacked_count, spell_level_diff_bonus);

- if(!spells[spell_id].uninterruptable && zone->random.Real(0, 100) > channelchance) {
- LogSpells("Casting of [{}] canceled: interrupted", spell_id);
- InterruptSpell();
- return;
+ if(!spells[spell_id].uninterruptable) {
+ LogSpells("Channel chance: [{}]", channelchance);
+ int channel_checks = attacked_count;
+ for(channel_checks; channel_checks > 0; channel_checks--) {
+ int interruptchance = zone->random.Real(0, 391);
+ LogSpells("Interrupt roll: [{}] Check Number: [{}]", interruptchance, channel_checks);
+ if(interruptchance > channelchance && interruptchance > 39) {
+ LogSpells("Casting of [{}] canceled: interrupted", spell_id);
+ InterruptSpell();
+ return;
+ }
+ }
}
+
// if we got here, we regained concentration
regain_conc = true;
MessageString(Chat::Spells, REGAIN_AND_CONTINUE);
Screen shots of testing:

https://imgur.com/a/zncfhij

Successful cast

[You must be logged in to view images. Log in or Register.]

Two rolls failure

[You must be logged in to view images. Log in or Register.]

One roll failure, we don't reroll if you failed the first roll

[You must be logged in to view images. Log in or Register.]
Reply With Quote
  #3  
Old 12-04-2021, 08:52 PM
Lich Lich is offline
Kobold

Lich's Avatar

Join Date: Oct 2009
Posts: 186
Default

Stop spamming.
Reply With Quote
  #4  
Old 12-05-2021, 03:19 AM
Dolalin Dolalin is offline
Planar Protector

Dolalin's Avatar

Join Date: Oct 2009
Location: UK
Posts: 2,545
Default

I confirm I supplied the LUA pseudocode that Torven sent me from TAKP for this change.
Reply With Quote
  #5  
Old 12-07-2021, 04:51 PM
Tunabros Tunabros is offline
Banned


Join Date: May 2018
Location: California, United States
Posts: 3,375
Default

nilbog isnt going to even glance at this bro
Reply With Quote
  #6  
Old 12-07-2021, 09:21 PM
Gustoo Gustoo is offline
Planar Protector

Gustoo's Avatar

Join Date: Mar 2012
Location: The side of Bristlebane
Posts: 6,039
Default

I don't know nilbog but this looks like an exemplary bug report and your shit posting isn't warranted in this guys thread. In my threads I consider it acceptable but only because I'm a bristlebane guy.
__________________
Discord PVP Server:
Quote:
Originally Posted by Rogean View Post
Lost but not forgotten.
Reply With Quote
  #7  
Old 12-07-2021, 10:40 PM
azxten azxten is offline
Fire Giant

azxten's Avatar

Join Date: May 2010
Posts: 754
Default

It's okay I like the haters. Nilbog already said in PM he'll review it but it also likely warrants testing as I noted which may take awhile.
Reply With Quote
  #8  
Old 12-08-2021, 11:52 AM
loramin loramin is offline
Planar Protector

loramin's Avatar

Join Date: Jul 2013
Posts: 9,340
Default

Quote:
Originally Posted by Tunabros [You must be logged in to view images. Log in or Register.]
nilbog isnt going to even glance at this bro
Shitpost elsewhere: this is the bugs forum.
__________________

Loramin Frostseer, Oracle of the Tribunal <Anonymous> and Fan of the "Where To Go For XP/For Treasure?" Guides
Anyone can improve the wiki! If you are new to the Blue server, you can improve the wiki to earn a "welcome package" of up to 2k+ platinum! Message me for details.
Reply With Quote
  #9  
Old 12-08-2021, 03:22 PM
starkind starkind is offline
Banned


Join Date: Apr 2021
Posts: 7,661
Default

Feels good. On classic I corner casted AoE spells with like 8 mobs on me as a wiz, more than that was crazy, I imagine sometimes they missed it was hard and not easy.

Otherwise I would strafe run and turn a bit to try and get a root off if out of doors.
Reply With Quote
  #10  
Old 12-09-2021, 04:04 PM
nilbog nilbog is offline
Project Manager

nilbog's Avatar

Join Date: Oct 2009
Posts: 14,460
Default

I haven't had the time to review this yet, but if it is an improvement on our existing system, it will certainly be considered and credit given where it is due.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 02:21 PM.


Everquest is a registered trademark of Daybreak Game Company LLC.
Project 1999 is not associated or affiliated in any way with Daybreak Game Company LLC.
Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.