From 3098a08d6e8850b9442d89b38ef87f34a32085df Mon Sep 17 00:00:00 2001
From: DBotThePony <dbotthepony@yandex.ru>
Date: Mon, 23 Aug 2021 14:52:12 +0700
Subject: [PATCH] Attack speed overclocking, improve research builder

---
 .../java/ru/dbotthepony/mc/otm/Registry.java  |  3 ++
 .../mc/otm/android/AndroidResearch.java       | 52 +++++++++++++++----
 .../feature/AndroidLimbOverclocking.java      | 21 ++++++--
 .../mc/otm/screen/AndroidStationScreen.java   |  4 +-
 .../overdrive_that_matters/lang/en_us.json    | 10 +---
 5 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/src/main/java/ru/dbotthepony/mc/otm/Registry.java b/src/main/java/ru/dbotthepony/mc/otm/Registry.java
index 628348225..7ead81516 100644
--- a/src/main/java/ru/dbotthepony/mc/otm/Registry.java
+++ b/src/main/java/ru/dbotthepony/mc/otm/Registry.java
@@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm;
 
 import net.minecraft.client.gui.screens.MenuScreens;
 import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.chat.TranslatableComponent;
 import net.minecraft.resources.ResourceLocation;
 import net.minecraft.world.damagesource.DamageSource;
 import net.minecraft.world.food.FoodProperties;
@@ -381,6 +382,8 @@ public class Registry {
 					.setExperienceCost(24 + i * 8)
 					.withIconText(new TextComponent(String.valueOf(i + 1)))
 					.withIcon(ICON_LIMB_OVERCLOCKING)
+					.withName(new TranslatableComponent("android_research.overdrive_that_matters.limb_overclocking", i + 1))
+					.withDescription(new TranslatableComponent("android_research.overdrive_that_matters.limb_overclocking.description", (i + 1) * 8, (i + 1) * 6))
 					.addFeatureResult(Names.LIMB_OVERCLOCKING, i);
 
 				if (i > 0) {
diff --git a/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearch.java b/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearch.java
index 594029d1f..32c791f6a 100644
--- a/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearch.java
+++ b/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearch.java
@@ -56,15 +56,29 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 		return null;
 	}
 
+	public Component getDisplayName() {
+		return type.getDisplayName();
+	}
+
 	public List<Component> getTooltip() {
-		return List.of(type.getDisplayName());
+		return List.of(getDisplayName());
+	}
+
+	public boolean canResearch() {
+		for (var preq : getPrerequisites()) {
+			if (!capability.getResearch(preq).isResearched()) {
+				return false;
+			}
+		}
+
+		return canAfford();
 	}
 
 	public boolean research(boolean force) {
 		if (researched)
 			return false;
 
-		if (!force && !canAfford())
+		if (!force && !canResearch())
 			return false;
 
 		consumeCost();
@@ -121,6 +135,8 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 		public int experience = 0;
 		public Component text;
 		public boolean has_description = false;
+		public Component custom_description;
+		public Component custom_name;
 		public final ArrayList<DeferredItemStack> items = new ArrayList<>();
 		public final ArrayList<ResourceLocation> prerequisites = new ArrayList<>();
 		public final ArrayList<DeferredFeature> feature_results = new ArrayList<>();
@@ -176,6 +192,17 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 			return this;
 		}
 
+		public Builder withDescription(Component text) {
+			this.has_description = true;
+			this.custom_description = text;
+			return this;
+		}
+
+		public Builder withName(Component text) {
+			this.custom_name = text;
+			return this;
+		}
+
 		public Builder withIcon(SkinElement icon) {
 			this.icon = icon;
 			return this;
@@ -232,8 +259,17 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 		public AndroidResearchType.AndroidResearchFactory<AndroidResearch> build() {
 			return (type, capability) -> {
 				resolve();
+				final var list_cp = List.copyOf(resolved_preq);
 
 				return new AndroidResearch(type, capability) {
+					@Override
+					public Component getDisplayName() {
+						if (custom_name != null)
+							return custom_name;
+
+						return super.getDisplayName();
+					}
+
 					@Nullable
 					@Override
 					public SkinElement getIcon() {
@@ -250,7 +286,9 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 					public List<Component> getTooltip() {
 						var list = new ArrayList<>(super.getTooltip());
 
-						if (has_description) {
+						if (custom_description != null) {
+							list.add(custom_description);
+						} else if (has_description) {
 							list.add(new TranslatableComponent("android_research." + type.getRegistryName().getNamespace() + "." + type.getRegistryName().getPath() + ".description"));
 						}
 
@@ -295,7 +333,7 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 
 					@Override
 					public List<AndroidResearchType<?>> getPrerequisites() {
-						return List.copyOf(resolved_preq);
+						return list_cp;
 					}
 
 					@Override
@@ -314,12 +352,6 @@ public abstract class AndroidResearch implements INBTSerializable<CompoundTag> {
 
 					@Override
 					public boolean canAfford() {
-						for (var preq : resolved_preq) {
-							if (!capability.getResearch(preq).isResearched()) {
-								return false;
-							}
-						}
-
 						if (capability.ply.experienceLevel < experience)
 							return false;
 
diff --git a/src/main/java/ru/dbotthepony/mc/otm/android/feature/AndroidLimbOverclocking.java b/src/main/java/ru/dbotthepony/mc/otm/android/feature/AndroidLimbOverclocking.java
index b3e4cd4d4..b66611051 100644
--- a/src/main/java/ru/dbotthepony/mc/otm/android/feature/AndroidLimbOverclocking.java
+++ b/src/main/java/ru/dbotthepony/mc/otm/android/feature/AndroidLimbOverclocking.java
@@ -9,7 +9,7 @@ import ru.dbotthepony.mc.otm.capability.IAndroidCapability;
 import java.util.UUID;
 
 public class AndroidLimbOverclocking extends AndroidFeature {
-	public static final UUID MODIFIER_NAME = UUID.fromString("4a3fae46-e57b-4e20-857d-f5c2b2c8f2f2");
+	public static final UUID MODIFIER_ID = UUID.fromString("4a3fae46-e57b-4e20-857d-f5c2b2c8f2f2");
 
 	public AndroidLimbOverclocking(AndroidFeatureType<?> type, IAndroidCapability capability) {
 		super(type, capability);
@@ -20,8 +20,15 @@ public class AndroidLimbOverclocking extends AndroidFeature {
 		var speed = capability.getEntity().getAttribute(Attributes.MOVEMENT_SPEED);
 
 		if (speed != null) {
-			speed.removePermanentModifier(MODIFIER_NAME);
-			speed.addPermanentModifier(new AttributeModifier(MODIFIER_NAME, type.getDisplayName().toString(), 0.08d * (level + 1), AttributeModifier.Operation.MULTIPLY_TOTAL));
+			speed.removePermanentModifier(MODIFIER_ID);
+			speed.addPermanentModifier(new AttributeModifier(MODIFIER_ID, type.getDisplayName().toString(), 0.08d * (level + 1), AttributeModifier.Operation.MULTIPLY_TOTAL));
+		}
+
+		var attack_speed = capability.getEntity().getAttribute(Attributes.ATTACK_SPEED);
+
+		if (attack_speed != null) {
+			attack_speed.removePermanentModifier(MODIFIER_ID);
+			attack_speed.addPermanentModifier(new AttributeModifier(MODIFIER_ID, type.getDisplayName().toString(), 0.06d * (level + 1), AttributeModifier.Operation.MULTIPLY_TOTAL));
 		}
 	}
 
@@ -30,7 +37,13 @@ public class AndroidLimbOverclocking extends AndroidFeature {
 		var speed = capability.getEntity().getAttribute(Attributes.MOVEMENT_SPEED);
 
 		if (speed != null) {
-			speed.removePermanentModifier(MODIFIER_NAME);
+			speed.removePermanentModifier(MODIFIER_ID);
+		}
+
+		var attack_speed = capability.getEntity().getAttribute(Attributes.ATTACK_SPEED);
+
+		if (attack_speed != null) {
+			attack_speed.removePermanentModifier(MODIFIER_ID);
 		}
 	}
 }
diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/AndroidStationScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/AndroidStationScreen.java
index 74ad9f5aa..11cc8b6b4 100644
--- a/src/main/java/ru/dbotthepony/mc/otm/screen/AndroidStationScreen.java
+++ b/src/main/java/ru/dbotthepony/mc/otm/screen/AndroidStationScreen.java
@@ -37,7 +37,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> {
 				if (_cap instanceof AndroidCapabilityPlayer cap) {
 					if (node.isResearched()) {
 						RESEARCHED.setSystemColor();
-					} else if (node.canAfford()) {
+					} else if (node.canResearch()) {
 						CAN_BE_RESEARCHED.setSystemColor();
 					} else {
 						CAN_NOT_BE_RESEARCHED.setSystemColor();
@@ -73,7 +73,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> {
 
 				if (node.isResearched()) {
 					list.add(new TranslatableComponent("otm.android_station.research.researched").withStyle(ChatFormatting.DARK_AQUA));
-				} else if (node.canAfford()) {
+				} else if (node.canResearch()) {
 					list.add(new TranslatableComponent("otm.android_station.research.can_be_researched").withStyle(ChatFormatting.DARK_GREEN));
 				} else {
 					list.add(new TranslatableComponent("otm.android_station.research.can_not_be_researched").withStyle(ChatFormatting.DARK_RED));
diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json
index 3ae205a93..fe0a114c0 100644
--- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json
+++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json
@@ -49,15 +49,9 @@
 	"android_feature.overdrive_that_matters.limb_overclocking_3": "Limb overclocking 3",
 	"android_feature.overdrive_that_matters.limb_overclocking_4": "Limb overclocking 4",
 
-	"android_research.overdrive_that_matters.limb_overclocking_1": "Limb overclocking 1",
-	"android_research.overdrive_that_matters.limb_overclocking_2": "Limb overclocking 2",
-	"android_research.overdrive_that_matters.limb_overclocking_3": "Limb overclocking 3",
-	"android_research.overdrive_that_matters.limb_overclocking_4": "Limb overclocking 4",
+	"android_research.overdrive_that_matters.limb_overclocking": "Limb overclocking %s",
 
-	"android_research.overdrive_that_matters.limb_overclocking_1.description": "Boosts unit mobility by 8%% and attack speed by 4%%",
-	"android_research.overdrive_that_matters.limb_overclocking_2.description": "Boosts unit mobility by 16%% and attack speed by 8%%",
-	"android_research.overdrive_that_matters.limb_overclocking_3.description": "Boosts unit mobility by 24%% and attack speed by 12%%",
-	"android_research.overdrive_that_matters.limb_overclocking_4.description": "Boosts unit mobility by 32%% and attack speed by 16%%",
+	"android_research.overdrive_that_matters.limb_overclocking.description": "Boosts unit mobility by %s%% and attack speed by %s%%",
 
 	"android_research.overdrive_that_matters.air_bags": "Air bags",
 	"android_research.overdrive_that_matters.air_bags.description": "Allows unit to swim in water",