Project 1999

Go Back   Project 1999 > Class Discussions > Tanks

Reply
 
Thread Tools Display Modes
  #1  
Old 01-30-2023, 07:18 AM
Encroaching Death Encroaching Death is offline
Banned


Join Date: Sep 2022
Posts: 3,236
Default

Regen is only crucial on a Necro.

Warriors should never be in a fight without a healer babysitting them.

Monks can bandage and Mend to 100% HP.

Shamans have Torpor.

Regen doesn't really do anything past level 20.
Reply With Quote
  #2  
Old 01-30-2023, 06:43 PM
Sizar Sizar is offline
Fire Giant


Join Date: May 2010
Posts: 601
Default

Quote:
Originally Posted by Encroaching Death [You must be logged in to view images. Log in or Register.]
Regen doesn't really do anything past level 20.
Never used a fungi? They must be a real bad item in your view then
Reply With Quote
  #3  
Old 01-30-2023, 07:11 PM
Encroaching Death Encroaching Death is offline
Banned


Join Date: Sep 2022
Posts: 3,236
Default

Quote:
Originally Posted by Sizar [You must be logged in to view images. Log in or Register.]
Never used a fungi? They must be a real bad item in your view then
Fungi is a useless and over hyped item.

Really only good until level 10.

I always sell mine once my alt hits 10.
Reply With Quote
  #4  
Old 01-30-2023, 10:59 AM
Snaggles Snaggles is offline
Planar Protector


Join Date: Jul 2011
Posts: 3,505
Default

If you are FD splitting with a SK you might see more use from this. Bash is generally the first skill a npc blows on engage (or one of them, they don’t save skills for the opportune moment). One bash on a knight is meh, 3-4 npcs trying to bash is a fairly high chance of having FD interrupted. Throw in a caster and you have multiple factors to worry about with splitting.

See? Pragmatic point made about FSI actually being beneficial (but not necessary) for a tank in the tank section. Where’s my academy award?
Reply With Quote
  #5  
Old 01-30-2023, 11:30 AM
DeathsSilkyMist DeathsSilkyMist is online now
Planar Protector

DeathsSilkyMist's Avatar

Join Date: Jan 2014
Posts: 8,154
Default

Quote:
Originally Posted by Snaggles [You must be logged in to view images. Log in or Register.]
If you are FD splitting with a SK you might see more use from this. Bash is generally the first skill a npc blows on engage (or one of them, they don’t save skills for the opportune moment). One bash on a knight is meh, 3-4 npcs trying to bash is a fairly high chance of having FD interrupted. Throw in a caster and you have multiple factors to worry about with splitting.

See? Pragmatic point made about FSI actually being beneficial (but not necessary) for a tank in the tank section. Where’s my academy award?
Hehe unfortunately you won't be getting that award. OP is really talking about Shamans. He is bringing a conversation from the Priest forums over to here for some strange reason. I guess he didn't think the discussion was getting enough attention since it was off topic from the thread at hand. It became off topic due to him.

To further expand upon how FSI should work, I have included some code from the EQEMU GitHub within the spoiler below. The important code is marked in bold:

 

Code:
		bool can_stun = false;
		int stunbash_chance = 0; // bonus
		if (attacker) {
			if (skill_used == EQ::skills::SkillBash) {
				can_stun = true;
				if (attacker->IsClient())
					stunbash_chance = attacker->spellbonuses.StunBashChance +
					attacker->itembonuses.StunBashChance +
					attacker->aabonuses.StunBashChance;
			}
			else if (skill_used == EQ::skills::SkillKick &&
				(attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == WARRIOR) {
				can_stun = true;
			}

			bool is_immune_to_frontal_stun = false;

			if (IsBot() || IsClient() || IsMerc()) {
				if (
					IsPlayerClass(GetClass()) &&
					RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass())
				) {
					is_immune_to_frontal_stun = true;
				}


				if (
					(
						IsPlayerRace(GetBaseRace()) &&
						RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
					) ||
					GetBaseRace() == RACE_OGGOK_CITIZEN_93
				) {
					is_immune_to_frontal_stun = true;
				}
			} else if (IsNPC()) {
				if (
					RuleB(Combat, NPCsUseFrontalStunImmunityClasses) &&
					IsPlayerClass(GetClass()) &&
					RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass())
				) {
					is_immune_to_frontal_stun = true;
				}

				if (
					RuleB(Combat, NPCsUseFrontalStunImmunityRaces) &&
					(
						(
							IsPlayerRace(GetBaseRace()) &&
							RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
						) ||
						GetBaseRace() == RACE_OGGOK_CITIZEN_93
					)
				) {
					is_immune_to_frontal_stun = true;
				}
			}

			if (
				is_immune_to_frontal_stun &&
				!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())
			) {
				can_stun = false;
			}

			if (GetSpecialAbility(UNSTUNABLE)) {
				can_stun = false;
			}
		}
		if (can_stun) {
			int bashsave_roll = zone->random.Int(0, 100);
			if (bashsave_roll > 98 || bashsave_roll > (55 - stunbash_chance)) {
				// did stun -- roll other resists
				// SE_FrontalStunResist description says any angle now a days
				int stun_resist2 = spellbonuses.FrontalStunResist + itembonuses.FrontalStunResist +
					aabonuses.FrontalStunResist;
				if (zone->random.Int(1, 100) > stun_resist2) {
					// stun resist 2 failed
					// time to check SE_StunResist and mod2 stun resist
					int stun_resist =
						spellbonuses.StunResist + itembonuses.StunResist + aabonuses.StunResist;
					if (zone->random.Int(0, 100) >= stun_resist) {
						// did stun
						// nothing else to check!
						Stun(2000); // straight 2 seconds every time
					}
					else {
						// stun resist passed!
						if (IsClient())
							MessageString(Chat::Stun, SHAKE_OFF_STUN);
					}
				}
				else {
					// stun resist 2 passed!
					if (IsClient())
						MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
				}
			}
			else {
				// main stun failed -- extra interrupt roll
				if (IsCasting() &&
					!EQ::ValueWithin(casting_spell_id, 859, 1023)) // these spells are excluded
																	  // 90% chance >< -- stun immune won't reach this branch though :(
					if (zone->random.Int(0, 9) > 1)
						InterruptSpell();
			}
		}

		if (spell_id != SPELL_UNKNOWN && !iBuffTic) {
			//see if root will break
			if (IsRooted() && !FromDamageShield)  // neotoyko: only spells cancel root
				TryRootFadeByDamage(buffslot, attacker);
		}
		else if (spell_id == SPELL_UNKNOWN)
		{
			//increment chances of interrupting
			if (IsCasting()) { //shouldnt interrupt on regular spell damage
				attacked_count++;
				LogCombat("Melee attack while casting. Attack count [{}]", attacked_count);
			}
		}


As you can see, if you have FSI, the stun and extra interrupt check are bypassed completely. There is no other code in this function that calls the InterruptSpell() function. This means there is no special code to force interrupt a spell after a stun has been resisted via FSI.

Now, people are going to say "P99 has custom code changes that aren't in the EQEMU repository!", and that is true. But P99 is based on this code, and P99 didn't change every single line of code. If you want to claim that spells always get interrupted after FSI prevents a stun, you need to provide evidence to suggest the P99 developers changed this portion of code. Finding a discussion based on FSI where the developers contributed would be a great piece of evidence to suggest they at least looked at this section of code and made a decision about it. I haven't seen that, but I haven't scoured the forums either.

When it comes to Monks/Shadowknights/Warriors, racial Regeneration is a much bigger helper when it comes to soloing. It will significantly reduce your down times. Outside of soloing, it doesn't really do much. Most racials operate this way: you get the best utility from them when soloing, and lose most of their utility outside of that. FSI is specifically very good for Shamans, because it can save you during the pre-slow period of the fight (the first minute or so), where racial Regeneration is just too slow to save you. You will get a total of 80HP in that minute. When fighting mobs that hit for 140+, that isn't even 1 hit saved. Once the mob is slowed, no racial really matters since the fight is under control, barring any extreme exceptions like getting attacked by other mobs or something.
Last edited by DeathsSilkyMist; 01-30-2023 at 11:36 AM..
Reply With Quote
  #6  
Old 01-30-2023, 03:47 PM
ya.dingus ya.dingus is offline
Sarnak

ya.dingus's Avatar

Join Date: May 2022
Posts: 316
Default

Quote:
Originally Posted by DeathsSilkyMist [You must be logged in to view images. Log in or Register.]
Hehe unfortunately you won't be getting that award. OP is really talking about Shamans. He is bringing a conversation from the Priest forums over to here for some strange reason. I guess he didn't think the discussion was getting enough attention since it was off topic from the thread at hand. It became off topic due to him.

To further expand upon how FSI should work, I have included some code from the EQEMU GitHub within the spoiler below. The important code is marked in bold:

 

Code:
		bool can_stun = false;
		int stunbash_chance = 0; // bonus
		if (attacker) {
			if (skill_used == EQ::skills::SkillBash) {
				can_stun = true;
				if (attacker->IsClient())
					stunbash_chance = attacker->spellbonuses.StunBashChance +
					attacker->itembonuses.StunBashChance +
					attacker->aabonuses.StunBashChance;
			}
			else if (skill_used == EQ::skills::SkillKick &&
				(attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == WARRIOR) {
				can_stun = true;
			}

			bool is_immune_to_frontal_stun = false;

			if (IsBot() || IsClient() || IsMerc()) {
				if (
					IsPlayerClass(GetClass()) &&
					RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass())
				) {
					is_immune_to_frontal_stun = true;
				}


				if (
					(
						IsPlayerRace(GetBaseRace()) &&
						RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
					) ||
					GetBaseRace() == RACE_OGGOK_CITIZEN_93
				) {
					is_immune_to_frontal_stun = true;
				}
			} else if (IsNPC()) {
				if (
					RuleB(Combat, NPCsUseFrontalStunImmunityClasses) &&
					IsPlayerClass(GetClass()) &&
					RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass())
				) {
					is_immune_to_frontal_stun = true;
				}

				if (
					RuleB(Combat, NPCsUseFrontalStunImmunityRaces) &&
					(
						(
							IsPlayerRace(GetBaseRace()) &&
							RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
						) ||
						GetBaseRace() == RACE_OGGOK_CITIZEN_93
					)
				) {
					is_immune_to_frontal_stun = true;
				}
			}

			if (
				is_immune_to_frontal_stun &&
				!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())
			) {
				can_stun = false;
			}

			if (GetSpecialAbility(UNSTUNABLE)) {
				can_stun = false;
			}
		}
		if (can_stun) {
			int bashsave_roll = zone->random.Int(0, 100);
			if (bashsave_roll > 98 || bashsave_roll > (55 - stunbash_chance)) {
				// did stun -- roll other resists
				// SE_FrontalStunResist description says any angle now a days
				int stun_resist2 = spellbonuses.FrontalStunResist + itembonuses.FrontalStunResist +
					aabonuses.FrontalStunResist;
				if (zone->random.Int(1, 100) > stun_resist2) {
					// stun resist 2 failed
					// time to check SE_StunResist and mod2 stun resist
					int stun_resist =
						spellbonuses.StunResist + itembonuses.StunResist + aabonuses.StunResist;
					if (zone->random.Int(0, 100) >= stun_resist) {
						// did stun
						// nothing else to check!
						Stun(2000); // straight 2 seconds every time
					}
					else {
						// stun resist passed!
						if (IsClient())
							MessageString(Chat::Stun, SHAKE_OFF_STUN);
					}
				}
				else {
					// stun resist 2 passed!
					if (IsClient())
						MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
				}
			}
			else {
				// main stun failed -- extra interrupt roll
				if (IsCasting() &&
					!EQ::ValueWithin(casting_spell_id, 859, 1023)) // these spells are excluded
																	  // 90% chance >< -- stun immune won't reach this branch though :(
					if (zone->random.Int(0, 9) > 1)
						InterruptSpell();
			}
		}

		if (spell_id != SPELL_UNKNOWN && !iBuffTic) {
			//see if root will break
			if (IsRooted() && !FromDamageShield)  // neotoyko: only spells cancel root
				TryRootFadeByDamage(buffslot, attacker);
		}
		else if (spell_id == SPELL_UNKNOWN)
		{
			//increment chances of interrupting
			if (IsCasting()) { //shouldnt interrupt on regular spell damage
				attacked_count++;
				LogCombat("Melee attack while casting. Attack count [{}]", attacked_count);
			}
		}


As you can see, if you have FSI, the stun and extra interrupt check are bypassed completely. There is no other code in this function that calls the InterruptSpell() function. This means there is no special code to force interrupt a spell after a stun has been resisted via FSI.

Now, people are going to say "P99 has custom code changes that aren't in the EQEMU repository!", and that is true. But P99 is based on this code, and P99 didn't change every single line of code. If you want to claim that spells always get interrupted after FSI prevents a stun, you need to provide evidence to suggest the P99 developers changed this portion of code. Finding a discussion based on FSI where the developers contributed would be a great piece of evidence to suggest they at least looked at this section of code and made a decision about it. I haven't seen that, but I haven't scoured the forums either.

When it comes to Monks/Shadowknights/Warriors, racial Regeneration is a much bigger helper when it comes to soloing. It will significantly reduce your down times. Outside of soloing, it doesn't really do much. Most racials operate this way: you get the best utility from them when soloing, and lose most of their utility outside of that. FSI is specifically very good for Shamans, because it can save you during the pre-slow period of the fight (the first minute or so), where racial Regeneration is just too slow to save you. You will get a total of 80HP in that minute. When fighting mobs that hit for 140+, that isn't even 1 hit saved. Once the mob is slowed, no racial really matters since the fight is under control, barring any extreme exceptions like getting attacked by other mobs or something.
Is that C or C++ it's hideous looking.
__________________
Ever /report a playa?

(nope)

Reply With Quote
  #7  
Old 01-30-2023, 03:53 PM
Jimjam Jimjam is offline
Planar Protector


Join Date: Jul 2013
Posts: 12,724
Default

 
Quote:
Originally Posted by DeathsSilkyMist [You must be logged in to view images. Log in or Register.]
Hehe unfortunately you won't be getting that award. OP is really talking about Shamans. He is bringing a conversation from the Priest forums over to here for some strange reason. I guess he didn't think the discussion was getting enough attention since it was off topic from the thread at hand. It became off topic due to him.

To further expand upon how FSI should work, I have included some code from the EQEMU GitHub within the spoiler below. The important code is marked in bold:

 

Code:
		bool can_stun = false;
		int stunbash_chance = 0; // bonus
		if (attacker) {
			if (skill_used == EQ::skills::SkillBash) {
				can_stun = true;
				if (attacker->IsClient())
					stunbash_chance = attacker->spellbonuses.StunBashChance +
					attacker->itembonuses.StunBashChance +
					attacker->aabonuses.StunBashChance;
			}
			else if (skill_used == EQ::skills::SkillKick &&
				(attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == WARRIOR) {
				can_stun = true;
			}

			bool is_immune_to_frontal_stun = false;

			if (IsBot() || IsClient() || IsMerc()) {
				if (
					IsPlayerClass(GetClass()) &&
					RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass())
				) {
					is_immune_to_frontal_stun = true;
				}


				if (
					(
						IsPlayerRace(GetBaseRace()) &&
						RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
					) ||
					GetBaseRace() == RACE_OGGOK_CITIZEN_93
				) {
					is_immune_to_frontal_stun = true;
				}
			} else if (IsNPC()) {
				if (
					RuleB(Combat, NPCsUseFrontalStunImmunityClasses) &&
					IsPlayerClass(GetClass()) &&
					RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass())
				) {
					is_immune_to_frontal_stun = true;
				}

				if (
					RuleB(Combat, NPCsUseFrontalStunImmunityRaces) &&
					(
						(
							IsPlayerRace(GetBaseRace()) &&
							RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
						) ||
						GetBaseRace() == RACE_OGGOK_CITIZEN_93
					)
				) {
					is_immune_to_frontal_stun = true;
				}
			}

			if (
				is_immune_to_frontal_stun &&
				!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())
			) {
				can_stun = false;
			}

			if (GetSpecialAbility(UNSTUNABLE)) {
				can_stun = false;
			}
		}
		if (can_stun) {
			int bashsave_roll = zone->random.Int(0, 100);
			if (bashsave_roll > 98 || bashsave_roll > (55 - stunbash_chance)) {
				// did stun -- roll other resists
				// SE_FrontalStunResist description says any angle now a days
				int stun_resist2 = spellbonuses.FrontalStunResist + itembonuses.FrontalStunResist +
					aabonuses.FrontalStunResist;
				if (zone->random.Int(1, 100) > stun_resist2) {
					// stun resist 2 failed
					// time to check SE_StunResist and mod2 stun resist
					int stun_resist =
						spellbonuses.StunResist + itembonuses.StunResist + aabonuses.StunResist;
					if (zone->random.Int(0, 100) >= stun_resist) {
						// did stun
						// nothing else to check!
						Stun(2000); // straight 2 seconds every time
					}
					else {
						// stun resist passed!
						if (IsClient())
							MessageString(Chat::Stun, SHAKE_OFF_STUN);
					}
				}
				else {
					// stun resist 2 passed!
					if (IsClient())
						MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
				}
			}
			else {
				// main stun failed -- extra interrupt roll
				if (IsCasting() &&
					!EQ::ValueWithin(casting_spell_id, 859, 1023)) // these spells are excluded
																	  // 90% chance >< -- stun immune won't reach this branch though :(
					if (zone->random.Int(0, 9) > 1)
						InterruptSpell();
			}
		}

		if (spell_id != SPELL_UNKNOWN && !iBuffTic) {
			//see if root will break
			if (IsRooted() && !FromDamageShield)  // neotoyko: only spells cancel root
				TryRootFadeByDamage(buffslot, attacker);
		}
		else if (spell_id == SPELL_UNKNOWN)
		{
			//increment chances of interrupting
			if (IsCasting()) { //shouldnt interrupt on regular spell damage
				attacked_count++;
				LogCombat("Melee attack while casting. Attack count [{}]", attacked_count);
			}
		}


As you can see, if you have FSI, the stun and extra interrupt check are bypassed completely. There is no other code in this function that calls the InterruptSpell() function. This means there is no special code to force interrupt a spell after a stun has been resisted via FSI.

Now, people are going to say "P99 has custom code changes that aren't in the EQEMU repository!", and that is true. But P99 is based on this code, and P99 didn't change every single line of code. If you want to claim that spells always get interrupted after FSI prevents a stun, you need to provide evidence to suggest the P99 developers changed this portion of code. Finding a discussion based on FSI where the developers contributed would be a great piece of evidence to suggest they at least looked at this section of code and made a decision about it. I haven't seen that, but I haven't scoured the forums either.

When it comes to Monks/Shadowknights/Warriors, racial Regeneration is a much bigger helper when it comes to soloing. It will significantly reduce your down times. Outside of soloing, it doesn't really do much. Most racials operate this way: you get the best utility from them when soloing, and lose most of their utility outside of that. FSI is specifically very good for Shamans, because it can save you during the pre-slow period of the fight (the first minute or so), where racial Regeneration is just too slow to save you. You will get a total of 80HP in that minute. When fighting mobs that hit for 140+, that isn't even 1 hit saved. Once the mob is slowed, no racial really matters since the fight is under control, barring any extreme exceptions like getting attacked by other mobs or something.

Even eq emu isn’t classic. Classic eq was janky!

The way bypassing stun checks in classic would work often returned an autointerrupt.

I think the best known one is landing a bash on a giant with a rune would auto interrupt it (because no stun check and no damage done bypassed all the checks so eq went ‘herp derp no checks passed so spell casting is interrupted).

FSI on a sk that would use rune for aggro/damage absorb was actually a draw back!
Reply With Quote
  #8  
Old 01-30-2023, 04:29 PM
DeathsSilkyMist DeathsSilkyMist is online now
Planar Protector

DeathsSilkyMist's Avatar

Join Date: Jan 2014
Posts: 8,154
Default

Quote:
Originally Posted by ya.dingus [You must be logged in to view images. Log in or Register.]
Is that C or C++ it's hideous looking.
It's C++, but I agree I am not a fan of the coding style lol.

Quote:
Originally Posted by Jimjam [You must be logged in to view images. Log in or Register.]
 


Even eq emu isn’t classic. Classic eq was janky!

The way bypassing stun checks in classic would work often returned an autointerrupt.

I think the best known one is landing a bash on a giant with a rune would auto interrupt it (because no stun check and no damage done bypassed all the checks so eq went ‘herp derp no checks passed so spell casting is interrupted).

FSI on a sk that would use rune for aggro/damage absorb was actually a draw back!
Of course EQEMU isn't classic. But that is what we have to work with, and that is the codebase P99 is based off of. I don't think we will ever get the actual server-side codebase for a build of Everquest in the Classic-Velious era. EQEMU is basically rebuilt from the ground up using packet sniffers as far as I am aware.

I am simply pointing out that the EQEMU codebase doesn't have special spell interrupt code for stuns specifically resisted by FSI. Occam's razor is currently on my side, since the assumption should be the code hasn't changed significantly. Until P99 releases the source code we will never know for sure, but if someone wants to assert the code works differently, they will need to provide some evidence as to why they think that. As I said, a thread discussing FSI where a developer responded would show they were at least thinking about changing the code. Or perhaps patch notes discussing FSI.
Reply With Quote
  #9  
Old 01-30-2023, 11:36 AM
Snaggles Snaggles is offline
Planar Protector


Join Date: Jul 2011
Posts: 3,505
Default

I'm shocked you arent taking my side with FSI but also remember you have a troll SK.

We know where this thread is going. I'll bow out.
Reply With Quote
  #10  
Old 01-30-2023, 11:40 AM
DeathsSilkyMist DeathsSilkyMist is online now
Planar Protector

DeathsSilkyMist's Avatar

Join Date: Jan 2014
Posts: 8,154
Default

Quote:
Originally Posted by Snaggles [You must be logged in to view images. Log in or Register.]
I'm shocked you arent taking my side with FSI but also remember you have a troll SK.

We know where this thread is going. I'll bow out.
I didn't really comment on your explanation specifically, but I can certainly do so.

My stance on Shadowknights has been if you MOSTLY group/raid with your SK, go Ogre. The FSI will help you out more in group situations than regen typically, because you will have a healer. Your example with pulling mobs is also correct, and you are more likely to pull like that in a group.

If you mostly solo, go Troll. FSI isn't going to help you too much in this situation, because you will be fear kiting a large portion of the time anyway, which means you aren't getting stunned. The HP Regeneration is going to reduce your downtime more than getting saved with FSI.
Reply With Quote
Reply


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 08:13 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 - 2025, Jelsoft Enterprises Ltd.