mirror of
https://github.com/FatherToast/SpecialMobs.git
synced 2025-08-09 20:01:22 +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.common.bestiary.MobFamily;
|
||||
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.witherskeleton.NinjaWitherSkeletonEntity;
|
||||
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.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
@ -15,6 +23,7 @@ import net.minecraftforge.fml.common.Mod;
|
|||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
|
@ -24,10 +33,10 @@ public class ClientRegister {
|
|||
@SubscribeEvent
|
||||
public static void onClientSetup( FMLClientSetupEvent event ) {
|
||||
ClientEventHandler.registerConfigGUIFactory();
|
||||
registerEntityRenderers();
|
||||
registerEntityRenderers( event.getMinecraftSupplier() );
|
||||
}
|
||||
|
||||
private static void registerEntityRenderers() {
|
||||
private static void registerEntityRenderers( Supplier<Minecraft> game ) {
|
||||
// Family-based renderers
|
||||
registerFamilyRenderers( MobFamily.CREEPER, SpecialCreeperRenderer::new );
|
||||
registerFamilyRenderers( MobFamily.ZOMBIE, SpecialZombieRenderer::new );
|
||||
|
@ -47,6 +56,10 @@ public class ClientRegister {
|
|||
// Species overrides
|
||||
registerSpeciesRenderer( NinjaSkeletonEntity.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 ) {
|
||||
|
@ -58,4 +71,9 @@ public class ClientRegister {
|
|||
private static <T extends LivingEntity> void registerSpeciesRenderer( MobFamily.Species<T> species, IRenderFactory<? super T> 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<>(
|
||||
"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<>(
|
||||
|
|
|
@ -2,8 +2,10 @@ package fathertoast.specialmobs.common.core.register;
|
|||
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||
import fathertoast.specialmobs.common.entity.projectile.CorporealShiftFireballEntity;
|
||||
import fathertoast.specialmobs.common.util.AnnotationHelper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityClassification;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraftforge.event.entity.EntityAttributeCreationEvent;
|
||||
import net.minecraftforge.fml.RegistryObject;
|
||||
|
@ -13,6 +15,10 @@ import net.minecraftforge.registries.ForgeRegistries;
|
|||
public class SMEntities {
|
||||
|
||||
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. */
|
||||
public static <T extends Entity> RegistryObject<EntityType<T>> register( String name, EntityType.Builder<T> builder ) {
|
||||
|
|
|
@ -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.
|
||||
|
||||
# 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
|
||||
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