View Single Post
  #1  
Old 11-08-2010, 04:18 AM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 539
Default COMMITTED: Heroics - Extended

The base of heroics have been in for a while but there are a number of effects that were not supported:
EQ Forums

Quote:
- Heroic Intelligence: For intelligence-based casters, increases mana pool, mana regen, and the maximum amount of mana regen a character can have.
- Heroic Wisdom: For wisdom-based casters, increases mana pool, mana regen, and the maximum amount of mana regen a character can have.
- Heroic Strength: Increases endurance pool, endurance regen, and the maximum amount of endurance regen a character can have. Also increases damage done by melee attacks and improves the bonus granted to armor class while using a shield.
- Heroic Stamina: Increases hit point pool, hit point regen, and the maximum amount of hit point regen a character can have. Also increases endurance pool, endurance regen, and the maximum amount of endurance regen a character can have.
- Heroic Agility: Increases endurance pool, endurance regen, and the maximum amount of endurance regen a character can have. Also increases the chance to dodge an attack, grants a bonus to defense skill, and reduces falling damage.
- Heroic Dexterity: Increases endurance pool, endurance regen, and the maximum amount of endurance regen a character can have. Also increases damage done by ranged attacks, improves chance to successfully assassinate or headshot, and improves the chance to riposte, block, and parry incoming attacks.
- Heroic Charisma: Improves reaction rolls with some NPCs and increases the amount of faction you gain or lose when faction is adjusted.
I have added support for all that was missing except for the falling damage part since AFAIK that is handled by the client.

New Rule
Code:
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:ItemEnduranceRegenCap', '15', 'Endurance cap from items');
Code:
Index: EQEmuServer/common/ruletypes.h
===================================================================
--- EQEmuServer/common/ruletypes.h	(revision 1715)
+++ EQEmuServer/common/ruletypes.h	(working copy)
@@ -60,6 +60,7 @@
 RULE_INT ( Character, ItemStunResistCap, 35)
 RULE_INT ( Character, ItemStrikethroughCap, 35)
 RULE_INT ( Character, ItemATKCap, 250)
+RULE_INT ( Character, ItemEnduranceRegenCap, 15)
 RULE_INT ( Character, SkillUpModifier, 100) //skill ups are at 100%
 RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping for now
 RULE_BOOL ( Character, BindAnywhere, false)
Index: EQEmuServer/zone/aggro.cpp
===================================================================
--- EQEmuServer/zone/aggro.cpp	(revision 1715)
+++ EQEmuServer/zone/aggro.cpp	(working copy)
@@ -316,6 +316,9 @@
 	// Are they kos?
 	// Are we stupid or are they green
 	// and they don't have their gm flag on
+	int heroicCHA_mod = mob->itembonuses.HeroicCHA/25; // 800 Heroic CHA cap
+	if(heroicCHA_mod > THREATENLY_ARRGO_CHANCE)
+		heroicCHA_mod = THREATENLY_ARRGO_CHANCE;
 	if
 	(
 	//old InZone check taken care of above by !mob->CastToClient()->Connected()
@@ -334,7 +337,7 @@
 			||
 			(
 				fv == FACTION_THREATENLY
-				&& MakeRandomInt(0,99) < THREATENLY_ARRGO_CHANCE
+				&& MakeRandomInt(0,99) < THREATENLY_ARRGO_CHANCE - heroicCHA_mod
 			)
 		)
 	)
Index: EQEmuServer/zone/attack.cpp
===================================================================
--- EQEmuServer/zone/attack.cpp	(revision 1715)
+++ EQEmuServer/zone/attack.cpp	(working copy)
@@ -435,7 +435,7 @@
 		if (!ghit) {	//if they are not using a garunteed hit discipline
 			bonus = 2.0 + skill/60.0 + (GetDEX()/200);
 			bonus = bonus * (100 + defender->spellbonuses.RiposteChance + defender->itembonuses.RiposteChance) / 100.0f;
-			RollTable[0] = bonus;
+			RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block
 		}
 	}
 	
@@ -542,7 +542,7 @@
 		if (!ghit) {	//if they are not using a garunteed hit discipline
 			bonus = 2.0 + skill/60.0 + (GetAGI()/200);
 			bonus = bonus * (100 + defender->spellbonuses.DodgeChance + defender->itembonuses.DodgeChance) / 100.0f;
-			RollTable[3] = RollTable[2] + bonus;
+			RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25); // Remove the dex as it doesnt count for dodge
 		}
 	}
 	else{
@@ -671,11 +671,11 @@
 		mitigation_rating = 0.0;
 		if(GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER)
 		{
-			mitigation_rating = (GetSkill(DEFENSE) / 4.0) + armor + 1;
+			mitigation_rating = ((GetSkill(DEFENSE) + itembonuses.HeroicAGI/10) / 4.0) + armor + 1;
 		}
 		else
 		{
-			mitigation_rating = (GetSkill(DEFENSE) / 3.0) + (armor * 1.333333) + 1;
+			mitigation_rating = ((GetSkill(DEFENSE) + itembonuses.HeroicAGI/10) / 3.0) + (armor * 1.333333) + 1;
 		}
 		mitigation_rating *= 0.847;
 
@@ -1270,6 +1270,7 @@
 			other->AvoidDamage(this, damage);
 			other->MeleeMitigation(this, damage, min_hit);
 			ApplyMeleeDamageBonus(skillinuse, damage);
+			damage += itembonuses.HeroicSTR / 10; 
 			damage = GetSkillDmgTaken(skillinuse, damage);
 			TryCriticalHit(other, skillinuse, damage);
 			mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage);
Index: EQEmuServer/zone/bonuses.cpp
===================================================================
--- EQEmuServer/zone/bonuses.cpp	(revision 1715)
+++ EQEmuServer/zone/bonuses.cpp	(working copy)
@@ -152,14 +152,22 @@
 			continue;
 		AddItemBonuses(inst, newbon, false, true);
 	}
+	// Caps
+	if(newbon->HPRegen > RuleI(Character, ItemHealthRegenCap) + (itembonuses.HeroicSTA/25))
+		newbon->HPRegen = RuleI(Character, ItemHealthRegenCap) + (itembonuses.HeroicSTA/25);
+
+	if(GetCasterClass() == 'I') {
+		if(newbon->ManaRegen > RuleI(Character, ItemManaRegenCap) + GetAA(aaExpansiveMind) + (itembonuses.HeroicINT / 25))
+			newbon->ManaRegen = RuleI(Character, ItemManaRegenCap) + GetAA(aaExpansiveMind) + (itembonuses.HeroicINT / 25);
+	}
+	else if(GetCasterClass() == 'W') {
+		if(newbon->ManaRegen > RuleI(Character, ItemManaRegenCap) + GetAA(aaExpansiveMind) + (itembonuses.HeroicWIS / 25))
+			newbon->ManaRegen = RuleI(Character, ItemManaRegenCap) + GetAA(aaExpansiveMind) + (itembonuses.HeroicWIS / 25);
+	}
 	
-	//caps
-	if(newbon->ManaRegen > (RuleI(Character, ItemManaRegenCap) + GetAA(aaExpansiveMind)))
-		newbon->ManaRegen = RuleI(Character, ItemManaRegenCap) + GetAA(aaExpansiveMind);
-	if(newbon->HPRegen > RuleI(Character, ItemHealthRegenCap))
-		newbon->HPRegen = RuleI(Character, ItemHealthRegenCap);
-	
-	
+	if(newbon->EnduranceRegen > RuleI(Character, ItemEnduranceRegenCap) + itembonuses.HeroicSTR/25 + itembonuses.HeroicDEX/25 + itembonuses.HeroicAGI/25 + itembonuses.HeroicSTA/25)
+			newbon->EnduranceRegen = RuleI(Character, ItemEnduranceRegenCap) + itembonuses.HeroicSTR/25 + itembonuses.HeroicDEX/25 + itembonuses.HeroicAGI/25 + itembonuses.HeroicSTA/25;
+			
 	SetAttackTimer();
 }
 		
@@ -294,12 +302,15 @@
 	if(newbon->haste < (sint8)item->Haste) {
 		newbon->haste = item->Haste;
 	}
-	if(item->Regen > 0) {
+	if(item->Regen > 0)
 		newbon->HPRegen += item->Regen;
-	}
-	if(item->ManaRegen > 0) {
+
+	if(item->ManaRegen > 0)
 		newbon->ManaRegen += item->ManaRegen;
-	}
+	
+	if(item->EnduranceRegen > 0)
+		newbon->EnduranceRegen += item->EnduranceRegen;
+
 	if(item->Attack > 0) {
 		if((newbon->ATK + item->Attack) > RuleI(Character, ItemATKCap))
 		{
@@ -310,9 +321,6 @@
 			newbon->ATK += item->Attack;
 		}
 	}
-	if(item->EnduranceRegen > 0){
-		newbon->EnduranceRegen += item->EnduranceRegen;
-	}
 	if(item->DamageShield > 0) {
 		if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap))
 			newbon->DamageShield = RuleI(Character, ItemDamageShieldCap);
Index: EQEmuServer/zone/client_mods.cpp
===================================================================
--- EQEmuServer/zone/client_mods.cpp	(revision 1715)
+++ EQEmuServer/zone/client_mods.cpp	(working copy)
@@ -213,10 +213,9 @@
 }
 
 sint32 Client::CalcHPRegen() {
-	sint32 regen = LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen;
+	sint32 regen = LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen + (itembonuses.HeroicSTA / 25);
 	//AAs
 	regen += GetAA(aaInnateRegeneration)
-		//+ GetAA(aaInnateRegeneration2) //not currently in the AA table anymore, so why bother?
 		+ GetAA(aaNaturalHealing)
 		+ GetAA(aaBodyAndMindRejuvenation)
 		+ GetAA(aaConvalescence)
@@ -847,8 +846,7 @@
 sint16 Client::CalcAC() {
 
 	// new formula
-	int avoidance = 0;
-	avoidance = (acmod() + ((GetSkill(DEFENSE)*16)/9));
+	int avoidance = (acmod() + ((GetSkill(DEFENSE) + itembonuses.HeroicAGI/10)*16)/9);
 	if (avoidance < 0)
 		avoidance = 0;
 
@@ -856,12 +854,12 @@
 	if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) {
 		//something is wrong with this, naked casters have the wrong natural AC
 //		mitigation = (spellbonuses.AC/3) + (GetSkill(DEFENSE)/2) + (itembonuses.AC+1);
-		mitigation = GetSkill(DEFENSE)/4 + (itembonuses.AC+1);
+		mitigation = (GetSkill(DEFENSE) + itembonuses.HeroicAGI/10)/4 + (itembonuses.AC+1);
 		//this might be off by 4..
 		mitigation -= 4;
 	} else {
 //		mitigation = (spellbonuses.AC/4) + (GetSkill(DEFENSE)/3) + ((itembonuses.AC*4)/3);
-		mitigation = GetSkill(DEFENSE)/3 + ((itembonuses.AC*4)/3);
+		mitigation = (GetSkill(DEFENSE) + itembonuses.HeroicAGI/10)/3 + ((itembonuses.AC*4)/3);
 		if(m_pp.class_ == MONK)
 			mitigation += GetLevel() * 13/10;	//the 13/10 might be wrong, but it is close...
 	}
@@ -879,6 +877,16 @@
 			displayed += iksarlevel * 12 / 10;
 	}
 	
+	// Shield AC bonus for HeroicSTR
+	if(itembonuses.HeroicSTR) {
+		bool equiped = CastToClient()->m_inv.GetItem(14);
+		if(equiped) {
+			uint8 shield = CastToClient()->m_inv.GetItem(14)->GetItem()->ItemType;
+			if(shield == ItemTypeShield) 
+				displayed += itembonuses.HeroicSTR/2;
+		}
+	}
+	
 	//spell AC bonuses are added directly to natural total
 	displayed += spellbonuses.AC;
 	
@@ -1051,6 +1059,11 @@
 		regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen + (clevel / 5);
 	}
 
+	if(GetCasterClass() == 'I')
+		regen += (itembonuses.HeroicINT / 25);
+	else
+		regen += (itembonuses.HeroicWIS / 25);
+	
 	//AAs
 	regen += GetAA(aaMentalClarity) + GetAA(aaBodyAndMindRejuvenation);
 
@@ -1886,7 +1899,7 @@
 
 sint32 Client::CalcEnduranceRegen() {
 	sint32 regen = sint32(GetLevel() * 4 / 10) + 2;
-	regen += spellbonuses.EnduranceRegen + itembonuses.EnduranceRegen;
+	regen += spellbonuses.EnduranceRegen + itembonuses.EnduranceRegen + itembonuses.HeroicSTR/25 + itembonuses.HeroicSTA/25 + itembonuses.HeroicDEX/25 + itembonuses.HeroicAGI/25;
 	regen = (regen * RuleI(Character, EnduranceRegenMultiplier)) / 100;
 	return regen;
 }
Index: EQEmuServer/zone/faction.cpp
===================================================================
--- EQEmuServer/zone/faction.cpp	(revision 1715)
+++ EQEmuServer/zone/faction.cpp	(working copy)
@@ -540,6 +540,17 @@
 			// Get the characters current value with that faction
 			current_value = GetCharacterFactionLevel(faction_id[i]);
 			
+			if(this->itembonuses.HeroicCHA) {
+				int faction_mod = itembonuses.HeroicCHA / 5;
+				// If our result isn't truncated to 0, then just do that
+				if(npc_value[i] * faction_mod / 100 != 0) 
+					npc_value[i] += npc_value[i] * faction_mod / 100;
+				// If our result is truncated, then double a mob's value every once and a while to equal what they would have got
+				else {
+					if(MakeRandomInt(0, 100) < faction_mod)
+						npc_value[i] *= 2;
+				}
+			}
 			//figure out their modifier
 			mod = fm.base + fm.class_mod + fm.race_mod + fm.deity_mod;
 			if(mod > MAX_FACTION)
Index: EQEmuServer/zone/special_attacks.cpp
===================================================================
--- EQEmuServer/zone/special_attacks.cpp	(revision 1715)
+++ EQEmuServer/zone/special_attacks.cpp	(working copy)
@@ -542,7 +542,7 @@
 		}
 
 		// solar - chance to assassinate
-		float chance = (10.0+(GetDEX()/10)); //18.5% chance at 85 dex 40% chance at 300 dex
+		int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex
 		if(
 			level >= 60 && // player is 60 or higher
 			other->GetLevel() <= 45 && // mob 45 or under
@@ -869,6 +869,8 @@
 				else
 					TotalDmg = MakeRandomInt(1, MaxDmg);
 
+				TotalDmg += itembonuses.HeroicDEX; //think this adds like this since archery hits less often than melee
+				
 				int minDmg = 1;
 				if(GetLevel() > 25){
 					//twice, for ammo and weapon
@@ -1895,8 +1897,8 @@
 			if((GetLevelCon(GetLevel(), defender->GetLevel()) == CON_LIGHTBLUE || GetLevelCon(GetLevel(), defender->GetLevel()) == CON_GREEN) && defender->GetLevel() <= 60 && !defender->IsClient()) {
 				// WildcardX: These chance formula's below are arbitrary. If someone has a better formula that is more
 				// consistent with live, feel free to update these.
-				float AttackerChance = 0.20f + ((float)(GetLevel() - 51) * 0.005f);
-				float DefenderChance = (float)MakeRandomFloat(0.00f, 1.00f);
+				int AttackerChance = 20 + ((GetLevel() - 51) / 2) + (itembonuses.HeroicDEX / 10);
+				int DefenderChance = MakeRandomInt(0, 100);
 				if(AttackerChance > DefenderChance) {
 					mlog(COMBAT__ATTACKS, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
 					// WildcardX: At the time I wrote this, there wasnt a string id for something like HEADSHOT_BLOW
Reply With Quote