Enforcer WIP
This commit is contained in:
parent
c323f70a97
commit
d2371b03f6
1
src/bb/enforcer.bbmodel
Normal file
1
src/bb/enforcer.bbmodel
Normal file
File diff suppressed because one or more lines are too long
@ -127,6 +127,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
|
||||
|
||||
provider.generated(MItems.BREAD_MONSTER_SPAWN_EGG, modLocation("item/egg/bread_monster"))
|
||||
provider.generated(MItems.LOADER_SPAWN_EGG, modLocation("item/egg/loader"))
|
||||
provider.generated(MItems.CLEANER_DRONE_KIT, modLocation("item/egg/cleaner"))
|
||||
provider.generated(MItems.ANDROID_MELEE_SPAWN_EGG, modLocation("item/egg/android_melee"))
|
||||
|
||||
provider.generatedTiered(MItems.BATTERIES, "battery_tier")
|
||||
|
@ -952,6 +952,9 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
add(MItems.LOADER_SPAWN_EGG, "Loader Spawn Egg")
|
||||
add(MEntityTypes.LOADER, "Loader")
|
||||
|
||||
add(MItems.CLEANER_DRONE_KIT, "Cleaner Drone Kit")
|
||||
add(MEntityTypes.CLEANER, "Cleaner Drone")
|
||||
|
||||
add(MItems.ANDROID_MELEE_SPAWN_EGG, "Melee Android Spawn Egg")
|
||||
add(MEntityTypes.ANDROID_MELEE, "Melee Android")
|
||||
}
|
||||
|
@ -945,6 +945,9 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
add(MItems.LOADER_SPAWN_EGG, "Яйцо призыва погрузчика")
|
||||
add(MEntityTypes.LOADER, "Погрузчик")
|
||||
|
||||
add(MItems.CLEANER_DRONE_KIT, "Набор Дрона-уборщика")
|
||||
add(MEntityTypes.CLEANER, "Дрон-уборщик")
|
||||
|
||||
add(MItems.ANDROID_MELEE_SPAWN_EGG, "Яйцо призыва андроида ближнего боя")
|
||||
add(MEntityTypes.ANDROID_MELEE, "Андроид ближнего боя")
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
package ru.dbotthepony.mc.otm.client.animation;
|
||||
|
||||
import net.minecraft.client.animation.AnimationChannel;
|
||||
import net.minecraft.client.animation.AnimationDefinition;
|
||||
import net.minecraft.client.animation.Keyframe;
|
||||
import net.minecraft.client.animation.KeyframeAnimations;
|
||||
|
||||
public class EnforcerAnimation {
|
||||
public static final AnimationDefinition CHARGE = AnimationDefinition.Builder.withLength(0.0F).looping()
|
||||
.addAnimation("root", new AnimationChannel(AnimationChannel.Targets.POSITION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.posVec(0.0F, -1.0F, 0.0F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.addAnimation("Body", new AnimationChannel(AnimationChannel.Targets.ROTATION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.degreeVec(7.5F, 0.0F, 0.0F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.addAnimation("leg_FL", new AnimationChannel(AnimationChannel.Targets.ROTATION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.degreeVec(0.3244F, 25.5371F, -4.9817F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.addAnimation("leg_FR", new AnimationChannel(AnimationChannel.Targets.ROTATION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.degreeVec(0.5426F, -23.0465F, 4.9996F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.addAnimation("leg_BR", new AnimationChannel(AnimationChannel.Targets.ROTATION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.degreeVec(-0.3244F, 25.5371F, 4.9817F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.addAnimation("leg_BL", new AnimationChannel(AnimationChannel.Targets.ROTATION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.degreeVec(-0.3244F, -25.5371F, -4.9817F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.build();
|
||||
|
||||
public static final AnimationDefinition IDLE = AnimationDefinition.Builder.withLength(0.12F).looping()
|
||||
.addAnimation("Body", new AnimationChannel(AnimationChannel.Targets.POSITION,
|
||||
new Keyframe(0.0F, KeyframeAnimations.posVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.LINEAR),
|
||||
new Keyframe(0.12F, KeyframeAnimations.posVec(0.0F, -0.2F, 0.0F), AnimationChannel.Interpolations.LINEAR)
|
||||
))
|
||||
.build();
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package ru.dbotthepony.mc.otm.client.model.entity;
|
||||
|
||||
import net.minecraft.client.model.HierarchicalModel;
|
||||
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.*;
|
||||
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import ru.dbotthepony.mc.otm.client.animation.EnforcerAnimation;
|
||||
import ru.dbotthepony.mc.otm.client.animation.LoaderAnimation;
|
||||
import ru.dbotthepony.mc.otm.entity.Enforcer;
|
||||
import ru.dbotthepony.mc.otm.registry.MNames;
|
||||
|
||||
import static ru.dbotthepony.mc.otm.OverdriveThatMatters.loc;
|
||||
|
||||
public class EnforcerModel {
|
||||
public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(loc(MNames.ENFORCER), "main");
|
||||
|
||||
private static HierarchicalModel<Enforcer> model;
|
||||
private static LayerDefinition def;
|
||||
|
||||
public static HierarchicalModel<Enforcer> getModel() {
|
||||
if (def == null) {
|
||||
def = createBodyLayer();
|
||||
}
|
||||
|
||||
if (model == null) {
|
||||
return model = new EnforcerHierarchicalModel<>(def.bakeRoot());
|
||||
}
|
||||
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
public static LayerDefinition createBodyLayer() {
|
||||
MeshDefinition meshdefinition = new MeshDefinition();
|
||||
PartDefinition partdefinition = meshdefinition.getRoot();
|
||||
|
||||
PartDefinition root = partdefinition.addOrReplaceChild("root", CubeListBuilder.create(), PartPose.offset(0.0F, 25.0F, 0.0F));
|
||||
|
||||
PartDefinition cube_r1 = root.addOrReplaceChild("cube_r1", CubeListBuilder.create().texOffs(178, 168).addBox(0.0F, -18.5F, -1.0F, 0.0F, 19.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(8.0F, -41.5F, 8.0F, -0.1745F, 0.0F, 0.0F));
|
||||
|
||||
PartDefinition base = root.addOrReplaceChild("base", CubeListBuilder.create().texOffs(140, 104).addBox(-8.0F, -4.0F, -7.0F, 16.0F, 5.0F, 14.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(92, 33).addBox(-5.0F, -2.0F, -10.0F, 10.0F, 14.0F, 20.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, -22.0F, 0.0F));
|
||||
|
||||
PartDefinition Body = base.addOrReplaceChild("Body", CubeListBuilder.create().texOffs(80, 76).addBox(-11.0F, -17.4F, 10.9F, 22.0F, 14.0F, 14.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(0, 0).addBox(-12.0F, -15.4F, -11.1F, 24.0F, 16.0F, 22.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(0, 38).addBox(-12.0F, -15.4F, -11.1F, 24.0F, 16.0F, 22.0F, new CubeDeformation(0.5F))
|
||||
.texOffs(122, 168).addBox(12.0F, -13.4F, -6.1F, 2.0F, 12.0F, 12.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(150, 168).addBox(-14.0F, -13.4F, -6.1F, 2.0F, 12.0F, 12.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, -4.6F, 0.1F));
|
||||
|
||||
PartDefinition Head = Body.addOrReplaceChild("Head", CubeListBuilder.create().texOffs(92, 67).addBox(-4.0F, -3.0F, -1.0F, 7.0F, 3.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offset(-4.0F, 1.6F, -11.1F));
|
||||
|
||||
PartDefinition rocket = Body.addOrReplaceChild("rocket", CubeListBuilder.create().texOffs(0, 76).addBox(-12.0F, -10.5F, -14.0F, 12.0F, 21.0F, 28.0F, new CubeDeformation(0.0F)), PartPose.offset(-14.0F, -7.9F, -0.1F));
|
||||
|
||||
PartDefinition flamethrower = Body.addOrReplaceChild("flamethrower", CubeListBuilder.create().texOffs(44, 168).addBox(-0.25F, -5.2654F, -4.9728F, 10.0F, 10.0F, 10.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(92, 0).addBox(2.75F, 1.7346F, -13.9728F, 10.0F, 10.0F, 23.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(84, 168).addBox(4.75F, 3.7346F, -26.9728F, 6.0F, 6.0F, 13.0F, new CubeDeformation(0.0F)), PartPose.offset(14.25F, -7.1346F, -0.1272F));
|
||||
|
||||
PartDefinition cube_r2 = flamethrower.addOrReplaceChild("cube_r2", CubeListBuilder.create().texOffs(152, 33).addBox(-4.0F, -4.0F, 0.5F, 8.0F, 8.0F, 15.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(7.75F, 5.7346F, 6.5272F, 0.5236F, 0.0F, 0.0F));
|
||||
|
||||
PartDefinition leg_FL = root.addOrReplaceChild("leg_FL", CubeListBuilder.create().texOffs(158, 0).addBox(-4.5F, -5.5F, -9.5F, 9.0F, 11.0F, 13.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(80, 104).addBox(-5.5F, -2.5F, -24.5F, 11.0F, 13.0F, 19.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(9.5F, -13.5F, -6.5F, 0.1047F, -0.5061F, -0.0349F));
|
||||
|
||||
PartDefinition leg_FR = root.addOrReplaceChild("leg_FR", CubeListBuilder.create().texOffs(0, 125).addBox(-5.5F, -2.5F, -24.5F, 11.0F, 13.0F, 19.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(152, 80).addBox(-4.5F, -5.5F, -9.5F, 9.0F, 11.0F, 13.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-9.5F, -13.5F, -6.5F, 0.1047F, 0.5061F, 0.0349F));
|
||||
|
||||
PartDefinition leg_BL = root.addOrReplaceChild("leg_BL", CubeListBuilder.create().texOffs(60, 136).addBox(-5.5F, -2.1667F, 5.1667F, 11.0F, 13.0F, 19.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(199, 24).addBox(-4.5F, -7.1667F, 13.1667F, 9.0F, 11.0F, 13.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(0, 157).addBox(-4.5F, -5.1667F, -3.8333F, 9.0F, 11.0F, 13.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(9.5F, -13.8333F, 6.8333F, -0.1047F, 0.5061F, -0.0349F));
|
||||
|
||||
PartDefinition leg_BR = root.addOrReplaceChild("leg_BR", CubeListBuilder.create().texOffs(152, 56).addBox(-4.5F, -5.1667F, -3.1667F, 9.0F, 11.0F, 13.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(120, 136).addBox(-5.5F, -2.1667F, 5.8333F, 11.0F, 13.0F, 19.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(202, 0).addBox(-4.5F, -7.1667F, 13.8333F, 9.0F, 11.0F, 13.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-9.5F, -13.8333F, 6.1667F, -0.1047F, -0.5061F, 0.0349F));
|
||||
|
||||
model = null;
|
||||
return def = LayerDefinition.create(meshdefinition, 256, 256);
|
||||
}
|
||||
|
||||
private static class EnforcerHierarchicalModel<T extends Enforcer> extends HierarchicalModel<T> {
|
||||
private final ModelPart root;
|
||||
private final ModelPart base;
|
||||
private final ModelPart Body;
|
||||
private final ModelPart Head;
|
||||
private final ModelPart rocket;
|
||||
private final ModelPart flamethrower;
|
||||
public EnforcerHierarchicalModel(ModelPart root) {
|
||||
this.root = root.getChild("root");
|
||||
this.base = this.root.getChild("base");
|
||||
this.Body = this.base.getChild("Body");
|
||||
this.Head = this.Body.getChild("Head");
|
||||
this.rocket = this.Body.getChild("rocket");
|
||||
this.flamethrower = this.Body.getChild("flamethrower");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(@NotNull T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
|
||||
this.root().getAllParts().forEach(ModelPart::resetPose);
|
||||
|
||||
this.Body.getChild("Head").xRot = headPitch * ((float) Math.PI / 180F);
|
||||
this.base.getChild("Body").yRot = netHeadYaw * ((float) Math.PI / 180F);
|
||||
|
||||
this.Body.getChild("rocket").xRot = headPitch * ((float) Math.PI / 180F);
|
||||
this.Body.getChild("flamethrower").xRot = headPitch * ((float) Math.PI / 180F);
|
||||
|
||||
|
||||
//this.animate(entity.getChargeState(), EnforcerAnimation.CHARGE, ageInTicks, 1.0F);
|
||||
this.animateWalk(EnforcerAnimation.CHARGE, limbSwing, limbSwingAmount, 0.8F, 2.5F);
|
||||
this.animate(entity.getIdleState(), EnforcerAnimation.IDLE, ageInTicks, 1.0F);
|
||||
|
||||
}
|
||||
|
||||
public ModelPart getHead() {
|
||||
return this.Body.getChild("Head");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull ModelPart root() {
|
||||
return this.root;
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(EntityRenderersEvent.RegisterLayerDefinitions event) {
|
||||
event.registerLayerDefinition(LAYER_LOCATION, EnforcerModel::createBodyLayer);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package ru.dbotthepony.mc.otm.client.render.entity
|
||||
|
||||
import net.minecraft.client.model.HierarchicalModel
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider
|
||||
import net.minecraft.client.renderer.entity.MobRenderer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters.loc
|
||||
import ru.dbotthepony.mc.otm.client.model.entity.EnforcerModel
|
||||
import ru.dbotthepony.mc.otm.entity.Enforcer
|
||||
|
||||
class EnforcerRenderer(context: EntityRendererProvider.Context)
|
||||
: MobRenderer<Enforcer, HierarchicalModel<Enforcer>>(context, EnforcerModel.getModel(), 2.2f) {
|
||||
override fun getTextureLocation(entity: Enforcer): ResourceLocation = TEXTURE_LOCATION
|
||||
|
||||
companion object {
|
||||
private val TEXTURE_LOCATION = loc("textures/entity/enforcer.png")
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.entity
|
||||
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.AnimationState
|
||||
@ -7,6 +9,7 @@ import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal
|
||||
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal
|
||||
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation
|
||||
@ -21,6 +24,7 @@ class Cleaner(type: EntityType<Cleaner>, level: Level) : Monster(type, level) {
|
||||
}
|
||||
|
||||
override fun registerGoals() {
|
||||
goalSelector.addGoal(8, RandomLookAroundGoal(this))
|
||||
goalSelector.addGoal(7, WaterAvoidingRandomStrollGoal(this, 0.8))
|
||||
}
|
||||
|
||||
@ -38,6 +42,14 @@ class Cleaner(type: EntityType<Cleaner>, level: Level) : Monster(type, level) {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getHurtSound(damageSource: net.minecraft.world.damagesource.DamageSource): SoundEvent {
|
||||
return SoundEvents.HEAVY_CORE_BREAK
|
||||
}
|
||||
|
||||
override fun getDeathSound(): SoundEvent {
|
||||
return SoundEvents.VAULT_BREAK
|
||||
}
|
||||
|
||||
override fun mobInteract(player: Player, hand: InteractionHand): InteractionResult {
|
||||
if (!this.level().isClientSide) {
|
||||
player.startRiding(this)
|
||||
|
166
src/main/kotlin/ru/dbotthepony/mc/otm/entity/Enforcer.kt
Normal file
166
src/main/kotlin/ru/dbotthepony/mc/otm/entity/Enforcer.kt
Normal file
@ -0,0 +1,166 @@
|
||||
package ru.dbotthepony.mc.otm.entity
|
||||
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.entity.AnimationState
|
||||
import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import net.minecraft.world.entity.ai.goal.*
|
||||
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal
|
||||
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal
|
||||
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation
|
||||
import net.minecraft.world.entity.monster.*
|
||||
import net.minecraft.world.entity.npc.Villager
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.Level
|
||||
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents
|
||||
|
||||
class Enforcer(type: EntityType<Enforcer>, level: Level) : Monster(type,level) {
|
||||
val idleState = AnimationState()
|
||||
val chargeState = AnimationState()
|
||||
init {
|
||||
idleState.start(tickCount)
|
||||
}
|
||||
|
||||
override fun registerGoals() {
|
||||
goalSelector.addGoal(7, LookAtPlayerGoal(this, Player::class.java, 8f))
|
||||
goalSelector.addGoal(3, NearestAttackableTargetGoal(this, LivingEntity::class.java, 10, true, true) { entity ->
|
||||
entity is Player ||
|
||||
entity is Villager ||
|
||||
entity is AbstractIllager ||
|
||||
entity is Zombie ||
|
||||
entity is AbstractSkeleton
|
||||
})
|
||||
goalSelector.addGoal(2, RammingGoal(this))
|
||||
targetSelector.addGoal(1, HurtByTargetGoal(this))
|
||||
}
|
||||
|
||||
override fun createNavigation(level: Level): PathNavigation = GroundPathNavigation(this, level)
|
||||
|
||||
override fun isPushable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getHurtSound(damageSource: net.minecraft.world.damagesource.DamageSource): SoundEvent {
|
||||
return SoundEvents.HEAVY_CORE_BREAK
|
||||
}
|
||||
|
||||
override fun getDeathSound(): SoundEvent {
|
||||
return SoundEvents.VAULT_BREAK
|
||||
}
|
||||
|
||||
//charge attack, could possibly leave a smoke trail too idk
|
||||
class RammingGoal(private val mob: Enforcer) : Goal() {
|
||||
private var target: LivingEntity? = null
|
||||
private var chargeTime = 0
|
||||
private val windupTime = 20
|
||||
private val maxChargeTime = 40
|
||||
private var chargeDir: Vec3? = null
|
||||
private var cooldown = 0
|
||||
private val minCooldown = 20
|
||||
private val maxCooldown = 60
|
||||
private var isCharging = false
|
||||
|
||||
override fun canUse(): Boolean {
|
||||
if (cooldown > 0) {
|
||||
cooldown--
|
||||
return false
|
||||
}
|
||||
|
||||
target = mob.target
|
||||
return target != null
|
||||
}
|
||||
|
||||
override fun canContinueToUse(): Boolean {
|
||||
return isCharging && chargeTime < maxChargeTime
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
mob.playSound(MSoundEvents.PLASMA_WEAPON_OVERHEAT, 1.0f, 1.0f)
|
||||
chargeTime = 0
|
||||
mob.navigation.stop()
|
||||
cooldown = minCooldown + mob.random.nextInt(maxCooldown - minCooldown)
|
||||
isCharging = true
|
||||
|
||||
mob.chargeState.start(mob.tickCount)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if (!isCharging) return
|
||||
|
||||
chargeTime++
|
||||
val target = mob.target ?: return
|
||||
|
||||
if (chargeTime < windupTime) {
|
||||
chargeDir = Vec3(target.x - mob.x, 0.0, target.z - mob.z).normalize()
|
||||
|
||||
mob.lookControl.setLookAt(target, 30.0f, 30.0f)
|
||||
return
|
||||
}
|
||||
|
||||
if (chargeTime == windupTime) {
|
||||
if (chargeDir == null || chargeDir!!.length() < 0.1) {
|
||||
stop()
|
||||
return
|
||||
}
|
||||
mob.playSound(MSoundEvents.ANDROID_JUMP_BOOST, 1.0f, 1.0f)
|
||||
}
|
||||
|
||||
val dir = chargeDir ?: return
|
||||
mob.yRot = (-Mth.atan2(dir.x, dir.z) * (180f / Math.PI)).toFloat()
|
||||
mob.yHeadRot = mob.yRot
|
||||
|
||||
mob.move(net.minecraft.world.entity.MoverType.SELF, dir.scale(1.2))
|
||||
|
||||
|
||||
if (mob.horizontalCollision) {
|
||||
mob.level().playSound(
|
||||
null,
|
||||
mob.x, mob.y, mob.z,
|
||||
SoundEvents.GENERIC_EXPLODE,
|
||||
SoundSource.HOSTILE,
|
||||
1.0f,
|
||||
1.0f
|
||||
)
|
||||
stop()
|
||||
return
|
||||
}
|
||||
|
||||
if (mob.boundingBox.intersects(target.boundingBox)) {
|
||||
val knockbackStrength = 1.5
|
||||
val knockback = dir.scale(knockbackStrength)
|
||||
target.push(knockback.x, 0.5, knockback.z)
|
||||
|
||||
val damageAmount = 6.0f
|
||||
target.hurt(mob.damageSources().mobAttack(mob), damageAmount)
|
||||
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
mob.setDeltaMovement(Vec3.ZERO)
|
||||
chargeTime = 0
|
||||
chargeDir = null
|
||||
isCharging = false
|
||||
mob.chargeState.stop()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun createAttributes() : AttributeSupplier.Builder {
|
||||
return createMonsterAttributes()
|
||||
.add(Attributes.MAX_HEALTH, 300.0)
|
||||
.add(Attributes.ARMOR, 10.0)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.3)
|
||||
.add(Attributes.STEP_HEIGHT, 1.0)
|
||||
.add(Attributes.KNOCKBACK_RESISTANCE, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
@ -208,6 +208,8 @@ object MNames {
|
||||
const val BREAD_MONSTER_SPAWN_EGG = "bead_monster_spawn_egg"
|
||||
const val LOADER_SPAWN_EGG = "loader_spawn_egg"
|
||||
|
||||
const val CLEANER_DRONE_KIT = "cleaner_drone_kit"
|
||||
|
||||
const val ANDROID_MELEE_SPAWN_EGG = "android_melee_spawn_egg"
|
||||
|
||||
// items: crafting components
|
||||
@ -340,6 +342,8 @@ object MNames {
|
||||
const val ANDROID_RANGED = "android_ranged"
|
||||
const val ANDROID_OVERSEER = "android_overseer"
|
||||
|
||||
const val ENFORCER = "enforcer"
|
||||
|
||||
const val PHANTOM_ATTRACTOR = "phantom_attractor"
|
||||
const val JUMP_BOOST = "jump_boost"
|
||||
const val ENDER_TELEPORTER = "ender_teleporter"
|
||||
|
@ -16,6 +16,7 @@ import net.neoforged.neoforge.event.entity.EntityAttributeCreationEvent
|
||||
import ru.dbotthepony.mc.otm.client.render.entity.BreadMonsterRenderer
|
||||
import ru.dbotthepony.mc.otm.client.render.entity.LoaderRenderer
|
||||
import ru.dbotthepony.mc.otm.client.render.entity.CleanerRenderer
|
||||
import ru.dbotthepony.mc.otm.client.render.entity.EnforcerRenderer
|
||||
import ru.dbotthepony.mc.otm.client.render.entity.PlasmaProjectileRenderer
|
||||
import ru.dbotthepony.mc.otm.client.render.entity.RogueAndroidRenderer
|
||||
import ru.dbotthepony.mc.otm.entity.*
|
||||
@ -77,6 +78,14 @@ object MEntityTypes {
|
||||
.build(MNames.ANDROID_MELEE)
|
||||
}
|
||||
|
||||
val ENFORCER: EntityType<Enforcer> by registry.register(MNames.ENFORCER) {
|
||||
EntityType.Builder.of(::Enforcer, MobCategory.MONSTER)
|
||||
.sized(2.4f, 2.5f)
|
||||
.eyeHeight(2.0f)
|
||||
.passengerAttachments(2.5f)
|
||||
.clientTrackingRange(12)
|
||||
.build(MNames.ENFORCER)
|
||||
}
|
||||
|
||||
fun register(bus: IEventBus) {
|
||||
registry.register(bus)
|
||||
@ -90,6 +99,8 @@ object MEntityTypes {
|
||||
|
||||
event.put(ANDROID_MELEE, AndroidMelee.createAttributes().build())
|
||||
|
||||
event.put(ENFORCER, Enforcer.createAttributes().build())
|
||||
|
||||
event.put(CLEANER, Cleaner.createAttributes().build())
|
||||
}
|
||||
|
||||
@ -108,6 +119,8 @@ object MEntityTypes {
|
||||
|
||||
EntityRenderers.register(CLEANER, ::CleanerRenderer)
|
||||
|
||||
EntityRenderers.register(ENFORCER, ::EnforcerRenderer)
|
||||
|
||||
EntityRenderers.register(ANDROID_MELEE) { context ->
|
||||
RogueAndroidRenderer(context, ANDROID_MELEE, "melee",context.modelManager)
|
||||
}
|
||||
|
@ -678,6 +678,9 @@ object MItems {
|
||||
|
||||
val BREAD_MONSTER_SPAWN_EGG: Item by registry.register(MNames.BREAD_MONSTER_SPAWN_EGG){ SpawnEggItem(MEntityTypes.BREAD_MONSTER, 0xFFFFFF, 0xFFFFFF, Item.Properties())}
|
||||
val LOADER_SPAWN_EGG: Item by registry.register(MNames.LOADER_SPAWN_EGG){ SpawnEggItem(MEntityTypes.LOADER, 0xFFFFFF, 0xFFFFFF, Item.Properties())}
|
||||
|
||||
val CLEANER_DRONE_KIT: Item by registry.register(MNames.CLEANER_DRONE_KIT){ SpawnEggItem(MEntityTypes.CLEANER, 0xFFFFFF, 0xFFFFFF, Item.Properties())}
|
||||
|
||||
val ANDROID_MELEE_SPAWN_EGG: Item by registry.register(MNames.ANDROID_MELEE_SPAWN_EGG){ SpawnEggItem(MEntityTypes.ANDROID_MELEE, 0xFFFFFF, 0xFFFFFF, Item.Properties())}
|
||||
|
||||
val ROFLITE_ALLOY_INGOT: Item by registry.register(MNames.ROFLITE_ALLOY_INGOT) { Item(DEFAULT_PROPERTIES) }
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 513 B |
@ -17,7 +17,14 @@
|
||||
"spawn_overrides": {
|
||||
"ambient": {
|
||||
"bounding_box": "piece",
|
||||
"spawns": []
|
||||
"spawns": [
|
||||
{
|
||||
"type": "overdrive_that_matters:cleaner",
|
||||
"maxCount": 1,
|
||||
"minCount": 1,
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"monster": {
|
||||
"bounding_box": "piece",
|
||||
|
Loading…
Reference in New Issue
Block a user