Merge branch '1.16.5' of https://github.com/FatherToast/SpecialMobs into 1.16.5

This commit is contained in:
Sarinsa 2022-07-27 01:31:00 +02:00
commit 65e5a1f280
115 changed files with 1523 additions and 549 deletions

View file

@ -6,6 +6,7 @@ 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.slime.PotionSlimeEntity;
import fathertoast.specialmobs.common.entity.witherskeleton.NinjaWitherSkeletonEntity;
import fathertoast.specialmobs.common.entity.zombie.MadScientistZombieEntity;
import fathertoast.specialmobs.common.entity.zombifiedpiglin.VampireZombifiedPiglinEntity;
@ -58,6 +59,8 @@ public class ClientRegister {
registerSpeciesRenderer( NinjaSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
registerSpeciesRenderer( NinjaWitherSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new );
registerSpeciesRenderer( PotionSlimeEntity.SPECIES, PotionSlimeRenderer::new );
registerSpeciesRenderer( CorporealShiftGhastEntity.SPECIES, CorporealShiftGhastRenderer::new );
// Other

View file

@ -0,0 +1,26 @@
package fathertoast.specialmobs.client.renderer.entity;
import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobTintedLayer;
import fathertoast.specialmobs.common.entity.slime.PotionSlimeEntity;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.entity.IEntityRenderer;
import net.minecraft.client.renderer.entity.model.SlimeModel;
import net.minecraft.entity.monster.SlimeEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn( Dist.CLIENT )
public class PotionSlimeRenderer extends SpecialSlimeRenderer {
public PotionSlimeRenderer( EntityRendererManager rendererManager ) {
super( rendererManager );
addLayer( new PotionSlimeLayer( this ) );
}
private static class PotionSlimeLayer extends SpecialMobTintedLayer<SlimeEntity, SlimeModel<SlimeEntity>> {
public PotionSlimeLayer( IEntityRenderer<SlimeEntity, SlimeModel<SlimeEntity>> renderer ) { super( renderer ); }
@Override
protected int getColor( SlimeEntity entity ) { return ((PotionSlimeEntity) entity).getPotionColor(); }
}
}

View file

@ -30,7 +30,7 @@ public class SpecialMobEyesLayer<T extends Entity, M extends EntityModel<T>> ext
final IVertexBuilder vertexBuilder = buffer.getBuffer( RenderType.eyes( eyesTexture ) );
getParentModel().renderToBuffer( matrixStack, vertexBuilder, LightTexture.pack( 15, 15 ), OverlayTexture.NO_OVERLAY,
1.0F, 1.0F, 1.0F, 1.0F );
1.0F, 1.0F, 1.0F, 1.0F ); // RGBA
}
@Override

View file

@ -27,17 +27,17 @@ public class SpecialMobOverlayLayer<T extends Entity, M extends EntityModel<T>>
@Override
public void render( MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight, T entity,
float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch ) {
if( entity.isInvisible() ) return;
final ResourceLocation overlayTexture = ((ISpecialMob<?>) entity).getSpecialData().getTextureOverlay();
if( overlayTexture == null ) return;
if( !entity.isInvisible() ) {
getParentModel().copyPropertiesTo( layerModel );
layerModel.prepareMobModel( entity, limbSwing, limbSwingAmount, partialTicks );
layerModel.setupAnim( entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch );
final IVertexBuilder vertexBuilder = buffer.getBuffer( RenderType.entityCutoutNoCull( overlayTexture ) );
layerModel.renderToBuffer( matrixStack, vertexBuilder, packedLight, OverlayTexture.NO_OVERLAY,
1.0F, 1.0F, 1.0F, 1.0F ); // RGBA
}
getParentModel().copyPropertiesTo( layerModel );
layerModel.prepareMobModel( entity, limbSwing, limbSwingAmount, partialTicks );
layerModel.setupAnim( entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch );
final IVertexBuilder vertexBuilder = buffer.getBuffer( RenderType.entityCutoutNoCull( overlayTexture ) );
layerModel.renderToBuffer( matrixStack, vertexBuilder, packedLight, OverlayTexture.NO_OVERLAY,
1.0F, 1.0F, 1.0F, 1.0F ); // RGBA
}
}

View file

@ -0,0 +1,37 @@
package fathertoast.specialmobs.client.renderer.entity.layers;
import com.mojang.blaze3d.matrix.MatrixStack;
import fathertoast.specialmobs.common.entity.ISpecialMob;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.entity.IEntityRenderer;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.client.renderer.entity.model.EntityModel;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn( Dist.CLIENT )
public abstract class SpecialMobTintedLayer<T extends LivingEntity, M extends EntityModel<T>> extends LayerRenderer<T, M> {
public SpecialMobTintedLayer( IEntityRenderer<T, M> renderer ) { super( renderer ); }
/** @return The color to tint this layer. */
protected abstract int getColor( T entity );
@Override
public void render( MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight, T entity, float limbSwing,
float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch ) {
if( entity.isInvisible() ) return;
final ResourceLocation overlayTexture = ((ISpecialMob<?>) entity).getSpecialData().getTextureOverlay();
if( overlayTexture == null ) return;
final int color = getColor( entity );
final float r = (float) ((color >> 16) & 0xff) / (float) 0xff;
final float g = (float) ((color >> 8) & 0xff) / (float) 0xff;
final float b = (float) (color & 0xff) / (float) 0xff;
renderColoredCutoutModel( getParentModel(), overlayTexture, matrixStack, buffer, packedLight, entity, r, g, b );
}
}

View file

@ -227,8 +227,12 @@ public class BestiaryInfo {
owningSpecies = species;
entityTypeBuilder = typeBuilder;
// Special variants should copy many of the vanilla replacement's stats
if( species.specialVariantName != null ) {
if( species.specialVariantName == null ) {
// Fire immunity should be copied from the entity type
if( species.family.replaceableTypes[0].fireImmune() ) isImmuneToFire = true;
}
else {
// Special variants should copy many of the vanilla replacement's stats
final BestiaryInfo parent = species.family.vanillaReplacement.bestiaryInfo;
baseScale = parent.baseScale;

View file

@ -45,21 +45,21 @@ public class MobFamily<T extends LivingEntity, V extends FamilyConfig> {
public static final MobFamily<ZombieEntity, FamilyConfig> ZOMBIE = new MobFamily<>( FamilyConfig::newLessSpecial,
"Zombie", "zombies", 0x00AFAF, new EntityType[] { EntityType.ZOMBIE, EntityType.HUSK },
"Brute", "Fire", /*"Fishing",*/ "Giant", "Hungry", "Husk", "MadScientist", "Plague"
"Brute", "Fire", "Fishing", "Giant", "Hungry", "Husk", "MadScientist", "Plague"
);//TODO fishing
// TODO Drowned family and zombie transform mechanic
// public static final MobFamily<ZombieEntity, FamilyConfig> DROWNED = new MobFamily<>( FamilyConfig::new,
// "Zombie", "zombies", 0x8FF1D7, new EntityType[] { EntityType.DROWNED }, //VR egg: 0x799C65
// "Drowned", "drowned", 0x8FF1D7, new EntityType[] { EntityType.DROWNED }, //VR egg: 0x799C65
// "Brute", /*"Fishing",*/ "Giant", "Hungry", "Knight", "Plague"
// );
// );// ice/fire themes? (cold/warm ocean)
public static final MobFamily<ZombifiedPiglinEntity, FamilyConfig> ZOMBIFIED_PIGLIN = new MobFamily<>( FamilyConfig::new,
"ZombifiedPiglin", "zombified piglins", 0xEA9393, new EntityType[] { EntityType.ZOMBIFIED_PIGLIN },
"Brute", /*"Fishing",*/ "Giant", "Hungry", "Knight", "Plague", "Vampire"//TODO figure out crossbows
"Brute", "Fishing", "Giant", "Hungry", "Knight", "Plague", "Vampire"//TODO figure out crossbows
);//TODO fishing
public static final MobFamily<AbstractSkeletonEntity, SkeletonFamilyConfig> SKELETON = new MobFamily<>( SkeletonFamilyConfig::new,
"Skeleton", "skeletons", 0xC1C1C1, new EntityType[] { EntityType.SKELETON, EntityType.STRAY },
"Brute", "Fire", "Gatling", "Giant", "Knight", "Ninja", "Poison", "Sniper", "Spitfire", "Stray"
"Brute", "Fire", "Gatling", "Giant", "Knight", "Ninja", "Poison", "Sniper", "Spitfire", "Stray", "Weathered"
);
public static final MobFamily<AbstractSkeletonEntity, SkeletonFamilyConfig> WITHER_SKELETON = new MobFamily<>( SkeletonFamilyConfig::new,
"WitherSkeleton", "wither skeletons", 0x141414, new EntityType[] { EntityType.WITHER_SKELETON },
@ -68,7 +68,7 @@ public class MobFamily<T extends LivingEntity, V extends FamilyConfig> {
public static final MobFamily<SlimeEntity, SlimeFamilyConfig> SLIME = new MobFamily<>( SlimeFamilyConfig::new,
"Slime", "slimes", 0x51A03E, new EntityType[] { EntityType.SLIME },
"Blackberry", "Blueberry", "Caramel", "Grape", "Lemon", "Strawberry", "Watermelon"
"Blackberry", "Blueberry", "Caramel", "Frozen", "Grape", "Lemon", "Potion", "Strawberry", "Watermelon"
);
public static final MobFamily<MagmaCubeEntity, FamilyConfig> MAGMA_CUBE = new MobFamily<>( FamilyConfig::newMoreSpecial,
"MagmaCube", "magma cubes", 0x340000, new EntityType[] { EntityType.MAGMA_CUBE },
@ -86,7 +86,7 @@ public class MobFamily<T extends LivingEntity, V extends FamilyConfig> {
public static final MobFamily<SilverfishEntity, SilverfishFamilyConfig> SILVERFISH = new MobFamily<>( SilverfishFamilyConfig::new,
"Silverfish", "silverfish", 0x6E6E6E, new EntityType[] { EntityType.SILVERFISH },
"Blinding", "Desiccated", /*"Fishing",*/ "Flying", "Poison", /*"Puffer",*/ "Tough"
"Albino", "Blinding", "Desiccated", "Fire", "Fishing", "Flying", "Poison", "Puffer", "Tough"
);//TODO fishing, puffer
public static final MobFamily<EndermanEntity, FamilyConfig> ENDERMAN = new MobFamily<>( FamilyConfig::new,

View file

@ -0,0 +1,52 @@
package fathertoast.specialmobs.common.config.species;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.config.field.LazyRegistryEntryListField;
import fathertoast.specialmobs.common.config.field.RegistryEntryListField;
import fathertoast.specialmobs.common.config.file.ToastConfigSpec;
import fathertoast.specialmobs.common.config.util.ConfigUtil;
import fathertoast.specialmobs.common.config.util.LazyRegistryEntryList;
import fathertoast.specialmobs.common.core.register.SMEffects;
import net.minecraft.potion.Effect;
import net.minecraft.potion.Effects;
import net.minecraftforge.registries.ForgeRegistries;
public class PotionSlimeSpeciesConfig extends SpeciesConfig {
public final Potion POTION;
/** Builds the config spec that should be used for this config. */
public PotionSlimeSpeciesConfig( MobFamily.Species<?> species ) {
super( species );
POTION = new Potion( SPEC, species, speciesName );
}
public static class Potion extends Config.AbstractCategory {
public final RegistryEntryListField<Effect> allowedPotions;
Potion( ToastConfigSpec parent, MobFamily.Species<?> species, String speciesName ) {
super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ),
"Options specific to " + speciesName + "." );
allowedPotions = SPEC.define( new LazyRegistryEntryListField<>( "allowed_effects",
new LazyRegistryEntryList<>( ForgeRegistries.POTIONS,
Effects.MOVEMENT_SPEED, Effects.MOVEMENT_SLOWDOWN,
Effects.DIG_SPEED, Effects.DIG_SLOWDOWN,
Effects.DAMAGE_BOOST, Effects.WEAKNESS,
Effects.HEAL, Effects.HARM, Effects.HUNGER,
Effects.REGENERATION, Effects.POISON, Effects.WITHER,
Effects.JUMP, Effects.SLOW_FALLING, Effects.LEVITATION,
Effects.DAMAGE_RESISTANCE, SMEffects.VULNERABILITY,
Effects.FIRE_RESISTANCE, Effects.WATER_BREATHING,
Effects.BLINDNESS, Effects.NIGHT_VISION, Effects.CONFUSION,
Effects.HEALTH_BOOST, Effects.ABSORPTION,
Effects.GLOWING
),
"List of potions that " + speciesName + " can be 'filled' with on spawn (they will apply it on hit).",
"Each effect in the list has an equal chance to be selected." ) );
}
}
}

View file

@ -3,9 +3,11 @@ package fathertoast.specialmobs.common.config.util;
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
import fathertoast.specialmobs.common.core.SpecialMobs;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
@ -25,7 +27,8 @@ public class LazyRegistryEntryList<T extends IForgeRegistryEntry<T>> extends Reg
/**
* Create a new registry entry list from an array of entries. Used for creating default configs.
* <p>
* This method of creation can not take advantage of the * notation.
* This method of creation can only use entries that are loaded (typically only vanilla entries)
* and cannot take advantage of the * notation.
*/
@SafeVarargs
public LazyRegistryEntryList( IForgeRegistry<T> registry, T... entries ) {
@ -34,6 +37,38 @@ public class LazyRegistryEntryList<T extends IForgeRegistryEntry<T>> extends Reg
populated = true;
}
/**
* Create a new registry entry list from an array of entries. Used for creating default configs.
* <p>
* This method of creation is less safe, but can take advantage of the regular vanilla entries, deferred entries,
* resource locations, and raw strings.
*/
public LazyRegistryEntryList( IForgeRegistry<T> registry, Object... entries ) {
super( registry );
FIELD = null;
for( Object entry : entries ) {
if( entry instanceof IForgeRegistryEntry ) {
final ResourceLocation regKey = ((IForgeRegistryEntry<?>) entry).getRegistryName();
if( regKey == null ) {
throw new IllegalArgumentException( "Invalid default lazy registry list entry! " + entry );
}
PRINT_LIST.add( regKey.toString() );
}
else if( entry instanceof RegistryObject ) {
PRINT_LIST.add( ((RegistryObject<?>) entry).getId().toString() );
}
else if( entry instanceof ResourceLocation ) {
PRINT_LIST.add( entry.toString() );
}
else if( entry instanceof String ) {
PRINT_LIST.add( (String) entry );
}
else {
throw new IllegalArgumentException( "Invalid default lazy registry list entry! " + entry );
}
}
}
/**
* Create a new registry entry list from a list of registry key strings.
*/
@ -67,7 +102,7 @@ public class LazyRegistryEntryList<T extends IForgeRegistryEntry<T>> extends Reg
// Add a single registry entry
final ResourceLocation regKey = new ResourceLocation( line );
if( !mergeFrom( regKey ) ) {
SpecialMobs.LOG.warn( "Invalid entry for {} \"{}\"! Invalid entry: {}",
SpecialMobs.LOG.warn( "Invalid or duplicate entry for {} \"{}\"! Invalid entry: {}",
FIELD.getClass(), FIELD.getKey(), line );
}
}
@ -87,7 +122,7 @@ public class LazyRegistryEntryList<T extends IForgeRegistryEntry<T>> extends Reg
/** @return Returns true if the entry is contained in this list. */
@Override
public boolean contains( T entry ) {
public boolean contains( @Nullable T entry ) {
populateEntries();
return super.contains( entry );
}

View file

@ -63,7 +63,7 @@ public class RegistryEntryList<T extends IForgeRegistryEntry<T>> implements IStr
PRINT_LIST.add( regKey.toString() );
}
else {
SpecialMobs.LOG.warn( "Invalid entry for {} \"{}\"! Deleting entry. Invalid entry: {}",
SpecialMobs.LOG.warn( "Invalid or duplicate entry for {} \"{}\"! Deleting entry. Invalid entry: {}",
field.getClass(), field.getKey(), line );
}
}

View file

@ -2,9 +2,11 @@ package fathertoast.specialmobs.common.core;
import fathertoast.specialmobs.common.compat.top.SMTheOneProbe;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.core.register.SMEffects;
import fathertoast.specialmobs.common.core.register.SMEntities;
import fathertoast.specialmobs.common.core.register.SMItems;
import fathertoast.specialmobs.common.event.BiomeEvents;
import fathertoast.specialmobs.common.event.GameEvents;
import fathertoast.specialmobs.common.network.PacketHandler;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;
@ -40,8 +42,9 @@ public class SpecialMobs {
* o nether spawns
* o end spawns
* ? ocean/water spawns
* + potions
* + vulnerability (opposite of resistance)
* - potions
* - vulnerability (opposite of resistance)
* ? gravity (opposite of levitation)
* o entities
* - nbt-driven capabilities (special mob data)
* o fish hook
@ -53,8 +56,8 @@ public class SpecialMobs {
* - chance to spawn charged during thunderstorms
* + scope
* - zombies
* o villager infection
* + transformations
* o villager infection (is this still reasonably applicable?)
* + transformations (husk -> any other non-water-sensitive zombie -> any drowned)
* - ranged attack AI (using bow)
* - use shields
* + drowned
@ -118,14 +121,15 @@ public class SpecialMobs {
packetHandler.registerMessages();
//MinecraftForge.EVENT_BUS.register( new SMEventListener() );
MinecraftForge.EVENT_BUS.register( new BiomeEvents() );
MinecraftForge.EVENT_BUS.register( new GameEvents() );
IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus();
eventBus.addListener( SMEntities::createAttributes );
eventBus.addListener( this::sendIMCMessages );
SMEffects.REGISTRY.register( eventBus );
SMEntities.REGISTRY.register( eventBus );
SMItems.REGISTRY.register( eventBus );
}

View file

@ -0,0 +1,30 @@
package fathertoast.specialmobs.common.core.register;
import fathertoast.specialmobs.common.core.SpecialMobs;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectType;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.function.Supplier;
public class SMEffects {
public static final DeferredRegister<Effect> REGISTRY = DeferredRegister.create( ForgeRegistries.POTIONS, SpecialMobs.MOD_ID );
public static final RegistryObject<Effect> VULNERABILITY = register( "vulnerability", EffectType.HARMFUL, 0x96848D );
/** Registers a simple effect to the deferred register. */
public static RegistryObject<Effect> register( String name, EffectType type, int color ) {
return register( name, () -> new SimpleEffect( type, color ) );
}
/** Registers a custom effect to the deferred register. */
public static <T extends Effect> RegistryObject<T> register( String name, Supplier<T> effect ) { return REGISTRY.register( name, effect ); }
/** Really just here to allow access to the Effect::new. */
private static class SimpleEffect extends Effect {
SimpleEffect( EffectType type, int color ) { super( type, color ); }
}
}

View file

@ -11,12 +11,15 @@ import net.minecraft.block.material.Material;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.FrostWalkerEnchantment;
import net.minecraft.entity.*;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.monster.CreeperEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.*;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.EffectType;
import net.minecraft.potion.Effects;
@ -28,12 +31,14 @@ import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.Difficulty;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IServerWorld;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.event.entity.living.LivingKnockBackEvent;
import javax.annotation.Nullable;
import java.util.ArrayList;
@ -136,6 +141,81 @@ public final class MobHelper {
return EnchantmentHelper.getDamageBonus( item, CreatureAttribute.UNDEAD ) > 0.0F;
}
/**
* Knocks the target away from the source. Power is on the same scale as "level of Knockback enchantment".
* If the power is negative, this pulls the target toward the source instead.
*/
@SuppressWarnings( "unused" )
public static void knockback( Entity source, LivingEntity target, float power, float upwardMulti ) {
knockback( source, 0.6, target, power, upwardMulti, 0.5 );
}
/**
* Knocks the target away from the source. Power is on the same scale as "level of Knockback enchantment".
* If the power is negative, this pulls the target toward the source instead.
* Momentum is the amount of original velocity maintained by the entity after knockback.
*/
public static void knockback( Entity source, double sourceMomentum, LivingEntity target, float power, float upwardMulti, double momentum ) {
final float angle = source.yRot * (float) Math.PI / 180.0F;
knockback( target, power, upwardMulti, MathHelper.sin( angle ), -MathHelper.cos( angle ), momentum );
source.setDeltaMovement( source.getDeltaMovement().multiply( sourceMomentum, 1.0, sourceMomentum ) );
}
/**
* Knocks the target backward (based on its own facing). Power is on the same scale as "level of Knockback enchantment".
* If the power is negative, this pushes the target forward instead.
*/
@SuppressWarnings( "unused" )
public static void knockback( LivingEntity target, float power, float upwardMulti ) {
knockback( target, power, upwardMulti, 0.5 );
}
/**
* Knocks the target backward (based on its own facing). Power is on the same scale as "level of Knockback enchantment".
* If the power is negative, this pushes the target forward instead.
* Momentum is the amount of original velocity maintained by the entity after knockback.
*/
public static void knockback( LivingEntity target, float power, float upwardMulti, double momentum ) {
final float angle = target.yRot * (float) Math.PI / 180.0F;
knockback( target, power, upwardMulti, -MathHelper.sin( angle ), MathHelper.cos( angle ), momentum );
}
/**
* Knocks the target backward (opposite direction from the [x, z] vector provided).
* Power is on the same scale as "level of Knockback enchantment".
* If the power is negative, this pushes the target forward instead.
*/
@SuppressWarnings( "unused" )
public static void knockback( LivingEntity target, float power, float upwardMulti, double forwardX, double forwardZ ) {
knockback( target, power, upwardMulti, forwardX, forwardZ, 0.5 );
}
/**
* Knocks the target backward (opposite direction from the [x, z] vector provided).
* Power is on the same scale as "level of Knockback enchantment".
* If the power is negative, this pushes the target forward instead.
* Momentum is the amount of original velocity maintained by the entity after knockback.
*/
public static void knockback( LivingEntity target, float power, float upwardMulti, double forwardX, double forwardZ, double momentum ) {
final LivingKnockBackEvent event = power < 0.0F ?
ForgeHooks.onLivingKnockBack( target, -power * 0.5F, -forwardX, -forwardZ ) :
ForgeHooks.onLivingKnockBack( target, power * 0.5F, forwardX, forwardZ );
if( event.isCanceled() ) return;
power = (float) (event.getStrength() * (1.0 - target.getAttributeValue( Attributes.KNOCKBACK_RESISTANCE )));
if( power > 0.0F ) {
target.hasImpulse = true;
final Vector3d v = target.getDeltaMovement().scale( momentum );
final Vector3d vKB = new Vector3d( -event.getRatioX(), 0.0, -event.getRatioZ() ).normalize().scale( power );
final double vY = v.y + power * upwardMulti;
target.setDeltaMovement(
v.x + vKB.x,
target.isOnGround() ? Math.max( 0.2, vY ) : vY,
v.z + vKB.z );
target.hurtMarked = true;
}
}
/**
* Reduces the target's life directly. Will not reduce health below 1.
*
@ -204,8 +284,114 @@ public final class MobHelper {
}
}
/** Removes night vision from the target. Typically used when blindness is involved due to the awkward interaction. */
public static void removeNightVision( LivingEntity target ) { target.removeEffect( Effects.NIGHT_VISION ); }
/** Applies a random 'plague' potion effect to the target. */
public static void applyPlagueEffect( LivingEntity target, Random random ) {
applyEffectFromTemplate( target, PLAGUE_EFFECTS[random.nextInt( PLAGUE_EFFECTS.length -
(Config.MAIN.GENERAL.enableNausea.get() ? 0 : 1) )] );
}
/** Applies a random 'witch spider' potion effect to the target, optionally including poison in the effect pool. */
public static void applyWitchSpiderEffect( LivingEntity target, Random random, boolean includePoison ) {
applyEffectFromTemplate( target, WITCH_EFFECTS[random.nextInt( WITCH_EFFECTS.length - (includePoison ? 0 : 1) )] );
}
/** Applies a potion effect to the target with default duration. */
public static void applyEffect( LivingEntity target, Effect effect ) { applyEffect( target, effect, 1, 1.0F ); }
/** Applies a potion effect to the target with default duration and a specified level (amplifier + 1). */
public static void applyEffect( LivingEntity target, Effect effect, int level ) {
applyEffect( target, effect, level, 1.0F );
}
/** Applies a potion effect to the target with default duration and a specified level (amplifier + 1). */
public static void applyEffect( LivingEntity target, Effect effect, float durationMulti ) {
applyEffect( target, effect, 1, durationMulti );
}
/** Applies a potion effect to the target with default duration and a specified level (amplifier + 1). */
public static void applyEffect( LivingEntity target, Effect effect, int level, float durationMulti ) {
applyEffect( target, effect, level, effect.isInstantenous() ? 1 :
(int) (MobHelper.defaultEffectDuration( target.level.getDifficulty() ) * durationMulti) );
}
/** Applies a potion effect to the target with a specified level (amplifier + 1) and duration. */
public static void applyDurationEffect( LivingEntity target, Effect effect, int duration ) {
applyEffect( target, effect, 1, duration );
}
/** Applies a potion effect to the target with a specified level (amplifier + 1) and duration. */
public static void applyEffect( LivingEntity target, Effect effect, int level, int duration ) {
target.addEffect( new EffectInstance( effect, duration, level - 1 ) );
}
/** Applies a potion effect to the target based on a template effect. The template's duration is used as a multiplier. */
public static void applyEffectFromTemplate( LivingEntity target, EffectInstance template ) {
applyEffectFromTemplate( target, template, MobHelper.defaultEffectDuration( target.level.getDifficulty() ) );
}
/** Applies a potion effect to the target based on a template effect. The template's duration is used as a multiplier. */
public static void applyEffectFromTemplate( LivingEntity target, EffectInstance template, int baseDuration ) {
target.addEffect( new EffectInstance( template.getEffect(), template.getEffect().isInstantenous() ? 1 :
baseDuration * template.getDuration(), template.getAmplifier() ) );
}
/** Applies a random 'plague' potion effect to the arrow. */
public static AbstractArrowEntity tipPlagueArrow( AbstractArrowEntity arrow, Random random ) {
return tipArrowFromTemplate( arrow, PLAGUE_EFFECTS[random.nextInt( PLAGUE_EFFECTS.length -
(Config.MAIN.GENERAL.enableNausea.get() ? 0 : 1) )] );
}
// /** Applies a random 'witch spider' potion effect to the arrow, optionally including poison in the effect pool. */
// public static AbstractArrowEntity tipWitchSpiderArrow( AbstractArrowEntity arrow, Random random, boolean includePoison ) {
// return tipArrowFromTemplate( arrow, WITCH_EFFECTS[random.nextInt( WITCH_EFFECTS.length - (includePoison ? 0 : 1) )] );
// }
/** Applies a potion effect to the arrow with default duration. */
public static AbstractArrowEntity tipArrow( AbstractArrowEntity arrow, Effect effect ) {
return tipArrow( arrow, effect, 1, 1.0F );
}
/** Applies a potion effect to the arrow with default duration and a specified level (amplifier + 1). */
public static AbstractArrowEntity tipArrow( AbstractArrowEntity arrow, Effect effect, int level ) {
return tipArrow( arrow, effect, level, 1.0F );
}
/** Applies a potion effect to the arrow with default duration and a specified level (amplifier + 1). */
public static AbstractArrowEntity tipArrow( AbstractArrowEntity arrow, Effect effect, float durationMulti ) {
return tipArrow( arrow, effect, 1, durationMulti );
}
/** Applies a potion effect to the arrow with default duration and a specified level (amplifier + 1). */
public static AbstractArrowEntity tipArrow( AbstractArrowEntity arrow, Effect effect, int level, float durationMulti ) {
return tipArrow( arrow, effect, level, effect.isInstantenous() ? 1 :
(int) (MobHelper.defaultEffectDuration( arrow.level.getDifficulty() ) * durationMulti) );
}
/** Applies a potion effect to the arrow with a specified level (amplifier + 1) and duration. */
public static AbstractArrowEntity tipArrow( AbstractArrowEntity arrow, Effect effect, int level, int duration ) {
if( arrow instanceof ArrowEntity )
((ArrowEntity) arrow).addEffect( new EffectInstance( effect, duration, level - 1 ) );
return arrow;
}
/** Applies a potion effect to the arrow based on a template effect. The template's duration is used as a multiplier. */
public static AbstractArrowEntity tipArrowFromTemplate( AbstractArrowEntity arrow, EffectInstance template ) {
return tipArrowFromTemplate( arrow, template, MobHelper.defaultEffectDuration( arrow.level.getDifficulty() ) );
}
/** Applies a potion effect to the arrow based on a template effect. The template's duration is used as a multiplier. */
public static AbstractArrowEntity tipArrowFromTemplate( AbstractArrowEntity arrow, EffectInstance template, int baseDuration ) {
if( arrow instanceof ArrowEntity )
((ArrowEntity) arrow).addEffect( new EffectInstance( template.getEffect(), template.getEffect().isInstantenous() ? 1 :
baseDuration * template.getDuration(), template.getAmplifier() ) );
return arrow;
}
/** @return The base debuff duration. */
public static int getDebuffDuration( Difficulty difficulty ) {
public static int defaultEffectDuration( Difficulty difficulty ) {
switch( difficulty ) {
case PEACEFUL:
case EASY:
@ -217,52 +403,6 @@ public final class MobHelper {
}
}
/** @return The base debuff duration for effects that should be shorter than normal. */
public static int getShortDebuffDuration( Difficulty difficulty ) {
switch( difficulty ) {
case PEACEFUL:
case EASY:
return 40;
case NORMAL:
return 60;
default:
return 80;
}
}
/**
* Makes a random potion effect for a plague-type mob to apply on hit.
*
* @param random The rng to draw from.
* @param world The context.
* @return A newly created potion effect instance we can apply to an entity.
*/
public static EffectInstance nextPlagueEffect( Random random, World world ) {
final int duration = MobHelper.getDebuffDuration( world.getDifficulty() );
final EffectInstance potion = PLAGUE_EFFECTS[random.nextInt( PLAGUE_EFFECTS.length -
(Config.MAIN.GENERAL.enableNausea.get() ? 0 : 1) )];
return new EffectInstance( potion.getEffect(), duration * potion.getDuration(), potion.getAmplifier() );
}
/**
* Makes a random potion effect for a witch-spider-type mob to apply on hit,
* optionally including poison in the effect pool.
* <p>
* For example, witch cave spiders do not include poison in the pool because they apply poison already.
*
* @param random The rng to draw from.
* @param world The context.
* @param includePoison Whether to include poison in the potion pool.
* @return A newly created potion effect instance we can apply to an entity.
*/
public static EffectInstance nextWitchSpiderEffect( Random random, World world, boolean includePoison ) {
final int duration = MobHelper.getDebuffDuration( world.getDifficulty() );
final EffectInstance potion = WITCH_EFFECTS[random.nextInt( WITCH_EFFECTS.length - (includePoison ? 0 : 1) )];
return new EffectInstance( potion.getEffect(), duration * potion.getDuration(), potion.getAmplifier() );
}
/**
* Tries to block an incoming damage source on behalf of the blocker, possibly destroying their shield.
* Note that the blocker will have to call blockUsingShield() and cancel the damage event themselves if this works.
@ -360,10 +500,21 @@ public final class MobHelper {
* @param entity The entity.
* @param pos The block pos argument from #onChangedBlock.
*/
public static void updateFrostWalker( LivingEntity entity, BlockPos pos ) {
public static void updateFrostWalker( LivingEntity entity, BlockPos pos ) { updateFrostWalker( entity, pos, 1 ); }
/**
* Manually provides the frost walker enchantment's effects without any equipment requirements.
* <p>
* Should be called in the entity's {@link LivingEntity#onChangedBlock(BlockPos)} method right after super.
*
* @param entity The entity.
* @param pos The block pos argument from #onChangedBlock.
* @param level The level of enchantment. Platform radius is 2 + level.
*/
public static void updateFrostWalker( LivingEntity entity, BlockPos pos, int level ) {
final boolean actualOnGround = entity.isOnGround();
entity.setOnGround( true ); // Spoof the frost walker enchant requirement to be on the ground
FrostWalkerEnchantment.onEntityMoved( entity, entity.level, pos, 1 );
FrostWalkerEnchantment.onEntityMoved( entity, entity.level, pos, level );
entity.setOnGround( actualOnGround );
}
@ -375,7 +526,7 @@ public final class MobHelper {
* @param entity The entity to pop.
*/
public static void hopOnFluid( Entity entity ) {
if( entity.tickCount > 1 && entity.level.random.nextInt( 20 ) == 0 ) {
if( entity.tickCount > 1 && entity.isOnGround() && entity.level.random.nextInt( 10 ) == 0 ) {
if( ISelectionContext.of( entity ).isAbove( FlowingFluidBlock.STABLE_SHAPE, entity.blockPosition(), true ) &&
!entity.level.getFluidState( entity.blockPosition().above() ).is( FluidTags.WATER ) ) {
// Break water plants, otherwise frost walker will not work

View file

@ -5,8 +5,8 @@ import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -54,7 +54,7 @@ public class CinderBlazeEntity extends _SpecialBlazeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 4 );
}
}

View file

@ -6,7 +6,6 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.AttributeModifier;
@ -75,10 +74,8 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.stealLife( this, (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.stealLife( this, target, 2.0F );
}
/** @return Attempts to damage this entity; returns true if the hit was successful. */

View file

@ -6,7 +6,6 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -57,9 +56,7 @@ public class EmberBlazeEntity extends _SpecialBlazeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
}
}

View file

@ -8,7 +8,6 @@ import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -65,9 +64,7 @@ public class InfernoBlazeEntity extends _SpecialBlazeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
}
}

View file

@ -3,7 +3,6 @@ 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.ExplosionHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
@ -67,14 +66,6 @@ public class JoltBlazeEntity extends _SpecialBlazeEntity {
public JoltBlazeEntity( EntityType<? extends _SpecialBlazeEntity> entityType, World world ) { super( entityType, world ); }
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
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() {

View file

@ -81,7 +81,7 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 8 );
}

View file

@ -46,7 +46,7 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xFFF87E )
.vanillaTextureBaseOnly( "textures/entity/blaze.png" )
.experience( 10 ).fireImmune().waterSensitive()
.experience( 10 ).waterSensitive()
.fireballAttack( 1.0, 60, 100, 48.0 );
}
@ -100,12 +100,12 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Called to attack the target with a ranged attack. */
@Override

View file

@ -4,15 +4,14 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.core.register.SMEffects;
import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -60,18 +59,11 @@ public class DesertCaveSpiderEntity extends _SpecialCaveSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
if( Config.MAIN.GENERAL.enableNausea.get() ) {
livingTarget.addEffect( new EffectInstance( Effects.CONFUSION, duration, 0 ) );
}
livingTarget.addEffect( new EffectInstance( Effects.BLINDNESS, duration, 0 ) );
livingTarget.addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration, 2 ) );
livingTarget.addEffect( new EffectInstance( Effects.DAMAGE_RESISTANCE, duration, -3 ) ); // 40% inc damage taken
}
protected void onVariantAttack( LivingEntity target ) {
if( Config.MAIN.GENERAL.enableNausea.get() ) MobHelper.applyEffect( target, Effects.CONFUSION );
MobHelper.applyEffect( target, Effects.BLINDNESS );
MobHelper.removeNightVision( target );
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN, 2 );
MobHelper.applyEffect( target, SMEffects.VULNERABILITY.get() );
}
}

View file

@ -6,7 +6,6 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
@ -56,8 +55,8 @@ public class FireCaveSpiderEntity extends _SpecialCaveSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( !level.isClientSide() && target instanceof LivingEntity ) {
protected void onVariantAttack( LivingEntity target ) {
if( !level.isClientSide() ) {
final BlockPos pos = target.blockPosition();
if( level.getBlockState( pos ).getMaterial().isReplaceable() ) {
level.setBlock( pos, Blocks.FIRE.defaultBlockState(), References.SetBlockFlags.DEFAULTS );

View file

@ -6,12 +6,10 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -58,13 +56,8 @@ public class PaleCaveSpiderEntity extends _SpecialCaveSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.WEAKNESS, duration, 0 ) );
livingTarget.addEffect( new EffectInstance( Effects.DIG_SLOWDOWN, duration, 1 ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.WEAKNESS );
MobHelper.applyEffect( target, Effects.DIG_SLOWDOWN, 3 );
}
}

View file

@ -8,7 +8,6 @@ import fathertoast.specialmobs.common.config.species.WebSpiderSpeciesConfig;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -78,8 +77,8 @@ public class WebCaveSpiderEntity extends _SpecialCaveSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( !level.isClientSide() && webCount > 0 && target instanceof LivingEntity && !(target instanceof SpiderEntity) ) {
protected void onVariantAttack( LivingEntity target ) {
if( !level.isClientSide() && webCount > 0 && !(target instanceof SpiderEntity) ) {
final BlockPos pos = target.blockPosition();
if( !tryPlaceWeb( pos ) && target.getBbHeight() > 1.0F ) {
tryPlaceWeb( pos.above() );

View file

@ -6,7 +6,6 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -58,11 +57,9 @@ public class WitchCaveSpiderEntity extends _SpecialCaveSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
((LivingEntity) target).addEffect( MobHelper.nextWitchSpiderEffect( random, level, false ) );
MobHelper.stealBuffEffect( this, (LivingEntity) target );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyWitchSpiderEffect( target, random, false );
MobHelper.stealBuffEffect( this, target );
}
/** @return True if the effect can be applied to this entity. */

View file

@ -93,12 +93,12 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpeci
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -97,13 +97,13 @@ public class _SpecialCreeperEntity extends CreeperEntity implements IExplodingMo
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@SuppressWarnings( "unused" ) // Not normally used for creepers
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Called to perform this creeper's explosion 'attack'. */
@Override

View file

@ -3,12 +3,12 @@ package fathertoast.specialmobs.common.entity.enderman;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -60,8 +60,8 @@ public class BlindingEndermanEntity extends _SpecialEndermanEntity {
// Apply blinding effect while near target
final LivingEntity target = getTarget();
if( target != null && distanceToSqr( target ) < 100.0 ) {
target.addEffect( new EffectInstance( Effects.BLINDNESS, 50 ) );
target.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen)
MobHelper.applyDurationEffect( target, Effects.BLINDNESS, 50 );
MobHelper.removeNightVision( target );
}
}
}

View file

@ -72,12 +72,10 @@ public class FlameEndermanEntity extends _SpecialEndermanEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
target.setSecondsOnFire( 5 );
if( target instanceof LivingEntity ) {
for( int i = 0; i < 64; i++ ) {
if( teleport() ) break;
}
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 4 );
for( int i = 0; i < 64; i++ ) {
if( teleport() ) break;
}
}

View file

@ -11,7 +11,6 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.enchantment.FrostWalkerEnchantment;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluid;
@ -19,7 +18,6 @@ import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.pathfinding.PathNavigator;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.DamageSource;
@ -77,14 +75,9 @@ public class IcyEndermanEntity extends _SpecialEndermanEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getShortDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration, 4 ) );
livingTarget.addEffect( new EffectInstance( Effects.DIG_SLOWDOWN, duration, 2 ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN, 5, 0.5F );
MobHelper.applyEffect( target, Effects.DIG_SLOWDOWN, 3 );
}
/** Override to change this entity's AI goals. */

View file

@ -6,7 +6,6 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.ExplosionHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.LightningBoltEntity;
@ -56,12 +55,10 @@ public class LightningEndermanEntity extends _SpecialEndermanEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
ExplosionHelper.spawnLightning( level, target.getX(), target.getY(), target.getZ() );
for( int i = 0; i < 64; i++ ) {
if( teleport() ) break;
}
protected void onVariantAttack( LivingEntity target ) {
ExplosionHelper.spawnLightning( level, target.getX(), target.getY(), target.getZ() );
for( int i = 0; i < 64; i++ ) {
if( teleport() ) break;
}
}

View file

@ -6,8 +6,8 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
@ -71,7 +71,7 @@ public class MirageEndermanEntity extends _SpecialEndermanEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
for( int i = 0; i < 64; i++ ) {
if( teleport() ) break;
}

View file

@ -7,12 +7,10 @@ import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -63,13 +61,9 @@ public class RunicEndermanEntity extends _SpecialEndermanEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.LEVITATION, duration ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.LEVITATION );
MobHelper.knockback( this, target, 2.0F, 0.0F );
}
// NOTE would be fun to try and make this mob shoot an 'end crystal laser' to deal ranged damage and/or knockback

View file

@ -5,7 +5,6 @@ import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -61,11 +60,11 @@ public class ThiefEndermanEntity extends _SpecialEndermanEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( !level.isClientSide() && target instanceof LivingEntity && target.isAlive() && teleportTargetDelay <= 0 ) {
protected void onVariantAttack( LivingEntity target ) {
if( !level.isClientSide() && target.isAlive() && teleportTargetDelay <= 0 ) {
for( int i = 0; i < 64; i++ ) {
if( teleportTarget( (LivingEntity) target ) ) {
teleportTargetDelay = 160; // 8s cooldown
if( teleportTarget( target ) ) {
teleportTargetDelay = 160;
for( int j = 0; j < 16; j++ ) {
if( teleportTowards( target ) ) break;
}

View file

@ -78,12 +78,12 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -6,7 +6,6 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -58,9 +57,9 @@ public class FighterGhastEntity extends _SpecialGhastEntity {
public FighterGhastEntity( EntityType<? extends _SpecialGhastEntity> entityType, World world ) { super( entityType, world ); }
/** 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 );
}
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
MobHelper.knockback( this, target, 2.0F, 0.5F );
}
}

View file

@ -7,7 +7,6 @@ import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.CreatureAttribute;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -63,10 +62,9 @@ public class UnholyGhastEntity extends _SpecialGhastEntity {
public UnholyGhastEntity( EntityType<? extends _SpecialGhastEntity> entityType, World world ) { super( entityType, world ); }
/** 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 );
}
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.stealLife( this, target, 2.0F );
}
/** @return Attempts to damage this entity; returns true if the hit was successful. */

View file

@ -49,7 +49,7 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xBCBCBC )
.vanillaTextureWithAnimation( "textures/entity/ghast/ghast.png", "textures/entity/ghast/ghast_shooting.png" )
.experience( 5 ).fireImmune()
.experience( 5 )
.fireballAttack( 0.0, 20, 40, 64.0 );
}
@ -129,12 +129,12 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -3,15 +3,14 @@ package fathertoast.specialmobs.common.entity.magmacube;
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.entity.ai.goal.SpecialLeapAtTargetGoal;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
@SpecialMob
@ -61,21 +60,12 @@ public class HardenedMagmaCubeEntity extends _SpecialMagmaCubeEntity {
@Override
protected void registerVariantGoals() {
goalSelector.addGoal( 0, new SpecialLeapAtTargetGoal(
this, 10, 0.0F, 5.0F, 1.16F, 1.0F ) );
this, 5, 0.0F, 5.0F, 1.16F, 1.0F ) );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final float forwardPower = 0.8F;
final float upwardPower = 0.5F;
final Vector3d vKnockback = new Vector3d( target.getX() - getX(), 0.0, target.getZ() - getZ() )
.normalize().scale( forwardPower ).add( getDeltaMovement().scale( 0.2F ) );
target.setDeltaMovement( vKnockback.x, 0.4 * upwardPower, vKnockback.z );
target.hurtMarked = true;
setDeltaMovement( getDeltaMovement().multiply( 0.2, 1.0, 0.2 ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, 0.2, target, getSize(), 0.5F, 0.5 );
}
}

View file

@ -62,7 +62,7 @@ public class StickyMagmaCubeEntity extends _SpecialMagmaCubeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
if( grabTime <= -20 && getPassengers().isEmpty() ) {
if( target.startRiding( this, true ) ) grabTime = 20;
}

View file

@ -84,12 +84,12 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -0,0 +1,69 @@
package fathertoast.specialmobs.common.entity.silverfish;
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.species.SilverfishSpeciesConfig;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.entity.MobHelper;
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.Attributes;
import net.minecraft.item.Items;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@SpecialMob
public class AlbinoSilverfishEntity extends _SpecialSilverfishEntity {
//--------------- Static Special Mob Hooks ----------------
@SpecialMob.SpeciesReference
public static MobFamily.Species<AlbinoSilverfishEntity> SPECIES;
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xFFFFFF ).theme( BestiaryInfo.Theme.ICE )
.uniqueTextureBaseOnly()
.addExperience( 1 ).effectImmune( Effects.MOVEMENT_SLOWDOWN )
.addToAttribute( Attributes.ARMOR, 10.0 );
}
@SpecialMob.ConfigSupplier
public static SpeciesConfig createConfig( MobFamily.Species<?> species ) {
return new SilverfishSpeciesConfig( species, 1.0 );
}
@SpecialMob.LanguageProvider
public static String[] getTranslations( String langKey ) {
return References.translations( langKey, "Albino Silverfish",
"", "", "", "", "", "" );//TODO
}
@SpecialMob.LootTableProvider
public static void buildLootTable( LootTableBuilder loot ) {
addBaseLoot( loot );
loot.addCommonDrop( "common", Items.SNOWBALL );
}
@SpecialMob.Factory
public static EntityType.IFactory<AlbinoSilverfishEntity> getVariantFactory() { return AlbinoSilverfishEntity::new; }
/** @return This entity's mob species. */
@SpecialMob.SpeciesSupplier
@Override
public MobFamily.Species<? extends AlbinoSilverfishEntity> getSpecies() { return SPECIES; }
//--------------- Variant-Specific Implementations ----------------
public AlbinoSilverfishEntity( EntityType<? extends _SpecialSilverfishEntity> entityType, World world ) { super( entityType, world ); }
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN, 2 );
}
}

View file

@ -6,11 +6,9 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -56,13 +54,8 @@ public class BlindingSilverfishEntity extends _SpecialSilverfishEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.BLINDNESS, duration ) );
livingTarget.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen)
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.BLINDNESS );
MobHelper.removeNightVision( target );
}
}

View file

@ -11,13 +11,11 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.entity.CreatureAttribute;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.fluid.Fluids;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.tags.FluidTags;
import net.minecraft.tileentity.TileEntity;
@ -87,19 +85,14 @@ public class DesiccatedSilverfishEntity extends _SpecialSilverfishEntity {
/** Called each tick to update this entity's movement. */
@Override
public void aiStep() {
if( absorbCount > 0 && spongebob() ) spawnAnim();
if( !level.isClientSide() && absorbCount > 0 && spongebob() ) spawnAnim();
super.aiStep();
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.HUNGER, duration ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.HUNGER );
}
/** @return This entity's creature type. */

View file

@ -0,0 +1,88 @@
package fathertoast.specialmobs.common.entity.silverfish;
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
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.monster.SilverfishEntity;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
import java.util.List;
@SpecialMob
public class FireSilverfishEntity extends _SpecialSilverfishEntity {
//--------------- Static Special Mob Hooks ----------------
@SpecialMob.SpeciesReference
public static MobFamily.Species<FireSilverfishEntity> SPECIES;
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xDFA21B ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FIRE )
.uniqueTextureWithEyes()
.addExperience( 2 ).fireImmune();
}
@SpecialMob.LanguageProvider
public static String[] getTranslations( String langKey ) {
return References.translations( langKey, "Firebrat",
"", "", "", "", "", "" );//TODO
}
@SpecialMob.LootTableProvider
public static void buildLootTable( LootTableBuilder loot ) {
addBaseLoot( loot );
loot.addCommonDrop( "common", Items.FIRE_CHARGE );
loot.addUncommonDrop( "uncommon", Items.COAL );
}
@SpecialMob.Factory
public static EntityType.IFactory<FireSilverfishEntity> getVariantFactory() { return FireSilverfishEntity::new; }
/** @return This entity's mob species. */
@SpecialMob.SpeciesSupplier
@Override
public MobFamily.Species<? extends FireSilverfishEntity> getSpecies() { return SPECIES; }
//--------------- Variant-Specific Implementations ----------------
private byte auraCooldown = 20;
public FireSilverfishEntity( EntityType<? extends _SpecialSilverfishEntity> entityType, World world ) { super( entityType, world ); }
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 5 );
}
/** Called each tick to update this entity's movement. */
@Override
public void aiStep() {
super.aiStep();
if( auraCooldown-- <= 0 ) {
auraCooldown = 30;
pulseAura();
}
}
/** Applies this entity's aura effect. */
private void pulseAura() {
final List<SilverfishEntity> friends = level.getEntitiesOfClass( SilverfishEntity.class, getBoundingBox().inflate( 7.0 ) );
for( SilverfishEntity cutie : friends ) {
if( cutie.isAlive() && !cutie.fireImmune() ) {
cutie.addEffect( new EffectInstance( Effects.FIRE_RESISTANCE, 35 + random.nextInt( 16 ),
0, true, true ) );
}
}
}
}

View file

@ -31,7 +31,7 @@ public class FishingSilverfishEntity extends _SpecialSilverfishEntity implements
.addExperience( 2 ).drownImmune().fluidPushImmune()
.spitAttack( 0.0, 1.0, 40, 40, 10.0 )
.addToAttribute( Attributes.MAX_HEALTH, 4.0 )
.multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.9 );
.multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 );
}
@SpecialMob.ConfigSupplier

View file

@ -6,11 +6,9 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -56,12 +54,7 @@ public class PoisonSilverfishEntity extends _SpecialSilverfishEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.POISON );
}
}

View file

@ -0,0 +1,62 @@
package fathertoast.specialmobs.common.entity.silverfish;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@SpecialMob
public class PufferSilverfishEntity extends _SpecialSilverfishEntity {
//--------------- Static Special Mob Hooks ----------------
@SpecialMob.SpeciesReference
public static MobFamily.Species<PufferSilverfishEntity> SPECIES;
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xE6E861 ).theme( BestiaryInfo.Theme.WATER )
.uniqueTextureBaseOnly()//TODO Change texture or renderer to fix offset
.addExperience( 1 ).drownImmune().effectImmune( Effects.POISON );
}
@SpecialMob.LanguageProvider
public static String[] getTranslations( String langKey ) {
return References.translations( langKey, "\"Pufferfish\"",
"", "", "", "", "", "" );//TODO
}
@SpecialMob.LootTableProvider
public static void buildLootTable( LootTableBuilder loot ) {
addBaseLoot( loot );
loot.addUncommonDrop( "uncommon", Items.PUFFERFISH );
}
@SpecialMob.Factory
public static EntityType.IFactory<PufferSilverfishEntity> getVariantFactory() { return PufferSilverfishEntity::new; }
/** @return This entity's mob species. */
@SpecialMob.SpeciesSupplier
@Override
public MobFamily.Species<? extends PufferSilverfishEntity> getSpecies() { return SPECIES; }
//--------------- Variant-Specific Implementations ----------------
public PufferSilverfishEntity( EntityType<? extends _SpecialSilverfishEntity> entityType, World world ) { super( entityType, world ); }
//TODO swim behavior
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.POISON );
}
}

View file

@ -99,12 +99,12 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( @SuppressWarnings( "unused" ) CompoundNBT saveTag ) { }

View file

@ -6,15 +6,12 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -63,18 +60,14 @@ public class BruteSkeletonEntity extends _SpecialSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
MobHelper.knockback( this, target, 2.0F, 1.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.HARM ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.HARM );
}
}

View file

@ -5,8 +5,8 @@ import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@ -55,7 +55,7 @@ public class FireSkeletonEntity extends _SpecialSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 10 );
}

View file

@ -3,10 +3,14 @@ package fathertoast.specialmobs.common.entity.skeleton;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -20,7 +24,7 @@ public class GiantSkeletonEntity extends _SpecialSkeletonEntity {
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x494949 )
bestiaryInfo.color( 0x494949 ).theme( BestiaryInfo.Theme.MOUNTAIN )
.size( 1.5F, 0.9F, 2.99F )
.addExperience( 1 )
.addToAttribute( Attributes.MAX_HEALTH, 20.0 )
@ -55,6 +59,19 @@ public class GiantSkeletonEntity extends _SpecialSkeletonEntity {
maxUpStep = 1.0F;
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, target, 4.0F, 0.5F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
arrow.setKnockback( arrow.knockback + 2 );
return arrow;
}
/** Sets this entity as a baby. */
@Override
public void setBaby( boolean value ) { }

View file

@ -12,13 +12,15 @@ import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.player.PlayerEntity;
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.potion.Effects;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.DamageSource;
@ -96,13 +98,13 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) { revealTo( target, true ); }
protected void onVariantAttack( LivingEntity target ) { revealTo( target, true ); }
/** @return Attempts to damage this entity; returns true if the hit was successful. */
@Override
public boolean hurt( DamageSource source, float amount ) {
if( super.hurt( source, amount ) ) {
revealTo( source.getEntity(), false );
if( source.getEntity() instanceof LivingEntity ) revealTo( (LivingEntity) source.getEntity(), false );
return true;
}
return false;
@ -165,21 +167,18 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj
public void setRemainingFireTicks( int ticks ) { if( !isCrouchingTiger() ) super.setRemainingFireTicks( ticks ); }
/** Reveals this ninja and sets its target so that it doesn't immediately re-disguise itself. */
public void revealTo( @Nullable Entity target, boolean ambush ) {
public void revealTo( LivingEntity target, boolean ambush ) {
if( getHiddenDragon() == null ) return;
setHiddenDragon( null );
if( target instanceof LivingEntity && !(target instanceof PlayerEntity && ((PlayerEntity) target).isCreative()) ) {
final LivingEntity livingTarget = (LivingEntity) target;
setTarget( livingTarget );
if( !(target instanceof PlayerEntity && ((PlayerEntity) target).isCreative()) ) {
setTarget( target );
if( ambush ) {
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) );
livingTarget.addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration ) );
livingTarget.addEffect( new EffectInstance( Effects.BLINDNESS, duration ) );
livingTarget.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen)
MobHelper.applyEffect( target, Effects.POISON );
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN );
MobHelper.applyEffect( target, Effects.BLINDNESS );
MobHelper.removeNightVision( target );
}
}
}

View file

@ -6,14 +6,11 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.potion.PotionUtils;
import net.minecraft.potion.Potions;
@ -30,7 +27,7 @@ public class PoisonSkeletonEntity extends _SpecialSkeletonEntity {
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x779C68 ).theme( BestiaryInfo.Theme.FOREST )
.uniqueTextureWithOverlay()
.uniqueTexturesAll()
.addExperience( 1 );
}
@ -61,23 +58,13 @@ public class PoisonSkeletonEntity extends _SpecialSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.POISON );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.POISON, duration ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.POISON );
}
}

View file

@ -8,8 +8,15 @@ import fathertoast.specialmobs.common.config.species.SpeciesConfig;
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.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ProjectileHelper;
import net.minecraft.item.BowItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
@SpecialMob
@ -60,4 +67,45 @@ public class SniperSkeletonEntity extends _SpecialSkeletonEntity {
//--------------- Variant-Specific Implementations ----------------
public SniperSkeletonEntity( EntityType<? extends _SpecialSkeletonEntity> entityType, World world ) { super( entityType, world ); }
/** Called to attack the target with a ranged attack. */
@Override
public void performRangedAttack( LivingEntity target, float damageMulti ) {
// Would be nice if we could lead the target, maybe someday when we can more easily read player velocity
final double dX = target.getX() - getX();
final double dY = target.getY( 0.5 ) - getEyeY() + 0.1;
final double dZ = target.getZ() - getZ();
final double dH = MathHelper.sqrt( dX * dX + dZ * dZ );
final double g = 0.05; // Gravitational acceleration for AbstractArrowEntity
final float v = 1.6F;
final double radical = v * v * v * v - g * (g * dH * dH + 2 * dY * v * v);
if( radical < 0.0 ) {
// No firing solution, just fall back to the default
super.performRangedAttack( target, damageMulti );
return;
}
final double angle = Math.atan( (v * v - Math.sqrt( radical )) / (g * dH) ); // Use the flatter trajectory (-sqrt)
final double vY = Math.sin( angle );
final double vH = Math.cos( angle );
final ItemStack arrowItem = getProjectile( getItemInHand( ProjectileHelper.getWeaponHoldingHand(
this, item -> item instanceof BowItem ) ) );
AbstractArrowEntity arrow = getArrow( arrowItem, damageMulti );
if( getMainHandItem().getItem() instanceof BowItem )
arrow = ((BowItem) getMainHandItem().getItem()).customArrow( arrow );
arrow.shoot( dX / dH * vH, vY, dZ / dH * vH, v,
getSpecialData().getRangedAttackSpread() * (14 - 4 * level.getDifficulty().getId()) );
playSound( SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 0.8F) );
level.addFreshEntity( arrow );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
arrow.setKnockback( arrow.knockback + 2 );
return arrow;
}
}

View file

@ -7,7 +7,6 @@ import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -69,7 +68,7 @@ public class SpitfireSkeletonEntity extends _SpecialSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 10 );
}

View file

@ -65,24 +65,14 @@ public class StraySkeletonEntity extends _SpecialSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration * 2 ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN, 2.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration * 2 ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.MOVEMENT_SLOWDOWN, 2.0F );
}

View file

@ -0,0 +1,101 @@
package fathertoast.specialmobs.common.entity.skeleton;
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.Effects;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IServerWorld;
import net.minecraft.world.World;
import javax.annotation.Nullable;
@SpecialMob
public class WeatheredSkeletonEntity extends _SpecialSkeletonEntity {
//--------------- Static Special Mob Hooks ----------------
@SpecialMob.SpeciesReference
public static MobFamily.Species<WeatheredSkeletonEntity> SPECIES;
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xE6CC94 ).theme( BestiaryInfo.Theme.DESERT )
.uniqueTextureWithOverlay()
.addExperience( 1 )
.multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 );
}
@SpecialMob.ConfigSupplier
public static SpeciesConfig createConfig( MobFamily.Species<?> species ) {
return new SkeletonSpeciesConfig( species, 0.5, 0.0 );
}
@SpecialMob.LanguageProvider
public static String[] getTranslations( String langKey ) {
return References.translations( langKey, "Weathered Skeleton",
"", "", "", "", "", "" );//TODO
}
@SpecialMob.LootTableProvider
public static void buildLootTable( LootTableBuilder loot ) {
addBaseLoot( loot );
loot.addClusterDrop( "uncommon", Items.GOLD_NUGGET, 4 );
}
@SpecialMob.Factory
public static EntityType.IFactory<WeatheredSkeletonEntity> getVariantFactory() { return WeatheredSkeletonEntity::new; }
/** @return This entity's mob species. */
@SpecialMob.SpeciesSupplier
@Override
public MobFamily.Species<? extends WeatheredSkeletonEntity> getSpecies() { return SPECIES; }
//--------------- Variant-Specific Implementations ----------------
public WeatheredSkeletonEntity( EntityType<? extends _SpecialSkeletonEntity> entityType, World world ) { super( entityType, world ); }
/** Override to change starting equipment or stats. */
public void finalizeVariantSpawn( IServerWorld world, DifficultyInstance difficulty, @Nullable SpawnReason spawnReason,
@Nullable ILivingEntityData groupData ) {
if( getItemBySlot( EquipmentSlotType.MAINHAND ).getItem() == Items.IRON_SWORD ) {
setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.GOLDEN_SWORD ) );
if( getItemBySlot( EquipmentSlotType.OFFHAND ).isEmpty() ) {
setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.GOLDEN_SWORD ) );
}
}
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.HUNGER );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
return MobHelper.tipArrow( arrow, Effects.HUNGER );
}
/** @return Called each tick to check if the sun should set this entity on fire. */
@Override
protected boolean isSunBurnTick() { return false; }
}

View file

@ -119,7 +119,7 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS
arrow = ((BowItem) getMainHandItem().getItem()).customArrow( arrow );
final double dX = target.getX() - getX();
final double dY = target.getY( 1.0 / 3.0 ) - arrow.getY();
final double dY = target.getY( 0.3333 ) - arrow.getY();
final double dZ = target.getZ() - getZ();
final double dH = MathHelper.sqrt( dX * dX + dZ * dZ );
arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F,
@ -144,12 +144,12 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( @SuppressWarnings( "unused" ) CompoundNBT saveTag ) { }

View file

@ -66,7 +66,7 @@ public class CaramelSlimeEntity extends _SpecialSlimeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
if( grabTime <= -20 && getPassengers().isEmpty() ) {
if( target.startRiding( this, true ) ) grabTime = 20;
}

View file

@ -0,0 +1,132 @@
package fathertoast.specialmobs.common.entity.slime;
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.entity.ai.AIHelper;
import fathertoast.specialmobs.common.entity.ai.FluidPathNavigator;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.fluid.Fluid;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.pathfinding.PathNavigator;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.potion.Effects;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@SpecialMob
public class FrozenSlimeEntity extends _SpecialSlimeEntity {
//--------------- Static Special Mob Hooks ----------------
@SpecialMob.SpeciesReference
public static MobFamily.Species<FrozenSlimeEntity> SPECIES;
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x766BBC ).theme( BestiaryInfo.Theme.ICE )
.uniqueTextureBaseOnly()
.addExperience( 1 ).effectImmune( Effects.MOVEMENT_SLOWDOWN )
.addToAttribute( Attributes.ARMOR, 10.0 );
}
@SpecialMob.LanguageProvider
public static String[] getTranslations( String langKey ) {
return References.translations( langKey, "Frozen Slime",
"", "", "", "", "", "" );//TODO
}
@SpecialMob.LootTableProvider
public static void buildLootTable( LootTableBuilder loot ) {
addBaseLoot( loot );
loot.addCommonDrop( "common", Blocks.ICE );
loot.addRareDrop( "rare", Blocks.BLUE_ICE );
}
@SpecialMob.Factory
public static EntityType.IFactory<FrozenSlimeEntity> getVariantFactory() { return FrozenSlimeEntity::new; }
/** @return This entity's mob species. */
@SpecialMob.SpeciesSupplier
@Override
public MobFamily.Species<? extends FrozenSlimeEntity> getSpecies() { return SPECIES; }
//--------------- Variant-Specific Implementations ----------------
private byte frostWalking;
public FrozenSlimeEntity( EntityType<? extends _SpecialSlimeEntity> entityType, World world ) {
super( entityType, world );
setPathfindingMalus( PathNodeType.WATER, PathNodeType.WALKABLE.getMalus() );
}
/** Sets this slime's size, optionally resetting its health to max. */
@Override
protected void setSize( int size, boolean resetHealth ) {
super.setSize( size, resetHealth );
// Set frost walker level to -1 plus log base 2 of size (typically 0, 1, or 2)
frostWalking = -1;
while( size > 0 ) {
size >>= 1;
frostWalking++;
}
}
/** Override to change this entity's AI goals. */
@Override
protected void registerVariantGoals() {
AIHelper.removeGoals( goalSelector, 1 ); // SlimeEntity.FloatGoal
}
/** @return A new path navigator for this entity to use. */
@Override
protected PathNavigator createNavigation( World world ) {
return new FluidPathNavigator( this, world, true, false );
}
/** @return Whether this entity can stand on a particular type of fluid. */
@Override
public boolean canStandOnFluid( Fluid fluid ) { return fluid.is( FluidTags.WATER ); }
/** Called each tick to update this entity. */
@Override
public void tick() {
super.tick();
MobHelper.floatInFluid( this, 0.06, FluidTags.WATER );
MobHelper.hopOnFluid( this );
}
/** Called whenever this entity's block position changes. */
@Override
protected void onChangedBlock( BlockPos pos ) {
super.onChangedBlock( pos );
MobHelper.updateFrostWalker( this, pos, frostWalking );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN, 4, 0.5F );
}
/** Override to load data from this entity's NBT data. */
@Override
public void readVariantSaveData( CompoundNBT saveTag ) {
setPathfindingMalus( PathNodeType.WATER, PathNodeType.WALKABLE.getMalus() );
}
/** @return This slime's particle type for jump effects. */
@Override
protected IParticleData getParticleType() { return ParticleTypes.ITEM_SNOWBALL; }
}

View file

@ -6,7 +6,6 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.ExplosionHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -63,17 +62,15 @@ public class LemonSlimeEntity extends _SpecialSlimeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
ExplosionHelper.spawnLightning( level, target.getX(), target.getY(), target.getZ() );
// Knock self back
final float forwardPower = 1.1F;
final float upwardPower = 1.0F;
final Vector3d vKnockback = new Vector3d( target.getX() - getX(), 0.0, target.getZ() - getZ() )
.normalize().scale( -forwardPower ).add( getDeltaMovement().scale( 0.2F ) );
setDeltaMovement( vKnockback.x, 0.4 * upwardPower, vKnockback.z );
}
protected void onVariantAttack( LivingEntity target ) {
ExplosionHelper.spawnLightning( level, target.getX(), target.getY(), target.getZ() );
// Knock self back
final float forwardPower = 1.1F;
final float upwardPower = 1.0F;
final Vector3d vKnockback = new Vector3d( target.getX() - getX(), 0.0, target.getZ() - getZ() )
.normalize().scale( -forwardPower ).add( getDeltaMovement().scale( 0.2F ) );
setDeltaMovement( vKnockback.x, 0.4 * upwardPower, vKnockback.z );
}
/** Called when this entity is struck by lightning. */

View file

@ -0,0 +1,193 @@
package fathertoast.specialmobs.common.entity.slime;
import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.config.species.PotionSlimeSpeciesConfig;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.core.SpecialMobs;
import fathertoast.specialmobs.common.entity.MobHelper;
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.Attributes;
import net.minecraft.item.ItemStack;
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.IParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.*;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Set;
import static fathertoast.specialmobs.common.util.References.NBT_TYPE_STRING;
import static fathertoast.specialmobs.common.util.References.TAG_AMMO;
@SpecialMob
public class PotionSlimeEntity extends _SpecialSlimeEntity {
//--------------- Static Special Mob Hooks ----------------
@SpecialMob.SpeciesReference
public static MobFamily.Species<PotionSlimeEntity> SPECIES;
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0xA94725 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FOREST )
.uniqueTextureWithOverlay()
.addExperience( 2 )
.addToAttribute( Attributes.MAX_HEALTH, 2.0 )
.multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 );
}
@SpecialMob.ConfigSupplier
public static SpeciesConfig createConfig( MobFamily.Species<?> species ) {
return new PotionSlimeSpeciesConfig( species );
}
/** @return This entity's species config. */
public PotionSlimeSpeciesConfig getConfig() { return (PotionSlimeSpeciesConfig) getSpecies().config; }
@SpecialMob.LanguageProvider
public static String[] getTranslations( String langKey ) {
return References.translations( langKey, "Potion Slime",
"", "", "", "", "", "" );//TODO
}
@SpecialMob.LootTableProvider
public static void buildLootTable( LootTableBuilder loot ) {
addBaseLoot( loot );
loot.addUncommonDrop( "uncommon",
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.SLOWNESS ),
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.HARMING ),
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.POISON ),
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.WEAKNESS )
);
loot.addRareDrop( "rare",
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.STRONG_SLOWNESS ),
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.STRONG_HARMING ),
PotionUtils.setPotion( new ItemStack( Items.SPLASH_POTION ), Potions.STRONG_POISON ),
PotionUtils.setPotion( new ItemStack( Items.LINGERING_POTION ), Potions.HARMING )
);
}
@SpecialMob.Factory
public static EntityType.IFactory<PotionSlimeEntity> getVariantFactory() { return PotionSlimeEntity::new; }
/** @return This entity's mob species. */
@SpecialMob.SpeciesSupplier
@Override
public MobFamily.Species<? extends PotionSlimeEntity> getSpecies() { return SPECIES; }
//--------------- Variant-Specific Implementations ----------------
/** The parameter for potion color. */
private static final DataParameter<Integer> COLOR = EntityDataManager.defineId( PotionSlimeEntity.class, DataSerializers.INT );
/** The color of an empty potion. */
private static final int EMPTY_POTION_COLOR = 0x385DC6;
private Effect potionEffect;
public PotionSlimeEntity( EntityType<? extends _SpecialSlimeEntity> entityType, World world ) {
super( entityType, world );
setRandomPotionFill();
}
/** Called from the Entity.class constructor to define data watcher variables. */
@Override
protected void defineSynchedData() {
super.defineSynchedData();
entityData.define( COLOR, EMPTY_POTION_COLOR );
}
/** Sets the potion fill of this slime to a random effect based on config settings. */
private void setRandomPotionFill() {
final Set<Effect> allowedPotions = getConfig().POTION.allowedPotions.get().getEntries();
if( allowedPotions.size() > 0 ) {
final ArrayList<Effect> effects = new ArrayList<>( allowedPotions );
if( !Config.MAIN.GENERAL.enableNausea.get() ) effects.remove( Effects.CONFUSION );
if( effects.size() > 0 ) {
setPotionFill( effects.get( random.nextInt( effects.size() ) ) );
return;
}
}
setPotionFill( null );
}
/** Sets the potion fill of this slime. */
private void setPotionFill( @Nullable Effect effect ) {
potionEffect = effect;
entityData.set( COLOR, effect == null ? EMPTY_POTION_COLOR : effect.getColor() );
}
/** @return The color of the potion contained in this slime. */
public int getPotionColor() { return entityData.get( COLOR ); }
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
if( potionEffect == null ) target.clearFire();
else MobHelper.applyEffect( target, potionEffect );
}
/**
* Called when the slime spawns particles on landing, see onUpdate.
* Return true to prevent the spawning of the default particles.
*/
@Override
protected boolean spawnCustomParticles() {
final int color = getPotionColor();
final float r = (float) ((color >> 16) & 0xff) / (float) 0xff;
final float g = (float) ((color >> 8) & 0xff) / (float) 0xff;
final float b = (float) (color & 0xff) / (float) 0xff;
final int size = getSize();
for( int i = 0; i < size * 8; i++ ) {
final float angle = random.nextFloat() * 2.0F * (float) Math.PI;
final float distance = random.nextFloat() * 0.25F + 0.25F;
level.addParticle( getParticleType(),
getX() + MathHelper.sin( angle ) * size * distance,
getY(),
getZ() + MathHelper.cos( angle ) * size * distance,
r, g, b );
}
return true;
}
/** @return This slime's particle type for jump effects. */
@Override
protected IParticleData getParticleType() { return ParticleTypes.ENTITY_EFFECT; }
/** @return True if the effect can be applied to this entity. */
@Override
public boolean canBeAffected( EffectInstance effect ) {
// Immune to debuffs
return effect.getEffect().getCategory() != EffectType.HARMFUL && super.canBeAffected( effect );
}
/** Override to save data to this entity's NBT data. */
@Override
public void addVariantSaveData( CompoundNBT saveTag ) {
saveTag.putString( TAG_AMMO, SpecialMobs.toString( ForgeRegistries.POTIONS.getKey( potionEffect ) ) );
}
/** Override to load data from this entity's NBT data. */
@Override
public void readVariantSaveData( CompoundNBT saveTag ) {
if( saveTag.contains( TAG_AMMO, NBT_TYPE_STRING ) )
setPotionFill( ForgeRegistries.POTIONS.getValue( new ResourceLocation( saveTag.getString( TAG_AMMO ) ) ) );
}
}

View file

@ -8,8 +8,8 @@ import fathertoast.specialmobs.common.entity.ai.AIHelper;
import fathertoast.specialmobs.common.entity.ai.FluidPathNavigator;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
@ -66,7 +66,7 @@ public class StrawberrySlimeEntity extends _SpecialSlimeEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( getSize() * 3 );
}

View file

@ -3,10 +3,10 @@ package fathertoast.specialmobs.common.entity.slime;
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.entity.ai.goal.SpecialLeapAtTargetGoal;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -14,7 +14,6 @@ import net.minecraft.item.Items;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
@SpecialMob
@ -66,22 +65,13 @@ public class WatermelonSlimeEntity extends _SpecialSlimeEntity {
@Override
protected void registerVariantGoals() {
goalSelector.addGoal( 0, new SpecialLeapAtTargetGoal(
this, 10, 0.0F, 5.0F, 1.16F, 1.0F ) );
this, 5, 0.0F, 5.0F, 1.16F, 1.0F ) );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final float forwardPower = 0.8F;
final float upwardPower = 0.5F;
final Vector3d vKnockback = new Vector3d( target.getX() - getX(), 0.0, target.getZ() - getZ() )
.normalize().scale( forwardPower ).add( getDeltaMovement().scale( 0.2F ) );
target.setDeltaMovement( vKnockback.x, 0.4 * upwardPower, vKnockback.z );
target.hurtMarked = true;
setDeltaMovement( getDeltaMovement().multiply( 0.2, 1.0, 0.2 ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, 0.2, target, getSize(), 0.5F, 0.5 );
}
private static final IParticleData JUMP_PARTICLE = new ItemParticleData( ParticleTypes.ITEM, Items.MELON_SLICE.getDefaultInstance() );

View file

@ -85,12 +85,12 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -4,15 +4,14 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.core.register.SMEffects;
import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -60,18 +59,11 @@ public class DesertSpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
if( Config.MAIN.GENERAL.enableNausea.get() ) {
livingTarget.addEffect( new EffectInstance( Effects.CONFUSION, duration, 0 ) );
}
livingTarget.addEffect( new EffectInstance( Effects.BLINDNESS, duration, 0 ) );
livingTarget.addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration, 2 ) );
livingTarget.addEffect( new EffectInstance( Effects.DAMAGE_RESISTANCE, duration, -3 ) ); // 40% inc damage taken
}
protected void onVariantAttack( LivingEntity target ) {
if( Config.MAIN.GENERAL.enableNausea.get() ) MobHelper.applyEffect( target, Effects.CONFUSION );
MobHelper.applyEffect( target, Effects.BLINDNESS );
MobHelper.removeNightVision( target );
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN, 2 );
MobHelper.applyEffect( target, SMEffects.VULNERABILITY.get(), 2 );
}
}

View file

@ -6,7 +6,6 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
@ -56,8 +55,8 @@ public class FireSpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( !level.isClientSide() && target instanceof LivingEntity ) {
protected void onVariantAttack( LivingEntity target ) {
if( !level.isClientSide() ) {
final BlockPos pos = target.blockPosition();
if( level.getBlockState( pos ).getMaterial().isReplaceable() ) {
level.setBlock( pos, Blocks.FIRE.defaultBlockState(), References.SetBlockFlags.DEFAULTS );

View file

@ -3,9 +3,11 @@ package fathertoast.specialmobs.common.entity.spider;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -51,4 +53,10 @@ public class GiantSpiderEntity extends _SpecialSpiderEntity {
//--------------- Variant-Specific Implementations ----------------
public GiantSpiderEntity( EntityType<? extends _SpecialSpiderEntity> entityType, World world ) { super( entityType, world ); }
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, target, 3.0F, 0.5F );
}
}

View file

@ -6,7 +6,6 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.AttributeModifier;
@ -81,7 +80,7 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
if( level.isClientSide() ) return;
if( target instanceof PlayerEntity && ForgeEventFactory.getMobGriefingEvent( level, this ) ) {
@ -98,8 +97,8 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity {
playSound( SoundEvents.PLAYER_BURP, 0.5F, random.nextFloat() * 0.1F + 0.9F );
}
}
else if( target instanceof LivingEntity ) {
MobHelper.stealLife( this, (LivingEntity) target, 2.0F );
else {
MobHelper.stealLife( this, target, 2.0F );
}
}

View file

@ -6,12 +6,10 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -58,13 +56,8 @@ public class PaleSpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.WEAKNESS, duration, 0 ) );
livingTarget.addEffect( new EffectInstance( Effects.DIG_SLOWDOWN, duration, 1 ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.WEAKNESS );
MobHelper.applyEffect( target, Effects.DIG_SLOWDOWN, 3 );
}
}

View file

@ -6,11 +6,9 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -56,12 +54,7 @@ public class PoisonSpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.POISON );
}
}

View file

@ -8,7 +8,6 @@ import fathertoast.specialmobs.common.config.species.WebSpiderSpeciesConfig;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -78,8 +77,8 @@ public class WebSpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( !level.isClientSide() && webCount > 0 && target instanceof LivingEntity && !(target instanceof SpiderEntity) ) {
protected void onVariantAttack( LivingEntity target ) {
if( !level.isClientSide() && webCount > 0 && !(target instanceof SpiderEntity) ) {
final BlockPos pos = target.blockPosition();
if( !tryPlaceWeb( pos ) && target.getBbHeight() > 1.0F ) {
tryPlaceWeb( pos.above() );

View file

@ -6,7 +6,6 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -58,11 +57,9 @@ public class WitchSpiderEntity extends _SpecialSpiderEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
((LivingEntity) target).addEffect( MobHelper.nextWitchSpiderEffect( random, level, true ) );
MobHelper.stealBuffEffect( this, (LivingEntity) target );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyWitchSpiderEffect( target, random, true );
MobHelper.stealBuffEffect( this, target );
}
/** @return True if the effect can be applied to this entity. */

View file

@ -93,12 +93,12 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -3,6 +3,7 @@ package fathertoast.specialmobs.common.entity.witch;
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 net.minecraft.entity.EntityType;
@ -78,7 +79,7 @@ public class ShadowsWitchEntity extends _SpecialWitchEntity {
public void aiStep() {
final LivingEntity target = getTarget();
if( !level.isClientSide() && isAlive() && target != null && target.hasEffect( Effects.BLINDNESS ) && random.nextInt( 10 ) == 0 ) {
target.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen)
MobHelper.removeNightVision( target );
}
super.aiStep();
}

View file

@ -18,7 +18,6 @@ import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.pathfinding.PathNavigator;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.DamageSource;
@ -116,7 +115,7 @@ public class WindWitchEntity extends _SpecialWitchEntity {
}
}
else {
addEffect( new EffectInstance( Effects.INVISIBILITY, 30 ) );
MobHelper.applyDurationEffect( this, Effects.INVISIBILITY, 30 );
for( int i = 0; i < 16; i++ ) {
if( teleport() ) {
teleportDelay = 30;

View file

@ -99,12 +99,13 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( @SuppressWarnings( "unused" ) Entity target ) { }
@SuppressWarnings( "unused" ) // Not normally used for witches
protected void onVariantAttack( LivingEntity target ) { }
/** Called to attack the target with a ranged attack. */
@Override

View file

@ -6,15 +6,12 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -63,18 +60,14 @@ public class BruteWitherSkeletonEntity extends _SpecialWitherSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
MobHelper.knockback( this, target, 2.0F, 1.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.HARM ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.HARM );
}
}

View file

@ -3,10 +3,14 @@ package fathertoast.specialmobs.common.entity.witherskeleton;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -20,7 +24,7 @@ public class GiantWitherSkeletonEntity extends _SpecialWitherSkeletonEntity {
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x474D4D )
bestiaryInfo.color( 0x474D4D ).theme( BestiaryInfo.Theme.MOUNTAIN )
.size( 1.8F, 0.95F, 3.6F )
.addExperience( 1 )
.addToAttribute( Attributes.MAX_HEALTH, 20.0 )
@ -55,6 +59,19 @@ public class GiantWitherSkeletonEntity extends _SpecialWitherSkeletonEntity {
maxUpStep = 1.0F;
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, target, 4.0F, 1.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
arrow.setKnockback( arrow.knockback + 2 );
return arrow;
}
/** Sets this entity as a baby. */
@Override
public void setBaby( boolean value ) { }

View file

@ -12,13 +12,15 @@ import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.player.PlayerEntity;
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.potion.Effects;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.DamageSource;
@ -96,13 +98,13 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) { revealTo( target, true ); }
protected void onVariantAttack( LivingEntity target ) { revealTo( target, true ); }
/** @return Attempts to damage this entity; returns true if the hit was successful. */
@Override
public boolean hurt( DamageSource source, float amount ) {
if( super.hurt( source, amount ) ) {
revealTo( source.getEntity(), false );
if( source.getEntity() instanceof LivingEntity ) revealTo( (LivingEntity) source.getEntity(), false );
return true;
}
return false;
@ -171,21 +173,18 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
}
/** Reveals this ninja and sets its target so that it doesn't immediately re-disguise itself. */
public void revealTo( @Nullable Entity target, boolean ambush ) {
public void revealTo( LivingEntity target, boolean ambush ) {
if( getHiddenDragon() == null ) return;
setHiddenDragon( null );
if( target instanceof LivingEntity && !(target instanceof PlayerEntity && ((PlayerEntity) target).isCreative()) ) {
final LivingEntity livingTarget = (LivingEntity) target;
setTarget( livingTarget );
if( !(target instanceof PlayerEntity && ((PlayerEntity) target).isCreative()) ) {
setTarget( target );
if( ambush ) {
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) );
livingTarget.addEffect( new EffectInstance( Effects.MOVEMENT_SLOWDOWN, duration ) );
livingTarget.addEffect( new EffectInstance( Effects.BLINDNESS, duration ) );
livingTarget.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen)
MobHelper.applyEffect( target, Effects.POISON );
MobHelper.applyEffect( target, Effects.MOVEMENT_SLOWDOWN );
MobHelper.applyEffect( target, Effects.BLINDNESS );
MobHelper.removeNightVision( target );
}
}
}

View file

@ -8,8 +8,15 @@ import fathertoast.specialmobs.common.config.species.SpeciesConfig;
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.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ProjectileHelper;
import net.minecraft.item.BowItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
@SpecialMob
@ -60,4 +67,45 @@ public class SniperWitherSkeletonEntity extends _SpecialWitherSkeletonEntity {
//--------------- Variant-Specific Implementations ----------------
public SniperWitherSkeletonEntity( EntityType<? extends _SpecialWitherSkeletonEntity> entityType, World world ) { super( entityType, world ); }
/** Called to attack the target with a ranged attack. */
@Override
public void performRangedAttack( LivingEntity target, float damageMulti ) {
// Would be nice if we could lead the target, maybe someday when we can more easily read player velocity
final double dX = target.getX() - getX();
final double dY = target.getY( 0.5 ) - getEyeY() + 0.1;
final double dZ = target.getZ() - getZ();
final double dH = MathHelper.sqrt( dX * dX + dZ * dZ );
final double g = 0.05; // Gravitational acceleration for AbstractArrowEntity
final float v = 1.6F;
final double radical = v * v * v * v - g * (g * dH * dH + 2 * dY * v * v);
if( radical < 0.0 ) {
// No firing solution, just fall back to the default
super.performRangedAttack( target, damageMulti );
return;
}
final double angle = Math.atan( (v * v - Math.sqrt( radical )) / (g * dH) ); // Use the flatter trajectory (-sqrt)
final double vY = Math.sin( angle );
final double vH = Math.cos( angle );
final ItemStack arrowItem = getProjectile( getItemInHand( ProjectileHelper.getWeaponHoldingHand(
this, item -> item instanceof BowItem ) ) );
AbstractArrowEntity arrow = getArrow( arrowItem, damageMulti );
if( getMainHandItem().getItem() instanceof BowItem )
arrow = ((BowItem) getMainHandItem().getItem()).customArrow( arrow );
arrow.shoot( dX / dH * vH, vY, dZ / dH * vH, v,
getSpecialData().getRangedAttackSpread() * (14 - 4 * level.getDifficulty().getId()) );
playSound( SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 0.8F) );
level.addFreshEntity( arrow );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
arrow.setKnockback( arrow.knockback + 2 );
return arrow;
}
}

View file

@ -5,9 +5,9 @@ import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
@ -69,8 +69,9 @@ public class SpitfireWitherSkeletonEntity extends _SpecialWitherSkeletonEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 10 );
MobHelper.knockback( this, target, 3.0F, 1.0F );
}
/** Called to attack the target with a ranged attack. */

View file

@ -55,7 +55,7 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement
bestiaryInfo.color( 0x474D4D )
.vanillaTextureBaseOnly( "textures/entity/skeleton/wither_skeleton.png" )
.familySize( 1.2F )
.experience( 5 ).undead().fireImmune()
.experience( 5 ).undead()
.bowAttack( 2.0, 1.0, 1.0, 20, 15.0 );
}
@ -117,7 +117,7 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement
arrow = ((BowItem) getMainHandItem().getItem()).customArrow( arrow );
final double dX = target.getX() - getX();
final double dY = target.getY( 1.0 / 3.0 ) - arrow.getY();
final double dY = target.getY( 0.3333 ) - arrow.getY();
final double dZ = target.getZ() - getZ();
final double dH = MathHelper.sqrt( dX * dX + dZ * dZ );
arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F,
@ -142,12 +142,12 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( @SuppressWarnings( "unused" ) CompoundNBT saveTag ) { }

View file

@ -6,15 +6,12 @@ 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 net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
@ -63,18 +60,14 @@ public class BruteZombieEntity extends _SpecialZombieEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
MobHelper.knockback( this, target, 2.0F, 1.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.HARM ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.HARM );
}
}

View file

@ -5,8 +5,8 @@ import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@ -58,7 +58,7 @@ public class FireZombieEntity extends _SpecialZombieEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
target.setSecondsOnFire( 10 );
}

View file

@ -6,6 +6,7 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig;
import fathertoast.specialmobs.common.entity.ai.AIHelper;
import fathertoast.specialmobs.common.entity.ai.IAngler;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootEntryItemBuilder;
@ -87,6 +88,7 @@ public class FishingZombieEntity extends _SpecialZombieEntity implements IAngler
/** Override to change this entity's AI goals. */
@Override
protected void registerVariantGoals() {
AIHelper.replaceWaterAvoidingRandomWalking( this, 1.0 );
//TODO add angler AI @ attack priority
}

View file

@ -3,10 +3,14 @@ package fathertoast.specialmobs.common.entity.zombie;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -20,7 +24,7 @@ public class GiantZombieEntity extends _SpecialZombieEntity {
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x799C65 )
bestiaryInfo.color( 0x799C65 ).theme( BestiaryInfo.Theme.MOUNTAIN )
.size( 1.5F, 0.9F, 2.95F )
.addExperience( 1 )
.addToAttribute( Attributes.MAX_HEALTH, 20.0 )
@ -55,6 +59,19 @@ public class GiantZombieEntity extends _SpecialZombieEntity {
maxUpStep = 1.0F;
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, target, 4.0F, 0.5F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
arrow.setKnockback( arrow.knockback + 2 );
return arrow;
}
/** Sets this entity as a baby. */
@Override
public void setBaby( boolean value ) { }

View file

@ -6,7 +6,10 @@ 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 net.minecraft.entity.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Food;
@ -72,7 +75,7 @@ public class HungryZombieEntity extends _SpecialZombieEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
if( level.isClientSide() ) return;
if( target instanceof PlayerEntity && ForgeEventFactory.getMobGriefingEvent( level, this ) ) {
@ -85,8 +88,6 @@ public class HungryZombieEntity extends _SpecialZombieEntity {
}
}
// Take a bite out of the target if they have no food to eat
if( target instanceof LivingEntity ) {
MobHelper.stealLife( this, (LivingEntity) target, 2.0F );
}
MobHelper.stealLife( this, target, 2.0F );
}
}

View file

@ -6,15 +6,12 @@ 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 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.monster.HuskEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.util.DamageSource;
import net.minecraft.util.SoundEvent;
@ -66,24 +63,14 @@ public class HuskZombieEntity extends _SpecialZombieEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.HUNGER, duration ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyEffect( target, Effects.HUNGER );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.HUNGER, duration ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.HUNGER );
}

View file

@ -12,12 +12,14 @@ import fathertoast.specialmobs.common.entity.ai.IAmmoUser;
import fathertoast.specialmobs.common.entity.ai.goal.ChargeCreeperGoal;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.entity.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.monster.CreeperEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IServerWorld;
@ -104,12 +106,9 @@ public class MadScientistZombieEntity extends _SpecialZombieEntity implements IA
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity && hasAmmo() ) {
final LivingEntity livingTarget = (LivingEntity) target;
final int duration = MobHelper.getDebuffDuration( level.getDifficulty() );
livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) );
protected void onVariantAttack( LivingEntity target ) {
if( hasAmmo() ) {
MobHelper.applyEffect( target, Effects.POISON );
}
}

View file

@ -7,12 +7,10 @@ import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -61,18 +59,13 @@ public class PlagueZombieEntity extends _SpecialZombieEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
((LivingEntity) target).addEffect( MobHelper.nextPlagueEffect( random, level ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyPlagueEffect( target, random );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( MobHelper.nextPlagueEffect( random, level ) );
}
return arrow;
return MobHelper.tipPlagueArrow( arrow, random );
}
}

View file

@ -121,7 +121,7 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM
arrow = ((BowItem) getMainHandItem().getItem()).customArrow( arrow );
final double dX = target.getX() - getX();
final double dY = target.getY( 1.0 / 3.0 ) - arrow.getY();
final double dY = target.getY( 0.3333 ) - arrow.getY();
final double dZ = target.getZ() - getZ();
final double dH = MathHelper.sqrt( dX * dX + dZ * dZ );
arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F,
@ -145,12 +145,12 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( CompoundNBT saveTag ) { }

View file

@ -6,14 +6,15 @@ 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 net.minecraft.entity.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IServerWorld;
@ -76,18 +77,14 @@ public class BruteZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.causeLifeLoss( target, 2.0F );
MobHelper.knockback( this, target, 2.0F, 1.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.HARM ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.HARM );
}
}

View file

@ -6,6 +6,7 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob;
import fathertoast.specialmobs.common.config.Config;
import fathertoast.specialmobs.common.config.species.SpeciesConfig;
import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig;
import fathertoast.specialmobs.common.entity.ai.AIHelper;
import fathertoast.specialmobs.common.entity.ai.IAngler;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootEntryItemBuilder;
@ -87,6 +88,7 @@ public class FishingZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity
/** Override to change this entity's AI goals. */
@Override
protected void registerVariantGoals() {
AIHelper.replaceWaterAvoidingRandomWalking( this, 1.0 );
//TODO add angler AI @ attack priority
}

View file

@ -3,10 +3,14 @@ package fathertoast.specialmobs.common.entity.zombifiedpiglin;
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 net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -20,7 +24,7 @@ public class GiantZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity {
@SpecialMob.BestiaryInfoSupplier
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x4C7129 )
bestiaryInfo.color( 0x4C7129 ).theme( BestiaryInfo.Theme.MOUNTAIN )
.size( 1.5F, 0.9F, 2.95F )
.addExperience( 1 )
.addToAttribute( Attributes.MAX_HEALTH, 20.0 )
@ -55,6 +59,19 @@ public class GiantZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity {
maxUpStep = 1.0F;
}
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( LivingEntity target ) {
MobHelper.knockback( this, target, 4.0F, 0.5F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
arrow.setKnockback( arrow.knockback + 2 );
return arrow;
}
/** Sets this entity as a baby. */
@Override
public void setBaby( boolean value ) { }

View file

@ -6,7 +6,10 @@ 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 net.minecraft.entity.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Food;
@ -72,7 +75,7 @@ public class HungryZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
protected void onVariantAttack( LivingEntity target ) {
if( level.isClientSide() ) return;
if( target instanceof PlayerEntity && ForgeEventFactory.getMobGriefingEvent( level, this ) ) {
@ -85,8 +88,6 @@ public class HungryZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity {
}
}
// Take a bite out of the target if they have no food to eat
if( target instanceof LivingEntity ) {
MobHelper.stealLife( this, (LivingEntity) target, 2.0F );
}
MobHelper.stealLife( this, target, 2.0F );
}
}

View file

@ -7,12 +7,10 @@ import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
@ -61,18 +59,13 @@ public class PlagueZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity {
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
((LivingEntity) target).addEffect( MobHelper.nextPlagueEffect( random, level ) );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.applyPlagueEffect( target, random );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( MobHelper.nextPlagueEffect( random, level ) );
}
return arrow;
return MobHelper.tipPlagueArrow( arrow, random );
}
}

View file

@ -7,15 +7,12 @@ import fathertoast.specialmobs.common.entity.MobHelper;
import fathertoast.specialmobs.common.util.References;
import fathertoast.specialmobs.datagen.loot.LootTableBuilder;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
@ -67,19 +64,14 @@ public class VampireZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity
/** Override to apply effects when this entity hits a target with a melee attack. */
@Override
protected void onVariantAttack( Entity target ) {
if( target instanceof LivingEntity ) {
MobHelper.stealLife( this, (LivingEntity) target, 2.0F );
}
protected void onVariantAttack( LivingEntity target ) {
MobHelper.stealLife( this, target, 2.0F );
}
/** Override to modify this entity's ranged attack projectile. */
@Override
protected AbstractArrowEntity getVariantArrow( AbstractArrowEntity arrow, ItemStack arrowItem, float damageMulti ) {
if( arrow instanceof ArrowEntity ) {
((ArrowEntity) arrow).addEffect( new EffectInstance( Effects.HARM, 0, 1 ) );
}
return arrow;
return MobHelper.tipArrow( arrow, Effects.HARM, 2 );
}
/** @return Attempts to damage this entity; returns true if the hit was successful. */

View file

@ -54,7 +54,7 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme
public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) {
bestiaryInfo.color( 0x4C7129 )
.vanillaTextureBaseOnly( "textures/entity/piglin/zombified_piglin.png" )
.experience( 5 ).undead().fireImmune()
.experience( 5 ).undead()
.bowAttack( 2.0, 1.0, 0.8, 20, 15.0 );
}
@ -119,7 +119,7 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme
arrow = ((BowItem) getMainHandItem().getItem()).customArrow( arrow );
final double dX = target.getX() - getX();
final double dY = target.getY( 1.0 / 3.0 ) - arrow.getY();
final double dY = target.getY( 0.3333 ) - arrow.getY();
final double dZ = target.getZ() - getZ();
final double dH = MathHelper.sqrt( dX * dX + dZ * dZ );
arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F,
@ -143,12 +143,12 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme
/** Called when this entity successfully damages a target to apply on-hit effects. */
@Override
public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) {
onVariantAttack( target );
if( target instanceof LivingEntity ) onVariantAttack( (LivingEntity) target );
super.doEnchantDamageEffects( attacker, target );
}
/** Override to apply effects when this entity hits a target with a melee attack. */
protected void onVariantAttack( Entity target ) { }
protected void onVariantAttack( LivingEntity target ) { }
/** Override to save data to this entity's NBT data. */
public void addVariantSaveData( @SuppressWarnings( "unused" ) CompoundNBT saveTag ) { }

Some files were not shown because too many files have changed in this diff Show more