mirror of
https://github.com/FatherToast/SpecialMobs.git
synced 2025-08-11 04:41:23 +00:00
WIP Corporeal Shift Ghast
This commit is contained in:
parent
e3bd4627a6
commit
6a2d9bb91f
14 changed files with 523 additions and 4 deletions
|
@ -3,9 +3,17 @@ package fathertoast.specialmobs.client;
|
||||||
import fathertoast.specialmobs.client.renderer.entity.*;
|
import fathertoast.specialmobs.client.renderer.entity.*;
|
||||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
import fathertoast.specialmobs.common.core.register.SMEntities;
|
||||||
|
import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity;
|
||||||
import fathertoast.specialmobs.common.entity.skeleton.NinjaSkeletonEntity;
|
import fathertoast.specialmobs.common.entity.skeleton.NinjaSkeletonEntity;
|
||||||
import fathertoast.specialmobs.common.entity.witherskeleton.NinjaWitherSkeletonEntity;
|
import fathertoast.specialmobs.common.entity.witherskeleton.NinjaWitherSkeletonEntity;
|
||||||
import mcp.MethodsReturnNonnullByDefault;
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.ItemRenderer;
|
||||||
|
import net.minecraft.client.renderer.entity.SpriteRenderer;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.IRendersAsItem;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
@ -15,6 +23,7 @@ import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
|
@ -24,10 +33,10 @@ public class ClientRegister {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onClientSetup( FMLClientSetupEvent event ) {
|
public static void onClientSetup( FMLClientSetupEvent event ) {
|
||||||
ClientEventHandler.registerConfigGUIFactory();
|
ClientEventHandler.registerConfigGUIFactory();
|
||||||
registerEntityRenderers();
|
registerEntityRenderers( event.getMinecraftSupplier() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerEntityRenderers() {
|
private static void registerEntityRenderers( Supplier<Minecraft> game ) {
|
||||||
// Family-based renderers
|
// Family-based renderers
|
||||||
registerFamilyRenderers( MobFamily.CREEPER, SpecialCreeperRenderer::new );
|
registerFamilyRenderers( MobFamily.CREEPER, SpecialCreeperRenderer::new );
|
||||||
registerFamilyRenderers( MobFamily.ZOMBIE, SpecialZombieRenderer::new );
|
registerFamilyRenderers( MobFamily.ZOMBIE, SpecialZombieRenderer::new );
|
||||||
|
@ -47,6 +56,10 @@ public class ClientRegister {
|
||||||
// Species overrides
|
// Species overrides
|
||||||
registerSpeciesRenderer( NinjaSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
|
registerSpeciesRenderer( NinjaSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
|
||||||
registerSpeciesRenderer( NinjaWitherSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
|
registerSpeciesRenderer( NinjaWitherSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
|
||||||
|
registerSpeciesRenderer( CorporealShiftGhastEntity.SPECIES, CorporealShiftGhastRenderer::new );
|
||||||
|
|
||||||
|
// Other
|
||||||
|
registerSpriteRenderer( SMEntities.CORPOREAL_FIREBALL.get(), game, 3.0F, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends LivingEntity> void registerFamilyRenderers( MobFamily<T> family, IRenderFactory<? super T> renderFactory ) {
|
private static <T extends LivingEntity> void registerFamilyRenderers( MobFamily<T> family, IRenderFactory<? super T> renderFactory ) {
|
||||||
|
@ -58,4 +71,9 @@ public class ClientRegister {
|
||||||
private static <T extends LivingEntity> void registerSpeciesRenderer( MobFamily.Species<T> species, IRenderFactory<? super T> renderFactory ) {
|
private static <T extends LivingEntity> void registerSpeciesRenderer( MobFamily.Species<T> species, IRenderFactory<? super T> renderFactory ) {
|
||||||
RenderingRegistry.registerEntityRenderingHandler( species.entityType.get(), renderFactory );
|
RenderingRegistry.registerEntityRenderingHandler( species.entityType.get(), renderFactory );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T extends Entity & IRendersAsItem> void registerSpriteRenderer(EntityType<T> entityType, Supplier<Minecraft> minecraftSupplier, float scale, boolean fullBright) {
|
||||||
|
ItemRenderer itemRenderer = minecraftSupplier.get().getItemRenderer();
|
||||||
|
RenderingRegistry.registerEntityRenderingHandler(entityType, (renderManager) -> new SpriteRenderer<>(renderManager, itemRenderer, scale, fullBright));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package fathertoast.specialmobs.client.renderer.entity;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.entity.model.SegmentedModel;
|
||||||
|
import net.minecraft.client.renderer.model.ModelRenderer;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/** Copy of {@link net.minecraft.client.renderer.entity.model.GhastModel} */
|
||||||
|
public class CorporealShiftGhastModel<T extends Entity> extends SegmentedModel<T> {
|
||||||
|
private final ModelRenderer[] tentacles = new ModelRenderer[9];
|
||||||
|
private final ImmutableList<ModelRenderer> parts;
|
||||||
|
|
||||||
|
public CorporealShiftGhastModel() {
|
||||||
|
ImmutableList.Builder<ModelRenderer> builder = ImmutableList.builder();
|
||||||
|
ModelRenderer modelrenderer = new ModelRenderer(this, 0, 0);
|
||||||
|
modelrenderer.addBox(-8.0F, -8.0F, -8.0F, 16.0F, 16.0F, 16.0F);
|
||||||
|
modelrenderer.y = 17.6F;
|
||||||
|
builder.add(modelrenderer);
|
||||||
|
Random random = new Random(1660L);
|
||||||
|
|
||||||
|
for (int i = 0; i < this.tentacles.length; ++i) {
|
||||||
|
this.tentacles[i] = new ModelRenderer(this, 0, 0);
|
||||||
|
float f = (((float) (i % 3) - (float) (i / 3 % 2) * 0.5F + 0.25F) / 2.0F * 2.0F - 1.0F) * 5.0F;
|
||||||
|
float f1 = ((float) (i / 3) / 2.0F * 2.0F - 1.0F) * 5.0F;
|
||||||
|
int j = random.nextInt(7) + 8;
|
||||||
|
this.tentacles[i].addBox(-1.0F, 0.0F, -1.0F, 2.0F, (float) j, 2.0F);
|
||||||
|
this.tentacles[i].x = f;
|
||||||
|
this.tentacles[i].z = f1;
|
||||||
|
this.tentacles[i].y = 24.6F;
|
||||||
|
builder.add(this.tentacles[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parts = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRenderType(Function<ResourceLocation, RenderType> renderTypeFunc) {
|
||||||
|
this.renderType = renderTypeFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupAnim(T ghast, float p_225597_2_, float p_225597_3_, float p_225597_4_, float p_225597_5_, float p_225597_6_) {
|
||||||
|
for (int i = 0; i < this.tentacles.length; ++i) {
|
||||||
|
this.tentacles[i].xRot = 0.2F * MathHelper.sin(p_225597_4_ * 0.3F + (float) i) + 0.4F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterable<ModelRenderer> parts() {
|
||||||
|
return this.parts;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package fathertoast.specialmobs.client.renderer.entity;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import fathertoast.specialmobs.client.renderer.entity.layers.SpecialGhastEyesLayer;
|
||||||
|
import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobEyesLayer;
|
||||||
|
import fathertoast.specialmobs.client.renderer.entity.misc.SMRenderTypes;
|
||||||
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
import fathertoast.specialmobs.common.entity.ISpecialMob;
|
||||||
|
import fathertoast.specialmobs.common.entity.SpecialMobData;
|
||||||
|
import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity;
|
||||||
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||||
|
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class CorporealShiftGhastRenderer extends MobRenderer<CorporealShiftGhastEntity, CorporealShiftGhastModel<CorporealShiftGhastEntity>> {
|
||||||
|
|
||||||
|
private static final Function<ResourceLocation, RenderType> INCORPOREAL = (resourceLocation) -> SMRenderTypes.entityCutoutNoCullBlend(resourceLocation, SMRenderTypes.INCORPOREAL_ALPHA);
|
||||||
|
|
||||||
|
private static final ResourceLocation EYES = SpecialMobs.resourceLoc("textures/entity/ghast/corporeal_shift_eyes.png");
|
||||||
|
private static final ResourceLocation SHOOT_EYES = SpecialMobs.resourceLoc("textures/entity/ghast/corporeal_shift_shoot_eyes.png");
|
||||||
|
|
||||||
|
private final float baseShadowRadius;
|
||||||
|
|
||||||
|
public CorporealShiftGhastRenderer(EntityRendererManager rendererManager) {
|
||||||
|
super(rendererManager, new CorporealShiftGhastModel<>(), 1.5F);
|
||||||
|
addLayer(new SpecialGhastEyesLayer<>(this, EYES, SHOOT_EYES ));
|
||||||
|
baseShadowRadius = shadowRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(CorporealShiftGhastEntity ghast, float rotation, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight) {
|
||||||
|
model.renderType = ghast.isCorporeal() ? RenderType::entityCutoutNoCull : INCORPOREAL;
|
||||||
|
super.render(ghast, rotation, partialTicks, matrixStack, buffer, packedLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getTextureLocation( CorporealShiftGhastEntity entity ) {
|
||||||
|
final SpecialMobData<?> data = ((ISpecialMob<?>) entity).getSpecialData();
|
||||||
|
return entity.isCharging() && data.hasOverlayTexture() ? data.getTextureOverlay() : data.getTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void scale( CorporealShiftGhastEntity entity, MatrixStack matrixStack, float partialTick ) {
|
||||||
|
final float scale = 4.5F + ((ISpecialMob<?>) entity).getSpecialData().getRenderScale();
|
||||||
|
shadowRadius = baseShadowRadius * scale;
|
||||||
|
matrixStack.scale( scale, scale, scale );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package fathertoast.specialmobs.client.renderer.entity.layers;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||||
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.entity.IEntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.entity.layers.AbstractEyesLayer;
|
||||||
|
import net.minecraft.client.renderer.entity.model.EntityModel;
|
||||||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
import net.minecraft.entity.monster.GhastEntity;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
public class SpecialGhastEyesLayer<T extends GhastEntity, M extends EntityModel<T>> extends AbstractEyesLayer<T, M> {
|
||||||
|
private final RenderType FALLBACK = RenderType.eyes( new ResourceLocation( "textures/entity/spider_eyes.png" ) );
|
||||||
|
private final ResourceLocation eyes;
|
||||||
|
private final ResourceLocation shootEyes;
|
||||||
|
|
||||||
|
|
||||||
|
public SpecialGhastEyesLayer( IEntityRenderer<T, M> renderer, ResourceLocation eyes, ResourceLocation shootEyes ) {
|
||||||
|
super( renderer );
|
||||||
|
this.eyes = eyes;
|
||||||
|
this.shootEyes = shootEyes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight, T ghast, float limbSwing,
|
||||||
|
float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch ) {
|
||||||
|
|
||||||
|
IVertexBuilder vertexBuilder = buffer.getBuffer( RenderType.entityCutout(ghast.isCharging() ? shootEyes : eyes) );
|
||||||
|
this.getParentModel().renderToBuffer( matrixStack, vertexBuilder, LightTexture.pack(15, 15), OverlayTexture.NO_OVERLAY,
|
||||||
|
1.0F, 1.0F, 1.0F, 1.0F );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RenderType renderType() {
|
||||||
|
SpecialMobs.LOG.warn( "Something is attempting to get eye layer 'render type' for some reason! :(" );
|
||||||
|
return FALLBACK;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package fathertoast.specialmobs.client.renderer.entity.misc;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.RenderState;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
public class SMRenderTypes {
|
||||||
|
|
||||||
|
public static RenderState.AlphaState INCORPOREAL_ALPHA = new RenderState.AlphaState(0.05F);
|
||||||
|
|
||||||
|
public static RenderType entityCutoutNoCullBlend(ResourceLocation resourceLocation, RenderState.AlphaState alphaState) {
|
||||||
|
RenderType.State state = RenderType.State.builder()
|
||||||
|
.setTextureState(new RenderState.TextureState(resourceLocation, false, false))
|
||||||
|
.setTransparencyState(RenderState.ADDITIVE_TRANSPARENCY)
|
||||||
|
.setDiffuseLightingState(RenderState.DIFFUSE_LIGHTING)
|
||||||
|
.setAlphaState(alphaState)
|
||||||
|
.setLightmapState(RenderState.LIGHTMAP)
|
||||||
|
.setOverlayState(RenderState.OVERLAY)
|
||||||
|
.createCompositeState(true);
|
||||||
|
|
||||||
|
return RenderType.create("specialmobs_entity_cutout_no_cull_blend", DefaultVertexFormats.NEW_ENTITY, 7, 256, true, false, state);
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,7 +97,7 @@ public class MobFamily<T extends LivingEntity> {
|
||||||
|
|
||||||
public static final MobFamily<GhastEntity> GHAST = new MobFamily<>(
|
public static final MobFamily<GhastEntity> GHAST = new MobFamily<>(
|
||||||
"Ghast", "ghasts", 0xF9F9F9, new EntityType[] { EntityType.GHAST },
|
"Ghast", "ghasts", 0xF9F9F9, new EntityType[] { EntityType.GHAST },
|
||||||
"Baby", "Fighter", "King", "Queen", "Unholy"
|
"Baby", "Fighter", "King", "Queen", "Unholy", "CorporealShift"
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final MobFamily<BlazeEntity> BLAZE = new MobFamily<>(
|
public static final MobFamily<BlazeEntity> BLAZE = new MobFamily<>(
|
||||||
|
|
|
@ -2,8 +2,10 @@ package fathertoast.specialmobs.common.core.register;
|
||||||
|
|
||||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
import fathertoast.specialmobs.common.entity.projectile.CorporealShiftFireballEntity;
|
||||||
import fathertoast.specialmobs.common.util.AnnotationHelper;
|
import fathertoast.specialmobs.common.util.AnnotationHelper;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityClassification;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraftforge.event.entity.EntityAttributeCreationEvent;
|
import net.minecraftforge.event.entity.EntityAttributeCreationEvent;
|
||||||
import net.minecraftforge.fml.RegistryObject;
|
import net.minecraftforge.fml.RegistryObject;
|
||||||
|
@ -14,6 +16,10 @@ public class SMEntities {
|
||||||
|
|
||||||
public static final DeferredRegister<EntityType<?>> REGISTRY = DeferredRegister.create( ForgeRegistries.ENTITIES, SpecialMobs.MOD_ID );
|
public static final DeferredRegister<EntityType<?>> REGISTRY = DeferredRegister.create( ForgeRegistries.ENTITIES, SpecialMobs.MOD_ID );
|
||||||
|
|
||||||
|
/** Misc entities */
|
||||||
|
public static final RegistryObject<EntityType<CorporealShiftFireballEntity>> CORPOREAL_FIREBALL = register("corporeal_fireball",
|
||||||
|
EntityType.Builder.<CorporealShiftFireballEntity>of(CorporealShiftFireballEntity::new, EntityClassification.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(10));
|
||||||
|
|
||||||
/** Registers an entity type to the deferred register. */
|
/** Registers an entity type to the deferred register. */
|
||||||
public static <T extends Entity> RegistryObject<EntityType<T>> register( String name, EntityType.Builder<T> builder ) {
|
public static <T extends Entity> RegistryObject<EntityType<T>> register( String name, EntityType.Builder<T> builder ) {
|
||||||
return REGISTRY.register( name, () -> builder.build( name ) );
|
return REGISTRY.register( name, () -> builder.build( name ) );
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
package fathertoast.specialmobs.common.entity.ghast;
|
||||||
|
|
||||||
|
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||||
|
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||||
|
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||||
|
import fathertoast.specialmobs.common.entity.SpecialMobData;
|
||||||
|
import fathertoast.specialmobs.common.entity.projectile.CorporealShiftFireballEntity;
|
||||||
|
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||||
|
import fathertoast.specialmobs.common.util.References;
|
||||||
|
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.ai.attributes.AttributeModifierMap;
|
||||||
|
import net.minecraft.entity.ai.attributes.Attributes;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.network.datasync.DataParameter;
|
||||||
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
|
import net.minecraft.particles.ParticleTypes;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.common.util.Constants;
|
||||||
|
|
||||||
|
@SpecialMob
|
||||||
|
public class CorporealShiftGhastEntity extends _SpecialGhastEntity {
|
||||||
|
|
||||||
|
//--------------- Static Special Mob Hooks ----------------
|
||||||
|
|
||||||
|
@SpecialMob.SpeciesReference
|
||||||
|
public static MobFamily.Species<CorporealShiftGhastEntity> SPECIES;
|
||||||
|
|
||||||
|
@SpecialMob.BestiaryInfoSupplier
|
||||||
|
public static BestiaryInfo bestiaryInfo(EntityType.Builder<LivingEntity> entityType ) {
|
||||||
|
entityType.sized( 6.0F, 6.0F );
|
||||||
|
return new BestiaryInfo( 0xA7FF9B, BestiaryInfo.BaseWeight.LOW );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SpecialMob.AttributeCreator
|
||||||
|
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||||
|
return AttributeHelper.of( _SpecialGhastEntity.createAttributes() )
|
||||||
|
.addAttribute( Attributes.MAX_HEALTH, 20.0 )
|
||||||
|
.addAttribute( Attributes.ARMOR, 0.0 )
|
||||||
|
.addAttribute( Attributes.ATTACK_DAMAGE, 0.0 )
|
||||||
|
.multAttribute( Attributes.MOVEMENT_SPEED, 0.8 )
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SpecialMob.LanguageProvider
|
||||||
|
public static String[] getTranslations( String langKey ) {
|
||||||
|
return References.translations( langKey, "Corporeal Shift Ghast",
|
||||||
|
"", "", "", "", "", "" );//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@SpecialMob.LootTableProvider
|
||||||
|
public static void buildLootTable( LootTableBuilder loot ) {
|
||||||
|
addBaseLoot( loot );
|
||||||
|
// TODO - Uh uhm uhhhhh hmmm..
|
||||||
|
loot.addSemicommonDrop( "semicommon", Items.POISONOUS_POTATO );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SpecialMob.Factory
|
||||||
|
public static EntityType.IFactory<CorporealShiftGhastEntity> getVariantFactory() { return CorporealShiftGhastEntity::new; }
|
||||||
|
|
||||||
|
|
||||||
|
//--------------- Variant-Specific Implementations ----------------
|
||||||
|
|
||||||
|
public static final DataParameter<Boolean> CORPOREAL = EntityDataManager.defineId(CorporealShiftGhastEntity.class, DataSerializers.BOOLEAN);
|
||||||
|
|
||||||
|
private final int maxShiftTime = 600;
|
||||||
|
private int shiftTime = maxShiftTime;
|
||||||
|
|
||||||
|
public CorporealShiftGhastEntity( EntityType<? extends _SpecialGhastEntity> entityType, World world ) {
|
||||||
|
super( entityType, world );
|
||||||
|
getSpecialData().setRegenerationTime( 80 );
|
||||||
|
getSpecialData().setBaseScale( 1.0F );
|
||||||
|
xpReward += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void defineSynchedData() {
|
||||||
|
super.defineSynchedData();
|
||||||
|
entityData.define(CORPOREAL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
if ( --shiftTime <= 0 ) {
|
||||||
|
if ( !level.isClientSide ) {
|
||||||
|
shiftTime = maxShiftTime;
|
||||||
|
entityData.set(CORPOREAL, !entityData.get(CORPOREAL));
|
||||||
|
spawnShiftSmoke((ServerWorld)level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnShiftSmoke(ServerWorld world) {
|
||||||
|
world.sendParticles(ParticleTypes.CLOUD, this.getX(), this.getY(), this.getZ(), 25, 0.0, 0.0, 0.0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCorporeal() {
|
||||||
|
return entityData.get(CORPOREAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Override to change this ghast's explosion power multiplier. */
|
||||||
|
@Override
|
||||||
|
protected int getVariantExplosionPower( int radius ) { return Math.round( radius * 2.5F ); }
|
||||||
|
|
||||||
|
/** Called to attack the target with a ranged attack. */
|
||||||
|
@Override
|
||||||
|
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||||
|
if( !isSilent() ) level.levelEvent( null, References.EVENT_GHAST_SHOOT, blockPosition(), 0 );
|
||||||
|
|
||||||
|
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread;
|
||||||
|
final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() );
|
||||||
|
double dX = target.getX() - (getX() + lookVec.x) + getRandom().nextGaussian() * accelVariance;
|
||||||
|
double dY = target.getY( 0.5 ) - (0.5 + getY( 0.5 ));
|
||||||
|
double dZ = target.getZ() - (getZ() + lookVec.z) + getRandom().nextGaussian() * accelVariance;
|
||||||
|
|
||||||
|
final CorporealShiftFireballEntity fireball = new CorporealShiftFireballEntity( level, this, dX, dY, dZ );
|
||||||
|
fireball.explosionPower = getVariantExplosionPower( getExplosionPower() );
|
||||||
|
fireball.setPos(
|
||||||
|
getX() + lookVec.x,
|
||||||
|
getY( 0.5 ) + 0.5,
|
||||||
|
getZ() + lookVec.z );
|
||||||
|
level.addFreshEntity( fireball );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ResourceLocation[] TEXTURES = {
|
||||||
|
GET_TEXTURE_PATH( "corporeal_shift" ),
|
||||||
|
null,
|
||||||
|
GET_TEXTURE_PATH( "corporeal_shift_shoot" )
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @return All default textures for this entity. */
|
||||||
|
@Override
|
||||||
|
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||||
|
|
||||||
|
|
||||||
|
//--------------- SpecialMobData Hooks ----------------
|
||||||
|
|
||||||
|
/** @return Attempts to damage this entity; returns true if the hit was successful. */
|
||||||
|
@Override
|
||||||
|
public boolean hurt(DamageSource source, float amount ) {
|
||||||
|
return isCorporeal() && super.hurt(source, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Saves data to this entity's base NBT compound that is specific to its subclass. */
|
||||||
|
@Override
|
||||||
|
public void addAdditionalSaveData( CompoundNBT tag ) {
|
||||||
|
super.addAdditionalSaveData( tag );
|
||||||
|
tag.putInt("ShiftTime", shiftTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Loads data from this entity's base NBT compound that is specific to its subclass. */
|
||||||
|
@Override
|
||||||
|
public void readAdditionalSaveData( CompoundNBT tag ) {
|
||||||
|
super.readAdditionalSaveData( tag );
|
||||||
|
|
||||||
|
if (tag.contains("ShiftTime", Constants.NBT.TAG_ANY_NUMERIC)) {
|
||||||
|
shiftTime = tag.getInt("ShiftTime");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
package fathertoast.specialmobs.common.entity.projectile;
|
||||||
|
|
||||||
|
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||||
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
import fathertoast.specialmobs.common.core.register.SMEntities;
|
||||||
|
import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity;
|
||||||
|
import fathertoast.specialmobs.common.util.References;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.projectile.AbstractFireballEntity;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.network.IPacket;
|
||||||
|
import net.minecraft.network.datasync.DataParameter;
|
||||||
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
|
import net.minecraft.util.math.EntityRayTraceResult;
|
||||||
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
|
import net.minecraft.world.Explosion;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.event.ForgeEventFactory;
|
||||||
|
import net.minecraftforge.fml.network.NetworkHooks;
|
||||||
|
|
||||||
|
public class CorporealShiftFireballEntity extends AbstractFireballEntity {
|
||||||
|
|
||||||
|
private static final DataParameter<Boolean> CORPOREAL = EntityDataManager.defineId(CorporealShiftFireballEntity.class, DataSerializers.BOOLEAN);
|
||||||
|
|
||||||
|
public int explosionPower = 1;
|
||||||
|
private boolean shouldExplode = false;
|
||||||
|
|
||||||
|
|
||||||
|
public CorporealShiftFireballEntity(EntityType<? extends AbstractFireballEntity> entityType, World world) {
|
||||||
|
super(entityType, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CorporealShiftFireballEntity(World world, CorporealShiftGhastEntity ghast, double x, double y, double z) {
|
||||||
|
super(SMEntities.CORPOREAL_FIREBALL.get(), ghast, x, y, z, world);
|
||||||
|
setCorporeal(ghast.isCorporeal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SpecialMob.LanguageProvider
|
||||||
|
public static String[] getTranslations( String langKey ) {
|
||||||
|
return References.translations( langKey, "Corporeal Shift Fireball",
|
||||||
|
"", "", "", "", "", "" );//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void defineSynchedData() {
|
||||||
|
super.defineSynchedData();
|
||||||
|
entityData.define(CORPOREAL, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCorporeal() {
|
||||||
|
return entityData.get(CORPOREAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCorporeal(boolean corporeal) {
|
||||||
|
entityData.set(CORPOREAL, corporeal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
if ( !level.isClientSide && shouldExplode )
|
||||||
|
explode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void explode() {
|
||||||
|
boolean mobGrief = ForgeEventFactory.getMobGriefingEvent(level, getOwner());
|
||||||
|
Explosion.Mode mode = mobGrief ? Explosion.Mode.DESTROY : Explosion.Mode.NONE;
|
||||||
|
|
||||||
|
level.explode(null, this.getX(), this.getY(), this.getZ(), (float)explosionPower, mobGrief, mode);
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHit(RayTraceResult traceResult) {
|
||||||
|
super.onHit(traceResult);
|
||||||
|
|
||||||
|
if (!level.isClientSide && isCorporeal()) {
|
||||||
|
shouldExplode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHitEntity(EntityRayTraceResult traceResult) {
|
||||||
|
super.onHitEntity(traceResult);
|
||||||
|
|
||||||
|
if (!this.level.isClientSide) {
|
||||||
|
Entity target = traceResult.getEntity();
|
||||||
|
Entity owner = getOwner();
|
||||||
|
|
||||||
|
if (!isCorporeal()) {
|
||||||
|
// TODO - Figure out why this is cringe
|
||||||
|
SpecialMobs.LOG.info("X={}, XO={}", target.getX(), target.xo);
|
||||||
|
SpecialMobs.LOG.info("Z={}, ZO={}", target.getZ(), target.zo);
|
||||||
|
if (target.getX() != target.xo || target.getY() != target.yo || target.getZ() != target.zo)
|
||||||
|
explode();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target.hurt(DamageSource.fireball(this, owner), 6.0F);
|
||||||
|
|
||||||
|
if (owner instanceof LivingEntity) {
|
||||||
|
doEnchantDamageEffects((LivingEntity) owner, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hurt(DamageSource damageSource, float damage) {
|
||||||
|
if (!isCorporeal()) {
|
||||||
|
if (isInvulnerableTo(damageSource) || damageSource.isFire()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
shouldExplode = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return super.hurt(damageSource, damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAdditionalSaveData(CompoundNBT compoundNBT) {
|
||||||
|
super.addAdditionalSaveData(compoundNBT);
|
||||||
|
compoundNBT.putInt("ExplosionPower", explosionPower);
|
||||||
|
compoundNBT.putBoolean("Corporeal", isCorporeal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readAdditionalSaveData(CompoundNBT compoundNBT) {
|
||||||
|
super.readAdditionalSaveData(compoundNBT);
|
||||||
|
if (compoundNBT.contains("ExplosionPower", 99)) {
|
||||||
|
explosionPower = compoundNBT.getInt("ExplosionPower");
|
||||||
|
}
|
||||||
|
entityData.set(CORPOREAL, compoundNBT.getBoolean("Corporeal"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket<?> getAddEntityPacket() {
|
||||||
|
return NetworkHooks.getEntitySpawningPacket(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,11 @@
|
||||||
# anything inside a final class, and private and/or static fields & methods.
|
# anything inside a final class, and private and/or static fields & methods.
|
||||||
|
|
||||||
# Render stuff
|
# Render stuff
|
||||||
public net.minecraft.client.renderer.WorldRenderer field_228415_m_ # renderBuffers
|
public-f net.minecraft.client.renderer.model.Model field_228281_q_ # renderType
|
||||||
|
public net.minecraft.client.renderer.RenderState field_228511_c_ # ADDITIVE_TRANSPARENCY
|
||||||
|
public net.minecraft.client.renderer.RenderState field_228532_x_ # DIFFUSE_LIGHTING
|
||||||
|
public net.minecraft.client.renderer.RenderState field_228528_t_ # LIGHTMAP
|
||||||
|
public net.minecraft.client.renderer.RenderState field_228530_v_ # OVERLAY # LIGHTMAP
|
||||||
|
|
||||||
# Entity registration
|
# Entity registration
|
||||||
public net.minecraft.entity.EntityType field_233593_bg_ # immuneTo
|
public net.minecraft.entity.EntityType field_233593_bg_ # immuneTo
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 164 B |
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 195 B |
Loading…
Add table
Reference in a new issue