Compare commits

...

3 Commits

6 changed files with 187 additions and 10 deletions

View File

@ -0,0 +1,4 @@
kotlin version: 2.0.10
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

View File

@ -1,6 +1,9 @@
package ru.dbotthepony.mc.otm.entity package ru.dbotthepony.mc.otm.entity
import net.minecraft.core.particles.ParticleTypes import net.minecraft.core.particles.ParticleTypes
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.network.syncher.EntityDataSerializers
import net.minecraft.network.syncher.SynchedEntityData
import net.minecraft.server.level.ServerBossEvent import net.minecraft.server.level.ServerBossEvent
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.sounds.SoundEvent import net.minecraft.sounds.SoundEvent
@ -27,14 +30,43 @@ import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents import ru.dbotthepony.mc.otm.registry.game.MSoundEvents
import java.util.*
class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) { class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
val idleState = AnimationState() val idleState = AnimationState()
val chargeState = AnimationState() val chargeState = AnimationState()
init { init {
idleState.start(tickCount) idleState.start(tickCount)
} }
companion object {
fun createAttributes() : AttributeSupplier.Builder {
return createMonsterAttributes()
.add(Attributes.MAX_HEALTH, 300.0)
.add(Attributes.ARMOR, 20.0)
.add(Attributes.MOVEMENT_SPEED, 0.3)
.add(Attributes.STEP_HEIGHT, 1.0)
.add(Attributes.KNOCKBACK_RESISTANCE, 1.0)
}
private val IS_CHARGING: EntityDataAccessor<Boolean> =
SynchedEntityData.defineId(Enforcer::class.java, EntityDataSerializers.BOOLEAN)
}
override fun defineSynchedData(builder: SynchedEntityData.Builder) {
super.defineSynchedData(builder)
builder.define(IS_CHARGING, false)
}
fun setCharging(value: Boolean) {
entityData.set(IS_CHARGING, value)
}
fun isCharging(): Boolean {
return entityData.get(IS_CHARGING)
}
override fun registerGoals() { override fun registerGoals() {
goalSelector.addGoal(7, LookAtPlayerGoal(this, Player::class.java, 8f)) goalSelector.addGoal(7, LookAtPlayerGoal(this, Player::class.java, 8f))
goalSelector.addGoal(3, NearestAttackableTargetGoal(this, LivingEntity::class.java, 10, true, true) { entity -> goalSelector.addGoal(3, NearestAttackableTargetGoal(this, LivingEntity::class.java, 10, true, true) { entity ->
@ -46,6 +78,7 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
}) })
goalSelector.addGoal(2, RammingGoal(this)) goalSelector.addGoal(2, RammingGoal(this))
goalSelector.addGoal(2, StayNearGoal(this))
targetSelector.addGoal(1, HurtByTargetGoal(this)) targetSelector.addGoal(1, HurtByTargetGoal(this))
} }
@ -81,6 +114,12 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
bossEvent.progress = this.health / this.maxHealth bossEvent.progress = this.health / this.maxHealth
} }
//this stuff removes 180-degree head rotation limits that minecraft mobs have, since this is a turret on a tank, we don't need such limits
//WE ARE BEYOND THAT, THOSE ARE MY GREAT WAR-MACHINES
override fun getMaxHeadYRot(): Int {
return 180
}
override fun die(cause: net.minecraft.world.damagesource.DamageSource) { override fun die(cause: net.minecraft.world.damagesource.DamageSource) {
super.die(cause) super.die(cause)
bossEvent.removeAllPlayers() bossEvent.removeAllPlayers()
@ -91,6 +130,10 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
class RammingGoal(private val mob: Enforcer) : Goal() { class RammingGoal(private val mob: Enforcer) : Goal() {
private var target: LivingEntity? = null private var target: LivingEntity? = null
init {
setFlags(EnumSet.of(Goal.Flag.MOVE))
}
private var chargeTime = 0 private var chargeTime = 0
private val windupTime = 20 private val windupTime = 20
private val maxChargeTime = 40 private val maxChargeTime = 40
@ -115,12 +158,12 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
} }
override fun start() { override fun start() {
mob.setCharging(true)
mob.playSound(MSoundEvents.ENFORCER_ALERT, 1.0f, 1.0f) mob.playSound(MSoundEvents.ENFORCER_ALERT, 1.0f, 1.0f)
chargeTime = 0 chargeTime = 0
mob.navigation.stop() mob.navigation.stop()
cooldown = minCooldown + mob.random.nextInt(maxCooldown - minCooldown) cooldown = minCooldown + mob.random.nextInt(maxCooldown - minCooldown)
isCharging = true isCharging = true
mob.chargeState.start(mob.tickCount) mob.chargeState.start(mob.tickCount)
} }
@ -203,23 +246,56 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
} }
override fun stop() { override fun stop() {
mob.setCharging(false)
mob.setDeltaMovement(Vec3.ZERO) mob.setDeltaMovement(Vec3.ZERO)
chargeTime = 0 chargeTime = 0
chargeDir = null chargeDir = null
isCharging = false isCharging = false
mob.chargeState.stop() mob.chargeState.stop()
} }
} }
companion object { class StayNearGoal(private val mob: Enforcer) : Goal() {
fun createAttributes() : AttributeSupplier.Builder { private var target: LivingEntity? = null
return createMonsterAttributes() private var moveCD = 0
.add(Attributes.MAX_HEALTH, 300.0) private var movePos: Vec3? = null
.add(Attributes.ARMOR, 20.0)
.add(Attributes.MOVEMENT_SPEED, 0.3) override fun canUse(): Boolean {
.add(Attributes.STEP_HEIGHT, 1.0) return mob.target != null && !mob.isCharging()
.add(Attributes.KNOCKBACK_RESISTANCE, 1.0) }
override fun canContinueToUse(): Boolean {
return canUse()
}
override fun start() {
target = mob.target
moveCD = 0
}
override fun tick() {
mob.lookControl.setLookAt(target, 30.0f, 30.0f)
val target = mob.target ?: return
if (moveCD > 0) {
moveCD--
return
}
moveCD = 10 + mob.random.nextInt(10)
val targetX = target.x
val targetZ = target.z
val angle = mob.random.nextDouble() * Math.PI * 2
val distance = 8.0 + mob.random.nextDouble() * 3.0
val offsetX = Math.cos(angle) * distance
val offsetZ = Math.sin(angle) * distance
movePos = Vec3(targetX + offsetX, target.y + 2.0, targetZ + offsetZ)
mob.navigation.moveTo(movePos!!.x, movePos!!.y, movePos!!.z, 1.5)
} }
} }
} }

View File

@ -57,6 +57,7 @@ class Loader(type: EntityType<Loader>, level: Level) : Monster(type, level) {
super.defineSynchedData(builder) super.defineSynchedData(builder)
builder.define(DATA_ATTACKING, false) builder.define(DATA_ATTACKING, false)
} }
var isAttacking: Boolean var isAttacking: Boolean
get() = this.entityData.get(DATA_ATTACKING) get() = this.entityData.get(DATA_ATTACKING)
set(value) { set(value) {

View File

@ -0,0 +1,90 @@
package ru.dbotthepony.mc.otm.entity
import net.minecraft.core.particles.ParticleTypes
import net.minecraft.network.syncher.SynchedEntityData
import net.minecraft.world.damagesource.DamageTypes
import net.minecraft.world.entity.projectile.Projectile
import net.minecraft.world.entity.projectile.ProjectileUtil
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.LevelEvent
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.phys.EntityHitResult
import net.minecraft.world.phys.HitResult
import net.neoforged.neoforge.event.EventHooks
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import ru.dbotthepony.mc.otm.registry.game.MEntityTypes
import ru.dbotthepony.mc.otm.registry.MatteryDamageSource
class RocketProjectile(level: Level) : Projectile(MEntityTypes.PLASMA, level) {
var inflictor: ItemStack? = null
var damage = 6.0f
var ttl = 200
override fun defineSynchedData(p_326003_: SynchedEntityData.Builder) {
}
override fun onHit(p_37260_: HitResult) {
super.onHit(p_37260_)
if (!level().isClientSide) {
discard()
}
}
override fun onHitEntity(p_37259_: EntityHitResult) {
super.onHitEntity(p_37259_)
if (!level().isClientSide) {
p_37259_.entity.hurt(MatteryDamageSource(level().registryAccess().damageType(DamageTypes.EXPLOSION), owner, inflictor), damage)
level().explode(this, x, y, z, 2.5f, Level.ExplosionInteraction.BLOCK)
}
}
override fun onHitBlock(p_37258_: BlockHitResult) {
super.onHitBlock(p_37258_)
}
override fun tick() {
if (--ttl <= 0) {
discard()
return
}
super.tick()
val trace = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity)
if (trace.type == HitResult.Type.BLOCK) {
val pos = (trace as BlockHitResult).blockPos
val state = level().getBlockState(pos)
level().explode(this, x, y, z, 2.5f, Level.ExplosionInteraction.BLOCK)
if (state.`is`(Blocks.NETHER_PORTAL) || state.`is`(Blocks.END_GATEWAY)) {
onHitBlock(trace)
// don't teleport plasma projectile
if (!level().isClientSide)
discard()
return
}
}
if (trace.type != HitResult.Type.MISS && !EventHooks.onProjectileImpact(this, trace)) {
onHit(trace)
}
checkInsideBlocks()
val x = x + deltaMovement.x
val y = y + deltaMovement.y
val z = z + deltaMovement.z
setPos(x, y, z)
}
}

View File

@ -333,6 +333,8 @@ object MNames {
// entities // entities
const val PLASMA = "plasma_projectile" const val PLASMA = "plasma_projectile"
const val ROCKET = "rocket_projectile"
const val RIDEABLE_DUMMY = "rideable_dummy" const val RIDEABLE_DUMMY = "rideable_dummy"
const val BREAD_MONSTER = "bread_monster" const val BREAD_MONSTER = "bread_monster"
const val LOADER = "loader" const val LOADER = "loader"

View File

@ -25,6 +25,10 @@ object MEntityTypes {
EntityType.Builder.of({ _, level -> PlasmaProjectile(level) }, MobCategory.MISC).sized(0.4f, 0.4f).build(MNames.PLASMA) EntityType.Builder.of({ _, level -> PlasmaProjectile(level) }, MobCategory.MISC).sized(0.4f, 0.4f).build(MNames.PLASMA)
} }
val ROCKET: EntityType<RocketProjectile> by registry.register(MNames.ROCKET) {
EntityType.Builder.of({ _, level -> RocketProjectile(level) }, MobCategory.MISC).sized(0.4f, 0.4f).build(MNames.ROCKET)
}
val CARGO_CRATE_MINECARTS: Map<DyeColor?, EntityType<MinecartCargoCrate>> = registry.coloredWithBase(MNames.MINECART_CARGO_CRATE) { color -> val CARGO_CRATE_MINECARTS: Map<DyeColor?, EntityType<MinecartCargoCrate>> = registry.coloredWithBase(MNames.MINECART_CARGO_CRATE) { color ->
EntityType.Builder.of({ it, level -> MinecartCargoCrate(it, color, level)}, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8).build("dfu doesn't works ✅") EntityType.Builder.of({ it, level -> MinecartCargoCrate(it, color, level)}, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8).build("dfu doesn't works ✅")