This commit is contained in:
GearShocky 2025-03-16 13:20:21 +05:00
parent 24485696f3
commit 5e3fcddd34

View File

@ -11,26 +11,34 @@ import net.minecraft.sounds.SoundEvents
import net.minecraft.sounds.SoundSource import net.minecraft.sounds.SoundSource
import net.minecraft.util.Mth import net.minecraft.util.Mth
import net.minecraft.world.BossEvent import net.minecraft.world.BossEvent
import net.minecraft.world.phys.Vec3 import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.AnimationState import net.minecraft.world.entity.AnimationState
import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.AttributeSupplier import net.minecraft.world.entity.ai.attributes.AttributeSupplier
import net.minecraft.world.entity.ai.attributes.Attributes import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.ai.goal.* import net.minecraft.world.entity.ai.goal.Goal
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation import net.minecraft.world.entity.ai.navigation.GroundPathNavigation
import net.minecraft.world.entity.ai.navigation.PathNavigation import net.minecraft.world.entity.ai.navigation.PathNavigation
import net.minecraft.world.entity.monster.* import net.minecraft.world.entity.monster.AbstractIllager
import net.minecraft.world.entity.monster.AbstractSkeleton
import net.minecraft.world.entity.monster.Monster
import net.minecraft.world.entity.monster.Zombie
import net.minecraft.world.entity.npc.Villager import net.minecraft.world.entity.npc.Villager
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.entity.projectile.SmallFireball
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.phys.Vec3
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.isFire
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.* import java.util.*
import kotlin.math.cos
import kotlin.math.sin
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()
@ -48,6 +56,7 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
.add(Attributes.MOVEMENT_SPEED, 0.3) .add(Attributes.MOVEMENT_SPEED, 0.3)
.add(Attributes.STEP_HEIGHT, 1.0) .add(Attributes.STEP_HEIGHT, 1.0)
.add(Attributes.KNOCKBACK_RESISTANCE, 1.0) .add(Attributes.KNOCKBACK_RESISTANCE, 1.0)
.add(Attributes.FOLLOW_RANGE, 32.0)
} }
private val IS_CHARGING: EntityDataAccessor<Boolean> = private val IS_CHARGING: EntityDataAccessor<Boolean> =
SynchedEntityData.defineId(Enforcer::class.java, EntityDataSerializers.BOOLEAN) SynchedEntityData.defineId(Enforcer::class.java, EntityDataSerializers.BOOLEAN)
@ -79,6 +88,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)) goalSelector.addGoal(2, StayNearGoal(this))
goalSelector.addGoal(2, BlazeFireballGoal(this))
targetSelector.addGoal(1, HurtByTargetGoal(this)) targetSelector.addGoal(1, HurtByTargetGoal(this))
} }
@ -95,6 +105,18 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
override fun getDeathSound(): SoundEvent { override fun getDeathSound(): SoundEvent {
return SoundEvents.VAULT_BREAK return SoundEvents.VAULT_BREAK
} }
//fire inv
//there should be a better way
override fun isInvulnerableTo(source: DamageSource): Boolean {
return source.isFire || super.isInvulnerableTo(source)
}
override fun hurt(source: DamageSource, amount: Float): Boolean {
if (source.isFire) return false
return super.hurt(source, amount)
}
///boss healthbar ///boss healthbar
private val bossEvent: ServerBossEvent = private val bossEvent: ServerBossEvent =
ServerBossEvent(TranslatableComponent(MNames.ENFORCER), BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.PROGRESS) ServerBossEvent(TranslatableComponent(MNames.ENFORCER), BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.PROGRESS)
@ -114,17 +136,42 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
bossEvent.progress = this.health / this.maxHealth bossEvent.progress = this.health / this.maxHealth
} }
override fun die(cause: net.minecraft.world.damagesource.DamageSource) {
super.die(cause)
bossEvent.removeAllPlayers()
}
///
//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 //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 //WE ARE BEYOND THAT, THOSE ARE MY GREAT WAR-MACHINES
override fun getMaxHeadYRot(): Int { override fun getMaxHeadYRot(): Int {
return 180 return 180
} }
override fun die(cause: net.minecraft.world.damagesource.DamageSource) { fun shootFireball(math: Float) {
super.die(cause) if (level().isClientSide) return
bossEvent.removeAllPlayers()
val offset_dist = 1.4
val viewVector = this.getViewVector(1.0F).normalize()
val leftVec = Vec3(viewVector.z, 0.0, -viewVector.x).normalize().scale(offset_dist)
val gun_x = x + leftVec.x
val gun_z = z + leftVec.z
val gun_y = y + 1.2
//stfu idea i like my underscores
val fireballX = gun_x
val fireballY = gun_y
val fireballZ = gun_z
val fireball = SmallFireball(level(), fireballX, fireballY, fireballZ, viewVector)
fireball.shootFromRotation(this, this.xRot, this.yHeadRot, 0.0F, 1.5F, 0.2F)
fireball.setPos(fireballX, fireballY, fireballZ)
fireball.owner = this
level().addFreshEntity(fireball)
} }
///
//charge attack, could possibly leave a smoke trail too idk //charge attack, could possibly leave a smoke trail too idk
class RammingGoal(private val mob: Enforcer) : Goal() { class RammingGoal(private val mob: Enforcer) : Goal() {
@ -238,7 +285,7 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
target.push(knockback.x, 0.5, knockback.z) target.push(knockback.x, 0.5, knockback.z)
val damageAmount = 6.0f val damageAmount = 10.0f
target.hurt(mob.damageSources().mobAttack(mob), damageAmount) target.hurt(mob.damageSources().mobAttack(mob), damageAmount)
stop() stop()
@ -298,4 +345,54 @@ class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
mob.navigation.moveTo(movePos!!.x, movePos!!.y, movePos!!.z, 1.5) mob.navigation.moveTo(movePos!!.x, movePos!!.y, movePos!!.z, 1.5)
} }
} }
class BlazeFireballGoal(private val mob: Enforcer) : Goal() {
private var cooldown = 0
private var fireTick = 0
init {
setFlags(EnumSet.of(Goal.Flag.LOOK))
}
override fun canUse(): Boolean {
return mob.target != null && !mob.isCharging()
}
override fun canContinueToUse(): Boolean {
return canUse()
}
override fun tick() {
val target = mob.target ?: return
mob.lookControl.setLookAt(target, 30.0f, 30.0f)
if (cooldown > 0) {
fireTick = 20
cooldown--
return
}
if (fireTick > 0){
fireTick --
if (fireTick == 15){
mob.shootFireball(0.5f)
//could have a better firing sound
mob.playSound(SoundEvents.BLAZE_SHOOT, 1.0f, 1.0f)
}
if (fireTick == 10){
mob.shootFireball(0.5f)
mob.playSound(SoundEvents.BLAZE_SHOOT, 1.0f, 1.0f)
}
if (fireTick == 5){
mob.shootFireball(0.5f)
mob.playSound(SoundEvents.BLAZE_SHOOT, 1.0f, 1.0f)
}
return
} else {
cooldown = 5 + mob.random.nextInt(10)
}
}
}
} }