mirror of
https://github.com/FatherToast/SpecialMobs.git
synced 2025-08-21 01:21:23 +00:00
Merge branch '1.16.5' of https://github.com/FatherToast/SpecialMobs into 1.16.5
This commit is contained in:
commit
4986eaf10d
21 changed files with 1366 additions and 37 deletions
|
@ -40,6 +40,7 @@ public class ClientRegister {
|
|||
registerFamilyRenderers( MobFamily.SILVERFISH, SpecialSilverfishRenderer::new );
|
||||
registerFamilyRenderers( MobFamily.ENDERMAN, SpecialEndermanRenderer::new );
|
||||
//registerFamilyRenderers( MobFamily.WITCH, SpecialWitchRenderer::new );
|
||||
registerFamilyRenderers( MobFamily.BLAZE, SpecialBlazeRenderer::new );
|
||||
|
||||
// Species overrides
|
||||
registerSpeciesRenderer( NinjaSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package fathertoast.specialmobs.client.renderer.entity;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import fathertoast.specialmobs.common.entity.ISpecialMob;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.client.renderer.entity.BlazeRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||
import net.minecraft.entity.monster.BlazeEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@OnlyIn( Dist.CLIENT )
|
||||
public class SpecialBlazeRenderer extends BlazeRenderer {
|
||||
|
||||
private final float baseShadowRadius;
|
||||
|
||||
public SpecialBlazeRenderer( EntityRendererManager rendererManager ) {
|
||||
super( rendererManager );
|
||||
baseShadowRadius = shadowRadius;
|
||||
// Unneeded, the whole model is full brightness
|
||||
//addLayer( new SpecialMobEyesLayer<>( this ) );
|
||||
// Model doesn't support size parameter
|
||||
//addLayer( new SpecialMobOverlayLayer<>( this, new SilverfishModel<>( 0.25F ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation( BlazeEntity entity ) {
|
||||
return ((ISpecialMob<?>) entity).getSpecialData().getTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scale( BlazeEntity entity, MatrixStack matrixStack, float partialTick ) {
|
||||
super.scale( entity, matrixStack, partialTick );
|
||||
|
||||
final float scale = ((ISpecialMob<?>) entity).getSpecialData().getRenderScale();
|
||||
shadowRadius = baseShadowRadius * scale;
|
||||
matrixStack.scale( scale, scale, scale );
|
||||
}
|
||||
}
|
|
@ -27,12 +27,12 @@ public class SpecialCreeperRenderer extends CreeperRenderer {
|
|||
public SpecialCreeperRenderer( EntityRendererManager rendererManager ) {
|
||||
super( rendererManager );
|
||||
baseShadowRadius = shadowRadius;
|
||||
// Get rid of this one since we have our own implementation
|
||||
layers.removeIf( ( layer ) -> layer instanceof CreeperChargeLayer );
|
||||
|
||||
addLayer( new SpecialMobEyesLayer<>( this ) );
|
||||
addLayer( new SpecialMobOverlayLayer<>( this, new CreeperModel<>( 0.25F ) ) );
|
||||
addLayer( new SpecialCreeperChargeLayer<>(this, new CreeperModel<>( 2.0F )) );
|
||||
|
||||
// Get rid of this one since we have our own implementation
|
||||
layers.removeIf((layer) -> layer instanceof CreeperChargeLayer);
|
||||
addLayer( new SpecialCreeperChargeLayer<>( this, new CreeperModel<>( 2.0F ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,6 +7,7 @@ import fathertoast.specialmobs.common.entity.ISpecialMob;
|
|||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.client.renderer.entity.EndermanRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||
import net.minecraft.client.renderer.entity.layers.EndermanEyesLayer;
|
||||
import net.minecraft.client.renderer.entity.model.EndermanModel;
|
||||
import net.minecraft.entity.monster.EndermanEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
@ -24,9 +25,11 @@ public class SpecialEndermanRenderer extends EndermanRenderer {
|
|||
|
||||
public SpecialEndermanRenderer( EntityRendererManager rendererManager ) {
|
||||
super( rendererManager );
|
||||
layers.remove( layers.size() - 2 ); // Remove vanilla eyes layer
|
||||
// Get rid of this one since we have our own implementation
|
||||
layers.removeIf( ( layer ) -> layer instanceof EndermanEyesLayer );
|
||||
|
||||
baseShadowRadius = shadowRadius;
|
||||
//addLayer( new SpecialMobEyesLayer<>( this ) );//TODO temp until textures are fixed
|
||||
addLayer( new SpecialMobEyesLayer<>( this ) );
|
||||
addLayer( new SpecialMobOverlayLayer<>( this, new EndermanModel<>( 0.25F ) ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package fathertoast.specialmobs.client.renderer.entity;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobEyesLayer;
|
||||
import fathertoast.specialmobs.common.entity.ISpecialMob;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||
|
@ -23,7 +22,8 @@ public class SpecialMagmaCubeRenderer extends MagmaCubeRenderer {
|
|||
public SpecialMagmaCubeRenderer( EntityRendererManager rendererManager ) {
|
||||
super( rendererManager );
|
||||
baseShadowRadius = shadowRadius;
|
||||
addLayer( new SpecialMobEyesLayer<>( this ) );
|
||||
// Unneeded, the whole model is full brightness
|
||||
//addLayer( new SpecialMobEyesLayer<>( this ) );
|
||||
// Model doesn't support size parameter
|
||||
//addLayer( new SpecialMobOverlayLayer<>( this, new MagmaCubeModel<>( 0.25F ) ) );
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import fathertoast.specialmobs.common.entity.ISpecialMob;
|
|||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||
import net.minecraft.client.renderer.entity.SpiderRenderer;
|
||||
import net.minecraft.client.renderer.entity.layers.SpiderEyesLayer;
|
||||
import net.minecraft.entity.monster.SpiderEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
@ -22,7 +23,9 @@ public class SpecialSpiderRenderer extends SpiderRenderer<SpiderEntity> {
|
|||
|
||||
public SpecialSpiderRenderer( EntityRendererManager rendererManager ) {
|
||||
super( rendererManager );
|
||||
layers.remove( layers.size() - 1 ); // Remove vanilla eyes layer
|
||||
// Get rid of this one since we have our own implementation
|
||||
layers.removeIf( ( layer ) -> layer instanceof SpiderEyesLayer );
|
||||
|
||||
baseShadowRadius = shadowRadius;
|
||||
addLayer( new SpecialMobEyesLayer<>( this ) );
|
||||
// Model doesn't support size parameter
|
||||
|
|
|
@ -100,10 +100,10 @@ public class MobFamily<T extends LivingEntity> {
|
|||
// "Baby", "Fighter", "King", "Queen", "Unholy"
|
||||
// );
|
||||
|
||||
// public static final MobFamily<BlazeEntity> BLAZE = new MobFamily<>(
|
||||
// "Blaze", "blazes", 0xF6B201, new EntityType[] { EntityType.BLAZE },
|
||||
// "Cinder", "Conflagration", "Ember", "Hellfire", "Inferno", "Jolt", "Wildfire"
|
||||
// );
|
||||
public static final MobFamily<BlazeEntity> BLAZE = new MobFamily<>(
|
||||
"Blaze", "blazes", 0xF6B201, new EntityType[] { EntityType.BLAZE },
|
||||
"Cinder", "Conflagration", "Ember", "Hellfire", "Inferno", "Jolt", "Wildfire"
|
||||
);
|
||||
|
||||
static {
|
||||
final HashMap<EntityType<?>, MobFamily<?>> classToFamilyMap = new HashMap<>();
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
package fathertoast.specialmobs.common.entity.ai;
|
||||
|
||||
import fathertoast.specialmobs.common.entity.SpecialMobData;
|
||||
import fathertoast.specialmobs.common.entity.blaze._SpecialBlazeEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.ai.goal.Goal;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* The attack AI used by blazes. This handles both ranged and melee behaviors.
|
||||
*/
|
||||
public class SpecialBlazeAttackGoal extends Goal {
|
||||
|
||||
private final _SpecialBlazeEntity blaze;
|
||||
|
||||
private int attackStep;
|
||||
private int attackTime;
|
||||
private int lastSeen;
|
||||
|
||||
public SpecialBlazeAttackGoal( _SpecialBlazeEntity entity ) {
|
||||
blaze = entity;
|
||||
setFlags( EnumSet.of( Goal.Flag.MOVE, Goal.Flag.LOOK ) );
|
||||
}
|
||||
|
||||
/** @return Returns true if this AI can be activated. */
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
final LivingEntity target = blaze.getTarget();
|
||||
return target != null && target.isAlive() && blaze.canAttack( target );
|
||||
}
|
||||
|
||||
/** Called when this AI is activated. */
|
||||
@Override
|
||||
public void start() {
|
||||
attackStep = 0;
|
||||
}
|
||||
|
||||
/** Called when this AI is deactivated. */
|
||||
@Override
|
||||
public void stop() {
|
||||
blaze.setCharged( false );
|
||||
lastSeen = 0;
|
||||
}
|
||||
|
||||
/** Called each tick while this AI is active. */
|
||||
@Override
|
||||
public void tick() {
|
||||
attackTime--;
|
||||
|
||||
final LivingEntity target = blaze.getTarget();
|
||||
if( target == null ) return;
|
||||
|
||||
final SpecialMobData<_SpecialBlazeEntity> data = blaze.getSpecialData();
|
||||
|
||||
final boolean canSee = blaze.getSensing().canSee( target );
|
||||
if( canSee ) lastSeen = 0;
|
||||
else lastSeen++;
|
||||
|
||||
final double distanceSqr = blaze.distanceToSqr( target );
|
||||
final float rangeSq = data.rangedAttackMaxRange * data.rangedAttackMaxRange;
|
||||
if( distanceSqr < getAttackReachSqr( target ) ) {
|
||||
if( canSee && attackTime <= 0 ) {
|
||||
attackTime = 20;
|
||||
blaze.doHurtTarget( target );
|
||||
}
|
||||
blaze.getMoveControl().setWantedPosition( target.getX(), target.getY(), target.getZ(), 1.0 );
|
||||
}
|
||||
else if( distanceSqr < rangeSq && canSee ) {
|
||||
if( attackTime <= 0 ) {
|
||||
attackStep++;
|
||||
|
||||
if( attackStep == 1 ) {
|
||||
attackTime = data.rangedAttackMaxCooldown - data.rangedAttackCooldown;
|
||||
blaze.setCharged( true );
|
||||
}
|
||||
else if( attackStep <= 1 + blaze.fireballBurstCount ) {
|
||||
attackTime = blaze.fireballBurstDelay;
|
||||
}
|
||||
else {
|
||||
attackTime = data.rangedAttackCooldown;
|
||||
attackStep = 0;
|
||||
blaze.setCharged( false );
|
||||
}
|
||||
|
||||
if( attackStep > 1 ) {
|
||||
blaze.performRangedAttack( target, attackStep );
|
||||
}
|
||||
}
|
||||
blaze.getLookControl().setLookAt( target, 10.0F, 10.0F );
|
||||
}
|
||||
else if( lastSeen < 5 ) {
|
||||
blaze.getMoveControl().setWantedPosition( target.getX(), target.getY(), target.getZ(), 1.0 );
|
||||
}
|
||||
|
||||
super.tick();
|
||||
}
|
||||
|
||||
protected double getAttackReachSqr( LivingEntity target ) {
|
||||
return blaze.getBbWidth() * blaze.getBbWidth() * 4.0F + target.getBbWidth() + 2.0F;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.entity.Entity;
|
||||
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.world.World;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class CinderBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<CinderBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
entityType.sized( 0.5F, 0.9F );
|
||||
return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.DISABLED );
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() )
|
||||
.addAttribute( Attributes.ATTACK_DAMAGE, -2.0 )
|
||||
.multAttribute( Attributes.MOVEMENT_SPEED, 1.3 )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Cinder",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
loot.addCommonDrop( "common", Items.BLAZE_POWDER, 1 );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<CinderBlazeEntity> getVariantFactory() { return CinderBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
public CinderBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().setBaseScale( 0.5F );
|
||||
xpReward = 1;
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
getSpecialData().rangedAttackDamage -= 1.0F;
|
||||
disableRangedAI();
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) {
|
||||
target.setSecondsOnFire( 4 );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.entity.MobHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance;
|
||||
import net.minecraft.entity.projectile.SnowballEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.potion.PotionUtils;
|
||||
import net.minecraft.potion.Potions;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.UUID;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class ConflagrationBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<ConflagrationBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
entityType.sized( 0.9F, 2.7F );
|
||||
return new BestiaryInfo( 0xFFF87E, BestiaryInfo.BaseWeight.LOW );
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Conflagration",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
addBaseLoot( loot );
|
||||
loot.addCommonDrop( "common", Items.FIRE_CHARGE );
|
||||
loot.addRareDrop( "rare", PotionUtils.setPotion( new ItemStack( Items.POTION ), Potions.FIRE_RESISTANCE ) );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<ConflagrationBlazeEntity> getVariantFactory() { return ConflagrationBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
/** The damage boost to apply from growth level. */
|
||||
private static final AttributeModifier DAMAGE_BOOST = new AttributeModifier( UUID.fromString( "70457CAB-AA09-4E1C-B44B-99DD4A2A836D" ),
|
||||
"Feeding damage boost", 1.0, AttributeModifier.Operation.ADDITION );
|
||||
|
||||
/** The level of increased attack damage gained. */
|
||||
private int growthLevel;
|
||||
|
||||
public ConflagrationBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().setBaseScale( 1.5F );
|
||||
xpReward += 4;
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) {
|
||||
if( target instanceof LivingEntity ) {
|
||||
MobHelper.stealLife( this, (LivingEntity) target, 2.0F );
|
||||
}
|
||||
}
|
||||
|
||||
/** @return Attempts to damage this entity; returns true if the hit was successful. */
|
||||
@Override
|
||||
public boolean hurt( DamageSource source, float amount ) {
|
||||
if( isInvulnerableTo( source ) || fireImmune() && source.isFire() ) return false;
|
||||
|
||||
if( !source.isExplosion() && !source.isMagic() && !DamageSource.DROWN.getMsgId().equals( source.getMsgId() ) &&
|
||||
!(source.getDirectEntity() instanceof SnowballEntity) ) {
|
||||
|
||||
if( !level.isClientSide() && growthLevel < 7 ) {
|
||||
growthLevel++;
|
||||
|
||||
getSpecialData().rangedAttackDamage += 0.5F;
|
||||
getSpecialData().rangedAttackCooldown -= 4;
|
||||
getSpecialData().rangedAttackMaxCooldown -= 4;
|
||||
if( growthLevel == 7 ) fireballBurstCount++;
|
||||
|
||||
updateFeedingLevels();
|
||||
}
|
||||
amount /= 2.0F;
|
||||
}
|
||||
return super.hurt( source, amount );
|
||||
}
|
||||
|
||||
/** Recalculates the modifiers associated with this entity's feeding level counters. */
|
||||
private void updateFeedingLevels() {
|
||||
if( level != null && !level.isClientSide ) {
|
||||
final ModifiableAttributeInstance damage = getAttribute( Attributes.ATTACK_DAMAGE );
|
||||
//noinspection ConstantConditions
|
||||
damage.removeModifier( DAMAGE_BOOST.getId() );
|
||||
if( growthLevel > 0 ) {
|
||||
damage.addPermanentModifier( new AttributeModifier( DAMAGE_BOOST.getId(), DAMAGE_BOOST.getName(),
|
||||
DAMAGE_BOOST.getAmount() * growthLevel, DAMAGE_BOOST.getOperation() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Override to save data to this entity's NBT data. */
|
||||
@Override
|
||||
public void addVariantSaveData( CompoundNBT saveTag ) {
|
||||
saveTag.putByte( References.TAG_GROWTH_LEVEL, (byte) growthLevel );
|
||||
}
|
||||
|
||||
/** Override to load data from this entity's NBT data. */
|
||||
@Override
|
||||
public void readVariantSaveData( CompoundNBT saveTag ) {
|
||||
if( saveTag.contains( References.TAG_GROWTH_LEVEL, References.NBT_TYPE_NUMERICAL ) )
|
||||
growthLevel = saveTag.getByte( References.TAG_GROWTH_LEVEL );
|
||||
updateFeedingLevels();
|
||||
}
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = {
|
||||
GET_TEXTURE_PATH( "conflagration" )
|
||||
};
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.entity.MobHelper;
|
||||
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.entity.Entity;
|
||||
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.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class EmberBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<EmberBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
return new BestiaryInfo( 0x000000 );
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() )
|
||||
.addAttribute( Attributes.MAX_HEALTH, 10.0 )
|
||||
.addAttribute( Attributes.ARMOR, 10.0 )
|
||||
.multAttribute( Attributes.MOVEMENT_SPEED, 1.3 )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Ember",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
addBaseLoot( loot );
|
||||
loot.addCommonDrop( "common", Items.COAL, 1 );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<EmberBlazeEntity> getVariantFactory() { return EmberBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
public EmberBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
xpReward += 2;
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
disableRangedAI();
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) {
|
||||
if( target instanceof LivingEntity ) {
|
||||
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
|
||||
}
|
||||
}
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = {
|
||||
GET_TEXTURE_PATH( "ember" )
|
||||
};
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
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.entity.projectile.FireballEntity;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class HellfireBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<HellfireBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
entityType.sized( 0.7F, 1.99F );
|
||||
return new BestiaryInfo( 0xDDDDDD );
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() )
|
||||
.addAttribute( Attributes.MAX_HEALTH, 10.0 )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Hellfire",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
addBaseLoot( loot );
|
||||
loot.addCommonDrop( "common", Items.GUNPOWDER );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<HellfireBlazeEntity> getVariantFactory() { return HellfireBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
/** The base explosion strength of this blaze's fireballs. */
|
||||
private int explosionPower = 2;
|
||||
|
||||
public HellfireBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().setBaseScale( 1.1F );
|
||||
xpReward += 2;
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
getSpecialData().rangedAttackSpread = 0.0F;
|
||||
setRangedAI( 1, 0, 60, 100, 40.0F );
|
||||
}
|
||||
|
||||
/** Called to attack the target with a ranged attack. */
|
||||
@Override
|
||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||
if( !isSilent() ) level.levelEvent( null, 1018, blockPosition(), 0 );
|
||||
|
||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * getSpecialData().rangedAttackSpread / 28.0F;
|
||||
final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance;
|
||||
final double dY = target.getY( 0.5 ) - getY( 0.5 );
|
||||
final double dZ = target.getZ() - getZ() + getRandom().nextGaussian() * accelVariance;
|
||||
|
||||
final FireballEntity fireball = new FireballEntity( level, this, dX, dY, dZ );
|
||||
fireball.explosionPower = explosionPower;
|
||||
fireball.setPos( fireball.getX(), getY( 0.5 ) + 0.5, fireball.getZ() );
|
||||
level.addFreshEntity( fireball );
|
||||
}
|
||||
|
||||
/** Override to save data to this entity's NBT data. */
|
||||
@Override
|
||||
public void addVariantSaveData( CompoundNBT saveTag ) {
|
||||
saveTag.putByte( References.TAG_EXPLOSION_POWER, (byte) explosionPower );
|
||||
}
|
||||
|
||||
/** Override to load data from this entity's NBT data. */
|
||||
@Override
|
||||
public void readVariantSaveData( CompoundNBT saveTag ) {
|
||||
if( saveTag.contains( References.TAG_EXPLOSION_POWER, References.NBT_TYPE_NUMERICAL ) )
|
||||
explosionPower = saveTag.getByte( References.TAG_EXPLOSION_POWER );
|
||||
}
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = {
|
||||
GET_TEXTURE_PATH( "hellfire" )
|
||||
};
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.entity.MobHelper;
|
||||
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.entity.Entity;
|
||||
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.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class InfernoBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<InfernoBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
return new BestiaryInfo( 0xF14F00 );
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() )
|
||||
.addAttribute( Attributes.MAX_HEALTH, 10.0 )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Inferno",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
addBaseLoot( loot );
|
||||
loot.addCommonDrop( "common", Items.BLAZE_POWDER );
|
||||
loot.addSemicommonDrop( "semicommon", Items.FIRE_CHARGE );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<InfernoBlazeEntity> getVariantFactory() { return InfernoBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
public InfernoBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
xpReward += 2;
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
getSpecialData().rangedAttackSpread *= 3.0F;
|
||||
setRangedAI( 12, 2, 80, 100, 20.0F );
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) {
|
||||
if( target instanceof LivingEntity ) {
|
||||
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
|
||||
}
|
||||
}
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = {
|
||||
GET_TEXTURE_PATH( "inferno" )
|
||||
};
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.entity.MobHelper;
|
||||
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||
import fathertoast.specialmobs.common.util.ExplosionHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
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.entity.effect.LightningBoltEntity;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.IndirectEntityDamageSource;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
import net.minecraftforge.event.entity.living.EntityTeleportEvent;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class JoltBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<JoltBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
return new BestiaryInfo( 0x499CAE );
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() )
|
||||
.addAttribute( Attributes.MAX_HEALTH, 10.0 )
|
||||
.addAttribute( Attributes.ARMOR, 10.0 )
|
||||
.multAttribute( Attributes.MOVEMENT_SPEED, 1.3 )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Jolt",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
addBaseLoot( loot );
|
||||
loot.addCommonDrop( "common", Items.REDSTONE );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<JoltBlazeEntity> getVariantFactory() { return JoltBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
public JoltBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
xpReward += 2;
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
disableRangedAI();
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) {
|
||||
if( target instanceof LivingEntity ) {
|
||||
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
|
||||
}
|
||||
}
|
||||
|
||||
/** Called each tick to update this entity's movement. */
|
||||
@Override
|
||||
public void aiStep() {
|
||||
if( !level.isClientSide() && isAlive() && getTarget() != null && random.nextInt( 20 ) == 0 &&
|
||||
distanceToSqr( getTarget() ) > 256.0 ) {
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
if( teleportTowards( getTarget() ) ) break;
|
||||
}
|
||||
}
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
/** @return Attempts to damage this entity; returns true if the hit was successful. */
|
||||
@Override
|
||||
public boolean hurt( DamageSource source, float amount ) {
|
||||
if( isInvulnerableTo( source ) || fireImmune() && source.isFire() ) return false;
|
||||
|
||||
if( source instanceof IndirectEntityDamageSource ) {
|
||||
for( int i = 0; i < 64; i++ ) {
|
||||
if( teleport() ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean success = super.hurt( source, amount );
|
||||
if( !level.isClientSide() && getHealth() > 0.0F ) {
|
||||
if( source.getEntity() instanceof LivingEntity ) {
|
||||
for( int i = 0; i < 16; i++ ) {
|
||||
if( teleport() ) break;
|
||||
}
|
||||
}
|
||||
else if( random.nextInt( 10 ) != 0 ) {
|
||||
teleport();
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/** @return Teleports this "enderman" to a random nearby position; returns true if successful. */
|
||||
protected boolean teleport() {
|
||||
if( level.isClientSide() || !isAlive() ) return false;
|
||||
|
||||
final double x = getX() + (random.nextDouble() - 0.5) * 32.0;
|
||||
final double y = getY() + (double) (random.nextInt( 16 ) - 8);
|
||||
final double z = getZ() + (random.nextDouble() - 0.5) * 32.0;
|
||||
return teleport( x, y, z );
|
||||
}
|
||||
|
||||
/** @return Teleports this "enderman" towards another entity; returns true if successful. */
|
||||
protected boolean teleportTowards( Entity target ) {
|
||||
final Vector3d directionFromTarget = new Vector3d(
|
||||
getX() - target.getX(),
|
||||
getY( 0.5 ) - target.getEyeY(),
|
||||
getZ() - target.getZ() )
|
||||
.normalize();
|
||||
|
||||
final double x = getX() + (random.nextDouble() - 0.5) * 8.0 - directionFromTarget.x * 16.0;
|
||||
final double y = getY() + (double) (random.nextInt( 8 ) - 2) - directionFromTarget.y * 16.0;
|
||||
final double z = getZ() + (random.nextDouble() - 0.5) * 8.0 - directionFromTarget.z * 16.0;
|
||||
return teleport( x, y, z );
|
||||
}
|
||||
|
||||
/** @return Teleports this "enderman" to a new position; returns true if successful. */
|
||||
protected boolean teleport( double x, double y, double z ) {
|
||||
final BlockPos.Mutable pos = new BlockPos.Mutable( x, y, z );
|
||||
|
||||
while( pos.getY() > 0 && !level.getBlockState( pos ).getMaterial().blocksMotion() ) {
|
||||
pos.move( Direction.DOWN );
|
||||
}
|
||||
|
||||
final BlockState block = level.getBlockState( pos );
|
||||
if( !block.getMaterial().blocksMotion() || block.getFluidState().is( FluidTags.WATER ) ) return false;
|
||||
|
||||
EntityTeleportEvent.EnderEntity event = ForgeEventFactory.onEnderTeleport( this, x, y, z );
|
||||
if( event.isCanceled() ) return false;
|
||||
|
||||
final boolean success = randomTeleport( event.getTargetX(), event.getTargetY(), event.getTargetZ(), false );
|
||||
if( success ) {
|
||||
ExplosionHelper.spawnLightning( level, xo, yo, zo );
|
||||
ExplosionHelper.spawnLightning( level, getX(), getY(), getZ() );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/** Called when this entity is struck by lightning. */
|
||||
@Override
|
||||
public void thunderHit( ServerWorld world, LightningBoltEntity lightningBolt ) { }
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = {
|
||||
GET_TEXTURE_PATH( "jolt" )
|
||||
};
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.util.AttributeHelper;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.entity.*;
|
||||
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.util.ResourceLocation;
|
||||
import net.minecraft.world.IServerWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class WildfireBlazeEntity extends _SpecialBlazeEntity {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<WildfireBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
entityType.sized( 0.9F, 2.7F );
|
||||
return new BestiaryInfo( 0xF4EE32 );
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() )
|
||||
.addAttribute( Attributes.MAX_HEALTH, 20.0 )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Wildfire",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void buildLootTable( LootTableBuilder loot ) {
|
||||
addBaseLoot( loot );
|
||||
loot.addCommonDrop( "common", Items.COAL, 1 );
|
||||
loot.addUncommonDrop( "uncommon", Items.BLAZE_SPAWN_EGG );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<WildfireBlazeEntity> getVariantFactory() { return WildfireBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
/** The number of babies spawned on death. */
|
||||
private int babies;
|
||||
/** The number of extra babies that can be spawned by attacks. */
|
||||
private int extraBabies;
|
||||
|
||||
public WildfireBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().setBaseScale( 1.5F );
|
||||
getSpecialData().setRegenerationTime( 40 );
|
||||
xpReward += 2;
|
||||
|
||||
babies = 2 + random.nextInt( 3 );
|
||||
extraBabies = 3 + random.nextInt( 4 );
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
getSpecialData().rangedAttackSpread *= 0.1F;
|
||||
setRangedAI( 1, 0, 30, 50, 20.0F );
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) {
|
||||
target.setSecondsOnFire( 8 );
|
||||
}
|
||||
|
||||
/** Called to attack the target with a ranged attack. */
|
||||
@Override
|
||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||
if( !level.isClientSide() && extraBabies > 0 && random.nextInt( 2 ) == 0 ) {
|
||||
extraBabies--;
|
||||
|
||||
final double vX = target.getX() - getX();
|
||||
final double vZ = target.getZ() - getZ();
|
||||
final double vH = Math.sqrt( vX * vX + vZ * vZ );
|
||||
spawnBaby( vX / vH * 0.8 + getDeltaMovement().x * 0.2, vZ / vH * 0.8 + getDeltaMovement().z * 0.2, null );
|
||||
spawnAnim();
|
||||
if( !isSilent() ) level.levelEvent( null, 1018, blockPosition(), 0 );
|
||||
}
|
||||
else {
|
||||
super.performRangedAttack( target, damageMulti );
|
||||
}
|
||||
}
|
||||
|
||||
/** Called to remove this entity from the world. Includes death, unloading, interdimensional travel, etc. */
|
||||
@Override
|
||||
public void remove( boolean keepData ) {
|
||||
//noinspection deprecation
|
||||
if( isDeadOrDying() && !removed && level instanceof IServerWorld ) { // Same conditions as slime splitting
|
||||
// Spawn babies on death
|
||||
final int babiesToSpawn = babies + extraBabies;
|
||||
ILivingEntityData groupData = null;
|
||||
for( int i = 0; i < babiesToSpawn; i++ ) {
|
||||
groupData = spawnBaby( (random.nextDouble() - 0.5) * 0.3, (random.nextDouble() - 0.5) * 0.3, groupData );
|
||||
}
|
||||
spawnAnim();
|
||||
if( !isSilent() ) level.levelEvent( null, 1018, blockPosition(), 0 );
|
||||
}
|
||||
super.remove( keepData );
|
||||
}
|
||||
|
||||
/** Helper method to simplify spawning babies. */
|
||||
@Nullable
|
||||
private ILivingEntityData spawnBaby( double vX, double vZ, @Nullable ILivingEntityData groupData ) {
|
||||
final CinderBlazeEntity baby = CinderBlazeEntity.SPECIES.entityType.get().create( level );
|
||||
if( baby == null ) return groupData;
|
||||
|
||||
baby.copyPosition( this );
|
||||
baby.yHeadRot = yRot;
|
||||
baby.yBodyRot = yRot;
|
||||
groupData = baby.finalizeSpawn( (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ),
|
||||
SpawnReason.MOB_SUMMONED, groupData, null );
|
||||
baby.setTarget( getTarget() );
|
||||
|
||||
baby.setDeltaMovement( vX, 0.0, vZ );
|
||||
baby.setOnGround( false );
|
||||
|
||||
level.addFreshEntity( baby );
|
||||
return groupData;
|
||||
}
|
||||
|
||||
/** Override to save data to this entity's NBT data. */
|
||||
@Override
|
||||
public void addVariantSaveData( CompoundNBT saveTag ) {
|
||||
saveTag.putByte( References.TAG_BABIES, (byte) babies );
|
||||
saveTag.putByte( References.TAG_EXTRA_BABIES, (byte) extraBabies );
|
||||
}
|
||||
|
||||
/** Override to load data from this entity's NBT data. */
|
||||
@Override
|
||||
public void readVariantSaveData( CompoundNBT saveTag ) {
|
||||
if( saveTag.contains( References.TAG_BABIES, References.NBT_TYPE_NUMERICAL ) )
|
||||
babies = saveTag.getByte( References.TAG_BABIES );
|
||||
if( saveTag.contains( References.TAG_EXTRA_BABIES, References.NBT_TYPE_NUMERICAL ) )
|
||||
extraBabies = saveTag.getByte( References.TAG_EXTRA_BABIES );
|
||||
}
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = {
|
||||
GET_TEXTURE_PATH( "wildfire" )
|
||||
};
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
package fathertoast.specialmobs.common.entity.blaze;
|
||||
|
||||
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
|
||||
import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||
import fathertoast.specialmobs.common.bestiary.SpecialMob;
|
||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||
import fathertoast.specialmobs.common.entity.ISpecialMob;
|
||||
import fathertoast.specialmobs.common.entity.SpecialMobData;
|
||||
import fathertoast.specialmobs.common.entity.ai.AIHelper;
|
||||
import fathertoast.specialmobs.common.entity.ai.SpecialBlazeAttackGoal;
|
||||
import fathertoast.specialmobs.common.entity.ai.SpecialHurtByTargetGoal;
|
||||
import fathertoast.specialmobs.common.util.References;
|
||||
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifierMap;
|
||||
import net.minecraft.entity.monster.BlazeEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.projectile.SmallFireballEntity;
|
||||
import net.minecraft.entity.projectile.SnowballEntity;
|
||||
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.potion.EffectInstance;
|
||||
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.DifficultyInstance;
|
||||
import net.minecraft.world.IServerWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@SpecialMob
|
||||
public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob, ISpecialMob<_SpecialBlazeEntity> {
|
||||
|
||||
//--------------- Static Special Mob Hooks ----------------
|
||||
|
||||
@SpecialMob.SpeciesReference
|
||||
public static MobFamily.Species<_SpecialBlazeEntity> SPECIES;
|
||||
|
||||
@SpecialMob.BestiaryInfoSupplier
|
||||
public static BestiaryInfo bestiaryInfo( EntityType.Builder<LivingEntity> entityType ) {
|
||||
return new BestiaryInfo( 0xFFF87E ); //TODO - TEMP: base size = 0.6F, 1.8F
|
||||
}
|
||||
|
||||
@SpecialMob.AttributeCreator
|
||||
public static AttributeModifierMap.MutableAttribute createAttributes() {
|
||||
return BlazeEntity.createAttributes();
|
||||
}
|
||||
|
||||
@SpecialMob.LanguageProvider
|
||||
public static String[] getTranslations( String langKey ) {
|
||||
return References.translations( langKey, "Blaze",
|
||||
"", "", "", "", "", "" );//TODO
|
||||
}
|
||||
|
||||
@SpecialMob.LootTableProvider
|
||||
public static void addBaseLoot( LootTableBuilder loot ) {
|
||||
loot.addLootTable( "main", EntityType.BLAZE.getDefaultLootTable() );
|
||||
}
|
||||
|
||||
@SpecialMob.Factory
|
||||
public static EntityType.IFactory<_SpecialBlazeEntity> getFactory() { return _SpecialBlazeEntity::new; }
|
||||
|
||||
|
||||
//--------------- Variant-Specific Breakouts ----------------
|
||||
|
||||
public _SpecialBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().initialize();
|
||||
getSpecialData().setDamagedByWater( true );
|
||||
}
|
||||
|
||||
/** Called in the MobEntity.class constructor to initialize AI goals. */
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
super.registerGoals();
|
||||
AIHelper.removeGoals( goalSelector, 4 ); // BlazeEntity.FireballAttackGoal
|
||||
goalSelector.addGoal( 4, new SpecialBlazeAttackGoal( this ) );
|
||||
AIHelper.replaceHurtByTarget( this, new SpecialHurtByTargetGoal( this, BlazeEntity.class ).setAlertOthers() );
|
||||
|
||||
setRangedAI( 3, 6, 60, 100, 48.0F );
|
||||
registerVariantGoals();
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
protected void registerVariantGoals() { }
|
||||
|
||||
/** Helper method to set the ranged attack AI more easily. */
|
||||
protected void disableRangedAI() {
|
||||
setRangedAI( 0, 6, 60, 100, 0.0F );
|
||||
}
|
||||
|
||||
/** Helper method to set the ranged attack AI more easily. */
|
||||
protected void setRangedAI( int burstCount, int burstDelay, int chargeTime, int cooldownTime, float range ) {
|
||||
fireballBurstCount = burstCount;
|
||||
fireballBurstDelay = burstDelay;
|
||||
|
||||
getSpecialData().rangedAttackCooldown = cooldownTime;
|
||||
getSpecialData().rangedAttackMaxCooldown = cooldownTime + chargeTime;
|
||||
getSpecialData().rangedAttackMaxRange = range;
|
||||
}
|
||||
|
||||
/** Called when this entity successfully damages a target to apply on-hit effects. */
|
||||
@Override
|
||||
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
|
||||
onVariantAttack( target );
|
||||
super.doEnchantDamageEffects( attacker, target );
|
||||
}
|
||||
|
||||
/** Override to apply effects when this entity hits a target with a melee attack. */
|
||||
protected void onVariantAttack( Entity target ) { }
|
||||
|
||||
/** Override to save data to this entity's NBT data. */
|
||||
public void addVariantSaveData( CompoundNBT saveTag ) { }
|
||||
|
||||
/** Override to load data from this entity's NBT data. */
|
||||
public void readVariantSaveData( CompoundNBT saveTag ) { }
|
||||
|
||||
|
||||
//--------------- Family-Specific Implementations ----------------
|
||||
|
||||
/** The parameter for special mob render scale. */
|
||||
private static final DataParameter<Float> SCALE = EntityDataManager.defineId( _SpecialBlazeEntity.class, DataSerializers.FLOAT );
|
||||
|
||||
// The amount of fireballs in each burst.
|
||||
public int fireballBurstCount;
|
||||
// The ticks between each shot in a burst.
|
||||
public int fireballBurstDelay;
|
||||
|
||||
/** Called from the Entity.class constructor to define data watcher variables. */
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
specialData = new SpecialMobData<>( this, SCALE, 1.0F );
|
||||
}
|
||||
|
||||
/** Called to attack the target with a ranged attack. */
|
||||
@Override
|
||||
public void performRangedAttack( LivingEntity target, float damageMulti ) {
|
||||
if( !isSilent() ) level.levelEvent( null, 1018, blockPosition(), 0 );
|
||||
|
||||
final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * getSpecialData().rangedAttackSpread / 28.0F;
|
||||
final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance;
|
||||
final double dY = target.getY( 0.5 ) - getY( 0.5 );
|
||||
final double dZ = target.getZ() - getZ() + getRandom().nextGaussian() * accelVariance;
|
||||
|
||||
final SmallFireballEntity fireball = new SmallFireballEntity( level, this, dX, dY, dZ );
|
||||
fireball.setPos( fireball.getX(), getY( 0.5 ) + 0.5, fireball.getZ() );
|
||||
level.addFreshEntity( fireball );
|
||||
}
|
||||
|
||||
/** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */
|
||||
@Nullable
|
||||
public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason,
|
||||
@Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) {
|
||||
groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag );
|
||||
// TODO ranged attack
|
||||
return groupData;
|
||||
}
|
||||
|
||||
|
||||
//--------------- ISpecialMob Implementation ----------------
|
||||
|
||||
private SpecialMobData<_SpecialBlazeEntity> specialData;
|
||||
|
||||
/** @return This mob's special data. */
|
||||
@Override
|
||||
public SpecialMobData<_SpecialBlazeEntity> getSpecialData() { return specialData; }
|
||||
|
||||
/** @return The experience that should be dropped by this entity. */
|
||||
@Override
|
||||
public final int getExperience() { return xpReward; }
|
||||
|
||||
/** Sets the experience that should be dropped by this entity. */
|
||||
@Override
|
||||
public final void setExperience( int xp ) { xpReward = xp; }
|
||||
|
||||
static ResourceLocation GET_TEXTURE_PATH( String type ) {
|
||||
return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "blaze/" + type + ".png" );
|
||||
}
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/blaze.png" ) };
|
||||
|
||||
/** @return All default textures for this entity. */
|
||||
@Override
|
||||
public ResourceLocation[] getDefaultTextures() { return TEXTURES; }
|
||||
|
||||
|
||||
//--------------- SpecialMobData Hooks ----------------
|
||||
|
||||
/** Called each tick to update this entity's movement. */
|
||||
@Override
|
||||
public void aiStep() {
|
||||
super.aiStep();
|
||||
getSpecialData().tick();
|
||||
}
|
||||
|
||||
/** @return The eye height of this entity when standing. */
|
||||
@Override
|
||||
protected float getStandingEyeHeight( Pose pose, EntitySize size ) {
|
||||
return super.getStandingEyeHeight( pose, size ) * getSpecialData().getBaseScale() * (isBaby() ? 0.53448F : 1.0F);
|
||||
}
|
||||
|
||||
/** @return Whether this entity is immune to fire damage. */
|
||||
@Override
|
||||
public boolean fireImmune() { return getSpecialData().isImmuneToFire(); }
|
||||
|
||||
/** Sets this entity on fire for a specific duration. */
|
||||
@Override
|
||||
public void setRemainingFireTicks( int ticks ) {
|
||||
if( !getSpecialData().isImmuneToBurning() ) super.setRemainingFireTicks( ticks );
|
||||
}
|
||||
|
||||
/** @return True if this entity can be leashed. */
|
||||
@Override
|
||||
public boolean canBeLeashed( PlayerEntity player ) { return !isLeashed() && getSpecialData().allowLeashing(); }
|
||||
|
||||
/** Sets this entity 'stuck' inside a block, such as a cobweb or sweet berry bush. Mod blocks could use this as a speed boost. */
|
||||
@Override
|
||||
public void makeStuckInBlock( BlockState block, Vector3d speedMulti ) {
|
||||
if( getSpecialData().canBeStuckIn( block ) ) super.makeStuckInBlock( block, speedMulti );
|
||||
}
|
||||
|
||||
/** @return Called when this mob falls. Calculates and applies fall damage. Returns false if canceled. */
|
||||
@Override
|
||||
public boolean causeFallDamage( float distance, float damageMultiplier ) {
|
||||
return super.causeFallDamage( distance, damageMultiplier * getSpecialData().getFallDamageMultiplier() );
|
||||
}
|
||||
|
||||
/** @return True if this entity should NOT trigger pressure plates or tripwires. */
|
||||
@Override
|
||||
public boolean isIgnoringBlockTriggers() { return getSpecialData().ignorePressurePlates(); }
|
||||
|
||||
/** @return True if this entity can breathe underwater. */
|
||||
@Override
|
||||
public boolean canBreatheUnderwater() { return getSpecialData().canBreatheInWater(); }
|
||||
|
||||
/** @return True if this entity can be pushed by (flowing) fluids. */
|
||||
@Override
|
||||
public boolean isPushedByFluid() { return !getSpecialData().ignoreWaterPush(); }
|
||||
|
||||
/** @return True if this entity takes damage while wet. */
|
||||
@Override
|
||||
public boolean isSensitiveToWater() { return getSpecialData().isDamagedByWater(); }
|
||||
|
||||
/** @return Attempts to damage this entity; returns true if the hit was successful. */
|
||||
@Override
|
||||
public boolean hurt( DamageSource source, float amount ) {
|
||||
if( source.getDirectEntity() instanceof SnowballEntity ) {
|
||||
if( isSensitiveToWater() ) amount = Math.max( 3.0F, amount );
|
||||
else amount = 0.0F; // Allow blazes to be insensitive to snowballs
|
||||
}
|
||||
return super.hurt( source, amount );
|
||||
}
|
||||
|
||||
/** @return True if the effect can be applied to this entity. */
|
||||
@Override
|
||||
public boolean canBeAffected( EffectInstance effect ) { return getSpecialData().isPotionApplicable( effect ); }
|
||||
|
||||
/** Saves data to this entity's base NBT compound that is specific to its subclass. */
|
||||
@Override
|
||||
public void addAdditionalSaveData( CompoundNBT tag ) {
|
||||
super.addAdditionalSaveData( tag );
|
||||
|
||||
final CompoundNBT saveTag = SpecialMobData.getSaveLocation( tag );
|
||||
|
||||
saveTag.putByte( References.TAG_BURST_COUNT, (byte) fireballBurstCount );
|
||||
saveTag.putByte( References.TAG_BURST_DELAY, (byte) fireballBurstDelay );
|
||||
|
||||
getSpecialData().writeToNBT( saveTag );
|
||||
addVariantSaveData( saveTag );
|
||||
}
|
||||
|
||||
/** Loads data from this entity's base NBT compound that is specific to its subclass. */
|
||||
@Override
|
||||
public void readAdditionalSaveData( CompoundNBT tag ) {
|
||||
super.readAdditionalSaveData( tag );
|
||||
|
||||
final CompoundNBT saveTag = SpecialMobData.getSaveLocation( tag );
|
||||
|
||||
if( saveTag.contains( References.TAG_BURST_COUNT, References.NBT_TYPE_NUMERICAL ) )
|
||||
fireballBurstCount = saveTag.getByte( References.TAG_BURST_COUNT );
|
||||
if( saveTag.contains( References.TAG_BURST_DELAY, References.NBT_TYPE_NUMERICAL ) )
|
||||
fireballBurstDelay = saveTag.getByte( References.TAG_BURST_DELAY );
|
||||
|
||||
getSpecialData().readFromNBT( saveTag );
|
||||
readVariantSaveData( saveTag );
|
||||
}
|
||||
}
|
|
@ -189,11 +189,11 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob<
|
|||
/** Called when this entity is struck by lightning. */
|
||||
@Override
|
||||
public void thunderHit( ServerWorld world, LightningBoltEntity lightningBolt ) {
|
||||
if (!isPowered() && random.nextDouble() < 0.1D)
|
||||
setSupercharged(true);
|
||||
|
||||
if( !isPowered() && random.nextDouble() < 0.1D )
|
||||
setSupercharged( true );
|
||||
|
||||
super.thunderHit( world, lightningBolt );
|
||||
|
||||
|
||||
// Make it less likely for charged "explode while burning" creepers to immediately explode
|
||||
if( explodesWhileBurning() ) clearFire();
|
||||
}
|
||||
|
@ -222,13 +222,13 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob<
|
|||
private static final byte EXPLODE_FLAG_ON_FIRE = 0b0010;
|
||||
/** The bit for "explodes when shot". */
|
||||
private static final byte EXPLODE_FLAG_WHEN_SHOT = 0b0100;
|
||||
|
||||
|
||||
|
||||
|
||||
/** @return True if this creeper is super charged. */
|
||||
public boolean isSupercharged() {
|
||||
return entityData.get( IS_SUPERCHARGED );
|
||||
}
|
||||
|
||||
|
||||
/** Sets this creeper's supercharged state to the given value. */
|
||||
public void setSupercharged( boolean superCharged ) {
|
||||
entityData.set( IS_SUPERCHARGED, superCharged );
|
||||
|
@ -385,8 +385,9 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob<
|
|||
super.addAdditionalSaveData( tag );
|
||||
|
||||
final CompoundNBT saveTag = SpecialMobData.getSaveLocation( tag );
|
||||
|
||||
|
||||
saveTag.putBoolean( References.TAG_SUPERCHARGED, isSupercharged() );
|
||||
|
||||
saveTag.putBoolean( References.TAG_DRY_EXPLODE, cannotExplodeWhileWet() );
|
||||
saveTag.putBoolean( References.TAG_WHEN_BURNING_EXPLODE, explodesWhileBurning() );
|
||||
saveTag.putBoolean( References.TAG_WHEN_SHOT_EXPLODE, explodesWhenShot() );
|
||||
|
@ -401,9 +402,10 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob<
|
|||
super.readAdditionalSaveData( tag );
|
||||
|
||||
final CompoundNBT saveTag = SpecialMobData.getSaveLocation( tag );
|
||||
|
||||
setSupercharged( saveTag.getBoolean(References.TAG_SUPERCHARGED) );
|
||||
|
||||
|
||||
if( saveTag.contains( References.TAG_SUPERCHARGED, References.NBT_TYPE_NUMERICAL ) )
|
||||
setSupercharged( saveTag.getBoolean( References.TAG_SUPERCHARGED ) );
|
||||
|
||||
if( saveTag.contains( References.TAG_DRY_EXPLODE, References.NBT_TYPE_NUMERICAL ) )
|
||||
setCannotExplodeWhileWet( saveTag.getBoolean( References.TAG_DRY_EXPLODE ) );
|
||||
if( saveTag.contains( References.TAG_WHEN_BURNING_EXPLODE, References.NBT_TYPE_NUMERICAL ) )
|
||||
|
|
|
@ -71,13 +71,6 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity {
|
|||
|
||||
//--------------- Variant-Specific Implementations ----------------
|
||||
|
||||
public HungrySpiderEntity( EntityType<? extends _SpecialSpiderEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().setBaseScale( 1.5F );
|
||||
getSpecialData().setRegenerationTime( 40 );
|
||||
xpReward += 2;
|
||||
}
|
||||
|
||||
/** The damage boost to apply from growth level. */
|
||||
private static final AttributeModifier DAMAGE_BOOST = new AttributeModifier( UUID.fromString( "70457CAB-AA09-4E1C-B44B-99DD4A2A836D" ),
|
||||
"Feeding damage boost", 1.0, AttributeModifier.Operation.ADDITION );
|
||||
|
@ -90,6 +83,13 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity {
|
|||
/** The level of increased max health gained. */
|
||||
private int maxHealthStacks;
|
||||
|
||||
public HungrySpiderEntity( EntityType<? extends _SpecialSpiderEntity> entityType, World world ) {
|
||||
super( entityType, world );
|
||||
getSpecialData().setBaseScale( 1.5F );
|
||||
getSpecialData().setRegenerationTime( 40 );
|
||||
xpReward += 2;
|
||||
}
|
||||
|
||||
/** Override to change this entity's AI goals. */
|
||||
@Override
|
||||
protected void registerVariantGoals() {
|
||||
|
|
|
@ -74,7 +74,7 @@ public class MotherSpiderEntity extends _SpecialSpiderEntity {
|
|||
xpReward += 1;
|
||||
|
||||
babies = 2 + random.nextInt( 3 );
|
||||
extraBabies = 2 + random.nextInt( 3 );
|
||||
extraBabies = 3 + random.nextInt( 4 );
|
||||
}
|
||||
|
||||
/** The number of babies spawned on death. */
|
||||
|
|
|
@ -22,8 +22,6 @@ public final class References {
|
|||
//--------------- ENTITY EVENTS ----------------
|
||||
// Used in World#broadcastEntityEvent(Entity, byte) then executed by Entity#handleEntityEvent(byte)
|
||||
|
||||
public static final byte EVENT_SHIELD_BLOCK_SOUND = 29;
|
||||
public static final byte EVENT_SHIELD_BREAK_SOUND = 30;
|
||||
public static final byte EVENT_TELEPORT_TRAIL_PARTICLES = 46;
|
||||
|
||||
|
||||
|
@ -60,13 +58,17 @@ public final class References {
|
|||
public static final String TAG_WATER_DAMAGE = "WaterDamage";
|
||||
public static final String TAG_STICKY_IMMUNE = "StickyImmune";
|
||||
public static final String TAG_POTION_IMMUNE = "PotionImmune";
|
||||
public static final String TAG_SUPERCHARGED = "Supercharged";
|
||||
|
||||
// Creepers
|
||||
public static final String TAG_SUPERCHARGED = "Supercharged";
|
||||
public static final String TAG_DRY_EXPLODE = "CannotExplodeWhileWet";
|
||||
public static final String TAG_WHEN_BURNING_EXPLODE = "ExplodesWhileBurning";
|
||||
public static final String TAG_WHEN_SHOT_EXPLODE = "ExplodesWhenShot";
|
||||
|
||||
// Blazes
|
||||
public static final String TAG_BURST_COUNT = "FireballBurstCount";
|
||||
public static final String TAG_BURST_DELAY = "FireballBurstDelay";
|
||||
|
||||
// Baby-able families - Skeletons, Wither Skeletons
|
||||
public static final String TAG_IS_BABY = "IsBaby";
|
||||
|
||||
|
@ -75,13 +77,14 @@ public final class References {
|
|||
public static final String TAG_EXTRA_BABIES = "ExtraBabies"; // Splitting Creeper, Mother (Cave) Spider
|
||||
|
||||
// Growing mobs
|
||||
public static final String TAG_GROWTH_LEVEL = "GrowthLevel"; // Hungry Spider
|
||||
public static final String TAG_GROWTH_LEVEL = "GrowthLevel"; // Hungry Spider, Conflagration Blaze
|
||||
public static final String TAG_HEALTH_STACKS = "HealthStacks"; // Hungry Spider
|
||||
|
||||
// Misc.
|
||||
public static final String TAG_FUSE_TIME = "FuseTime"; // Blackberry Slime, Volatile Magma Cube
|
||||
public static final String TAG_AMMO = "Ammo"; // Web (Cave) Spider
|
||||
public static final String TAG_IS_FAKE = "IsFake"; // Mirage Enderman
|
||||
public static final String TAG_EXPLOSION_POWER = "ExplosionPower"; // Hellfire Blaze
|
||||
|
||||
|
||||
//--------------- INTERNATIONALIZATION ----------------
|
||||
|
|
|
@ -18,4 +18,7 @@ protected net.minecraft.entity.monster.CreeperEntity func_190741_do()V # spawnLi
|
|||
|
||||
# Endermen
|
||||
protected net.minecraft.entity.monster.EndermanEntity func_70816_c(Lnet/minecraft/entity/Entity;)Z # teleportTowards(Entity)
|
||||
protected net.minecraft.entity.monster.EndermanEntity func_70825_j(DDD)Z # teleport(x,y,z)
|
||||
protected net.minecraft.entity.monster.EndermanEntity func_70825_j(DDD)Z # teleport(x,y,z)
|
||||
|
||||
# Blazes
|
||||
public net.minecraft.entity.monster.BlazeEntity func_70844_e(Z)V # setCharged(value)
|
Loading…
Add table
Reference in a new issue