From 72249110bff8195dbe54cb94d0ce53f83f015cc2 Mon Sep 17 00:00:00 2001
From: Evan Debenham <Evan.SHPX@gmail.com>
Date: Fri, 16 Nov 2018 01:48:50 -0500
Subject: [PATCH] v0.7.1: various ring adjustments/improvements:

- rings now display statistical information about their effects
- ring of accuracy now boosts hero accuracy, instead of reducing enemy evasion
- ring of energy buffed, now provides a percentage boost to charge speed
- ring of furor rebalanced, no longger better with slower weapons
---
 .../actors/hero/Hero.java                     |  5 ++-
 .../actors/mobs/Mob.java                      |  5 +--
 .../items/rings/Ring.java                     | 18 ++++++----
 .../items/rings/RingOfAccuracy.java           | 21 +++++++++---
 .../items/rings/RingOfElements.java           | 14 ++++++++
 .../items/rings/RingOfEnergy.java             | 21 ++++++++++++
 .../items/rings/RingOfEvasion.java            | 15 ++++++++
 .../items/rings/RingOfForce.java              | 21 ++++++------
 .../items/rings/RingOfFuror.java              | 20 +++++++++--
 .../items/rings/RingOfHaste.java              | 15 ++++++++
 .../items/rings/RingOfMight.java              | 15 ++++++++
 .../items/rings/RingOfSharpshooting.java      | 17 +++++++++-
 .../items/rings/RingOfTenacity.java           | 15 ++++++++
 .../items/rings/RingOfWealth.java             | 14 ++++++++
 .../items/wands/Wand.java                     |  4 +--
 .../items/weapon/Weapon.java                  |  2 +-
 .../messages/items/items.properties           | 34 +++++++++++++++----
 17 files changed, 215 insertions(+), 41 deletions(-)

diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java
index dd84be280..b5a989aac 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java
@@ -80,6 +80,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
 import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
 import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
 import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
+import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfAccuracy;
 import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEvasion;
 import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfForce;
 import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfFuror;
@@ -308,6 +309,8 @@ public class Hero extends Char {
 		KindOfWeapon wep = belongings.weapon;
 		
 		float accuracy = 1;
+		accuracy *= RingOfAccuracy.accuracyMultiplier( this );
+		
 		if (wep instanceof MissileWeapon && rangedAttack
 				&& Dungeon.level.distance( pos, target.pos ) == 1) {
 			accuracy *= 0.5f;
@@ -437,7 +440,7 @@ public class Hero extends Char {
 			//Normally putting furor speed on unarmed attacks would be unnecessary
 			//But there's going to be that one guy who gets a furor+force ring combo
 			//This is for that one guy, you shall get your fists of fury!
-			return RingOfFuror.modifyAttackDelay(1f, this);
+			return RingOfFuror.attackDelayMultiplier(this);
 		}
 	}
 
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java
index ac1c823cd..13e8b6ca1 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java
@@ -48,7 +48,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
 import com.shatteredpixel.shatteredpixeldungeon.items.Item;
 import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass;
 import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
-import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfAccuracy;
 import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth;
 import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfAggression;
 import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
@@ -498,9 +497,7 @@ public abstract class Mob extends Char {
 		if ( seen
 				&& paralysed == 0
 				&& !(alignment == Alignment.ALLY && enemy == Dungeon.hero)) {
-			int defenseSkill = this.defenseSkill;
-			defenseSkill *= RingOfAccuracy.enemyEvasionMultiplier( enemy );
-			return defenseSkill;
+			return this.defenseSkill;
 		} else {
 			return 0;
 		}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/Ring.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/Ring.java
index cc48e0595..6f555384d 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/Ring.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/Ring.java
@@ -155,9 +155,9 @@ public class Ring extends KindofMisc {
 	}
 	
 	@Override
-	public String info() {
+	public String desc() {
 
-		String desc = isKnown()? desc() : Messages.get(this, "unknown_desc");
+		String desc = isKnown() ? super.desc() : Messages.get(this, "unknown_desc");
 
 		if (cursed && isEquipped( Dungeon.hero )) {
 			desc += "\n\n" + Messages.get(Ring.class, "cursed_worn");
@@ -280,6 +280,14 @@ public class Ring extends KindofMisc {
 		}
 		return bonus;
 	}
+	
+	public int soloBonus(){
+		if (cursed){
+			return Math.min( 0, Ring.this.level()-2 );
+		} else {
+			return Ring.this.level()+1;
+		}
+	}
 
 	public class RingBuff extends Buff {
 		
@@ -298,11 +306,7 @@ public class Ring extends KindofMisc {
 		}
 
 		public int level(){
-			if (Ring.this.cursed){
-				return Math.min( 0, Ring.this.level()-2 );
-			} else {
-				return Ring.this.level()+1;
-			}
+			return Ring.this.soloBonus();
 		}
 
 	}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfAccuracy.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfAccuracy.java
index fafba52d4..eda10568e 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfAccuracy.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfAccuracy.java
@@ -22,18 +22,31 @@
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfAccuracy extends Ring {
 	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.3f, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(30f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Accuracy();
 	}
 	
-	//The ring of accuracy reduces enemy evasion
-	// this makes it more powerful against more evasive enemies
-	public static float enemyEvasionMultiplier( Char target ){
-		return (float)Math.pow(0.75, getBonus(target, Accuracy.class));
+	public static float accuracyMultiplier( Char target ){
+		return (float)Math.pow(1.3f, getBonus(target, Accuracy.class));
 	}
 	
 	public class Accuracy extends RingBuff {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfElements.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfElements.java
index bdabe96f8..c0b7574cd 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfElements.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfElements.java
@@ -39,11 +39,25 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Warlock;
 import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DisintegrationTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
 
+import java.text.DecimalFormat;
 import java.util.HashSet;
 
 public class RingOfElements extends Ring {
 	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (1f - Math.pow(0.875f, soloBonus()))));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(12.5f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Resistance();
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java
index 137e24332..69f4fead2 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEnergy.java
@@ -21,13 +21,34 @@
 
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
+import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
+
 public class RingOfEnergy extends Ring {
 	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.2f, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(20f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Energy();
 	}
 	
+	public static float wandChargeMultiplier( Char target ){
+		return (float)Math.pow(1.2, getBonus(target, Energy.class));
+	}
+	
 	public class Energy extends RingBuff {
 	}
 }
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEvasion.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEvasion.java
index 46edb7a19..bda827a34 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEvasion.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfEvasion.java
@@ -22,9 +22,24 @@
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfEvasion extends Ring {
 	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.15f, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(15f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Evasion();
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java
index 1a535d4cb..d4ef9c7b4 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfForce.java
@@ -63,30 +63,31 @@ public class RingOfForce extends Ring {
 
 	//same as equivalent tier weapon
 	private static int min(int lvl, float tier){
-		return Math.round(
+		return Math.max( 0, Math.round(
 				tier +  //base
 				lvl     //level scaling
-		);
+		));
 	}
 
 	//same as equivalent tier weapon
 	private static int max(int lvl, float tier){
-		return Math.round(
+		return Math.max( 0, Math.round(
 				5*(tier+1) +    //base
 				lvl*(tier+1)    //level scaling
-		);
+		));
 	}
 
 	@Override
 	public String desc() {
 		String desc = super.desc();
-		float tier = tier(Dungeon.hero.STR());
-		if (levelKnown) {
-			desc += "\n\n" + Messages.get(this, "avg_dmg", min(level(), tier), max(level(), tier));
-		} else {
-			desc += "\n\n" + Messages.get(this, "typical_avg_dmg", min(1, tier), max(1, tier));
+		if (isKnown()) {
+			float tier = tier(Dungeon.hero.STR());
+			if (isIdentified()) {
+				desc += "\n\n" + Messages.get(this, "stats", min(soloBonus(), tier), max(soloBonus(), tier));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", min(1, tier), max(1, tier));
+			}
 		}
-
 		return desc;
 	}
 
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfFuror.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfFuror.java
index 3fe18df0a..be3a2cb4f 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfFuror.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfFuror.java
@@ -22,17 +22,31 @@
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfFuror extends Ring {
+	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.125f, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(12.5f));
+			}
+		}
+		return desc;
+	}
 
 	@Override
 	protected RingBuff buff( ) {
 		return new Furor();
 	}
 	
-	public static float modifyAttackDelay( float delay, Char target){
-		//furor bonus only affects delay after 0.2
-		return (float)(0.2 + (delay - 0.2)*Math.pow(0.85, getBonus(target, Furor.class)));
+	public static float attackDelayMultiplier(Char target ){
+		return 1f / (float)Math.pow(1.125, getBonus(target, Furor.class));
 	}
 
 	public class Furor extends RingBuff {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfHaste.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfHaste.java
index bae8a3964..f468064ca 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfHaste.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfHaste.java
@@ -22,9 +22,24 @@
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfHaste extends Ring {
 	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.2f, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(20f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Haste();
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfMight.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfMight.java
index 2bcb575d3..c72be91e0 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfMight.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfMight.java
@@ -25,6 +25,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
 import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
 import com.shatteredpixel.shatteredpixeldungeon.items.Item;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfMight extends Ring {
 
@@ -66,6 +69,18 @@ public class RingOfMight extends Ring {
 			((Hero) buff.target).updateHT( false );
 		}
 	}
+	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", soloBonus(), new DecimalFormat("#.##").format(100f * (Math.pow(1.035, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", 1, new DecimalFormat("#.##").format(3.5f));
+			}
+		}
+		return desc;
+	}
 
 	@Override
 	protected RingBuff buff( ) {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfSharpshooting.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfSharpshooting.java
index 8f9e7075b..92da96c79 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfSharpshooting.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfSharpshooting.java
@@ -22,9 +22,24 @@
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfSharpshooting extends Ring {
-
+	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", soloBonus(), new DecimalFormat("#.##").format(100f * (Math.pow(1.2, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", 1, new DecimalFormat("#.##").format(20f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Aim();
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfTenacity.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfTenacity.java
index afeac5a8c..907032bea 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfTenacity.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfTenacity.java
@@ -22,8 +22,23 @@
 package com.shatteredpixel.shatteredpixeldungeon.items.rings;
 
 import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+
+import java.text.DecimalFormat;
 
 public class RingOfTenacity extends Ring {
+	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (1f - Math.pow(0.85f, soloBonus()))));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(15f));
+			}
+		}
+		return desc;
+	}
 
 	@Override
 	protected RingBuff buff( ) {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java
index 7494f6b8f..c549507b7 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/rings/RingOfWealth.java
@@ -27,8 +27,10 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
 import com.shatteredpixel.shatteredpixeldungeon.items.Honeypot;
 import com.shatteredpixel.shatteredpixeldungeon.items.Item;
 import com.shatteredpixel.shatteredpixeldungeon.items.bombs.Bomb;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
 import com.watabou.utils.Random;
 
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.HashSet;
 
@@ -36,6 +38,18 @@ public class RingOfWealth extends Ring {
 	
 	private float triesToDrop = 0;
 	
+	public String info() {
+		String desc = desc();
+		if (isKnown()){
+			if (isIdentified()){
+				desc += "\n\n" + Messages.get(this, "stats", new DecimalFormat("#.##").format(100f * (Math.pow(1.15f, soloBonus()) - 1f)));
+			} else {
+				desc += "\n\n" + Messages.get(this, "typical_stats", new DecimalFormat("#.##").format(15f));
+			}
+		}
+		return desc;
+	}
+	
 	@Override
 	protected RingBuff buff( ) {
 		return new Wealth();
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java
index 991509146..59c84257e 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/Wand.java
@@ -38,7 +38,6 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
 import com.shatteredpixel.shatteredpixeldungeon.items.Item;
 import com.shatteredpixel.shatteredpixeldungeon.items.bags.Bag;
 import com.shatteredpixel.shatteredpixeldungeon.items.bags.MagicalHolster;
-import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
 import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy;
 import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
 import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
@@ -453,7 +452,6 @@ public abstract class Wand extends Item {
 
 		private void recharge(){
 			int missingCharges = maxCharges - curCharges;
-			missingCharges += Ring.getBonus(target, RingOfEnergy.Energy.class);
 			missingCharges = Math.max(0, missingCharges);
 
 			float turnsToCharge = (float) (BASE_CHARGE_DELAY
@@ -461,7 +459,7 @@ public abstract class Wand extends Item {
 
 			LockedFloor lock = target.buff(LockedFloor.class);
 			if (lock == null || lock.regenOn())
-				partialCharge += 1f/turnsToCharge;
+				partialCharge += (1f/turnsToCharge) * RingOfEnergy.wandChargeMultiplier(target);
 
 			for (Recharging bonus : target.buffs(Recharging.class)){
 				if (bonus != null && bonus.remainder() > 0f) {
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/Weapon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/Weapon.java
index b3634e8c7..cc963f0ae 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/Weapon.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/Weapon.java
@@ -171,7 +171,7 @@ abstract public class Weapon extends KindOfWeapon {
 
 		float DLY = augment.delayFactor(this.DLY);
 
-		DLY = RingOfFuror.modifyAttackDelay(DLY, owner);
+		DLY *= RingOfFuror.attackDelayMultiplier(owner);
 
 		return (encumbrance > 0 ? (float)(DLY * Math.pow( 1.2, encumbrance )) : DLY);
 	}
diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties
index 9c58bb7ba..1cf009a16 100644
--- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties
+++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/items/items.properties
@@ -729,38 +729,58 @@ items.rings.ring.curse_known=You can feel a malevolent magic lurking within this
 items.rings.ring.not_cursed=This ring is free of malevolent magic.
 
 items.rings.ringofaccuracy.name=ring of accuracy
-items.rings.ringofaccuracy.desc=This ring increases your focus, reducing your enemy's ability to dodge your attacks. A cursed ring will instead make it easier for enemies to evade your attacks.
+items.rings.ringofaccuracy.stats=When worn, this ring will increase your accuracy by _%s%%._
+items.rings.ringofaccuracy.typical_stats=When worn, this ring will typically increase your accuracy by _%s%%._
+items.rings.ringofaccuracy.desc=This ring increases your focus, making it easier for your attacks to find their mark. A cursed ring will instead make it harder for your attacks to connect.
 
 items.rings.ringofelements.name=ring of elements
+items.rings.ringofelements.stats=When worn, this ring will provide _%s%%_ elemental resistance.
+items.rings.ringofelements.typical_stats=When worn, this ring will typically provide _%s%%_ elemental resistance.
 items.rings.ringofelements.desc=This ring provides resistance to most elemental and magical effects, decreasing damage and debuff duration. Naturally a cursed ring will instead worsen these effects.
 
+items.rings.ringofenergy.name=ring of energy
+items.rings.ringofenergy.stats=When worn, this ring will increase wand charge speed by _%s%%._
+items.rings.ringofenergy.typical_stats=When worn, this ring will typically increase wand charge speed by _%s%%._
+items.rings.ringofenergy.desc=Your wands will recharge more quickly in the arcane field that radiates from this ring. A cursed ring will instead slow wand recharge.
+
 items.rings.ringofevasion.name=ring of evasion
+items.rings.ringofevasion.stats=When worn, this ring will increase your evasion by _%s%%._
+items.rings.ringofevasion.typical_stats=When worn, this ring will typically increase your evasion by _%s%%._
 items.rings.ringofevasion.desc=This ring quickens the wearer's reactions, making it harder to land blows on them. A cursed ring will instead make the user easier to strike.
 
 items.rings.ringofforce.name=ring of force
-items.rings.ringofforce.avg_dmg=When unarmed, at your current strength, this ring will deal _%1$d-%2$d damage._
-items.rings.ringofforce.typical_avg_dmg=When unarmed, at your current strength, typically this ring will deal _%1$d-%2$d damage._
+items.rings.ringofforce.stats=When unarmed, at your current strength, this ring will deal _%1$d-%2$d damage._
+items.rings.ringofforce.typical_stats=When unarmed, at your current strength, typically this ring will deal _%1$d-%2$d damage._
 items.rings.ringofforce.desc=This ring enhances the force of the wearer's blows. This extra power is fairly weak when wielding weapons, but an unarmed attack will be made much stronger. A cursed ring will instead weaken the wearer's blows.
 
 items.rings.ringoffuror.name=ring of furor
-items.rings.ringoffuror.desc=This ring grants the wearer an inner fury, allowing them to attack more rapidly. This fury works best in large bursts, so slow weapons benefit far more than fast ones. A cursed ring will instead slow the wearer's speed of attack.
+items.rings.ringoffuror.stats=When worn, this ring will increase the speed of your attacks by _%s%%._
+items.rings.ringoffuror.typical_stats=When worn, this ring will typically increase the speed of your attacks by _%s%%._
+items.rings.ringoffuror.desc=This ring grants the wearer an inner fury, allowing them to attack more rapidly. A cursed ring will instead slow the wearer's speed of attack.
 
 items.rings.ringofhaste.name=ring of haste
+items.rings.ringofhaste.stats=When worn, this ring will increase your movement speed by _%s%%._
+items.rings.ringofhaste.typical_stats=When worn, this ring will typically increase your movement speed by _%s%%._
 items.rings.ringofhaste.desc=This ring reduces the stress of movement on the wearer, allowing them to run at superhuman speeds. A cursed ring will instead weigh the wearer down.
 
-items.rings.ringofenergy.name=ring of energy
-items.rings.ringofenergy.desc=Your wands will recharge more quickly in the arcane field that radiates from this ring. A cursed ring will instead slow wand recharge.
-
 items.rings.ringofmight.name=ring of might
+items.rings.ringofmight.stats=When worn, this ring will increase your strength by _%1$d_ and your max HP by _%2$s%%._
+items.rings.ringofmight.typical_stats=When worn, this ring will typically increase your strength by _%1$d_ and your max HP by _%2$s%%._
 items.rings.ringofmight.desc=This ring enhances the physical traits of the wearer, granting them greater physical strength and constitution. A cursed ring will weaken the wearer.
 
 items.rings.ringofsharpshooting.name=ring of sharpshooting
+items.rings.ringofsharpshooting.stats=When worn, this ring will increase the effective level of your thrown weapons by _%1$d_ and will increase their durability by _%2$s%%._
+items.rings.ringofsharpshooting.typical_stats=When worn, this ring will typically increase the effective level of your thrown weapons by _%1$d_ and will increase their durability by _%2$s%%._
 items.rings.ringofsharpshooting.desc=This ring enhances the wearer's precision and aim, which will make all projectile weapons more damaging and durable. A cursed ring will have the opposite effect.
 
 items.rings.ringoftenacity.name=ring of tenacity
+items.rings.ringoftenacity.stats=When worn, this ring will reduce the damage you take by up to _%s%%._
+items.rings.ringoftenacity.typical_stats=When worn, this ring will typically reduce the damage you take by up to _%s%%._
 items.rings.ringoftenacity.desc=When worn, this ring will allow the wearer to resist normally mortal strikes. The more injured the user is, the more resistant they will be to damage. A cursed ring will instead make it easier for enemies to execute the wearer.
 
 items.rings.ringofwealth.name=ring of wealth
+items.rings.ringofwealth.stats=When worn, this ring will increase your luck by _%s%%._
+items.rings.ringofwealth.typical_stats=When worn, this ring will typically increase your luck by _%s%%._
 items.rings.ringofwealth.desc=It's not clear what this ring does exactly, good luck may influence the life of an adventurer in many subtle ways. Naturally a cursed ring would give bad luck.