Nanobots, Regeneration and Armor features and research

This commit is contained in:
DBotThePony 2021-08-24 18:14:53 +07:00
parent c45c7045d9
commit 7c5bfb1b36
Signed by: DBot
GPG Key ID: DCC23B5715498507
10 changed files with 415 additions and 34 deletions

View File

@ -20,6 +20,8 @@ import ru.dbotthepony.mc.otm.android.AndroidFeature;
import ru.dbotthepony.mc.otm.android.AndroidResearchBuilder; import ru.dbotthepony.mc.otm.android.AndroidResearchBuilder;
import ru.dbotthepony.mc.otm.android.AndroidResearchType; import ru.dbotthepony.mc.otm.android.AndroidResearchType;
import ru.dbotthepony.mc.otm.android.feature.AndroidLimbOverclocking; import ru.dbotthepony.mc.otm.android.feature.AndroidLimbOverclocking;
import ru.dbotthepony.mc.otm.android.feature.AndroidNanobotsArmor;
import ru.dbotthepony.mc.otm.android.feature.AndroidNanobotsRegeneration;
import ru.dbotthepony.mc.otm.block.*; import ru.dbotthepony.mc.otm.block.*;
import ru.dbotthepony.mc.otm.block.entity.*; import ru.dbotthepony.mc.otm.block.entity.*;
import ru.dbotthepony.mc.otm.android.AndroidFeatureType; import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
@ -109,6 +111,7 @@ public class Registry {
// android features and research // android features and research
public static final ResourceLocation AIR_BAGS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "air_bags"); public static final ResourceLocation AIR_BAGS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "air_bags");
public static final ResourceLocation LIMB_OVERCLOCKING = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking"); public static final ResourceLocation LIMB_OVERCLOCKING = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking");
public static final ResourceLocation LIMB_OVERCLOCKING_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_1"); public static final ResourceLocation LIMB_OVERCLOCKING_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_1");
public static final ResourceLocation LIMB_OVERCLOCKING_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_2"); public static final ResourceLocation LIMB_OVERCLOCKING_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_2");
@ -116,6 +119,40 @@ public class Registry {
public static final ResourceLocation LIMB_OVERCLOCKING_4 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_4"); public static final ResourceLocation LIMB_OVERCLOCKING_4 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "limb_overclocking_4");
public static final ResourceLocation[] LIMB_OVERCLOCKING_LIST = new ResourceLocation[] { LIMB_OVERCLOCKING_1, LIMB_OVERCLOCKING_2, LIMB_OVERCLOCKING_3, LIMB_OVERCLOCKING_4 }; public static final ResourceLocation[] LIMB_OVERCLOCKING_LIST = new ResourceLocation[] { LIMB_OVERCLOCKING_1, LIMB_OVERCLOCKING_2, LIMB_OVERCLOCKING_3, LIMB_OVERCLOCKING_4 };
public static final ResourceLocation NANOBOTS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots");
public static final ResourceLocation NANOBOTS_REGENERATION = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_regeneration");
public static final ResourceLocation NANOBOTS_REGENERATION_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_regeneration_1");
public static final ResourceLocation NANOBOTS_REGENERATION_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_regeneration_2");
public static final ResourceLocation NANOBOTS_REGENERATION_3 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_regeneration_3");
public static final ResourceLocation NANOBOTS_REGENERATION_4 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_regeneration_4");
public static final ResourceLocation[] NANOBOTS_REGENERATION_LIST = new ResourceLocation[] { NANOBOTS_REGENERATION_1, NANOBOTS_REGENERATION_2, NANOBOTS_REGENERATION_3, NANOBOTS_REGENERATION_4 };
public static final ResourceLocation NANOBOTS_ARMOR = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor");
public static final ResourceLocation NANOBOTS_ARMOR_STRENGTH_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_1");
public static final ResourceLocation NANOBOTS_ARMOR_STRENGTH_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_2");
public static final ResourceLocation NANOBOTS_ARMOR_STRENGTH_3 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_3");
public static final ResourceLocation[] NANOBOTS_ARMOR_STRENGTH_LIST = new ResourceLocation[] {
NANOBOTS_ARMOR_STRENGTH_1,
NANOBOTS_ARMOR_STRENGTH_2,
NANOBOTS_ARMOR_STRENGTH_3,
};
public static final ResourceLocation NANOBOTS_ARMOR_SPEED_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_1");
public static final ResourceLocation NANOBOTS_ARMOR_SPEED_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_2");
public static final ResourceLocation NANOBOTS_ARMOR_SPEED_3 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_3");
public static final ResourceLocation[] NANOBOTS_ARMOR_SPEED_LIST = new ResourceLocation[] {
NANOBOTS_ARMOR_SPEED_1,
NANOBOTS_ARMOR_SPEED_2,
NANOBOTS_ARMOR_SPEED_3,
};
public static final ResourceLocation HYDRAULICS_OVERLOAD = new ResourceLocation(OverdriveThatMatters.MOD_ID, "hydraulics_overload");
public static final ResourceLocation HYDRAULICS_OVERLOAD_1 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "hydraulics_overload_1");
public static final ResourceLocation HYDRAULICS_OVERLOAD_2 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "hydraulics_overload_2");
public static final ResourceLocation HYDRAULICS_OVERLOAD_3 = new ResourceLocation(OverdriveThatMatters.MOD_ID, "hydraulics_overload_3");
} }
public static class Blocks { public static class Blocks {
@ -299,16 +336,22 @@ public class Registry {
public static class AndroidFeatures { public static class AndroidFeatures {
public static final AndroidFeatureType<AndroidFeature> AIR_BAGS = new AndroidFeatureType<>(AndroidFeature::new); public static final AndroidFeatureType<AndroidFeature> AIR_BAGS = new AndroidFeatureType<>(AndroidFeature::new);
public static final AndroidFeatureType<AndroidLimbOverclocking> LIMB_OVERCLOCKING = new AndroidFeatureType<>(AndroidLimbOverclocking::new); public static final AndroidFeatureType<AndroidLimbOverclocking> LIMB_OVERCLOCKING = new AndroidFeatureType<>(AndroidLimbOverclocking::new);
public static final AndroidFeatureType<AndroidNanobotsRegeneration> NANOBOTS_REGENERATION = new AndroidFeatureType<>(AndroidNanobotsRegeneration::new);
public static final AndroidFeatureType<AndroidNanobotsArmor> NANOBOTS_ARMOR = new AndroidFeatureType<>(AndroidNanobotsArmor::new);
static { static {
AIR_BAGS.setRegistryName(Names.AIR_BAGS); AIR_BAGS.setRegistryName(Names.AIR_BAGS);
LIMB_OVERCLOCKING.setRegistryName(Names.LIMB_OVERCLOCKING); LIMB_OVERCLOCKING.setRegistryName(Names.LIMB_OVERCLOCKING);
NANOBOTS_REGENERATION.setRegistryName(Names.NANOBOTS_REGENERATION);
NANOBOTS_ARMOR.setRegistryName(Names.NANOBOTS_ARMOR);
} }
@SubscribeEvent @SubscribeEvent
public static void register(final RegistryEvent.Register<AndroidFeatureType<?>> event) { public static void register(final RegistryEvent.Register<AndroidFeatureType<?>> event) {
event.getRegistry().register(AIR_BAGS); event.getRegistry().register(AIR_BAGS);
event.getRegistry().register(LIMB_OVERCLOCKING); event.getRegistry().register(LIMB_OVERCLOCKING);
event.getRegistry().register(NANOBOTS_REGENERATION);
event.getRegistry().register(NANOBOTS_ARMOR);
} }
} }
@ -326,7 +369,7 @@ public class Registry {
public static final SkinElement ICON_ARC; public static final SkinElement ICON_ARC;
public static final SkinElement ICON_ARROW; public static final SkinElement ICON_ARROW;
public static final SkinElement ICON_ARMOR; public static final SkinElement ICON_ARMOR;
public static final SkinElement ICON_REGENERATIVE; public static final SkinElement ICON_NANOBOTS;
public static final SkinElement ICON_NIGHT_VISION; public static final SkinElement ICON_NIGHT_VISION;
public static final SkinElement ICON_OXYGEN_SUPPLY; public static final SkinElement ICON_OXYGEN_SUPPLY;
@ -357,7 +400,7 @@ public class Registry {
ICON_ARC = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18; ICON_ARC = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18;
ICON_ARROW = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18; ICON_ARROW = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18;
ICON_ARMOR = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18; ICON_ARMOR = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18;
ICON_REGENERATIVE = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18; ICON_NANOBOTS = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18;
ICON_NIGHT_VISION = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18; ICON_NIGHT_VISION = new SkinElement(ICONS, x, y, 18, 18, 126, 126); x += 18;
ICON_OXYGEN_SUPPLY = new SkinElement(ICONS, x, y, 18, 18, 126, 126); ICON_OXYGEN_SUPPLY = new SkinElement(ICONS, x, y, 18, 18, 126, 126);
@ -382,40 +425,131 @@ public class Registry {
.build(); .build();
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch>[] LIMB_OVERCLOCKING = new AndroidResearchType[4]; public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch>[] LIMB_OVERCLOCKING = new AndroidResearchType[4];
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch>[] NANOBOTS_REGENERATION = new AndroidResearchType[4];
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch>[] NANOBOTS_ARMOR_STRENGTH = new AndroidResearchType[3];
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch>[] NANOBOTS_ARMOR_SPEED = new AndroidResearchType[3];
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch> NANOBOTS =
new AndroidResearchBuilder()
.setExperienceCost(15)
.withDescription()
.withIcon(ICON_NANOBOTS)
.build();
public static final AndroidResearchType<ru.dbotthepony.mc.otm.android.AndroidResearch> NANOBOTS_ARMOR =
new AndroidResearchBuilder()
.setExperienceCost(25)
.withDescription()
.addPrerequisite(Names.NANOBOTS)
.addFeatureResult(Names.NANOBOTS_ARMOR)
.withIcon(ICON_ARMOR)
.build();
static { static {
AIR_BAGS.setRegistryName(Names.AIR_BAGS); AIR_BAGS.setRegistryName(Names.AIR_BAGS);
NANOBOTS.setRegistryName(Names.NANOBOTS);
NANOBOTS_ARMOR.setRegistryName(Names.NANOBOTS_ARMOR);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
var builder = new AndroidResearchBuilder() var limbs = new AndroidResearchBuilder()
.withDescription() .setExperienceCost(18 + i * 8)
.setExperienceCost(24 + i * 8)
.withIconText(new TextComponent(String.valueOf(i + 1))) .withIconText(new TextComponent(String.valueOf(i + 1)))
.withIcon(ICON_LIMB_OVERCLOCKING) .withIcon(ICON_LIMB_OVERCLOCKING)
.withName(new TranslatableComponent("android_research.overdrive_that_matters.limb_overclocking", i + 1)) .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)) .withDescription(new TranslatableComponent("android_research.overdrive_that_matters.limb_overclocking.description", (i + 1) * 8, (i + 1) * 6))
.addFeatureResult(Names.LIMB_OVERCLOCKING, i); .addFeatureResult(Names.LIMB_OVERCLOCKING, i);
var regeneration = new AndroidResearchBuilder()
.setExperienceCost(20 + i * 6)
.withIconText(new TextComponent(String.valueOf(i + 1)))
.withIcon(ICON_NANOBOTS)
.withName(new TranslatableComponent("android_research.overdrive_that_matters.nanobots_regeneration", i + 1))
.withDescription(
i > 0 ? new TranslatableComponent("android_research.overdrive_that_matters.nanobots_regeneration.description_improve") : new TranslatableComponent("android_research.overdrive_that_matters.nanobots_regeneration.description"))
.addFeatureResult(Names.NANOBOTS_REGENERATION, i);
if (i > 0) { if (i > 0) {
builder.addPrerequisite(Names.LIMB_OVERCLOCKING_LIST[i - 1]); limbs.addPrerequisite(Names.LIMB_OVERCLOCKING_LIST[i - 1]);
regeneration.addPrerequisite(Names.NANOBOTS_REGENERATION_LIST[i - 1]);
} else {
regeneration.addPrerequisite(Names.NANOBOTS);
} }
LIMB_OVERCLOCKING[i] = builder.build(); LIMB_OVERCLOCKING[i] = limbs.build();
NANOBOTS_REGENERATION[i] = regeneration.build();
}
for (int i = 0; i < 3; i++) {
final int level = i + 1;
NANOBOTS_ARMOR_STRENGTH[i] = new AndroidResearchBuilder()
.setExperienceCost(20 + i * 8)
.withIconText(new TextComponent(String.valueOf(i + 1)))
.withIcon(ICON_ARMOR)
.addPrerequisite(i > 0 ? Names.NANOBOTS_ARMOR_STRENGTH_LIST[i - 1] : Names.NANOBOTS_ARMOR)
.withName(new TranslatableComponent("android_research.overdrive_that_matters.nanobots_armor_strength", i + 1))
.withDescription(new TranslatableComponent("android_research.overdrive_that_matters.nanobots_armor_strength.description", (i + 1) * 8, (i + 1) * 6))
.addFeatureResult(Names.NANOBOTS_ARMOR, 0, (feature) -> {
if (((AndroidNanobotsArmor) feature).getStrength() < level)
((AndroidNanobotsArmor) feature).setStrength(level);
})
.build();
NANOBOTS_ARMOR_SPEED[i] = new AndroidResearchBuilder()
.setExperienceCost(20 + i * 8)
.withIconText(new TextComponent(String.valueOf(i + 1)))
.withIcon(ICON_ARMOR)
.addPrerequisite(i > 0 ? Names.NANOBOTS_ARMOR_SPEED_LIST[i - 1] : Names.NANOBOTS_ARMOR)
.withName(new TranslatableComponent("android_research.overdrive_that_matters.nanobots_armor_speed", i + 1))
.withDescription(new TranslatableComponent("android_research.overdrive_that_matters.nanobots_armor_speed.description", (i + 1) * 8, (i + 1) * 6))
.addFeatureResult(Names.NANOBOTS_ARMOR, 0, (feature) -> {
if (((AndroidNanobotsArmor) feature).getSpeed() < level)
((AndroidNanobotsArmor) feature).setSpeed(level);
})
.build();
} }
LIMB_OVERCLOCKING[0].setRegistryName(Names.LIMB_OVERCLOCKING_1); LIMB_OVERCLOCKING[0].setRegistryName(Names.LIMB_OVERCLOCKING_1);
LIMB_OVERCLOCKING[1].setRegistryName(Names.LIMB_OVERCLOCKING_2); LIMB_OVERCLOCKING[1].setRegistryName(Names.LIMB_OVERCLOCKING_2);
LIMB_OVERCLOCKING[2].setRegistryName(Names.LIMB_OVERCLOCKING_3); LIMB_OVERCLOCKING[2].setRegistryName(Names.LIMB_OVERCLOCKING_3);
LIMB_OVERCLOCKING[3].setRegistryName(Names.LIMB_OVERCLOCKING_4); LIMB_OVERCLOCKING[3].setRegistryName(Names.LIMB_OVERCLOCKING_4);
NANOBOTS_ARMOR_SPEED[0].setRegistryName(Names.NANOBOTS_ARMOR_SPEED_1);
NANOBOTS_ARMOR_SPEED[1].setRegistryName(Names.NANOBOTS_ARMOR_SPEED_2);
NANOBOTS_ARMOR_SPEED[2].setRegistryName(Names.NANOBOTS_ARMOR_SPEED_3);
NANOBOTS_ARMOR_STRENGTH[0].setRegistryName(Names.NANOBOTS_ARMOR_STRENGTH_1);
NANOBOTS_ARMOR_STRENGTH[1].setRegistryName(Names.NANOBOTS_ARMOR_STRENGTH_2);
NANOBOTS_ARMOR_STRENGTH[2].setRegistryName(Names.NANOBOTS_ARMOR_STRENGTH_3);
NANOBOTS_REGENERATION[0].setRegistryName(Names.NANOBOTS_REGENERATION_1);
NANOBOTS_REGENERATION[1].setRegistryName(Names.NANOBOTS_REGENERATION_2);
NANOBOTS_REGENERATION[2].setRegistryName(Names.NANOBOTS_REGENERATION_3);
NANOBOTS_REGENERATION[3].setRegistryName(Names.NANOBOTS_REGENERATION_4);
} }
@SubscribeEvent @SubscribeEvent
public static void register(final RegistryEvent.Register<AndroidResearchType<?>> event) { public static void register(final RegistryEvent.Register<AndroidResearchType<?>> event) {
event.getRegistry().register(AIR_BAGS); event.getRegistry().register(AIR_BAGS);
event.getRegistry().register(NANOBOTS);
event.getRegistry().register(NANOBOTS_ARMOR);
event.getRegistry().register(LIMB_OVERCLOCKING[0]); event.getRegistry().register(LIMB_OVERCLOCKING[0]);
event.getRegistry().register(LIMB_OVERCLOCKING[1]); event.getRegistry().register(LIMB_OVERCLOCKING[1]);
event.getRegistry().register(LIMB_OVERCLOCKING[2]); event.getRegistry().register(LIMB_OVERCLOCKING[2]);
event.getRegistry().register(LIMB_OVERCLOCKING[3]); event.getRegistry().register(LIMB_OVERCLOCKING[3]);
event.getRegistry().register(NANOBOTS_ARMOR_SPEED[0]);
event.getRegistry().register(NANOBOTS_ARMOR_SPEED[1]);
event.getRegistry().register(NANOBOTS_ARMOR_SPEED[2]);
event.getRegistry().register(NANOBOTS_ARMOR_STRENGTH[0]);
event.getRegistry().register(NANOBOTS_ARMOR_STRENGTH[1]);
event.getRegistry().register(NANOBOTS_ARMOR_STRENGTH[2]);
event.getRegistry().register(NANOBOTS_REGENERATION[0]);
event.getRegistry().register(NANOBOTS_REGENERATION[1]);
event.getRegistry().register(NANOBOTS_REGENERATION[2]);
event.getRegistry().register(NANOBOTS_REGENERATION[3]);
} }
} }

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.android;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import ru.dbotthepony.mc.otm.capability.IAndroidCapability; import ru.dbotthepony.mc.otm.capability.IAndroidCapability;
public class AndroidFeature implements INBTSerializable<CompoundTag> { public class AndroidFeature implements INBTSerializable<CompoundTag> {
@ -47,11 +48,11 @@ public class AndroidFeature implements INBTSerializable<CompoundTag> {
} }
public void tickClient() { public void tickClient() {
// override
} }
public void tickServer() { public void tickServer() {
// override
} }
public void applyModifiers() {} public void applyModifiers() {}
@ -61,6 +62,10 @@ public class AndroidFeature implements INBTSerializable<CompoundTag> {
tag.putInt("level", level); tag.putInt("level", level);
} }
public void onHurt(LivingHurtEvent event) {
// override
}
@Override @Override
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {
var tag = new CompoundTag(); var tag = new CompoundTag();

View File

@ -15,19 +15,29 @@ import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer;
public class AndroidResearchBuilder { public class AndroidResearchBuilder {
record DeferredItemStack(ResourceLocation id, int amount) { record DeferredItemStack(ResourceLocation id, int amount) {
} }
record DeferredFeature(ResourceLocation id, int level) { record DeferredFeature(ResourceLocation id, int level, Consumer<AndroidFeature> callback) {
DeferredFeature(ResourceLocation id, int level) { DeferredFeature(ResourceLocation id, int level, Consumer<AndroidFeature> callback) {
this.id = id; this.id = id;
this.level = level; this.level = level;
this.callback = callback;
}
DeferredFeature(ResourceLocation id, int level) {
this(id, level, (f) -> {});
}
DeferredFeature(ResourceLocation id, Consumer<AndroidFeature> callback) {
this(id, 0, (f) -> {});
} }
DeferredFeature(ResourceLocation id) { DeferredFeature(ResourceLocation id) {
this(id, 0); this(id, 0, (f) -> {});
} }
} }
@ -61,6 +71,16 @@ public class AndroidResearchBuilder {
return this; return this;
} }
public AndroidResearchBuilder addFeatureResult(ResourceLocation location, Consumer<AndroidFeature> callback) {
feature_results.add(new DeferredFeature(location, callback));
return this;
}
public AndroidResearchBuilder addFeatureResult(AndroidFeatureType<?> location, Consumer<AndroidFeature> callback) {
feature_results.add(new DeferredFeature(Objects.requireNonNull(location.getRegistryName()), callback));
return this;
}
public AndroidResearchBuilder addFeatureResult(ResourceLocation location, int level) { public AndroidResearchBuilder addFeatureResult(ResourceLocation location, int level) {
feature_results.add(new DeferredFeature(location, level)); feature_results.add(new DeferredFeature(location, level));
return this; return this;
@ -71,6 +91,16 @@ public class AndroidResearchBuilder {
return this; return this;
} }
public AndroidResearchBuilder addFeatureResult(ResourceLocation location, int level, Consumer<AndroidFeature> callback) {
feature_results.add(new DeferredFeature(location, level, callback));
return this;
}
public AndroidResearchBuilder addFeatureResult(AndroidFeatureType<?> location, int level, Consumer<AndroidFeature> callback) {
feature_results.add(new DeferredFeature(Objects.requireNonNull(location.getRegistryName()), level, callback));
return this;
}
public AndroidResearchBuilder addItem(ResourceLocation location) { public AndroidResearchBuilder addItem(ResourceLocation location) {
items.add(new DeferredItemStack(location, 1)); items.add(new DeferredItemStack(location, 1));
return this; return this;
@ -115,7 +145,7 @@ public class AndroidResearchBuilder {
private final ArrayList<ItemStack> resolved_stacks = new ArrayList<>(); private final ArrayList<ItemStack> resolved_stacks = new ArrayList<>();
private List<AndroidResearchType<?>> resolved_preq; private List<AndroidResearchType<?>> resolved_preq;
record ResolvedFeature(AndroidFeatureType<?> type, int level) { record ResolvedFeature(AndroidFeatureType<?> type, int level, Consumer<AndroidFeature> callback) {
} }
private final ArrayList<ResolvedFeature> resolved_features = new ArrayList<>(); private final ArrayList<ResolvedFeature> resolved_features = new ArrayList<>();
@ -152,7 +182,7 @@ public class AndroidResearchBuilder {
var get = Registry.ANDROID_FEATURES().getValue(entry.id); var get = Registry.ANDROID_FEATURES().getValue(entry.id);
if (get != null) { if (get != null) {
resolved_features.add(new ResolvedFeature(get, entry.level)); resolved_features.add(new ResolvedFeature(get, entry.level, entry.callback));
} else { } else {
throw new IllegalArgumentException("Can not find android feature " + entry); throw new IllegalArgumentException("Can not find android feature " + entry);
} }
@ -246,8 +276,12 @@ public class AndroidResearchBuilder {
if (get == null) { if (get == null) {
get = capability.addFeature(feature.type); get = capability.addFeature(feature.type);
get.setLevel(feature.level); get.setLevel(feature.level);
} else if (get.getLevel() < feature.level) { feature.callback.accept(get);
get.setLevel(feature.level); } else {
if (get.getLevel() < feature.level)
get.setLevel(feature.level);
feature.callback.accept(get);
} }
} }
} }

View File

@ -0,0 +1,105 @@
package ru.dbotthepony.mc.otm.android.feature;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.android.AndroidFeature;
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.capability.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import java.math.BigDecimal;
public class AndroidNanobotsArmor extends AndroidFeature {
public AndroidNanobotsArmor(AndroidFeatureType<?> type, IAndroidCapability capability) {
super(type, capability);
}
public int getStrength() {
return strength;
}
public void setStrength(int strength) {
this.strength = Math.max(0, Math.min(2, strength));
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = Math.max(0, Math.min(2, speed));
}
protected int strength = 0;
protected int speed = 0;
protected int ticks_passed = 0;
protected int layers = 0;
protected static final BigDecimal ENERGY_PER_BUILT = new BigDecimal(200);
protected static final BigDecimal ENERGY_PER_HITPOINT = new BigDecimal(500);
public static final int[] TICKS = new int[] {
80, // 4 seconds to build a layer
70, // 3.5 seconds to build a layer
60, // 3 seconds to build a layer
50, // 2.5 seconds to build a layer
};
public static final float[] SHIELD_STRENGTH = new float[] {
0.1f,
0.2f,
0.3f,
0.4f,
};
@Override
public void tickServer() {
if (layers < strength + 1 && capability.extractEnergyInner(ENERGY_PER_BUILT, true).compareTo(ENERGY_PER_BUILT) == 0) {
ticks_passed++;
if (ticks_passed >= TICKS[speed]) {
layers++;
capability.extractEnergyInner(ENERGY_PER_BUILT, false);
}
} else {
ticks_passed = 0;
}
}
@Override
public void onHurt(LivingHurtEvent event) {
ticks_passed = 0;
if (!event.getSource().isBypassArmor() && layers > 0) {
var absorbed = event.getAmount() * SHIELD_STRENGTH[layers];
if (absorbed > 0.1f) {
var required = ENERGY_PER_HITPOINT.multiply(new BigDecimal(Float.toString(absorbed)));
var extracted = capability.extractEnergyInner(required, false);
event.setAmount(event.getAmount() - absorbed * extracted.divide(required, MatteryCapability.ROUND_RULES).floatValue());
layers--;
}
}
}
@Override
public void serializeNBT(CompoundTag tag) {
super.serializeNBT(tag);
tag.putInt("ticks_passed", ticks_passed);
tag.putInt("layers", layers);
tag.putInt("strength", strength);
tag.putInt("speed", speed);
}
@Override
public void deserializeNBT(CompoundTag tag) {
super.deserializeNBT(tag);
ticks_passed = tag.getInt("ticks_passed");
layers = tag.getInt("layers");
strength = tag.getInt("strength");
speed = tag.getInt("speed");
}
}

View File

@ -0,0 +1,73 @@
package ru.dbotthepony.mc.otm.android.feature;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import ru.dbotthepony.mc.otm.android.AndroidFeature;
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.capability.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import java.math.BigDecimal;
public class AndroidNanobotsRegeneration extends AndroidFeature {
public AndroidNanobotsRegeneration(AndroidFeatureType<?> type, IAndroidCapability capability) {
super(type, capability);
}
protected int ticks_passed = 0;
protected int heal_ticks = 0;
protected static final BigDecimal ENERGY_PER_HITPOINT = new BigDecimal(800);
protected static final int[] TICKS_BETWEEN_HEAL = new int[] {
100, // 5 seconds
80, // 4 seconds
60, // 3 seconds
40, // 2 seconds
};
@Override
public void tickServer() {
var ent = capability.getEntity();
if (ent.getHealth() > 0 && ent.getHealth() < ent.getMaxHealth()) {
ticks_passed++;
var wait_time = heal_ticks >= TICKS_BETWEEN_HEAL.length ? TICKS_BETWEEN_HEAL[TICKS_BETWEEN_HEAL.length - 1] : TICKS_BETWEEN_HEAL[heal_ticks];
if (ticks_passed > wait_time) {
var missing = Math.min(1, ent.getMaxHealth() - ent.getHealth());
var extract = capability.extractEnergyInner(ENERGY_PER_HITPOINT.multiply(new BigDecimal(Float.toString(missing))), false);
if (extract.compareTo(BigDecimal.ZERO) > 0) {
heal_ticks = Math.min(heal_ticks + 1, level);
ent.heal(missing * extract.divide(ENERGY_PER_HITPOINT, MatteryCapability.ROUND_RULES).floatValue());
ticks_passed = 0;
}
}
} else {
heal_ticks = 0;
ticks_passed = 0;
}
}
@Override
public void onHurt(LivingHurtEvent event) {
heal_ticks = 0;
ticks_passed = 0;
}
@Override
public void serializeNBT(CompoundTag tag) {
super.serializeNBT(tag);
tag.putInt("heal_ticks", heal_ticks);
tag.putInt("ticks_passed", ticks_passed);
}
@Override
public void deserializeNBT(CompoundTag tag) {
super.deserializeNBT(tag);
heal_ticks = tag.getInt("heal_ticks");
ticks_passed = tag.getInt("ticks_passed");
}
}

View File

@ -17,6 +17,8 @@ import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fmllegacy.network.PacketDistributor; import net.minecraftforge.fmllegacy.network.PacketDistributor;
@ -69,11 +71,11 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
} }
@Override @Override
public AndroidFeature addFeature(@Nonnull AndroidFeatureType<?> feature) { public <T extends AndroidFeature> T addFeature(@Nonnull AndroidFeatureType<T> feature) {
var get = features.get(feature); var get = features.get(feature);
if (get != null) if (get != null)
return get; return (T) get;
var factory = feature.factory(this); var factory = feature.factory(this);
features.put(feature, factory); features.put(feature, factory);
@ -125,8 +127,8 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
} }
@Nullable @Nullable
public AndroidFeature getFeature(AndroidFeatureType<?> feature) { public <T extends AndroidFeature> T getFeature(AndroidFeatureType<T> feature) {
return features.get(feature); return (T) features.get(feature);
} }
public static final Set<MobEffect> UNAFFECTED_EFFECTS = new HashSet<>(); public static final Set<MobEffect> UNAFFECTED_EFFECTS = new HashSet<>();
@ -181,6 +183,21 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
ent.getCapability(MatteryCapability.ANDROID).ifPresent(ent.level.isClientSide ? IAndroidCapability::tickClient : IAndroidCapability::tick); ent.getCapability(MatteryCapability.ANDROID).ifPresent(ent.level.isClientSide ? IAndroidCapability::tickClient : IAndroidCapability::tick);
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
public static void onHurtEvent(LivingHurtEvent event) {
if (event.isCanceled())
return;
var ent = event.getEntity();
ent.getCapability(MatteryCapability.ANDROID).ifPresent((cap) -> cap.onHurt(event));
}
public void onHurt(LivingHurtEvent event) {
for (var feature : features.values()) {
feature.onHurt(event);
}
}
@Override @Override
@Nonnull @Nonnull
public CompoundTag serializeNBT() { public CompoundTag serializeNBT() {

View File

@ -115,10 +115,10 @@ public class AndroidCapabilityPlayer extends AndroidCapability {
return tag; return tag;
} }
public AndroidResearch getResearch(AndroidResearchType<?> type) { public <T extends AndroidResearch> T getResearch(AndroidResearchType<T> type) {
for (var instance : research_list) { for (var instance : research_list) {
if (instance.type == type) { if (instance.type == type) {
return instance; return (T) instance;
} }
} }
@ -200,14 +200,14 @@ public class AndroidCapabilityPlayer extends AndroidCapability {
var stats = ply.getFoodData(); var stats = ply.getFoodData();
while (stats.getFoodLevel() < 17 && this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).compareTo(ENERGY_FOR_HUNGER_POINT) == 0) { while (stats.getFoodLevel() < 18 && this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).compareTo(ENERGY_FOR_HUNGER_POINT) == 0) {
this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false); this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false);
stats.setFoodLevel(stats.getFoodLevel() + 1); stats.setFoodLevel(stats.getFoodLevel() + 1);
} }
// "block" quick regeneration // "block" quick regeneration
// also cause power to generate while in peaceful // also cause power to generate while in peaceful
while (stats.getFoodLevel() > 17 && this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true).compareTo(ENERGY_FOR_HUNGER_POINT) == 0) { while (stats.getFoodLevel() > 18 && this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true).compareTo(ENERGY_FOR_HUNGER_POINT) == 0) {
this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false); this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false);
stats.setFoodLevel(stats.getFoodLevel() - 1); stats.setFoodLevel(stats.getFoodLevel() - 1);
} }

View File

@ -4,6 +4,7 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import ru.dbotthepony.mc.otm.android.AndroidFeature; import ru.dbotthepony.mc.otm.android.AndroidFeature;
import ru.dbotthepony.mc.otm.android.AndroidFeatureType; import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage; import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
@ -18,14 +19,14 @@ public interface IAndroidCapability extends IMatteryEnergyStorage, INBTSerializa
void tickClient(); void tickClient();
LivingEntity getEntity(); LivingEntity getEntity();
AndroidFeature addFeature(@Nonnull AndroidFeatureType<?> feature); <T extends AndroidFeature> T addFeature(@Nonnull AndroidFeatureType<T> feature);
boolean removeFeature(@Nonnull AndroidFeatureType<?> feature); boolean removeFeature(@Nonnull AndroidFeatureType<?> feature);
boolean hasFeature(@Nullable AndroidFeatureType<?> feature); boolean hasFeature(@Nullable AndroidFeatureType<?> feature);
boolean hasFeatureLevel(@Nullable AndroidFeatureType<?> feature, int level); boolean hasFeatureLevel(@Nullable AndroidFeatureType<?> feature, int level);
AndroidFeature getFeature(AndroidFeatureType<?> feature); <T extends AndroidFeature> T getFeature(AndroidFeatureType<T> feature);
@Nonnull @Nonnull
default Optional<AndroidFeature> getFeatureO(AndroidFeatureType<?> feature) { default <T extends AndroidFeature> Optional<T> getFeatureO(AndroidFeatureType<T> feature) {
var get = getFeature(feature); var get = getFeature(feature);
return get != null ? Optional.of(get) : Optional.empty(); return get != null ? Optional.of(get) : Optional.empty();
} }
@ -33,6 +34,7 @@ public interface IAndroidCapability extends IMatteryEnergyStorage, INBTSerializa
default boolean isAndroid() { default boolean isAndroid() {
return true; return true;
} }
default void onHurt(LivingHurtEvent event) {}
@Nonnull @Nonnull
ItemStack getBatteryItemStack(); ItemStack getBatteryItemStack();

View File

@ -90,7 +90,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
} }
public static final int FRAME_WIDTH = 210; public static final int FRAME_WIDTH = 210;
public static final int GRID_WIDTH = 6; public static final int GRID_WIDTH = 5;
public static final int GRID_HEIGHT = 5; public static final int GRID_HEIGHT = 5;
public static final int FRAME_HEIGHT = 120; public static final int FRAME_HEIGHT = 120;
@ -115,7 +115,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
autoAttachToFrame(frame); autoAttachToFrame(frame);
var grid = new GridPanel(this, frame, 0, 0, GRID_WIDTH * 18, 0, GRID_WIDTH, GRID_HEIGHT); var grid = new GridPanel(this, frame, 0, 0, GRID_WIDTH * 22, 0, GRID_WIDTH, GRID_HEIGHT);
minecraft.player.getCapability(MatteryCapability.ANDROID).ifPresent(_cap -> { minecraft.player.getCapability(MatteryCapability.ANDROID).ifPresent(_cap -> {
if (_cap instanceof AndroidCapabilityPlayer cap) { if (_cap instanceof AndroidCapabilityPlayer cap) {

View File

@ -49,21 +49,32 @@
"otm.matter_bottler.switch_mode": "Switch work mode", "otm.matter_bottler.switch_mode": "Switch work mode",
"android_feature.overdrive_that_matters.air_bags": "Air bags", "android_feature.overdrive_that_matters.air_bags": "Air bags",
"android_feature.overdrive_that_matters.limb_overclocking_1": "Limb overclocking 1",
"android_feature.overdrive_that_matters.limb_overclocking_2": "Limb overclocking 2",
"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": "Limb overclocking %s", "android_research.overdrive_that_matters.limb_overclocking": "Limb overclocking %s",
"android_research.overdrive_that_matters.limb_overclocking.description": "Boosts unit mobility by %s%% and attack speed by %s%%", "android_research.overdrive_that_matters.limb_overclocking.description": "Boosts unit's mobility by %s%% and attack speed by %s%%",
"android_research.status.requires": "Requires %s to be researched", "android_research.status.requires": "Requires %s to be researched",
"android_research.status.blocks": "Locks %s", "android_research.status.blocks": "Locks %s",
"android_research.status.blocked_by": "Locked by %s", "android_research.status.blocked_by": "Locked by %s",
"android_research.overdrive_that_matters.air_bags": "Air bags", "android_research.overdrive_that_matters.air_bags": "Air bags",
"android_research.overdrive_that_matters.nanobots": "Nanobots",
"android_research.overdrive_that_matters.air_bags.description": "Allows unit to swim in water", "android_research.overdrive_that_matters.air_bags.description": "Allows unit to swim in water",
"android_research.overdrive_that_matters.nanobots.description": "Various useful nanobots for doing various tasks",
"android_research.overdrive_that_matters.nanobots_regeneration": "Regeneration %s",
"android_research.overdrive_that_matters.nanobots_regeneration.description": "Nanobots get ability to repair unit's internal systems on the move",
"android_research.overdrive_that_matters.nanobots_regeneration.description_improve": "Improves regeneration speed",
"android_research.overdrive_that_matters.nanobots_armor": "Nanobots armor",
"android_research.overdrive_that_matters.nanobots_armor.description": "Allows nanobots to align themselves in cell shape, reducing incoming damage by a %% by absorbing impacts",
"android_research.overdrive_that_matters.nanobots_armor_speed": "Nanobots armor build speed %s",
"android_research.overdrive_that_matters.nanobots_armor_speed.description": "Reduces time required for nanobots to form protection layer",
"android_research.overdrive_that_matters.nanobots_armor_strength": "Nanobots armor build speed %s",
"android_research.overdrive_that_matters.nanobots_armor_strength.description": "Increases impact absorption strength of nanobots",
"otm.suffix.merge": "%s %s", "otm.suffix.merge": "%s %s",