Androids now get damaged without spacesuits on planets without atmosphere

This commit is contained in:
DBotThePony 2023-03-14 17:36:23 +07:00
parent 2c745a302f
commit 34aaab371e
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 89 additions and 7 deletions

View File

@ -334,6 +334,7 @@ private fun death(provider: MatteryLanguageProvider) {
death("otm_event_horizon", "%1\$s never crossed the event horizon")
death("otm_hawking_radiation", "%1\$s discovered Hawking radiation")
death("otm_emp", "%1\$s electronics' fried")
death("otm_cosmic_rays", "%1\$s electronics' got scrambled by cosmic radiation")
death("otm_become_android.player", "%1\$s lost their humanity whilst %2\$s tried to reason with them")
death("otm_become_humane.player", "%1\$s gained their humanity whilst %2\$s tried to reason with them")

View File

@ -341,6 +341,7 @@ private fun death(provider: MatteryLanguageProvider) {
death("otm_event_horizon", "%1\$s никогда не пересёк горизонт событий")
death("otm_hawking_radiation", "%1\$s открыл излучение Хокинга")
death("otm_emp", "Электроника %1\$s перегорела")
death("otm_cosmic_rays", "Электроника %1\$s была ошеломлена космическим излучением")
death("otm_become_android.player", "%1\$s потерял свою человечность, когда %2\$s пытался образумить их")
death("otm_become_humane.player", "%1\$s восстановил свою человечность, когда %2\$s пытался образумить их")

View File

@ -201,6 +201,7 @@ public final class OverdriveThatMatters {
if (AdAstraCompatKt.isAdAstraLoaded()) {
EVENT_BUS.addListener(EventPriority.NORMAL, AdAstraCompatKt::onDamageEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, AdAstraCompatKt::onMatteryTick);
}
}

View File

@ -1,8 +1,7 @@
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
import earth.terrarium.ad_astra.common.data.Planet;
import earth.terrarium.ad_astra.common.data.PlanetData;
import earth.terrarium.ad_astra.common.entity.system.EntityTemperatureSystem;
import earth.terrarium.ad_astra.common.util.ModUtils;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
import org.spongepowered.asm.mixin.Mixin;
@ -21,7 +20,7 @@ public class EntityTemperatureSystemMixin {
remap = false
)
private static void temperatureTick(LivingEntity entity, ServerLevel level, CallbackInfo hook) {
if (ServerCompatConfig.AdAstra.INSTANCE.getWHATS_UP_WITH_TEMPERATURE() && !PlanetData.getPlanetFromLevel(level.dimension()).map(Planet::hasAtmosphere).orElse(true)) {
if (ServerCompatConfig.AdAstra.INSTANCE.getWHATS_UP_WITH_TEMPERATURE() && !ModUtils.planetHasAtmosphere(level)) {
hook.cancel();
}
}

View File

@ -21,8 +21,10 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.ProjectileWeaponItem
import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse
import net.minecraft.world.level.Level
import net.minecraft.world.phys.Vec3
import net.minecraftforge.common.ForgeHooks
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.INBTSerializable
@ -80,6 +82,32 @@ import kotlin.collections.HashMap
@Suppress("unused")
class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerializable<CompoundTag> {
/**
* This event is fired on main event bus before ticking logic takes place.
*
* Cancelling it is probably not a good idea, but you can do it anyway.
*/
data class PreTick(val capability: MatteryPlayerCapability) : Event() {
override fun isCancelable() = true
override fun hasResult() = false
override fun setResult(value: Result) {}
val player get() = capability.ply
val level: Level get() = capability.ply.level
}
/**
* This event is fired on main event bus after ticking logic took place.
*/
data class PostTick(val capability: MatteryPlayerCapability) : Event() {
override fun isCancelable() = false
override fun hasResult() = false
override fun setResult(value: Result) {}
val player get() = capability.ply
val level: Level get() = capability.ply.level
}
private inner class PlayerMatteryContainer(size: Int) : MatteryContainer(size) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
@ -777,6 +805,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
private fun tick() {
if (!ply.isAlive) return
PreTick(this).also {
MinecraftForge.EVENT_BUS.post(it)
if (it.isCanceled) return
}
ticksIExist++
if (willBecomeAndroid) {
@ -930,6 +963,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
}
tickInventory()
PostTick(this).also {
MinecraftForge.EVENT_BUS.post(it)
}
}
private val resolver = LazyOptional.of { this }

View File

@ -1,12 +1,18 @@
package ru.dbotthepony.mc.otm.compat.adastra
import earth.terrarium.ad_astra.AdAstra
import earth.terrarium.ad_astra.common.data.PlanetData
import earth.terrarium.ad_astra.common.item.armor.SpaceSuit
import earth.terrarium.ad_astra.common.registry.ModDamageSource
import earth.terrarium.ad_astra.common.util.ModUtils
import net.minecraft.world.entity.player.Player
import net.minecraftforge.event.entity.living.LivingHurtEvent
import net.minecraftforge.fml.ModList
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.config.ServerCompatConfig
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
val isAdAstraLoaded by lazy {
ModList.get().isLoaded(AdAstra.MOD_ID)
@ -26,3 +32,23 @@ fun onDamageEvent(event: LivingHurtEvent) {
}
}
}
fun onMatteryTick(event: MatteryPlayerCapability.PostTick) {
check(isAdAstraLoaded) { "Ad Astra is not loaded!" }
if (
ServerCompatConfig.AdAstra.ANDROID_COSMIC_RAYS &&
!event.player.abilities.invulnerable &&
event.capability.isAndroid &&
!ModUtils.planetHasAtmosphere(event.level)
) {
val rand = event.level.random
val noSpacesuits = event.player.armorSlots.count { it.item !is SpaceSuit }
val yesTritanium = if (!ServerCompatConfig.AdAstra.TRITANIUM_ARMOR_PROTECTS_AGAINST_COSMIC_RAYS) 0.0 else event.player.armorSlots.count { it.item in MItems.TRITANIUM_ARMOR } * 0.5
if (rand.nextDouble() <= (noSpacesuits - yesTritanium) * ServerCompatConfig.AdAstra.ANDROID_COSMIC_RAYS_CHANCE) {
event.player.hurt(MRegistry.DAMAGE_COSMIC_RAYS, 1f)
}
}
}

View File

@ -15,6 +15,20 @@ object ServerCompatConfig : AbstractConfig("compat-server") {
.comment("I attended physics classes in middle school, and this kills me.")
.define("WHATS_UP_WITH_TEMPERATURE", true)
val ANDROID_COSMIC_RAYS: Boolean by builder
.comment("Androids without spacesuit will get damaged over time by cosmic radiation")
.comment("on planets without atmosphere.")
.define("ANDROID_COSMIC_RAYS", true)
val ANDROID_COSMIC_RAYS_CHANCE: Double by builder
.comment("Chance in percent android will be damaged this tick per missing piece of spacesuit")
.comment("Max chance in tick of damage is this value multiplied by 4 (spacesuit is completely missing)")
.defineInRange("ANDROID_COSMIC_RAYS_CHANCE", 0.015, 0.0, 1.0)
val TRITANIUM_ARMOR_PROTECTS_AGAINST_COSMIC_RAYS: Boolean by builder
.comment("Should androids get half protection from cosmic rays per piece of tritanium armor")
.define("TRITANIUM_ARMOR_PROTECTS_AGAINST_COSMIC_RAYS", true)
init {
builder.pop()
}

View File

@ -138,7 +138,7 @@ class ImmutableDamageSource(private val parent: DamageSource) : DamageSource(par
}
}
abstract class MatteryDamageSource(name: String, private val entity: Entity? = null, private val inflictor: ItemStack? = null) : DamageSource(name) {
abstract class MatteryDamageSource(name: String, private val entity: Entity? = null, val inflictor: ItemStack? = null) : DamageSource(name) {
override fun getLocalizedDeathMessage(victim: LivingEntity): Component {
val itemStack = inflictor ?: (entity as LivingEntity?)?.mainHandItem ?: ItemStack.EMPTY

View File

@ -192,6 +192,10 @@ object MRegistry {
const val DAMAGE_EVENT_HORIZON_ID = "otm_event_horizon"
const val DAMAGE_HAWKING_RADIATION_ID = "otm_hawking_radiation"
const val DAMAGE_EXOPACK_PROBE_ID = "otm_exopack_probe"
const val DAMAGE_EMP_NAME = "otm_emp"
const val DAMAGE_SHOCKWAVE_NAME = "otm_shockwave"
const val DAMAGE_PLASMA_NAME = "otm_plasma"
const val DAMAGE_COSMIC_RAYS_NAME = "otm_cosmic_rays"
val DAMAGE_EXOPACK_PROBE = ImmutableDamageSource(DamageSource(DAMAGE_EXOPACK_PROBE_ID).bypassArmor().bypassMagic())
@ -199,9 +203,8 @@ object MRegistry {
val DAMAGE_BECOME_HUMANE = ImmutableDamageSource(DamageSource(DAMAGE_BECOME_HUMANE_ID).bypassArmor().bypassInvul().bypassMagic())
val DAMAGE_EVENT_HORIZON = ImmutableDamageSource(DamageSource(DAMAGE_EVENT_HORIZON_ID).bypassMagic().bypassArmor())
val DAMAGE_HAWKING_RADIATION = ImmutableDamageSource(DamageSource(DAMAGE_HAWKING_RADIATION_ID))
const val DAMAGE_EMP_NAME = "otm_emp"
const val DAMAGE_SHOCKWAVE_NAME = "otm_shockwave"
const val DAMAGE_PLASMA_NAME = "otm_plasma"
val DAMAGE_COSMIC_RAYS = ImmutableDamageSource(DamageSource(DAMAGE_COSMIC_RAYS_NAME).bypassArmor().bypassMagic())
val DAMAGE_EMP: DamageSource = ImmutableDamageSource(EMPDamageSource())
val TRITANIUM_STRIPED_BLOCK = StripedColoredDecorativeBlock(MNames.TRITANIUM_STRIPED_BLOCK, { colorA, _ ->