From e20a81c02cc798e2bbad841578bcccccc0759702 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 13 Jan 2022 15:10:05 +0700 Subject: [PATCH] Android research refund pill and health pill --- .../java/ru/dbotthepony/mc/otm/Registry.java | 8 ++ .../mc/otm/android/AndroidResearch.java | 8 ++ .../otm/android/AndroidResearchBuilder.java | 23 ++++++ .../capability/android/AndroidCapability.kt | 8 +- .../android/AndroidCapabilityPlayer.kt | 17 ++++ .../ru/dbotthepony/mc/otm/item/ItemPill.kt | 81 ++++++++++++++++--- .../overdrive_that_matters/lang/en_us.json | 10 +++ 7 files changed, 141 insertions(+), 14 deletions(-) diff --git a/src/main/java/ru/dbotthepony/mc/otm/Registry.java b/src/main/java/ru/dbotthepony/mc/otm/Registry.java index d194acab6..0bb19614c 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/Registry.java +++ b/src/main/java/ru/dbotthepony/mc/otm/Registry.java @@ -143,6 +143,8 @@ public class Registry { public static final ResourceLocation PILL_ANDROID = loc("pill_android"); public static final ResourceLocation PILL_HUMANE = loc("pill_humane"); + public static final ResourceLocation PILL_OBLIVION = loc("pill_oblivion"); + public static final ResourceLocation PILL_HEAL = loc("pill_heal"); public static final ResourceLocation BATTERY_CRUDE = loc("battery_crude"); public static final ResourceLocation BATTERY_BASIC = loc("battery_basic"); @@ -468,6 +470,8 @@ public class Registry { public static final ItemPill PILL_ANDROID = new ItemPill(PillType.BECOME_ANDROID); public static final ItemPill PILL_HUMANE = new ItemPill(PillType.BECOME_HUMANE); + public static final ItemPill PILL_OBLIVION = new ItemPill(PillType.OBLIVION); + public static final ItemPillHeal PILL_HEAL = new ItemPillHeal(); public static final ItemBattery BATTERY_CRUDE = new ItemBattery(new Fraction(30_000), new Fraction(150), new Fraction(150)); public static final ItemBattery BATTERY_BASIC = new ItemBattery(new Fraction(60_000), new Fraction(300), new Fraction(300)); @@ -568,6 +572,8 @@ public class Registry { GRAVITATIONAL_DISRUPTOR.setRegistryName(Names.GRAVITATIONAL_DISRUPTOR); PILL_ANDROID.setRegistryName(Names.PILL_ANDROID); PILL_HUMANE.setRegistryName(Names.PILL_HUMANE); + PILL_OBLIVION.setRegistryName(Names.PILL_OBLIVION); + PILL_HEAL.setRegistryName(Names.PILL_HEAL); BATTERY_CRUDE.setRegistryName(Names.BATTERY_CRUDE); BATTERY_BASIC.setRegistryName(Names.BATTERY_BASIC); BATTERY_NORMAL.setRegistryName(Names.BATTERY_NORMAL); @@ -647,6 +653,8 @@ public class Registry { event.getRegistry().register(GRAVITATIONAL_DISRUPTOR); event.getRegistry().register(PILL_ANDROID); event.getRegistry().register(PILL_HUMANE); + event.getRegistry().register(PILL_OBLIVION); + event.getRegistry().register(PILL_HEAL); event.getRegistry().register(BATTERY_CRUDE); event.getRegistry().register(BATTERY_BASIC); event.getRegistry().register(BATTERY_NORMAL); 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 edbf0c1b9..8044a902d 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearch.java +++ b/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearch.java @@ -26,6 +26,10 @@ public abstract class AndroidResearch implements INBTSerializable { return researched; } + public void unResearch() { + researched = false; + } + public AndroidResearch(AndroidResearchType type, AndroidCapabilityPlayer capability) { this.capability = capability; this.type = type; @@ -43,6 +47,10 @@ public abstract class AndroidResearch implements INBTSerializable { return type.getBlockedBy(); } + /** + * Should *only* refund research cost to host, not reverse its effects + */ + abstract public void refund(); abstract public void onResearched(); abstract public void consumeCost(); abstract public boolean canAfford(); diff --git a/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.java b/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.java index 2f3abf117..236845315 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.java +++ b/src/main/java/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.java @@ -152,6 +152,20 @@ public class AndroidResearchBuilder { private boolean resolved = false; + private static int getXpNeededForLevel(int level) { + int accumulated = 0; + + for (int thisLevel = 0; thisLevel < level; thisLevel++) { + if (thisLevel >= 30) { + accumulated += 112 + (thisLevel - 30) * 9; + } else { + accumulated += thisLevel >= 15 ? 37 + (thisLevel - 15) * 5 : 7 + thisLevel * 2; + } + } + + return accumulated; + } + private void resolve() { if (!resolved) { resolved = true; @@ -317,6 +331,15 @@ public class AndroidResearchBuilder { return true; } + @Override + public void refund() { + capability.ply.giveExperiencePoints(getXpNeededForLevel(experience)); + + for (var stack : resolved_stacks) { + capability.ply.spawnAtLocation(stack); + } + } + @Override public void consumeCost() { if (experience > 0) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt index 723930beb..2355736bd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt @@ -52,7 +52,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab private var remoteMaxBattery = Fraction(-1) private var remoteBatteryStack = ItemStack.EMPTY - @JvmField protected val features: MutableMap?, AndroidFeature> = HashMap() + @JvmField protected val features: MutableMap, AndroidFeature> = HashMap() @JvmField protected val networkQueue = ArrayList() @JvmField protected val queuedTicks = ArrayList() @JvmField protected var networkFirst = false @@ -79,7 +79,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab features[feature] = factory if (!ent.level.isClientSide) { - queuedTicks.add(Runnable { factory!!.applyModifiers() }) + queuedTicks.add(Runnable { factory.applyModifiers() }) } if (ent is ServerPlayer) { @@ -100,11 +100,9 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab if (ent is ServerPlayer) { sendNetwork(AndroidFeaturePacket(false, removed)) } - - return true } - return false + return removed != null } override fun hasFeature(feature: AndroidFeatureType<*>): Boolean { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt index 1ecb5c139..51a56c87b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt @@ -109,6 +109,23 @@ class AndroidCapabilityPlayer(@JvmField val ply: Player) : AndroidCapability(ply } } + fun obliviate(refund: Boolean = true) { + if (refund) { + for (instance in research) { + if (instance.isResearched) { + instance.unResearch() + instance.refund() + } + } + } + + val copy = java.util.List.copyOf(features.values) + + for (feature in copy) { + removeFeature(feature.type) + } + } + override fun serializeNBT(): CompoundTag { val tag = super.serializeNBT() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt index 1c280876b..30e5c4d67 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt @@ -6,6 +6,8 @@ import net.minecraft.network.chat.TranslatableComponent import net.minecraft.server.level.ServerPlayer import net.minecraft.world.InteractionHand import net.minecraft.world.InteractionResultHolder +import net.minecraft.world.effect.MobEffectInstance +import net.minecraft.world.effect.MobEffects import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.player.Player import net.minecraft.world.item.* @@ -16,7 +18,51 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer enum class PillType { - BECOME_ANDROID, BECOME_HUMANE + BECOME_ANDROID, BECOME_HUMANE, OBLIVION +} + +class ItemPillHeal : Item(Properties().stacksTo(64).rarity(Rarity.UNCOMMON).tab(OverdriveThatMatters.CREATIVE_TAB)) { + override fun getUseDuration(p_41454_: ItemStack): Int { + return 24 + } + + override fun appendHoverText( + p_41421_: ItemStack, + p_41422_: Level?, + p_41423_: MutableList, + p_41424_: TooltipFlag + ) { + super.appendHoverText(p_41421_, p_41422_, p_41423_, p_41424_) + + p_41423_.add(TranslatableComponent("otm.pill.heal").withStyle(ChatFormatting.GRAY)) + p_41423_.add(TranslatableComponent("otm.pill.heal_android").withStyle(ChatFormatting.GRAY)) + } + + override fun use(level: Level, ply: Player, hand: InteractionHand): InteractionResultHolder { + val resolver = ply.getCapability(MatteryCapability.ANDROID).resolve() + + if (!resolver.isEmpty && resolver.get().isAndroid()) + return super.use(level, ply, hand) + + ply.startUsingItem(hand) + return InteractionResultHolder.consume(ply.getItemInHand(hand)) + } + + override fun finishUsingItem(stack: ItemStack, level: Level, ent: LivingEntity): ItemStack { + val resolver = ent.getCapability(MatteryCapability.ANDROID).resolve() + + if (!resolver.isEmpty && resolver.get().isAndroid()) + return super.finishUsingItem(stack, level, ent) + + stack.shrink(1) + ent.addEffect(MobEffectInstance(MobEffects.ABSORPTION, 20 * 60 * 2, 4)) + ent.addEffect(MobEffectInstance(MobEffects.REGENERATION, 20 * 8, 2)) + ent.heal(8f) + + return stack + } + + override fun getUseAnimation(p_41452_: ItemStack): UseAnim = UseAnim.EAT } class ItemPill(val pillType: PillType) : @@ -34,11 +80,15 @@ class ItemPill(val pillType: PillType) : ) { super.appendHoverText(p_41421_, p_41422_, p_41423_, p_41424_) - if (pillType == PillType.BECOME_ANDROID) { - p_41423_.add(TranslatableComponent("otm.pill.android").withStyle(ChatFormatting.GRAY)) - } else { - p_41423_.add(TranslatableComponent("otm.pill.humane").withStyle(ChatFormatting.GRAY)) - p_41423_.add(TranslatableComponent("otm.pill.warning").withStyle(ChatFormatting.RED)) + when (pillType) { + PillType.BECOME_ANDROID -> p_41423_.add(TranslatableComponent("otm.pill.android").withStyle(ChatFormatting.GRAY)) + + PillType.BECOME_HUMANE -> { + p_41423_.add(TranslatableComponent("otm.pill.humane").withStyle(ChatFormatting.GRAY)) + p_41423_.add(TranslatableComponent("otm.pill.warning").withStyle(ChatFormatting.RED)) + } + + PillType.OBLIVION -> p_41423_.add(TranslatableComponent("otm.pill.oblivion").withStyle(ChatFormatting.GRAY)) } } @@ -53,7 +103,11 @@ class ItemPill(val pillType: PillType) : val cap = resolver.get() as AndroidCapabilityPlayer - if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid() || pillType == PillType.BECOME_HUMANE && cap.isEverAndroid()) { + if ( + pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid() || + pillType == PillType.BECOME_HUMANE && cap.isEverAndroid() || + pillType == PillType.OBLIVION && cap.isAndroid() + ) { ply.startUsingItem(hand) return InteractionResultHolder.consume(ply.getItemInHand(hand)) } @@ -69,11 +123,20 @@ class ItemPill(val pillType: PillType) : val resolver = ent.getCapability(MatteryCapability.ANDROID).resolve() if (resolver.isEmpty || resolver.get() !is AndroidCapabilityPlayer) - return super.finishUsingItem(stack, level, ent); + return super.finishUsingItem(stack, level, ent) val cap = resolver.get() as AndroidCapabilityPlayer - if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid()) { + if (pillType == PillType.OBLIVION && cap.isAndroid()) { + if (!ent.abilities.instabuild) { + stack.shrink(1) + } + + if (ent is ServerPlayer) { + cap.obliviate() + ent.displayClientMessage(TranslatableComponent("otm.pill.message_oblivion").withStyle(ChatFormatting.GRAY), false) + } + } else if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid()) { if (ent.abilities.instabuild) { if (ent is ServerPlayer) { cap.becomeAndroid() 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 af2a00a9c..44428d1e4 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 @@ -3,7 +3,15 @@ "otm.pill.warning": "WARNING: This will INSTANTLY decommission you upon ingestion!", "otm.pill.android": "Take this pill and lose what is holding you back.", + "otm.pill.humane": "Take this pill and wake up in bed none the wiser.", + + "otm.pill.oblivion": "Items and Experience spent on research is fully refunded.", + "otm.pill.message_oblivion": "All android features are removed and all research refunded.", + + "otm.pill.heal": "Instantly restores 4 hearts upon ingestion, provides 2 min Absorption V and 8 seconds Regeneration III.", + "otm.pill.heal_android": "Does nothing to androids.", + "otm.pill.message": "Nothing happened, but you feel exhausted?.. Maybe get rest.", "otm.pill.message_finish": "§kONE OF US ONE OF US ONE OF US ONE OF US ONE OF US", @@ -187,6 +195,8 @@ "item.overdrive_that_matters.pill_android": "Android Pill", "item.overdrive_that_matters.pill_humane": "Humane Pill", + "item.overdrive_that_matters.pill_oblivion": "Android Factory Reset Pill", + "item.overdrive_that_matters.pill_heal": "Medical Pill", "item.overdrive_that_matters.portable_condensation_drive": "Portable Condensation Drive", "item.overdrive_that_matters.portable_dense_condensation_drive": "Portable Dense Condensation Drive",